1 // REQUIRES: x86-registered-target
2 // RUN: %clang_cc1 %s -triple i386-pc-windows-msvc -fms-extensions -S -o - | FileCheck %s
3 
4 // Yes, this is an assembly test from Clang, because we need to make it all the
5 // way through code generation to know if our call became a direct, pc-relative
6 // call or an indirect call through memory.
7 
8 int k(int);
9 __declspec(dllimport) int kimport(int);
10 int (*kptr)(int);
11 int (*gptr())(int);
12 
13 int foo() {
14   // CHECK-LABEL: _foo:
15   int (*r)(int) = gptr();
16 
17   // Simple case: direct call.
18   __asm call k;
19   // CHECK:     calll   _k
20 
21   // Marginally harder: indirect calls, via dllimport or function pointer.
22   __asm call r;
23   // CHECK:     calll   *({{.*}})
24   __asm call kimport;
25   // CHECK:     calll   *({{.*}})
26 
27   // Broken case: Call through a global function pointer.
28   __asm call kptr;
29   // CHECK:     calll   _kptr
30   // CHECK-FIXME: calll   *_kptr
31 }
32 
33 int bar() {
34   // CHECK-LABEL: _bar:
35   __asm jmp k;
36   // CHECK:     jmp     _k
37 }
38 
39 int baz() {
40   // CHECK-LABEL: _baz:
41   __asm mov eax, k;
42   // CHECK: movl    _k, %eax
43   __asm mov eax, kptr;
44   // CHECK: movl    _kptr, %eax
45 }
46 
47 // Test that this asm blob doesn't require more registers than available.  This
48 // has to be an LLVM code generation test.
49 
50 void __declspec(naked) naked() {
51   __asm pusha
52   __asm call k
53   __asm popa
54   __asm ret
55   // CHECK-LABEL: _naked:
56   // CHECK: pushal
57   // CHECK-NEXT: calll _k
58   // CHECK-NEXT: popal
59   // CHECK-NEXT: retl
60 }
61