diff options
author | Daniel Dunbar <daniel@zuster.org> | 2010-09-16 20:42:06 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2010-09-16 20:42:06 +0000 |
commit | e59d8585bb40a8bae6b847ad258536a2c01f20ea (patch) | |
tree | 6b0e92b4821daf71e640e55780a2c755f1d6d23f | |
parent | cf3b6f2504596812db1fcef0df8ce5b3449c4aac (diff) |
IRgen/ABI/x86-32: Realign indirect arguments when the ABI requires us to pass
them with a smaller alignment than the rest of codegen expects.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@114115 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/TargetInfo.cpp | 39 | ||||
-rw-r--r-- | test/CodeGen/x86_32-arguments-darwin.c | 20 | ||||
-rw-r--r-- | test/CodeGen/x86_32-arguments-linux.c | 24 | ||||
-rw-r--r-- | test/CodeGen/x86_32-arguments-realign.c | 11 |
4 files changed, 57 insertions, 37 deletions
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index 3ee4d1ad6d..34a6d37726 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -353,7 +353,7 @@ class X86_32ABIInfo : public ABIInfo { ABIArgInfo getIndirectResult(QualType Ty, bool ByVal = true) const; /// \brief Return the alignment to use for the given type on the stack. - unsigned getTypeStackAlignInBytes(QualType Ty) const; + unsigned getTypeStackAlignInBytes(QualType Ty, unsigned Align) const; public: @@ -580,16 +580,18 @@ static bool isRecordWithSSEVectorType(ASTContext &Context, QualType Ty) { return false; } -unsigned X86_32ABIInfo::getTypeStackAlignInBytes(QualType Ty) const { - // On non-Darwin, the stack type alignment is always 4. - if (!IsDarwinVectorABI) - return MinABIStackAlignInBytes; - - // Otherwise, if the alignment is less than or equal to 4, use the minimum ABI - // alignment. - unsigned Align = getContext().getTypeAlign(Ty) / 8; +unsigned X86_32ABIInfo::getTypeStackAlignInBytes(QualType Ty, + unsigned Align) const { + // Otherwise, if the alignment is less than or equal to the minimum ABI + // alignment, just use the default; the backend will handle this. if (Align <= MinABIStackAlignInBytes) + return 0; // Use default alignment. + + // On non-Darwin, the stack type alignment is always 4. + if (!IsDarwinVectorABI) { + // Set explicit alignment, since we may need to realign the top. return MinABIStackAlignInBytes; + } // Otherwise, if the type contains an SSE vector type, the alignment is 16. if (isRecordWithSSEVectorType(getContext(), Ty)) @@ -602,12 +604,19 @@ ABIArgInfo X86_32ABIInfo::getIndirectResult(QualType Ty, bool ByVal) const { 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. - unsigned Align = getTypeStackAlignInBytes(Ty); - if (Align > MinABIStackAlignInBytes) - return ABIArgInfo::getIndirect(Align); - return ABIArgInfo::getIndirect(0); + // Compute the byval alignment. + unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8; + unsigned StackAlign = getTypeStackAlignInBytes(Ty, TypeAlign); + if (StackAlign == 0) + return ABIArgInfo::getIndirect(0); + + // If the stack alignment is less than the type alignment, realign the + // argument. + if (StackAlign < TypeAlign) + return ABIArgInfo::getIndirect(StackAlign, /*ByVal=*/true, + /*Realign=*/true); + + return ABIArgInfo::getIndirect(StackAlign); } ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty) const { diff --git a/test/CodeGen/x86_32-arguments-darwin.c b/test/CodeGen/x86_32-arguments-darwin.c index 531ae1df69..3566834bdc 100644 --- a/test/CodeGen/x86_32-arguments-darwin.c +++ b/test/CodeGen/x86_32-arguments-darwin.c @@ -202,13 +202,13 @@ void f50(struct s50 a0) { } struct s51 { vvbp f0; int f1; }; void f51(struct s51 a0) { } -// CHECK: define void @f52(%struct.s52* byval %x) +// CHECK: define void @f52(%struct.s52* byval align 4) struct s52 { long double a; }; void f52(struct s52 x) {} -// CHECK: define void @f53(%struct.s53* byval %x) +// CHECK: define void @f53(%struct.s53* byval align 4) struct __attribute__((aligned(32))) s53 { int x; int y; @@ -230,21 +230,21 @@ v4i32 f55(v4i32 arg) { return arg+arg; } // CHECK: define void @f56( // CHECK: i8 signext %a0, %struct.s56_0* byval %a1, -// CHECK: <2 x i32> %a2, %struct.s56_1* byval %a3, -// CHECK: i64 %a4.coerce, %struct.s56_2* byval %a5, +// CHECK: <2 x i32> %a2, %struct.s56_1* byval align 4, +// CHECK: i64 %a4.coerce, %struct.s56_2* byval align 4, // CHECK: <4 x i32> %a6, %struct.s39* byval align 16 %a7, // CHECK: <2 x double> %a8, %struct.s56_4* byval align 16 %a9, -// CHECK: <8 x i32> %a10, %struct.s56_5* byval %a11, -// CHECK: <4 x double> %a12, %struct.s56_6* byval %a13) +// CHECK: <8 x i32> %a10, %struct.s56_5* byval align 4, +// CHECK: <4 x double> %a12, %struct.s56_6* byval align 4) // CHECK: call void (i32, ...)* @f56_0(i32 1, // CHECK: i32 %{{[^ ]*}}, %struct.s56_0* byval %{{[^ ]*}}, -// CHECK: <2 x i32> %{{[^ ]*}}, %struct.s56_1* byval %{{[^ ]*}}, -// CHECK: i64 %{{[^ ]*}}, %struct.s56_2* byval %{{[^ ]*}}, +// CHECK: <2 x i32> %{{[^ ]*}}, %struct.s56_1* byval align 4 %{{[^ ]*}}, +// CHECK: i64 %{{[^ ]*}}, %struct.s56_2* byval align 4 %{{[^ ]*}}, // CHECK: <4 x i32> %{{[^ ]*}}, %struct.s39* byval align 16 %{{[^ ]*}}, // CHECK: <2 x double> %{{[^ ]*}}, %struct.s56_4* byval align 16 %{{[^ ]*}}, -// CHECK: <8 x i32> {{[^ ]*}}, %struct.s56_5* byval %{{[^ ]*}}, -// CHECK: <4 x double> {{[^ ]*}}, %struct.s56_6* byval %{{[^ ]*}}) +// CHECK: <8 x i32> {{[^ ]*}}, %struct.s56_5* byval align 4 %{{[^ ]*}}, +// CHECK: <4 x double> {{[^ ]*}}, %struct.s56_6* byval align 4 %{{[^ ]*}}) // CHECK: } // // <rdar://problem/7964854> [i386] clang misaligns long double in structures diff --git a/test/CodeGen/x86_32-arguments-linux.c b/test/CodeGen/x86_32-arguments-linux.c index 31b184c37e..0e3a05cbf8 100644 --- a/test/CodeGen/x86_32-arguments-linux.c +++ b/test/CodeGen/x86_32-arguments-linux.c @@ -3,21 +3,21 @@ // CHECK: define void @f56( // CHECK: i8 signext %a0, %struct.s56_0* byval %a1, -// CHECK: <2 x i32> %a2, %struct.s56_1* byval %a3, -// CHECK: <1 x double> %a4, %struct.s56_2* byval %a5, -// CHECK: <4 x i32> %a6, %struct.s56_3* byval %a7, -// CHECK: <2 x double> %a8, %struct.s56_4* byval %a9, -// CHECK: <8 x i32> %a10, %struct.s56_5* byval %a11, -// CHECK: <4 x double> %a12, %struct.s56_6* byval %a13) +// CHECK: <2 x i32> %a2, %struct.s56_1* byval align 4, +// CHECK: <1 x double> %a4, %struct.s56_2* byval align 4, +// CHECK: <4 x i32> %a6, %struct.s56_3* byval align 4, +// CHECK: <2 x double> %a8, %struct.s56_4* byval align 4, +// CHECK: <8 x i32> %a10, %struct.s56_5* byval align 4, +// CHECK: <4 x double> %a12, %struct.s56_6* byval align 4) // CHECK: call void (i32, ...)* @f56_0(i32 1, // CHECK: i32 %{{.*}}, %struct.s56_0* byval %{{[^ ]*}}, -// CHECK: <2 x i32> %{{[^ ]*}}, %struct.s56_1* byval %{{[^ ]*}}, -// CHECK: <1 x double> %{{[^ ]*}}, %struct.s56_2* byval %{{[^ ]*}}, -// CHECK: <4 x i32> %{{[^ ]*}}, %struct.s56_3* byval %{{[^ ]*}}, -// CHECK: <2 x double> %{{[^ ]*}}, %struct.s56_4* byval %{{[^ ]*}}, -// CHECK: <8 x i32> %{{[^ ]*}}, %struct.s56_5* byval %{{[^ ]*}}, -// CHECK: <4 x double> %{{[^ ]*}}, %struct.s56_6* byval %{{[^ ]*}}) +// CHECK: <2 x i32> %{{[^ ]*}}, %struct.s56_1* byval align 4 %{{[^ ]*}}, +// CHECK: <1 x double> %{{[^ ]*}}, %struct.s56_2* byval align 4 %{{[^ ]*}}, +// CHECK: <4 x i32> %{{[^ ]*}}, %struct.s56_3* byval align 4 %{{[^ ]*}}, +// CHECK: <2 x double> %{{[^ ]*}}, %struct.s56_4* byval align 4 %{{[^ ]*}}, +// CHECK: <8 x i32> %{{[^ ]*}}, %struct.s56_5* byval align 4 %{{[^ ]*}}, +// CHECK: <4 x double> %{{[^ ]*}}, %struct.s56_6* byval align 4 %{{[^ ]*}}) // CHECK: } // // <rdar://problem/7964854> [i386] clang misaligns long double in structures diff --git a/test/CodeGen/x86_32-arguments-realign.c b/test/CodeGen/x86_32-arguments-realign.c new file mode 100644 index 0000000000..b08862ee43 --- /dev/null +++ b/test/CodeGen/x86_32-arguments-realign.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -w -fblocks -triple i386-apple-darwin9 -emit-llvm -o %t %s +// RUN: FileCheck < %t %s + +// CHECK: define void @f0(%struct.s0* byval align 4) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %{{.*}}, i8* %{{.*}}, i32 16, i32 4, i1 false) +// CHECK: } +struct s0 { long double a; }; +void f0(struct s0 a0) { + extern long double f0_g0; + f0_g0 = a0.a; +} |