Fix tail call support in VC++ builds
authorJeff Cohen <jeffc@jolt-lang.org>
Fri, 20 May 2005 01:35:39 +0000 (01:35 +0000)
committerJeff Cohen <jeffc@jolt-lang.org>
Fri, 20 May 2005 01:35:39 +0000 (01:35 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22143 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86JITInfo.cpp

index 77200d0ac9873428a2e60869e0085c54438812e4..4fef094a3facb3e90fd5b39953a80772fbe4b529 100644 (file)
@@ -28,45 +28,56 @@ void X86JITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
 }
 
 
-#ifdef _MSC_VER
-#pragma optimize("y", off)
-#endif
-
 /// JITCompilerFunction - This contains the address of the JIT function used to
 /// compile a function lazily.
 static TargetJITInfo::JITCompilerFn JITCompilerFunction;
 
 // Provide a wrapper for X86CompilationCallback2 that saves non-traditional
 // callee saved registers, for the fastcc calling convention.
-extern "C" void X86CompilationCallback(void);
-
-#if defined(__i386__) || defined(i386)
+extern "C" {
+#if defined(__i386__) || defined(i386) || defined(_M_IX86)
 #ifndef _MSC_VER
-asm(
-   ".text\n"
-   ".align 8\n"
-   ".globl X86CompilationCallback\n"
-"X86CompilationCallback:\n"
-   "pushl   %ebp\n"
-   "movl    %esp, %ebp\n"    // Standard prologue
-   "pushl   %eax\n"
-   "pushl   %edx\n"          // save EAX/EDX
-   "call X86CompilationCallback2\n"
-   "popl    %edx\n"
-   "popl    %eax\n"
-   "popl    %ebp\n"
-   "ret\n");
+  void X86CompilationCallback(void);
+  asm(
+    ".text\n"
+    ".align 8\n"
+    ".globl X86CompilationCallback\n"
+  "X86CompilationCallback:\n"
+    "pushl   %ebp\n"
+    "movl    %esp, %ebp\n"    // Standard prologue
+    "pushl   %eax\n"
+    "pushl   %edx\n"          // save EAX/EDX
+    "call X86CompilationCallback2\n"
+    "popl    %edx\n"
+    "popl    %eax\n"
+    "popl    %ebp\n"
+    "ret\n");
 #else
-// FIXME: implement this for VC++
+  extern "C" void *_AddressOfReturnAddress(void);
+  #pragma intrinsic(_AddressOfReturnAddress)
+
+  void X86CompilationCallback2(void);
+
+  _declspec(naked) void X86CompilationCallback(void) {
+    __asm {
+      push  eax
+      push  edx
+      call  X86CompilationCallback2
+      pop   edx
+      pop   eax
+      ret
+    }
+  }
 #endif
 
 #else
-// Not an i386 host
-void X86CompilationCallback() {
-  assert(0 && "This is not a X86, you can't execute this!");
-  abort();
-}
+  // Not an i386 host
+  void X86CompilationCallback() {
+    assert(0 && "This is not a X86, you can't execute this!");
+    abort();
+  }
 #endif
+}
 
 /// X86CompilationCallback - This is the target-specific function invoked by the
 /// function stub when we did not know the real target of a call.  This function
@@ -74,14 +85,14 @@ void X86CompilationCallback() {
 /// compiler function.
 extern "C" void X86CompilationCallback2() {
 #ifdef _MSC_VER
-  // FIXME: This needs to go up one more level!
-  unsigned *StackPtr, RetAddr;
-  __asm mov StackPtr, ebp;
-  __asm mov eax, DWORD PTR [ebp + 4];
-  __asm mov RetAddr, eax;
+  assert(sizeof(size_t) == 4); // FIXME: handle Win64
+  unsigned *RetAddrLoc = (unsigned *)_AddressOfReturnAddress();
+  RetAddrLoc += 3;  // skip over ret addr, edx, eax
+  unsigned RetAddr = *RetAddrLoc;
 #else
   unsigned *StackPtr = (unsigned*)__builtin_frame_address(1);
   unsigned RetAddr = (unsigned)(intptr_t)__builtin_return_address(1);
+  unsigned *RetAddrLoc = &StackPtr[1];
 
   // NOTE: __builtin_frame_address doesn't work if frame pointer elimination has
   // been performed.  Having a variable sized alloca disables frame pointer
@@ -89,7 +100,7 @@ extern "C" void X86CompilationCallback2() {
   alloca(10+(RetAddr >> 31));
 
 #endif
-  assert(StackPtr[1] == RetAddr &&
+  assert(*RetAddrLoc == RetAddr &&
          "Could not find return address on the stack!");
 
   // It's a stub if there is an interrupt marker after the call.
@@ -123,13 +134,9 @@ extern "C" void X86CompilationCallback2() {
   }
 
   // Change the return address to reexecute the call instruction...
-  StackPtr[1] -= 5;
+  *RetAddrLoc -= 5;
 }
 
-#ifdef _MSC_VER
-#pragma optimize( "", on )
-#endif
-
 TargetJITInfo::LazyResolverFn
 X86JITInfo::getLazyResolverFunction(JITCompilerFn F) {
   JITCompilerFunction = F;