Skip to content

Commit 600069d

Browse files
authored
[DevMSAN] Fix missed symbols __msan_memset & __msan_warning (#16477)
1 parent d830821 commit 600069d

File tree

5 files changed

+167
-50
lines changed

5 files changed

+167
-50
lines changed

libdevice/sanitizer/msan_rtl.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,19 @@ MSAN_MAYBE_WARNING(u16, 2)
159159
MSAN_MAYBE_WARNING(u32, 4)
160160
MSAN_MAYBE_WARNING(u64, 8)
161161

162+
DEVICE_EXTERN_C_NOINLINE void
163+
__msan_warning(const char __SYCL_CONSTANT__ *file, uint32_t line,
164+
const char __SYCL_CONSTANT__ *func) {
165+
__msan_report_error(1, file, line, func);
166+
}
167+
168+
DEVICE_EXTERN_C_NOINLINE void
169+
__msan_warning_noreturn(const char __SYCL_CONSTANT__ *file, uint32_t line,
170+
const char __SYCL_CONSTANT__ *func) {
171+
__msan_internal_report_save(1, file, line, func);
172+
__devicelib_exit();
173+
}
174+
162175
DEVICE_EXTERN_C_NOINLINE uptr __msan_get_shadow(uptr addr, uint32_t as) {
163176
// Return clean shadow (0s) by default
164177
uptr shadow_ptr = (uptr)CleanShadow;
@@ -187,4 +200,19 @@ DEVICE_EXTERN_C_NOINLINE uptr __msan_get_shadow(uptr addr, uint32_t as) {
187200
return shadow_ptr;
188201
}
189202

203+
#define MSAN_MEMSET(as) \
204+
DEVICE_EXTERN_C_NOINLINE void __msan_memset_p##as( \
205+
__attribute__((address_space(as))) char *dest, int val, size_t size) { \
206+
uptr shadow = __msan_get_shadow((uptr)dest, as); \
207+
for (size_t i = 0; i < size; i++) { \
208+
dest[i] = val; \
209+
((__SYCL_GLOBAL__ char *)shadow)[i] = 0; \
210+
} \
211+
}
212+
213+
MSAN_MEMSET(0)
214+
MSAN_MEMSET(1)
215+
MSAN_MEMSET(3)
216+
MSAN_MEMSET(4)
217+
190218
#endif // __SPIR__ || __SPIRV__

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

Lines changed: 80 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,8 @@ static const unsigned kRetvalTLSSize = 800;
233233
// Accesses sizes are powers of two: 1, 2, 4, 8.
234234
static const size_t kNumberOfAccessSizes = 4;
235235

236+
static constexpr unsigned kNumberOfAddressSpace = 5;
237+
236238
/// Track origins of uninitialized values.
237239
///
238240
/// Adds a section to MemorySanitizer report that points to the allocation
@@ -678,6 +680,9 @@ class MemorySanitizer {
678680
/// MSan runtime replacements for memmove, memcpy and memset.
679681
FunctionCallee MemmoveFn, MemcpyFn, MemsetFn;
680682

683+
/// MSan runtime replacements for memset with address space.
684+
FunctionCallee MemsetOffloadFn[kNumberOfAddressSpace];
685+
681686
/// KMSAN callback for task-local function argument shadow.
682687
StructType *MsanContextStateTy;
683688
FunctionCallee MsanGetContextStateFn;
@@ -964,7 +969,19 @@ void MemorySanitizer::createUserspaceApi(Module &M,
964969
} else {
965970
StringRef WarningFnName =
966971
Recover ? "__msan_warning" : "__msan_warning_noreturn";
967-
WarningFn = M.getOrInsertFunction(WarningFnName, IRB.getVoidTy());
972+
if (!TargetTriple.isSPIROrSPIRV()) {
973+
WarningFn = M.getOrInsertFunction(WarningFnName, IRB.getVoidTy());
974+
} else {
975+
// __msan_warning[_noreturn](
976+
// char* file,
977+
// unsigned int line,
978+
// char* func
979+
// )
980+
WarningFn = M.getOrInsertFunction(
981+
WarningFnName, IRB.getVoidTy(),
982+
IRB.getInt8PtrTy(kSpirOffloadConstantAS), IRB.getInt32Ty(),
983+
IRB.getInt8PtrTy(kSpirOffloadConstantAS));
984+
}
968985
}
969986

970987
// Create the global TLS variables.
@@ -1050,13 +1067,24 @@ void MemorySanitizer::initializeCallbacks(Module &M,
10501067
MsanSetOriginFn = M.getOrInsertFunction(
10511068
"__msan_set_origin", TLI.getAttrList(C, {2}, /*Signed=*/false),
10521069
IRB.getVoidTy(), PtrTy, IntptrTy, IRB.getInt32Ty());
1053-
MemmoveFn =
1054-
M.getOrInsertFunction("__msan_memmove", PtrTy, PtrTy, PtrTy, IntptrTy);
1055-
MemcpyFn =
1056-
M.getOrInsertFunction("__msan_memcpy", PtrTy, PtrTy, PtrTy, IntptrTy);
1057-
MemsetFn = M.getOrInsertFunction("__msan_memset",
1058-
TLI.getAttrList(C, {1}, /*Signed=*/true),
1059-
PtrTy, PtrTy, IRB.getInt32Ty(), IntptrTy);
1070+
if (!TargetTriple.isSPIROrSPIRV()) {
1071+
MemmoveFn =
1072+
M.getOrInsertFunction("__msan_memmove", PtrTy, PtrTy, PtrTy, IntptrTy);
1073+
MemcpyFn =
1074+
M.getOrInsertFunction("__msan_memcpy", PtrTy, PtrTy, PtrTy, IntptrTy);
1075+
MemsetFn = M.getOrInsertFunction("__msan_memset",
1076+
TLI.getAttrList(C, {1}, /*Signed=*/true),
1077+
PtrTy, PtrTy, IRB.getInt32Ty(), IntptrTy);
1078+
} else {
1079+
for (unsigned FirstArgAS = 0; FirstArgAS < kNumberOfAddressSpace;
1080+
FirstArgAS++) {
1081+
const std::string Suffix = "_p" + itostr(FirstArgAS);
1082+
PointerType *FirstArgPtrTy = IRB.getPtrTy(FirstArgAS);
1083+
MemsetOffloadFn[FirstArgAS] = M.getOrInsertFunction(
1084+
"__msan_memset" + Suffix, TLI.getAttrList(C, {1}, /*Signed=*/true),
1085+
FirstArgPtrTy, FirstArgPtrTy, IRB.getInt32Ty(), IntptrTy);
1086+
}
1087+
}
10601088

10611089
MsanInstrumentAsmStoreFn = M.getOrInsertFunction(
10621090
"__msan_instrument_asm_store", IRB.getVoidTy(), PtrTy, IntptrTy);
@@ -1560,6 +1588,35 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
15601588
return LazyWarningDebugLocationCount[DebugLoc] >= ClDisambiguateWarning;
15611589
}
15621590

1591+
void appendDebugInfoToArgs(IRBuilder<> &IRB, SmallVectorImpl<Value *> &Args) {
1592+
auto *M = F.getParent();
1593+
auto &C = IRB.getContext();
1594+
auto DebugLoc = IRB.getCurrentDebugLocation();
1595+
1596+
// SPIR constant address space
1597+
auto *ConstASPtrTy =
1598+
PointerType::get(Type::getInt8Ty(C), kSpirOffloadConstantAS);
1599+
1600+
// file name and line number
1601+
if (DebugLoc) {
1602+
llvm::SmallString<128> Source = DebugLoc->getDirectory();
1603+
sys::path::append(Source, DebugLoc->getFilename());
1604+
auto *FileNameGV = getOrCreateGlobalString(*M, "__msan_file", Source,
1605+
kSpirOffloadConstantAS);
1606+
Args.push_back(ConstantExpr::getPointerCast(FileNameGV, ConstASPtrTy));
1607+
Args.push_back(ConstantInt::get(Type::getInt32Ty(C), DebugLoc.getLine()));
1608+
} else {
1609+
Args.push_back(ConstantPointerNull::get(ConstASPtrTy));
1610+
Args.push_back(ConstantInt::get(Type::getInt32Ty(C), 0));
1611+
}
1612+
1613+
// function name
1614+
auto FuncName = F.getName();
1615+
auto *FuncNameGV = getOrCreateGlobalString(
1616+
*M, "__msan_func", demangle(FuncName), kSpirOffloadConstantAS);
1617+
Args.push_back(ConstantExpr::getPointerCast(FuncNameGV, ConstASPtrTy));
1618+
}
1619+
15631620
/// Helper function to insert a warning at IRB's current insert point.
15641621
void insertWarningFn(IRBuilder<> &IRB, Value *Origin) {
15651622
if (!Origin)
@@ -1584,10 +1641,16 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
15841641
}
15851642
}
15861643

1587-
if (MS.CompileKernel || MS.TrackOrigins)
1588-
IRB.CreateCall(MS.WarningFn, Origin)->setCannotMerge();
1589-
else
1590-
IRB.CreateCall(MS.WarningFn)->setCannotMerge();
1644+
if (!SpirOrSpirv) {
1645+
if (MS.CompileKernel || MS.TrackOrigins)
1646+
IRB.CreateCall(MS.WarningFn, Origin)->setCannotMerge();
1647+
else
1648+
IRB.CreateCall(MS.WarningFn)->setCannotMerge();
1649+
} else { // SPIR or SPIR-V
1650+
SmallVector<Value *, 3> Args;
1651+
appendDebugInfoToArgs(IRB, Args);
1652+
IRB.CreateCall(MS.WarningFn, Args)->setCannotMerge();
1653+
}
15911654
// FIXME: Insert UnreachableInst if !MS.Recover?
15921655
// This may invalidate some of the following checks and needs to be done
15931656
// at the very end.
@@ -1617,43 +1680,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
16171680
ConvertedShadow2,
16181681
MS.TrackOrigins && Origin ? Origin : (Value *)IRB.getInt32(0)};
16191682

1620-
{
1621-
auto *M = F.getParent();
1622-
auto *ConstASPtrTy = IRB.getInt8PtrTy(kSpirOffloadConstantAS);
1623-
1624-
// file name and line number
1625-
{
1626-
bool HasDebugLoc = false;
1627-
auto *ConvertedShadowInst = dyn_cast<Instruction>(ConvertedShadow);
1628-
1629-
if (ConvertedShadowInst) {
1630-
if (auto &Loc = ConvertedShadowInst->getDebugLoc()) {
1631-
llvm::SmallString<128> Source = Loc->getDirectory();
1632-
sys::path::append(Source, Loc->getFilename());
1633-
auto *FileNameGV = getOrCreateGlobalString(
1634-
*M, "__asan_file", Source, kSpirOffloadConstantAS);
1635-
Args.push_back(
1636-
ConstantExpr::getPointerCast(FileNameGV, ConstASPtrTy));
1637-
Args.push_back(
1638-
ConstantInt::get(IRB.getInt32Ty(), Loc.getLine()));
1639-
1640-
HasDebugLoc = true;
1641-
}
1642-
}
1643-
1644-
if (!HasDebugLoc) {
1645-
Args.push_back(ConstantPointerNull::get(ConstASPtrTy));
1646-
Args.push_back(ConstantInt::get(IRB.getInt32Ty(), 0));
1647-
}
1648-
}
1649-
1650-
// function name
1651-
auto FuncName = F.getName();
1652-
auto *FuncNameGV = getOrCreateGlobalString(
1653-
*M, "__asan_func", demangle(FuncName), kSpirOffloadConstantAS);
1654-
Args.push_back(
1655-
ConstantExpr::getPointerCast(FuncNameGV, ConstASPtrTy));
1656-
}
1683+
appendDebugInfoToArgs(IRB, Args);
16571684

16581685
CallBase *CB = IRB.CreateCall(Fn, Args);
16591686
CB->addParamAttr(0, Attribute::ZExt);
@@ -3160,7 +3187,10 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
31603187
void visitMemSetInst(MemSetInst &I) {
31613188
IRBuilder<> IRB(&I);
31623189
IRB.CreateCall(
3163-
MS.MemsetFn,
3190+
SpirOrSpirv ? MS.MemsetOffloadFn[cast<PointerType>(
3191+
I.getArgOperand(0)->getType())
3192+
->getAddressSpace()]
3193+
: MS.MemsetFn,
31643194
{I.getArgOperand(0),
31653195
IRB.CreateIntCast(I.getArgOperand(1), IRB.getInt32Ty(), false),
31663196
IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
; RUN: opt < %s -passes=msan -msan-instrumentation-with-call-threshold=0 -msan-eager-checks=1 -S | FileCheck %s
2+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"
3+
target triple = "spir64-unknown-unknown"
4+
5+
; Function Attrs: sanitize_memory
6+
define spir_kernel void @MyKernel(<3 x i32> %extractVec.i8.i.i.i) #0 {
7+
; CHECK-LABEL: @MyKernel
8+
entry:
9+
br label %for.body.i
10+
11+
; CHECK: call void @__msan_warning_noreturn(ptr addrspace(2) null, i32 0, ptr addrspace(2) @__msan_func_MyKernel)
12+
for.body.i: ; preds = %for.body.i, %entry
13+
%div.i.i.i.i.i.i = sdiv <3 x i32> zeroinitializer, %extractVec.i8.i.i.i
14+
br label %for.body.i
15+
}
16+
17+
attributes #0 = { sanitize_memory }
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
; RUN: opt < %s -passes=msan -msan-instrumentation-with-call-threshold=0 -msan-eager-checks=1 -S | FileCheck %s
2+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"
3+
target triple = "spir64-unknown-unknown"
4+
5+
define spir_kernel void @MyKernel(ptr %offset.i) {
6+
; CHECK-LABEL: @MyKernel
7+
entry:
8+
call void @llvm.memset.p0.i64(ptr %offset.i, i8 0, i64 0, i1 false)
9+
; CHECK: call ptr @__msan_memset_p0
10+
ret void
11+
}
12+
13+
; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
14+
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #0
15+
16+
attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// REQUIRES: linux, cpu || (gpu && level_zero)
2+
// RUN: %{build} %device_msan_flags -O1 -g -o %t2.out
3+
// RUN: %{run} not %t2.out 2>&1 | FileCheck %s
4+
// RUN: %{build} %device_msan_flags -O2 -g -o %t3.out
5+
// RUN: %{run} not %t3.out 2>&1 | FileCheck %s
6+
7+
#include "sycl/detail/core.hpp"
8+
#include <sycl/vector.hpp>
9+
10+
int main() {
11+
sycl::buffer<sycl::int3, 1> b(sycl::range<1>(2));
12+
sycl::queue myQueue;
13+
myQueue
14+
.submit([&](sycl::handler &cgh) {
15+
auto B = b.get_access<sycl::access::mode::read_write>(cgh);
16+
cgh.parallel_for<class MyKernel>(
17+
sycl::range<1>{2}, [=](sycl::id<1> ID) {
18+
B[ID] = sycl::int3{(sycl::int3)ID[0]} / B[ID];
19+
});
20+
})
21+
.wait();
22+
// CHECK: use-of-uninitialized-value
23+
// CHECK: kernel <{{.*MyKernel}}>
24+
25+
return 0;
26+
}

0 commit comments

Comments
 (0)