Skip to content

Commit eefc9ea

Browse files
committed
Add __MsanKernelMetadata
1 parent 7384106 commit eefc9ea

File tree

8 files changed

+178
-25
lines changed

8 files changed

+178
-25
lines changed

clang/lib/Driver/OffloadBundler.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -687,12 +687,12 @@ class ObjectFileHandler final : public FileHandler {
687687
if (Error Err = Symbol.printName(NameOS))
688688
return std::move(Err);
689689

690-
// If we are dealing with a bitcode file do not add special globals
691-
// llvm.used and llvm.compiler.used and __AsanDeviceGlobalMetadata to
690+
// If we are dealing with a bitcode file do not add special globals to
692691
// the list of defined symbols.
693692
if (SF->isIR() &&
694693
(Name == "llvm.used" || Name == "llvm.compiler.used" ||
695-
Name == "__AsanDeviceGlobalMetadata"))
694+
Name == "__AsanDeviceGlobalMetadata" ||
695+
Name == "__MsanKernelMetadata"))
696696
continue;
697697

698698
// Add symbol name with the target prefix to the buffer.

llvm/include/llvm/SYCLLowerIR/ComputeModuleRuntimeInfo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ struct GlobalBinImageProps {
2929
bool EmitDeviceGlobalPropSet;
3030
};
3131
bool isModuleUsingAsan(const Module &M);
32+
bool isModuleUsingMsan(const Module &M);
3233
using PropSetRegTy = llvm::util::PropertySetRegistry;
3334
using EntryPointSet = SetVector<Function *>;
3435

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//===-- SanitizerKernelMetadata.h - fix kernel medatadata for sanitizer ---===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
// This pass fixes attributes and metadata of the global variable
9+
// "__XsanKernelMetadata"
10+
//===----------------------------------------------------------------------===//
11+
12+
#pragma once
13+
14+
#include "llvm/IR/PassManager.h"
15+
16+
namespace llvm {
17+
18+
class SanitizerKernelMetadataPass
19+
: public PassInfoMixin<SanitizerKernelMetadataPass> {
20+
public:
21+
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
22+
};
23+
24+
} // namespace llvm

llvm/lib/SYCLLowerIR/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ add_llvm_component_library(LLVMSYCLLowerIR
7474
GlobalOffset.cpp
7575
TargetHelpers.cpp
7676

77+
SanitizerKernelMetadata.cpp
78+
7779
ADDITIONAL_HEADER_DIRS
7880
${LLVM_MAIN_INCLUDE_DIR}/llvm/SYCLLowerIR
7981
${LLVM_MAIN_SRC_DIR}/projects/vc-intrinsics/GenXIntrinsics/include

llvm/lib/SYCLLowerIR/ComputeModuleRuntimeInfo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ bool isModuleUsingAsan(const Module &M) {
5959
}
6060

6161
bool isModuleUsingMsan(const Module &M) {
62-
return M.getGlobalVariable("__MsanLaunchInfo") != nullptr;
62+
return M.getGlobalVariable("__MsanKernelMetadata") != nullptr;
6363
}
6464

6565
// This function traverses over reversed call graph by BFS algorithm.
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//===-- SanitizerKernelMetadata.cpp - fix kernel medatadata for sanitizer -===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
// This pass fixes attributes and metadata of global variable
9+
// "__SanitizerKernelMetadata".
10+
// We treat "__SanitizerKernelMetadata" as a device global variable, so that it
11+
// can be read by runtime. "spirv.Decorations" is removed by llvm-link, so we
12+
// add it here again.
13+
//===----------------------------------------------------------------------===//
14+
15+
#include "llvm/SYCLLowerIR/SanitizerKernelMetadata.h"
16+
17+
#include "llvm/IR/IRBuilder.h"
18+
19+
#define DEBUG_TYPE "SanitizerKernelMetadata"
20+
21+
using namespace llvm;
22+
23+
namespace llvm {
24+
25+
constexpr StringRef SPIRV_DECOR_MD_KIND = "spirv.Decorations";
26+
constexpr uint32_t SPIRV_HOST_ACCESS_DECOR = 6147;
27+
28+
PreservedAnalyses SanitizerKernelMetadataPass::run(Module &M,
29+
ModuleAnalysisManager &MAM) {
30+
auto *KernelMetadata = M.getNamedGlobal("__MsanKernelMetadata");
31+
if (!KernelMetadata) {
32+
return PreservedAnalyses::all();
33+
}
34+
35+
auto &DL = M.getDataLayout();
36+
auto &Ctx = M.getContext();
37+
38+
// Fix attributes
39+
KernelMetadata->addAttribute(
40+
"sycl-device-global-size",
41+
std::to_string(DL.getTypeAllocSize(KernelMetadata->getValueType())));
42+
43+
// Fix metadata
44+
unsigned MDKindID = Ctx.getMDKindID(SPIRV_DECOR_MD_KIND);
45+
46+
SmallVector<Metadata *, 1> MDOps;
47+
48+
SmallVector<Metadata *, 3> MD;
49+
auto *Ty = Type::getInt32Ty(Ctx);
50+
MD.push_back(ConstantAsMetadata::get(
51+
Constant::getIntegerValue(Ty, APInt(32, SPIRV_HOST_ACCESS_DECOR))));
52+
MD.push_back(
53+
ConstantAsMetadata::get(Constant::getIntegerValue(Ty, APInt(32, 0))));
54+
MD.push_back(MDString::get(Ctx, "_Z20__SanitizerKernelMetadata"));
55+
56+
MDOps.push_back(MDNode::get(Ctx, MD));
57+
58+
KernelMetadata->addMetadata(MDKindID, *MDNode::get(Ctx, MDOps));
59+
60+
return PreservedAnalyses::none();
61+
}
62+
63+
} // namespace llvm

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

Lines changed: 76 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,71 @@ MemorySanitizerOptions::MemorySanitizerOptions(int TO, bool R, bool K,
730730
Recover(getOptOrDefault(ClKeepGoing, Kernel || R)),
731731
EagerChecks(getOptOrDefault(ClEagerChecks, EagerChecks)) {}
732732

733+
static StringMap<GlobalVariable *> GlobalStringMap;
734+
735+
GlobalVariable *getOrCreateGlobalString(Module &M, StringRef Name,
736+
StringRef Value,
737+
unsigned AddressSpace) {
738+
GlobalVariable *StringGV = nullptr;
739+
if (GlobalStringMap.find(Value.str()) != GlobalStringMap.end())
740+
return GlobalStringMap.at(Value.str());
741+
742+
auto *Ty = ArrayType::get(Type::getInt8Ty(M.getContext()), Value.size() + 1);
743+
StringGV = new GlobalVariable(
744+
M, Ty, true, GlobalValue::InternalLinkage,
745+
ConstantDataArray::getString(M.getContext(), Value), Name, nullptr,
746+
GlobalValue::NotThreadLocal, AddressSpace);
747+
GlobalStringMap[Value.str()] = StringGV;
748+
749+
return StringGV;
750+
}
751+
752+
static void extendSpirKernelArgs(Module &M) {
753+
SmallVector<Constant *, 8> SpirKernelsMetadata;
754+
755+
auto DL = M.getDataLayout();
756+
Type *IntptrTy = DL.getIntPtrType(M.getContext());
757+
758+
// SpirKernelsMetadata only saves fixed kernels, and is described by
759+
// following structure:
760+
// uptr unmangled_kernel_name
761+
// uptr unmangled_kernel_name_size
762+
StructType *StructTy = StructType::get(IntptrTy, IntptrTy);
763+
for (Function &F : M) {
764+
if (F.getCallingConv() != CallingConv::SPIR_KERNEL)
765+
continue;
766+
767+
if (!F.hasFnAttribute(Attribute::SanitizeMemory) ||
768+
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
769+
continue;
770+
771+
auto KernelName = F.getName();
772+
auto *KernelNameGV = getOrCreateGlobalString(M, "__msan_kernel", KernelName,
773+
kSpirOffloadGlobalAS);
774+
SpirKernelsMetadata.emplace_back(ConstantStruct::get(
775+
StructTy, ConstantExpr::getPointerCast(KernelNameGV, IntptrTy),
776+
ConstantInt::get(IntptrTy, KernelName.size())));
777+
}
778+
779+
// Create global variable to record spirv kernels' information
780+
ArrayType *ArrayTy = ArrayType::get(StructTy, SpirKernelsMetadata.size());
781+
Constant *MetadataInitializer =
782+
ConstantArray::get(ArrayTy, SpirKernelsMetadata);
783+
GlobalVariable *MsanSpirKernelMetadata = new GlobalVariable(
784+
M, MetadataInitializer->getType(), false, GlobalValue::AppendingLinkage,
785+
MetadataInitializer, "__MsanKernelMetadata", nullptr,
786+
GlobalValue::NotThreadLocal, 1);
787+
MsanSpirKernelMetadata->setUnnamedAddr(GlobalValue::UnnamedAddr::Local);
788+
// Add device global attributes
789+
MsanSpirKernelMetadata->addAttribute(
790+
"sycl-device-global-size", std::to_string(DL.getTypeAllocSize(ArrayTy)));
791+
MsanSpirKernelMetadata->addAttribute("sycl-device-image-scope");
792+
MsanSpirKernelMetadata->addAttribute("sycl-host-access", "0"); // read only
793+
MsanSpirKernelMetadata->addAttribute("sycl-unique-id",
794+
"_Z20__MsanKernelMetadata");
795+
MsanSpirKernelMetadata->setDSOLocal(true);
796+
}
797+
733798
PreservedAnalyses MemorySanitizerPass::run(Module &M,
734799
ModuleAnalysisManager &AM) {
735800
// Return early if nosanitize_memory module flag is present for the module.
@@ -743,6 +808,11 @@ PreservedAnalyses MemorySanitizerPass::run(Module &M,
743808
Modified = true;
744809
}
745810

811+
if (TargetTriple.isSPIROrSPIRV()) {
812+
extendSpirKernelArgs(M);
813+
Modified = true;
814+
}
815+
746816
auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
747817
for (Function &F : M) {
748818
if (F.empty())
@@ -752,6 +822,10 @@ PreservedAnalyses MemorySanitizerPass::run(Module &M,
752822
Msan.sanitizeFunction(F, FAM.getResult<TargetLibraryAnalysis>(F));
753823
}
754824

825+
// Clear GlobalStringMap to prevent its content from being used by other
826+
// modules
827+
GlobalStringMap.clear();
828+
755829
if (!Modified)
756830
return PreservedAnalyses::all();
757831

@@ -1276,7 +1350,6 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
12761350
SmallVector<std::pair<IntrinsicInst *, AllocaInst *>, 16> LifetimeStartList;
12771351
SmallVector<StoreInst *, 16> StoreList;
12781352
int64_t SplittableBlocksCount = 0;
1279-
StringMap<GlobalVariable *> GlobalStringMap;
12801353

12811354
MemorySanitizerVisitor(Function &F, MemorySanitizer &MS,
12821355
const TargetLibraryInfo &TLI)
@@ -1474,24 +1547,6 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
14741547
return LazyWarningDebugLocationCount[DebugLoc] >= ClDisambiguateWarning;
14751548
}
14761549

1477-
GlobalVariable *GetOrCreateGlobalString(Module &M, StringRef Name,
1478-
StringRef Value,
1479-
unsigned AddressSpace) {
1480-
GlobalVariable *StringGV = nullptr;
1481-
if (GlobalStringMap.find(Value.str()) != GlobalStringMap.end())
1482-
return GlobalStringMap.at(Value.str());
1483-
1484-
auto *Ty =
1485-
ArrayType::get(Type::getInt8Ty(M.getContext()), Value.size() + 1);
1486-
StringGV = new GlobalVariable(
1487-
M, Ty, true, GlobalValue::InternalLinkage,
1488-
ConstantDataArray::getString(M.getContext(), Value), Name, nullptr,
1489-
GlobalValue::NotThreadLocal, AddressSpace);
1490-
GlobalStringMap[Value.str()] = StringGV;
1491-
1492-
return StringGV;
1493-
}
1494-
14951550
/// Helper function to insert a warning at IRB's current insert point.
14961551
void insertWarningFn(IRBuilder<> &IRB, Value *Origin) {
14971552
if (!Origin)
@@ -1562,7 +1617,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
15621617
if (auto &Loc = ConvertedShadowInst->getDebugLoc()) {
15631618
llvm::SmallString<128> Source = Loc->getDirectory();
15641619
sys::path::append(Source, Loc->getFilename());
1565-
auto *FileNameGV = GetOrCreateGlobalString(
1620+
auto *FileNameGV = getOrCreateGlobalString(
15661621
*M, "__asan_file", Source, kSpirOffloadConstantAS);
15671622
Args.push_back(
15681623
ConstantExpr::getPointerCast(FileNameGV, ConstASPtrTy));
@@ -1581,7 +1636,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
15811636

15821637
// function name
15831638
auto FuncName = F.getName();
1584-
auto *FuncNameGV = GetOrCreateGlobalString(
1639+
auto *FuncNameGV = getOrCreateGlobalString(
15851640
*M, "__asan_func", demangle(FuncName), kSpirOffloadConstantAS);
15861641
Args.push_back(
15871642
ConstantExpr::getPointerCast(FuncNameGV, ConstASPtrTy));

llvm/tools/sycl-post-link/sycl-post-link.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "llvm/SYCLLowerIR/ModuleSplitter.h"
4141
#include "llvm/SYCLLowerIR/SYCLJointMatrixTransform.h"
4242
#include "llvm/SYCLLowerIR/SYCLUtils.h"
43+
#include "llvm/SYCLLowerIR/SanitizerKernelMetadata.h"
4344
#include "llvm/SYCLLowerIR/SpecConstants.h"
4445
#include "llvm/SYCLLowerIR/Support.h"
4546
#include "llvm/Support/CommandLine.h"
@@ -790,6 +791,13 @@ processInputModule(std::unique_ptr<Module> M) {
790791
if (M->getTargetTriple().find("spir") != std::string::npos)
791792
Modified |= removeDeviceGlobalFromCompilerUsed(*M.get());
792793

794+
// AddressSanitizer specific passes
795+
if (isModuleUsingMsan(*M)) {
796+
// Fix attributes and metadata of the global variable
797+
// "__AsanKernelMetadata"
798+
Modified |= runModulePass<SanitizerKernelMetadataPass>(*M);
799+
}
800+
793801
// Transform Joint Matrix builtin calls to align them with SPIR-V friendly
794802
// LLVM IR specification.
795803
Modified |= runModulePass<SYCLJointMatrixTransformPass>(*M);

0 commit comments

Comments
 (0)