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 | |