61 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			61 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			C
		
	
	
	
| // REQUIRES: x86-registered-target
 | |
| // RUN: %clang_cc1 %s -triple i386-pc-windows-msvc -fms-extensions -S -o - | FileCheck %s
 | |
| 
 | |
| // Yes, this is an assembly test from Clang, because we need to make it all the
 | |
| // way through code generation to know if our call became a direct, pc-relative
 | |
| // call or an indirect call through memory.
 | |
| 
 | |
| int k(int);
 | |
| __declspec(dllimport) int kimport(int);
 | |
| int (*kptr)(int);
 | |
| int (*gptr())(int);
 | |
| 
 | |
| int foo() {
 | |
|   // CHECK-LABEL: _foo:
 | |
|   int (*r)(int) = gptr();
 | |
| 
 | |
|   // Simple case: direct call.
 | |
|   __asm call k;
 | |
|   // CHECK:     calll   _k
 | |
| 
 | |
|   // Marginally harder: indirect calls, via dllimport or function pointer.
 | |
|   __asm call r;
 | |
|   // CHECK:     calll   *({{.*}})
 | |
|   __asm call kimport;
 | |
|   // CHECK:     calll   *({{.*}})
 | |
| 
 | |
|   // Broken case: Call through a global function pointer.
 | |
|   __asm call kptr;
 | |
|   // CHECK:     calll   _kptr
 | |
|   // CHECK-FIXME: calll   *_kptr
 | |
| }
 | |
| 
 | |
| int bar() {
 | |
|   // CHECK-LABEL: _bar:
 | |
|   __asm jmp k;
 | |
|   // CHECK:     jmp     _k
 | |
| }
 | |
| 
 | |
| int baz() {
 | |
|   // CHECK-LABEL: _baz:
 | |
|   __asm mov eax, k;
 | |
|   // CHECK: movl    _k, %eax
 | |
|   __asm mov eax, kptr;
 | |
|   // CHECK: movl    _kptr, %eax
 | |
| }
 | |
| 
 | |
| // Test that this asm blob doesn't require more registers than available.  This
 | |
| // has to be an LLVM code generation test.
 | |
| 
 | |
| void __declspec(naked) naked() {
 | |
|   __asm pusha
 | |
|   __asm call k
 | |
|   __asm popa
 | |
|   __asm ret
 | |
|   // CHECK-LABEL: _naked:
 | |
|   // CHECK: pushal
 | |
|   // CHECK-NEXT: calll _k
 | |
|   // CHECK-NEXT: popal
 | |
|   // CHECK-NEXT: retl
 | |
| }
 |