From b3306eca3743294252d6efe683c174bf2d071833 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Wed, 23 Apr 2025 10:41:37 +0200 Subject: [PATCH 1/3] wip --- libdevice/sanitizer/msan_rtl.cpp | 22 +++++++++++++ .../Instrumentation/MemorySanitizer.cpp | 31 ++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/libdevice/sanitizer/msan_rtl.cpp b/libdevice/sanitizer/msan_rtl.cpp index dad35683cb990..4e4eaff49df0f 100644 --- a/libdevice/sanitizer/msan_rtl.cpp +++ b/libdevice/sanitizer/msan_rtl.cpp @@ -564,4 +564,26 @@ DEVICE_EXTERN_C_NOINLINE void __msan_unpoison_stack(__SYCL_PRIVATE__ void *ptr, __spirv_ocl_printf(__msan_print_func_end, "__msan_unpoison_stack")); } +void __msan_unpoison_strided_copy(uptr dest, uptr src, uptr counts, uptr stride) { + if (!GetMsanLaunchInfo) + return; + + MSAN_DEBUG(__spirv_ocl_printf(__msan_print_func_beg, + "__msan_unpoison_strided_copy")); + + for (uptr i = 0; i < counts; ++i) { + auto shadow_address = __msan_get_shadow(dest, ADDRESS_SPACE_PRIVATE); + MSAN_DEBUG(__spirv_ocl_printf(__msan_print_set_shadow_private, + (void *)shadow_address, + (void *)(shadow_address + stride), 0x0)); + + for (size_t j = 0; j < stride; j++) + ((__SYCL_GLOBAL__ u8 *)shadow_address)[j] = 0; + dest += stride; + } + + MSAN_DEBUG(__spirv_ocl_printf(__msan_print_func_end, + "__msan_unpoison_strided_copy")); +} + #endif // __SPIR__ || __SPIRV__ diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index 56b0b89c9c253..a154fca9f24b9 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -810,6 +810,8 @@ class MemorySanitizerOnSpirv { void initializeKernelCallerMap(Function *F); private: + friend struct MemorySanitizerVisitor; + Module &M; LLVMContext &C; const DataLayout &DL; @@ -836,6 +838,7 @@ class MemorySanitizerOnSpirv { FunctionCallee MsanUnpoisonShadowDynamicLocalFunc; FunctionCallee MsanBarrierFunc; FunctionCallee MsanUnpoisonStackFunc; + FunctionCallee MsanShadowStridedCopyFunc; }; } // end anonymous namespace @@ -926,6 +929,10 @@ void MemorySanitizerOnSpirv::initializeCallbacks() { // ) MsanUnpoisonStackFunc = M.getOrInsertFunction( "__msan_unpoison_stack", IRB.getVoidTy(), PtrTy, IntptrTy); + + MsanShadowStridedCopyFunc = + M.getOrInsertFunction("__msan_unpoison_strided_copy", IRB.getVoidTy(), IntptrTy, + IntptrTy, IRB.getInt64Ty(), IRB.getInt64Ty()); } // Handle global variables: @@ -1804,7 +1811,7 @@ static void setNoSanitizedMetadataSPIR(Instruction &I) { } } else { auto FuncName = Func->getName(); - if (FuncName.contains("__spirv_")) + if (FuncName.contains("__spirv_") && !FuncName.contains("__spirv_GroupAsyncCopy")) I.setNoSanitizeMetadata(); } } @@ -5994,6 +6001,8 @@ struct MemorySanitizerVisitor : public InstVisitor { void visitCallBase(CallBase &CB) { assert(!CB.getMetadata(LLVMContext::MD_nosanitize)); + outs() << "!!! call base\n"; + if (CB.isInlineAsm()) { // For inline asm (either a call to asm function, or callbr instruction), // do the usual thing: check argument shadow and mark all outputs as @@ -6029,6 +6038,7 @@ struct MemorySanitizerVisitor : public InstVisitor { if (auto *Call = dyn_cast(&CB)) { assert(!isa(Call) && "intrinsics are handled elsewhere"); + outs() << "!!! call inst\n"; // We are going to insert code that relies on the fact that the callee // will become a non-readonly function after it is instrumented by us. To @@ -6151,6 +6161,25 @@ struct MemorySanitizerVisitor : public InstVisitor { VAHelper->visitCallBase(CB, IRB); } + if (SpirOrSpirv) { + auto *Func = CB.getCalledFunction(); + if (Func) { + auto FuncName = Func->getName(); + outs() << "!!!! " << FuncName << "\n"; + if (FuncName.contains("__spirv_GroupAsyncCopy")) { + auto *Dest = CB.getArgOperand(1); + auto *Src = CB.getArgOperand(2); + auto *NumElements = CB.getArgOperand(3); + auto *Stride = CB.getArgOperand(4); + + IRB.CreateCall(MS.Spirv.MsanShadowStridedCopyFunc, + {IRB.CreatePointerCast(Dest, MS.Spirv.IntptrTy), + IRB.CreatePointerCast(Src, MS.Spirv.IntptrTy), NumElements, + Stride}); + } + } + } + // Now, get the shadow for the RetVal. if (!CB.getType()->isSized()) return; From ba8223d50f485e363620656da16f59c8dfdda81b Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Fri, 25 Apr 2025 10:29:03 +0200 Subject: [PATCH 2/3] wip --- .../Instrumentation/MemorySanitizer.cpp | 65 +++++++++++++++++-- 1 file changed, 58 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index de2348bdb56c5..2466de3b310b3 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -832,7 +832,7 @@ class MemorySanitizerOnSpirv { FunctionCallee MsanUnpoisonShadowDynamicLocalFunc; FunctionCallee MsanBarrierFunc; FunctionCallee MsanUnpoisonStackFunc; - FunctionCallee MsanShadowStridedCopyFunc; + FunctionCallee MsanUnpoisonStridedCopyFunc; }; } // end anonymous namespace @@ -924,9 +924,9 @@ void MemorySanitizerOnSpirv::initializeCallbacks() { MsanUnpoisonStackFunc = M.getOrInsertFunction( "__msan_unpoison_stack", IRB.getVoidTy(), PtrTy, IntptrTy); - MsanShadowStridedCopyFunc = - M.getOrInsertFunction("__msan_unpoison_strided_copy", IRB.getVoidTy(), IntptrTy, - IntptrTy, IRB.getInt64Ty(), IRB.getInt64Ty()); + MsanUnpoisonStridedCopyFunc = M.getOrInsertFunction( + "__msan_unpoison_strided_copy", IRB.getVoidTy(), IntptrTy, IntptrTy, + IRB.getInt32Ty(), IRB.getInt64Ty(), IRB.getInt64Ty()); } // Handle global variables: @@ -1827,6 +1827,50 @@ static void setNoSanitizedMetadataSPIR(Instruction &I) { I.setNoSanitizeMetadata(); } +// This is not a gerneral-purpose function, but a helper for demangling +// "__spirv_GroupAsyncCopy" function name +static int getTypeSizeFromManglingName(StringRef Name) { + auto GetTypeSize = [](const char C) { + switch (C) { + case 'c': + return 1; + case 'd': + return 8; + case 'f': + return 4; + case 'i': + return 4; + case 'l': + return 8; + case 's': + return 2; + default: + return 0; + } + }; + + // 1. Basic type + if (Name[0] != 'D') + return GetTypeSize(Name[0]); + + // 2. Vector type + + // Drop "Dv" + assert(Name[0] == 'D' && Name[1] == 'v' && + "Invalid mangling name for vector type"); + Name = Name.drop_front(2); + + // Vector length + int Len = std::stoi(Name.str()); + Name = Name.drop_front(Len >= 10 ? 2 : 1); + + assert(Name[0] == '_' && "Invalid mangling name for vector type"); + Name = Name.drop_front(1); + + int Size = GetTypeSize(Name[0]); + return Len * Size; +} + namespace { /// Helper class to attach debug information of the given instruction onto new @@ -6173,15 +6217,22 @@ struct MemorySanitizerVisitor : public InstVisitor { auto FuncName = Func->getName(); outs() << "!!!! " << FuncName << "\n"; if (FuncName.contains("__spirv_GroupAsyncCopy")) { + // Like "_Z22__spirv_GroupAsyncCopyiPU3AS3dPU3AS1dllP13__spirv_Event" + // "__spirv_GroupAsyncCopy(int, double AS3*, double AS1*, long, long, __spirv_Event*)" + auto *Dest = CB.getArgOperand(1); auto *Src = CB.getArgOperand(2); auto *NumElements = CB.getArgOperand(3); auto *Stride = CB.getArgOperand(4); - IRB.CreateCall(MS.Spirv.MsanShadowStridedCopyFunc, + // Skip "_Z22__spirv_GroupAsyncCopyiPU3AS3", get the size of parameter type directly + int ElementSize = getTypeSizeFromManglingName(FuncName.substr(33)); + + IRB.CreateCall(MS.Spirv.MsanUnpoisonStridedCopyFunc, {IRB.CreatePointerCast(Dest, MS.Spirv.IntptrTy), - IRB.CreatePointerCast(Src, MS.Spirv.IntptrTy), NumElements, - Stride}); + IRB.CreatePointerCast(Src, MS.Spirv.IntptrTy), + IRB.getInt32(ElementSize), + NumElements, Stride}); } } } From c5efc922c26cdcebf8687103ab4e5eda8e8c35a8 Mon Sep 17 00:00:00 2001 From: "Zhao, Yang2" Date: Tue, 29 Apr 2025 09:30:32 +0200 Subject: [PATCH 3/3] wip --- libdevice/sanitizer/msan_rtl.cpp | 48 +++++++++++++++---- .../Instrumentation/MemorySanitizer.cpp | 21 ++++---- 2 files changed, 49 insertions(+), 20 deletions(-) diff --git a/libdevice/sanitizer/msan_rtl.cpp b/libdevice/sanitizer/msan_rtl.cpp index 06aaaac094fe4..d6b0648ab18b0 100644 --- a/libdevice/sanitizer/msan_rtl.cpp +++ b/libdevice/sanitizer/msan_rtl.cpp @@ -220,6 +220,14 @@ inline void __msan_exit() { __devicelib_exit(); } +template +void GroupAsyncCopy(dataT *Dest, const dataT *Src, size_t NumElements, + size_t Stride) { + for (size_t i = 0; i < NumElements; i++) { + Dest[i] = Src[i * Stride]; + } +} + } // namespace #define MSAN_MAYBE_WARNING(type, size) \ @@ -576,22 +584,42 @@ DEVICE_EXTERN_C_NOINLINE void __msan_unpoison_stack(__SYCL_PRIVATE__ void *ptr, __spirv_ocl_printf(__msan_print_func_end, "__msan_unpoison_stack")); } -void __msan_unpoison_strided_copy(uptr dest, uptr src, uptr counts, uptr stride) { +static __SYCL_CONSTANT__ const char __msan_print_strided_copy_unsupport_type[] = + "[kernel] __msan_unpoison_strided_copy: unsupport type(%d)\n"; + +DEVICE_EXTERN_C_NOINLINE void +__msan_unpoison_strided_copy(uptr dest, uint32_t dest_as, uptr src, + uint32_t src_as, uint32_t element_size, + uptr counts, uptr stride) { if (!GetMsanLaunchInfo) return; MSAN_DEBUG(__spirv_ocl_printf(__msan_print_func_beg, "__msan_unpoison_strided_copy")); - for (uptr i = 0; i < counts; ++i) { - auto shadow_address = __msan_get_shadow(dest, ADDRESS_SPACE_PRIVATE); - MSAN_DEBUG(__spirv_ocl_printf(__msan_print_set_shadow_private, - (void *)shadow_address, - (void *)(shadow_address + stride), 0x0)); - - for (size_t j = 0; j < stride; j++) - ((__SYCL_GLOBAL__ u8 *)shadow_address)[j] = 0; - dest += stride; + uptr shadow_dest = __msan_get_shadow(dest, dest_as); + uptr shadow_src = __msan_get_shadow(src, src_as); + + switch (element_size) { + case 1: + GroupAsyncCopy((int8_t *)shadow_dest, (int8_t *)shadow_src, counts, + stride); + break; + case 2: + GroupAsyncCopy((int16_t *)shadow_dest, (int16_t *)shadow_src, + counts, stride); + break; + case 4: + GroupAsyncCopy((int32_t *)shadow_dest, (int32_t *)shadow_src, + counts, stride); + break; + case 8: + GroupAsyncCopy((int64_t *)shadow_dest, (int64_t *)shadow_src, + counts, stride); + break; + default: + MSAN_DEBUG(__spirv_ocl_printf(__msan_print_strided_copy_unsupport_type, + element_size)); } MSAN_DEBUG(__spirv_ocl_printf(__msan_print_func_end, diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index 2466de3b310b3..f984f495c1cd4 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -925,8 +925,9 @@ void MemorySanitizerOnSpirv::initializeCallbacks() { "__msan_unpoison_stack", IRB.getVoidTy(), PtrTy, IntptrTy); MsanUnpoisonStridedCopyFunc = M.getOrInsertFunction( - "__msan_unpoison_strided_copy", IRB.getVoidTy(), IntptrTy, IntptrTy, - IRB.getInt32Ty(), IRB.getInt64Ty(), IRB.getInt64Ty()); + "__msan_unpoison_strided_copy", IRB.getVoidTy(), IntptrTy, + IRB.getInt32Ty(), IntptrTy, IRB.getInt32Ty(), IRB.getInt32Ty(), + IRB.getInt64Ty(), IRB.getInt64Ty()); } // Handle global variables: @@ -6051,7 +6052,6 @@ struct MemorySanitizerVisitor : public InstVisitor { void visitCallBase(CallBase &CB) { assert(!CB.getMetadata(LLVMContext::MD_nosanitize)); - outs() << "!!! call base\n"; if (CB.isInlineAsm()) { // For inline asm (either a call to asm function, or callbr instruction), @@ -6088,7 +6088,6 @@ struct MemorySanitizerVisitor : public InstVisitor { if (auto *Call = dyn_cast(&CB)) { assert(!isa(Call) && "intrinsics are handled elsewhere"); - outs() << "!!! call inst\n"; // We are going to insert code that relies on the fact that the callee // will become a non-readonly function after it is instrumented by us. To @@ -6227,12 +6226,14 @@ struct MemorySanitizerVisitor : public InstVisitor { // Skip "_Z22__spirv_GroupAsyncCopyiPU3AS3", get the size of parameter type directly int ElementSize = getTypeSizeFromManglingName(FuncName.substr(33)); - - IRB.CreateCall(MS.Spirv.MsanUnpoisonStridedCopyFunc, - {IRB.CreatePointerCast(Dest, MS.Spirv.IntptrTy), - IRB.CreatePointerCast(Src, MS.Spirv.IntptrTy), - IRB.getInt32(ElementSize), - NumElements, Stride}); + + IRB.CreateCall( + MS.Spirv.MsanUnpoisonStridedCopyFunc, + {IRB.CreatePointerCast(Dest, MS.Spirv.IntptrTy), + IRB.getInt32(Dest->getType()->getPointerAddressSpace()), + IRB.CreatePointerCast(Src, MS.Spirv.IntptrTy), + IRB.getInt32(Src->getType()->getPointerAddressSpace()), + IRB.getInt32(ElementSize), NumElements, Stride}); } } }