From a1e6de9171d10c3a3dde7fc2e8cf72cc98bf6362 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Sat, 13 Jun 2009 21:37:10 +0000 Subject: [PATCH] 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 --- lib/CodeGen/TargetABIInfo.cpp | 38 +++++++++++++++++++++++++++++---- test/CodeGen/x86_32-arguments.c | 5 +++++ 2 files changed, 39 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()); diff --git a/test/CodeGen/x86_32-arguments.c b/test/CodeGen/x86_32-arguments.c index 8980c66b20..43a3ab246c 100644 --- a/test/CodeGen/x86_32-arguments.c +++ b/test/CodeGen/x86_32-arguments.c @@ -154,4 +154,9 @@ struct s37 { float c[1][1]; } f37(void) {} // RUN: grep 'define void @f38(.struct.s38. noalias sret .agg.result)' %t && struct s38 { char a[3]; short b; } f38(void) {} +// RUN: grep 'define void @f39(.struct.s39. byval align 16 .x)' %t && +typedef int v39 __attribute((vector_size(16))); +struct s39 { v39 x; }; +void f39(struct s39 x) {} + // RUN: true -- 2.50.1