From: Eli Friedman Date: Wed, 25 Jan 2012 22:46:34 +0000 (+0000) Subject: Add some ABI tweaks for i386-pc-win32 triple so that we return structs in an MSVC... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=55fc7e2b8005ba87a81664d065e9b9e2fff1b1af;p=clang Add some ABI tweaks for i386-pc-win32 triple so that we return structs in an MSVC-compatible way. Patch by Joe Groff. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148992 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index 956daef462..e5865f35bf 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -389,8 +389,8 @@ ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy) const { ABIArgInfo::getExtend() : ABIArgInfo::getDirect()); } -/// UseX86_MMXType - Return true if this is an MMX type that should use the special -/// x86_mmx type. +/// UseX86_MMXType - Return true if this is an MMX type that should use the +/// special x86_mmx type. bool UseX86_MMXType(llvm::Type *IRType) { // If the type is an MMX type <2 x i32>, <4 x i16>, or <8 x i8>, use the // special x86_mmx type. @@ -418,6 +418,7 @@ class X86_32ABIInfo : public ABIInfo { bool IsDarwinVectorABI; bool IsSmallStructInRegABI; bool IsMMXDisabled; + bool IsWin32FloatStructABI; static bool isRegisterSize(unsigned Size) { return (Size == 8 || Size == 16 || Size == 32 || Size == 64); @@ -447,15 +448,16 @@ public: virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty, CodeGenFunction &CGF) const; - X86_32ABIInfo(CodeGen::CodeGenTypes &CGT, bool d, bool p, bool m) + X86_32ABIInfo(CodeGen::CodeGenTypes &CGT, bool d, bool p, bool m, bool w) : ABIInfo(CGT), IsDarwinVectorABI(d), IsSmallStructInRegABI(p), - IsMMXDisabled(m) {} + IsMMXDisabled(m), IsWin32FloatStructABI(w) {} }; class X86_32TargetCodeGenInfo : public TargetCodeGenInfo { public: - X86_32TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, bool d, bool p, bool m) - :TargetCodeGenInfo(new X86_32ABIInfo(CGT, d, p, m)) {} + X86_32TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, + bool d, bool p, bool m, bool w) + :TargetCodeGenInfo(new X86_32ABIInfo(CGT, d, p, m, w)) {} void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const; @@ -586,10 +588,12 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy) const { // As a special-case, if the struct is a "single-element" struct, and // the field is of type "float" or "double", return it in a - // floating-point register. We apply a similar transformation for - // pointer types to improve the quality of the generated IR. + // floating-point register. (MSVC does not apply this special case.) + // We apply a similar transformation for pointer types to improve the + // quality of the generated IR. if (const Type *SeltTy = isSingleElementStruct(RetTy, getContext())) - if (SeltTy->isRealFloatingType() || SeltTy->hasPointerRepresentation()) + if ((!IsWin32FloatStructABI && SeltTy->isRealFloatingType()) + || SeltTy->hasPointerRepresentation()) return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0))); // FIXME: We should be able to narrow this integer in cases with dead @@ -2238,7 +2242,8 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty) const { // FIXME: mingw-w64-gcc emits 128-bit struct as i128 if (Size == 128 && - getContext().getTargetInfo().getTriple().getOS() == llvm::Triple::MinGW32) + getContext().getTargetInfo().getTriple().getOS() + == llvm::Triple::MinGW32) return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), Size)); @@ -2373,7 +2378,8 @@ public: ARMABIInfo(CodeGenTypes &CGT, ABIKind _Kind) : ABIInfo(CGT), Kind(_Kind) {} bool isEABI() const { - StringRef Env = getContext().getTargetInfo().getTriple().getEnvironmentName(); + StringRef Env = + getContext().getTargetInfo().getTriple().getEnvironmentName(); return (Env == "gnueabi" || Env == "eabi" || Env == "androideabi"); } @@ -3591,7 +3597,8 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { if (Triple.isOSDarwin()) return *(TheTargetCodeGenInfo = - new X86_32TargetCodeGenInfo(Types, true, true, DisableMMX)); + new X86_32TargetCodeGenInfo( + Types, true, true, DisableMMX, false)); switch (Triple.getOS()) { case llvm::Triple::Cygwin: @@ -3601,11 +3608,18 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { case llvm::Triple::FreeBSD: case llvm::Triple::OpenBSD: return *(TheTargetCodeGenInfo = - new X86_32TargetCodeGenInfo(Types, false, true, DisableMMX)); + new X86_32TargetCodeGenInfo( + Types, false, true, DisableMMX, false)); + + case llvm::Triple::Win32: + return *(TheTargetCodeGenInfo = + new X86_32TargetCodeGenInfo( + Types, false, true, DisableMMX, true)); default: return *(TheTargetCodeGenInfo = - new X86_32TargetCodeGenInfo(Types, false, false, DisableMMX)); + new X86_32TargetCodeGenInfo( + Types, false, false, DisableMMX, false)); } } diff --git a/test/CodeGen/x86_32-arguments-win32.c b/test/CodeGen/x86_32-arguments-win32.c new file mode 100644 index 0000000000..f18bb30fa4 --- /dev/null +++ b/test/CodeGen/x86_32-arguments-win32.c @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -w -triple i386-pc-win32 -emit-llvm -o - %s | FileCheck %s + +// CHECK: define i64 @f1_1() +// CHECK: define void @f1_2(i32 %a0.0, i32 %a0.1) +struct s1 { + int a; + int b; +}; +struct s1 f1_1(void) { while (1) {} } +void f1_2(struct s1 a0) {} + +// CHECK: define i32 @f2_1() +struct s2 { + short a; + short b; +}; +struct s2 f2_1(void) { while (1) {} } + +// CHECK: define i16 @f3_1() +struct s3 { + char a; + char b; +}; +struct s3 f3_1(void) { while (1) {} } + +// CHECK: define i8 @f4_1() +struct s4 { + char a:4; + char b:4; +}; +struct s4 f4_1(void) { while (1) {} } + +// CHECK: define i64 @f5_1() +// CHECK: define void @f5_2(double %a0.0) +struct s5 { + double a; +}; +struct s5 f5_1(void) { while (1) {} } +void f5_2(struct s5 a0) {} + +// CHECK: define i32 @f6_1() +// CHECK: define void @f6_2(float %a0.0) +struct s6 { + float a; +}; +struct s6 f6_1(void) { while (1) {} } +void f6_2(struct s6 a0) {} +