Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -2250,6 +2250,21 @@ case CallingConv::AMDGPU_CS: Assert(!F.hasStructRetAttr(), "Calling convention does not allow sret", &F); + if (F.getCallingConv() != CallingConv::SPIR_KERNEL) { + unsigned StackAS = DL.getAllocaAddrSpace(); + unsigned i = 0; + for (const Argument &Arg : F.args()) { + if (Attrs.hasParamAttribute(i, Attribute::ByVal)) { + // FIXME: Should also disallow LDS and GDS, but we don't have the enum + // value here. + Assert(Arg.getType()->getPointerAddressSpace() != StackAS, + "Calling convention disallows stack byval", &F); + } + + ++i; + } + } + LLVM_FALLTHROUGH; case CallingConv::Fast: case CallingConv::Cold: Index: llvm/test/CodeGen/AMDGPU/hsa-metadata-from-llvm-ir-full-v3.ll =================================================================== --- llvm/test/CodeGen/AMDGPU/hsa-metadata-from-llvm-ir-full-v3.ll +++ llvm/test/CodeGen/AMDGPU/hsa-metadata-from-llvm-ir-full-v3.ll @@ -572,59 +572,6 @@ ret void } -; CHECK: - .args: -; CHECK-NEXT: - .address_space: private -; CHECK-NEXT: .name: a -; CHECK-NEXT: .offset: 0 -; CHECK-NEXT: .size: 4 -; CHECK-NEXT: .type_name: struct A -; CHECK-NEXT: .value_kind: global_buffer -; CHECK-NEXT: .value_type: struct -; CHECK-NEXT: - .offset: 8 -; CHECK-NEXT: .size: 8 -; CHECK-NEXT: .value_kind: hidden_global_offset_x -; CHECK-NEXT: .value_type: i64 -; CHECK-NEXT: - .offset: 16 -; CHECK-NEXT: .size: 8 -; CHECK-NEXT: .value_kind: hidden_global_offset_y -; CHECK-NEXT: .value_type: i64 -; CHECK-NEXT: - .offset: 24 -; CHECK-NEXT: .size: 8 -; CHECK-NEXT: .value_kind: hidden_global_offset_z -; CHECK-NEXT: .value_type: i64 -; CHECK-NEXT: - .address_space: global -; CHECK-NEXT: .offset: 32 -; CHECK-NEXT: .size: 8 -; CHECK-NEXT: .value_kind: hidden_printf_buffer -; CHECK-NEXT: .value_type: i8 -; CHECK-NEXT: - .address_space: global -; CHECK-NEXT: .offset: 40 -; CHECK-NEXT: .size: 8 -; CHECK-NEXT: .value_kind: hidden_none -; CHECK-NEXT: .value_type: i8 -; CHECK-NEXT: - .address_space: global -; CHECK-NEXT: .offset: 48 -; CHECK-NEXT: .size: 8 -; CHECK-NEXT: .value_kind: hidden_none -; CHECK-NEXT: .value_type: i8 -; CHECK-NEXT: - .address_space: global -; CHECK-NEXT: .offset: 56 -; CHECK-NEXT: .size: 8 -; CHECK-NEXT: .value_kind: hidden_multigrid_sync_arg -; CHECK-NEXT: .value_type: i8 -; CHECK: .language: OpenCL C -; CHECK-NEXT: .language_version: -; CHECK-NEXT: - 2 -; CHECK-NEXT: - 0 -; CHECK: .name: test_struct_byval_private -; CHECK: .symbol: test_struct_byval_private.kd -; FIXME: This test makes no sense and should fail the verifier -define amdgpu_kernel void @test_struct_byval_private(%struct.A addrspace(5)* byval %a) #0 - !kernel_arg_addr_space !1 !kernel_arg_access_qual !2 !kernel_arg_type !20 - !kernel_arg_base_type !20 !kernel_arg_type_qual !4 { - ret void -} - ; CHECK: - .args: ; CHECK-NEXT: .name: a ; CHECK-NEXT: .offset: 0 @@ -1634,59 +1581,6 @@ ret void } -; CHECK: - .args: -; CHECK-NEXT: - .address_space: private -; CHECK-NEXT: .name: a -; CHECK-NEXT: .offset: 0 -; CHECK-NEXT: .size: 4 -; CHECK-NEXT: .type_name: struct B -; CHECK-NEXT: .value_kind: global_buffer -; CHECK-NEXT: .value_type: struct -; CHECK-NEXT: - .offset: 8 -; CHECK-NEXT: .size: 8 -; CHECK-NEXT: .value_kind: hidden_global_offset_x -; CHECK-NEXT: .value_type: i64 -; CHECK-NEXT: - .offset: 16 -; CHECK-NEXT: .size: 8 -; CHECK-NEXT: .value_kind: hidden_global_offset_y -; CHECK-NEXT: .value_type: i64 -; CHECK-NEXT: - .offset: 24 -; CHECK-NEXT: .size: 8 -; CHECK-NEXT: .value_kind: hidden_global_offset_z -; CHECK-NEXT: .value_type: i64 -; CHECK-NEXT: - .address_space: global -; CHECK-NEXT: .offset: 32 -; CHECK-NEXT: .size: 8 -; CHECK-NEXT: .value_kind: hidden_printf_buffer -; CHECK-NEXT: .value_type: i8 -; CHECK-NEXT: - .address_space: global -; CHECK-NEXT: .offset: 40 -; CHECK-NEXT: .size: 8 -; CHECK-NEXT: .value_kind: hidden_none -; CHECK-NEXT: .value_type: i8 -; CHECK-NEXT: - .address_space: global -; CHECK-NEXT: .offset: 48 -; CHECK-NEXT: .size: 8 -; CHECK-NEXT: .value_kind: hidden_none -; CHECK-NEXT: .value_type: i8 -; CHECK-NEXT: - .address_space: global -; CHECK-NEXT: .offset: 56 -; CHECK-NEXT: .size: 8 -; CHECK-NEXT: .value_kind: hidden_multigrid_sync_arg -; CHECK-NEXT: .value_type: i8 -; CHECK: .language: OpenCL C -; CHECK-NEXT: .language_version: -; CHECK-NEXT: - 2 -; CHECK-NEXT: - 0 -; CHECK: .name: test_arg_struct_byval_private_contains_ptr -; CHECK: .symbol: test_arg_struct_byval_private_contains_ptr.kd -; FIXME: This makes no sense and should fail the verifier -define amdgpu_kernel void @test_arg_struct_byval_private_contains_ptr(%struct.B addrspace(5)* byval %a) #0 - !kernel_arg_addr_space !1 !kernel_arg_access_qual !2 !kernel_arg_type !82 - !kernel_arg_base_type !82 !kernel_arg_type_qual !4 { - ret void -} - ; CHECK: - .args: ; CHECK-NEXT: - .name: a ; CHECK-NEXT: .offset: 0 Index: llvm/test/Verifier/amdgpu-cc.ll =================================================================== --- llvm/test/Verifier/amdgpu-cc.ll +++ llvm/test/Verifier/amdgpu-cc.ll @@ -1,5 +1,7 @@ ; RUN: not llvm-as < %s 2>&1 | FileCheck %s +target datalayout = "A5" + ; CHECK: Calling convention requires void return type ; CHECK-NEXT: i32 ()* @nonvoid_cc_amdgpu_kernel define amdgpu_kernel i32 @nonvoid_cc_amdgpu_kernel() { @@ -13,8 +15,14 @@ } ; CHECK: Calling convention does not allow sret -; CHECK-NEXT: void (i32*)* @sret_cc_amdgpu_kernel -define amdgpu_kernel void @sret_cc_amdgpu_kernel(i32* sret %ptr) { +; CHECK-NEXT: void (i32*)* @sret_cc_amdgpu_kernel_as0 +define amdgpu_kernel void @sret_cc_amdgpu_kernel_as0(i32* sret %ptr) { + ret void +} + +; CHECK: Calling convention does not allow sret +; CHECK-NEXT: void (i32 addrspace(5)*)* @sret_cc_amdgpu_kernel +define amdgpu_kernel void @sret_cc_amdgpu_kernel(i32 addrspace(5)* sret %ptr) { ret void } @@ -53,3 +61,39 @@ define spir_kernel void @varargs_spir_kernel(...) { ret void } + +; CHECK: Calling convention disallows stack byval +; CHECK-NEXT: void (i32 addrspace(5)*)* @byval_cc_amdgpu_kernel +define amdgpu_kernel void @byval_cc_amdgpu_kernel(i32 addrspace(5)* byval %ptr) { + ret void +} + +; CHECK: Calling convention disallows stack byval +; CHECK-NEXT: void (i32 addrspace(5)*)* @byval_cc_amdgpu_vs +define amdgpu_vs void @byval_cc_amdgpu_vs(i32 addrspace(5)* byval %ptr) { + ret void +} + +; CHECK: Calling convention disallows stack byval +; CHECK-NEXT: void (i32 addrspace(5)*)* @byval_cc_amdgpu_hs +define amdgpu_hs void @byval_cc_amdgpu_hs(i32 addrspace(5)* byval %ptr) { + ret void +} + +; CHECK: Calling convention disallows stack byval +; CHECK-NEXT: void (i32 addrspace(5)*)* @byval_cc_amdgpu_gs +define amdgpu_gs void @byval_cc_amdgpu_gs(i32 addrspace(5)* byval %ptr) { + ret void +} + +; CHECK: Calling convention disallows stack byval +; CHECK-NEXT: void (i32 addrspace(5)*)* @byval_cc_amdgpu_ps +define amdgpu_ps void @byval_cc_amdgpu_ps(i32 addrspace(5)* byval %ptr) { + ret void +} + +; CHECK: Calling convention disallows stack byval +; CHECK-NEXT: void (i32 addrspace(5)*)* @byval_cc_amdgpu_cs +define amdgpu_cs void @byval_cc_amdgpu_cs(i32 addrspace(5)* byval %ptr) { + ret void +}