Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame^] | 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 | } |