1 ; Test of multiple indirect calls to the same target. Each call 2 ; should be to the same operand, whether it's in a register or on the 3 ; stack. 4 5 ; RUN: %if --need=target_X8632 --command %p2i --filetype=obj --disassemble \ 6 ; RUN: --target x8632 -i %s --args -O2 \ 7 ; RUN: | %if --need=target_X8632 --command FileCheck %s 8 ; RUN: %if --need=allow_dump --need=target_X8632 --command %p2i --filetype=asm \ 9 ; RUN: --assemble --disassemble -i %s --args -O2 \ 10 ; RUN: | %if --need=allow_dump --need=target_X8632 --command FileCheck %s 11 ; RUN: %if --need=target_X8632 --command %p2i --filetype=obj --disassemble \ 12 ; RUN: --target x8632 -i %s --args -Om1 \ 13 ; RUN: | %if --need=target_X8632 --command FileCheck --check-prefix=OPTM1 %s 14 15 ; RUN: %if --need=target_X8664 --command %p2i --filetype=obj --disassemble \ 16 ; RUN: --target x8664 -i %s --args -O2 \ 17 ; RUN: | %if --need=target_X8664 --command FileCheck --check-prefix X8664 %s 18 ; RUN: %if --need=allow_dump --need=target_X8664 --command %p2i --filetype=asm \ 19 ; RUN: --assemble --disassemble --target x8664 -i %s --args -O2 \ 20 ; RUN: | %if --need=allow_dump --need=target_X8664 \ 21 ; RUN: --command FileCheck --check-prefix=X8664 %s 22 ; RUN: %if --need=target_X8664 --command %p2i --filetype=obj --disassemble \ 23 ; RUN: --target x8664 -i %s --args -Om1 \ 24 ; RUN: | %if --need=target_X8664 \ 25 ; RUN: --command FileCheck --check-prefix=X8664-OPTM1 %s 26 27 ; RUN: %if --need=target_ARM32 \ 28 ; RUN: --command %p2i --filetype=obj \ 29 ; RUN: --disassemble --target arm32 -i %s --args -O2 \ 30 ; RUN: | %if --need=target_ARM32 \ 31 ; RUN: --command FileCheck --check-prefix ARM32 %s 32 ; RUN: %if --need=target_ARM32 \ 33 ; RUN: --command %p2i --filetype=obj \ 34 ; RUN: --disassemble --target arm32 -i %s --args -Om1 \ 35 ; RUN: | %if --need=target_ARM32_dump \ 36 ; RUN: --command FileCheck --check-prefix ARM32 %s 37 38 ; RUN: %if --need=target_MIPS32 --need=allow_dump \ 39 ; RUN: --command %p2i --filetype=asm --assemble --disassemble --target \ 40 ; RUN: mips32 -i %s --args -O2 -allow-externally-defined-symbols \ 41 ; RUN: | %if --need=target_MIPS32 --need=allow_dump \ 42 ; RUN: --command FileCheck --check-prefix MIPS32 %s 43 44 @__init_array_start = internal constant [0 x i8] zeroinitializer, align 4 45 @__fini_array_start = internal constant [0 x i8] zeroinitializer, align 4 46 @__tls_template_start = internal constant [0 x i8] zeroinitializer, align 8 47 @__tls_template_alignment = internal constant [4 x i8] c"\01\00\00\00", align 4 48 49 define internal void @CallIndirect(i32 %f) { 50 entry: 51 %__1 = inttoptr i32 %f to void ()* 52 call void %__1() 53 call void %__1() 54 call void %__1() 55 call void %__1() 56 call void %__1() 57 call void %__1() 58 ret void 59 } 60 ; CHECK-LABEL: CallIndirect 61 ; Use the first call as a barrier in case the register allocator decides to use 62 ; a scratch register for it but a common preserved register for the rest. 63 ; CHECK: call 64 ; CHECK: call [[REGISTER:[a-z]+]] 65 ; CHECK: call [[REGISTER]] 66 ; CHECK: call [[REGISTER]] 67 ; CHECK: call [[REGISTER]] 68 ; CHECK: call [[REGISTER]] 69 ; 70 ; OPTM1-LABEL: CallIndirect 71 ; OPTM1: call [[TARGET:.+]] 72 ; OPTM1: call [[TARGET]] 73 ; OPTM1: call [[TARGET]] 74 ; OPTM1: call [[TARGET]] 75 ; OPTM1: call [[TARGET]] 76 ; 77 ; X8664-LABEL: CallIndirect 78 ; Use the first call as a barrier so we skip the movs in the function prolog. 79 ; X8664: call r{{..}} 80 ; X8664: mov e[[REG:..]], 81 ; X8664-NEXT: call r[[REG]] 82 ; X8664: mov e[[REG:..]], 83 ; X8664-NEXT: call r[[REG]] 84 ; X8664: mov e[[REG:..]], 85 ; X8664-NEXT: call r[[REG]] 86 ; X8664: call r{{..}} 87 ; 88 ; X8664-OPTM1-LABEL: CallIndirect 89 ; X8664-OPTM1: mov e[[REG:..]],DWORD PTR 90 ; X8664-OPTM1: call r[[REG]] 91 ; X8664-OPTM1: mov e[[REG:..]],DWORD PTR 92 ; X8664-OPTM1: call r[[REG]] 93 ; X8664-OPTM1: mov e[[REG:..]],DWORD PTR 94 ; X8664-OPTM1: call r[[REG]] 95 ; X8664-OPTM1: mov e[[REG:..]],DWORD PTR 96 ; X8664-OPTM1: call r[[REG]] 97 ; X8664-OPTM1: mov e[[REG:..]],DWORD PTR 98 ; X8664-OPTM1: call r[[REG]] 99 ; 100 ; ARM32-LABEL: CallIndirect 101 ; ARM32: blx [[REGISTER:r.*]] 102 ; ARM32: blx [[REGISTER]] 103 ; ARM32: blx [[REGISTER]] 104 ; ARM32: blx [[REGISTER]] 105 ; ARM32: blx [[REGISTER]] 106 107 ; MIPS32-LABEL: CallIndirect 108 ; MIPS32: jalr [[REGISTER:.*]] 109 ; MIPS32: jalr [[REGISTER]] 110 ; MIPS32: jalr [[REGISTER]] 111 ; MIPS32: jalr [[REGISTER]] 112 113 @fp_v = internal global [4 x i8] zeroinitializer, align 4 114 115 define internal void @CallIndirectGlobal() { 116 entry: 117 %fp_ptr_i32 = bitcast [4 x i8]* @fp_v to i32* 118 %fp_ptr = load i32, i32* %fp_ptr_i32, align 1 119 %fp = inttoptr i32 %fp_ptr to void ()* 120 call void %fp() 121 call void %fp() 122 call void %fp() 123 call void %fp() 124 ret void 125 } 126 ; CHECK-LABEL: CallIndirectGlobal 127 ; Allow the first call to be to a different register because of simple 128 ; availability optimization. 129 ; CHECK: call 130 ; CHECK: call [[REGISTER:[a-z]+]] 131 ; CHECK: call [[REGISTER]] 132 ; CHECK: call [[REGISTER]] 133 ; 134 ; OPTM1-LABEL: CallIndirectGlobal 135 ; OPTM1: call [[TARGET:.+]] 136 ; OPTM1: call [[TARGET]] 137 ; OPTM1: call [[TARGET]] 138 ; OPTM1: call [[TARGET]] 139 ; 140 ; X8664-LABEL: CallIndirectGlobal 141 ; X8664: call r[[REG]] 142 ; X8664: mov e[[REG:..]] 143 ; X8664-NEXT: call r[[REG]] 144 ; X8664: mov e[[REG:..]] 145 ; X8664-NEXT: call r[[REG]] 146 ; X8664: call r{{..}} 147 ; 148 ; X8664-OPTM1-LABEL: CallIndirectGlobal 149 ; X8664-OPTM1: mov e[[REG:..]],DWORD PTR 150 ; X8664-OPTM1: call r[[REG]] 151 ; X8664-OPTM1: mov e[[REG:..]],DWORD PTR 152 ; X8664-OPTM1: call r[[REG]] 153 ; X8664-OPTM1: mov e[[REG:..]],DWORD PTR 154 ; X8664-OPTM1: call r[[REG]] 155 ; X8664-OPTM1: mov e[[REG:..]],DWORD PTR 156 ; X8664-OPTM1: call r[[REG]] 157 ; 158 ; ARM32-LABEL: CallIndirectGlobal 159 ; ARM32: blx {{r.*}} 160 ; ARM32: blx [[REGISTER:r[0-9]*]] 161 ; ARM32: blx [[REGISTER]] 162 ; ARM32: blx [[REGISTER]] 163 164 ; MIPS32-LABEL: CallIndirectGlobal 165 ; MIPS32: jalr [[REGISTER:.*]] 166 ; MIPS32: jalr [[REGISTER]] 167 ; MIPS32: jalr [[REGISTER]] 168 ; MIPS32: jalr [[REGISTER]] 169 170 ; Calling an absolute address is used for non-IRT PNaCl pexes to directly 171 ; access syscall trampolines. This is not really an indirect call, but 172 ; there is a cast from int to pointer first. 173 define internal void @CallConst() { 174 entry: 175 %__1 = inttoptr i32 66496 to void ()* 176 call void %__1() 177 call void %__1() 178 call void %__1() 179 ret void 180 } 181 182 ; CHECK-LABEL: CallConst 183 ; CHECK: e8 bc 03 01 00 call {{[0-9a-f]+}} {{.*}} R_386_PC32 *ABS* 184 ; CHECK: e8 bc 03 01 00 call {{[0-9a-f]+}} {{.*}} R_386_PC32 *ABS* 185 ; CHECK: e8 bc 03 01 00 call {{[0-9a-f]+}} {{.*}} R_386_PC32 *ABS* 186 ; 187 ; OPTM1-LABEL: CallConst 188 ; OPTM1: e8 bc 03 01 00 call {{[0-9a-f]+}} {{.*}} R_386_PC32 *ABS* 189 ; OPTM1: e8 bc 03 01 00 call {{[0-9a-f]+}} {{.*}} R_386_PC32 *ABS* 190 ; OPTM1: e8 bc 03 01 00 call {{[0-9a-f]+}} {{.*}} R_386_PC32 *ABS* 191 ; 192 ; X8664-LABEL: CallConst 193 ; TODO(jpp): fix absolute call emission. 194 ; These are broken: the emitted code should be 195 ; e8 00 00 00 00 call {{.*}} *ABS*+0x103bc 196 ; 197 ; X8664-OPTM1-LABEL: CallConst 198 ; TODO(jpp): fix absolute call emission. 199 ; These are broken: the emitted code should be 200 ; e8 00 00 00 00 call {{.*}} *ABS*+0x103bc 201 ; 202 ; ARM32-LABEL: CallConst 203 ; ARM32: movw [[REGISTER:r.*]], #960 204 ; ARM32: movt [[REGISTER]], #1 205 ; ARM32: blx [[REGISTER]] 206 ; The legalization of the constant could be shared, but it isn't. 207 ; ARM32: movw [[REGISTER:r.*]], #960 208 ; ARM32: blx [[REGISTER]] 209 ; ARM32: blx [[REGISTER]] 210