• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
49define internal void @CallIndirect(i32 %f) {
50entry:
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
115define internal void @CallIndirectGlobal() {
116entry:
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.
173define internal void @CallConst() {
174entry:
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