wxiao3 created this revision. wxiao3 added reviewers: annita.zhang, LuoYuanke, smaslov, hjl.tools, RKSimon, rnk, andreadb. wxiao3 added a project: clang. Herald added a subscriber: cfe-commits.
According to i386 System V ABI 2.1: Structures and unions assume the alignment of their most strictly aligned component. But current implementation always takes them as 4-byte aligned which will result in incorrect code, e.g: 1 #include <immintrin.h> 2 typedef union { 3 int d[4]; 4 __m128 m; 5 } M128; 6 extern void foo(int, ...); 7 void test(void) 8 { 9 M128 a; 10 foo(1, a); 11 foo(1, a.m); 12 } The first call (line 10) takes the second arg as 4-byte aligned while the second call (line 11) takes the second arg as 16-byte aligned. There is oxymoron for the alignment of the 2 calls because they should be the same. This patch fixes the bug by following i386 System V ABI. Repository: rC Clang https://reviews.llvm.org/D60748 Files: lib/CodeGen/TargetInfo.cpp test/CodeGen/x86_32-align-linux.c test/CodeGen/x86_32-arguments-linux.c
Index: test/CodeGen/x86_32-arguments-linux.c =================================================================== --- test/CodeGen/x86_32-arguments-linux.c +++ test/CodeGen/x86_32-arguments-linux.c @@ -3,21 +3,21 @@ // CHECK-LABEL: define void @f56( // CHECK: i8 signext %a0, %struct.s56_0* byval align 4 %a1, -// CHECK: i64 %a2.coerce, %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: i64 %a2.coerce, %struct.s56_1* byval align 8 %a3, +// CHECK: <1 x double> %a4, %struct.s56_2* byval align 8 %a5, +// CHECK: <4 x i32> %a6, %struct.s56_3* 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 align 32 %a11, +// CHECK: <4 x double> %a12, %struct.s56_6* byval align 32 %a13) // CHECK: call void (i32, ...) @f56_0(i32 1, // CHECK: i32 %{{.*}}, %struct.s56_0* byval align 4 %{{[^ ]*}}, -// CHECK: i64 %{{[^ ]*}}, %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: i64 %{{[^ ]*}}, %struct.s56_1* byval align 8 %{{[^ ]*}}, +// CHECK: <1 x double> %{{[^ ]*}}, %struct.s56_2* byval align 8 %{{[^ ]*}}, +// CHECK: <4 x i32> %{{[^ ]*}}, %struct.s56_3* byval align 16 %{{[^ ]*}}, +// CHECK: <2 x double> %{{[^ ]*}}, %struct.s56_4* byval align 16 %{{[^ ]*}}, +// CHECK: <8 x i32> %{{[^ ]*}}, %struct.s56_5* byval align 32 %{{[^ ]*}}, +// CHECK: <4 x double> %{{[^ ]*}}, %struct.s56_6* byval align 32 %{{[^ ]*}}) // CHECK: } // // <rdar://problem/7964854> [i386] clang misaligns long double in structures Index: test/CodeGen/x86_32-align-linux.c =================================================================== --- /dev/null +++ test/CodeGen/x86_32-align-linux.c @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -w -fblocks -ffreestanding -triple i386-pc-linux-gnu -emit-llvm -o %t %s +// RUN: FileCheck < %t %s + +#include <immintrin.h> + +typedef union { + int d[4]; + __m128 m; +} M128; + +extern void foo(int, ...); + +M128 a; + +// CHECK-LABEL: define void @test +// CHECK: entry: +// CHECK: call void (i32, ...) @foo(i32 1, %union.M128* byval align 16 +// CHECK: call void (i32, ...) @foo(i32 1, <4 x float> + +void test(void) +{ + foo(1, a); + foo(1, a.m); +} + Index: lib/CodeGen/TargetInfo.cpp =================================================================== --- lib/CodeGen/TargetInfo.cpp +++ lib/CodeGen/TargetInfo.cpp @@ -1492,18 +1492,18 @@ 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. + if (IsDarwinVectorABI) { + // On Darwin, if the type contains an SSE vector type, the alignment is 16. + if (Align >= 16 && (isSSEVectorType(getContext(), Ty) || + isRecordWithSSEVectorType(getContext(), Ty))) + return 16; + return MinABIStackAlignInBytes; + } else if (IsWin32StructABI) { return MinABIStackAlignInBytes; } - - // Otherwise, if the type contains an SSE vector type, the alignment is 16. - if (Align >= 16 && (isSSEVectorType(getContext(), Ty) || - isRecordWithSSEVectorType(getContext(), Ty))) - return 16; - - return MinABIStackAlignInBytes; + // i386 System V ABI 2.1: Structures and unions assume the alignment of their + // most strictly aligned component. + return Align; } ABIArgInfo X86_32ABIInfo::getIndirectResult(QualType Ty, bool ByVal,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits