Index: clang/lib/CodeGen/CGCall.cpp =================================================================== --- clang/lib/CodeGen/CGCall.cpp +++ clang/lib/CodeGen/CGCall.cpp @@ -2048,7 +2048,7 @@ // Attach attributes to inalloca argument. if (IRFunctionArgs.hasInallocaArg()) { llvm::AttrBuilder Attrs; - Attrs.addAttribute(llvm::Attribute::InAlloca); + Attrs.addInAllocaAttr(FI.getArgStruct()); ArgAttrs[IRFunctionArgs.getInallocaArgNo()] = llvm::AttributeSet::get(getLLVMContext(), Attrs); } Index: clang/test/CodeGenCXX/attr-target-mv-inalloca.cpp =================================================================== --- clang/test/CodeGenCXX/attr-target-mv-inalloca.cpp +++ clang/test/CodeGenCXX/attr-target-mv-inalloca.cpp @@ -16,20 +16,20 @@ bar(f); } -// WINDOWS: define dso_local i32 @"?bar@@YAHUFoo@@@Z"(<{ %struct.Foo }>* inalloca %0) +// WINDOWS: define dso_local i32 @"?bar@@YAHUFoo@@@Z"(<{ %struct.Foo }>* inalloca(<{ %struct.Foo }>) %0) // WINDOWS: %[[O:[0-9a-zA-Z]+]] = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %0, i32 0, i32 0 // WINDOWS: %[[X:[0-9a-zA-Z]+]] = getelementptr inbounds %struct.Foo, %struct.Foo* %[[O]], i32 0, i32 0 // WINDOWS: %[[LOAD:[0-9a-zA-Z]+]] = load i32, i32* %[[X]] // WINDOWS: ret i32 %[[LOAD]] -// WINDOWS: define dso_local i32 @"?bar@@YAHUFoo@@@Z.sse4.2"(<{ %struct.Foo }>* inalloca %0) +// WINDOWS: define dso_local i32 @"?bar@@YAHUFoo@@@Z.sse4.2"(<{ %struct.Foo }>* inalloca(<{ %struct.Foo }>) %0) // WINDOWS: %[[O:[0-9a-zA-Z]+]] = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %0, i32 0, i32 0 // WINDOWS: %[[X:[0-9a-zA-Z]+]] = getelementptr inbounds %struct.Foo, %struct.Foo* %[[O]], i32 0, i32 0 // WINDOWS: %[[LOAD:[0-9a-zA-Z]+]] = load i32, i32* %[[X]] // WINDOWS: %[[ADD:[0-9a-zA-Z]+]] = add nsw i32 %[[LOAD]], 1 // WINDOWS: ret i32 %[[ADD]] -// WINDOWS: define dso_local i32 @"?bar@@YAHUFoo@@@Z.arch_ivybridge"(<{ %struct.Foo }>* inalloca %0) +// WINDOWS: define dso_local i32 @"?bar@@YAHUFoo@@@Z.arch_ivybridge"(<{ %struct.Foo }>* inalloca(<{ %struct.Foo }>) %0) // WINDOWS: %[[O:[0-9a-zA-Z]+]] = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %0, i32 0, i32 0 // WINDOWS: %[[X:[0-9a-zA-Z]+]] = getelementptr inbounds %struct.Foo, %struct.Foo* %[[O]], i32 0, i32 0 // WINDOWS: %[[LOAD:[0-9a-zA-Z]+]] = load i32, i32* %[[X]] @@ -39,7 +39,7 @@ // WINDOWS: define dso_local void @"?usage@@YAXXZ"() // WINDOWS: %[[F:[0-9a-zA-Z]+]] = alloca %struct.Foo // WINDOWS: %[[ARGMEM:[0-9a-zA-Z]+]] = alloca inalloca <{ %struct.Foo }> -// WINDOWS: %[[CALL:[0-9a-zA-Z]+]] = call i32 @"?bar@@YAHUFoo@@@Z.resolver"(<{ %struct.Foo }>* inalloca %[[ARGMEM]]) +// WINDOWS: %[[CALL:[0-9a-zA-Z]+]] = call i32 @"?bar@@YAHUFoo@@@Z.resolver"(<{ %struct.Foo }>* inalloca(<{ %struct.Foo }>) %[[ARGMEM]]) // WINDOWS: define weak_odr dso_local i32 @"?bar@@YAHUFoo@@@Z.resolver"(<{ %struct.Foo }>* %0) // WINDOWS: %[[RET:[0-9a-zA-Z]+]] = musttail call i32 @"?bar@@YAHUFoo@@@Z.arch_ivybridge"(<{ %struct.Foo }>* %0) Index: clang/test/CodeGenCXX/inheriting-constructor.cpp =================================================================== --- clang/test/CodeGenCXX/inheriting-constructor.cpp +++ clang/test/CodeGenCXX/inheriting-constructor.cpp @@ -134,7 +134,7 @@ // WIN32: store i32 2, i32* %[[ARG2]] // WIN32: %[[ARG4:.*]] = getelementptr {{.*}} %[[ARGMEM]] // WIN32: store {{.*}}* %[[TMP]], {{.*}}** %[[ARG4]] - // WIN32: call {{.*}} @"??0A@inalloca_nonvirt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]]) + // WIN32: call {{.*}} @"??0A@inalloca_nonvirt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca(<{{.*}}>) %[[ARGMEM]]) // WIN32: call void @llvm.stackrestore( // WIN32: call {{.*}} @"??0Z@@QAE@XZ"( // WIN32: call {{.*}} @"??1Q@@QAE@XZ"( @@ -170,7 +170,7 @@ // WIN32: store i32 2, i32* %[[ARG2]] // WIN32: %[[ARG4:.*]] = getelementptr {{.*}} %[[ARGMEM]] // WIN32: store {{.*}}* %[[TMP]], {{.*}}** %[[ARG4]] - // WIN32: call {{.*}} @"??0A@inalloca_nonvirt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]]) + // WIN32: call {{.*}} @"??0A@inalloca_nonvirt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca(<{{.*}}>) %[[ARGMEM]]) // WIN32: call void @llvm.stackrestore( // WIN32: call {{.*}} @"??0Z@@QAE@XZ"( // WIN32: call {{.*}} @"??1Q@@QAE@XZ"( @@ -216,7 +216,7 @@ // WIN32: store i32 2, i32* %[[ARG2]] // WIN32: %[[ARG4:.*]] = getelementptr {{.*}} %[[ARGMEM]] // WIN32: store {{.*}}* %[[TMP]], {{.*}}** %[[ARG4]] - // WIN32: call {{.*}} @"??0A@inalloca_virt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]]) + // WIN32: call {{.*}} @"??0A@inalloca_virt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca(<{{.*}}>) %[[ARGMEM]]) // WIN32: call void @llvm.stackrestore( // WIN32: br // @@ -266,7 +266,7 @@ // WIN32: store i32 2, i32* %[[ARG2]] // WIN32: %[[ARG4:.*]] = getelementptr {{.*}} %[[ARGMEM]] // WIN32: store {{.*}}* %[[TMP]], {{.*}}** %[[ARG4]] - // WIN32: call {{.*}} @"??0A@inalloca_virt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]]) + // WIN32: call {{.*}} @"??0A@inalloca_virt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca(<{{.*}}>) %[[ARGMEM]]) // WIN32: call void @llvm.stackrestore( // WIN32: br // Index: clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp =================================================================== --- clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp +++ clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp @@ -14,7 +14,7 @@ // Order of destruction should be left to right. // // X86-LABEL: define dso_local void @"?foo@@YAXUA@@00@Z" -// X86: ([[argmem_ty:<{ %struct.A, %struct.A, %struct.A }>]]* inalloca %0) +// X86: ([[argmem_ty:<{ %struct.A, %struct.A, %struct.A }>]]* inalloca([[argmem_ty]]) %0) // X86: %[[a:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %0, i32 0, i32 0 // X86: %[[b:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %0, i32 0, i32 1 // X86: %[[c:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %0, i32 0, i32 2 @@ -47,7 +47,7 @@ // X86: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@H@Z"(%struct.A* %[[arg2]], i32 2) // X86: %[[arg1:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0 // X86: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@H@Z"(%struct.A* %[[arg1]], i32 1) -// X86: call void @"?foo@@YAXUA@@00@Z"([[argmem_ty]]* inalloca %[[argmem]]) +// X86: call void @"?foo@@YAXUA@@00@Z"([[argmem_ty]]* inalloca([[argmem_ty]]) %[[argmem]]) // X86: call void @llvm.stackrestore // X86: ret void // Index: clang/test/CodeGenCXX/microsoft-abi-byval-sret.cpp =================================================================== --- clang/test/CodeGenCXX/microsoft-abi-byval-sret.cpp +++ clang/test/CodeGenCXX/microsoft-abi-byval-sret.cpp @@ -19,7 +19,7 @@ } // CHECK-LABEL: define dso_local x86_thiscallcc %struct.A* @"?foo@B@@QAE?AUA@@U2@@Z" -// CHECK: (%struct.B* %this, <{ %struct.A*, %struct.A }>* inalloca %0) +// CHECK: (%struct.B* %this, <{ %struct.A*, %struct.A }>* inalloca(<{ %struct.A*, %struct.A }>) %0) // CHECK: getelementptr inbounds <{ %struct.A*, %struct.A }>, <{ %struct.A*, %struct.A }>* %{{.*}}, i32 0, i32 0 // CHECK: load %struct.A*, %struct.A** // CHECK: ret %struct.A* @@ -29,7 +29,7 @@ } // CHECK-LABEL: define dso_local %struct.A* @"?bar@B@@QAA?AUA@@U2@@Z" -// CHECK: (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca %0) +// CHECK: (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca(<{ %struct.B*, %struct.A*, %struct.A }>) %0) // CHECK: getelementptr inbounds <{ %struct.B*, %struct.A*, %struct.A }>, <{ %struct.B*, %struct.A*, %struct.A }>* %{{.*}}, i32 0, i32 1 // CHECK: load %struct.A*, %struct.A** // CHECK: ret %struct.A* @@ -39,7 +39,7 @@ } // CHECK-LABEL: define dso_local x86_stdcallcc %struct.A* @"?baz@B@@QAG?AUA@@U2@@Z" -// CHECK: (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca %0) +// CHECK: (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca(<{ %struct.B*, %struct.A*, %struct.A }>) %0) // CHECK: getelementptr inbounds <{ %struct.B*, %struct.A*, %struct.A }>, <{ %struct.B*, %struct.A*, %struct.A }>* %{{.*}}, i32 0, i32 1 // CHECK: load %struct.A*, %struct.A** // CHECK: ret %struct.A* @@ -49,7 +49,7 @@ } // CHECK-LABEL: define dso_local x86_fastcallcc void @"?qux@B@@QAI?AUA@@U2@@Z" -// CHECK: (%struct.B* inreg %this, %struct.A* inreg noalias sret %agg.result, <{ %struct.A }>* inalloca %0) +// CHECK: (%struct.B* inreg %this, %struct.A* inreg noalias sret %agg.result, <{ %struct.A }>* inalloca(<{ %struct.A }>) %0) // CHECK: ret void int main() { @@ -61,10 +61,10 @@ } // CHECK: call x86_thiscallcc %struct.A* @"?foo@B@@QAE?AUA@@U2@@Z" -// CHECK: (%struct.B* %{{[^,]*}}, <{ %struct.A*, %struct.A }>* inalloca %{{[^,]*}}) +// CHECK: (%struct.B* %{{[^,]*}}, <{ %struct.A*, %struct.A }>* inalloca(<{ %struct.A*, %struct.A }>) %{{[^,]*}}) // CHECK: call %struct.A* @"?bar@B@@QAA?AUA@@U2@@Z" -// CHECK: (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca %{{[^,]*}}) +// CHECK: (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca(<{ %struct.B*, %struct.A*, %struct.A }>) %{{[^,]*}}) // CHECK: call x86_stdcallcc %struct.A* @"?baz@B@@QAG?AUA@@U2@@Z" -// CHECK: (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca %{{[^,]*}}) +// CHECK: (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca(<{ %struct.B*, %struct.A*, %struct.A }>) %{{[^,]*}}) // CHECK: call x86_fastcallcc void @"?qux@B@@QAI?AUA@@U2@@Z" -// CHECK: (%struct.B* inreg %{{[^,]*}}, %struct.A* inreg sret %{{.*}}, <{ %struct.A }>* inalloca %{{[^,]*}}) +// CHECK: (%struct.B* inreg %{{[^,]*}}, %struct.A* inreg sret %{{.*}}, <{ %struct.A }>* inalloca(<{ %struct.A }>) %{{[^,]*}}) Index: clang/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp =================================================================== --- clang/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp +++ clang/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp @@ -15,10 +15,10 @@ C::C() {} // force emission // CHECK32-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?foo@C@byval_thunk@@W3AEXUAgg@2@@Z" -// CHECK32: (%"struct.byval_thunk::C"* %this, <{ %"struct.byval_thunk::Agg" }>* inalloca %0) +// CHECK32: (%"struct.byval_thunk::C"* %this, <{ %"struct.byval_thunk::Agg" }>* inalloca(<{ %"struct.byval_thunk::Agg" }>) %0) // CHECK32: getelementptr i8, i8* %{{.*}}, i32 -4 // CHECK32: musttail call x86_thiscallcc void @"?foo@C@byval_thunk@@UAEXUAgg@2@@Z" -// CHECK32: (%"struct.byval_thunk::C"* %{{.*}}, <{ %"struct.byval_thunk::Agg" }>* inalloca %0) +// CHECK32: (%"struct.byval_thunk::C"* %{{.*}}, <{ %"struct.byval_thunk::Agg" }>* inalloca(<{ %"struct.byval_thunk::Agg" }>) %0) // CHECK32-NEXT: ret void // CHECK64-LABEL: define linkonce_odr dso_local void @"?foo@C@byval_thunk@@W7EAAXUAgg@2@@Z" @@ -44,13 +44,13 @@ C::C() {} // force emission // CHECK32-LABEL: define linkonce_odr dso_local x86_stdcallcc void @"?foo@C@stdcall_thunk@@W3AGXUAgg@2@@Z" -// CHECK32: (<{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>* inalloca %0) +// CHECK32: (<{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>* inalloca(<{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>) %0) // CHECK32: %[[this_slot:[^ ]*]] = getelementptr inbounds <{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>, <{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>* %0, i32 0, i32 0 // CHECK32: load %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::C"** %[[this_slot]] // CHECK32: getelementptr i8, i8* %{{.*}}, i32 -4 // CHECK32: store %"struct.stdcall_thunk::C"* %{{.*}}, %"struct.stdcall_thunk::C"** %[[this_slot]] // CHECK32: musttail call x86_stdcallcc void @"?foo@C@stdcall_thunk@@UAGXUAgg@2@@Z" -// CHECK32: (<{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>* inalloca %0) +// CHECK32: (<{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>* inalloca(<{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>) %0) // CHECK32-NEXT: ret void // CHECK64-LABEL: define linkonce_odr dso_local void @"?foo@C@stdcall_thunk@@W7EAAXUAgg@2@@Z" @@ -76,13 +76,13 @@ C::C() {} // force emission // CHECK32-LABEL: define linkonce_odr dso_local %"struct.sret_thunk::Agg"* @"?foo@C@sret_thunk@@W3AA?AUAgg@2@U32@@Z" -// CHECK32: (<{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>* inalloca %0) +// CHECK32: (<{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>* inalloca(<{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>) %0) // CHECK32: %[[this_slot:[^ ]*]] = getelementptr inbounds <{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>, <{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>* %0, i32 0, i32 0 // CHECK32: load %"struct.sret_thunk::C"*, %"struct.sret_thunk::C"** %[[this_slot]] // CHECK32: getelementptr i8, i8* %{{.*}}, i32 -4 // CHECK32: store %"struct.sret_thunk::C"* %{{.*}}, %"struct.sret_thunk::C"** %[[this_slot]] // CHECK32: %[[rv:[^ ]*]] = musttail call %"struct.sret_thunk::Agg"* @"?foo@C@sret_thunk@@UAA?AUAgg@2@U32@@Z" -// CHECK32: (<{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>* inalloca %0) +// CHECK32: (<{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>* inalloca(<{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>) %0) // 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" Index: clang/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp =================================================================== --- clang/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp +++ clang/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp @@ -19,14 +19,14 @@ return sum; } -// CHECK-LABEL: define dso_local i32 @"?foo@@YAHUA@@ZZ"(<{ %struct.A }>* inalloca %0, ...) +// CHECK-LABEL: define dso_local i32 @"?foo@@YAHUA@@ZZ"(<{ %struct.A }>* inalloca(<{ %struct.A }>) %0, ...) int main() { return foo(A(3), 1, 2, 3); } // CHECK-LABEL: define dso_local i32 @main() // CHECK: %[[argmem:[^ ]*]] = alloca inalloca <{ %struct.A, i32, i32, i32 }> -// CHECK: call i32 {{.*bitcast.*}}@"?foo@@YAHUA@@ZZ"{{.*}}(<{ %struct.A, i32, i32, i32 }>* inalloca %[[argmem]]) +// CHECK: call i32 {{.*bitcast.*}}@"?foo@@YAHUA@@ZZ"{{.*}}(<{ %struct.A, i32, i32, i32 }>* inalloca(<{ %struct.A, i32, i32, i32 }>) %[[argmem]]) void varargs_zero(...); void varargs_one(int, ...); @@ -41,10 +41,10 @@ } // CHECK-LABEL: define dso_local void @"?call_var_args@@YAXXZ"() -// CHECK: call void {{.*bitcast.*varargs_zero.*}}(<{ %struct.A }>* inalloca %{{.*}}) -// CHECK: call void {{.*bitcast.*varargs_one.*}}(<{ i32, %struct.A }>* inalloca %{{.*}}) -// CHECK: call void {{.*bitcast.*varargs_two.*}}(<{ i32, i32, %struct.A }>* inalloca %{{.*}}) -// CHECK: call void {{.*bitcast.*varargs_three.*}}(<{ i32, i32, i32, %struct.A }>* inalloca %{{.*}}) +// CHECK: call void {{.*bitcast.*varargs_zero.*}}(<{ %struct.A }>* inalloca(<{ %struct.A }>) %{{.*}}) +// CHECK: call void {{.*bitcast.*varargs_one.*}}(<{ i32, %struct.A }>* inalloca(<{ i32, %struct.A }>) %{{.*}}) +// CHECK: call void {{.*bitcast.*varargs_two.*}}(<{ i32, i32, %struct.A }>* inalloca(<{ i32, i32, %struct.A }>) %{{.*}}) +// CHECK: call void {{.*bitcast.*varargs_three.*}}(<{ i32, i32, i32, %struct.A }>* inalloca(<{ i32, i32, i32, %struct.A }>) %{{.*}}) // CHECK-LABEL: declare dso_local void @"?varargs_zero@@YAXZZ"(...) // CHECK-LABEL: declare dso_local void @"?varargs_one@@YAXHZZ"(i32, ...) Index: clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp =================================================================== --- clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp +++ clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp @@ -54,7 +54,7 @@ // WIN32: invoke x86_thiscallcc %struct.A* @"??0A@@QAE@XZ" // WIN32: store i1 false, i1* %[[isactive]] // -// WIN32: invoke i32 @"?TakesTwo@@YAHUA@@0@Z"([[argmem_ty]]* inalloca %[[argmem]]) +// WIN32: invoke i32 @"?TakesTwo@@YAHUA@@0@Z"([[argmem_ty]]* inalloca([[argmem_ty]]) %[[argmem]]) // Destroy the two const ref temporaries. // WIN32: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}}) // WIN32: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}}) Index: clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp =================================================================== --- clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp +++ clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp @@ -76,7 +76,9 @@ // WIN32: declare dso_local void @"{{.*take_bools_and_chars.*}}" // WIN32: (<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor, -// WIN32: i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>* inalloca) +// WIN32: i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>* +// WIN32: inalloca(<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor, +// WIN32: i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>)) void take_bools_and_chars(char a, char b, SmallWithDtor c, char d, bool e, int f, bool g); void call_bools_and_chars() { take_bools_and_chars('A', 'B', SmallWithDtor(), 'D', true, 13, false); @@ -163,7 +165,7 @@ // Test that dtors are invoked in the callee. void small_arg_with_dtor(SmallWithDtor s) {} -// WIN32: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(<{ %struct.SmallWithDtor }>* inalloca %0) {{.*}} { +// WIN32: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(<{ %struct.SmallWithDtor }>* inalloca(<{ %struct.SmallWithDtor }>) %0) {{.*}} { // WIN32: call x86_thiscallcc void @"??1SmallWithDtor@@QAE@XZ" // WIN32: } // WIN64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %s.coerce) {{.*}} { @@ -240,13 +242,13 @@ void small_arg_with_vftable(SmallWithVftable s) {} // LINUX-LABEL: define void @_Z22small_arg_with_vftable16SmallWithVftable(%struct.SmallWithVftable* %s) -// WIN32: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(<{ %struct.SmallWithVftable }>* inalloca %0) +// WIN32: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(<{ %struct.SmallWithVftable }>* inalloca(<{ %struct.SmallWithVftable }>) %0) // WIN64: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* %s) // WOA64: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* %s) void medium_arg_with_copy_ctor(MediumWithCopyCtor s) {} // LINUX-LABEL: define void @_Z25medium_arg_with_copy_ctor18MediumWithCopyCtor(%struct.MediumWithCopyCtor* %s) -// WIN32: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(<{ %struct.MediumWithCopyCtor }>* inalloca %0) +// WIN32: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(<{ %struct.MediumWithCopyCtor }>* inalloca(<{ %struct.MediumWithCopyCtor }>) %0) // WIN64: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s) // WOA: define dso_local arm_aapcs_vfpcc void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s) // WOA64: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s) @@ -347,7 +349,7 @@ }; void g(X) { } -// WIN32: define dso_local void @"?g@@YAXUX@@@Z"(<{ %struct.X, [3 x i8] }>* inalloca %0) {{.*}} { +// WIN32: define dso_local void @"?g@@YAXUX@@@Z"(<{ %struct.X, [3 x i8] }>* inalloca(<{ %struct.X, [3 x i8] }>) %0) {{.*}} { // WIN32: call x86_thiscallcc void @"??1X@@QAE@XZ"(%struct.X* {{.*}}) // WIN32: } void f() { @@ -382,7 +384,7 @@ // WIN32: call void @llvm.memcpy // WIN32: getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0 // WIN32: call x86_thiscallcc %"struct.test2::NonTrivial"* @"??0NonTrivial@test2@@QAE@XZ" -// WIN32: call i32 @"?foo@test2@@YAHUNonTrivial@1@UPOD@1@@Z"([[argmem_ty]]* inalloca %argmem) +// WIN32: call i32 @"?foo@test2@@YAHUNonTrivial@1@UPOD@1@@Z"([[argmem_ty]]* inalloca([[argmem_ty]]) %argmem) // WIN32: ret void // WIN32: } @@ -398,7 +400,7 @@ int a; }; void foo(NonTrivial a, bool b) { } -// WIN32-LABEL: define dso_local void @"?foo@test3@@YAXUNonTrivial@1@_N@Z"(<{ %"struct.test3::NonTrivial", i8, [3 x i8] }>* inalloca %0) +// WIN32-LABEL: define dso_local void @"?foo@test3@@YAXUNonTrivial@1@_N@Z"(<{ %"struct.test3::NonTrivial", i8, [3 x i8] }>* inalloca(<{ %"struct.test3::NonTrivial", i8, [3 x i8] }>) %0) } @@ -424,7 +426,7 @@ // WIN32: %[[gep2:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0 // WIN32: %[[addr:[^ ]*]] = bitcast {}** %[[gep2]] to void [[dst_ty]]* // WIN32: store void [[dst_ty]] %[[a2]], void [[dst_ty]]* %[[addr]], align 4 -// WIN32: call void @"?fn1@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z"([[argmem_ty]]* inalloca %[[argmem]]) +// WIN32: call void @"?fn1@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z"([[argmem_ty]]* inalloca([[argmem_ty]]) %[[argmem]]) namespace pr30293 { // Virtual methods living in a secondary vtable take i8* as their 'this' @@ -446,8 +448,8 @@ // WIN32-LABEL: define dso_local x86_thiscallcc void @"?g@C@pr30293@@QAEXXZ"(%"struct.pr30293::C"* %this) // WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"??0SmallWithDtor@@QAE@XZ" -// WIN32: call void @"?h@C@pr30293@@UAAXUSmallWithDtor@@@Z"(<{ i8*, %struct.SmallWithDtor }>* inalloca %{{[^,)]*}}) -// WIN32: declare dso_local void @"?h@C@pr30293@@UAAXUSmallWithDtor@@@Z"(<{ i8*, %struct.SmallWithDtor }>* inalloca) +// WIN32: call void @"?h@C@pr30293@@UAAXUSmallWithDtor@@@Z"(<{ i8*, %struct.SmallWithDtor }>* inalloca(<{ i8*, %struct.SmallWithDtor }>) %{{[^,)]*}}) +// WIN32: declare dso_local void @"?h@C@pr30293@@UAAXUSmallWithDtor@@@Z"(<{ i8*, %struct.SmallWithDtor }>* inalloca(<{ i8*, %struct.SmallWithDtor }>)) // WIN64-LABEL: define dso_local void @"?g@C@pr30293@@QEAAXXZ"(%"struct.pr30293::C"* %this) // WIN64: declare dso_local void @"?h@C@pr30293@@UEAAXUSmallWithDtor@@@Z"(i8*, i32) Index: clang/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp =================================================================== --- clang/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp +++ clang/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp @@ -94,7 +94,7 @@ // CHECK-LABEL: define dso_local void @"?f@cdecl_inalloca@@YAXPAUC@1@@Z"(%"struct.cdecl_inalloca::C"* %c) // CHECK: call void bitcast (void (%"struct.cdecl_inalloca::C"*, ...)* @"??_9C@cdecl_inalloca@@$BA@AA" to void (%"struct.cdecl_inalloca::C"*)*)(%"struct.cdecl_inalloca::C"* %{{.*}}) -// CHECK: call void bitcast (void (%"struct.cdecl_inalloca::C"*, ...)* @"??_9C@cdecl_inalloca@@$BA@AA" to void (<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>*)*)(<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>* inalloca %{{.*}}) +// CHECK: call void bitcast (void (%"struct.cdecl_inalloca::C"*, ...)* @"??_9C@cdecl_inalloca@@$BA@AA" to void (<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>*)*)(<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>* inalloca(<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>) %{{.*}}) // CHECK-LABEL: define linkonce_odr void @"??_9C@cdecl_inalloca@@$BA@AA"(%"struct.cdecl_inalloca::C"* %this, ...) {{.*}} comdat // CHECK: musttail call void (%"struct.cdecl_inalloca::C"*, ...) %{{.*}}(%"struct.cdecl_inalloca::C"* %{{.*}}, ...) Index: clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp =================================================================== --- clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp +++ clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp @@ -189,7 +189,7 @@ whatsthis = this; } -// BITCODE-LABEL: define dso_local void @"?g@C@pr30293@@UAAXUNonTrivial@2@@Z"(<{ i8*, %"struct.pr30293::NonTrivial" }>* inalloca %0) +// BITCODE-LABEL: define dso_local void @"?g@C@pr30293@@UAAXUNonTrivial@2@@Z"(<{ i8*, %"struct.pr30293::NonTrivial" }>* inalloca(<{ i8*, %"struct.pr30293::NonTrivial" }>) %0) // BITCODE: %[[thisaddr:[^ ]*]] = getelementptr inbounds <{ i8*, %"struct.pr30293::NonTrivial" }>, <{ i8*, %"struct.pr30293::NonTrivial" }>* {{.*}}, i32 0, i32 0 // BITCODE: %[[thisaddr1:[^ ]*]] = bitcast i8** %[[thisaddr]] to %"struct.pr30293::C"** // BITCODE: %[[this1:[^ ]*]] = load %"struct.pr30293::C"*, %"struct.pr30293::C"** %[[thisaddr1]], align 4 Index: clang/test/CodeGenCXX/vararg-non-pod-ms-compat.cpp =================================================================== --- clang/test/CodeGenCXX/vararg-non-pod-ms-compat.cpp +++ clang/test/CodeGenCXX/vararg-non-pod-ms-compat.cpp @@ -13,7 +13,7 @@ // CHECK-LABEL: define dso_local void @"?test@@YAXUX@@@Z" // X86: %[[argmem:[^ ]*]] = alloca inalloca <{ %struct.X }> - // X86: call void (<{ %struct.X }>*, ...) bitcast (void (...)* @"?vararg@@YAXZZ" to void (<{ %struct.X }>*, ...)*)(<{ %struct.X }>* inalloca %[[argmem]]) + // X86: call void (<{ %struct.X }>*, ...) bitcast (void (...)* @"?vararg@@YAXZZ" to void (<{ %struct.X }>*, ...)*)(<{ %struct.X }>* inalloca(<{ %struct.X }>) %[[argmem]]) // X64: alloca %struct.X Index: clang/test/CodeGenObjCXX/arc-indirect.mm =================================================================== --- clang/test/CodeGenObjCXX/arc-indirect.mm +++ clang/test/CodeGenObjCXX/arc-indirect.mm @@ -15,8 +15,8 @@ } @end -// CHECK-GNUSTEP: define internal void @_i_C__object_struct_(<{ %0*, i8*, i8*, %struct.S, [3 x i8] }>* inalloca %0) -// CHECK-DARWIN: define internal void @"\01-[C object:struct:]"(<{ %0*, i8*, i8*, %struct.S, [3 x i8] }>* inalloca %0) +// CHECK-GNUSTEP: define internal void @_i_C__object_struct_(<{ %0*, i8*, i8*, %struct.S, [3 x i8] }>* inalloca(<{ %0*, i8*, i8*, %struct.S, [3 x i8] }>) %0) +// CHECK-DARWIN: define internal void @"\01-[C object:struct:]"(<{ %0*, i8*, i8*, %struct.S, [3 x i8] }>* inalloca(<{ %0*, i8*, i8*, %struct.S, [3 x i8] }>) %0) // CHECK: %obj = getelementptr inbounds <{ %0*, i8*, i8*, %struct.S, [3 x i8] }>, <{ %0*, i8*, i8*, %struct.S, [3 x i8] }>* %0, i32 0, i32 2 // CHECK: %[[INSTANCE:[0-9]+]] = load i8*, i8** %obj, align 4 // CHECK: call void @llvm.objc.storeStrong(i8** %obj, i8* %[[INSTANCE]]) Index: clang/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm =================================================================== --- clang/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm +++ clang/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm @@ -10,7 +10,7 @@ // Verify that we destruct things from left to right in the MS C++ ABI: a, b, c, d. // // CHECK-LABEL: define dso_local void @"?test_arc_order@@YAXUA@@PAUobjc_object@@01@Z" -// CHECK: (<{ %struct.A, i8*, %struct.A, i8* }>* inalloca %0) +// CHECK: (<{ %struct.A, i8*, %struct.A, i8* }>* inalloca(<{ %struct.A, i8*, %struct.A, i8* }>) %0) void test_arc_order(A a, id __attribute__((ns_consumed)) b , A c, id __attribute__((ns_consumed)) d) { // CHECK: call x86_thiscallcc void @"??1A@@QAE@XZ"(%struct.A* %{{.*}}) // CHECK: call void @llvm.objc.storeStrong(i8** %{{.*}}, i8* null) Index: llvm/include/llvm/CodeGen/TargetCallingConv.h =================================================================== --- llvm/include/llvm/CodeGen/TargetCallingConv.h +++ llvm/include/llvm/CodeGen/TargetCallingConv.h @@ -42,14 +42,14 @@ unsigned IsHva : 1; ///< HVA field for unsigned IsHvaStart : 1; ///< HVA structure start unsigned IsSecArgPass : 1; ///< Second argument - unsigned ByValAlign : 4; ///< Log 2 of byval alignment + unsigned Alignment : 4; ///< Log 2 of byval alignment unsigned OrigAlign : 5; ///< Log 2 of original alignment unsigned IsInConsecutiveRegsLast : 1; unsigned IsInConsecutiveRegs : 1; unsigned IsCopyElisionCandidate : 1; ///< Argument copy elision candidate unsigned IsPointer : 1; - unsigned ByValSize; ///< Byval struct size + unsigned Size; ///< struct size from byval or inalloca unsigned PointerAddrSpace; ///< Address space of pointer argument @@ -58,9 +58,9 @@ : IsZExt(0), IsSExt(0), IsInReg(0), IsSRet(0), IsByVal(0), IsNest(0), IsReturned(0), IsSplit(0), IsInAlloca(0), IsSplitEnd(0), IsSwiftSelf(0), IsSwiftError(0), IsCFGuardTarget(0), IsHva(0), - IsHvaStart(0), IsSecArgPass(0), ByValAlign(0), OrigAlign(0), + IsHvaStart(0), IsSecArgPass(0), Alignment(0), OrigAlign(0), IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0), - IsCopyElisionCandidate(0), IsPointer(0), ByValSize(0), + IsCopyElisionCandidate(0), IsPointer(0), Size(0), PointerAddrSpace(0) { static_assert(sizeof(*this) == 3 * sizeof(unsigned), "flags are too big"); } @@ -125,13 +125,13 @@ bool isPointer() const { return IsPointer; } void setPointer() { IsPointer = 1; } - unsigned getByValAlign() const { - MaybeAlign A = decodeMaybeAlign(ByValAlign); + unsigned getAlign() const { + MaybeAlign A = decodeMaybeAlign(Alignment); return A ? A->value() : 0; } - void setByValAlign(Align A) { - ByValAlign = encode(A); - assert(getByValAlign() == A.value() && "bitfield overflow"); + void setAlign(Align A) { + Alignment = encode(A); + assert(getAlign() == A.value() && "bitfield overflow"); } unsigned getOrigAlign() const { @@ -143,8 +143,8 @@ assert(getOrigAlign() == A.value() && "bitfield overflow"); } - unsigned getByValSize() const { return ByValSize; } - void setByValSize(unsigned S) { ByValSize = S; } + unsigned getSize() const { return Size; } + void setSize(unsigned S) { Size = S; } unsigned getPointerAddrSpace() const { return PointerAddrSpace; } void setPointerAddrSpace(unsigned AS) { PointerAddrSpace = AS; } Index: llvm/include/llvm/CodeGen/TargetLowering.h =================================================================== --- llvm/include/llvm/CodeGen/TargetLowering.h +++ llvm/include/llvm/CodeGen/TargetLowering.h @@ -192,7 +192,9 @@ bool IsSwiftError : 1; bool IsCFGuardTarget : 1; uint16_t Alignment = 0; - Type *ByValType = nullptr; + + // For type embedded in byval or inalloca attribute. + Type *AttrTy = nullptr; ArgListEntry() : IsSExt(false), IsZExt(false), IsInReg(false), IsSRet(false), @@ -1271,7 +1273,7 @@ /// Return the desired alignment for ByVal or InAlloca aggregate function /// arguments in the caller parameter area. This is the actual alignment, not /// its logarithm. - virtual unsigned getByValTypeAlignment(Type *Ty, const DataLayout &DL) const; + virtual unsigned getAttrTypeAlignment(Type *Ty, const DataLayout &DL) const; /// Return the type of registers that this ValueType will eventually require. MVT getRegisterType(MVT VT) const { Index: llvm/include/llvm/IR/Argument.h =================================================================== --- llvm/include/llvm/IR/Argument.h +++ llvm/include/llvm/IR/Argument.h @@ -86,6 +86,9 @@ /// If this is a byval argument, return its type. Type *getParamByValType() const; + /// If this is a byval argument, return its type. + Type *getParamInAllocaType() const; + /// Return true if this argument has the nest attribute. bool hasNestAttr() const; Index: llvm/include/llvm/IR/Attributes.h =================================================================== --- llvm/include/llvm/IR/Attributes.h +++ llvm/include/llvm/IR/Attributes.h @@ -105,6 +105,7 @@ unsigned ElemSizeArg, const Optional &NumElemsArg); static Attribute getWithByValType(LLVMContext &Context, Type *Ty); + static Attribute getWithInAllocaType(LLVMContext &Context, Type *Ty); //===--------------------------------------------------------------------===// // Attribute Accessors @@ -290,6 +291,7 @@ uint64_t getDereferenceableBytes() const; uint64_t getDereferenceableOrNullBytes() const; Type *getByValType() const; + Type *getInAllocaType() const; std::pair> getAllocSizeArgs() const; std::string getAsString(bool InAttrGrp = false) const; @@ -612,6 +614,9 @@ /// Return the byval type for the specified function parameter. Type *getParamByValType(unsigned ArgNo) const; + /// Return the inalloca type for the specified function parameter. + Type *getParamInAllocaType(unsigned ArgNo) const; + /// Get the stack alignment. MaybeAlign getStackAlignment(unsigned Index) const; @@ -712,6 +717,7 @@ uint64_t DerefOrNullBytes = 0; uint64_t AllocSizeArgs = 0; Type *ByValType = nullptr; + Type *InAllocaType = nullptr; public: AttrBuilder() = default; @@ -790,6 +796,9 @@ /// Retrieve the byval type. Type *getByValType() const { return ByValType; } + /// Retrieve the inalloca type. + Type *getInAllocaType() const { return InAllocaType; } + /// Retrieve the allocsize args, if the allocsize attribute exists. If it /// doesn't exist, pair(0, 0) is returned. std::pair> getAllocSizeArgs() const; @@ -833,6 +842,9 @@ /// This turns a byval type into the form used internally in Attribute. AttrBuilder &addByValAttr(Type *Ty); + /// This turns a inalloca type into the form used internally in Attribute. + AttrBuilder &addInAllocaAttr(Type *Ty); + /// Add an allocsize attribute, using the representation returned by /// Attribute.getIntValue(). AttrBuilder &addAllocSizeAttrFromRawRepr(uint64_t RawAllocSizeRepr); Index: llvm/include/llvm/IR/CallSite.h =================================================================== --- llvm/include/llvm/IR/CallSite.h +++ llvm/include/llvm/IR/CallSite.h @@ -420,6 +420,11 @@ CALLSITE_DELEGATE_GETTER(getParamByValType(ArgNo)); } + /// Extract the byval type for a call or parameter (nullptr=unknown). + Type *getParamInAllocaType(unsigned ArgNo) const { + CALLSITE_DELEGATE_GETTER(getParamInAllocaType(ArgNo)); + } + /// Extract the number of dereferenceable bytes for a call or parameter /// (0=unknown). uint64_t getDereferenceableBytes(unsigned i) const { Index: llvm/include/llvm/IR/Function.h =================================================================== --- llvm/include/llvm/IR/Function.h +++ llvm/include/llvm/IR/Function.h @@ -453,6 +453,12 @@ return Ty ? Ty : (arg_begin() + ArgNo)->getType()->getPointerElementType(); } + /// Extract the inalloca type for a parameter. + Type *getParamInAllocaType(unsigned ArgNo) const { + Type *Ty = AttributeSets.getParamInAllocaType(ArgNo); + return Ty ? Ty : (arg_begin() + ArgNo)->getType()->getPointerElementType(); + } + /// Extract the number of dereferenceable bytes for a call or /// parameter (0=unknown). /// @param i AttributeList index, referring to a return value or argument. Index: llvm/include/llvm/IR/InstrTypes.h =================================================================== --- llvm/include/llvm/IR/InstrTypes.h +++ llvm/include/llvm/IR/InstrTypes.h @@ -1616,6 +1616,12 @@ return Ty ? Ty : getArgOperand(ArgNo)->getType()->getPointerElementType(); } + /// Extract the inalloca type for a call or parameter. + Type *getParamInAllocaType(unsigned ArgNo) const { + Type *Ty = Attrs.getParamInAllocaType(ArgNo); + return Ty ? Ty : getArgOperand(ArgNo)->getType()->getPointerElementType(); + } + /// Extract the number of dereferenceable bytes for a call or /// parameter (0=unknown). uint64_t getDereferenceableBytes(unsigned i) const { Index: llvm/lib/AsmParser/LLParser.h =================================================================== --- llvm/lib/AsmParser/LLParser.h +++ llvm/lib/AsmParser/LLParser.h @@ -339,7 +339,7 @@ bool ParseFnAttributeValuePairs(AttrBuilder &B, std::vector &FwdRefAttrGrps, bool inAttrGrp, LocTy &BuiltinLoc); - bool ParseByValWithOptionalType(Type *&Result); + bool ParseAttrWithOptionalType(Type *&Result); // Module Summary Index Parsing. bool SkipModuleSummaryEntry(); Index: llvm/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/lib/AsmParser/LLParser.cpp +++ llvm/lib/AsmParser/LLParser.cpp @@ -1612,7 +1612,7 @@ } case lltok::kw_byval: { Type *Ty; - if (ParseByValWithOptionalType(Ty)) + if (ParseAttrWithOptionalType(Ty)) return true; B.addByValAttr(Ty); continue; @@ -1631,7 +1631,13 @@ B.addDereferenceableOrNullAttr(Bytes); continue; } - case lltok::kw_inalloca: B.addAttribute(Attribute::InAlloca); break; + case lltok::kw_inalloca: { + Type *Ty; + if (ParseAttrWithOptionalType(Ty)) + return true; + B.addInAllocaAttr(Ty); + continue; + } case lltok::kw_inreg: B.addAttribute(Attribute::InReg); break; case lltok::kw_nest: B.addAttribute(Attribute::Nest); break; case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); break; @@ -2483,13 +2489,17 @@ return false; } -/// ParseByValWithOptionalType +/// ParseAttrWithOptionalType /// ::= byval +/// ::= inalloca /// ::= byval() -bool LLParser::ParseByValWithOptionalType(Type *&Result) { +/// ::= inalloca() +bool LLParser::ParseAttrWithOptionalType(Type *&Result) { Result = nullptr; - if (!EatIfPresent(lltok::kw_byval)) - return true; + + assert(Lex.getKind() == lltok::kw_byval || Lex.getKind() ==lltok::kw_inalloca); + Lex.Lex(); + if (!EatIfPresent(lltok::lparen)) return false; if (ParseType(Result)) Index: llvm/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -715,9 +715,9 @@ return getFnValueByID(ValNo, Ty); } - /// Upgrades old-style typeless byval attributes by adding the corresponding - /// argument's pointee type. - void propagateByValTypes(CallBase *CB, ArrayRef ArgsFullTys); + /// Upgrades old-style typeless byval and inalloca attributes by adding the + /// corresponding argument's pointee type. + void propagateAttributeTypes(CallBase *CB, ArrayRef ArgsFullTys); /// Converts alignment exponent (i.e. power of two (or zero)) to the /// corresponding alignment to use. If alignment is too large, returns @@ -1610,11 +1610,13 @@ if (Error Err = parseAttrKind(Record[++i], &Kind)) return Err; - // Upgrade old-style byval attribute to one with a type, even if it's - // nullptr. We will have to insert the real type when we associate - // this AttributeList with a function. + // Upgrade old-style byval and inalloca attributes to one with a type, + // even if it's nullptr. We will have to insert the real type when we + // associate this AttributeList with a function. if (Kind == Attribute::ByVal) B.addByValAttr(nullptr); + else if (Kind == Attribute::InAlloca) + B.addInAllocaAttr(nullptr); B.addAttribute(Kind); } else if (Record[i] == 1) { // Integer attribute @@ -1658,6 +1660,8 @@ return Err; if (Kind == Attribute::ByVal) B.addByValAttr(HasType ? getTypeByID(Record[++i]) : nullptr); + else if (Kind == Attribute::InAlloca) + B.addInAllocaAttr(HasType ? getTypeByID(Record[++i]) : nullptr); } } @@ -3232,17 +3236,23 @@ 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 and inalloca 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; + if (Func->hasParamAttribute(i, Attribute::ByVal)) { + Type *PTy = cast(FullFTy)->getParamType(i); + Func->removeParamAttr(i, Attribute::ByVal); + Func->addParamAttr(i, Attribute::getWithByValType( + Context, getPointerElementFlatType(PTy))); + } - Type *PTy = cast(FullFTy)->getParamType(i); - Func->removeParamAttr(i, Attribute::ByVal); - Func->addParamAttr(i, Attribute::getWithByValType( + if (Func->hasParamAttribute(i, Attribute::InAlloca)) { + Type *PTy = cast(FullFTy)->getParamType(i); + Func->removeParamAttr(i, Attribute::InAlloca); + Func->addParamAttr(i, Attribute::getWithInAllocaType( Context, getPointerElementFlatType(PTy))); + } } MaybeAlign Alignment; @@ -3679,16 +3689,21 @@ return Error::success(); } -void BitcodeReader::propagateByValTypes(CallBase *CB, - ArrayRef ArgsFullTys) { +void BitcodeReader::propagateAttributeTypes(CallBase *CB, + ArrayRef ArgsFullTys) { for (unsigned i = 0; i != CB->arg_size(); ++i) { - if (!CB->paramHasAttr(i, Attribute::ByVal)) - continue; - - CB->removeParamAttr(i, Attribute::ByVal); - CB->addParamAttr( - i, Attribute::getWithByValType( - Context, getPointerElementFlatType(ArgsFullTys[i]))); + if (CB->paramHasAttr(i, Attribute::ByVal)) { + CB->removeParamAttr(i, Attribute::ByVal); + CB->addParamAttr(i, + Attribute::getWithByValType( + Context, getPointerElementFlatType(ArgsFullTys[i]))); + } + if (CB->paramHasAttr(i, Attribute::InAlloca)) { + CB->removeParamAttr(i, Attribute::InAlloca); + CB->addParamAttr(i, + Attribute::getWithInAllocaType( + Context, getPointerElementFlatType(ArgsFullTys[i]))); + } } } @@ -4538,7 +4553,7 @@ cast(I)->setCallingConv( static_cast(CallingConv::MaxID & CCInfo)); cast(I)->setAttributes(PAL); - propagateByValTypes(cast(I), ArgsFullTys); + propagateAttributeTypes(cast(I), ArgsFullTys); break; } @@ -5076,7 +5091,7 @@ TCK = CallInst::TCK_NoTail; cast(I)->setTailCallKind(TCK); cast(I)->setAttributes(PAL); - propagateByValTypes(cast(I), ArgsFullTys); + propagateAttributeTypes(cast(I), ArgsFullTys); if (FMF.any()) { if (!isa(I)) return error("Fast-math-flags specified for call without " Index: llvm/lib/Bitcode/Writer/ValueEnumerator.cpp =================================================================== --- llvm/lib/Bitcode/Writer/ValueEnumerator.cpp +++ llvm/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -953,6 +953,8 @@ EnumerateValue(&I); if (I.hasAttribute(Attribute::ByVal)) EnumerateType(I.getParamByValType()); + if (I.hasAttribute(Attribute::InAlloca)) + EnumerateType(I.getParamInAllocaType()); } FirstFuncConstantID = Values.size(); Index: llvm/lib/CodeGen/CallingConvLower.cpp =================================================================== --- llvm/lib/CodeGen/CallingConvLower.cpp +++ llvm/lib/CodeGen/CallingConvLower.cpp @@ -44,8 +44,8 @@ CCValAssign::LocInfo LocInfo, int MinSize, int MinAlignment, ISD::ArgFlagsTy ArgFlags) { Align MinAlign(MinAlignment); - Align Alignment(ArgFlags.getByValAlign()); - unsigned Size = ArgFlags.getByValSize(); + Align Alignment(ArgFlags.getAlign()); + unsigned Size = ArgFlags.getSize(); if (MinSize > (int)Size) Size = MinSize; if (MinAlign > Alignment) Index: llvm/lib/CodeGen/GlobalISel/CallLowering.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/CallLowering.cpp +++ llvm/lib/CodeGen/GlobalISel/CallLowering.cpp @@ -101,7 +101,7 @@ Type *ElementTy = cast(Arg.Ty)->getElementType(); auto Ty = Attrs.getAttribute(OpIdx, Attribute::ByVal).getValueAsType(); - Flags.setByValSize(DL.getTypeAllocSize(Ty ? Ty : ElementTy)); + Flags.setSize(DL.getTypeAllocSize(Ty ? Ty : ElementTy)); // For ByVal, alignment should be passed from FE. BE will guess if // this info is not there but there are cases it cannot get right. @@ -109,8 +109,8 @@ if (FuncInfo.getParamAlignment(OpIdx - 2)) FrameAlign = FuncInfo.getParamAlignment(OpIdx - 2); else - FrameAlign = getTLI()->getByValTypeAlignment(ElementTy, DL); - Flags.setByValAlign(Align(FrameAlign)); + FrameAlign = getTLI()->getAttrTypeAlignment(ElementTy, DL); + Flags.setAlign(Align(FrameAlign)); } if (Attrs.hasAttribute(OpIdx, Attribute::Nest)) Flags.setNest(); Index: llvm/lib/CodeGen/SelectionDAG/FastISel.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +++ llvm/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -1207,15 +1207,15 @@ PointerType *Ty = cast(Arg.Ty); Type *ElementTy = Ty->getElementType(); unsigned FrameSize = - DL.getTypeAllocSize(Arg.ByValType ? Arg.ByValType : ElementTy); + DL.getTypeAllocSize(Arg.AttrTy ? Arg.AttrTy : ElementTy); // For ByVal, alignment should come from FE. BE will guess if this info // is not there, but there are cases it cannot get right. unsigned FrameAlign = Arg.Alignment; if (!FrameAlign) - FrameAlign = TLI.getByValTypeAlignment(ElementTy, DL); - Flags.setByValSize(FrameSize); - Flags.setByValAlign(Align(FrameAlign)); + FrameAlign = TLI.getAttrTypeAlignment(ElementTy, DL); + Flags.setSize(FrameSize); + Flags.setAlign(Align(FrameAlign)); } if (Arg.IsNest) Flags.setNest(); Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -9199,17 +9199,17 @@ PointerType *Ty = cast(Args[i].Ty); Type *ElementTy = Ty->getElementType(); - unsigned FrameSize = DL.getTypeAllocSize( - Args[i].ByValType ? Args[i].ByValType : ElementTy); - Flags.setByValSize(FrameSize); + unsigned FrameSize = + DL.getTypeAllocSize(Args[i].AttrTy ? Args[i].AttrTy : ElementTy); + Flags.setSize(FrameSize); // info is not there but there are cases it cannot get right. unsigned FrameAlign; if (Args[i].Alignment) FrameAlign = Args[i].Alignment; else - FrameAlign = getByValTypeAlignment(ElementTy, DL); - Flags.setByValAlign(Align(FrameAlign)); + FrameAlign = getAttrTypeAlignment(ElementTy, DL); + Flags.setAlign(Align(FrameAlign)); } if (Args[i].IsNest) Flags.setNest(); @@ -9709,14 +9709,14 @@ // guess if this info is not there but there are cases it cannot get // right. unsigned FrameSize = DL.getTypeAllocSize(Arg.getParamByValType()); - Flags.setByValSize(FrameSize); + Flags.setSize(FrameSize); unsigned FrameAlign; if (Arg.getParamAlignment()) FrameAlign = Arg.getParamAlignment(); else - FrameAlign = TLI->getByValTypeAlignment(ElementTy, DL); - Flags.setByValAlign(Align(FrameAlign)); + FrameAlign = TLI->getAttrTypeAlignment(ElementTy, DL); + Flags.setAlign(Align(FrameAlign)); } if (Arg.hasAttribute(Attribute::Nest)) Flags.setNest(); Index: llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -115,9 +115,11 @@ IsSwiftSelf = Call->paramHasAttr(ArgIdx, Attribute::SwiftSelf); IsSwiftError = Call->paramHasAttr(ArgIdx, Attribute::SwiftError); Alignment = Call->getParamAlignment(ArgIdx); - ByValType = nullptr; + AttrTy = nullptr; if (Call->paramHasAttr(ArgIdx, Attribute::ByVal)) - ByValType = Call->getParamByValType(ArgIdx); + AttrTy = Call->getParamByValType(ArgIdx); + else if (Call->paramHasAttr(ArgIdx, Attribute::InAlloca)) + AttrTy = Call->getParamInAllocaType(ArgIdx); } /// Generate a libcall taking the given operands as arguments and returning a Index: llvm/lib/CodeGen/TargetLoweringBase.cpp =================================================================== --- llvm/lib/CodeGen/TargetLoweringBase.cpp +++ llvm/lib/CodeGen/TargetLoweringBase.cpp @@ -1512,11 +1512,11 @@ } } -/// getByValTypeAlignment - Return the desired alignment for ByVal aggregate +/// getTypeAlignment - Return the desired alignment for ByVal aggregate /// function arguments in the caller parameter area. This is the actual /// alignment, not its logarithm. -unsigned TargetLoweringBase::getByValTypeAlignment(Type *Ty, - const DataLayout &DL) const { +unsigned TargetLoweringBase::getAttrTypeAlignment(Type *Ty, + const DataLayout &DL) const { return DL.getABITypeAlignment(Ty); } Index: llvm/lib/IR/AsmWriter.cpp =================================================================== --- llvm/lib/IR/AsmWriter.cpp +++ llvm/lib/IR/AsmWriter.cpp @@ -4140,9 +4140,11 @@ return; } - assert(Attr.hasAttribute(Attribute::ByVal) && "unexpected type attr"); + assert((Attr.hasAttribute(Attribute::ByVal) || + Attr.hasAttribute(Attribute::InAlloca)) && + "unexpected type attr"); - Out << "byval"; + Out << (Attr.hasAttribute(Attribute::ByVal) ? "byval" : "inalloca"); if (Type *Ty = Attr.getValueAsType()) { Out << '('; TypePrinter.print(Ty, Out); Index: llvm/lib/IR/AttributeImpl.h =================================================================== --- llvm/lib/IR/AttributeImpl.h +++ llvm/lib/IR/AttributeImpl.h @@ -215,6 +215,7 @@ std::pair> getAllocSizeArgs() const; std::string getAsString(bool InAttrGrp) const; Type *getByValType() const; + Type *getInAllocaType() const; using iterator = const Attribute *; Index: llvm/lib/IR/Attributes.cpp =================================================================== --- llvm/lib/IR/Attributes.cpp +++ llvm/lib/IR/Attributes.cpp @@ -84,6 +84,7 @@ ID.AddInteger(Kind); if (Val) ID.AddInteger(Val); + assert(Kind != InAlloca); void *InsertPoint; AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint); @@ -168,6 +169,10 @@ return get(Context, ByVal, Ty); } +Attribute Attribute::getWithInAllocaType(LLVMContext &Context, Type *Ty) { + return get(Context, InAlloca, Ty); +} + Attribute Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg, const Optional &NumElemsArg) { @@ -298,8 +303,6 @@ return "inaccessiblememonly"; if (hasAttribute(Attribute::InaccessibleMemOrArgMemOnly)) return "inaccessiblemem_or_argmemonly"; - if (hasAttribute(Attribute::InAlloca)) - return "inalloca"; if (hasAttribute(Attribute::InlineHint)) return "inlinehint"; if (hasAttribute(Attribute::InReg)) @@ -406,6 +409,18 @@ return Result; } + if (hasAttribute(Attribute::InAlloca)) { + std::string Result; + Result += "inalloca"; + if (Type *Ty = getValueAsType()) { + raw_string_ostream OS(Result); + Result += '('; + Ty->print(OS, false, true); + OS.flush(); + Result += ')'; + } + return Result; + } // FIXME: These should be output like this: // // align=4 @@ -687,6 +702,10 @@ return SetNode ? SetNode->getByValType() : nullptr; } +Type *AttributeSet::getInAllocaType() const { + return SetNode ? SetNode->getInAllocaType() : nullptr; +} + std::pair> AttributeSet::getAllocSizeArgs() const { return SetNode ? SetNode->getAllocSizeArgs() : std::pair>(0, 0); @@ -778,6 +797,9 @@ case Attribute::ByVal: Attr = Attribute::getWithByValType(C, B.getByValType()); break; + case Attribute::InAlloca: + Attr = Attribute::getWithInAllocaType(C, B.getInAllocaType()); + break; case Attribute::Alignment: assert(B.getAlignment() && "Alignment must be set"); Attr = Attribute::getWithAlignment(C, *B.getAlignment()); @@ -856,6 +878,13 @@ return 0; } +Type *AttributeSetNode::getInAllocaType() const { + for (const auto &I : *this) + if (I.hasAttribute(Attribute::InAlloca)) + return I.getValueAsType(); + return 0; +} + uint64_t AttributeSetNode::getDereferenceableBytes() const { for (const auto &I : *this) if (I.hasAttribute(Attribute::Dereferenceable)) @@ -1360,6 +1389,10 @@ return getAttributes(Index+FirstArgIndex).getByValType(); } +Type *AttributeList::getParamInAllocaType(unsigned Index) const { + return getAttributes(Index+FirstArgIndex).getInAllocaType(); +} + MaybeAlign AttributeList::getStackAlignment(unsigned Index) const { return getAttributes(Index).getStackAlignment(); } @@ -1441,6 +1474,7 @@ DerefBytes = DerefOrNullBytes = 0; AllocSizeArgs = 0; ByValType = nullptr; + InAllocaType = nullptr; } AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) { @@ -1467,6 +1501,8 @@ StackAlignment = Attr.getStackAlignment(); else if (Kind == Attribute::ByVal) ByValType = Attr.getValueAsType(); + else if (Kind == Attribute::InAlloca) + InAllocaType = Attr.getValueAsType(); else if (Kind == Attribute::Dereferenceable) DerefBytes = Attr.getDereferenceableBytes(); else if (Kind == Attribute::DereferenceableOrNull) @@ -1491,6 +1527,8 @@ StackAlignment.reset(); else if (Val == Attribute::ByVal) ByValType = nullptr; + else if (Val == Attribute::InAlloca) + InAllocaType = nullptr; else if (Val == Attribute::Dereferenceable) DerefBytes = 0; else if (Val == Attribute::DereferenceableOrNull) @@ -1579,6 +1617,12 @@ return *this; } +AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) { + Attrs[Attribute::InAlloca] = true; + InAllocaType = Ty; + return *this; +} + AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) { // FIXME: What if both have alignments, but they don't match?! if (!Alignment) @@ -1599,6 +1643,9 @@ if (!ByValType) ByValType = B.ByValType; + if (!InAllocaType) + InAllocaType = B.InAllocaType; + Attrs |= B.Attrs; for (auto I : B.td_attrs()) @@ -1627,6 +1674,9 @@ if (B.ByValType) ByValType = nullptr; + if (B.InAllocaType) + InAllocaType = nullptr; + Attrs &= ~B.Attrs; for (auto I : B.td_attrs()) @@ -1686,7 +1736,8 @@ return false; return Alignment == B.Alignment && StackAlignment == B.StackAlignment && - DerefBytes == B.DerefBytes && ByValType == B.ByValType; + DerefBytes == B.DerefBytes && ByValType == B.ByValType && + InAllocaType == B.InAllocaType; } //===----------------------------------------------------------------------===// Index: llvm/lib/IR/Core.cpp =================================================================== --- llvm/lib/IR/Core.cpp +++ llvm/lib/IR/Core.cpp @@ -149,6 +149,11 @@ return wrap(Attribute::getWithByValType(Ctx, NULL)); } + if (AttrKind == Attribute::AttrKind::InAlloca) { + // Similarly inalloca for now. + return wrap(Attribute::getWithInAllocaType(Ctx, NULL)); + } + return wrap(Attribute::get(Ctx, AttrKind, Val)); } Index: llvm/lib/IR/Function.cpp =================================================================== --- llvm/lib/IR/Function.cpp +++ llvm/lib/IR/Function.cpp @@ -136,6 +136,11 @@ return getParent()->getParamByValType(getArgNo()); } +Type *Argument::getParamInAllocaType() const { + assert(getType()->isPointerTy() && "Only pointers have byval types"); + return getParent()->getParamInAllocaType(getArgNo()); +} + uint64_t Argument::getDereferenceableBytes() const { assert(getType()->isPointerTy() && "Only pointers have dereferenceable bytes"); Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -1654,6 +1654,11 @@ "Attribute 'byval' type does not match parameter!", V); } + if (Attrs.hasAttribute(Attribute::InAlloca) && Attrs.getInAllocaType()) { + Assert(Attrs.getInAllocaType() == cast(Ty)->getElementType(), + "Attribute 'inalloca' type does not match parameter!", V); + } + AttrBuilder IncompatibleAttrs = AttributeFuncs::typeIncompatible(Ty); Assert(!AttrBuilder(Attrs).overlaps(IncompatibleAttrs), "Wrong types for attribute: " + Index: llvm/lib/Linker/IRMover.cpp =================================================================== --- llvm/lib/Linker/IRMover.cpp +++ llvm/lib/Linker/IRMover.cpp @@ -645,6 +645,15 @@ Attrs = Attrs.addAttribute( C, i, Attribute::getWithByValType(C, TypeMap.get(Ty))); } + if (Attrs.hasAttribute(i, Attribute::InAlloca)) { + Type *Ty = Attrs.getAttribute(i, Attribute::InAlloca).getValueAsType(); + if (!Ty) + continue; + + Attrs = Attrs.removeAttribute(C, i, Attribute::InAlloca); + Attrs = Attrs.addAttribute( + C, i, Attribute::getWithInAllocaType(C, TypeMap.get(Ty))); + } } return Attrs; } Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -3315,7 +3315,7 @@ // Byval is used for HFAs in the PCS, but the system should work in a // non-compliant manner for larger structs. EVT PtrVT = getPointerTy(DAG.getDataLayout()); - int Size = Ins[i].Flags.getByValSize(); + int Size = Ins[i].Flags.getSize(); unsigned NumRegs = (Size + 7) / 8; // FIXME: This works on big-endian for composite byvals, which are the common @@ -4078,7 +4078,7 @@ // FIXME: This works on big-endian for composite byvals, which are the // common case. It should also work for fundamental types too. uint32_t BEAlign = 0; - unsigned OpSize = Flags.isByVal() ? Flags.getByValSize() * 8 + unsigned OpSize = Flags.isByVal() ? Flags.getSize() * 8 : VA.getValVT().getSizeInBits(); OpSize = (OpSize + 7) / 8; if (!Subtarget->isLittleEndian() && !Flags.isByVal() && @@ -4113,9 +4113,9 @@ if (Outs[i].Flags.isByVal()) { SDValue SizeNode = - DAG.getConstant(Outs[i].Flags.getByValSize(), DL, MVT::i64); + DAG.getConstant(Outs[i].Flags.getSize(), DL, MVT::i64); SDValue Cpy = DAG.getMemcpy( - Chain, DL, DstAddr, Arg, SizeNode, Outs[i].Flags.getByValAlign(), + Chain, DL, DstAddr, Arg, SizeNode, Outs[i].Flags.getAlign(), /*isVol = */ false, /*AlwaysInline = */ false, /*isTailCall = */ false, DstInfo, MachinePointerInfo()); Index: llvm/lib/Target/AMDGPU/SIISelLowering.cpp =================================================================== --- llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -1517,7 +1517,7 @@ MachineFrameInfo &MFI = MF.getFrameInfo(); if (Arg.Flags.isByVal()) { - unsigned Size = Arg.Flags.getByValSize(); + unsigned Size = Arg.Flags.getSize(); int FrameIdx = MFI.CreateFixedObject(Size, VA.getLocMemOffset(), false); return DAG.getFrameIndex(FrameIdx, MVT::i32); } @@ -2832,12 +2832,12 @@ if (IsTailCall) { ISD::ArgFlagsTy Flags = Outs[i].Flags; unsigned OpSize = Flags.isByVal() ? - Flags.getByValSize() : VA.getValVT().getStoreSize(); + Flags.getSize() : VA.getValVT().getStoreSize(); // FIXME: We can have better than the minimum byval required alignment. Alignment = Flags.isByVal() - ? MaybeAlign(Flags.getByValAlign()) + ? MaybeAlign(Flags.getAlign()) : commonAlignment(Subtarget->getStackAlignment(), Offset); Offset = Offset + FPDiff; @@ -2863,9 +2863,9 @@ if (Outs[i].Flags.isByVal()) { SDValue SizeNode = - DAG.getConstant(Outs[i].Flags.getByValSize(), DL, MVT::i32); + DAG.getConstant(Outs[i].Flags.getSize(), DL, MVT::i32); SDValue Cpy = DAG.getMemcpy( - Chain, DL, DstAddr, Arg, SizeNode, Outs[i].Flags.getByValAlign(), + Chain, DL, DstAddr, Arg, SizeNode, Outs[i].Flags.getAlign(), /*isVol = */ false, /*AlwaysInline = */ true, /*isTailCall = */ false, DstInfo, MachinePointerInfo(AMDGPUAS::PRIVATE_ADDRESS)); Index: llvm/lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- llvm/lib/Target/ARM/ARMISelLowering.cpp +++ llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -2254,16 +2254,16 @@ CCInfo.nextInRegsParam(); } - if (Flags.getByValSize() > 4*offset) { + if (Flags.getSize() > 4*offset) { auto PtrVT = getPointerTy(DAG.getDataLayout()); unsigned LocMemOffset = VA.getLocMemOffset(); SDValue StkPtrOff = DAG.getIntPtrConstant(LocMemOffset, dl); SDValue Dst = DAG.getNode(ISD::ADD, dl, PtrVT, StackPtr, StkPtrOff); SDValue SrcOffset = DAG.getIntPtrConstant(4*offset, dl); SDValue Src = DAG.getNode(ISD::ADD, dl, PtrVT, Arg, SrcOffset); - SDValue SizeNode = DAG.getConstant(Flags.getByValSize() - 4*offset, dl, + SDValue SizeNode = DAG.getConstant(Flags.getSize() - 4*offset, dl, MVT::i32); - SDValue AlignNode = DAG.getConstant(Flags.getByValAlign(), dl, + SDValue AlignNode = DAG.getConstant(Flags.getAlign(), dl, MVT::i32); SDVTList VTs = DAG.getVTList(MVT::Other, MVT::Glue); @@ -4151,7 +4151,7 @@ int FrameIndex = StoreByValRegs( CCInfo, DAG, dl, Chain, &*CurOrigArg, CurByValIndex, - VA.getLocMemOffset(), Flags.getByValSize()); + VA.getLocMemOffset(), Flags.getSize()); InVals.push_back(DAG.getFrameIndex(FrameIndex, PtrVT)); CCInfo.nextInRegsParam(); } else { Index: llvm/lib/Target/Hexagon/HexagonISelLowering.cpp =================================================================== --- llvm/lib/Target/Hexagon/HexagonISelLowering.cpp +++ llvm/lib/Target/Hexagon/HexagonISelLowering.cpp @@ -166,8 +166,8 @@ static SDValue CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain, ISD::ArgFlagsTy Flags, SelectionDAG &DAG, const SDLoc &dl) { - SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), dl, MVT::i32); - return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(), + SDValue SizeNode = DAG.getConstant(Flags.getSize(), dl, MVT::i32); + return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getAlign(), /*isVolatile=*/false, /*AlwaysInline=*/false, /*isTailCall=*/false, MachinePointerInfo(), MachinePointerInfo()); @@ -778,11 +778,10 @@ // 1. 32- and 64-bit values and HVX vectors are passed directly, // 2. Large structs are passed via an address, and the address is // passed in a register. - if (VA.isRegLoc() && ByVal && Flags.getByValSize() <= 8) + if (VA.isRegLoc() && ByVal && Flags.getSize() <= 8) llvm_unreachable("ByValSize must be bigger than 8 bytes"); - bool InReg = VA.isRegLoc() && - (!ByVal || (ByVal && Flags.getByValSize() > 8)); + bool InReg = VA.isRegLoc() && (!ByVal || (ByVal && Flags.getSize() > 8)); if (InReg) { MVT RegVT = VA.getLocVT(); @@ -817,8 +816,8 @@ // If it's a byval parameter, then we need to compute the // "real" size, not the size of the pointer. unsigned ObjSize = Flags.isByVal() - ? Flags.getByValSize() - : VA.getLocVT().getStoreSizeInBits() / 8; + ? Flags.getSize() + : VA.getLocVT().getStoreSizeInBits() / 8; // Create the frame index object for this incoming parameter. int Offset = HEXAGON_LRFP_SIZE + VA.getLocMemOffset(); Index: llvm/lib/Target/Lanai/LanaiISelLowering.cpp =================================================================== --- llvm/lib/Target/Lanai/LanaiISelLowering.cpp +++ llvm/lib/Target/Lanai/LanaiISelLowering.cpp @@ -632,8 +632,8 @@ continue; SDValue Arg = OutVals[I]; - unsigned Size = Flags.getByValSize(); - unsigned Align = Flags.getByValAlign(); + unsigned Size = Flags.getSize(); + unsigned Align = Flags.getAlign(); int FI = MFI.CreateStackObject(Size, Align, false); SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); Index: llvm/lib/Target/MSP430/MSP430ISelLowering.cpp =================================================================== --- llvm/lib/Target/MSP430/MSP430ISelLowering.cpp +++ llvm/lib/Target/MSP430/MSP430ISelLowering.cpp @@ -678,7 +678,7 @@ ISD::ArgFlagsTy Flags = Ins[i].Flags; if (Flags.isByVal()) { - int FI = MFI.CreateFixedObject(Flags.getByValSize(), + int FI = MFI.CreateFixedObject(Flags.getSize(), VA.getLocMemOffset(), true); InVal = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); } else { @@ -862,9 +862,9 @@ ISD::ArgFlagsTy Flags = Outs[i].Flags; if (Flags.isByVal()) { - SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), dl, MVT::i16); + SDValue SizeNode = DAG.getConstant(Flags.getSize(), dl, MVT::i16); MemOp = DAG.getMemcpy(Chain, dl, PtrOff, Arg, SizeNode, - Flags.getByValAlign(), + Flags.getAlign(), /*isVolatile*/false, /*AlwaysInline=*/true, /*isTailCall=*/false, Index: llvm/lib/Target/Mips/MipsISelLowering.cpp =================================================================== --- llvm/lib/Target/Mips/MipsISelLowering.cpp +++ llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -3254,7 +3254,7 @@ unsigned ByValIdx = CCInfo.getInRegsParamsProcessed(); CCInfo.getInRegsParamInfo(ByValIdx, FirstByValReg, LastByValReg); - assert(Flags.getByValSize() && + assert(Flags.getSize() && "ByVal args of size 0 should have been ignored by front-end."); assert(ByValIdx < CCInfo.getInRegsParamsCount()); assert(!IsTailCall && @@ -3627,7 +3627,7 @@ unsigned ByValIdx = CCInfo.getInRegsParamsProcessed(); CCInfo.getInRegsParamInfo(ByValIdx, FirstByValReg, LastByValReg); - assert(Flags.getByValSize() && + assert(Flags.getSize() && "ByVal args of size 0 should have been ignored by front-end."); assert(ByValIdx < CCInfo.getInRegsParamsCount()); copyByValRegs(Chain, DL, OutChains, DAG, Flags, InVals, &*FuncArg, @@ -4302,7 +4302,7 @@ unsigned GPRSizeInBytes = Subtarget.getGPRSizeInBytes(); unsigned NumRegs = LastReg - FirstReg; unsigned RegAreaSize = NumRegs * GPRSizeInBytes; - unsigned FrameObjSize = std::max(Flags.getByValSize(), RegAreaSize); + unsigned FrameObjSize = std::max(Flags.getSize(), RegAreaSize); int FrameObjOffset; ArrayRef ByValArgRegs = ABI.GetByValArgRegs(); @@ -4351,10 +4351,10 @@ MachineFrameInfo &MFI, SelectionDAG &DAG, SDValue Arg, unsigned FirstReg, unsigned LastReg, const ISD::ArgFlagsTy &Flags, bool isLittle, const CCValAssign &VA) const { - unsigned ByValSizeInBytes = Flags.getByValSize(); + unsigned ByValSizeInBytes = Flags.getSize(); unsigned OffsetInBytes = 0; // From beginning of struct unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); - unsigned Alignment = std::min(Flags.getByValAlign(), RegSizeInBytes); + unsigned Alignment = std::min(Flags.getAlign(), RegSizeInBytes); EVT PtrTy = getPointerTy(DAG.getDataLayout()), RegTy = MVT::getIntegerVT(RegSizeInBytes * 8); unsigned NumRegs = LastReg - FirstReg; Index: llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp =================================================================== --- llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp +++ llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp @@ -1358,7 +1358,7 @@ assert(PTy && "Param with byval attribute should be a pointer type"); Type *ETy = PTy->getElementType(); - unsigned align = Outs[OIdx].Flags.getByValAlign(); + unsigned align = Outs[OIdx].Flags.getAlign(); unsigned sz = DL.getTypeAllocSize(ETy); O << ".param .align " << align << " .b8 "; O << "_"; @@ -1583,9 +1583,9 @@ ComputePTXValueVTs(*this, DL, PTy->getElementType(), VTs, &Offsets, 0); // declare .param .align .b8 .param[]; - unsigned sz = Outs[OIdx].Flags.getByValSize(); + unsigned sz = Outs[OIdx].Flags.getSize(); SDVTList DeclareParamVTs = DAG.getVTList(MVT::Other, MVT::Glue); - unsigned ArgAlign = Outs[OIdx].Flags.getByValAlign(); + unsigned ArgAlign = Outs[OIdx].Flags.getAlign(); // The ByValAlign in the Outs[OIdx].Flags is alway set at this point, // so we don't need to worry about natural alignment or not. // See TargetLowering::LowerCallTo(). Index: llvm/lib/Target/PowerPC/PPCISelLowering.h =================================================================== --- llvm/lib/Target/PowerPC/PPCISelLowering.h +++ llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -805,11 +805,11 @@ getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override; - /// getByValTypeAlignment - Return the desired alignment for ByVal aggregate + /// getAttrTypeAlignment - Return the desired alignment for ByVal aggregate /// function arguments in the caller parameter area. This is the actual /// alignment, not its logarithm. - unsigned getByValTypeAlignment(Type *Ty, - const DataLayout &DL) const override; + unsigned getAttrTypeAlignment(Type *Ty, + const DataLayout &DL) const override; /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops /// vector. If it is invalid, don't add anything to Ops. Index: llvm/lib/Target/PowerPC/PPCISelLowering.cpp =================================================================== --- llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -1282,7 +1282,7 @@ } } -/// getMaxByValAlign - Helper for getByValTypeAlignment to determine +/// getMaxByValAlign - Helper for getAttrTypeAlignment to determine /// the desired ByVal argument alignment. static void getMaxByValAlign(Type *Ty, unsigned &MaxAlign, unsigned MaxMaxAlign) { @@ -1312,8 +1312,8 @@ /// getByValTypeAlignment - Return the desired alignment for ByVal aggregate /// function arguments in the caller parameter area. -unsigned PPCTargetLowering::getByValTypeAlignment(Type *Ty, - const DataLayout &DL) const { +unsigned PPCTargetLowering::getAttrTypeAlignment(Type *Ty, + const DataLayout &DL) const { // Darwin passes everything on 4 byte boundary. if (Subtarget.isDarwin()) return 4; @@ -3328,7 +3328,7 @@ unsigned PtrByteSize) { unsigned ArgSize = ArgVT.getStoreSize(); if (Flags.isByVal()) - ArgSize = Flags.getByValSize(); + ArgSize = Flags.getSize(); // Round up to multiples of the pointer size, except for array members, // which are always packed. @@ -3358,7 +3358,7 @@ // ByVal parameters are aligned as requested. if (Flags.isByVal()) { - unsigned BVAlign = Flags.getByValAlign(); + unsigned BVAlign = Flags.getAlign(); if (BVAlign > PtrByteSize) { if (BVAlign % PtrByteSize != 0) llvm_unreachable( @@ -3846,7 +3846,7 @@ ComputeArgOffset(); // ObjSize is the true size, ArgSize rounded up to multiple of registers. - ObjSize = Flags.getByValSize(); + ObjSize = Flags.getSize(); ArgSize = ((ObjSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize; // Empty aggregate parameters do not take up registers. Examples: // struct { } a; @@ -4208,7 +4208,7 @@ if (Flags.isByVal()) { // ObjSize is the true size, ArgSize rounded up to multiple of regs. - unsigned ObjSize = Flags.getByValSize(); + unsigned ObjSize = Flags.getSize(); unsigned ArgSize = ((ObjSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize; VecArgOffset += ArgSize; @@ -4284,7 +4284,7 @@ assert(Ins[ArgNo].isOrigArg() && "Byval arguments cannot be implicit"); // ObjSize is the true size, ArgSize rounded up to multiple of registers. - ObjSize = Flags.getByValSize(); + ObjSize = Flags.getSize(); ArgSize = ((ObjSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize; // Objects of size 1 and 2 are right justified, everything else is // left justified. This means the memory address is adjusted forwards. @@ -4925,8 +4925,8 @@ static SDValue CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain, ISD::ArgFlagsTy Flags, SelectionDAG &DAG, const SDLoc &dl) { - SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), dl, MVT::i32); - return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(), + SDValue SizeNode = DAG.getConstant(Flags.getSize(), dl, MVT::i32); + return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getAlign(), false, false, false, MachinePointerInfo(), MachinePointerInfo()); } @@ -5872,7 +5872,7 @@ if (CallConv == CallingConv::Fast) { if (Flags.isByVal()) { - NumGPRsUsed += (Flags.getByValSize()+7)/8; + NumGPRsUsed += (Flags.getSize()+7)/8; if (NumGPRsUsed > NumGPRs) HasParameterArea = true; } else { @@ -6033,7 +6033,7 @@ // will have Size = 4. With #pragma pack(1), it will have Size = 3. // These are the proper values we need for right-justifying the // aggregate in a parameter register. - unsigned Size = Flags.getByValSize(); + unsigned Size = Flags.getSize(); // An empty aggregate parameter takes up no storage and no // registers. @@ -6591,7 +6591,7 @@ // Note: "by value" is code for passing a structure by value, not // basic types. if (Flags.isByVal()) { - unsigned Size = Flags.getByValSize(); + unsigned Size = Flags.getSize(); // Very small objects are passed right-justified. Everything else is // passed left-justified. if (Size==1 || Size==2) { Index: llvm/lib/Target/RISCV/RISCVISelLowering.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -2125,8 +2125,8 @@ continue; SDValue Arg = OutVals[i]; - unsigned Size = Flags.getByValSize(); - unsigned Align = Flags.getByValAlign(); + unsigned Size = Flags.getSize(); + unsigned Align = Flags.getAlign(); int FI = MF.getFrameInfo().CreateStackObject(Size, Align, /*isSS=*/false); SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); Index: llvm/lib/Target/Sparc/SparcISelLowering.cpp =================================================================== --- llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -752,8 +752,8 @@ continue; SDValue Arg = OutVals[i]; - unsigned Size = Flags.getByValSize(); - unsigned Align = Flags.getByValAlign(); + unsigned Size = Flags.getSize(); + unsigned Align = Flags.getAlign(); if (Size > 0U) { int FI = MFI.CreateStackObject(Size, Align, false); Index: llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp =================================================================== --- llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -729,16 +729,14 @@ fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments"); if (Out.Flags.isInConsecutiveRegsLast()) fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments"); - if (Out.Flags.isByVal() && Out.Flags.getByValSize() != 0) { + if (Out.Flags.isByVal() && Out.Flags.getSize() != 0) { auto &MFI = MF.getFrameInfo(); - int FI = MFI.CreateStackObject(Out.Flags.getByValSize(), - Out.Flags.getByValAlign(), + int FI = MFI.CreateStackObject(Out.Flags.getSize(), Out.Flags.getAlign(), /*isSS=*/false); - SDValue SizeNode = - DAG.getConstant(Out.Flags.getByValSize(), DL, MVT::i32); + SDValue SizeNode = DAG.getConstant(Out.Flags.getSize(), DL, MVT::i32); SDValue FINode = DAG.getFrameIndex(FI, getPointerTy(Layout)); Chain = DAG.getMemcpy( - Chain, DL, FINode, OutVal, SizeNode, Out.Flags.getByValAlign(), + Chain, DL, FINode, OutVal, SizeNode, Out.Flags.getAlign(), /*isVolatile*/ false, /*AlwaysInline=*/false, /*isTailCall*/ false, MachinePointerInfo(), MachinePointerInfo()); OutVal = FINode; Index: llvm/lib/Target/X86/X86FastISel.cpp =================================================================== --- llvm/lib/Target/X86/X86FastISel.cpp +++ llvm/lib/Target/X86/X86FastISel.cpp @@ -3424,7 +3424,7 @@ if (Flags.isByVal()) { X86AddressMode SrcAM; SrcAM.Base.Reg = ArgReg; - if (!TryEmitSmallMemcpy(AM, SrcAM, Flags.getByValSize())) + if (!TryEmitSmallMemcpy(AM, SrcAM, Flags.getSize())) return false; } else if (isa(ArgVal) || isa(ArgVal)) { // If this is a really simple value, emit this with the Value* version Index: llvm/lib/Target/X86/X86ISelLowering.h =================================================================== --- llvm/lib/Target/X86/X86ISelLowering.h +++ llvm/lib/Target/X86/X86ISelLowering.h @@ -753,8 +753,8 @@ /// function arguments in the caller parameter area. For X86, aggregates /// that contains are placed at 16-byte boundaries while the rest are at /// 4-byte boundaries. - unsigned getByValTypeAlignment(Type *Ty, - const DataLayout &DL) const override; + unsigned getAttrTypeAlignment(Type *Ty, + const DataLayout &DL) const override; /// Returns the target specific optimal type for load /// and store operations as a result of memset, memcpy, and memmove Index: llvm/lib/Target/X86/X86ISelLowering.cpp =================================================================== --- llvm/lib/Target/X86/X86ISelLowering.cpp +++ llvm/lib/Target/X86/X86ISelLowering.cpp @@ -2221,8 +2221,8 @@ /// function arguments in the caller parameter area. For X86, aggregates /// that contain SSE vectors are placed at 16-byte boundaries while the rest /// are at 4-byte boundaries. -unsigned X86TargetLowering::getByValTypeAlignment(Type *Ty, - const DataLayout &DL) const { +unsigned X86TargetLowering::getAttrTypeAlignment(Type *Ty, + const DataLayout &DL) const { if (Subtarget.is64Bit()) { // Max of 8 and alignment of type. unsigned TyAlign = DL.getABITypeAlignment(Ty); @@ -3130,9 +3130,9 @@ static SDValue CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain, ISD::ArgFlagsTy Flags, SelectionDAG &DAG, const SDLoc &dl) { - SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), dl, MVT::i32); + SDValue SizeNode = DAG.getConstant(Flags.getSize(), dl, MVT::i32); - return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(), + return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getAlign(), /*isVolatile*/false, /*AlwaysInline=*/true, /*isTailCall*/false, MachinePointerInfo(), MachinePointerInfo()); @@ -3214,7 +3214,7 @@ // In case of tail call optimization mark all arguments mutable. Since they // could be overwritten by lowering of arguments in case of a tail call. if (Flags.isByVal()) { - unsigned Bytes = Flags.getByValSize(); + unsigned Bytes = Flags.getSize(); if (Bytes == 0) Bytes = 1; // Don't create zero-sized stack objects. // FIXME: For now, all byval parameter objects are marked as aliasing. This @@ -3967,8 +3967,7 @@ // the caller from seeing any modifications the callee may make // as guaranteed by the `byval` attribute. int FrameIdx = MF.getFrameInfo().CreateStackObject( - Flags.getByValSize(), std::max(16, (int)Flags.getByValAlign()), - false); + Flags.getSize(), std::max(16, (int)Flags.getAlign()), false); SDValue StackSlot = DAG.getFrameIndex(FrameIdx, getPointerTy(DAG.getDataLayout())); Chain = @@ -4409,7 +4408,7 @@ Opcode == X86::LEA64_32r) && Def->getOperand(1).isFI()) { FI = Def->getOperand(1).getIndex(); - Bytes = Flags.getByValSize(); + Bytes = Flags.getSize(); } else return false; } @@ -4429,7 +4428,7 @@ } else if (Arg.getOpcode() == ISD::FrameIndex && Flags.isByVal()) { FrameIndexSDNode *FINode = cast(Arg); FI = FINode->getIndex(); - Bytes = Flags.getByValSize(); + Bytes = Flags.getSize(); } else return false; Index: llvm/lib/Target/XCore/XCoreISelLowering.cpp =================================================================== --- llvm/lib/Target/XCore/XCoreISelLowering.cpp +++ llvm/lib/Target/XCore/XCoreISelLowering.cpp @@ -1389,9 +1389,9 @@ for (SmallVectorImpl::const_iterator ArgDI = ArgData.begin(), ArgDE = ArgData.end(); ArgDI != ArgDE; ++ArgDI) { - if (ArgDI->Flags.isByVal() && ArgDI->Flags.getByValSize()) { - unsigned Size = ArgDI->Flags.getByValSize(); - unsigned Align = std::max(StackSlotSize, ArgDI->Flags.getByValAlign()); + if (ArgDI->Flags.isByVal() && ArgDI->Flags.getSize()) { + unsigned Size = ArgDI->Flags.getSize(); + unsigned Align = std::max(StackSlotSize, ArgDI->Flags.getAlign()); // Create a new object on the stack and copy the pointee into it. int FI = MFI.CreateStackObject(Size, Align, false); SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); Index: llvm/lib/Transforms/Utils/ValueMapper.cpp =================================================================== --- llvm/lib/Transforms/Utils/ValueMapper.cpp +++ llvm/lib/Transforms/Utils/ValueMapper.cpp @@ -909,6 +909,15 @@ Attrs = Attrs.addAttribute( C, i, Attribute::getWithByValType(C, TypeMapper->remapType(Ty))); } + if (Attrs.hasAttribute(i, Attribute::InAlloca)) { + Type *Ty = Attrs.getAttribute(i, Attribute::InAlloca).getValueAsType(); + if (!Ty) + continue; + + Attrs = Attrs.removeAttribute(C, i, Attribute::InAlloca); + Attrs = Attrs.addAttribute( + C, i, Attribute::getWithInAllocaType(C, TypeMapper->remapType(Ty))); + } } CS.setAttributes(Attrs); return; Index: llvm/test/Assembler/inalloca-type-attr.ll =================================================================== --- /dev/null +++ llvm/test/Assembler/inalloca-type-attr.ll @@ -0,0 +1,43 @@ +; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s + +; CHECK: define void @foo(i32* inalloca(i32) align 4 %0) +define void @foo(i32* inalloca(i32) align 4 %0) { + ret void +} + +; CHECK: define void @bar({ i32*, i8 }* inalloca({ i32*, i8 }) align 4 %0) +define void @bar({i32*, i8}* inalloca({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 }* inalloca({ i32*, i8 }) %ptr) +; CHECK: invoke void @bar({ i32*, i8 }* inalloca({ i32*, i8 }) %ptr) + call void @bar({i32*, i8}* inalloca %ptr) + invoke void @bar({i32*, i8}* inalloca %ptr) to label %success unwind label %fail + +success: + ret void + +fail: + landingpad { i8*, i32 } cleanup + ret void +} + +; CHECK: declare void @baz([8 x i8]* inalloca([8 x i8])) +%named_type = type [8 x i8] +declare void @baz(%named_type* inalloca(%named_type)) + +declare i32 @__gxx_personality_v0(...) + +%0 = type opaque + +; CHECK: define void @anon({ %0* }* inalloca({ %0* }) %arg) +; CHECK: call void @anon_callee({ %0* }* inalloca({ %0* }) %arg) +define void @anon({ %0* }* inalloca({ %0* }) %arg) { + call void @anon_callee({ %0* }* inalloca({ %0* }) %arg) + ret void +} + +; CHECK: declare void @anon_callee({ %0* }* inalloca({ %0* })) +declare void @anon_callee({ %0* }* inalloca({ %0* })) Index: llvm/test/Assembler/invalid-inalloca-type1.ll =================================================================== --- /dev/null +++ llvm/test/Assembler/invalid-inalloca-type1.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +; CHECK: Attribute 'inalloca' type does not match parameter! +declare void @foo(i32* inalloca(i8)) Index: llvm/test/Assembler/invalid-inalloca-type2.ll =================================================================== --- /dev/null +++ llvm/test/Assembler/invalid-inalloca-type2.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +; CHECK: error: void type only allowed for function results +declare void @foo(i32* inalloca(void)) Index: llvm/test/Assembler/invalid-inalloca-type3.ll =================================================================== --- /dev/null +++ llvm/test/Assembler/invalid-inalloca-type3.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +; CHECK: Attributes 'byval' and 'inalloca' do not support unsized types! +declare void @foo(void()* inalloca(void())) Index: llvm/test/Bitcode/attributes.ll =================================================================== --- llvm/test/Bitcode/attributes.ll +++ llvm/test/Bitcode/attributes.ll @@ -214,8 +214,8 @@ ret void; } -define void @f36(i8* inalloca %0) { -; CHECK: define void @f36(i8* inalloca %0) { +define void @f36(i8* inalloca(i8) %0) { +; CHECK: define void @f36(i8* inalloca(i8) %0) { ret void } Index: llvm/test/Bitcode/compatibility-3.6.ll =================================================================== --- llvm/test/Bitcode/compatibility-3.6.ll +++ llvm/test/Bitcode/compatibility-3.6.ll @@ -406,7 +406,7 @@ declare void @f.param.byval({ i8, i8 }* byval) ; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 })) declare void @f.param.inalloca(i8* inalloca) -; CHECK: declare void @f.param.inalloca(i8* inalloca) +; CHECK: declare void @f.param.inalloca(i8* inalloca(i8)) declare void @f.param.sret(i8* sret) ; CHECK: declare void @f.param.sret(i8* sret) declare void @f.param.noalias(i8* noalias) @@ -993,7 +993,7 @@ define void @instructions.call_musttail(i8* inalloca %val) { musttail call void @f.param.inalloca(i8* inalloca %val) - ; CHECK: musttail call void @f.param.inalloca(i8* inalloca %val) + ; CHECK: musttail call void @f.param.inalloca(i8* inalloca(i8) %val) ret void } Index: llvm/test/Bitcode/compatibility-3.7.ll =================================================================== --- llvm/test/Bitcode/compatibility-3.7.ll +++ llvm/test/Bitcode/compatibility-3.7.ll @@ -412,7 +412,7 @@ declare void @f.param.byval({ i8, i8 }* byval) ; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 })) declare void @f.param.inalloca(i8* inalloca) -; CHECK: declare void @f.param.inalloca(i8* inalloca) +; CHECK: declare void @f.param.inalloca(i8* inalloca(i8)) declare void @f.param.sret(i8* sret) ; CHECK: declare void @f.param.sret(i8* sret) declare void @f.param.noalias(i8* noalias) @@ -1034,7 +1034,7 @@ define void @instructions.call_musttail(i8* inalloca %val) { musttail call void @f.param.inalloca(i8* inalloca %val) - ; CHECK: musttail call void @f.param.inalloca(i8* inalloca %val) + ; CHECK: musttail call void @f.param.inalloca(i8* inalloca(i8) %val) ret void } Index: llvm/test/Bitcode/compatibility-3.8.ll =================================================================== --- llvm/test/Bitcode/compatibility-3.8.ll +++ llvm/test/Bitcode/compatibility-3.8.ll @@ -437,7 +437,7 @@ declare void @f.param.byval({ i8, i8 }* byval) ; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 })) declare void @f.param.inalloca(i8* inalloca) -; CHECK: declare void @f.param.inalloca(i8* inalloca) +; CHECK: declare void @f.param.inalloca(i8* inalloca(i8)) declare void @f.param.sret(i8* sret) ; CHECK: declare void @f.param.sret(i8* sret) declare void @f.param.noalias(i8* noalias) @@ -1182,7 +1182,7 @@ define void @instructions.call_musttail(i8* inalloca %val) { musttail call void @f.param.inalloca(i8* inalloca %val) - ; CHECK: musttail call void @f.param.inalloca(i8* inalloca %val) + ; CHECK: musttail call void @f.param.inalloca(i8* inalloca(i8) %val) ret void } Index: llvm/test/Bitcode/compatibility-3.9.ll =================================================================== --- llvm/test/Bitcode/compatibility-3.9.ll +++ llvm/test/Bitcode/compatibility-3.9.ll @@ -506,7 +506,7 @@ declare void @f.param.byval({ i8, i8 }* byval) ; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 })) declare void @f.param.inalloca(i8* inalloca) -; CHECK: declare void @f.param.inalloca(i8* inalloca) +; CHECK: declare void @f.param.inalloca(i8* inalloca(i8)) declare void @f.param.sret(i8* sret) ; CHECK: declare void @f.param.sret(i8* sret) declare void @f.param.noalias(i8* noalias) @@ -1253,7 +1253,7 @@ define void @instructions.call_musttail(i8* inalloca %val) { musttail call void @f.param.inalloca(i8* inalloca %val) - ; CHECK: musttail call void @f.param.inalloca(i8* inalloca %val) + ; CHECK: musttail call void @f.param.inalloca(i8* inalloca(i8) %val) ret void } Index: llvm/test/Bitcode/compatibility-4.0.ll =================================================================== --- llvm/test/Bitcode/compatibility-4.0.ll +++ llvm/test/Bitcode/compatibility-4.0.ll @@ -506,7 +506,7 @@ declare void @f.param.byval({ i8, i8 }* byval) ; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 })) declare void @f.param.inalloca(i8* inalloca) -; CHECK: declare void @f.param.inalloca(i8* inalloca) +; CHECK: declare void @f.param.inalloca(i8* inalloca(i8)) declare void @f.param.sret(i8* sret) ; CHECK: declare void @f.param.sret(i8* sret) declare void @f.param.noalias(i8* noalias) @@ -1253,7 +1253,7 @@ define void @instructions.call_musttail(i8* inalloca %val) { musttail call void @f.param.inalloca(i8* inalloca %val) - ; CHECK: musttail call void @f.param.inalloca(i8* inalloca %val) + ; CHECK: musttail call void @f.param.inalloca(i8* inalloca(i8) %val) ret void } Index: llvm/test/Bitcode/compatibility-5.0.ll =================================================================== --- llvm/test/Bitcode/compatibility-5.0.ll +++ llvm/test/Bitcode/compatibility-5.0.ll @@ -510,7 +510,7 @@ declare void @f.param.byval({ i8, i8 }* byval) ; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 })) declare void @f.param.inalloca(i8* inalloca) -; CHECK: declare void @f.param.inalloca(i8* inalloca) +; CHECK: declare void @f.param.inalloca(i8* inalloca(i8)) declare void @f.param.sret(i8* sret) ; CHECK: declare void @f.param.sret(i8* sret) declare void @f.param.noalias(i8* noalias) @@ -1263,7 +1263,7 @@ define void @instructions.call_musttail(i8* inalloca %val) { musttail call void @f.param.inalloca(i8* inalloca %val) - ; CHECK: musttail call void @f.param.inalloca(i8* inalloca %val) + ; CHECK: musttail call void @f.param.inalloca(i8* inalloca(i8) %val) ret void } Index: llvm/test/Bitcode/compatibility-6.0.ll =================================================================== --- llvm/test/Bitcode/compatibility-6.0.ll +++ llvm/test/Bitcode/compatibility-6.0.ll @@ -517,7 +517,7 @@ declare void @f.param.byval({ i8, i8 }* byval) ; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 })) declare void @f.param.inalloca(i8* inalloca) -; CHECK: declare void @f.param.inalloca(i8* inalloca) +; CHECK: declare void @f.param.inalloca(i8* inalloca(i8)) declare void @f.param.sret(i8* sret) ; CHECK: declare void @f.param.sret(i8* sret) declare void @f.param.noalias(i8* noalias) @@ -1274,7 +1274,7 @@ define void @instructions.call_musttail(i8* inalloca %val) { musttail call void @f.param.inalloca(i8* inalloca %val) - ; CHECK: musttail call void @f.param.inalloca(i8* inalloca %val) + ; CHECK: musttail call void @f.param.inalloca(i8* inalloca(i8) %val) ret void } Index: llvm/test/Bitcode/compatibility.ll =================================================================== --- llvm/test/Bitcode/compatibility.ll +++ llvm/test/Bitcode/compatibility.ll @@ -530,8 +530,8 @@ ; CHECK: declare void @f.param.inreg(i8 inreg) declare void @f.param.byval({ i8, i8 }* byval) ; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 })) -declare void @f.param.inalloca(i8* inalloca) -; CHECK: declare void @f.param.inalloca(i8* inalloca) +declare void @f.param.inalloca(i8* inalloca(i8)) +; CHECK: declare void @f.param.inalloca(i8* inalloca(i8)) declare void @f.param.sret(i8* sret) ; CHECK: declare void @f.param.sret(i8* sret) declare void @f.param.noalias(i8* noalias) @@ -1462,9 +1462,9 @@ ret void } -define void @instructions.call_musttail(i8* inalloca %val) { - musttail call void @f.param.inalloca(i8* inalloca %val) - ; CHECK: musttail call void @f.param.inalloca(i8* inalloca %val) +define void @instructions.call_musttail(i8* inalloca(i8) %val) { + musttail call void @f.param.inalloca(i8* inalloca(i8) %val) + ; CHECK: musttail call void @f.param.inalloca(i8* inalloca(i8) %val) ret void } Index: llvm/test/Bitcode/inalloca.ll =================================================================== --- llvm/test/Bitcode/inalloca.ll +++ llvm/test/Bitcode/inalloca.ll @@ -3,17 +3,17 @@ ; inalloca should roundtrip. -define void @foo(i32* inalloca %args) { +define void @foo(i32* inalloca(i32) %args) { ret void } -; CHECK-LABEL: define void @foo(i32* inalloca %args) +; CHECK-LABEL: define void @foo(i32* inalloca(i32) %args) define void @bar() { ; Use the maximum alignment, since we stuff our bit with alignment. %args = alloca inalloca i32, align 536870912 - call void @foo(i32* inalloca %args) + call void @foo(i32* inalloca(i32) %args) ret void } ; CHECK-LABEL: define void @bar() { ; CHECK: %args = alloca inalloca i32, align 536870912 -; CHECK: call void @foo(i32* inalloca %args) +; CHECK: call void @foo(i32* inalloca(i32) %args) Index: llvm/test/Transforms/Attributor/ArgumentPromotion/inalloca.ll =================================================================== --- llvm/test/Transforms/Attributor/ArgumentPromotion/inalloca.ll +++ llvm/test/Transforms/Attributor/ArgumentPromotion/inalloca.ll @@ -7,9 +7,9 @@ %struct.ss = type { i32, i32 } ; Argpromote + sroa should change this to passing the two integers by value. -define internal i32 @f(%struct.ss* inalloca %s) { +define internal i32 @f(%struct.ss* inalloca(%struct.ss) %s) { ; ATTRIBUTOR-LABEL: define {{[^@]+}}@f -; ATTRIBUTOR-SAME: (%struct.ss* inalloca noalias nocapture nofree nonnull align 4 dereferenceable(8) [[S:%.*]]) +; ATTRIBUTOR-SAME: (%struct.ss* noalias nocapture nofree nonnull inalloca(%struct.ss) align 4 dereferenceable(8) [[S:%.*]]) ; ATTRIBUTOR-NEXT: entry: ; ATTRIBUTOR-NEXT: [[F0:%.*]] = getelementptr [[STRUCT_SS:%.*]], %struct.ss* [[S]], i32 0, i32 0 ; ATTRIBUTOR-NEXT: [[F1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 @@ -45,7 +45,7 @@ ; ATTRIBUTOR-NEXT: [[F1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 ; ATTRIBUTOR-NEXT: store i32 1, i32* [[F0]], align 4 ; ATTRIBUTOR-NEXT: store i32 2, i32* [[F1]], align 4 -; ATTRIBUTOR-NEXT: [[R:%.*]] = call i32 @f(%struct.ss* inalloca noalias nocapture nofree nonnull align 4 dereferenceable(8) [[S]]) +; ATTRIBUTOR-NEXT: [[R:%.*]] = call i32 @f(%struct.ss* noalias nocapture nofree nonnull inalloca(%struct.ss) align 4 dereferenceable(8) [[S]]) ; ATTRIBUTOR-NEXT: ret i32 [[R]] ; ; GLOBALOPT_ATTRIBUTOR-LABEL: define {{[^@]+}}@main() local_unnamed_addr @@ -64,12 +64,12 @@ %f1 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 1 store i32 1, i32* %f0, align 4 store i32 2, i32* %f1, align 4 - %r = call i32 @f(%struct.ss* inalloca %S) + %r = call i32 @f(%struct.ss* inalloca(%struct.ss) %S) ret i32 %r } ; Argpromote can't promote %a because of the icmp use. -define internal i1 @g(%struct.ss* %a, %struct.ss* inalloca %b) nounwind { +define internal i1 @g(%struct.ss* %a, %struct.ss* inalloca(%struct.ss) %b) nounwind { entry: %c = icmp eq %struct.ss* %a, %b ret i1 %c @@ -86,6 +86,6 @@ ; entry: %S = alloca inalloca %struct.ss - %c = call i1 @g(%struct.ss* %S, %struct.ss* inalloca %S) + %c = call i1 @g(%struct.ss* %S, %struct.ss* inalloca(%struct.ss) %S) ret i32 0 } Index: llvm/test/Transforms/Attributor/readattrs.ll =================================================================== --- llvm/test/Transforms/Attributor/readattrs.ll +++ llvm/test/Transforms/Attributor/readattrs.ll @@ -51,9 +51,9 @@ ret void } -; ATTRIBUTOR: define void @test7_1(i32* inalloca nocapture nofree writeonly %a) +; ATTRIBUTOR: define void @test7_1(i32* nocapture nofree writeonly inalloca(i32) %a) ; inalloca parameters are always considered written -define void @test7_1(i32* inalloca %a) { +define void @test7_1(i32* inalloca(i32) %a) { ret void } Index: llvm/test/Transforms/Attributor/value-simplify.ll =================================================================== --- llvm/test/Transforms/Attributor/value-simplify.ll +++ llvm/test/Transforms/Attributor/value-simplify.ll @@ -201,9 +201,9 @@ ; Do not touch complicated arguments (for now) %struct.X = type { i8* } -define internal i32* @test_inalloca(i32* inalloca %a) { +define internal i32* @test_inalloca(i32* inalloca(i32) %a) { ; CHECK-LABEL: define {{[^@]+}}@test_inalloca -; CHECK-SAME: (i32* inalloca noalias nofree returned writeonly [[A:%.*]]) +; CHECK-SAME: (i32* noalias nofree returned writeonly inalloca(i32) [[A:%.*]]) ; CHECK-NEXT: ret i32* [[A]] ; ret i32* %a Index: llvm/test/Transforms/FunctionAttrs/readattrs.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/readattrs.ll +++ llvm/test/Transforms/FunctionAttrs/readattrs.ll @@ -50,9 +50,9 @@ ret void } -; CHECK: define void @test7_1(i32* inalloca nocapture %a) +; CHECK: define void @test7_1(i32* nocapture inalloca(i32) %a) ; inalloca parameters are always considered written -define void @test7_1(i32* inalloca %a) { +define void @test7_1(i32* inalloca(i32) %a) { ret void } Index: llvm/test/Transforms/InstCombine/stacksaverestore.ll =================================================================== --- llvm/test/Transforms/InstCombine/stacksaverestore.ll +++ llvm/test/Transforms/InstCombine/stacksaverestore.ll @@ -72,7 +72,7 @@ declare void @bar(i32, i8*, i8*, i8*, i8*, i32) -declare void @inalloca_callee(i32* inalloca) +declare void @inalloca_callee(i32* inalloca(i32)) define void @test3(i32 %c) { entry: @@ -83,7 +83,7 @@ %save1 = call i8* @llvm.stacksave() %argmem = alloca inalloca i32 store i32 0, i32* %argmem - call void @inalloca_callee(i32* inalloca %argmem) + call void @inalloca_callee(i32* inalloca(i32) %argmem) ; This restore cannot be deleted, the restore below does not make it dead. call void @llvm.stackrestore(i8* %save1) @@ -106,7 +106,7 @@ ; CHECK: %save1 = call i8* @llvm.stacksave() ; CHECK: %argmem = alloca inalloca i32 ; CHECK: store i32 0, i32* %argmem -; CHECK: call void @inalloca_callee(i32* inalloca {{.*}} %argmem) +; CHECK: call void @inalloca_callee(i32* {{.*}} inalloca(i32) %argmem) ; CHECK: call void @llvm.stackrestore(i8* %save1) ; CHECK: br i1 %done, label %loop, label %return ; CHECK: ret void Index: llvm/unittests/IR/AttributesTest.cpp =================================================================== --- llvm/unittests/IR/AttributesTest.cpp +++ llvm/unittests/IR/AttributesTest.cpp @@ -184,6 +184,16 @@ A = Attribute::getWithByValType(C, Type::getInt32Ty(C)); EXPECT_EQ(A.getAsString(), "byval(i32)"); + + // or inalloca(%mystruct = { i32 }) + A = Attribute::getWithInAllocaType(C, Ty); + EXPECT_EQ(A.getAsString(), "inalloca(%mystruct)"); + + A = Attribute::getWithInAllocaType(C, nullptr); + EXPECT_EQ(A.getAsString(), "inalloca"); + + A = Attribute::getWithInAllocaType(C, Type::getInt32Ty(C)); + EXPECT_EQ(A.getAsString(), "inalloca(i32)"); } } // end anonymous namespace