aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2010-04-21 19:49:55 +0000
committerDaniel Dunbar <daniel@zuster.org>2010-04-21 19:49:55 +0000
commit46c54fb8ec45765a475b7b709b9aee7f94c490c2 (patch)
tree374ee3816b50b89101bf32c3cf85a33c3df81e56
parentd0ef54cb306ef3090ffd551733c491e1cae2a28d (diff)
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
-rw-r--r--lib/CodeGen/TargetInfo.cpp59
-rw-r--r--test/CodeGen/x86_32-arguments.c12
-rw-r--r--test/CodeGen/x86_64-arguments.c16
3 files changed, 67 insertions, 20 deletions
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<RecordType>())
- 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,
@@ -697,6 +692,10 @@ class X86_64ABIInfo : public ABIInfo {
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<EnumType>())
+ 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) {}