OLD | NEW |
(Empty) | |
| 1 ; RUN: pnacl-llc -O2 -mtriple=x86_64-none-nacl -filetype=obj < %s | \ |
| 2 ; RUN: llvm-objdump -d -r - | FileCheck %s |
| 3 ; RUN: pnacl-llc -O2 -mtriple=x86_64-none-nacl -filetype=obj < %s | \ |
| 4 ; RUN: llvm-objdump -d -r - | FileCheck %s --check-prefix=NOCALLRET |
| 5 ; RUN: pnacl-llc -O2 -mtriple=x86_64-none-nacl -filetype=obj \ |
| 6 ; RUN: -relocation-model=pic < %s | \ |
| 7 ; RUN: llvm-objdump -d -r - | FileCheck %s --check-prefix=PIC |
| 8 |
| 9 ; RUN: pnacl-llc -O2 -mtriple=x86_64-none-nacl -filetype=asm < %s | \ |
| 10 ; RUN: FileCheck %s --check-prefix=ASM |
| 11 |
| 12 ; ModuleID = 'pnacl-hides-sandbox-x86-64.c' |
| 13 target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64
:64:64-p:32:32:32-v128:32:32" |
| 14 target triple = "le32-unknown-nacl" |
| 15 |
| 16 @IndirectCallTarget = external global void ()* |
| 17 @.str = private unnamed_addr constant [8 x i8] c"Prime 1\00", align 1 |
| 18 @.str1 = private unnamed_addr constant [8 x i8] c"Prime 2\00", align 1 |
| 19 @.str2 = private unnamed_addr constant [8 x i8] c"Prime 3\00", align 1 |
| 20 @.str3 = private unnamed_addr constant [8 x i8] c"Prime 4\00", align 1 |
| 21 @.str4 = private unnamed_addr constant [8 x i8] c"Prime 5\00", align 1 |
| 22 |
| 23 ; Function Attrs: nounwind |
| 24 define void @TestDirectCall() #0 { |
| 25 entry: |
| 26 call void @DirectCallTarget() |
| 27 ret void |
| 28 } |
| 29 ; CHECK-LABEL: TestDirectCall: |
| 30 ; Push only the bottom 32-bits of the frame pointer |
| 31 ; CHECK: movl %ebp, %eax |
| 32 ; CHECK-NEXT: pushq %rax |
| 33 ; Push the immediate return address |
| 34 ; CHECK: pushq $0 |
| 35 ; CHECK-NEXT: .text |
| 36 ; Immediate jump to the target |
| 37 ; CHECK: jmp 0 |
| 38 ; CHECK-NEXT: DirectCallTarget |
| 39 ; The return sequence should use %r11 |
| 40 ; CHECK: popq %r11 |
| 41 ; CHECK: andl $-32, %r11d |
| 42 ; CHECK-NEXT: addq %r15, %r11 |
| 43 ; CHECK-NEXT: jmpq *%r11 |
| 44 |
| 45 ; PIC-LABEL: TestDirectCall |
| 46 ; PIC: leal 19(%rip), %r10d |
| 47 ; PIC-NEXT: pushq %r10 |
| 48 ; PIC-NEXT: jmp 0 |
| 49 ; PIC-NEXT: DirectCallTarget |
| 50 |
| 51 ; ASM-LABEL: TestDirectCall: |
| 52 ; Push only the bottom 32-bits of the frame pointer |
| 53 ; ASM: movl %ebp, %eax |
| 54 ; ASM-NEXT: pushq %rax |
| 55 ; In asm, direct calls are just 'call' |
| 56 ; ASM: callq DirectCallTarget |
| 57 ; The return sequence should use %r11 |
| 58 ; ASM: popq %r11 |
| 59 ; ASM: nacljmp %r11d, %r15 |
| 60 |
| 61 declare hidden void @DirectCallTarget() #1 |
| 62 |
| 63 ; Function Attrs: nounwind |
| 64 define void @TestIndirectCall() #0 { |
| 65 entry: |
| 66 %0 = load void ()** @IndirectCallTarget, align 4 |
| 67 call void %0() |
| 68 ret void |
| 69 } |
| 70 ; CHECK-LABEL: TestIndirectCall: |
| 71 ; Push the immediate return address |
| 72 ; CHECK: pushq $0 |
| 73 ; CHECK-NEXT: .text |
| 74 ; Fixed sequence for indirect jump |
| 75 ; CHECK: andl $-32, %r11d |
| 76 ; CHECK-NEXT: addq %r15, %r11 |
| 77 ; CHECK-NEXT: jmpq *%r11 |
| 78 |
| 79 ; PIC-LABEL: TestIndirectCall: |
| 80 ; Ensure that the mov of the call target happens before the return address |
| 81 ; calculation |
| 82 ; PIC: movl {{.*}}, %r11d |
| 83 ; Calculate and push the return address |
| 84 ; PIC-NEXT: leal {{[0-9]+}}(%rip), %r10d |
| 85 ; PIC-NEXT: pushq %r10 |
| 86 ; Fixed sequence for indirect jump |
| 87 ; PIC: andl $-32, %r11d |
| 88 ; PIC-NEXT: addq %r15, %r11 |
| 89 ; PIC-NEXT: jmpq *%r11 |
| 90 |
| 91 ; Function Attrs: nounwind |
| 92 define void @TestMaskedFramePointer(i32 %Arg) #0 { |
| 93 entry: |
| 94 %Arg.addr = alloca i32, align 4 |
| 95 %Tmp = alloca i8*, align 4 |
| 96 store i32 %Arg, i32* %Arg.addr, align 4 |
| 97 %0 = load i32* %Arg.addr, align 4 |
| 98 %1 = alloca i8, i32 %0 |
| 99 store i8* %1, i8** %Tmp, align 4 |
| 100 %2 = load i8** %Tmp, align 4 |
| 101 call void @Consume(i8* %2) |
| 102 ret void |
| 103 } |
| 104 ; Verify that the old frame pointer isn't leaked when saved |
| 105 ; CHECK: TestMaskedFramePointer: |
| 106 ; CHECK: movl %ebp, %eax |
| 107 ; CHECK: pushq %rax |
| 108 ; CHECK: movq %rsp, %rbp |
| 109 |
| 110 declare void @Consume(i8*) #1 |
| 111 |
| 112 ; Function Attrs: nounwind |
| 113 define void @TestMaskedFramePointerVarargs(i32 %Arg, ...) #0 { |
| 114 entry: |
| 115 %Arg.addr = alloca i32, align 4 |
| 116 %Tmp = alloca i8*, align 4 |
| 117 store i32 %Arg, i32* %Arg.addr, align 4 |
| 118 %0 = load i32* %Arg.addr, align 4 |
| 119 %1 = alloca i8, i32 %0 |
| 120 store i8* %1, i8** %Tmp, align 4 |
| 121 %2 = load i8** %Tmp, align 4 |
| 122 call void @Consume(i8* %2) |
| 123 ret void |
| 124 } |
| 125 ; Verify use of r10 instead of rax in the presence of varargs, |
| 126 ; when saving the old rbp. |
| 127 ; CHECK: TestMaskedFramePointerVarargs: |
| 128 ; CHECK: movl %ebp, %r10d |
| 129 ; CHECK: pushq %r10 |
| 130 ; CHECK: movq %rsp, %rbp |
| 131 |
| 132 ; Function Attrs: nounwind |
| 133 define void @TestIndirectJump(i32 %Arg) #0 { |
| 134 entry: |
| 135 %Arg.addr = alloca i32, align 4 |
| 136 store i32 %Arg, i32* %Arg.addr, align 4 |
| 137 %0 = load i32* %Arg.addr, align 4 |
| 138 switch i32 %0, label %sw.epilog [ |
| 139 i32 2, label %sw.bb |
| 140 i32 3, label %sw.bb1 |
| 141 i32 5, label %sw.bb3 |
| 142 i32 7, label %sw.bb5 |
| 143 i32 11, label %sw.bb7 |
| 144 ] |
| 145 |
| 146 sw.bb: ; preds = %entry |
| 147 %call = call i32 @puts(i8* getelementptr inbounds ([8 x i8]* @.str, i32 0, i32
0)) |
| 148 br label %sw.epilog |
| 149 |
| 150 sw.bb1: ; preds = %entry |
| 151 %call2 = call i32 @puts(i8* getelementptr inbounds ([8 x i8]* @.str1, i32 0, i
32 0)) |
| 152 br label %sw.epilog |
| 153 |
| 154 sw.bb3: ; preds = %entry |
| 155 %call4 = call i32 @puts(i8* getelementptr inbounds ([8 x i8]* @.str2, i32 0, i
32 0)) |
| 156 br label %sw.epilog |
| 157 |
| 158 sw.bb5: ; preds = %entry |
| 159 %call6 = call i32 @puts(i8* getelementptr inbounds ([8 x i8]* @.str3, i32 0, i
32 0)) |
| 160 br label %sw.epilog |
| 161 |
| 162 sw.bb7: ; preds = %entry |
| 163 %call8 = call i32 @puts(i8* getelementptr inbounds ([8 x i8]* @.str4, i32 0, i
32 0)) |
| 164 br label %sw.epilog |
| 165 |
| 166 sw.epilog: ; preds = %entry, %sw.bb7, %sw
.bb5, %sw.bb3, %sw.bb1, %sw.bb |
| 167 ret void |
| 168 } |
| 169 ; Test the indirect jump sequence derived from a "switch" statement. |
| 170 ; CHECK: TestIndirectJump: |
| 171 ; CHECK: andl $-32, %r11d |
| 172 ; CHECK-NEXT: addq %r15, %r11 |
| 173 ; CHECK-NEXT: jmpq *%r11 |
| 174 ; At least 4 "jmp"s due to 5 switch cases |
| 175 ; CHECK: jmp |
| 176 ; CHECK: jmp |
| 177 ; CHECK: jmp |
| 178 ; CHECK: jmp |
| 179 ; At least 1 direct call to puts() |
| 180 ; CHECK: pushq $0 |
| 181 ; CHECK-NEXT: .text |
| 182 ; CHECK: jmp 0 |
| 183 ; CHECK-NEXT: puts |
| 184 |
| 185 declare i32 @puts(i8*) #1 |
| 186 |
| 187 ; Function Attrs: nounwind |
| 188 define void @TestReturn() #0 { |
| 189 entry: |
| 190 ret void |
| 191 } |
| 192 ; Return sequence is just the indirect jump sequence |
| 193 ; CHECK: TestReturn: |
| 194 ; CHECK: andl $-32, %r11d |
| 195 ; CHECK-NEXT: addq %r15, %r11 |
| 196 ; CHECK-NEXT: jmpq *%r11 |
| 197 |
| 198 attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"=
"true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nan
s-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } |
| 199 attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "n
o-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math
"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } |
| 200 |
| 201 ; Special test that no "call" or "ret" instructions are generated. |
| 202 ; NOCALLRET-NOT: call |
| 203 ; NOCALLRET-NOT: ret |
OLD | NEW |