1 | // REQUIRES: x86-registered-target |
2 | // RUN: %clang_cc1 %s -triple i386-apple-darwin10 -fasm-blocks -emit-llvm -o - | FileCheck %s |
3 | |
4 | void t1() { |
5 | // CHECK: @t1 |
6 | // CHECK: call void asm sideeffect inteldialect "", "~{dirflag},~{fpsr},~{flags}"() |
7 | // CHECK: ret void |
8 | __asm {} |
9 | } |
10 | |
11 | void t2() { |
12 | // CHECK: @t2 |
13 | // CHECK: call void asm sideeffect inteldialect "nop\0A\09nop\0A\09nop", "~{dirflag},~{fpsr},~{flags}"() |
14 | // CHECK: ret void |
15 | __asm nop |
16 | __asm nop |
17 | __asm nop |
18 | } |
19 | |
20 | void t3() { |
21 | // CHECK: @t3 |
22 | // CHECK: call void asm sideeffect inteldialect "nop\0A\09nop\0A\09nop", "~{dirflag},~{fpsr},~{flags}"() |
23 | // CHECK: ret void |
24 | __asm nop __asm nop __asm nop |
25 | } |
26 | |
27 | void t4(void) { |
28 | // CHECK: @t4 |
29 | // CHECK: call void asm sideeffect inteldialect "mov ebx, eax\0A\09mov ecx, ebx", "~{ebx},~{ecx},~{dirflag},~{fpsr},~{flags}"() |
30 | // CHECK: ret void |
31 | __asm mov ebx, eax |
32 | __asm mov ecx, ebx |
33 | } |
34 | |
35 | void t5(void) { |
36 | // CHECK: @t5 |
37 | // CHECK: call void asm sideeffect inteldialect "mov ebx, eax\0A\09mov ecx, ebx", "~{ebx},~{ecx},~{dirflag},~{fpsr},~{flags}"() |
38 | // CHECK: ret void |
39 | __asm mov ebx, eax __asm mov ecx, ebx |
40 | } |
41 | |
42 | void t6(void) { |
43 | __asm int 0x2c |
44 | // CHECK: t6 |
45 | // CHECK: call void asm sideeffect inteldialect "int $$44", "~{dirflag},~{fpsr},~{flags}"() |
46 | } |
47 | |
48 | void t7() { |
49 | __asm { |
50 | int 0x2cU ; } asm comments are fun! }{ |
51 | } |
52 | __asm { |
53 | { |
54 | int 0x2c ; } asm comments are fun! }{ |
55 | } |
56 | } |
57 | __asm {} |
58 | __asm { |
59 | ; |
60 | ; label |
61 | mov eax, ebx |
62 | } |
63 | // CHECK: t7 |
64 | // CHECK: call void asm sideeffect inteldialect "int $$44", "~{dirflag},~{fpsr},~{flags}"() |
65 | // CHECK: call void asm sideeffect inteldialect "", "~{dirflag},~{fpsr},~{flags}"() |
66 | // CHECK: call void asm sideeffect inteldialect "mov eax, ebx", "~{eax},~{dirflag},~{fpsr},~{flags}"() |
67 | } |
68 | |
69 | int t8() { |
70 | __asm int 4 ; } comments for single-line asm |
71 | __asm {} |
72 | __asm { int 5} |
73 | __asm int 6 |
74 | __asm int 7 |
75 | __asm { |
76 | int 8 |
77 | } |
78 | return 10; |
79 | // CHECK: t8 |
80 | // CHECK: call i32 asm sideeffect inteldialect "int $$4", "={eax},~{dirflag},~{fpsr},~{flags}"() |
81 | // CHECK: call i32 asm sideeffect inteldialect "", "={eax},~{dirflag},~{fpsr},~{flags}"() |
82 | // CHECK: call i32 asm sideeffect inteldialect "int $$5", "={eax},~{dirflag},~{fpsr},~{flags}"() |
83 | // CHECK: call i32 asm sideeffect inteldialect "int $$6\0A\09int $$7", "={eax},~{dirflag},~{fpsr},~{flags}"() |
84 | // CHECK: call i32 asm sideeffect inteldialect "int $$8", "={eax},~{dirflag},~{fpsr},~{flags}"() |
85 | // CHECK: ret i32 10 |
86 | } |
87 | |
88 | void t9() { |
89 | __asm { |
90 | push ebx |
91 | { mov ebx, 0x07 } |
92 | __asm { pop ebx } |
93 | } |
94 | // CHECK: t9 |
95 | // CHECK: call void asm sideeffect inteldialect |
96 | // CHECK-SAME: push ebx |
97 | // CHECK-SAME: mov ebx, $$7 |
98 | // CHECK-SAME: pop ebx |
99 | // CHECK-SAME: "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() |
100 | } |
101 | |
102 | unsigned t10(void) { |
103 | unsigned i = 1, j; |
104 | __asm { |
105 | mov eax, i |
106 | mov j, eax |
107 | } |
108 | return j; |
109 | // CHECK: t10 |
110 | // CHECK: [[r:%[a-zA-Z0-9]+]] = alloca i32, align 4 |
111 | // CHECK: [[I:%[a-zA-Z0-9]+]] = alloca i32, align 4 |
112 | // CHECK: [[J:%[a-zA-Z0-9]+]] = alloca i32, align 4 |
113 | // CHECK: store i32 1, i32* [[I]], align 4 |
114 | // CHECK: call i32 asm sideeffect inteldialect |
115 | // CHECK-SAME: mov eax, $2 |
116 | // CHECK-SAME: mov $0, eax |
117 | // CHECK-SAME: "=*m,={eax},*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}) |
118 | // CHECK: [[RET:%[a-zA-Z0-9]+]] = load i32, i32* [[J]], align 4 |
119 | // CHECK: ret i32 [[RET]] |
120 | } |
121 | |
122 | void t11(void) { |
123 | __asm mov eax, 1 |
124 | // CHECK: t11 |
125 | // CHECK: call void asm sideeffect inteldialect "mov eax, $$1", "~{eax},~{dirflag},~{fpsr},~{flags}"() |
126 | } |
127 | |
128 | unsigned t12(void) { |
129 | unsigned i = 1, j, l = 1, m; |
130 | __asm { |
131 | mov eax, i |
132 | mov j, eax |
133 | mov eax, l |
134 | mov m, eax |
135 | } |
136 | return j + m; |
137 | // CHECK: t12 |
138 | // CHECK: call i32 asm sideeffect inteldialect |
139 | // CHECK-SAME: mov eax, $3 |
140 | // CHECK-SAME: mov $0, eax |
141 | // CHECK-SAME: mov eax, $4 |
142 | // CHECK-SAME: mov $1, eax |
143 | // CHECK-SAME: "=*m,=*m,={eax},*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}) |
144 | } |
145 | |
146 | void t13() { |
147 | char i = 1; |
148 | short j = 2; |
149 | __asm movzx eax, i |
150 | __asm movzx eax, j |
151 | // CHECK-LABEL: define void @t13() |
152 | // CHECK: call void asm sideeffect inteldialect |
153 | // CHECK-SAME: movzx eax, byte ptr $0 |
154 | // CHECK-SAME: movzx eax, word ptr $1 |
155 | // CHECK-SAME: "*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i8* %{{.*}}i, i16* %{{.*}}j) |
156 | } |
157 | |
158 | void t13_brac() { |
159 | char i = 1; |
160 | short j = 2; |
161 | __asm movzx eax, [i] |
162 | __asm movzx eax, [j] |
163 | // CHECK-LABEL: define void @t13_brac() |
164 | // CHECK: call void asm sideeffect inteldialect |
165 | // CHECK-SAME: movzx eax, byte ptr $0 |
166 | // CHECK-SAME: movzx eax, word ptr $1 |
167 | // CHECK-SAME: "*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i8* %{{.*}}i, i16* %{{.*}}j) |
168 | } |
169 | |
170 | void t14() { |
171 | unsigned i = 1, j = 2; |
172 | __asm { |
173 | .if 1 |
174 | { mov eax, i } |
175 | .else |
176 | mov ebx, j |
177 | .endif |
178 | } |
179 | // CHECK: t14 |
180 | // CHECK: call void asm sideeffect inteldialect ".if 1\0A\09mov eax, $0\0A\09.else\0A\09mov ebx, j\0A\09.endif", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) |
181 | } |
182 | |
183 | int gvar = 10; |
184 | void t15() { |
185 | // CHECK: t15 |
186 | int lvar = 10; |
187 | __asm mov eax, lvar ; eax = 10 |
188 | // CHECK: mov eax, $0 |
189 | __asm mov eax, offset lvar ; eax = address of lvar |
190 | // CHECK: mov eax, $1 |
191 | __asm mov eax, offset gvar ; eax = address of gvar |
192 | // CHECK: mov eax, $2 |
193 | // CHECK: "*m,r,r,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}, i32* @{{.*}}) |
194 | } |
195 | |
196 | void t16() { |
197 | int var = 10; |
198 | __asm mov [eax], offset var |
199 | // CHECK: t16 |
200 | // CHECK: call void asm sideeffect inteldialect "mov [eax], $0", "r,~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) |
201 | } |
202 | |
203 | void t17() { |
204 | // CHECK: t17 |
205 | __asm _emit 0x4A |
206 | // CHECK: .byte 0x4A |
207 | __asm _emit 0x43L |
208 | // CHECK: .byte 0x43L |
209 | __asm _emit 0x4B |
210 | // CHECK: .byte 0x4B |
211 | __asm _EMIT 0x4B |
212 | // CHECK: .byte 0x4B |
213 | // CHECK: "~{dirflag},~{fpsr},~{flags}"() |
214 | } |
215 | |
216 | void t20() { |
217 | // CHECK: t20 |
218 | char bar; |
219 | int foo; |
220 | char _bar[2]; |
221 | int _foo[4]; |
222 | |
223 | __asm mov eax, LENGTH foo |
224 | // CHECK: mov eax, $$1 |
225 | __asm mov eax, LENGTH bar |
226 | // CHECK: mov eax, $$1 |
227 | __asm mov eax, LENGTH _foo |
228 | // CHECK: mov eax, $$4 |
229 | __asm mov eax, LENGTH _bar |
230 | // CHECK: mov eax, $$2 |
231 | __asm mov eax, [eax + LENGTH foo * 4] |
232 | // CHECK: mov eax, [eax + $$4] |
233 | |
234 | __asm mov eax, TYPE foo |
235 | // CHECK: mov eax, $$4 |
236 | __asm mov eax, TYPE bar |
237 | // CHECK: mov eax, $$1 |
238 | __asm mov eax, TYPE _foo |
239 | // CHECK: mov eax, $$4 |
240 | __asm mov eax, TYPE _bar |
241 | // CHECK: mov eax, $$1 |
242 | __asm mov eax, [eax + TYPE foo * 4] |
243 | // CHECK: mov eax, [eax + $$16] |
244 | |
245 | __asm mov eax, SIZE foo |
246 | // CHECK: mov eax, $$4 |
247 | __asm mov eax, SIZE bar |
248 | // CHECK: mov eax, $$1 |
249 | __asm mov eax, SIZE _foo |
250 | // CHECK: mov eax, $$16 |
251 | __asm mov eax, [eax + SIZE _foo * 4] |
252 | // CHECK: mov eax, [eax + $$64] |
253 | __asm mov eax, SIZE _bar |
254 | // CHECK: mov eax, $$2 |
255 | // CHECK: "~{eax},~{dirflag},~{fpsr},~{flags}"() |
256 | |
257 | } |
258 | |
259 | void t21() { |
260 | __asm { |
261 | __asm push ebx |
262 | __asm mov ebx, 07H |
263 | __asm pop ebx |
264 | } |
265 | // CHECK: t21 |
266 | // CHECK: call void asm sideeffect inteldialect |
267 | // CHECK-SAME: push ebx |
268 | // CHECK-SAME: mov ebx, $$7 |
269 | // CHECK-SAME: pop ebx |
270 | // CHECK-SAME: "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() |
271 | } |
272 | |
273 | extern void t22_helper(int x); |
274 | void t22() { |
275 | int x = 0; |
276 | __asm { |
277 | __asm push ebx |
278 | __asm mov ebx, esp |
279 | } |
280 | t22_helper(x); |
281 | __asm { |
282 | __asm mov esp, ebx |
283 | __asm pop ebx |
284 | } |
285 | // CHECK: t22 |
286 | // CHECK: call void asm sideeffect inteldialect |
287 | // CHECK-SAME: push ebx |
288 | // CHECK-SAME: mov ebx, esp |
289 | // CHECK-SAME: "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() |
290 | // CHECK: call void @t22_helper |
291 | // CHECK: call void asm sideeffect inteldialect |
292 | // CHECK-SAME: mov esp, ebx |
293 | // CHECK-SAME: pop ebx |
294 | // CHECK-SAME: "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() |
295 | } |
296 | |
297 | void t23() { |
298 | __asm { |
299 | the_label: |
300 | } |
301 | // CHECK: t23 |
302 | // CHECK: call void asm sideeffect inteldialect "{{.*}}__MSASMLABEL_.${:uid}__the_label:", "~{dirflag},~{fpsr},~{flags}"() |
303 | } |
304 | |
305 | void t24_helper(void) {} |
306 | void t24() { |
307 | __asm call t24_helper |
308 | // CHECK: t24 |
309 | // CHECK: call void asm sideeffect inteldialect "call dword ptr $0", "*m,~{dirflag},~{fpsr},~{flags}"(void ()* @t24_helper) |
310 | } |
311 | |
312 | void t25() { |
313 | // CHECK: t25 |
314 | __asm mov eax, 0ffffffffh |
315 | // CHECK: mov eax, $$4294967295 |
316 | __asm mov eax, 0fhU |
317 | // CHECK: mov eax, $$15 |
318 | __asm mov eax, 0a2h |
319 | // CHECK: mov eax, $$162 |
320 | __asm mov eax, 10100010b |
321 | // CHECK: mov eax, $$162 |
322 | __asm mov eax, 10100010BU |
323 | // CHECK: mov eax, $$162 |
324 | // CHECK: "~{eax},~{dirflag},~{fpsr},~{flags}"() |
325 | } |
326 | |
327 | void t26() { |
328 | // CHECK: t26 |
329 | __asm pushad |
330 | // CHECK: pushad |
331 | __asm mov eax, 0 |
332 | // CHECK: mov eax, $$0 |
333 | __asm __emit 0fh |
334 | // CHECK: .byte 0fh |
335 | __asm __emit 0a2h |
336 | // CHECK: .byte 0a2h |
337 | __asm __EMIT 0a2h |
338 | // CHECK: .byte 0a2h |
339 | __asm popad |
340 | // CHECK: popad |
341 | // CHECK: "~{eax},~{ebp},~{ebx},~{ecx},~{edi},~{edx},~{esi},~{esp},~{dirflag},~{fpsr},~{flags}"() |
342 | } |
343 | |
344 | void t27() { |
345 | __asm mov eax, fs:[0h] |
346 | // CHECK: t27 |
347 | // CHECK: call void asm sideeffect inteldialect "mov eax, fs:[$$0]", "~{eax},~{dirflag},~{fpsr},~{flags}"() |
348 | } |
349 | |
350 | void t28() { |
351 | // CHECK: t28 |
352 | __asm align 8 |
353 | // CHECK: .align 3 |
354 | __asm align 16; |
355 | // CHECK: .align 4 |
356 | __asm align 128; |
357 | // CHECK: .align 7 |
358 | __asm ALIGN 256; |
359 | // CHECK: .align 8 |
360 | // CHECK: "~{dirflag},~{fpsr},~{flags}"() |
361 | } |
362 | |
363 | void t29() { |
364 | // CHECK: t29 |
365 | int arr[2] = {0, 0}; |
366 | int olen = 0, osize = 0, otype = 0; |
367 | __asm mov olen, LENGTH arr |
368 | // CHECK: mov dword ptr $0, $$2 |
369 | __asm mov osize, SIZE arr |
370 | // CHECK: mov dword ptr $1, $$8 |
371 | __asm mov otype, TYPE arr |
372 | // CHECK: mov dword ptr $2, $$4 |
373 | // CHECK: "=*m,=*m,=*m,~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}) |
374 | } |
375 | |
376 | int results[2] = {13, 37}; |
377 | int *t30() |
378 | // CHECK: t30 |
379 | { |
380 | int *res; |
381 | __asm lea edi, results |
382 | // CHECK: lea edi, $2 |
383 | __asm mov res, edi |
384 | // CHECK: mov $0, edi |
385 | return res; |
386 | // CHECK: "=*m,={eax},*m,~{edi},~{dirflag},~{fpsr},~{flags}"(i32** %{{.*}}, [2 x i32]* @{{.*}}) |
387 | } |
388 | |
389 | void t31() { |
390 | // CHECK: t31 |
391 | __asm pushad |
392 | // CHECK: pushad |
393 | __asm popad |
394 | // CHECK: popad |
395 | // CHECK: "~{eax},~{ebp},~{ebx},~{ecx},~{edi},~{edx},~{esi},~{esp},~{dirflag},~{fpsr},~{flags}"() |
396 | } |
397 | |
398 | void t32() { |
399 | // CHECK: t32 |
400 | int i; |
401 | __asm mov eax, i |
402 | // CHECK: mov eax, $0 |
403 | __asm mov eax, dword ptr i |
404 | // CHECK: mov eax, dword ptr $1 |
405 | __asm mov ax, word ptr i |
406 | // CHECK: mov ax, word ptr $2 |
407 | __asm mov al, byte ptr i |
408 | // CHECK: mov al, byte ptr $3 |
409 | // CHECK: "*m,*m,*m,*m,~{al},~{ax},~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}) |
410 | } |
411 | |
412 | void t33() { |
413 | // CHECK: t33 |
414 | int i; |
415 | __asm mov eax, [i] |
416 | // CHECK: mov eax, $0 |
417 | __asm mov eax, dword ptr [i] |
418 | // CHECK: mov eax, dword ptr $1 |
419 | __asm mov ax, word ptr [i] |
420 | // CHECK: mov ax, word ptr $2 |
421 | __asm mov al, byte ptr [i] |
422 | // CHECK: mov al, byte ptr $3 |
423 | // CHECK: "*m,*m,*m,*m,~{al},~{ax},~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}) |
424 | } |
425 | |
426 | void t34() { |
427 | // CHECK: t34 |
428 | __asm prefetchnta 64[eax] |
429 | // CHECK: prefetchnta [eax + $$64] |
430 | __asm mov eax, dword ptr 4[eax] |
431 | // CHECK: mov eax, dword ptr [eax + $$4] |
432 | // CHECK: "~{eax},~{dirflag},~{fpsr},~{flags}"() |
433 | } |
434 | |
435 | void t35() { |
436 | // CHECK: t35 |
437 | __asm prefetchnta [eax + (200*64)] |
438 | // CHECK: prefetchnta [eax + $$12800] |
439 | __asm mov eax, dword ptr [eax + (200*64)] |
440 | // CHECK: mov eax, dword ptr [eax + $$12800] |
441 | // CHECK: "~{eax},~{dirflag},~{fpsr},~{flags}"() |
442 | } |
443 | |
444 | void t36() { |
445 | // CHECK: t36 |
446 | int arr[4]; |
447 | // Work around PR20368: These should be single line blocks |
448 | __asm { mov eax, 4[arr] } |
449 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$4]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) |
450 | __asm { mov eax, 4[arr + 4] } |
451 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$8]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) |
452 | __asm { mov eax, 8[arr + 4 + 32*2 - 4] } |
453 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$72]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) |
454 | __asm { mov eax, 12[4 + arr] } |
455 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$16]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) |
456 | __asm { mov eax, 4[4 + arr + 4] } |
457 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$12]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) |
458 | __asm { mov eax, 4[64 + arr + (2*32)] } |
459 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$132]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) |
460 | __asm { mov eax, 4[64 + arr - 2*32] } |
461 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$4]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) |
462 | __asm { mov eax, [arr + 4] } |
463 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$4]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) |
464 | __asm { mov eax, [arr + 4 + 32*2 - 4] } |
465 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$64]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) |
466 | __asm { mov eax, [4 + arr] } |
467 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$4]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) |
468 | __asm { mov eax, [4 + arr + 4] } |
469 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$8]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) |
470 | __asm { mov eax, [64 + arr + (2*32)] } |
471 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$128]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) |
472 | __asm { mov eax, [64 + arr - 2*32] } |
473 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) |
474 | } |
475 | |
476 | void t37() { |
477 | // CHECK: t37 |
478 | __asm mov eax, 4 + 8 |
479 | // CHECK: mov eax, $$12 |
480 | __asm mov eax, 4 + 8 * 16 |
481 | // CHECK: mov eax, $$132 |
482 | __asm mov eax, -4 + 8 * 16 |
483 | // CHECK: mov eax, $$124 |
484 | __asm mov eax, (4 + 4) * 16 |
485 | // CHECK: mov eax, $$128 |
486 | __asm mov eax, 4 + 8 * -16 |
487 | // CHECK: mov eax, $$-124 |
488 | __asm mov eax, 4 + 16 / -8 |
489 | // CHECK: mov eax, $$2 |
490 | __asm mov eax, (16 + 16) / -8 |
491 | // CHECK: mov eax, $$-4 |
492 | __asm mov eax, ~15 |
493 | // CHECK: mov eax, $$-16 |
494 | __asm mov eax, 6 ^ 3 |
495 | // CHECK: mov eax, $$5 |
496 | // CHECK: "~{eax},~{dirflag},~{fpsr},~{flags}"() |
497 | } |
498 | |
499 | void t38() { |
500 | // CHECK: t38 |
501 | int arr[4]; |
502 | // Work around PR20368: These should be single line blocks |
503 | __asm { mov eax, 4+4[arr] } |
504 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$8]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) |
505 | __asm { mov eax, (4+4)[arr + 4] } |
506 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$12]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) |
507 | __asm { mov eax, 8*2[arr + 4 + 32*2 - 4] } |
508 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$80]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) |
509 | __asm { mov eax, 12+20[4 + arr] } |
510 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$36]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) |
511 | __asm { mov eax, 4*16+4[4 + arr + 4] } |
512 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$76]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) |
513 | __asm { mov eax, 4*4[64 + arr + (2*32)] } |
514 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$144]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) |
515 | __asm { mov eax, 4*(4-2)[64 + arr - 2*32] } |
516 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$8]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) |
517 | __asm { mov eax, 32*(4-2)[arr - 2*32] } |
518 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) |
519 | } |
520 | |
521 | void cpuid() { |
522 | __asm cpuid |
523 | // CHECK-LABEL: define void @cpuid |
524 | // CHECK: call void asm sideeffect inteldialect "cpuid", "~{eax},~{ebx},~{ecx},~{edx},~{dirflag},~{fpsr},~{flags}"() |
525 | } |
526 | |
527 | typedef struct { |
528 | int a; |
529 | int b; |
530 | } A, *pA; |
531 | |
532 | typedef struct { |
533 | int b1; |
534 | A b2; |
535 | } B; |
536 | |
537 | typedef struct { |
538 | int c1; |
539 | A c2; |
540 | int c3; |
541 | B c4; |
542 | } C, *pC; |
543 | |
544 | void t39() { |
545 | // CHECK-LABEL: define void @t39 |
546 | __asm mov eax, [eax].A.b |
547 | // CHECK: mov eax, [eax + $$4] |
548 | __asm mov eax, [eax] A.b |
549 | // CHECK: mov eax, [eax + $$4] |
550 | __asm mov eax, [eax] pA.b |
551 | // CHECK: mov eax, [eax + $$4] |
552 | __asm mov eax, fs:[0] A.b |
553 | // CHECK: mov eax, fs:[$$4] |
554 | __asm mov eax, [eax].B.b2.a |
555 | // CHECK: mov eax, [eax + $$4] |
556 | __asm mov eax, [eax] B.b2.b |
557 | // CHECK: mov eax, [eax + $$8] |
558 | __asm mov eax, fs:[0] C.c2.b |
559 | // CHECK: mov eax, fs:[$$8] |
560 | __asm mov eax, [eax]C.c4.b2.b |
561 | // CHECK: mov eax, [eax + $$24] |
562 | __asm mov eax, [eax]pC.c4.b2.b |
563 | // CHECK: mov eax, [eax + $$24] |
564 | // CHECK: "~{eax},~{dirflag},~{fpsr},~{flags}"() |
565 | } |
566 | |
567 | void t40(float a) { |
568 | // CHECK-LABEL: define void @t40 |
569 | int i; |
570 | __asm fld a |
571 | // CHECK: fld dword ptr $1 |
572 | __asm fistp i |
573 | // CHECK: fistp dword ptr $0 |
574 | // CHECK: "=*m,*m,~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, float* %{{.*}}) |
575 | } |
576 | |
577 | void t41(unsigned short a) { |
578 | // CHECK-LABEL: define void @t41(i16 zeroext %a) |
579 | __asm mov cs, a; |
580 | // CHECK: mov cs, $0 |
581 | __asm mov ds, a; |
582 | // CHECK: mov ds, $1 |
583 | __asm mov es, a; |
584 | // CHECK: mov es, $2 |
585 | __asm mov fs, a; |
586 | // CHECK: mov fs, $3 |
587 | __asm mov gs, a; |
588 | // CHECK: mov gs, $4 |
589 | __asm mov ss, a; |
590 | // CHECK: mov ss, $5 |
591 | // CHECK: "*m,*m,*m,*m,*m,*m,~{dirflag},~{fpsr},~{flags}"(i16* {{.*}}, i16* {{.*}}, i16* {{.*}}, i16* {{.*}}, i16* {{.*}}, i16* {{.*}}) |
592 | } |
593 | |
594 | void t42() { |
595 | // CHECK-LABEL: define void @t42 |
596 | int flags; |
597 | __asm mov flags, eax |
598 | // CHECK: mov $0, eax |
599 | // CHECK: "=*m,~{dirflag},~{fpsr},~{flags}"(i32* %flags) |
600 | } |
601 | |
602 | void t43() { |
603 | // CHECK-LABEL: define void @t43 |
604 | C strct; |
605 | // Work around PR20368: These should be single line blocks |
606 | __asm { mov eax, 4[strct.c1] } |
607 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$4]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) |
608 | __asm { mov eax, 4[strct.c3 + 4] } |
609 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$8]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) |
610 | __asm { mov eax, 8[strct.c2.a + 4 + 32*2 - 4] } |
611 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$72]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) |
612 | __asm { mov eax, 12[4 + strct.c2.b] } |
613 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$16]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) |
614 | __asm { mov eax, 4[4 + strct.c4.b2.b + 4] } |
615 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$12]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) |
616 | __asm { mov eax, 4[64 + strct.c1 + (2*32)] } |
617 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$132]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) |
618 | __asm { mov eax, 4[64 + strct.c2.a - 2*32] } |
619 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$4]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) |
620 | __asm { mov eax, [strct.c4.b1 + 4] } |
621 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$4]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) |
622 | __asm { mov eax, [strct.c4.b2.a + 4 + 32*2 - 4] } |
623 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$64]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) |
624 | __asm { mov eax, [4 + strct.c1] } |
625 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$4]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) |
626 | __asm { mov eax, [4 + strct.c2.b + 4] } |
627 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$8]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) |
628 | __asm { mov eax, [64 + strct.c3 + (2*32)] } |
629 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0[$$128]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) |
630 | __asm { mov eax, [64 + strct.c4.b2.b - 2*32] } |
631 | // CHECK: call void asm sideeffect inteldialect "mov eax, $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) |
632 | } |
633 | |
634 | void t44() { |
635 | // CHECK-LABEL: define void @t44 |
636 | __asm { |
637 | mov cr0, eax |
638 | mov cr2, ebx |
639 | mov cr3, ecx |
640 | mov cr4, edx |
641 | } |
642 | // CHECK: call void asm sideeffect inteldialect "mov cr0, eax\0A\09mov cr2, ebx\0A\09mov cr3, ecx\0A\09mov cr4, edx", "~{cr0},~{cr2},~{cr3},~{cr4},~{dirflag},~{fpsr},~{flags}"() |
643 | } |
644 | |
645 | void t45() { |
646 | // CHECK-LABEL: define void @t45 |
647 | __asm { |
648 | mov dr0, eax |
649 | mov dr1, ebx |
650 | mov dr2, ebx |
651 | mov dr3, ecx |
652 | mov dr6, edx |
653 | mov dr7, ecx |
654 | } |
655 | // CHECK: call void asm sideeffect inteldialect "mov dr0, eax\0A\09mov dr1, ebx\0A\09mov dr2, ebx\0A\09mov dr3, ecx\0A\09mov dr6, edx\0A\09mov dr7, ecx", "~{dr0},~{dr1},~{dr2},~{dr3},~{dr6},~{dr7},~{dirflag},~{fpsr},~{flags}"() |
656 | } |
657 | |
658 | void t46() { |
659 | // CHECK-LABEL: define void @t46 |
660 | __asm add eax, -128[eax] |
661 | // CHECK: call void asm sideeffect inteldialect "add eax, [eax + $$-128]", "~{eax},~{flags},~{dirflag},~{fpsr},~{flags}"() |
662 | } |
663 | |
664 | void t47() { |
665 | // CHECK-LABEL: define void @t47 |
666 | __asm { |
667 | bndmk bnd0, dword ptr [eax] |
668 | bndmk bnd1, dword ptr [ebx] |
669 | bndmk bnd2, dword ptr [ecx] |
670 | bndmk bnd3, dword ptr [edx] |
671 | } |
672 | // CHECK: call void asm sideeffect inteldialect "bndmk bnd0, dword ptr [eax]\0A\09bndmk bnd1, dword ptr [ebx]\0A\09bndmk bnd2, dword ptr [ecx]\0A\09bndmk bnd3, dword ptr [edx]", "~{bnd0},~{bnd1},~{bnd2},~{bnd3},~{dirflag},~{fpsr},~{flags}"() |
673 | } |
674 | |
675 | void dot_operator(){ |
676 | // CHECK-LABEL: define void @dot_operator |
677 | __asm { mov eax, 3[ebx]A.b} |
678 | // CHECK: call void asm sideeffect inteldialect "mov eax, [ebx + $$7]", "~{eax},~{dirflag},~{fpsr},~{flags}" |
679 | } |
680 | |
681 | void call_clobber() { |
682 | __asm call t41 |
683 | // CHECK-LABEL: define void @call_clobber |
684 | // CHECK: call void asm sideeffect inteldialect "call dword ptr $0", "*m,~{dirflag},~{fpsr},~{flags}"(void (i16)* @t41) |
685 | } |
686 | |
687 | void xgetbv() { |
688 | __asm xgetbv |
689 | } |
690 | // CHECK-LABEL: define void @xgetbv() |
691 | // CHECK: call void asm sideeffect inteldialect "xgetbv", "~{eax},~{edx},~{dirflag},~{fpsr},~{flags}"() |
692 | |
693 | void label1() { |
694 | __asm { |
695 | label: |
696 | jmp label |
697 | } |
698 | // CHECK-LABEL: define void @label1() |
699 | // CHECK: call void asm sideeffect inteldialect "{{.*}}__MSASMLABEL_.${:uid}__label:\0A\09jmp {{.*}}__MSASMLABEL_.${:uid}__label", "~{dirflag},~{fpsr},~{flags}"() [[ATTR1:#[0-9]+]] |
700 | } |
701 | |
702 | void label2() { |
703 | __asm { |
704 | jmp label |
705 | label: |
706 | } |
707 | // CHECK-LABEL: define void @label2 |
708 | // CHECK: call void asm sideeffect inteldialect "jmp {{.*}}__MSASMLABEL_.${:uid}__label\0A\09{{.*}}__MSASMLABEL_.${:uid}__label:", "~{dirflag},~{fpsr},~{flags}"() |
709 | } |
710 | |
711 | void label3() { |
712 | __asm { |
713 | label: |
714 | mov eax, label |
715 | } |
716 | // CHECK-LABEL: define void @label3 |
717 | // CHECK: call void asm sideeffect inteldialect "{{.*}}__MSASMLABEL_.${:uid}__label:\0A\09mov eax, {{.*}}__MSASMLABEL_.${:uid}__label", "~{eax},~{dirflag},~{fpsr},~{flags}"() |
718 | } |
719 | |
720 | void label4() { |
721 | __asm { |
722 | label: |
723 | mov eax, [label] |
724 | } |
725 | // CHECK-LABEL: define void @label4 |
726 | // CHECK: call void asm sideeffect inteldialect "{{.*}}__MSASMLABEL_.${:uid}__label:\0A\09mov eax, {{.*}}__MSASMLABEL_.${:uid}__label", "~{eax},~{dirflag},~{fpsr},~{flags}"() |
727 | } |
728 | |
729 | void label5() { |
730 | __asm { |
731 | jmp dollar_label$ |
732 | dollar_label$: |
733 | } |
734 | // CHECK-LABEL: define void @label5 |
735 | // CHECK: call void asm sideeffect inteldialect "jmp {{.*}}__MSASMLABEL_.${:uid}__dollar_label$$\0A\09{{.*}}__MSASMLABEL_.${:uid}__dollar_label$$:", "~{dirflag},~{fpsr},~{flags}"() |
736 | } |
737 | |
738 | void label6(){ |
739 | __asm { |
740 | jmp short label |
741 | jc short label |
742 | jz short label |
743 | label: |
744 | } |
745 | // CHECK-LABEL: define void @label6 |
746 | // CHECK: jmp {{.*}}__MSASMLABEL_.${:uid}__label\0A\09jc {{.*}}__MSASMLABEL_.${:uid}__label\0A\09jz {{.*}}__MSASMLABEL_.${:uid}__label\0A\09{{.*}}__MSASMLABEL_.${:uid}__label:" |
747 | } |
748 | |
749 | // Don't include mxcsr in the clobber list. |
750 | void mxcsr() { |
751 | char buf[4096]; |
752 | __asm fxrstor buf |
753 | } |
754 | // CHECK-LABEL: define void @mxcsr |
755 | // CHECK: call void asm sideeffect inteldialect "fxrstor $0", "=*m,~{dirflag},~{fpsr},~{flags}" |
756 | |
757 | // Make sure we can find the register for the dirflag for popfd |
758 | void dirflag() { |
759 | __asm popfd |
760 | } |
761 | // CHECK-LABEL: define void @dirflag |
762 | // CHECK: call void asm sideeffect inteldialect "popfd", "~{dirflag},~{flags},~{esp},~{dirflag},~{fpsr},~{flags}" |
763 | |
764 | typedef union _LARGE_INTEGER { |
765 | struct { |
766 | unsigned int LowPart; |
767 | unsigned int HighPart; |
768 | }; |
769 | struct { |
770 | unsigned int LowPart; |
771 | unsigned int HighPart; |
772 | } u; |
773 | unsigned long long QuadPart; |
774 | } LARGE_INTEGER, *PLARGE_INTEGER; |
775 | |
776 | int test_indirect_field(LARGE_INTEGER LargeInteger) { |
777 | __asm mov eax, LargeInteger.LowPart |
778 | } |
779 | // CHECK-LABEL: define i32 @test_indirect_field( |
780 | // CHECK: call i32 asm sideeffect inteldialect "mov eax, $1", |
781 | |
782 | // MS ASM containing labels must not be duplicated (PR23715). |
783 | // CHECK: attributes [[ATTR1]] = { |
784 | // CHECK-NOT: noduplicate |
785 | // CHECK-SAME: }{{$}} |
786 | |