[llvm] r196312 - Fix mingw32 thiscall + sret.

Rafael Espindola rafael.espindola at gmail.com
Tue Dec 3 12:51:24 PST 2013


Author: rafael
Date: Tue Dec  3 14:51:23 2013
New Revision: 196312

URL: http://llvm.org/viewvc/llvm-project?rev=196312&view=rev
Log:
Fix mingw32 thiscall + sret.

Unlike msvc, when handling a thiscall + sret gcc will
* Put the sret in %ecx
* Put the this pointer is (%esp)

This fixes, for example, calling stringstream::str.

Modified:
    llvm/trunk/lib/Target/X86/X86CallingConv.td
    llvm/trunk/test/CodeGen/X86/win32_sret.ll

Modified: llvm/trunk/lib/Target/X86/X86CallingConv.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86CallingConv.td?rev=196312&r1=196311&r2=196312&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86CallingConv.td (original)
+++ llvm/trunk/lib/Target/X86/X86CallingConv.td Tue Dec  3 14:51:23 2013
@@ -453,18 +453,34 @@ def CC_X86_32_FastCall : CallingConv<[
   CCDelegateTo<CC_X86_32_Common>
 ]>;
 
-def CC_X86_32_ThisCall : CallingConv<[
+def CC_X86_32_ThisCall_Common : CallingConv<[
+  // The first integer argument is passed in ECX
+  CCIfType<[i32], CCAssignToReg<[ECX]>>,
+
+  // Otherwise, same as everything else.
+  CCDelegateTo<CC_X86_32_Common>
+]>;
+
+def CC_X86_32_ThisCall_Mingw : CallingConv<[
+  // Promote i8/i16 arguments to i32.
+  CCIfType<[i8, i16], CCPromoteToType<i32>>,
+
+  CCDelegateTo<CC_X86_32_ThisCall_Common>
+]>;
+
+def CC_X86_32_ThisCall_Win : CallingConv<[
   // Promote i8/i16 arguments to i32.
   CCIfType<[i8, i16], CCPromoteToType<i32>>,
 
   // Pass sret arguments indirectly through stack.
   CCIfSRet<CCAssignToStack<4, 4>>,
 
-  // The first integer argument is passed in ECX
-  CCIfType<[i32], CCAssignToReg<[ECX]>>,
+  CCDelegateTo<CC_X86_32_ThisCall_Common>
+]>;
 
-  // Otherwise, same as everything else.
-  CCDelegateTo<CC_X86_32_Common>
+def CC_X86_32_ThisCall : CallingConv<[
+  CCIfSubtarget<"isTargetCygMing()", CCDelegateTo<CC_X86_32_ThisCall_Mingw>>,
+  CCDelegateTo<CC_X86_32_ThisCall_Win>
 ]>;
 
 def CC_X86_32_FastCC : CallingConv<[

Modified: llvm/trunk/test/CodeGen/X86/win32_sret.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win32_sret.ll?rev=196312&r1=196311&r2=196312&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/win32_sret.ll (original)
+++ llvm/trunk/test/CodeGen/X86/win32_sret.ll Tue Dec  3 14:51:23 2013
@@ -124,3 +124,31 @@ entry:
 ; WIN32:      ret
   ret void
 }
+
+
+%struct.test6 = type { i32, i32, i32 }
+define void @test6_f(%struct.test6* %x) nounwind {
+; WIN32-LABEL: _test6_f:
+; MINGW_X86-LABEL: _test6_f:
+
+; The %x argument is moved to %ecx. It will be the this pointer.
+; WIN32: movl    8(%ebp), %ecx
+
+; The %x argument is moved to (%esp). It will be the this pointer. With -O0
+; we copy esp to ecx and use (ecx) instead of (esp).
+; MINGW_X86: movl    8(%ebp), %eax
+; MINGW_X86: movl    %eax, (%e{{([a-d]x)|(sp)}})
+
+; The sret pointer is (%esp)
+; WIN32:          leal    8(%esp), %[[REG:e[a-d]x]]
+; WIN32-NEXT:     movl    %[[REG]], (%e{{([a-d]x)|(sp)}})
+
+; The sret pointer is %ecx
+; MINGW_X86-NEXT: leal    8(%esp), %ecx
+; MINGW_X86-NEXT: calll   _test6_g
+
+  %tmp = alloca %struct.test6, align 4
+  call x86_thiscallcc void @test6_g(%struct.test6* sret %tmp, %struct.test6* %x)
+  ret void
+}
+declare x86_thiscallcc void @test6_g(%struct.test6* sret, %struct.test6*)





More information about the llvm-commits mailing list