From 22c457a869d5dd9d7e6ca0f97e2a8408bf7326f2 Mon Sep 17 00:00:00 2001 From: "Yaxun (Sam) Liu" Date: Thu, 5 Mar 2020 12:59:33 -0500 Subject: [HIP] Fix device stub name HIP emits a device stub function for each kernel in host code. The HIP debugger requires device stub function to have a different unmangled name as the kernel. Currently the name of the device stub function is the mangled name with a postfix .stub. However, this does not work with the HIP debugger since the unmangled name is the same as the kernel. This patch adds prefix __device__stub__ to the unmangled name of the device stub before mangling, therefore the device stub function has a valid mangled name which is different than the device kernel name. The device side kernel name is kept unchanged. kernels with extern "C" also gets the prefix added to the corresponding device stub function. Differential Revision: https://reviews.llvm.org/D68578 --- clang/lib/CodeGen/CodeGenModule.cpp | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) (limited to 'clang/lib/CodeGen/CodeGenModule.cpp') diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 415633536ad8..0c782e3e968e 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1033,6 +1033,9 @@ static std::string getMangledNameImpl(const CodeGenModule &CGM, GlobalDecl GD, if (FD && FD->getType()->castAs()->getCallConv() == CC_X86RegCall) { Out << "__regcall3__" << II->getName(); + } else if (FD && FD->hasAttr() && + GD.getKernelReferenceKind() == KernelReferenceKind::Stub) { + Out << "__device_stub__" << II->getName(); } else { Out << II->getName(); } @@ -1120,11 +1123,25 @@ StringRef CodeGenModule::getMangledName(GlobalDecl GD) { const auto *ND = cast(GD.getDecl()); std::string MangledName = getMangledNameImpl(*this, GD, ND); - // Adjust kernel stub mangling as we may need to be able to differentiate - // them from the kernel itself (e.g., for HIP). - if (auto *FD = dyn_cast(GD.getDecl())) - if (!getLangOpts().CUDAIsDevice && FD->hasAttr()) - MangledName = getCUDARuntime().getDeviceStubName(MangledName); + // Ensure either we have different ABIs between host and device compilations, + // says host compilation following MSVC ABI but device compilation follows + // Itanium C++ ABI or, if they follow the same ABI, kernel names after + // mangling should be the same after name stubbing. The later checking is + // very important as the device kernel name being mangled in host-compilation + // is used to resolve the device binaries to be executed. Inconsistent naming + // result in undefined behavior. Even though we cannot check that naming + // directly between host- and device-compilations, the host- and + // device-mangling in host compilation could help catching certain ones. + assert(!isa(ND) || !ND->hasAttr() || + getLangOpts().CUDAIsDevice || + (getContext().getAuxTargetInfo() && + (getContext().getAuxTargetInfo()->getCXXABI() != + getContext().getTargetInfo().getCXXABI())) || + getCUDARuntime().getDeviceSideName(ND) == + getMangledNameImpl( + *this, + GD.getWithKernelReferenceKind(KernelReferenceKind::Kernel), + ND)); auto Result = Manglings.insert(std::make_pair(MangledName, GD)); return MangledDeclNames[CanonicalGD] = Result.first->first(); @@ -5282,7 +5299,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { case Decl::CXXConversion: case Decl::CXXMethod: case Decl::Function: - EmitGlobal(cast(D)); + EmitGlobal(getGlobalDecl(cast(D))); // Always provide some coverage mapping // even for the functions that aren't emitted. AddDeferredUnusedCoverageMapping(D); @@ -5944,3 +5961,10 @@ CodeGenModule::createOpenCLIntToSamplerConversion(const Expr *E, "__translate_sampler_initializer"), {C}); } + +GlobalDecl CodeGenModule::getGlobalDecl(const FunctionDecl *FD) { + if (FD->hasAttr()) + return GlobalDecl::getDefaultKernelReference(FD); + else + return GlobalDecl(FD); +} -- cgit v1.2.3