20 changes: 10 additions & 10 deletions clang/test/CodeGenCXX/builtin-source-location.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ SL const_init_global = SL::current();
//
// CHECK-GLOBAL-TWO: define internal void @__cxx_global_var_init()
// CHECK-GLOBAL-TWO-NOT: ret
// CHECK-GLOBAL-TWO: call void @_ZN15source_location11bad_currentEjjPKcS1_(%struct.source_location* sret align 8 @runtime_init_global,
// CHECK-GLOBAL-TWO: call void @_ZN15source_location11bad_currentEjjPKcS1_(%struct.source_location* sret(%struct.source_location) align 8 @runtime_init_global,
// CHECK-GLOBAL-TWO-SAME: i32 1100, i32 {{[0-9]+}}, {{[^@]*}}@[[FILE]], {{[^@]*}}@[[FUNC]],
#line 1100 "test_runtime_init.cpp"
SL runtime_init_global = SL::bad_current();
Expand All @@ -77,7 +77,7 @@ extern "C" void test_function() {
// CHECK-LOCAL-ONE-DAG: @[[FILE:.*]] = {{.*}}c"test_current.cpp\00"
// CHECK-LOCAL-ONE-DAG: @[[FUNC:.*]] = {{.*}}c"test_function\00"
//
// CHECK-LOCAL-ONE: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret align 8 %local,
// CHECK-LOCAL-ONE: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret(%struct.source_location) align 8 %local,
// CHECK-LOCAL-ONE-SAME: i32 2100, i32 {{[0-9]+}},
// CHECK-LOCAL-ONE-SAME: {{[^@]*}}@[[FILE]], {{[^@]*}}@[[FUNC]],
#line 2100 "test_current.cpp"
Expand All @@ -102,7 +102,7 @@ struct TestInit {
// CHECK-CTOR-GLOBAL: define internal void @__cxx_global_var_init.{{[0-9]+}}()
// CHECK-CTOR-GLOBAL-NOT: ret
//
// CHECK-CTOR-GLOBAL: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret align 8 %[[TMP_ONE:[^,]*]],
// CHECK-CTOR-GLOBAL: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret(%struct.source_location) align 8 %[[TMP_ONE:[^,]*]],
// CHECK-CTOR-GLOBAL-SAME: i32 3400, i32 {{[0-9]+}}, {{[^@]*}}@[[FILE]], {{[^@]*}}@[[FUNC]],
// CHECK-CTOR-GLOBAL-NEXT: call void @_ZN8TestInitC1E15source_location(%struct.TestInit* @GlobalInitVal, %struct.source_location* {{.*}}%[[TMP_ONE]])
#line 3400 "GlobalInitVal.cpp"
Expand All @@ -117,7 +117,7 @@ extern "C" void test_init_function() {
// CHECK-CTOR-LOCAL: define void @test_init_function()
// CHECK-CTOR-LOCAL-NOT: ret
//
// CHECK-CTOR-LOCAL: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret align 8 %[[TMP:[^,]*]],
// CHECK-CTOR-LOCAL: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret(%struct.source_location) align 8 %[[TMP:[^,]*]],
// CHECK-CTOR-LOCAL-SAME: i32 3500, i32 {{[0-9]+}}, {{[^@]*}}@[[FILE]], {{[^@]*}}@[[FUNC]],
// CHECK-CTOR-LOCAL-NEXT: call void @_ZN8TestInitC1E15source_location(%struct.TestInit* %init_local, %struct.source_location* {{.*}}%[[TMP]])
#line 3500 "LocalInitVal.cpp"
Expand Down Expand Up @@ -153,7 +153,7 @@ extern "C" void test_init_function_constexpr() {
// CHECK-CONSTEXPR-LOCAL-DAG: @[[FILE:.*]] = {{.*}}c"ConstexprLocal.cpp\00"
//
// CHECK-CONSTEXPR-LOCAL: define void @test_init_function_constexpr()
// CHECK-CONSTEXPR-LOCAL: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret align 8 %[[TMP:[^,]*]],
// CHECK-CONSTEXPR-LOCAL: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret(%struct.source_location) align 8 %[[TMP:[^,]*]],
// CHECK-CONSTEXPR-LOCAL-SAME: i32 4600, i32 {{[0-9]+}}, {{[^@]*}}@[[FILE]], {{[^@]*}}@[[FUNC]]
// CHECK-CONSTEXPR-LOCAL: call void @_ZN17TestInitConstexprC1E15source_location(%struct.TestInitConstexpr* %local_val, {{.*}}%[[TMP]])
#line 4600 "ConstexprLocal.cpp"
Expand Down Expand Up @@ -189,7 +189,7 @@ extern "C" void test_agg_init() {
//
// CHECK-AGG-BRACE: define void @test_agg_init()
// CHECK-AGG-BRACE: %[[I2:.*]] = getelementptr inbounds %struct.TestInitAgg, %struct.TestInitAgg* %local_brace_init, i32 0, i32 1
// CHECK-AGG-BRACE-NEXT: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret align 8 %[[I2]],
// CHECK-AGG-BRACE-NEXT: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret(%struct.source_location) align 8 %[[I2]],
// CHECK-AGG-BRACE-SAME: i32 5700, i32 {{[0-9]+}}, {{[^@]*}}@[[FILE]], {{[^@]*}}@[[FUNC]]
#line 5600 "BraceInitStart.cpp"
TestInitAgg local_brace_init{
Expand All @@ -203,7 +203,7 @@ extern "C" void test_agg_init() {
//
// CHECK-AGG-EQUAL: define void @test_agg_init()
// CHECK-AGG-EQUAL: %[[I2:.*]] = getelementptr inbounds %struct.TestInitAgg, %struct.TestInitAgg* %local_equal_init, i32 0, i32 1
// CHECK-AGG-EQUAL-NEXT: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret align 8 %[[I2]],
// CHECK-AGG-EQUAL-NEXT: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret(%struct.source_location) align 8 %[[I2]],
// CHECK-AGG-EQUAL-SAME: i32 5900, i32 {{[0-9]+}}, {{[^@]*}}@[[FILE]], {{[^@]*}}@[[FUNC]]
#line 5800 "EqualInitStart.cpp"
TestInitAgg local_equal_init =
Expand All @@ -220,11 +220,11 @@ extern "C" void test_agg_init() {
// CHECK-AGG-LIST: define void @test_agg_init()
//
// CHECK-AGG-LIST: %[[I1:.*]] = getelementptr inbounds %struct.TestInitAgg, %struct.TestInitAgg* %local_list_init, i32 0, i32 0
// CHECK-AGG-LIST-NEXT: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret align 8 %[[I1]],
// CHECK-AGG-LIST-NEXT: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret(%struct.source_location) align 8 %[[I1]],
// CHECK-AGG-LIST-SAME: i32 6100, i32 {{[0-9]+}}, {{[^@]*}}@[[FILE_ELEM]], {{[^@]*}}@[[FUNC]]
//
// CHECK-AGG-LIST: %[[I2:.*]] = getelementptr inbounds %struct.TestInitAgg, %struct.TestInitAgg* %local_list_init, i32 0, i32 1
// CHECK-AGG-LIST-NEXT: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret align 8 %[[I2]],
// CHECK-AGG-LIST-NEXT: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret(%struct.source_location) align 8 %[[I2]],
// CHECK-AGG-LIST-SAME: i32 6200, i32 {{[0-9]+}}, {{[^@]*}}@[[FILE_DEFAULT]], {{[^@]*}}@[[FUNC]]
#line 6000 "InitListStart.cpp"
TestInitAgg local_list_init =
Expand Down Expand Up @@ -258,7 +258,7 @@ void test_template() {
// CHECK-TEMPL-NEXT: entry:
// CHECK-TEMPL-NOT: ret
//
// CHECK-TEMPL: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret align 8 %[[TMP:[^,]*]],
// CHECK-TEMPL: call void @_ZN15source_location7currentEjjPKcS1_(%struct.source_location* sret(%struct.source_location) align 8 %[[TMP:[^,]*]],
// CHECK-TEMPL-SAME: i32 7300, i32 {{[0-9]+}}, {{[^@]*}}@[[FILE]], {{[^@]*}}@[[FUNC]]
#line 7300 "local_templ.cpp"
TestTemplate<T, V> local_templ;
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGenCXX/call-with-static-chain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ void test() {
// CHECK64: call i32 bitcast (i32 (i64, i64, i64, i64, i64, i64, %struct.A*)* @f1 to i32 (i8*, i64, i64, i64, i64, i64, i64, %struct.A*)*)(i8* nest bitcast (i32 (i64, i64, i64, i64, i64, i64, %struct.A*)* @f1 to i8*)
__builtin_call_with_static_chain(f1(a, a, a, a), f1);

// CHECK32: call void bitcast (void (%struct.B*)* @f2 to void (%struct.B*, i8*)*)(%struct.B* sret align 4 %{{[0-9a-z]+}}, i8* nest bitcast (void (%struct.B*)* @f2 to i8*))
// CHECK64: call void bitcast (void (%struct.B*)* @f2 to void (%struct.B*, i8*)*)(%struct.B* sret align 8 %{{[0-9a-z]+}}, i8* nest bitcast (void (%struct.B*)* @f2 to i8*))
// CHECK32: call void bitcast (void (%struct.B*)* @f2 to void (%struct.B*, i8*)*)(%struct.B* sret(%struct.B) align 4 %{{[0-9a-z]+}}, i8* nest bitcast (void (%struct.B*)* @f2 to i8*))
// CHECK64: call void bitcast (void (%struct.B*)* @f2 to void (%struct.B*, i8*)*)(%struct.B* sret(%struct.B) align 8 %{{[0-9a-z]+}}, i8* nest bitcast (void (%struct.B*)* @f2 to i8*))
__builtin_call_with_static_chain(f2(), f2);

// CHECK32: call i64 bitcast (i64 ()* @f3 to i64 (i8*)*)(i8* nest bitcast (i64 ()* @f3 to i8*))
Expand Down
8 changes: 4 additions & 4 deletions clang/test/CodeGenCXX/conditional-gnu-ext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ namespace test3 {
B test1() {
// CHECK-LABEL: define void @_ZN5test35test1Ev(
// CHECK: [[TEMP:%.*]] = alloca [[B]],
// CHECK: call void @_ZN5test312test1_helperEv([[B]]* sret align 1 [[TEMP]])
// CHECK: call void @_ZN5test312test1_helperEv([[B]]* sret([[B]]) align 1 [[TEMP]])
// CHECK-NEXT: [[BOOL:%.*]] = call zeroext i1 @_ZN5test31BcvbEv([[B]]* [[TEMP]])
// CHECK-NEXT: br i1 [[BOOL]]
// CHECK: call void @_ZN5test31BC1ERKS0_([[B]]* [[RESULT:%.*]], [[B]]* nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) [[TEMP]])
Expand All @@ -115,7 +115,7 @@ namespace test3 {
// CHECK-NEXT: [[T0:%.*]] = load [[B]]*, [[B]]** [[X]]
// CHECK-NEXT: [[BOOL:%.*]] = call zeroext i1 @_ZN5test31BcvbEv([[B]]* [[T0]])
// CHECK-NEXT: br i1 [[BOOL]]
// CHECK: call void @_ZN5test31BcvNS_1AEEv([[A:%.*]]* sret align 1 [[RESULT:%.*]], [[B]]* [[T0]])
// CHECK: call void @_ZN5test31BcvNS_1AEEv([[A:%.*]]* sret([[A]]) align 1 [[RESULT:%.*]], [[B]]* [[T0]])
// CHECK-NEXT: br label
// CHECK: call void @_ZN5test31AC1Ev([[A]]* [[RESULT]])
// CHECK-NEXT: br label
Expand All @@ -126,10 +126,10 @@ namespace test3 {
A test3() {
// CHECK-LABEL: define void @_ZN5test35test3Ev(
// CHECK: [[TEMP:%.*]] = alloca [[B]],
// CHECK: call void @_ZN5test312test3_helperEv([[B]]* sret align 1 [[TEMP]])
// CHECK: call void @_ZN5test312test3_helperEv([[B]]* sret([[B]]) align 1 [[TEMP]])
// CHECK-NEXT: [[BOOL:%.*]] = call zeroext i1 @_ZN5test31BcvbEv([[B]]* [[TEMP]])
// CHECK-NEXT: br i1 [[BOOL]]
// CHECK: call void @_ZN5test31BcvNS_1AEEv([[A]]* sret align 1 [[RESULT:%.*]], [[B]]* [[TEMP]])
// CHECK: call void @_ZN5test31BcvNS_1AEEv([[A]]* sret([[A]]) align 1 [[RESULT:%.*]], [[B]]* [[TEMP]])
// CHECK-NEXT: br label
// CHECK: call void @_ZN5test31AC1Ev([[A]]* [[RESULT]])
// CHECK-NEXT: br label
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGenCXX/cxx1z-copy-omission.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ void g() {
// CHECK: %[[A:.*]] = alloca
// CHECK-NOT: alloca
// CHECK-NOT: call
// CHECK: call {{.*}} @_Z1fv({{.*}}* sret align 4 %[[A]])
// CHECK: call {{.*}} @_Z1fv({{.*}}* sret({{.*}}) align 4 %[[A]])
A a = A( A{ f() } );
// CHECK-NOT: call

Expand All @@ -40,7 +40,7 @@ void h() {
// CHECK-NOT: alloca
// CHECK-NOT: call

// CHECK: call {{.*}} @_Z1fv({{.*}}* sret align 4 %[[A]])
// CHECK: call {{.*}} @_Z1fv({{.*}}* sret({{.*}}) align 4 %[[A]])
// CHECK-NOT: call
// CHECK: call {{.*}} @_Z1f1A({{.*}}* %[[A]])
f(f());
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGenCXX/cxx1z-lambda-star-this.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace ns1 {
int X = A{}.foo()();
} //end ns1

//CHECK: @"?foo@A@@QAE?A?<auto>@@XZ"(%struct.A* %this, %class.anon* noalias sret align 8 %[[A_LAMBDA_RETVAL:.*]])
//CHECK: @"?foo@A@@QAE?A?<auto>@@XZ"(%struct.A* %this, %class.anon* noalias sret(%class.anon) align 8 %[[A_LAMBDA_RETVAL:.*]])
// get the first object with the closure type, which is of type 'struct.A'
//CHECK: %[[I0:.+]] = getelementptr inbounds %[[A_LAMBDA]], %[[A_LAMBDA]]* %[[A_LAMBDA_RETVAL]], i32 0, i32 0
//CHECK: %[[I1:.+]] = bitcast %struct.A* %[[I0]] to i8*
Expand All @@ -26,6 +26,6 @@ struct B {
namespace ns2 {
int X = B{}.bar()();
}
//CHECK: @"?bar@B@@QAE?A?<auto>@@XZ"(%struct.B* %this, %class.anon.0* noalias sret align 4 %agg.result)
//CHECK: @"?bar@B@@QAE?A?<auto>@@XZ"(%struct.B* %this, %class.anon.0* noalias sret(%class.anon.0) align 4 %agg.result)
//CHECK: %[[I20:.+]] = getelementptr inbounds %class.anon.0, %class.anon.0* %agg.result, i32 0, i32 0
//CHECK: store %struct.B* %this1, %struct.B** %[[I20]], align 4
6 changes: 3 additions & 3 deletions clang/test/CodeGenCXX/exceptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,12 @@ namespace test1 {
// CHECK: [[NEW:%.*]] = call noalias nonnull i8* @_Znwm(i64 8)
// CHECK-NEXT: store i1 true, i1* [[ACTIVE]]
// CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]*
// CHECK-NEXT: invoke void @_ZN5test15makeBEv([[B:%.*]]* sret align 4 [[T0:%.*]])
// CHECK-NEXT: invoke void @_ZN5test15makeBEv([[B:%.*]]* sret([[B]]) align 4 [[T0:%.*]])
// CHECK: [[T1:%.*]] = invoke i32 @_ZN5test11BcviEv([[B]]* [[T0]])
// CHECK: invoke void @_ZN5test11AC1Ei([[A]]* [[CAST]], i32 [[T1]])
// CHECK: store i1 false, i1* [[ACTIVE]]
// CHECK-NEXT: store [[A]]* [[CAST]], [[A]]** [[X]], align 8
// CHECK: invoke void @_ZN5test15makeBEv([[B:%.*]]* sret align 4 [[T2:%.*]])
// CHECK: invoke void @_ZN5test15makeBEv([[B:%.*]]* sret([[B]]) align 4 [[T2:%.*]])
// CHECK: [[RET:%.*]] = load [[A]]*, [[A]]** [[X]], align 8

// CHECK98: invoke void @_ZN5test11BD1Ev([[B]]* [[T2]])
Expand Down Expand Up @@ -239,7 +239,7 @@ namespace test3 {
// CHECK-NEXT: store i8* [[FOO]], i8** [[SAVED1]]
// CHECK-NEXT: store i1 true, i1* [[CLEANUPACTIVE]]
// CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]*
// CHECK-NEXT: invoke void @_ZN5test35makeAEv([[A]]* sret align 8 [[CAST]])
// CHECK-NEXT: invoke void @_ZN5test35makeAEv([[A]]* sret([[A]]) align 8 [[CAST]])
// CHECK: br label
// -> cond.end
new(foo(),10.0) A(makeA()) :
Expand Down
14 changes: 7 additions & 7 deletions clang/test/CodeGenCXX/homogeneous-aggregates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ struct I2 : Base2 {};
struct I3 : Base2 {};
struct D5 : I1, I2, I3 {}; // homogeneous aggregate

// PPC: define void @_Z7func_D12D1(%struct.D1* noalias sret align 8 %agg.result, [3 x i64] %x.coerce)
// ARM32: define arm_aapcs_vfpcc void @_Z7func_D12D1(%struct.D1* noalias sret align 8 %agg.result, [3 x i64] %x.coerce)
// ARM64: define void @_Z7func_D12D1(%struct.D1* noalias sret align 8 %agg.result, %struct.D1* %x)
// X64: define dso_local x86_vectorcallcc void @"\01_Z7func_D12D1@@24"(%struct.D1* noalias sret align 8 %agg.result, %struct.D1* %x)
// PPC: define void @_Z7func_D12D1(%struct.D1* noalias sret(%struct.D1) align 8 %agg.result, [3 x i64] %x.coerce)
// ARM32: define arm_aapcs_vfpcc void @_Z7func_D12D1(%struct.D1* noalias sret(%struct.D1) align 8 %agg.result, [3 x i64] %x.coerce)
// ARM64: define void @_Z7func_D12D1(%struct.D1* noalias sret(%struct.D1) align 8 %agg.result, %struct.D1* %x)
// X64: define dso_local x86_vectorcallcc void @"\01_Z7func_D12D1@@24"(%struct.D1* noalias sret(%struct.D1) align 8 %agg.result, %struct.D1* %x)
D1 CC func_D1(D1 x) { return x; }

// PPC: define [3 x double] @_Z7func_D22D2([3 x double] %x.coerce)
Expand All @@ -50,9 +50,9 @@ D1 CC func_D1(D1 x) { return x; }
// X64: define dso_local x86_vectorcallcc %struct.D2 @"\01_Z7func_D22D2@@24"(%struct.D2 inreg %x.coerce)
D2 CC func_D2(D2 x) { return x; }

// PPC: define void @_Z7func_D32D3(%struct.D3* noalias sret align 8 %agg.result, [4 x i64] %x.coerce)
// ARM32: define arm_aapcs_vfpcc void @_Z7func_D32D3(%struct.D3* noalias sret align 8 %agg.result, [4 x i64] %x.coerce)
// ARM64: define void @_Z7func_D32D3(%struct.D3* noalias sret align 8 %agg.result, %struct.D3* %x)
// PPC: define void @_Z7func_D32D3(%struct.D3* noalias sret(%struct.D3) align 8 %agg.result, [4 x i64] %x.coerce)
// ARM32: define arm_aapcs_vfpcc void @_Z7func_D32D3(%struct.D3* noalias sret(%struct.D3) align 8 %agg.result, [4 x i64] %x.coerce)
// ARM64: define void @_Z7func_D32D3(%struct.D3* noalias sret(%struct.D3) align 8 %agg.result, %struct.D3* %x)
D3 CC func_D3(D3 x) { return x; }

// PPC: define [4 x double] @_Z7func_D42D4([4 x double] %x.coerce)
Expand Down
6 changes: 3 additions & 3 deletions clang/test/CodeGenCXX/lambda-expressions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ namespace pr28595 {
// CHECK: br i1
//
// CHECK: ret void
//
//
// CHECK: landingpad
// CHECK: landingpad
// CHECK: br label %[[CLEANUP:.*]]{{$}}
Expand Down Expand Up @@ -194,8 +194,8 @@ namespace pr28595 {
// CHECK-NEXT: call i32 @"_ZZ1fvENK3$_6clEii"
// CHECK-NEXT: ret i32

// CHECK-LABEL: define internal void @"_ZZ1hvEN4$_118__invokeEv"(%struct.A* noalias sret align 1 %agg.result) {{.*}} {
// CHECK: call void @"_ZZ1hvENK4$_11clEv"(%struct.A* sret align 1 %agg.result,
// CHECK-LABEL: define internal void @"_ZZ1hvEN4$_118__invokeEv"(%struct.A* noalias sret(%struct.A) align 1 %agg.result) {{.*}} {
// CHECK: call void @"_ZZ1hvENK4$_11clEv"(%struct.A* sret(%struct.A) align 1 %agg.result,
// CHECK-NEXT: ret void
struct A { ~A(); };
void h() {
Expand Down
8 changes: 4 additions & 4 deletions clang/test/CodeGenCXX/matrix-type-builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ MyMatrix<T, C, R> transpose(const MyMatrix<T, R, C> &M) {

void test_transpose_template1() {
// CHECK-LABEL: define void @_Z24test_transpose_template1v()
// CHECK: call void @_Z9transposeIiLj4ELj10EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(%struct.MyMatrix.0* sret align 4 %M1_t, %struct.MyMatrix* nonnull align 4 dereferenceable(160) %M1)
// CHECK: call void @_Z9transposeIiLj4ELj10EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(%struct.MyMatrix.0* sret(%struct.MyMatrix.0) align 4 %M1_t, %struct.MyMatrix* nonnull align 4 dereferenceable(160) %M1)

// CHECK-LABEL: define linkonce_odr void @_Z9transposeIiLj4ELj10EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(
// CHECK: [[M:%.*]] = load <40 x i32>, <40 x i32>* {{.*}}, align 4
Expand All @@ -31,9 +31,9 @@ void test_transpose_template1() {

void test_transpose_template2(MyMatrix<double, 7, 6> &M) {
// CHECK-LABEL: define void @_Z24test_transpose_template2R8MyMatrixIdLj7ELj6EE(
// CHECK: call void @_Z9transposeIdLj7ELj6EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(%struct.MyMatrix.2* sret align 8 %ref.tmp1, %struct.MyMatrix.1* nonnull align 8 dereferenceable(336) %0)
// CHECK-NEXT: call void @_Z9transposeIdLj6ELj7EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(%struct.MyMatrix.1* sret align 8 %ref.tmp, %struct.MyMatrix.2* nonnull align 8 dereferenceable(336) %ref.tmp1)
// CHECK-NEXT: call void @_Z9transposeIdLj7ELj6EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(%struct.MyMatrix.2* sret align 8 %M2_t, %struct.MyMatrix.1* nonnull align 8 dereferenceable(336) %ref.tmp)
// CHECK: call void @_Z9transposeIdLj7ELj6EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(%struct.MyMatrix.2* sret(%struct.MyMatrix.2) align 8 %ref.tmp1, %struct.MyMatrix.1* nonnull align 8 dereferenceable(336) %0)
// CHECK-NEXT: call void @_Z9transposeIdLj6ELj7EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(%struct.MyMatrix.1* sret(%struct.MyMatrix.1) align 8 %ref.tmp, %struct.MyMatrix.2* nonnull align 8 dereferenceable(336) %ref.tmp1)
// CHECK-NEXT: call void @_Z9transposeIdLj7ELj6EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(%struct.MyMatrix.2* sret(%struct.MyMatrix.2) align 8 %M2_t, %struct.MyMatrix.1* nonnull align 8 dereferenceable(336) %ref.tmp)

// CHECK-LABEL: define linkonce_odr void @_Z9transposeIdLj7ELj6EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(
// CHECK: [[M:%.*]] = load <42 x double>, <42 x double>* {{.*}}, align 8
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGenCXX/matrix-type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ void matrix_template_reference(MatrixClassTemplate<Ty, Rows, Cols> &a, MatrixCla
}

MatrixClassTemplate<float, 10, 15> matrix_template_reference_caller(float *Data) {
// CHECK-LABEL: define void @_Z32matrix_template_reference_callerPf(%class.MatrixClassTemplate* noalias sret align 8 %agg.result, float* %Data
// CHECK-LABEL: define void @_Z32matrix_template_reference_callerPf(%class.MatrixClassTemplate* noalias sret(%class.MatrixClassTemplate) align 8 %agg.result, float* %Data
// CHECK-NEXT: entry:
// CHECK-NEXT: %Data.addr = alloca float*, align 8
// CHECK-NEXT: %Arg = alloca %class.MatrixClassTemplate, align 8
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGenCXX/microsoft-abi-byval-sret.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ A B::qux(A x) {
}

// CHECK-LABEL: define dso_local x86_fastcallcc void @"?qux@B@@QAI?AUA@@U2@@Z"
// CHECK: (%struct.B* inreg %this, %struct.A* inreg noalias sret align 4 %agg.result, <{ %struct.A }>* inalloca %0)
// CHECK: (%struct.B* inreg %this, %struct.A* inreg noalias sret(%struct.A) align 4 %agg.result, <{ %struct.A }>* inalloca %0)
// CHECK: ret void

int main() {
Expand All @@ -67,4 +67,4 @@ int main() {
// CHECK: call x86_stdcallcc %struct.A* @"?baz@B@@QAG?AUA@@U2@@Z"
// CHECK: (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca %{{[^,]*}})
// CHECK: call x86_fastcallcc void @"?qux@B@@QAI?AUA@@U2@@Z"
// CHECK: (%struct.B* inreg %{{[^,]*}}, %struct.A* inreg sret align 4 %{{.*}}, <{ %struct.A }>* inalloca %{{[^,]*}})
// CHECK: (%struct.B* inreg %{{[^,]*}}, %struct.A* inreg sret(%struct.A) align 4 %{{.*}}, <{ %struct.A }>* inalloca %{{[^,]*}})
4 changes: 2 additions & 2 deletions clang/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ C::C() {} // force emission
// CHECK32-NEXT: ret %"struct.sret_thunk::Agg"* %[[rv]]

// CHECK64-LABEL: define linkonce_odr dso_local void @"?foo@C@sret_thunk@@W7EAA?AUAgg@2@U32@@Z"
// CHECK64: (%"struct.sret_thunk::C"* %this, %"struct.sret_thunk::Agg"* noalias sret align 4 %agg.result, %"struct.sret_thunk::Agg"* %x)
// CHECK64: (%"struct.sret_thunk::C"* %this, %"struct.sret_thunk::Agg"* noalias sret(%"struct.sret_thunk::Agg") align 4 %agg.result, %"struct.sret_thunk::Agg"* %x)
// CHECK64: getelementptr i8, i8* %{{.*}}, i32 -8
// CHECK64: call void @"?foo@C@sret_thunk@@UEAA?AUAgg@2@U32@@Z"
// CHECK64: (%"struct.sret_thunk::C"* %{{.*}}, %"struct.sret_thunk::Agg"* sret align 4 %agg.result, %"struct.sret_thunk::Agg"* %x)
// CHECK64: (%"struct.sret_thunk::C"* %{{.*}}, %"struct.sret_thunk::Agg"* sret(%"struct.sret_thunk::Agg") align 4 %agg.result, %"struct.sret_thunk::Agg"* %x)
// CHECK64-NOT: call
// CHECK64: ret void
}
Expand Down
8 changes: 4 additions & 4 deletions clang/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ S C::variadic_sret(const char *f, ...) { return S(); }
S C::cdecl_sret() { return S(); }
S C::byval_and_sret(S a) { return S(); }

// CHECK: define dso_local void @"?variadic_sret@C@@QAA?AUS@@PBDZZ"(%struct.C* %this, %struct.S* noalias sret align 4 %agg.result, i8* %f, ...)
// CHECK: define dso_local void @"?cdecl_sret@C@@QAA?AUS@@XZ"(%struct.C* %this, %struct.S* noalias sret align 4 %agg.result)
// CHECK: define dso_local void @"?byval_and_sret@C@@QAA?AUS@@U2@@Z"(%struct.C* %this, %struct.S* noalias sret align 4 %agg.result, %struct.S* byval(%struct.S) align 4 %a)
// CHECK: define dso_local void @"?variadic_sret@C@@QAA?AUS@@PBDZZ"(%struct.C* %this, %struct.S* noalias sret(%struct.S) align 4 %agg.result, i8* %f, ...)
// CHECK: define dso_local void @"?cdecl_sret@C@@QAA?AUS@@XZ"(%struct.C* %this, %struct.S* noalias sret(%struct.S) align 4 %agg.result)
// CHECK: define dso_local void @"?byval_and_sret@C@@QAA?AUS@@U2@@Z"(%struct.C* %this, %struct.S* noalias sret(%struct.S) align 4 %agg.result, %struct.S* byval(%struct.S) align 4 %a)

int main() {
C c;
Expand All @@ -41,4 +41,4 @@ struct A {
S A::f(int x) {
return S();
}
// CHECK-LABEL: define dso_local x86_fastcallcc void @"?f@A@@QAI?AUS@@H@Z"(%struct.A* inreg %this, %struct.S* inreg noalias sret align 4 %agg.result, i32 %x)
// CHECK-LABEL: define dso_local x86_fastcallcc void @"?f@A@@QAI?AUS@@H@Z"(%struct.A* inreg %this, %struct.S* inreg noalias sret(%struct.S) align 4 %agg.result, i32 %x)
4 changes: 2 additions & 2 deletions clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ void HasEHCleanup() {
// WIN32-LABEL: define dso_local void @"?HasEHCleanup@@YAXXZ"() {{.*}} {
// WIN32: %[[base:.*]] = call i8* @llvm.stacksave()
// If this call throws, we have to restore the stack.
// WIN32: call void @"?getA@@YA?AUA@@XZ"(%struct.A* sret align 4 %{{.*}})
// WIN32: call void @"?getA@@YA?AUA@@XZ"(%struct.A* sret(%struct.A) align 4 %{{.*}})
// If this call throws, we have to cleanup the first temporary.
// WIN32: invoke void @"?getA@@YA?AUA@@XZ"(%struct.A* sret align 4 %{{.*}})
// WIN32: invoke void @"?getA@@YA?AUA@@XZ"(%struct.A* sret(%struct.A) align 4 %{{.*}})
// If this call throws, we have to cleanup the stacksave.
// WIN32: call i32 @"?TakesTwo@@YAHUA@@0@Z"
// WIN32: call void @llvm.stackrestore
Expand Down
64 changes: 32 additions & 32 deletions clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,45 +84,45 @@ void call_bools_and_chars() {

// Returning structs that fit into a register.
Small small_return() { return Small(); }
// LINUX-LABEL: define void @_Z12small_returnv(%struct.Small* noalias sret align 4 %agg.result)
// LINUX-LABEL: define void @_Z12small_returnv(%struct.Small* noalias sret(%struct.Small) align 4 %agg.result)
// WIN32: define dso_local i32 @"?small_return@@YA?AUSmall@@XZ"()
// WIN64: define dso_local i32 @"?small_return@@YA?AUSmall@@XZ"()

Medium medium_return() { return Medium(); }
// LINUX-LABEL: define void @_Z13medium_returnv(%struct.Medium* noalias sret align 4 %agg.result)
// LINUX-LABEL: define void @_Z13medium_returnv(%struct.Medium* noalias sret(%struct.Medium) align 4 %agg.result)
// WIN32: define dso_local i64 @"?medium_return@@YA?AUMedium@@XZ"()
// WIN64: define dso_local i64 @"?medium_return@@YA?AUMedium@@XZ"()

// Returning structs that fit into a register but are not POD.
SmallCpp11NotCpp03Pod small_non_pod_return() { return SmallCpp11NotCpp03Pod(); }
// LINUX-LABEL: define void @_Z20small_non_pod_returnv(%struct.SmallCpp11NotCpp03Pod* noalias sret align 4 %agg.result)
// WIN32: define dso_local void @"?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(%struct.SmallCpp11NotCpp03Pod* noalias sret align 4 %agg.result)
// WIN64: define dso_local void @"?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(%struct.SmallCpp11NotCpp03Pod* noalias sret align 4 %agg.result)
// LINUX-LABEL: define void @_Z20small_non_pod_returnv(%struct.SmallCpp11NotCpp03Pod* noalias sret(%struct.SmallCpp11NotCpp03Pod) align 4 %agg.result)
// WIN32: define dso_local void @"?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(%struct.SmallCpp11NotCpp03Pod* noalias sret(%struct.SmallCpp11NotCpp03Pod) align 4 %agg.result)
// WIN64: define dso_local void @"?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(%struct.SmallCpp11NotCpp03Pod* noalias sret(%struct.SmallCpp11NotCpp03Pod) align 4 %agg.result)

SmallWithCtor small_with_ctor_return() { return SmallWithCtor(); }
// LINUX-LABEL: define void @_Z22small_with_ctor_returnv(%struct.SmallWithCtor* noalias sret align 4 %agg.result)
// WIN32: define dso_local void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret align 4 %agg.result)
// WIN64: define dso_local void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret align 4 %agg.result)
// LINUX-LABEL: define void @_Z22small_with_ctor_returnv(%struct.SmallWithCtor* noalias sret(%struct.SmallWithCtor) align 4 %agg.result)
// WIN32: define dso_local void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret(%struct.SmallWithCtor) align 4 %agg.result)
// WIN64: define dso_local void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret(%struct.SmallWithCtor) align 4 %agg.result)
// FIXME: The 'sret' mark here doesn't seem to be enough to convince LLVM to
// preserve the hidden sret pointer in R0 across the function.
// WOA: define dso_local arm_aapcs_vfpcc void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret align 4 %agg.result)
// WOA: define dso_local arm_aapcs_vfpcc void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret(%struct.SmallWithCtor) align 4 %agg.result)

SmallWithVftable small_with_vftable_return() { return SmallWithVftable(); }
// LINUX-LABEL: define void @_Z25small_with_vftable_returnv(%struct.SmallWithVftable* noalias sret align 4 %agg.result)
// WIN32: define dso_local void @"?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(%struct.SmallWithVftable* noalias sret align 4 %agg.result)
// WIN64: define dso_local void @"?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(%struct.SmallWithVftable* noalias sret align 8 %agg.result)
// LINUX-LABEL: define void @_Z25small_with_vftable_returnv(%struct.SmallWithVftable* noalias sret(%struct.SmallWithVftable) align 4 %agg.result)
// WIN32: define dso_local void @"?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(%struct.SmallWithVftable* noalias sret(%struct.SmallWithVftable) align 4 %agg.result)
// WIN64: define dso_local void @"?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(%struct.SmallWithVftable* noalias sret(%struct.SmallWithVftable) align 8 %agg.result)

MediumWithCopyCtor medium_with_copy_ctor_return() { return MediumWithCopyCtor(); }
// LINUX-LABEL: define void @_Z28medium_with_copy_ctor_returnv(%struct.MediumWithCopyCtor* noalias sret align 4 %agg.result)
// WIN32: define dso_local void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret align 4 %agg.result)
// WIN64: define dso_local void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret align 4 %agg.result)
// WOA: define dso_local arm_aapcs_vfpcc void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret align 4 %agg.result)
// LINUX-LABEL: define void @_Z28medium_with_copy_ctor_returnv(%struct.MediumWithCopyCtor* noalias sret(%struct.MediumWithCopyCtor) align 4 %agg.result)
// WIN32: define dso_local void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret(%struct.MediumWithCopyCtor) align 4 %agg.result)
// WIN64: define dso_local void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret(%struct.MediumWithCopyCtor) align 4 %agg.result)
// WOA: define dso_local arm_aapcs_vfpcc void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret(%struct.MediumWithCopyCtor) align 4 %agg.result)

// Returning a large struct that doesn't fit into a register.
Big big_return() { return Big(); }
// LINUX-LABEL: define void @_Z10big_returnv(%struct.Big* noalias sret align 4 %agg.result)
// WIN32: define dso_local void @"?big_return@@YA?AUBig@@XZ"(%struct.Big* noalias sret align 4 %agg.result)
// WIN64: define dso_local void @"?big_return@@YA?AUBig@@XZ"(%struct.Big* noalias sret align 4 %agg.result)
// LINUX-LABEL: define void @_Z10big_returnv(%struct.Big* noalias sret(%struct.Big) align 4 %agg.result)
// WIN32: define dso_local void @"?big_return@@YA?AUBig@@XZ"(%struct.Big* noalias sret(%struct.Big) align 4 %agg.result)
// WIN64: define dso_local void @"?big_return@@YA?AUBig@@XZ"(%struct.Big* noalias sret(%struct.Big) align 4 %agg.result)


void small_arg(Small s) {}
Expand Down Expand Up @@ -181,7 +181,7 @@ void small_arg_with_dtor(SmallWithDtor s) {}

// Test that the eligible non-aggregate is passed directly, but returned
// indirectly on ARM64 Windows.
// WOA64: define dso_local void @"?small_arg_with_private_member@@YA?AUSmallWithPrivate@@U1@@Z"(%struct.SmallWithPrivate* inreg noalias sret align 4 %agg.result, i64 %s.coerce) {{.*}} {
// WOA64: define dso_local void @"?small_arg_with_private_member@@YA?AUSmallWithPrivate@@U1@@Z"(%struct.SmallWithPrivate* inreg noalias sret(%struct.SmallWithPrivate) align 4 %agg.result, i64 %s.coerce) {{.*}} {
SmallWithPrivate small_arg_with_private_member(SmallWithPrivate s) { return s; }

void call_small_arg_with_dtor() {
Expand Down Expand Up @@ -281,24 +281,24 @@ void pass_ref_field() {
class Class {
public:
Small thiscall_method_small() { return Small(); }
// LINUX: define {{.*}} void @_ZN5Class21thiscall_method_smallEv(%struct.Small* noalias sret align 4 %agg.result, %class.Class* %this)
// WIN32: define {{.*}} x86_thiscallcc void @"?thiscall_method_small@Class@@QAE?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret align 4 %agg.result)
// WIN64: define linkonce_odr dso_local void @"?thiscall_method_small@Class@@QEAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret align 4 %agg.result)
// LINUX: define {{.*}} void @_ZN5Class21thiscall_method_smallEv(%struct.Small* noalias sret(%struct.Small) align 4 %agg.result, %class.Class* %this)
// WIN32: define {{.*}} x86_thiscallcc void @"?thiscall_method_small@Class@@QAE?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret(%struct.Small) align 4 %agg.result)
// WIN64: define linkonce_odr dso_local void @"?thiscall_method_small@Class@@QEAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret(%struct.Small) align 4 %agg.result)

SmallWithCtor thiscall_method_small_with_ctor() { return SmallWithCtor(); }
// LINUX: define {{.*}} void @_ZN5Class31thiscall_method_small_with_ctorEv(%struct.SmallWithCtor* noalias sret align 4 %agg.result, %class.Class* %this)
// WIN32: define {{.*}} x86_thiscallcc void @"?thiscall_method_small_with_ctor@Class@@QAE?AUSmallWithCtor@@XZ"(%class.Class* %this, %struct.SmallWithCtor* noalias sret align 4 %agg.result)
// WIN64: define linkonce_odr dso_local void @"?thiscall_method_small_with_ctor@Class@@QEAA?AUSmallWithCtor@@XZ"(%class.Class* %this, %struct.SmallWithCtor* noalias sret align 4 %agg.result)
// LINUX: define {{.*}} void @_ZN5Class31thiscall_method_small_with_ctorEv(%struct.SmallWithCtor* noalias sret(%struct.SmallWithCtor) align 4 %agg.result, %class.Class* %this)
// WIN32: define {{.*}} x86_thiscallcc void @"?thiscall_method_small_with_ctor@Class@@QAE?AUSmallWithCtor@@XZ"(%class.Class* %this, %struct.SmallWithCtor* noalias sret(%struct.SmallWithCtor) align 4 %agg.result)
// WIN64: define linkonce_odr dso_local void @"?thiscall_method_small_with_ctor@Class@@QEAA?AUSmallWithCtor@@XZ"(%class.Class* %this, %struct.SmallWithCtor* noalias sret(%struct.SmallWithCtor) align 4 %agg.result)

Small __cdecl cdecl_method_small() { return Small(); }
// LINUX: define {{.*}} void @_ZN5Class18cdecl_method_smallEv(%struct.Small* noalias sret align 4 %agg.result, %class.Class* %this)
// WIN32: define {{.*}} void @"?cdecl_method_small@Class@@QAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret align 4 %agg.result)
// WIN64: define linkonce_odr dso_local void @"?cdecl_method_small@Class@@QEAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret align 4 %agg.result)
// LINUX: define {{.*}} void @_ZN5Class18cdecl_method_smallEv(%struct.Small* noalias sret(%struct.Small) align 4 %agg.result, %class.Class* %this)
// WIN32: define {{.*}} void @"?cdecl_method_small@Class@@QAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret(%struct.Small) align 4 %agg.result)
// WIN64: define linkonce_odr dso_local void @"?cdecl_method_small@Class@@QEAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret(%struct.Small) align 4 %agg.result)

Big __cdecl cdecl_method_big() { return Big(); }
// LINUX: define {{.*}} void @_ZN5Class16cdecl_method_bigEv(%struct.Big* noalias sret align 4 %agg.result, %class.Class* %this)
// WIN32: define {{.*}} void @"?cdecl_method_big@Class@@QAA?AUBig@@XZ"(%class.Class* %this, %struct.Big* noalias sret align 4 %agg.result)
// WIN64: define linkonce_odr dso_local void @"?cdecl_method_big@Class@@QEAA?AUBig@@XZ"(%class.Class* %this, %struct.Big* noalias sret align 4 %agg.result)
// LINUX: define {{.*}} void @_ZN5Class16cdecl_method_bigEv(%struct.Big* noalias sret(%struct.Big) align 4 %agg.result, %class.Class* %this)
// WIN32: define {{.*}} void @"?cdecl_method_big@Class@@QAA?AUBig@@XZ"(%class.Class* %this, %struct.Big* noalias sret(%struct.Big) align 4 %agg.result)
// WIN64: define linkonce_odr dso_local void @"?cdecl_method_big@Class@@QEAA?AUBig@@XZ"(%class.Class* %this, %struct.Big* noalias sret(%struct.Big) align 4 %agg.result)

void thiscall_method_arg(Empty s) {}
// LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE5Empty(%class.Class* %this)
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGenCXX/microsoft-abi-unknown-arch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ A B::foo(A x) {
return x;
}

// CHECK-LABEL: define void @"?foo@B@@QEAA?AUA@@U2@@Z"(%struct.B* %this, %struct.A* noalias sret align 4 %agg.result, %struct.A* %x)
// CHECK-LABEL: define void @"?foo@B@@QEAA?AUA@@U2@@Z"(%struct.B* %this, %struct.A* noalias sret(%struct.A) align 4 %agg.result, %struct.A* %x)
2 changes: 1 addition & 1 deletion clang/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ void f(C *c) {

// CHECK-LABEL: define dso_local void @"?f@sret@@YAXPAUC@1@@Z"(%"struct.sret::C"* %c)
// CHECK: call x86_thiscallcc i32 bitcast (void (%"struct.sret::C"*, ...)* @"??_9C@sret@@$BA@AE" to i32 (%"struct.sret::C"*)*)(%"struct.sret::C"* %{{.*}})
// CHECK: call x86_thiscallcc void bitcast (void (%"struct.sret::C"*, ...)* @"??_9C@sret@@$BA@AE" to void (%"struct.sret::C"*, %"struct.sret::Big"*)*)(%"struct.sret::C"* %{{.*}}, %"struct.sret::Big"* sret align 4 %{{.*}})
// CHECK: call x86_thiscallcc void bitcast (void (%"struct.sret::C"*, ...)* @"??_9C@sret@@$BA@AE" to void (%"struct.sret::C"*, %"struct.sret::Big"*)*)(%"struct.sret::C"* %{{.*}}, %"struct.sret::Big"* sret(%"struct.sret::Big") align 4 %{{.*}})

// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"??_9C@sret@@$BA@AE"(%"struct.sret::C"* %this, ...) {{.*}} comdat
// CHECK: musttail call x86_thiscallcc void (%"struct.sret::C"*, ...) %{{.*}}(%"struct.sret::C"* %{{.*}}, ...)
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGenCXX/pass-by-value-noalias.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ A *p;
// NO_NOALIAS: define void @_Z4take1A(%struct.A* %arg)
void take(A arg) {}

// WITH_NOALIAS: define void @_Z7CreateAPP1A(%struct.A* noalias sret align 1 %agg.result, %struct.A** %where)
// NO_NOALIAS: define void @_Z7CreateAPP1A(%struct.A* noalias sret align 1 %agg.result, %struct.A** %where)
// WITH_NOALIAS: define void @_Z7CreateAPP1A(%struct.A* noalias sret(%struct.A) align 1 %agg.result, %struct.A** %where)
// NO_NOALIAS: define void @_Z7CreateAPP1A(%struct.A* noalias sret(%struct.A) align 1 %agg.result, %struct.A** %where)
A CreateA(A **where) {
A justlikethis;
*where = &justlikethis; //Escaped pointer 2 (should also be UB, then)
Expand Down
8 changes: 4 additions & 4 deletions clang/test/CodeGenCXX/regcall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ bool __regcall operator ==(const test_class&, const test_class&){ --x; return fa
// CHECK-WIN32-DAG: define dso_local x86_regcallcc zeroext i1 @"??8@Yw_NABVtest_class@@0@Z"

test_class __regcall operator""_test_class (unsigned long long) { ++x; return test_class{};}
// CHECK-LIN64-DAG: define x86_regcallcc void @_Zli11_test_classy(%class.test_class* noalias sret align 4 %agg.result, i64 %0)
// CHECK-LIN32-DAG: define x86_regcallcc void @_Zli11_test_classy(%class.test_class* inreg noalias sret align 4 %agg.result, i64 %0)
// CHECK-LIN64-DAG: define x86_regcallcc void @_Zli11_test_classy(%class.test_class* noalias sret(%class.test_class) align 4 %agg.result, i64 %0)
// CHECK-LIN32-DAG: define x86_regcallcc void @_Zli11_test_classy(%class.test_class* inreg noalias sret(%class.test_class) align 4 %agg.result, i64 %0)
// CHECK-WIN64-DAG: ??__K_test_class@@Yw?AVtest_class@@_K@Z"
// CHECK-WIN32-DAG: ??__K_test_class@@Yw?AVtest_class@@_K@Z"

Expand All @@ -99,8 +99,8 @@ void force_gen() {
long double _Complex __regcall foo(long double _Complex f) {
return f;
}
// CHECK-LIN64-DAG: define x86_regcallcc void @_Z15__regcall3__fooCe({ x86_fp80, x86_fp80 }* noalias sret align 16 %agg.result, { x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16 %f)
// CHECK-LIN32-DAG: define x86_regcallcc void @_Z15__regcall3__fooCe({ x86_fp80, x86_fp80 }* inreg noalias sret align 4 %agg.result, { x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 4 %f)
// CHECK-LIN64-DAG: define x86_regcallcc void @_Z15__regcall3__fooCe({ x86_fp80, x86_fp80 }* noalias sret({ x86_fp80, x86_fp80 }) align 16 %agg.result, { x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16 %f)
// CHECK-LIN32-DAG: define x86_regcallcc void @_Z15__regcall3__fooCe({ x86_fp80, x86_fp80 }* inreg noalias sret({ x86_fp80, x86_fp80 }) align 4 %agg.result, { x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 4 %f)
// CHECK-WIN64-DAG: define dso_local x86_regcallcc { double, double } @"?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1)
// CHECK-WIN32-DAG: define dso_local x86_regcallcc { double, double } @"?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1)

Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGenCXX/stack-reuse-miscompile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const char * f(S s)
// CHECK: call void @llvm.lifetime.start.p0i8(i64 16, i8* [[T3i8]])
// CHECK: [[T5:%.*]] = call %class.T* @_ZN1TC1E1S(%class.T* [[T3]], [2 x i32] %{{.*}})
//
// CHECK: call void @_ZNK1T6concatERKS_(%class.T* sret align 4 [[T1]], %class.T* [[T2]], %class.T* nonnull align 4 dereferenceable(16) [[T3]])
// CHECK: call void @_ZNK1T6concatERKS_(%class.T* sret(%class.T) align 4 [[T1]], %class.T* [[T2]], %class.T* nonnull align 4 dereferenceable(16) [[T3]])
// CHECK: [[T6:%.*]] = call i8* @_ZNK1T3strEv(%class.T* [[T1]])
//
// CHECK: call void @llvm.lifetime.end.p0i8(
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGenCXX/stack-reuse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ int large_combiner_test(S_large s) {
// CHECK: [[T2:%.*]] = alloca %struct.Combiner
// CHECK: [[T1:%.*]] = alloca %struct.Combiner
// CHECK: [[T3:%.*]] = call %struct.Combiner* @_ZN8CombinerC1E7S_large(%struct.Combiner* nonnull [[T1]], [9 x i32] %s.coerce)
// CHECK: call void @_ZN8Combiner1fEv(%struct.Combiner* nonnull sret align 4 [[T2]], %struct.Combiner* nonnull [[T1]])
// CHECK: call void @_ZN8Combiner1fEv(%struct.Combiner* nonnull sret(%struct.Combiner) align 4 [[T2]], %struct.Combiner* nonnull [[T1]])
// CHECK: [[T4:%.*]] = getelementptr inbounds %struct.Combiner, %struct.Combiner* [[T2]], i32 0, i32 0, i32 0, i32 0
// CHECK: [[T5:%.*]] = load i32, i32* [[T4]]
// CHECK: ret i32 [[T5]]
Expand Down
44 changes: 22 additions & 22 deletions clang/test/CodeGenCXX/temporaries.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ void f2() {
struct C {
C();
~C();

C f();
};

Expand All @@ -102,7 +102,7 @@ void f3() {
struct D {
D();
~D();

D operator()();
};

Expand All @@ -128,7 +128,7 @@ void f5() {
// CHECK: call void @_ZN1ED1Ev
// CHECK: call void @_ZN1ED1Ev
E() + E();

// CHECK: call void @_ZN1EC1Ev
// CHECK: call void @_ZN1ED1Ev
// CHECK: call void @_ZN1ED1Ev
Expand Down Expand Up @@ -161,7 +161,7 @@ void f7() {
// CHECK: call void @_Z1aRK1A
// CHECK: call void @_ZN1AD1Ev
a(A());

// CHECK: call void @_ZN1GC1Ev
// CHECK: call void @_ZN1Gcv1AEv
// CHECK: call void @_Z1aRK1A
Expand Down Expand Up @@ -201,7 +201,7 @@ B::B()
// CHECK: call void @_ZN6PR50771fEv
f();
}

}

A f8() {
Expand All @@ -222,7 +222,7 @@ void f9(H h) {
// CHECK: call void @_Z2f91H
// CHECK: call void @_ZN1HD1Ev
f9(H());

// CHECK: call void @_ZN1HC1ERKS_
// CHECK: call void @_Z2f91H
// CHECK: call void @_ZN1HD1Ev
Expand All @@ -236,7 +236,7 @@ void f11(H h) {
// CHECK: call void @_Z3f10RK1H
// CHECK: call void @_ZN1HD1Ev
f10(H());

// CHECK: call void @_Z3f10RK1H
// CHECK-NOT: call void @_ZN1HD1Ev
// CHECK: ret void
Expand Down Expand Up @@ -305,13 +305,13 @@ namespace PR6199 {
}

template A f2<int>(int);

}

namespace T12 {

struct A {
A();
struct A {
A();
~A();
int f();
};
Expand Down Expand Up @@ -352,7 +352,7 @@ namespace UserConvertToValue {

void f(X);

// CHECK: void @_ZN18UserConvertToValue1gEv()
// CHECK: void @_ZN18UserConvertToValue1gEv()
void g() {
// CHECK: call void @_ZN18UserConvertToValue1XC1Ei
// CHECK: call void @_ZN18UserConvertToValue1fENS_1XE
Expand All @@ -363,13 +363,13 @@ namespace UserConvertToValue {
}

namespace PR7556 {
struct A { ~A(); };
struct B { int i; ~B(); };
struct C { int C::*pm; ~C(); };
struct A { ~A(); };
struct B { int i; ~B(); };
struct C { int C::*pm; ~C(); };
// CHECK-LABEL: define void @_ZN6PR75563fooEv()
void foo() {
void foo() {
// CHECK: call void @_ZN6PR75561AD1Ev
A();
A();
// CHECK: call void @llvm.memset.p0i8.i64
// CHECK: call void @_ZN6PR75561BD1Ev
B();
Expand Down Expand Up @@ -403,13 +403,13 @@ namespace Elision {
// CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[I]])
A i = (foo(), A());

// CHECK-NEXT: call void @_ZN7Elision4fooAEv([[A]]* sret align 8 [[T0]])
// CHECK-NEXT: call void @_ZN7Elision4fooAEv([[A]]* sret([[A]]) align 8 [[T0]])
// CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[J]])
// CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[T0]])
A j = (fooA(), A());

// CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[T1]])
// CHECK-NEXT: call void @_ZN7Elision4fooAEv([[A]]* sret align 8 [[K]])
// CHECK-NEXT: call void @_ZN7Elision4fooAEv([[A]]* sret([[A]]) align 8 [[K]])
// CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[T1]])
A k = (A(), fooA());

Expand All @@ -436,15 +436,15 @@ namespace Elision {
// CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[I]])
}

// CHECK: define void @_ZN7Elision5test2Ev([[A]]* noalias sret align 8
// CHECK: define void @_ZN7Elision5test2Ev([[A]]* noalias sret([[A]]) align 8
A test2() {
// CHECK: call void @_ZN7Elision3fooEv()
// CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[RET:%.*]])
// CHECK-NEXT: ret void
return (foo(), A());
}

// CHECK: define void @_ZN7Elision5test3EiNS_1AE([[A]]* noalias sret align 8
// CHECK: define void @_ZN7Elision5test3EiNS_1AE([[A]]* noalias sret([[A]]) align 8
A test3(int v, A x) {
if (v < 5)
// CHECK: call void @_ZN7Elision1AC1Ev([[A]]* [[RET:%.*]])
Expand Down Expand Up @@ -485,7 +485,7 @@ namespace Elision {
}

// rdar://problem/8433352
// CHECK: define void @_ZN7Elision5test5Ev([[A]]* noalias sret align 8
// CHECK: define void @_ZN7Elision5test5Ev([[A]]* noalias sret([[A]]) align 8
struct B { A a; B(); };
A test5() {
// CHECK: [[AT0:%.*]] = alloca [[A]], align 8
Expand Down Expand Up @@ -523,7 +523,7 @@ namespace Elision {
void test6(const C *x) {
// CHECK: [[T0:%.*]] = alloca [[A]], align 8
// CHECK: [[X:%.*]] = load [[C]]*, [[C]]** {{%.*}}, align 8
// CHECK-NEXT: call void @_ZNK7Elision1CcvNS_1AEEv([[A]]* sret align 8 [[T0]], [[C]]* [[X]])
// CHECK-NEXT: call void @_ZNK7Elision1CcvNS_1AEEv([[A]]* sret([[A]]) align 8 [[T0]], [[C]]* [[X]])
// CHECK-NEXT: call void @_ZNK7Elision1A3fooEv([[A]]* [[T0]])
// CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[T0]])
// CHECK-NEXT: ret void
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGenCXX/thiscall-struct-return.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ void test( void ) {
// CHECK: call void @_ZN1CC1Ev(%class.C* [[C:%.+]])
C c;

// CHECK: call x86_thiscallcc void @_ZNK1C5SmallEv(%struct.S* sret align 4 %{{.+}}, %class.C* [[C]])
// CHECK: call x86_thiscallcc void @_ZNK1C5SmallEv(%struct.S* sret(%struct.S) align 4 %{{.+}}, %class.C* [[C]])
(void)c.Small();
// CHECK: call x86_thiscallcc void @_ZNK1C6MediumEv(%struct.M* sret align 4 %{{.+}}, %class.C* [[C]])
// CHECK: call x86_thiscallcc void @_ZNK1C6MediumEv(%struct.M* sret(%struct.M) align 4 %{{.+}}, %class.C* [[C]])
(void)c.Medium();
}
4 changes: 2 additions & 2 deletions clang/test/CodeGenCXX/thunk-returning-memptr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@ C::C() {}
// Because of the tail call, the return value cannot be copied into a local
// alloca. (PR39901)

// CHECK-LABEL: define linkonce_odr void @_ZThn4_N1C1fEv({ i32, i32 }* noalias sret align 4 %agg.result, %struct.C* %this)
// CHECK: tail call void @_ZN1C1fEv({ i32, i32 }* sret align 4 %agg.result
// CHECK-LABEL: define linkonce_odr void @_ZThn4_N1C1fEv({ i32, i32 }* noalias sret({ i32, i32 }) align 4 %agg.result, %struct.C* %this)
// CHECK: tail call void @_ZN1C1fEv({ i32, i32 }* sret({ i32, i32 }) align 4 %agg.result
16 changes: 8 additions & 8 deletions clang/test/CodeGenCXX/thunks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ struct B {

struct C : A, B {
virtual void c();

virtual void f();
};

Expand Down Expand Up @@ -83,7 +83,7 @@ struct A {

struct B : A {
virtual void b();

virtual V2 *f();
};

Expand All @@ -107,7 +107,7 @@ struct B {

struct __attribute__((visibility("protected"))) C : A, B {
virtual void c();

virtual void f();
};

Expand Down Expand Up @@ -142,8 +142,8 @@ namespace Test4B {
void C::f() {}

// Force C::f to be used.
void f() {
C c;
void f() {
C c;
c.f();
}
}
Expand Down Expand Up @@ -206,13 +206,13 @@ namespace Test6 {
// CHECK-LABEL: define void @_ZThn16_N5Test66Thunks1fEv
// CHECK-DBG-NOT: dbg.declare
// CHECK-NOT: memcpy
// CHECK: {{call void @_ZN5Test66Thunks1fEv.*sret align 1}}
// CHECK: {{call void @_ZN5Test66Thunks1fEv.*sret(.+) align 1}}
// CHECK: ret void
X Thunks::f() { return X(); }

// WIN64-LABEL: define linkonce_odr dso_local void @"?f@Thunks@Test6@@WBA@EAA?AUX@2@XZ"({{.*}} sret align 1 %{{.*}})
// WIN64-LABEL: define linkonce_odr dso_local void @"?f@Thunks@Test6@@WBA@EAA?AUX@2@XZ"({{.*}} sret({{.*}}) align 1 %{{.*}})
// WIN64-NOT: memcpy
// WIN64: tail call void @"?f@Thunks@Test6@@UEAA?AUX@2@XZ"({{.*}} sret align 1 %{{.*}})
// WIN64: tail call void @"?f@Thunks@Test6@@UEAA?AUX@2@XZ"({{.*}} sret({{.*}}) align 1 %{{.*}})
}

namespace Test7 {
Expand Down
8 changes: 4 additions & 4 deletions clang/test/CodeGenCXX/trivial_abi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ void testIgnoredSmall() {
void testParamLarge(Large a) noexcept {
}

// CHECK: define void @_Z15testReturnLargev(%[[STRUCT_LARGE:.*]]* noalias sret align 8 %[[AGG_RESULT:.*]])
// CHECK: define void @_Z15testReturnLargev(%[[STRUCT_LARGE:.*]]* noalias sret(%[[STRUCT_LARGE]]) align 8 %[[AGG_RESULT:.*]])
// CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[AGG_RESULT]])
// CHECK: ret void
// CHECK: }
Expand All @@ -178,7 +178,7 @@ void testCallLarge0() {

// CHECK: define void @_Z14testCallLarge1v()
// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8
// CHECK: call void @_Z15testReturnLargev(%[[STRUCT_LARGE]]* sret align 8 %[[AGG_TMP]])
// CHECK: call void @_Z15testReturnLargev(%[[STRUCT_LARGE]]* sret(%[[STRUCT_LARGE]]) align 8 %[[AGG_TMP]])
// CHECK: call void @_Z14testParamLarge5Large(%[[STRUCT_LARGE]]* %[[AGG_TMP]])
// CHECK: ret void
// CHECK: }
Expand All @@ -189,7 +189,7 @@ void testCallLarge1() {

// CHECK: define void @_Z16testIgnoredLargev()
// CHECK: %[[AGG_TMP_ENSURED:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8
// CHECK: call void @_Z15testReturnLargev(%[[STRUCT_LARGE]]* sret align 8 %[[AGG_TMP_ENSURED]])
// CHECK: call void @_Z15testReturnLargev(%[[STRUCT_LARGE]]* sret(%[[STRUCT_LARGE]]) align 8 %[[AGG_TMP_ENSURED]])
// CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP_ENSURED]])
// CHECK: ret void
// CHECK: }
Expand All @@ -211,7 +211,7 @@ Trivial testReturnHasTrivial() {
return t;
}

// CHECK: define void @_Z23testReturnHasNonTrivialv(%[[STRUCT_NONTRIVIAL:.*]]* noalias sret align 4 %[[AGG_RESULT:.*]])
// CHECK: define void @_Z23testReturnHasNonTrivialv(%[[STRUCT_NONTRIVIAL:.*]]* noalias sret(%[[STRUCT_NONTRIVIAL]]) align 4 %[[AGG_RESULT:.*]])
// CHECK: %[[CALL:.*]] = call %[[STRUCT_NONTRIVIAL]]* @_ZN10NonTrivialC1Ev(%[[STRUCT_NONTRIVIAL]]* %[[AGG_RESULT]])
// CHECK: ret void
// CHECK: }
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGenCXX/unknown-anytype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ struct Test7 {
};
extern "C" __unknown_anytype test7_any(int);
Test7 test7() {
// COMMON: call void @test7_any({{%.*}}* sret align 1 {{%.*}}, i32 5)
// COMMON: call void @test7_any({{%.*}}* sret({{%.*}}) align 1 {{%.*}}, i32 5)
return (Test7) test7_any(5);
}

Expand Down
18 changes: 9 additions & 9 deletions clang/test/CodeGenCXX/wasm-args-returns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,52 +30,52 @@ struct two_fields {
double d, e;
};
test(two_fields);
// CHECK: define void @_Z7forward10two_fields(%struct.two_fields* noalias nocapture sret align 8 %{{.*}}, %struct.two_fields* nocapture readonly byval(%struct.two_fields) align 8 %{{.*}})
// CHECK: define void @_Z7forward10two_fields(%struct.two_fields* noalias nocapture sret(%struct.two_fields) align 8 %{{.*}}, %struct.two_fields* nocapture readonly byval(%struct.two_fields) align 8 %{{.*}})
//
// CHECK: define void @_Z15test_two_fieldsv()
// CHECK: %[[tmp:.*]] = alloca %struct.two_fields, align 8
// CHECK: call void @_Z14def_two_fieldsv(%struct.two_fields* nonnull sret align 8 %[[tmp]])
// CHECK: call void @_Z14def_two_fieldsv(%struct.two_fields* nonnull sret(%struct.two_fields) align 8 %[[tmp]])
// CHECK: call void @_Z3use10two_fields(%struct.two_fields* nonnull byval(%struct.two_fields) align 8 %[[tmp]])
// CHECK: ret void
//
// CHECK: declare void @_Z3use10two_fields(%struct.two_fields* byval(%struct.two_fields) align 8)
// CHECK: declare void @_Z14def_two_fieldsv(%struct.two_fields* sret align 8)
// CHECK: declare void @_Z14def_two_fieldsv(%struct.two_fields* sret(%struct.two_fields) align 8)

struct copy_ctor {
double d;
copy_ctor(copy_ctor const &);
};
test(copy_ctor);
// CHECK: define void @_Z7forward9copy_ctor(%struct.copy_ctor* noalias sret align 8 %{{.*}}, %struct.copy_ctor* nonnull %{{.*}})
// CHECK: define void @_Z7forward9copy_ctor(%struct.copy_ctor* noalias sret(%struct.copy_ctor) align 8 %{{.*}}, %struct.copy_ctor* nonnull %{{.*}})
//
// CHECK: declare %struct.copy_ctor* @_ZN9copy_ctorC1ERKS_(%struct.copy_ctor* returned, %struct.copy_ctor* nonnull align 8 dereferenceable(8))
//
// CHECK: define void @_Z14test_copy_ctorv()
// CHECK: %[[tmp:.*]] = alloca %struct.copy_ctor, align 8
// CHECK: call void @_Z13def_copy_ctorv(%struct.copy_ctor* nonnull sret align 8 %[[tmp]])
// CHECK: call void @_Z13def_copy_ctorv(%struct.copy_ctor* nonnull sret(%struct.copy_ctor) align 8 %[[tmp]])
// CHECK: call void @_Z3use9copy_ctor(%struct.copy_ctor* nonnull %[[tmp]])
// CHECK: ret void
//
// CHECK: declare void @_Z3use9copy_ctor(%struct.copy_ctor*)
// CHECK: declare void @_Z13def_copy_ctorv(%struct.copy_ctor* sret align 8)
// CHECK: declare void @_Z13def_copy_ctorv(%struct.copy_ctor* sret(%struct.copy_ctor) align 8)

struct __attribute__((aligned(16))) aligned_copy_ctor {
double d, e;
aligned_copy_ctor(aligned_copy_ctor const &);
};
test(aligned_copy_ctor);
// CHECK: define void @_Z7forward17aligned_copy_ctor(%struct.aligned_copy_ctor* noalias sret align 16 %{{.*}}, %struct.aligned_copy_ctor* nonnull %{{.*}})
// CHECK: define void @_Z7forward17aligned_copy_ctor(%struct.aligned_copy_ctor* noalias sret(%struct.aligned_copy_ctor) align 16 %{{.*}}, %struct.aligned_copy_ctor* nonnull %{{.*}})
//
// CHECK: declare %struct.aligned_copy_ctor* @_ZN17aligned_copy_ctorC1ERKS_(%struct.aligned_copy_ctor* returned, %struct.aligned_copy_ctor* nonnull align 16 dereferenceable(16))
//
// CHECK: define void @_Z22test_aligned_copy_ctorv()
// CHECK: %[[tmp:.*]] = alloca %struct.aligned_copy_ctor, align 16
// CHECK: call void @_Z21def_aligned_copy_ctorv(%struct.aligned_copy_ctor* nonnull sret align 16 %[[tmp]])
// CHECK: call void @_Z21def_aligned_copy_ctorv(%struct.aligned_copy_ctor* nonnull sret(%struct.aligned_copy_ctor) align 16 %[[tmp]])
// CHECK: call void @_Z3use17aligned_copy_ctor(%struct.aligned_copy_ctor* nonnull %[[tmp]])
// CHECK: ret void
//
// CHECK: declare void @_Z3use17aligned_copy_ctor(%struct.aligned_copy_ctor*)
// CHECK: declare void @_Z21def_aligned_copy_ctorv(%struct.aligned_copy_ctor* sret align 16)
// CHECK: declare void @_Z21def_aligned_copy_ctorv(%struct.aligned_copy_ctor* sret(%struct.aligned_copy_ctor) align 16)

struct empty {};
test(empty);
Expand Down
10 changes: 5 additions & 5 deletions clang/test/CodeGenCXX/x86_32-arguments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ struct S {
short s;
};

// CHECK-LABEL: define void @_Z1fv(%struct.S* noalias sret align 2 %
// CHECK-LABEL: define void @_Z1fv(%struct.S* noalias sret(%struct.S) align 2 %
S f() { return S(); }
// CHECK-LABEL: define void @_Z1f1S(%struct.S* %0)
void f(S) { }
Expand All @@ -18,10 +18,10 @@ class C {
double c;
};

// CHECK-LABEL: define void @_Z1gv(%class.C* noalias sret align 4 %
// CHECK-LABEL: define void @_Z1gv(%class.C* noalias sret(%class.C) align 4 %
C g() { return C(); }

// CHECK-LABEL: define void @_Z1f1C(%class.C* %0)
// CHECK-LABEL: define void @_Z1f1C(%class.C* %0)
void f(C) { }


Expand Down Expand Up @@ -103,13 +103,13 @@ struct s7_1 { double x; };
struct s7 : s7_0, s7_1 { };
s7 f7() { return s7(); }

// CHECK-LABEL: define void @_Z2f8v(%struct.s8* noalias sret align 4 %agg.result)
// CHECK-LABEL: define void @_Z2f8v(%struct.s8* noalias sret(%struct.s8) align 4 %agg.result)
struct s8_0 { };
struct s8_1 { double x; };
struct s8 { s8_0 a; s8_1 b; };
s8 f8() { return s8(); }

// CHECK-LABEL: define void @_Z2f9v(%struct.s9* noalias sret align 4 %agg.result)
// CHECK-LABEL: define void @_Z2f9v(%struct.s9* noalias sret(%struct.s9) align 4 %agg.result)
struct s9_0 { unsigned : 0; };
struct s9_1 { double x; };
struct s9 { s9_0 a; s9_1 b; };
Expand Down
12 changes: 6 additions & 6 deletions clang/test/CodeGenCXX/x86_64-arguments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,14 @@ namespace PR7742 { // Also rdar://8250764
struct s2 {
float a[2];
};

struct c2 : public s2 {};

// CHECK-LABEL: define <2 x float> @_ZN6PR77423fooEPNS_2c2E(%"struct.PR7742::c2"* %P)
c2 foo(c2 *P) {
return c2();
}

}

namespace PR5179 {
Expand Down Expand Up @@ -101,7 +101,7 @@ namespace test5 {
Empty empty;
Y f();
};
struct Y : public X {
struct Y : public X {
Empty empty;
};
X getX();
Expand Down Expand Up @@ -176,7 +176,7 @@ namespace test9 {
// CHECK: define void @_ZN5test93fooEPNS_1SEPNS_1TE([[S:%.*]]* %0, [[T:%.*]]* %1)
void foo(S*, T*) {}

// CHECK: define void @_ZN5test91aEiiiiNS_1TEPv([[S]]* noalias sret align 8 {{%.*}}, i32 %0, i32 %1, i32 %2, i32 %3, [[T]]* byval([[T]]) align 8 %4, i8* %5)
// CHECK: define void @_ZN5test91aEiiiiNS_1TEPv([[S]]* noalias sret([[S]]) align 8 {{%.*}}, i32 %0, i32 %1, i32 %2, i32 %3, [[T]]* byval([[T]]) align 8 %4, i8* %5)
S a(int, int, int, int, T, void*) {
return S();
}
Expand All @@ -186,7 +186,7 @@ namespace test9 {
return sret;
}

// CHECK: define void @_ZN5test91cEiiiNS_1TEPv([[S]]* noalias sret align 8 {{%.*}}, i32 %0, i32 %1, i32 %2, i8* {{%.*}}, i8* {{%.*}}, i8* %3)
// CHECK: define void @_ZN5test91cEiiiNS_1TEPv([[S]]* noalias sret([[S]]) align 8 {{%.*}}, i32 %0, i32 %1, i32 %2, i8* {{%.*}}, i8* {{%.*}}, i8* %3)
S c(int, int, int, T, void*) {
return S();
}
Expand Down
10 changes: 5 additions & 5 deletions clang/test/CodeGenCoroutines/coro-await.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ extern "C" void f1(int) {
// CHECK: %[[PROMISE:.+]] = alloca %"struct.std::experimental::coroutine_traits<void, int>::promise_type"
// CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin(
co_yield 42;
// CHECK: call void @_ZNSt12experimental16coroutine_traitsIJviEE12promise_type11yield_valueEi(%struct.suspend_maybe* sret align 4 %[[AWAITER:.+]], %"struct.std::experimental::coroutine_traits<void, int>::promise_type"* %[[PROMISE]], i32 42)
// CHECK: call void @_ZNSt12experimental16coroutine_traitsIJviEE12promise_type11yield_valueEi(%struct.suspend_maybe* sret(%struct.suspend_maybe) align 4 %[[AWAITER:.+]], %"struct.std::experimental::coroutine_traits<void, int>::promise_type"* %[[PROMISE]], i32 42)

// See if we need to suspend:
// --------------------------
Expand Down Expand Up @@ -197,20 +197,20 @@ extern "C" void UseAggr(Aggr&&);
extern "C" void TestAggr() {
UseAggr(co_await AggrAwaiter{});
Whatever();
// CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(%struct.Aggr* sret align 4 %[[AwaitResume:.+]],
// CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(%struct.Aggr* sret(%struct.Aggr) align 4 %[[AwaitResume:.+]],
// CHECK: call void @UseAggr(%struct.Aggr* nonnull align 4 dereferenceable(12) %[[AwaitResume]])
// CHECK: call void @_ZN4AggrD1Ev(%struct.Aggr* %[[AwaitResume]])
// CHECK: call void @Whatever()

co_await AggrAwaiter{};
Whatever();
// CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(%struct.Aggr* sret align 4 %[[AwaitResume2:.+]],
// CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(%struct.Aggr* sret(%struct.Aggr) align 4 %[[AwaitResume2:.+]],
// CHECK: call void @_ZN4AggrD1Ev(%struct.Aggr* %[[AwaitResume2]])
// CHECK: call void @Whatever()

Aggr Val = co_await AggrAwaiter{};
Whatever();
// CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(%struct.Aggr* sret align 4 %[[AwaitResume3:.+]],
// CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(%struct.Aggr* sret(%struct.Aggr) align 4 %[[AwaitResume3:.+]],
// CHECK: call void @Whatever()
// CHECK: call void @_ZN4AggrD1Ev(%struct.Aggr* %[[AwaitResume3]])
}
Expand Down Expand Up @@ -253,7 +253,7 @@ extern "C" void TestOpAwait() {

co_await MyAgg{};
// CHECK: call void @_ZN5MyAggawEv(%struct.MyAgg* %
// CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(%struct.Aggr* sret align 4 %
// CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(%struct.Aggr* sret(%struct.Aggr) align 4 %
}

// CHECK-LABEL: EndlessLoop(
Expand Down
10 changes: 5 additions & 5 deletions clang/test/CodeGenCoroutines/coro-gro-nrvo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ struct coro {
};

// Verify that the NRVO is applied to the Gro object.
// CHECK-LABEL: define void @_Z1fi(%struct.coro* noalias sret align 8 %agg.result, i32 %0)
// CHECK-LABEL: define void @_Z1fi(%struct.coro* noalias sret(%struct.coro) align 8 %agg.result, i32 %0)
coro f(int) {
// CHECK: %call = call noalias nonnull i8* @_Znwm(
// CHECK-NEXT: br label %[[CoroInit:.*]]

// CHECK: {{.*}}[[CoroInit]]:
// CHECK: store i1 false, i1* %gro.active
// CHECK: call void @{{.*get_return_objectEv}}(%struct.coro* sret align 8 %agg.result
// CHECK: call void @{{.*get_return_objectEv}}(%struct.coro* sret(%struct.coro) align 8 %agg.result
// CHECK-NEXT: store i1 true, i1* %gro.active
co_return;
}
Expand All @@ -65,20 +65,20 @@ struct coro_two {
};

// Verify that the NRVO is applied to the Gro object.
// CHECK-LABEL: define void @_Z1hi(%struct.coro_two* noalias sret align 8 %agg.result, i32 %0)
// CHECK-LABEL: define void @_Z1hi(%struct.coro_two* noalias sret(%struct.coro_two) align 8 %agg.result, i32 %0)
coro_two h(int) {

// CHECK: %call = call noalias i8* @_ZnwmRKSt9nothrow_t
// CHECK-NEXT: %[[CheckNull:.*]] = icmp ne i8* %call, null
// CHECK-NEXT: br i1 %[[CheckNull]], label %[[InitOnSuccess:.*]], label %[[InitOnFailure:.*]]

// CHECK: {{.*}}[[InitOnFailure]]:
// CHECK-NEXT: call void @{{.*get_return_object_on_allocation_failureEv}}(%struct.coro_two* sret align 8 %agg.result
// CHECK-NEXT: call void @{{.*get_return_object_on_allocation_failureEv}}(%struct.coro_two* sret(%struct.coro_two) align 8 %agg.result
// CHECK-NEXT: br label %[[RetLabel:.*]]

// CHECK: {{.*}}[[InitOnSuccess]]:
// CHECK: store i1 false, i1* %gro.active
// CHECK: call void @{{.*get_return_objectEv}}(%struct.coro_two* sret align 8 %agg.result
// CHECK: call void @{{.*get_return_objectEv}}(%struct.coro_two* sret(%struct.coro_two) align 8 %agg.result
// CHECK-NEXT: store i1 true, i1* %gro.active

// CHECK: [[RetLabel]]:
Expand Down
10 changes: 5 additions & 5 deletions clang/test/CodeGenObjC/arc.m
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ void test3() {
// Call to -initWith: with elided retain of consumed argument.
// CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_
// CHECK-NEXT: bitcast
// CHECK-NEXT: [[INIT:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*, i32)*)(i8*
// CHECK-NEXT: [[INIT:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*, i32)*)(i8*
// CHECK-NEXT: bitcast
// CHECK-NEXT: [[INIT:%.*]] = bitcast
// Assignment for initialization, retention elided.
Expand Down Expand Up @@ -1046,7 +1046,7 @@ - (id) test __attribute__((ns_returns_retained)) {
return test43_produce();
// CHECK: call i8* @test43_produce()
// CHECK-NEXT: notail call i8* @llvm.objc.retainAutoreleasedReturnValue(
// CHECK-NEXT: ret
// CHECK-NEXT: ret
}
@end

Expand Down Expand Up @@ -1440,7 +1440,7 @@ @implementation Person
@synthesize address;
@end
// CHECK: tail call i8* @objc_getProperty
// CHECK: call void @objc_setProperty
// CHECK: call void @objc_setProperty

// Verify that we successfully parse and preserve this attribute in
// this position.
Expand Down Expand Up @@ -1538,14 +1538,14 @@ void test70(id i) {
void test71(void) {
// CHECK: %[[T:[^ ]+]] = bitcast %struct.AggDtor* %[[TMP1:[^ ]+]] to i8*
// CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* %[[T]])
// CHECK: call void @getAggDtor(%struct.AggDtor* sret align 8 %[[TMP1]])
// CHECK: call void @getAggDtor(%struct.AggDtor* sret(%struct.AggDtor) align 8 %[[TMP1]])
// CHECK: %[[T:[^ ]+]] = bitcast %struct.AggDtor* %[[TMP1]] to i8**
// CHECK: call void @__destructor_8_s40(i8** %[[T]])
// CHECK: %[[T:[^ ]+]] = bitcast %struct.AggDtor* %[[TMP1:[^ ]+]] to i8*
// CHECK: call void @llvm.lifetime.end.p0i8({{[^,]+}}, i8* %[[T]])
// CHECK: %[[T:[^ ]+]] = bitcast %struct.AggDtor* %[[TMP2:[^ ]+]] to i8*
// CHECK: call void @llvm.lifetime.start.p0i8({{[^,]+}}, i8* %[[T]])
// CHECK: call void @getAggDtor(%struct.AggDtor* sret align 8 %[[TMP2]])
// CHECK: call void @getAggDtor(%struct.AggDtor* sret(%struct.AggDtor) align 8 %[[TMP2]])
// CHECK: %[[T:[^ ]+]] = bitcast %struct.AggDtor* %[[TMP2]] to i8**
// CHECK: call void @__destructor_8_s40(i8** %[[T]])
// CHECK: %[[T:[^ ]+]] = bitcast %struct.AggDtor* %[[TMP2:[^ ]+]] to i8*
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGenObjC/direct-method.m
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ + (struct my_complex_struct)classGetComplex __attribute__((objc_direct)) {

// CHECK-LABEL: define hidden void @"\01-[Root getAggregate]"(
- (struct my_aggregate_struct)getAggregate __attribute__((objc_direct)) {
// CHECK: %struct.my_aggregate_struct* noalias sret align 4 [[RETVAL:%[^,]*]],
// CHECK: %struct.my_aggregate_struct* noalias sret(%struct.my_aggregate_struct) align 4 [[RETVAL:%[^,]*]],

// loading parameters
// CHECK-LABEL: entry:
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGenObjC/nontrivial-c-struct-exception.m
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ void testStrongException(void) {
// CHECK: define void @testWeakException()
// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_WEAK]], align 8
// CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_WEAK]], align 8
// CHECK: call void @genWeak(%[[STRUCT_WEAK]]* sret align 8 %[[AGG_TMP]])
// CHECK: invoke void @genWeak(%[[STRUCT_WEAK]]* sret align 8 %[[AGG_TMP1]])
// CHECK: call void @genWeak(%[[STRUCT_WEAK]]* sret(%[[STRUCT_WEAK]]) align 8 %[[AGG_TMP]])
// CHECK: invoke void @genWeak(%[[STRUCT_WEAK]]* sret(%[[STRUCT_WEAK]]) align 8 %[[AGG_TMP1]])

// CHECK: call void @calleeWeak(%[[STRUCT_WEAK]]* %[[AGG_TMP]], %[[STRUCT_WEAK]]* %[[AGG_TMP1]])
// CHECK: ret void
Expand Down
6 changes: 3 additions & 3 deletions clang/test/CodeGenObjC/objc-non-trivial-struct-nrvo.m
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Trivial testTrivial(void) {

void func1(TrivialBig *);

// CHECK: define void @testTrivialBig(%[[STRUCT_TRIVIALBIG]]* noalias sret align 4 %[[AGG_RESULT:.*]])
// CHECK: define void @testTrivialBig(%[[STRUCT_TRIVIALBIG]]* noalias sret(%[[STRUCT_TRIVIALBIG]]) align 4 %[[AGG_RESULT:.*]])
// CHECK: call void @func1(%[[STRUCT_TRIVIALBIG]]* %[[AGG_RESULT]])
// CHECK-NEXT: ret void

Expand Down Expand Up @@ -69,7 +69,7 @@ Strong testStrong(void) {
return a;
}

// CHECK: define void @testWeak(%[[STRUCT_WEAK]]* noalias sret align 8 %[[AGG_RESULT:.*]])
// CHECK: define void @testWeak(%[[STRUCT_WEAK]]* noalias sret(%[[STRUCT_WEAK]]) align 8 %[[AGG_RESULT:.*]])
// CHECK: %[[NRVO:.*]] = alloca i1, align 1
// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_RESULT]] to i8**
// CHECK: call void @__default_constructor_8_w0(i8** %[[V0]])
Expand Down Expand Up @@ -105,7 +105,7 @@ Weak testWeak2(int c) {
return b;
}

// CHECK: define internal void @"\01-[C1 foo1]"(%[[STRUCT_WEAK]]* noalias sret align 8 %[[AGG_RESULT:.*]], %{{.*}}* %{{.*}}, i8* %{{.*}})
// CHECK: define internal void @"\01-[C1 foo1]"(%[[STRUCT_WEAK]]* noalias sret(%[[STRUCT_WEAK]]) align 8 %[[AGG_RESULT:.*]], %{{.*}}* %{{.*}}, i8* %{{.*}})
// CHECK: %[[NRVO:.*]] = alloca i1, align 1
// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_RESULT]] to i8**
// CHECK: call void @__default_constructor_8_w0(i8** %[[V0]])
Expand Down
8 changes: 4 additions & 4 deletions clang/test/CodeGenObjC/stret-1.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@ int main(int argc, const char **argv)
{
struct stret s;
s = [(id)(argc&~255) method];
// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (%struct.stret*, i8*, i8*)*)(%struct.stret* sret align 4 [[T0:%[^,]+]]
// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (%struct.stret*, i8*, i8*)*)(%struct.stret* sret(%struct.stret) align 4 [[T0:%[^,]+]]
// CHECK: [[T0P:%.*]] = bitcast %struct.stret* [[T0]] to i8*
// CHECK: call void @llvm.memset.p0i8.i64(i8* align 4 [[T0P]], i8 0, i64 400, i1 false)

s = [Test method];
// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (%struct.stret*, i8*, i8*)*)(%struct.stret* sret align 4 [[T1:%[^,]+]]
// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (%struct.stret*, i8*, i8*)*)(%struct.stret* sret(%struct.stret) align 4 [[T1:%[^,]+]]
// CHECK-NOT: call void @llvm.memset.p0i8.i64(

[(id)(argc&~255) method];
// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (%struct.stret*, i8*, i8*)*)(%struct.stret* sret align 4 [[T1:%[^,]+]]
// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (%struct.stret*, i8*, i8*)*)(%struct.stret* sret(%struct.stret) align 4 [[T1:%[^,]+]]
// CHECK-NOT: call void @llvm.memset.p0i8.i64(

[Test method];
// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (%struct.stret*, i8*, i8*)*)(%struct.stret* sret align 4 [[T1:%[^,]+]]
// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (%struct.stret*, i8*, i8*)*)(%struct.stret* sret(%struct.stret) align 4 [[T1:%[^,]+]]
// CHECK-NOT: call void @llvm.memset.p0i8.i64(
}
4 changes: 2 additions & 2 deletions clang/test/CodeGenObjC/stret_lookup.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ void test0(void) {
// HASSTRET-LABEL: define void @test0()
// HASSTRET: [[T0:%.*]] = call i8* (i8*, i8*, ...)* @objc_msg_lookup_stret(i8* bitcast (i64* @_OBJC_CLASS_Test0 to i8*),
// HASSTRET-NEXT: [[T1:%.*]] = bitcast i8* (i8*, i8*, ...)* [[T0]] to void (%struct.test*, i8*, i8*)*
// HASSTRET-NEXT: call void [[T1]](%struct.test* sret {{.*}}, i8* bitcast (i64* @_OBJC_CLASS_Test0 to i8*),
// HASSTRET-NEXT: call void [[T1]](%struct.test* sret(%struct.test) {{.*}}, i8* bitcast (i64* @_OBJC_CLASS_Test0 to i8*),

// NOSTRET-LABEL: define void @test0()
// NOSTRET: [[T0:%.*]] = call i8* (i8*, i8*, ...)* @objc_msg_lookup(i8*
// NOSTRET-NEXT: [[T1:%.*]] = bitcast i8* (i8*, i8*, ...)* [[T0]] to void (%struct.test*, i8*, i8*)*
// NOSTRET-NEXT: call void [[T1]](%struct.test* sret {{.*}}, i8* {{.*}}, i8* bitcast ([2 x { i8*, i8* }]*
// NOSTRET-NEXT: call void [[T1]](%struct.test* sret(%struct.test) {{.*}}, i8* {{.*}}, i8* bitcast ([2 x { i8*, i8* }]*
2 changes: 1 addition & 1 deletion clang/test/CodeGenObjC/weak-in-c-struct.m
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ void test_argument_Weak(Weak *a) {
calleeWeak(*a);
}

// COMMON: define void @test_return_Weak(%[[STRUCT_WEAK]]* noalias sret align {{.*}} %[[AGG_RESULT:.*]], %[[STRUCT_WEAK]]* %[[A:.*]])
// COMMON: define void @test_return_Weak(%[[STRUCT_WEAK]]* noalias sret(%[[STRUCT_WEAK]]) align {{.*}} %[[AGG_RESULT:.*]], %[[STRUCT_WEAK]]* %[[A:.*]])
// COMMON: %[[A_ADDR:.*]] = alloca %[[STRUCT_WEAK]]*
// COMMON: store %[[STRUCT_WEAK]]* %[[A]], %[[STRUCT_WEAK]]** %[[A_ADDR]]
// COMMON: %[[V0:.*]] = load %[[STRUCT_WEAK]]*, %[[STRUCT_WEAK]]** %[[A_ADDR]]
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGenObjCXX/objc-struct-cxx-abi.mm
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ void testCallStrongWeak(StrongWeak *a) {
testParamStrongWeak(*a);
}

// CHECK: define void @_Z20testReturnStrongWeakP10StrongWeak(%[[STRUCT_STRONGWEAK:.*]]* noalias sret align 8 %[[AGG_RESULT:.*]], %[[STRUCT_STRONGWEAK]]* %[[A:.*]])
// CHECK: define void @_Z20testReturnStrongWeakP10StrongWeak(%[[STRUCT_STRONGWEAK:.*]]* noalias sret(%[[STRUCT_STRONGWEAK]]) align 8 %[[AGG_RESULT:.*]], %[[STRUCT_STRONGWEAK]]* %[[A:.*]])
// CHECK: %[[A_ADDR:.*]] = alloca %[[STRUCT_STRONGWEAK]]*, align 8
// CHECK: store %[[STRUCT_STRONGWEAK]]* %[[A]], %[[STRUCT_STRONGWEAK]]** %[[A_ADDR]], align 8
// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONGWEAK]]*, %[[STRUCT_STRONGWEAK]]** %[[A_ADDR]], align 8
Expand Down
6 changes: 3 additions & 3 deletions clang/test/CodeGenOpenCL/addr-space-struct-arg.cl
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ struct LargeStructTwoMember {
struct LargeStructOneMember g_s;
#endif

// X86-LABEL: define void @foo(%struct.Mat4X4* noalias sret align 4 %agg.result, %struct.Mat3X3* byval(%struct.Mat3X3) align 4 %in)
// X86-LABEL: define void @foo(%struct.Mat4X4* noalias sret(%struct.Mat4X4) align 4 %agg.result, %struct.Mat3X3* byval(%struct.Mat3X3) align 4 %in)
// AMDGCN-LABEL: define %struct.Mat4X4 @foo([9 x i32] %in.coerce)
Mat4X4 __attribute__((noinline)) foo(Mat3X3 in) {
Mat4X4 out;
Expand All @@ -63,8 +63,8 @@ kernel void ker(global Mat3X3 *in, global Mat4X4 *out) {
out[0] = foo(in[1]);
}

// X86-LABEL: define void @foo_large(%struct.Mat64X64* noalias sret align 4 %agg.result, %struct.Mat32X32* byval(%struct.Mat32X32) align 4 %in)
// AMDGCN-LABEL: define void @foo_large(%struct.Mat64X64 addrspace(5)* noalias sret align 4 %agg.result, %struct.Mat32X32 addrspace(5)* byval(%struct.Mat32X32) align 4 %in)
// X86-LABEL: define void @foo_large(%struct.Mat64X64* noalias sret(%struct.Mat64X64) align 4 %agg.result, %struct.Mat32X32* byval(%struct.Mat32X32) align 4 %in)
// AMDGCN-LABEL: define void @foo_large(%struct.Mat64X64 addrspace(5)* noalias sret(%struct.Mat64X64) align 4 %agg.result, %struct.Mat32X32 addrspace(5)* byval(%struct.Mat32X32) align 4 %in)
Mat64X64 __attribute__((noinline)) foo_large(Mat32X32 in) {
Mat64X64 out;
return out;
Expand Down
6 changes: 3 additions & 3 deletions clang/test/CodeGenOpenCL/amdgpu-abi-struct-coerce.cl
Original file line number Diff line number Diff line change
Expand Up @@ -403,14 +403,14 @@ struct_arr16 func_ret_struct_arr16()
return s;
}

// CHECK: define void @func_ret_struct_arr32(%struct.struct_arr32 addrspace(5)* noalias nocapture sret align 4 %agg.result)
// CHECK: define void @func_ret_struct_arr32(%struct.struct_arr32 addrspace(5)* noalias nocapture sret(%struct.struct_arr32) align 4 %agg.result)
struct_arr32 func_ret_struct_arr32()
{
struct_arr32 s = { 0 };
return s;
}

// CHECK: define void @func_ret_struct_arr33(%struct.struct_arr33 addrspace(5)* noalias nocapture sret align 4 %agg.result)
// CHECK: define void @func_ret_struct_arr33(%struct.struct_arr33 addrspace(5)* noalias nocapture sret(%struct.struct_arr33) align 4 %agg.result)
struct_arr33 func_ret_struct_arr33()
{
struct_arr33 s = { 0 };
Expand Down Expand Up @@ -439,7 +439,7 @@ different_size_type_pair func_different_size_type_pair_ret()
return s;
}

// CHECK: define void @func_flexible_array_ret(%struct.flexible_array addrspace(5)* noalias nocapture sret align 4 %agg.result)
// CHECK: define void @func_flexible_array_ret(%struct.flexible_array addrspace(5)* noalias nocapture sret(%struct.flexible_array) align 4 %agg.result)
flexible_array func_flexible_array_ret()
{
flexible_array s = { 0 };
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGenOpenCLCXX/addrspace-of-this.cl
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ __kernel void test__global() {
// Test the address space of 'this' when invoking the operator+
// COMMON: [[C1GEN:%[.a-z0-9]+]] = addrspacecast %class.C* %c1 to %class.C addrspace(4)*
// COMMON: [[C2GEN:%[.a-z0-9]+]] = addrspacecast %class.C* %c2 to %class.C addrspace(4)*
// COMMON: call spir_func void @_ZNU3AS41CplERU3AS4KS_(%class.C* sret align 4 %c3, %class.C addrspace(4)* [[C1GEN]], %class.C addrspace(4)* align 4 dereferenceable(4) [[C2GEN]])
// COMMON: call spir_func void @_ZNU3AS41CplERU3AS4KS_(%class.C* sret(%class.C) align 4 %c3, %class.C addrspace(4)* [[C1GEN]], %class.C addrspace(4)* align 4 dereferenceable(4) [[C2GEN]])

// Test the address space of 'this' when invoking the move constructor
// COMMON: [[C4GEN:%[.a-z0-9]+]] = addrspacecast %class.C* %c4 to %class.C addrspace(4)*
Expand All @@ -134,7 +134,7 @@ __kernel void test__global() {

// Tests address space of inline members
//COMMON: @_ZNU3AS41C3getEv(%class.C addrspace(4)* %this)
//COMMON: @_ZNU3AS41CplERU3AS4KS_(%class.C* noalias sret align 4 %agg.result, %class.C addrspace(4)* %this
//COMMON: @_ZNU3AS41CplERU3AS4KS_(%class.C* noalias sret(%class.C) align 4 %agg.result, %class.C addrspace(4)* %this
#define TEST(AS) \
__kernel void test##AS() { \
AS C c; \
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Modules/templates.mm
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ void testWithAttributes() {

// Check that returnNonTrivial doesn't return Class0<S0> directly in registers.

// CHECK: declare void @_Z16returnNonTrivialv(%struct.Class0* sret align 8)
// CHECK: declare void @_Z16returnNonTrivialv(%struct.Class0* sret(%struct.Class0) align 8)

@import template_nontrivial0;
@import template_nontrivial1;
Expand Down
10 changes: 7 additions & 3 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1057,8 +1057,8 @@ Currently, only the following parameter attributes are defined:
``byval`` parameters). This is not a valid attribute for return
values.

The byval attribute also supports an optional type argument, which must be
the same as the pointee type of the argument.
The byval attribute also supports an optional type argument, which
must be the same as the pointee type of the argument.

The byval attribute also supports specifying an alignment with the
align attribute. It indicates the alignment of the stack slot to
Expand Down Expand Up @@ -1144,14 +1144,18 @@ Currently, only the following parameter attributes are defined:
See :doc:`InAlloca` for more information on how to use this
attribute.

``sret``
``sret`` or ``sret(<ty>)``
This indicates that the pointer parameter specifies the address of a
structure that is the return value of the function in the source
program. This pointer must be guaranteed by the caller to be valid:
loads and stores to the structure may be assumed by the callee not
to trap and to be properly aligned. This is not a valid attribute
for return values.

The sret attribute also supports an optional type argument, which
must be the same as the pointee type of the argument. In the
future this will be required.

.. _attr_align:

``align <n>`` or ``align(<n>)``
Expand Down
3 changes: 3 additions & 0 deletions llvm/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ Changes to the LLVM IR
* Added the ``byref`` attribute to better represent argument passing
for the `amdgpu_kernel` calling convention.

* Added type parameter to the ``sret`` attribute to continue work on
removing pointer element types.

Changes to building LLVM
------------------------

Expand Down
12 changes: 12 additions & 0 deletions llvm/include/llvm/IR/Attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ class Attribute {
unsigned ElemSizeArg,
const Optional<unsigned> &NumElemsArg);
static Attribute getWithByValType(LLVMContext &Context, Type *Ty);
static Attribute getWithStructRetType(LLVMContext &Context, Type *Ty);
static Attribute getWithByRefType(LLVMContext &Context, Type *Ty);
static Attribute getWithPreallocatedType(LLVMContext &Context, Type *Ty);

Expand Down Expand Up @@ -307,6 +308,7 @@ class AttributeSet {
uint64_t getDereferenceableBytes() const;
uint64_t getDereferenceableOrNullBytes() const;
Type *getByValType() const;
Type *getStructRetType() const;
Type *getByRefType() const;
Type *getPreallocatedType() const;
std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
Expand Down Expand Up @@ -631,6 +633,9 @@ class AttributeList {
/// Return the byval type for the specified function parameter.
Type *getParamByValType(unsigned ArgNo) const;

/// Return the sret type for the specified function parameter.
Type *getParamStructRetType(unsigned ArgNo) const;

/// Return the byref type for the specified function parameter.
Type *getParamByRefType(unsigned ArgNo) const;

Expand Down Expand Up @@ -737,6 +742,7 @@ class AttrBuilder {
uint64_t DerefOrNullBytes = 0;
uint64_t AllocSizeArgs = 0;
Type *ByValType = nullptr;
Type *StructRetType = nullptr;
Type *ByRefType = nullptr;
Type *PreallocatedType = nullptr;

Expand Down Expand Up @@ -824,6 +830,9 @@ class AttrBuilder {
/// Retrieve the byval type.
Type *getByValType() const { return ByValType; }

/// Retrieve the sret type.
Type *getStructRetType() const { return StructRetType; }

/// Retrieve the byref type.
Type *getByRefType() const { return ByRefType; }

Expand Down Expand Up @@ -873,6 +882,9 @@ class AttrBuilder {
/// This turns a byval type into the form used internally in Attribute.
AttrBuilder &addByValAttr(Type *Ty);

/// This turns a sret type into the form used internally in Attribute.
AttrBuilder &addStructRetAttr(Type *Ty);

/// This turns a byref type into the form used internally in Attribute.
AttrBuilder &addByRefAttr(Type *Ty);

Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/IR/Attributes.td
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ def StackProtectStrong : EnumAttr<"sspstrong">;
def StrictFP : EnumAttr<"strictfp">;

/// Hidden pointer to structure to return.
def StructRet : EnumAttr<"sret">;
def StructRet : TypeAttr<"sret">;

/// AddressSanitizer is on.
def SanitizeAddress : EnumAttr<"sanitize_address">;
Expand Down
4 changes: 2 additions & 2 deletions llvm/include/llvm/IR/Function.h
Original file line number Diff line number Diff line change
Expand Up @@ -474,8 +474,8 @@ class Function : public GlobalObject, public ilist_node<Function> {

/// Extract the sret type for a parameter.
Type *getParamStructRetType(unsigned ArgNo) const {
// FIXME: Add type to attribute like byval
return (arg_begin() + ArgNo)->getType()->getPointerElementType();
Type *Ty = AttributeSets.getParamStructRetType(ArgNo);
return Ty ? Ty : (arg_begin() + ArgNo)->getType()->getPointerElementType();
}

/// Extract the byref type for a parameter.
Expand Down
14 changes: 10 additions & 4 deletions llvm/lib/AsmParser/LLParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1657,11 +1657,18 @@ bool LLParser::ParseOptionalParamAttrs(AttrBuilder &B) {
}
case lltok::kw_byval: {
Type *Ty;
if (ParseByValWithOptionalType(Ty))
if (ParseOptionalTypeAttr(Ty, lltok::kw_byval))
return true;
B.addByValAttr(Ty);
continue;
}
case lltok::kw_sret: {
Type *Ty;
if (ParseOptionalTypeAttr(Ty, lltok::kw_sret))
return true;
B.addStructRetAttr(Ty);
continue;
}
case lltok::kw_preallocated: {
Type *Ty;
if (ParsePreallocated(Ty))
Expand Down Expand Up @@ -1704,7 +1711,6 @@ bool LLParser::ParseOptionalParamAttrs(AttrBuilder &B) {
case lltok::kw_readonly: B.addAttribute(Attribute::ReadOnly); break;
case lltok::kw_returned: B.addAttribute(Attribute::Returned); break;
case lltok::kw_signext: B.addAttribute(Attribute::SExt); break;
case lltok::kw_sret: B.addAttribute(Attribute::StructRet); break;
case lltok::kw_swifterror: B.addAttribute(Attribute::SwiftError); break;
case lltok::kw_swiftself: B.addAttribute(Attribute::SwiftSelf); break;
case lltok::kw_writeonly: B.addAttribute(Attribute::WriteOnly); break;
Expand Down Expand Up @@ -2571,9 +2577,9 @@ bool LLParser::ParseParameterList(SmallVectorImpl<ParamInfo> &ArgList,
/// ParseByValWithOptionalType
/// ::= byval
/// ::= byval(<ty>)
bool LLParser::ParseByValWithOptionalType(Type *&Result) {
bool LLParser::ParseOptionalTypeAttr(Type *&Result, lltok::Kind AttrName) {
Result = nullptr;
if (!EatIfPresent(lltok::kw_byval))
if (!EatIfPresent(AttrName))
return true;
if (!EatIfPresent(lltok::lparen))
return false;
Expand Down
3 changes: 1 addition & 2 deletions llvm/lib/AsmParser/LLParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -332,8 +332,7 @@ namespace llvm {
bool ParseFnAttributeValuePairs(AttrBuilder &B,
std::vector<unsigned> &FwdRefAttrGrps,
bool inAttrGrp, LocTy &BuiltinLoc);
bool ParseByValWithOptionalType(Type *&Result);

bool ParseOptionalTypeAttr(Type *&Result, lltok::Kind AttrName);
bool ParseRequiredTypeAttr(Type *&Result, lltok::Kind AttrName);
bool ParsePreallocated(Type *&Result);
bool ParseByRef(Type *&Result);
Expand Down
61 changes: 39 additions & 22 deletions llvm/lib/Bitcode/Reader/BitcodeReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -717,9 +717,9 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer {
return getFnValueByID(ValNo, Ty);
}

/// Upgrades old-style typeless byval attributes by adding the corresponding
/// argument's pointee type.
void propagateByValTypes(CallBase *CB, ArrayRef<Type *> ArgsFullTys);
/// Upgrades old-style typeless byval or sret attributes by adding the
/// corresponding argument's pointee type.
void propagateByValSRetTypes(CallBase *CB, ArrayRef<Type *> ArgsFullTys);

/// Converts alignment exponent (i.e. power of two (or zero)) to the
/// corresponding alignment to use. If alignment is too large, returns
Expand Down Expand Up @@ -1611,6 +1611,8 @@ Error BitcodeReader::parseAttributeGroupBlock() {
// this AttributeList with a function.
if (Kind == Attribute::ByVal)
B.addByValAttr(nullptr);
else if (Kind == Attribute::StructRet)
B.addStructRetAttr(nullptr);

B.addAttribute(Kind);
} else if (Record[i] == 1) { // Integer attribute
Expand Down Expand Up @@ -1654,6 +1656,8 @@ Error BitcodeReader::parseAttributeGroupBlock() {
return Err;
if (Kind == Attribute::ByVal) {
B.addByValAttr(HasType ? getTypeByID(Record[++i]) : nullptr);
} else if (Kind == Attribute::StructRet) {
B.addStructRetAttr(HasType ? getTypeByID(Record[++i]) : nullptr);
} else if (Kind == Attribute::ByRef) {
B.addByRefAttr(getTypeByID(Record[++i]));
} else if (Kind == Attribute::Preallocated) {
Expand Down Expand Up @@ -3288,17 +3292,24 @@ Error BitcodeReader::parseFunctionRecord(ArrayRef<uint64_t> Record) {
Func->setLinkage(getDecodedLinkage(RawLinkage));
Func->setAttributes(getAttributes(Record[4]));

// Upgrade any old-style byval without a type by propagating the argument's
// pointee type. There should be no opaque pointers where the byval type is
// implicit.
// Upgrade any old-style byval or sret without a type by propagating the
// argument's pointee type. There should be no opaque pointers where the byval
// type is implicit.
for (unsigned i = 0; i != Func->arg_size(); ++i) {
if (!Func->hasParamAttribute(i, Attribute::ByVal))
continue;
for (Attribute::AttrKind Kind : {Attribute::ByVal, Attribute::StructRet}) {
if (!Func->hasParamAttribute(i, Kind))
continue;

Type *PTy = cast<FunctionType>(FullFTy)->getParamType(i);
Func->removeParamAttr(i, Attribute::ByVal);
Func->addParamAttr(i, Attribute::getWithByValType(
Context, getPointerElementFlatType(PTy)));
Func->removeParamAttr(i, Kind);

Type *PTy = cast<FunctionType>(FullFTy)->getParamType(i);
Type *PtrEltTy = getPointerElementFlatType(PTy);
Attribute NewAttr =
Kind == Attribute::ByVal
? Attribute::getWithByValType(Context, PtrEltTy)
: Attribute::getWithStructRetType(Context, PtrEltTy);
Func->addParamAttr(i, NewAttr);
}
}

MaybeAlign Alignment;
Expand Down Expand Up @@ -3759,16 +3770,22 @@ Error BitcodeReader::typeCheckLoadStoreInst(Type *ValType, Type *PtrType) {
return Error::success();
}

void BitcodeReader::propagateByValTypes(CallBase *CB,
ArrayRef<Type *> ArgsFullTys) {
void BitcodeReader::propagateByValSRetTypes(CallBase *CB,
ArrayRef<Type *> ArgsFullTys) {
for (unsigned i = 0; i != CB->arg_size(); ++i) {
if (!CB->paramHasAttr(i, Attribute::ByVal))
continue;
for (Attribute::AttrKind Kind : {Attribute::ByVal, Attribute::StructRet}) {
if (!CB->paramHasAttr(i, Kind))
continue;

CB->removeParamAttr(i, Attribute::ByVal);
CB->addParamAttr(
i, Attribute::getWithByValType(
Context, getPointerElementFlatType(ArgsFullTys[i])));
CB->removeParamAttr(i, Kind);

Type *PtrEltTy = getPointerElementFlatType(ArgsFullTys[i]);
Attribute NewAttr =
Kind == Attribute::ByVal
? Attribute::getWithByValType(Context, PtrEltTy)
: Attribute::getWithStructRetType(Context, PtrEltTy);
CB->addParamAttr(i, NewAttr);
}
}
}

Expand Down Expand Up @@ -4620,7 +4637,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
cast<InvokeInst>(I)->setCallingConv(
static_cast<CallingConv::ID>(CallingConv::MaxID & CCInfo));
cast<InvokeInst>(I)->setAttributes(PAL);
propagateByValTypes(cast<CallBase>(I), ArgsFullTys);
propagateByValSRetTypes(cast<CallBase>(I), ArgsFullTys);

break;
}
Expand Down Expand Up @@ -5227,7 +5244,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
TCK = CallInst::TCK_NoTail;
cast<CallInst>(I)->setTailCallKind(TCK);
cast<CallInst>(I)->setAttributes(PAL);
propagateByValTypes(cast<CallBase>(I), ArgsFullTys);
propagateByValSRetTypes(cast<CallBase>(I), ArgsFullTys);
if (FMF.any()) {
if (!isa<FPMathOperator>(I))
return error("Fast-math-flags specified for call without "
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/IR/AsmWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4288,12 +4288,15 @@ void AssemblyWriter::writeAttribute(const Attribute &Attr, bool InAttrGroup) {
}

assert((Attr.hasAttribute(Attribute::ByVal) ||
Attr.hasAttribute(Attribute::StructRet) ||
Attr.hasAttribute(Attribute::ByRef) ||
Attr.hasAttribute(Attribute::Preallocated)) &&
"unexpected type attr");

if (Attr.hasAttribute(Attribute::ByVal)) {
Out << "byval";
} else if (Attr.hasAttribute(Attribute::StructRet)) {
Out << "sret";
} else if (Attr.hasAttribute(Attribute::ByRef)) {
Out << "byref";
} else {
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/IR/AttributeImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ class AttributeSetNode final
std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
std::string getAsString(bool InAttrGrp) const;
Type *getByValType() const;
Type *getStructRetType() const;
Type *getByRefType() const;
Type *getPreallocatedType() const;

Expand Down
50 changes: 44 additions & 6 deletions llvm/lib/IR/Attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@ Attribute Attribute::getWithByValType(LLVMContext &Context, Type *Ty) {
return get(Context, ByVal, Ty);
}

Attribute Attribute::getWithStructRetType(LLVMContext &Context, Type *Ty) {
return get(Context, StructRet, Ty);
}

Attribute Attribute::getWithByRefType(LLVMContext &Context, Type *Ty) {
return get(Context, ByRef, Ty);
}
Expand Down Expand Up @@ -433,8 +437,6 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
return "shadowcallstack";
if (hasAttribute(Attribute::StrictFP))
return "strictfp";
if (hasAttribute(Attribute::StructRet))
return "sret";
if (hasAttribute(Attribute::SanitizeThread))
return "sanitize_thread";
if (hasAttribute(Attribute::SanitizeMemory))
Expand All @@ -450,9 +452,10 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
if (hasAttribute(Attribute::NoUndef))
return "noundef";

if (hasAttribute(Attribute::ByVal)) {
const bool IsByVal = hasAttribute(Attribute::ByVal);
if (IsByVal || hasAttribute(Attribute::StructRet)) {
std::string Result;
Result += "byval";
Result += IsByVal ? "byval" : "sret";
if (Type *Ty = getValueAsType()) {
raw_string_ostream OS(Result);
Result += '(';
Expand Down Expand Up @@ -754,6 +757,10 @@ Type *AttributeSet::getByValType() const {
return SetNode ? SetNode->getByValType() : nullptr;
}

Type *AttributeSet::getStructRetType() const {
return SetNode ? SetNode->getStructRetType() : nullptr;
}

Type *AttributeSet::getPreallocatedType() const {
return SetNode ? SetNode->getPreallocatedType() : nullptr;
}
Expand Down Expand Up @@ -850,6 +857,9 @@ AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
case Attribute::ByVal:
Attr = Attribute::getWithByValType(C, B.getByValType());
break;
case Attribute::StructRet:
Attr = Attribute::getWithStructRetType(C, B.getStructRetType());
break;
case Attribute::ByRef:
Attr = Attribute::getWithByRefType(C, B.getByRefType());
break;
Expand Down Expand Up @@ -939,6 +949,12 @@ Type *AttributeSetNode::getByValType() const {
return nullptr;
}

Type *AttributeSetNode::getStructRetType() const {
if (auto A = findEnumAttribute(Attribute::StructRet))
return A->getValueAsType();
return nullptr;
}

Type *AttributeSetNode::getByRefType() const {
if (auto A = findEnumAttribute(Attribute::ByRef))
return A->getValueAsType();
Expand Down Expand Up @@ -1466,6 +1482,10 @@ Type *AttributeList::getParamByValType(unsigned Index) const {
return getAttributes(Index+FirstArgIndex).getByValType();
}

Type *AttributeList::getParamStructRetType(unsigned Index) const {
return getAttributes(Index + FirstArgIndex).getStructRetType();
}

Type *AttributeList::getParamByRefType(unsigned Index) const {
return getAttributes(Index + FirstArgIndex).getByRefType();
}
Expand Down Expand Up @@ -1555,6 +1575,7 @@ void AttrBuilder::clear() {
DerefBytes = DerefOrNullBytes = 0;
AllocSizeArgs = 0;
ByValType = nullptr;
StructRetType = nullptr;
ByRefType = nullptr;
PreallocatedType = nullptr;
}
Expand All @@ -1574,6 +1595,8 @@ AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
StackAlignment = Attr.getStackAlignment();
else if (Kind == Attribute::ByVal)
ByValType = Attr.getValueAsType();
else if (Kind == Attribute::StructRet)
StructRetType = Attr.getValueAsType();
else if (Kind == Attribute::ByRef)
ByRefType = Attr.getValueAsType();
else if (Kind == Attribute::Preallocated)
Expand Down Expand Up @@ -1602,6 +1625,8 @@ AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
StackAlignment.reset();
else if (Val == Attribute::ByVal)
ByValType = nullptr;
else if (Val == Attribute::StructRet)
StructRetType = nullptr;
else if (Val == Attribute::ByRef)
ByRefType = nullptr;
else if (Val == Attribute::Preallocated)
Expand Down Expand Up @@ -1694,6 +1719,12 @@ AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {
return *this;
}

AttrBuilder &AttrBuilder::addStructRetAttr(Type *Ty) {
Attrs[Attribute::StructRet] = true;
StructRetType = Ty;
return *this;
}

AttrBuilder &AttrBuilder::addByRefAttr(Type *Ty) {
Attrs[Attribute::ByRef] = true;
ByRefType = Ty;
Expand Down Expand Up @@ -1726,6 +1757,9 @@ AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
if (!ByValType)
ByValType = B.ByValType;

if (!StructRetType)
StructRetType = B.StructRetType;

if (!ByRefType)
ByRefType = B.ByRefType;

Expand Down Expand Up @@ -1760,6 +1794,9 @@ AttrBuilder &AttrBuilder::remove(const AttrBuilder &B) {
if (B.ByValType)
ByValType = nullptr;

if (B.StructRetType)
StructRetType = nullptr;

if (B.ByRefType)
ByRefType = nullptr;

Expand Down Expand Up @@ -1826,7 +1863,8 @@ bool AttrBuilder::operator==(const AttrBuilder &B) {

return Alignment == B.Alignment && StackAlignment == B.StackAlignment &&
DerefBytes == B.DerefBytes && ByValType == B.ByValType &&
ByRefType == B.ByRefType && PreallocatedType == B.PreallocatedType;
StructRetType == B.StructRetType && ByRefType == B.ByRefType &&
PreallocatedType == B.PreallocatedType;
}

//===----------------------------------------------------------------------===//
Expand All @@ -1852,10 +1890,10 @@ AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) {
.addDereferenceableOrNullAttr(1) // the int here is ignored
.addAttribute(Attribute::ReadNone)
.addAttribute(Attribute::ReadOnly)
.addAttribute(Attribute::StructRet)
.addAttribute(Attribute::InAlloca)
.addPreallocatedAttr(Ty)
.addByValAttr(Ty)
.addStructRetAttr(Ty)
.addByRefAttr(Ty);

return Incompatible;
Expand Down
43 changes: 43 additions & 0 deletions llvm/test/Assembler/sret-type-attr.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s

; CHECK: define void @foo(i32* sret(i32) align 4 %0)
define void @foo(i32* sret(i32) align 4 %0) {
ret void
}

; CHECK: define void @bar({ i32*, i8 }* sret({ i32*, i8 }) align 4 %0)
define void @bar({i32*, i8}* sret({i32*, i8}) align 4 %0) {
ret void
}

define void @caller({ i32*, i8 }* %ptr) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
; CHECK: call void @bar({ i32*, i8 }* sret({ i32*, i8 }) %ptr)
; CHECK: invoke void @bar({ i32*, i8 }* sret({ i32*, i8 }) %ptr)
call void @bar({i32*, i8}* sret %ptr)
invoke void @bar({i32*, i8}* sret %ptr) to label %success unwind label %fail

success:
ret void

fail:
landingpad { i8*, i32 } cleanup
ret void
}

; CHECK: declare void @baz([8 x i8]* sret([8 x i8]))
%named_type = type [8 x i8]
declare void @baz(%named_type* sret(%named_type))

declare i32 @__gxx_personality_v0(...)

%0 = type opaque

; CHECK: define void @anon({ %0* }* sret({ %0* }) %arg)
; CHECK: call void @anon_callee({ %0* }* sret({ %0* }) %arg)
define void @anon({ %0* }* sret({ %0* }) %arg) {
call void @anon_callee({ %0* }* sret({ %0* }) %arg)
ret void
}

; CHECK: declare void @anon_callee({ %0* }* sret({ %0* }))
declare void @anon_callee({ %0* }* sret({ %0* }))
2 changes: 1 addition & 1 deletion llvm/test/Bitcode/attributes-3.3.ll
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ define void @f4(i8 inreg %0)
}

define void @f5(i8* sret %0)
; CHECK: define void @f5(i8* sret %0)
; CHECK: define void @f5(i8* sret(i8) %0)
{
ret void;
}
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Bitcode/attributes.ll
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ define void @f4(i8 inreg %0)
}

define void @f5(i8* sret %0)
; CHECK: define void @f5(i8* sret %0)
; CHECK: define void @f5(i8* sret(i8) %0)
{
ret void;
}
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Bitcode/compatibility-3.6.ll
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ declare void @f.param.byval({ i8, i8 }* byval)
declare void @f.param.inalloca(i8* inalloca)
; CHECK: declare void @f.param.inalloca(i8* inalloca)
declare void @f.param.sret(i8* sret)
; CHECK: declare void @f.param.sret(i8* sret)
; CHECK: declare void @f.param.sret(i8* sret(i8))
declare void @f.param.noalias(i8* noalias)
; CHECK: declare void @f.param.noalias(i8* noalias)
declare void @f.param.nocapture(i8* nocapture)
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Bitcode/compatibility-3.7.ll
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ declare void @f.param.byval({ i8, i8 }* byval)
declare void @f.param.inalloca(i8* inalloca)
; CHECK: declare void @f.param.inalloca(i8* inalloca)
declare void @f.param.sret(i8* sret)
; CHECK: declare void @f.param.sret(i8* sret)
; CHECK: declare void @f.param.sret(i8* sret(i8))
declare void @f.param.noalias(i8* noalias)
; CHECK: declare void @f.param.noalias(i8* noalias)
declare void @f.param.nocapture(i8* nocapture)
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Bitcode/compatibility-3.8.ll
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ declare void @f.param.byval({ i8, i8 }* byval)
declare void @f.param.inalloca(i8* inalloca)
; CHECK: declare void @f.param.inalloca(i8* inalloca)
declare void @f.param.sret(i8* sret)
; CHECK: declare void @f.param.sret(i8* sret)
; CHECK: declare void @f.param.sret(i8* sret(i8))
declare void @f.param.noalias(i8* noalias)
; CHECK: declare void @f.param.noalias(i8* noalias)
declare void @f.param.nocapture(i8* nocapture)
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Bitcode/compatibility-3.9.ll
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ declare void @f.param.byval({ i8, i8 }* byval)
declare void @f.param.inalloca(i8* inalloca)
; CHECK: declare void @f.param.inalloca(i8* inalloca)
declare void @f.param.sret(i8* sret)
; CHECK: declare void @f.param.sret(i8* sret)
; CHECK: declare void @f.param.sret(i8* sret(i8))
declare void @f.param.noalias(i8* noalias)
; CHECK: declare void @f.param.noalias(i8* noalias)
declare void @f.param.nocapture(i8* nocapture)
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Bitcode/compatibility-4.0.ll
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ declare void @f.param.byval({ i8, i8 }* byval)
declare void @f.param.inalloca(i8* inalloca)
; CHECK: declare void @f.param.inalloca(i8* inalloca)
declare void @f.param.sret(i8* sret)
; CHECK: declare void @f.param.sret(i8* sret)
; CHECK: declare void @f.param.sret(i8* sret(i8))
declare void @f.param.noalias(i8* noalias)
; CHECK: declare void @f.param.noalias(i8* noalias)
declare void @f.param.nocapture(i8* nocapture)
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Bitcode/compatibility-5.0.ll
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ declare void @f.param.byval({ i8, i8 }* byval)
declare void @f.param.inalloca(i8* inalloca)
; CHECK: declare void @f.param.inalloca(i8* inalloca)
declare void @f.param.sret(i8* sret)
; CHECK: declare void @f.param.sret(i8* sret)
; CHECK: declare void @f.param.sret(i8* sret(i8))
declare void @f.param.noalias(i8* noalias)
; CHECK: declare void @f.param.noalias(i8* noalias)
declare void @f.param.nocapture(i8* nocapture)
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Bitcode/compatibility-6.0.ll
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ declare void @f.param.byval({ i8, i8 }* byval)
declare void @f.param.inalloca(i8* inalloca)
; CHECK: declare void @f.param.inalloca(i8* inalloca)
declare void @f.param.sret(i8* sret)
; CHECK: declare void @f.param.sret(i8* sret)
; CHECK: declare void @f.param.sret(i8* sret(i8))
declare void @f.param.noalias(i8* noalias)
; CHECK: declare void @f.param.noalias(i8* noalias)
declare void @f.param.nocapture(i8* nocapture)
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Bitcode/compatibility.ll
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ declare void @f.param.byval({ i8, i8 }* byval)
declare void @f.param.inalloca(i8* inalloca)
; CHECK: declare void @f.param.inalloca(i8* inalloca)
declare void @f.param.sret(i8* sret)
; CHECK: declare void @f.param.sret(i8* sret)
; CHECK: declare void @f.param.sret(i8* sret(i8))
declare void @f.param.noalias(i8* noalias)
; CHECK: declare void @f.param.noalias(i8* noalias)
declare void @f.param.nocapture(i8* nocapture)
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Bitcode/highLevelStructure.3.2.ll
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ module asm "some assembly"
declare void @ParamAttr1(i8 zeroext)
; CHECK: declare void @ParamAttr2(i8* nest)
declare void @ParamAttr2(i8* nest)
; CHECK: declare void @ParamAttr3(i8* sret)
; CHECK: declare void @ParamAttr3(i8* sret(i8))
declare void @ParamAttr3(i8* sret)
; CHECK: declare void @ParamAttr4(i8 signext)
declare void @ParamAttr4(i8 signext)
Expand Down
Loading