diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2009-06-13 21:37:10 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2009-06-13 21:37:10 +0000 |
commit | a1e6de9171d10c3a3dde7fc2e8cf72cc98bf6362 (patch) | |
tree | 16888dd6e3c4b1192d887a42b961af0ec2c93d0e /lib/CodeGen/TargetABIInfo.cpp | |
parent | 9509108b3dde280dca1999b5c054f5b789581e68 (diff) |
Fix the calling convention for structs/unions containing SSE vectors on
x86-32. This is slightly messy, but I think it's consistent with gcc.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73306 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/TargetABIInfo.cpp')
-rw-r--r-- | lib/CodeGen/TargetABIInfo.cpp | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/lib/CodeGen/TargetABIInfo.cpp b/lib/CodeGen/TargetABIInfo.cpp index 6f7bea2340..361e5c0005 100644 --- a/lib/CodeGen/TargetABIInfo.cpp +++ b/lib/CodeGen/TargetABIInfo.cpp @@ -159,6 +159,23 @@ static bool areAllFields32Or64BitBasicType(const RecordDecl *RD, return true; } +static bool typeContainsSSEVector(const RecordDecl *RD, ASTContext &Context) { + for (RecordDecl::field_iterator i = RD->field_begin(Context), + e = RD->field_end(Context); i != e; ++i) { + const FieldDecl *FD = *i; + + if (FD->getType()->isVectorType() && + Context.getTypeSize(FD->getType()) >= 128) + return true; + + if (const RecordType* RT = FD->getType()->getAsRecordType()) + if (typeContainsSSEVector(RT->getDecl(), Context)) + return true; + } + + return false; +} + namespace { /// DefaultABIInfo - The default implementation for ABI specific /// details. This implementation provides information which results in @@ -193,6 +210,9 @@ class X86_32ABIInfo : public ABIInfo { static bool shouldReturnTypeInRegister(QualType Ty, ASTContext &Context); + static unsigned getIndirectArgumentAlignment(QualType Ty, + ASTContext &Context); + public: ABIArgInfo classifyReturnType(QualType RetTy, ASTContext &Context) const; @@ -350,6 +370,16 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, } } +unsigned X86_32ABIInfo::getIndirectArgumentAlignment(QualType Ty, + ASTContext &Context) { + unsigned Align = Context.getTypeAlign(Ty); + if (Align < 128) return 0; + if (const RecordType* RT = Ty->getAsRecordType()) + if (typeContainsSSEVector(RT->getDecl(), Context)) + return 16; + return 0; +} + ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, ASTContext &Context) const { // FIXME: Set alignment on indirect arguments. @@ -357,11 +387,11 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, // Structures with flexible arrays are always indirect. if (const RecordType *RT = Ty->getAsStructureType()) if (RT->getDecl()->hasFlexibleArrayMember()) - return ABIArgInfo::getIndirect(0); + return ABIArgInfo::getIndirect(getIndirectArgumentAlignment(Ty, + Context)); // Ignore empty structs. - uint64_t Size = Context.getTypeSize(Ty); - if (Ty->isStructureType() && Size == 0) + if (Ty->isStructureType() && Context.getTypeSize(Ty) == 0) return ABIArgInfo::getIgnore(); // Expand structs with size <= 128-bits which consist only of @@ -373,7 +403,7 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, return ABIArgInfo::getExpand(); } - return ABIArgInfo::getIndirect(0); + return ABIArgInfo::getIndirect(getIndirectArgumentAlignment(Ty, Context)); } else { return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend() : ABIArgInfo::getDirect()); |