Skip to content

Commit

Permalink
[CodeGen] Add an alignment attribute to all sret parameters
Browse files Browse the repository at this point in the history
This fixes a miscompile when the parameter is actually underaligned.
rdar://58316406

Differential revision: https://reviews.llvm.org/D74183
  • Loading branch information
epilk committed Mar 24, 2020
1 parent 43a6d28 commit de98cf9
Show file tree
Hide file tree
Showing 101 changed files with 570 additions and 559 deletions.
1 change: 1 addition & 0 deletions clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2084,6 +2084,7 @@ void CodeGenModule::ConstructAttributeList(
hasUsedSRet = true;
if (RetAI.getInReg())
SRETAttrs.addAttribute(llvm::Attribute::InReg);
SRETAttrs.addAlignmentAttr(RetAI.getIndirectAlign().getQuantity());
ArgAttrs[IRFunctionArgs.getSRetArgNo()] =
llvm::AttributeSet::get(getLLVMContext(), SRETAttrs);
}
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGen/2006-05-19-SingleEltReturn.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ struct Y bar() {


// X86_32: define void @foo(%struct.Y* %P)
// X86_32: call void @bar(%struct.Y* sret %{{[^),]*}})
// X86_32: call void @bar(%struct.Y* sret align 4 %{{[^),]*}})

// X86_32: define void @bar(%struct.Y* noalias sret %{{[^,)]*}})
// X86_32: define void @bar(%struct.Y* noalias sret align 4 %{{[^,)]*}})
// X86_32: ret void
4 changes: 2 additions & 2 deletions clang/test/CodeGen/aarch64-varargs.c
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ typedef struct __attribute__((aligned(32))) {
__int128 val;
} overaligned_int128_struct;
overaligned_int128_struct overaligned_int128_struct_test() {
// CHECK-LABEL: define void @overaligned_int128_struct_test(%struct.overaligned_int128_struct* noalias sret %agg.result)
// CHECK-LABEL: define void @overaligned_int128_struct_test(%struct.overaligned_int128_struct* noalias sret align 32 %agg.result)
return va_arg(the_list, overaligned_int128_struct);
// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, i32* getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 3)
// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0
Expand Down Expand Up @@ -853,7 +853,7 @@ typedef struct {
__int128 val __attribute__((aligned(32)));
} overaligned_int128_struct_member;
overaligned_int128_struct_member overaligned_int128_struct_member_test() {
// CHECK-LABEL: define void @overaligned_int128_struct_member_test(%struct.overaligned_int128_struct_member* noalias sret %agg.result)
// CHECK-LABEL: define void @overaligned_int128_struct_member_test(%struct.overaligned_int128_struct_member* noalias sret align 32 %agg.result)
return va_arg(the_list, overaligned_int128_struct_member);
// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, i32* getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 3)
// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0
Expand Down
8 changes: 4 additions & 4 deletions clang/test/CodeGen/aggregate-assign-call.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,17 @@ struct S baz(int i, volatile int *j) {
// O1-NEWPM: %[[TMP3:.*]] = bitcast %struct.S* %[[TMP2_ALLOCA]] to i8*
// O1-NEWPM: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* nonnull %[[P]])
//
// O1-LEGACY: call void @foo_int(%struct.S* sret %[[TMP1_ALLOCA]],
// O1-NEWPM: call void @foo_int(%struct.S* nonnull sret %[[TMP1_ALLOCA]],
// O1-LEGACY: call void @foo_int(%struct.S* sret align 4 %[[TMP1_ALLOCA]],
// O1-NEWPM: call void @foo_int(%struct.S* nonnull sret align 4 %[[TMP1_ALLOCA]],
// O1: call void @llvm.memcpy
// O1-LEGACY: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP1_ALLOCA]] to i8*
// O1-LEGACY: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* %[[P]])
// O1-NEWPM: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* nonnull %[[P]])
// O1-LEGACY: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP2_ALLOCA]] to i8*
// O1-LEGACY: call void @llvm.lifetime.start.p0i8({{[^,]*}}, i8* %[[P]])
// O1-NEWPM: call void @llvm.lifetime.start.p0i8({{[^,]*}}, i8* nonnull %[[TMP3]])
// O1-LEGACY: call void @foo_int(%struct.S* sret %[[TMP2_ALLOCA]],
// O1-NEWPM: call void @foo_int(%struct.S* nonnull sret %[[TMP2_ALLOCA]],
// O1-LEGACY: call void @foo_int(%struct.S* sret align 4 %[[TMP2_ALLOCA]],
// O1-NEWPM: call void @foo_int(%struct.S* nonnull sret align 4 %[[TMP2_ALLOCA]],
// O1: call void @llvm.memcpy
// O1-LEGACY: %[[P:[^ ]+]] = bitcast %struct.S* %[[TMP2_ALLOCA]] to i8*
// O1-LEGACY: call void @llvm.lifetime.end.p0i8({{[^,]*}}, i8* %[[P]])
Expand Down
10 changes: 10 additions & 0 deletions clang/test/CodeGen/aligned-sret.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos %s -S -emit-llvm -o- | FileCheck %s

typedef __attribute__((__ext_vector_type__(4),__aligned__(16))) double simd_double4;
typedef struct { simd_double4 columns[4]; } simd_double4x4;
typedef simd_double4x4 matrix_double4x4;

// CHECK: define void @ident(%struct.simd_double4x4* noalias sret align 16 %agg.result
matrix_double4x4 ident(matrix_double4x4 x) {
return x;
}
8 changes: 4 additions & 4 deletions clang/test/CodeGen/arc/arguments.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ void cf1(cs1 i) {}
typedef struct {
int cc;
} s2;
// CHECK: define void @f2(%struct.s2* noalias sret %agg.result)
// CHECK: define void @f2(%struct.s2* noalias sret align 4 %agg.result)
s2 f2() {
s2 foo;
return foo;
Expand All @@ -32,7 +32,7 @@ typedef struct {
int cc;
int dd;
} s3;
// CHECK: define void @f3(%struct.s3* noalias sret %agg.result)
// CHECK: define void @f3(%struct.s3* noalias sret align 4 %agg.result)
s3 f3() {
s3 foo;
return foo;
Expand Down Expand Up @@ -128,8 +128,8 @@ void st3(s16 a, s16 b, s16 c) {}

// 1 sret + 1 i32 + 2*(i32 coerce) + 4*(i32 coerce) + 1 byval
s16 st4(int x, s8 a, s16 b, s16 c) { return b; }
// CHECK: define void @st4(%struct.s16* noalias sret %agg.result, i32 inreg %x, i32 inreg %a.coerce0, i32 inreg %a.coerce1, i32 inreg %b.coerce0, i32 inreg %b.coerce1, i32 inreg %b.coerce2, i32 inreg %b.coerce3, { i32, i32, i32, i32 } %c.coerce)
// CHECK: define void @st4(%struct.s16* noalias sret align 4 %agg.result, i32 inreg %x, i32 inreg %a.coerce0, i32 inreg %a.coerce1, i32 inreg %b.coerce0, i32 inreg %b.coerce1, i32 inreg %b.coerce2, i32 inreg %b.coerce3, { i32, i32, i32, i32 } %c.coerce)

// 1 sret + 2*(i32 coerce) + 4*(i32 coerce) + 4*(i32 coerce)
s16 st5(s8 a, s16 b, s16 c) { return b; }
// CHECK: define void @st5(%struct.s16* noalias sret %agg.result, i32 inreg %a.coerce0, i32 inreg %a.coerce1, i32 inreg %b.coerce0, i32 inreg %b.coerce1, i32 inreg %b.coerce2, i32 inreg %b.coerce3, { i32, i32, i32, i32 } %c.coerce)
// CHECK: define void @st5(%struct.s16* noalias sret align 4 %agg.result, i32 inreg %a.coerce0, i32 inreg %a.coerce1, i32 inreg %b.coerce0, i32 inreg %b.coerce1, i32 inreg %b.coerce2, i32 inreg %b.coerce3, { i32, i32, i32, i32 } %c.coerce)
2 changes: 1 addition & 1 deletion clang/test/CodeGen/arm-aapcs-vfp.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ void test_vfp_stack_gpr_split_1(double a, double b, double c, double d, double e
// CHECK: define arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_2(double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, i32 %j, [2 x i64] %k.coerce)
void test_vfp_stack_gpr_split_2(double a, double b, double c, double d, double e, double f, double g, double h, double i, int j, struct_long_long_int k) {}

// CHECK: define arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_3(%struct.struct_long_long_int* noalias sret %agg.result, double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, [2 x i64] %k.coerce)
// CHECK: define arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_3(%struct.struct_long_long_int* noalias sret align 8 %agg.result, double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, [2 x i64] %k.coerce)
struct_long_long_int test_vfp_stack_gpr_split_3(double a, double b, double c, double d, double e, double f, double g, double h, double i, struct_long_long_int k) {}

typedef struct { int a; int b:4; int c; } struct_int_bitfield_int;
Expand Down
8 changes: 4 additions & 4 deletions clang/test/CodeGen/arm-homogenous.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ void test_union_with_first_floats(void) {
void test_return_union_with_first_floats(void) {
g_u_f = returns_union_with_first_floats();
}
// CHECK: declare arm_aapcs_vfpcc void @returns_union_with_first_floats(%union.union_with_first_floats* sret)
// CHECK: declare arm_aapcs_vfpcc void @returns_union_with_first_floats(%union.union_with_first_floats* sret align 4)

/* This is not a homogenous aggregate - fundamental types are different */
typedef union {
Expand All @@ -47,7 +47,7 @@ void test_union_with_non_first_floats(void) {
void test_return_union_with_non_first_floats(void) {
g_u_nf_f = returns_union_with_non_first_floats();
}
// CHECK: declare arm_aapcs_vfpcc void @returns_union_with_non_first_floats(%union.union_with_non_first_floats* sret)
// CHECK: declare arm_aapcs_vfpcc void @returns_union_with_non_first_floats(%union.union_with_non_first_floats* sret align 4)

/* This is not a homogenous aggregate - fundamental types are different */
typedef struct {
Expand All @@ -67,7 +67,7 @@ void test_struct_with_union_with_first_floats(void) {
void test_return_struct_with_union_with_first_floats(void) {
g_s_f = returns_struct_with_union_with_first_floats();
}
// CHECK: declare arm_aapcs_vfpcc void @returns_struct_with_union_with_first_floats(%struct.struct_with_union_with_first_floats* sret)
// CHECK: declare arm_aapcs_vfpcc void @returns_struct_with_union_with_first_floats(%struct.struct_with_union_with_first_floats* sret align 4)

/* This is not a homogenous aggregate - fundamental types are different */
typedef struct {
Expand All @@ -87,7 +87,7 @@ void test_struct_with_union_with_non_first_floats(void) {
void test_return_struct_with_union_with_non_first_floats(void) {
g_s_nf_f = returns_struct_with_union_with_non_first_floats();
}
// CHECK: declare arm_aapcs_vfpcc void @returns_struct_with_union_with_non_first_floats(%struct.struct_with_union_with_non_first_floats* sret)
// CHECK: declare arm_aapcs_vfpcc void @returns_struct_with_union_with_non_first_floats(%struct.struct_with_union_with_non_first_floats* sret align 4)

/* Plain array is not a homogenous aggregate */
extern void takes_array_of_floats(float a[4]);
Expand Down
Loading

0 comments on commit de98cf9

Please sign in to comment.