diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -523,6 +523,22 @@ !Context.getTargetInfo().getTriple().isOSEmscripten()) { EmitMainVoidAlias(); } + + // Emit reference of __amdgpu_device_library_preserve_asan_functions to + // preserve ASAN functions in bitcode libraries. + if (LangOpts.Sanitize.has(SanitizerKind::Address) && getTriple().isAMDGPU()) { + auto *FT = llvm::FunctionType::get(VoidTy, {}); + auto *F = llvm::Function::Create( + FT, llvm::GlobalValue::ExternalLinkage, + "__amdgpu_device_library_preserve_asan_functions", &getModule()); + auto *Var = new llvm::GlobalVariable( + getModule(), FT->getPointerTo(), + /*isConstant=*/true, llvm::GlobalValue::WeakAnyLinkage, F, + "__amdgpu_device_library_preserve_asan_functions_ptr", nullptr, + llvm::GlobalVariable::NotThreadLocal); + addCompilerUsedGlobal(Var); + } + emitLLVMUsed(); if (SanStats) SanStats->finish(); diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -2973,12 +2973,9 @@ // a fat binary containing all the code objects for different GPU's. // The fat binary is then an input to the host action. for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) { - if (GPUSanitize || C.getDriver().isUsingLTO(/*IsOffload=*/true)) { - // When GPU sanitizer is enabled, since we need to link in the - // the sanitizer runtime library after the sanitize pass, we have - // to skip the backend and assemble phases and use lld to link - // the bitcode. The same happens if users request to use LTO - // explicitly. + if (C.getDriver().isUsingLTO(/*IsOffload=*/true)) { + // When LTO is enabled, skip the backend and assemble phases and + // use lld to link the bitcode. ActionList AL; AL.push_back(CudaDeviceActions[I]); // Create a link action to link device IR with device library @@ -2986,7 +2983,7 @@ CudaDeviceActions[I] = C.MakeAction(AL, types::TY_Image); } else { - // When GPU sanitizer is not enabled, we follow the conventional + // When LTO is not enabled, we follow the conventional // compiler phases, including backend and assemble phases. ActionList AL; auto BackendAction = C.getDriver().ConstructPhaseAction( diff --git a/clang/test/CodeGenCUDA/amdgpu-asan.cu b/clang/test/CodeGenCUDA/amdgpu-asan.cu new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenCUDA/amdgpu-asan.cu @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=amdgcn-amd-amdhsa \ +// RUN: -fcuda-is-device -target-cpu gfx906 -fsanitize=address \ +// RUN: -x hip | FileCheck -check-prefix=ASAN %s + +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=amdgcn-amd-amdhsa \ +// RUN: -fcuda-is-device -target-cpu gfx906 -x hip \ +// RUN: | FileCheck %s + +// REQUIRES: amdgpu-registered-target + +// ASAN-DAG: declare void @__amdgpu_device_library_preserve_asan_functions() +// ASAN-DAG: @__amdgpu_device_library_preserve_asan_functions_ptr = weak addrspace(1) constant void ()* @__amdgpu_device_library_preserve_asan_functions +// ASAN-DAG: @llvm.compiler.used = {{.*}}@__amdgpu_device_library_preserve_asan_functions_ptr + +// CHECK-NOT: @__amdgpu_device_library_preserve_asan_functions_ptr diff --git a/clang/test/Driver/hip-sanitize-options.hip b/clang/test/Driver/hip-sanitize-options.hip --- a/clang/test/Driver/hip-sanitize-options.hip +++ b/clang/test/Driver/hip-sanitize-options.hip @@ -34,7 +34,7 @@ // CHECK-NOT: {{"[^"]*lld(\.exe){0,1}".* ".*hip.bc"}} // CHECK: {{"[^"]*clang[^"]*".* "-triple" "x86_64-unknown-linux-gnu".* "-fsanitize=address"}} -// NORDC: {{"[^"]*clang[^"]*".* "-fcuda-is-device".* "-fsanitize=address".*}} "-o" "[[OUT:[^"]*.bc]]" +// NORDC: {{"[^"]*clang[^"]*".* "-emit-obj".* "-fcuda-is-device".* "-fsanitize=address".*}} "-o" "[[OUT:[^"]*.o]]" // NORDC: {{"[^"]*lld(\.exe){0,1}".*}} "[[OUT]]" {{".*asanrtl.bc" ".*hip.bc"}} // NORDC: {{"[^"]*clang[^"]*".* "-triple" "x86_64-unknown-linux-gnu".* "-fsanitize=address"}}