From: Daniel Dunbar Date: Wed, 21 Apr 2010 19:49:55 +0000 (+0000) Subject: ABI/x86-32 & x86-64: Alignment on 'byval' must be set when when the alignment X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=46c54fb8ec45765a475b7b709b9aee7f94c490c2;p=clang ABI/x86-32 & x86-64: Alignment on 'byval' must be set when when the alignment exceeds the minimum ABI alignment. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102019 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index c6cc31b7b0..e1fdf86eb0 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -292,9 +292,6 @@ class X86_32ABIInfo : public ABIInfo { static bool shouldReturnTypeInRegister(QualType Ty, ASTContext &Context); - static unsigned getIndirectArgumentAlignment(QualType Ty, - ASTContext &Context); - /// getIndirectResult - Give a source type \arg Ty, return a suitable result /// such that the argument will be passed in memory. ABIArgInfo getIndirectResult(QualType Ty, ASTContext &Context, @@ -496,21 +493,19 @@ 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->getAs()) - if (typeContainsSSEVector(RT->getDecl(), Context)) - return 16; - return 0; -} - ABIArgInfo X86_32ABIInfo::getIndirectResult(QualType Ty, ASTContext &Context, bool ByVal) const { - return ABIArgInfo::getIndirect(getIndirectArgumentAlignment(Ty, Context), - ByVal); + if (!ByVal) + return ABIArgInfo::getIndirect(0, false); + + // Compute the byval alignment. We trust the back-end to honor the + // minimum ABI alignment for byval, to make cleaner IR. + const unsigned MinABIAlign = 4; + unsigned Align = Context.getTypeAlign(Ty) / 8; + if (Align > MinABIAlign) + return ABIArgInfo::getIndirect(Align); + return ABIArgInfo::getIndirect(0); } ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, @@ -696,6 +691,10 @@ class X86_64ABIInfo : public ABIInfo { const llvm::Type *CoerceTo, ASTContext &Context) const; + /// getIndirectResult - Give a source type \arg Ty, return a suitable result + /// such that the argument will be returned in memory. + ABIArgInfo getIndirectReturnResult(QualType Ty, ASTContext &Context) const; + /// getIndirectResult - Give a source type \arg Ty, return a suitable result /// such that the argument will be passed in memory. ABIArgInfo getIndirectResult(QualType Ty, ASTContext &Context) const; @@ -1071,6 +1070,22 @@ ABIArgInfo X86_64ABIInfo::getCoerceResult(QualType Ty, return ABIArgInfo::getCoerce(CoerceTo); } +ABIArgInfo X86_64ABIInfo::getIndirectReturnResult(QualType Ty, + ASTContext &Context) const { + // If this is a scalar LLVM value then assume LLVM will pass it in the right + // place naturally. + if (!CodeGenFunction::hasAggregateLLVMType(Ty)) { + // Treat an enum type as its underlying type. + if (const EnumType *EnumTy = Ty->getAs()) + Ty = EnumTy->getDecl()->getIntegerType(); + + return (Ty->isPromotableIntegerType() ? + ABIArgInfo::getExtend() : ABIArgInfo::getDirect()); + } + + return ABIArgInfo::getIndirect(0); +} + ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty, ASTContext &Context) const { // If this is a scalar LLVM value then assume LLVM will pass it in the right @@ -1084,10 +1099,16 @@ ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty, ABIArgInfo::getExtend() : ABIArgInfo::getDirect()); } - bool ByVal = !isRecordWithNonTrivialDestructorOrCopyConstructor(Ty); + if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty)) + return ABIArgInfo::getIndirect(0, /*ByVal=*/false); - // FIXME: Set alignment correctly. - return ABIArgInfo::getIndirect(0, ByVal); + // Compute the byval alignment. We trust the back-end to honor the + // minimum ABI alignment for byval, to make cleaner IR. + const unsigned MinABIAlign = 8; + unsigned Align = Context.getTypeAlign(Ty) / 8; + if (Align > MinABIAlign) + return ABIArgInfo::getIndirect(Align); + return ABIArgInfo::getIndirect(0); } ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy, @@ -1115,7 +1136,7 @@ ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy, // AMD64-ABI 3.2.3p4: Rule 2. Types of class memory are returned via // hidden argument. case Memory: - return getIndirectResult(RetTy, Context); + return getIndirectReturnResult(RetTy, Context); // AMD64-ABI 3.2.3p4: Rule 3. If the class is INTEGER, the next // available register of the sequence %rax, %rdx is used. diff --git a/test/CodeGen/x86_32-arguments.c b/test/CodeGen/x86_32-arguments.c index 42eeb434c3..01c3e236f3 100644 --- a/test/CodeGen/x86_32-arguments.c +++ b/test/CodeGen/x86_32-arguments.c @@ -202,3 +202,15 @@ void f50(struct s50 a0) { } struct s51 { vvbp f0; int f1; }; void f51(struct s51 a0) { } +// CHECK: define void @f52(%struct.s52* byval align 16 %x) +struct s52 { + long double a; +}; +void f52(struct s52 x) {} + +// CHECK: define void @f53(%struct.s53* byval align 32 %x) +struct __attribute__((aligned(32))) s53 { + int x; + int y; +}; +void f53(struct s53 x) {} diff --git a/test/CodeGen/x86_64-arguments.c b/test/CodeGen/x86_64-arguments.c index dd332bed99..47b2eb1585 100644 --- a/test/CodeGen/x86_64-arguments.c +++ b/test/CodeGen/x86_64-arguments.c @@ -60,7 +60,7 @@ struct s9 { int a; int b; int : 0; } f9(void) { while (1) {} } struct s10 { int a; int b; int : 0; }; void f10(struct s10 a0) {} -// CHECK: define void @f11(%union.anon* sret %agg.result) +// CHECK: define void @f11(%struct.s19* sret %agg.result) union { long double a; float b; } f11() { while (1) {} } // CHECK: define i64 @f12_0() @@ -99,3 +99,17 @@ void f17(float a, float b, float c, float d, float e, float f, float g, float h, struct f18_s0 { int f0; }; void f18(int a, struct f18_s0 f18_arg1) { while (1) {} } +// Check byval alignment. + +// CHECK: define void @f19(%struct.s19* byval align 16 %x) +struct s19 { + long double a; +}; +void f19(struct s19 x) {} + +// CHECK: define void @f20(%struct.s20* byval align 32 %x) +struct __attribute__((aligned(32))) s20 { + int x; + int y; +}; +void f20(struct s20 x) {}