From 66070f4db7a8116a822a7d435da8e6a28ba432ab Mon Sep 17 00:00:00 2001 From: Joey F Date: Mon, 16 Jun 2025 18:12:04 -0400 Subject: [PATCH 1/2] IR/Verifier: Do not allow kernel to kernel calls. Allowing a kernel to call another kernel is invalid. This extends the Verifier to recognize this fact. The calling convention is retrieved from the module because it may not be labeling the callsite. --- llvm/lib/IR/Verifier.cpp | 12 ++++++++++++ llvm/test/Verifier/AMDGPU/kernel-recursivecall.ll | 9 +++++++++ 2 files changed, 21 insertions(+) create mode 100755 llvm/test/Verifier/AMDGPU/kernel-recursivecall.ll diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 592bb6aa90613..179cb85ca04f4 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -3636,6 +3636,18 @@ void Verifier::visitCallBase(CallBase &Call) { Check(isCallableCC(Call.getCallingConv()), "calling convention does not permit calls", Call); + // Find the actual CC of the callee from the Module. + CallingConv::ID CalleeCC = Call.getParent()->getParent()->getParent() + ->getFunction(Call.getCalledFunction()->getName())->getCallingConv(); + // Verify that a kernel does not call another kernel. + if (CalleeCC == CallingConv::AMDGPU_KERNEL || + CalleeCC == CallingConv::SPIR_KERNEL) { + CallingConv::ID CallerCC = Call.getParent()->getParent()->getCallingConv(); + Check(CallerCC != CallingConv::AMDGPU_KERNEL && + CallerCC != CallingConv::SPIR_KERNEL, + "a kernel may not call a kernel", Call.getParent()->getParent()); + } + // Disallow passing/returning values with alignment higher than we can // represent. // FIXME: Consider making DataLayout cap the alignment, so this isn't diff --git a/llvm/test/Verifier/AMDGPU/kernel-recursivecall.ll b/llvm/test/Verifier/AMDGPU/kernel-recursivecall.ll new file mode 100755 index 0000000000000..83e8f6dadedfe --- /dev/null +++ b/llvm/test/Verifier/AMDGPU/kernel-recursivecall.ll @@ -0,0 +1,9 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +define amdgpu_kernel void @kernel(ptr addrspace(1) %out, i32 %n) { +entry: +; CHECK: a kernel may not call a kernel +; CHECK-NEXT: ptr @kernel + call void @kernel(ptr addrspace(1) %out, i32 %n) + ret void +} From 1f463183bc62fc95b353f7ccbc0648a0cdd0b095 Mon Sep 17 00:00:00 2001 From: Joey F Date: Tue, 17 Jun 2025 09:53:44 -0400 Subject: [PATCH 2/2] Merge rules together. --- llvm/lib/IR/Verifier.cpp | 15 +++------------ llvm/test/Verifier/AMDGPU/kernel-recursivecall.ll | 6 +++--- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 179cb85ca04f4..e17e7fafa6b6f 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -3632,21 +3632,12 @@ void Verifier::visitCallBase(CallBase &Call) { Check(Callee->getValueType() == FTy, "Intrinsic called with incompatible signature", Call); - // Verify if the calling convention of the callee is callable. - Check(isCallableCC(Call.getCallingConv()), - "calling convention does not permit calls", Call); - // Find the actual CC of the callee from the Module. CallingConv::ID CalleeCC = Call.getParent()->getParent()->getParent() ->getFunction(Call.getCalledFunction()->getName())->getCallingConv(); - // Verify that a kernel does not call another kernel. - if (CalleeCC == CallingConv::AMDGPU_KERNEL || - CalleeCC == CallingConv::SPIR_KERNEL) { - CallingConv::ID CallerCC = Call.getParent()->getParent()->getCallingConv(); - Check(CallerCC != CallingConv::AMDGPU_KERNEL && - CallerCC != CallingConv::SPIR_KERNEL, - "a kernel may not call a kernel", Call.getParent()->getParent()); - } + // Verify if the calling convention of the callee is callable. + Check(isCallableCC(CalleeCC), + "calling convention does not permit calls", Call); // Disallow passing/returning values with alignment higher than we can // represent. diff --git a/llvm/test/Verifier/AMDGPU/kernel-recursivecall.ll b/llvm/test/Verifier/AMDGPU/kernel-recursivecall.ll index 83e8f6dadedfe..34513fcdecccf 100755 --- a/llvm/test/Verifier/AMDGPU/kernel-recursivecall.ll +++ b/llvm/test/Verifier/AMDGPU/kernel-recursivecall.ll @@ -1,9 +1,9 @@ -; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s +; RUN: not llvm-as %s -disable-output 2>&1 | FileCheck %s define amdgpu_kernel void @kernel(ptr addrspace(1) %out, i32 %n) { entry: -; CHECK: a kernel may not call a kernel -; CHECK-NEXT: ptr @kernel +; CHECK: calling convention does not permit calls +; CHECK-NEXT: call void @kernel(ptr addrspace(1) %out, i32 %n) call void @kernel(ptr addrspace(1) %out, i32 %n) ret void }