diff --git a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp @@ -296,6 +296,15 @@ 0x100000000000, // OriginBase }; +// loongarch64 Linux +// NOLINTNEXTLINE(readability-identifier-naming) +static const MemoryMapParams Linux_LoongArch64_MemoryMapParams = { + 0, // AndMask (not used) + 0x500000000000, // XorMask + 0, // ShadowBase (not used) + 0x100000000000, // OriginBase +}; + namespace { class DFSanABIList { @@ -1033,13 +1042,17 @@ } IRBuilder<> IRB(&I); Value *CondShadow = getShadow(Condition); + CallInst *CI; if (DFS.shouldTrackOrigins()) { Value *CondOrigin = getOrigin(Condition); - IRB.CreateCall(DFS.DFSanConditionalCallbackOriginFn, - {CondShadow, CondOrigin}); + CI = IRB.CreateCall(DFS.DFSanConditionalCallbackOriginFn, + {CondShadow, CondOrigin}); } else { - IRB.CreateCall(DFS.DFSanConditionalCallbackFn, {CondShadow}); + CI = IRB.CreateCall(DFS.DFSanConditionalCallbackFn, {CondShadow}); } + Triple TargetTriple(I.getModule()->getTargetTriple()); + if (TargetTriple.getArch() == Triple::loongarch64) + CI->addParamAttr(0, Attribute::ZExt); } void DFSanFunction::addReachesFunctionCallbacksIfEnabled(IRBuilder<> &IRB, @@ -1078,6 +1091,9 @@ args = { DataShadow, FilePathPtr, CILine, FunctionNamePtr }; CB = IRB.CreateCall(DFS.DFSanReachesFunctionCallbackFn, args); } + Triple TargetTriple(I.getModule()->getTargetTriple()); + if (TargetTriple.getArch() == Triple::loongarch64) + CB->addParamAttr(0, Attribute::ZExt); CB->setDebugLoc(dbgloc); } @@ -1110,10 +1126,12 @@ if (TargetTriple.getOS() != Triple::Linux) report_fatal_error("unsupported operating system"); - if (TargetTriple.getArch() != Triple::x86_64) + if (TargetTriple.getArch() == Triple::x86_64) + MapParams = &Linux_X86_64_MemoryMapParams; + else if (TargetTriple.getArch() == Triple::loongarch64) + MapParams = &Linux_LoongArch64_MemoryMapParams; + else report_fatal_error("unsupported architecture"); - MapParams = &Linux_X86_64_MemoryMapParams; - Mod = &M; Ctx = &M.getContext(); Int8Ptr = Type::getInt8PtrTy(*Ctx); @@ -1413,25 +1431,30 @@ // Initializes event callback functions and declare them in the module void DataFlowSanitizer::initializeCallbackFunctions(Module &M) { - DFSanLoadCallbackFn = Mod->getOrInsertFunction("__dfsan_load_callback", - DFSanLoadStoreCallbackFnTy); - DFSanStoreCallbackFn = Mod->getOrInsertFunction("__dfsan_store_callback", - DFSanLoadStoreCallbackFnTy); + Triple TargetTriple(M.getTargetTriple()); + AttributeList AL; + if (TargetTriple.getArch() == Triple::loongarch64) + AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt); + DFSanLoadCallbackFn = Mod->getOrInsertFunction( + "__dfsan_load_callback", DFSanLoadStoreCallbackFnTy, AL); + DFSanStoreCallbackFn = Mod->getOrInsertFunction( + "__dfsan_store_callback", DFSanLoadStoreCallbackFnTy, AL); DFSanMemTransferCallbackFn = Mod->getOrInsertFunction( "__dfsan_mem_transfer_callback", DFSanMemTransferCallbackFnTy); - DFSanCmpCallbackFn = - Mod->getOrInsertFunction("__dfsan_cmp_callback", DFSanCmpCallbackFnTy); + DFSanCmpCallbackFn = Mod->getOrInsertFunction("__dfsan_cmp_callback", + DFSanCmpCallbackFnTy, AL); DFSanConditionalCallbackFn = Mod->getOrInsertFunction( - "__dfsan_conditional_callback", DFSanConditionalCallbackFnTy); + "__dfsan_conditional_callback", DFSanConditionalCallbackFnTy, AL); DFSanConditionalCallbackOriginFn = Mod->getOrInsertFunction("__dfsan_conditional_callback_origin", - DFSanConditionalCallbackOriginFnTy); - DFSanReachesFunctionCallbackFn = Mod->getOrInsertFunction( - "__dfsan_reaches_function_callback", DFSanReachesFunctionCallbackFnTy); + DFSanConditionalCallbackOriginFnTy, AL); + DFSanReachesFunctionCallbackFn = + Mod->getOrInsertFunction("__dfsan_reaches_function_callback", + DFSanReachesFunctionCallbackFnTy, AL); DFSanReachesFunctionCallbackOriginFn = Mod->getOrInsertFunction("__dfsan_reaches_function_callback_origin", - DFSanReachesFunctionCallbackOriginFnTy); + DFSanReachesFunctionCallbackOriginFnTy, AL); } void DataFlowSanitizer::injectMetadataGlobals(Module &M) { @@ -2403,7 +2426,11 @@ if (ClEventCallbacks) { IRBuilder<> IRB(Pos); Value *Addr8 = IRB.CreateBitCast(LI.getPointerOperand(), DFSF.DFS.Int8Ptr); - IRB.CreateCall(DFSF.DFS.DFSanLoadCallbackFn, {PrimitiveShadow, Addr8}); + CallInst *CI = + IRB.CreateCall(DFSF.DFS.DFSanLoadCallbackFn, {PrimitiveShadow, Addr8}); + Triple TargetTriple(LI.getModule()->getTargetTriple()); + if (TargetTriple.getArch() == Triple::loongarch64) + CI->addParamAttr(0, Attribute::ZExt); } IRBuilder<> IRB(AfterLi); @@ -2663,7 +2690,11 @@ if (ClEventCallbacks) { IRBuilder<> IRB(&SI); Value *Addr8 = IRB.CreateBitCast(SI.getPointerOperand(), DFSF.DFS.Int8Ptr); - IRB.CreateCall(DFSF.DFS.DFSanStoreCallbackFn, {PrimitiveShadow, Addr8}); + CallInst *CI = + IRB.CreateCall(DFSF.DFS.DFSanStoreCallbackFn, {PrimitiveShadow, Addr8}); + Triple TargetTriple(SI.getModule()->getTargetTriple()); + if (TargetTriple.getArch() == Triple::loongarch64) + CI->addParamAttr(0, Attribute::ZExt); } } @@ -2725,7 +2756,11 @@ if (ClEventCallbacks) { IRBuilder<> IRB(&CI); Value *CombinedShadow = DFSF.getShadow(&CI); - IRB.CreateCall(DFSF.DFS.DFSanCmpCallbackFn, CombinedShadow); + CallInst *CallI = + IRB.CreateCall(DFSF.DFS.DFSanCmpCallbackFn, CombinedShadow); + Triple TargetTriple(CI.getModule()->getTargetTriple()); + if (TargetTriple.getArch() == Triple::loongarch64) + CallI->addParamAttr(0, Attribute::ZExt); } } diff --git a/llvm/test/Instrumentation/DataFlowSanitizer/callback-loongarch64.ll b/llvm/test/Instrumentation/DataFlowSanitizer/callback-loongarch64.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Instrumentation/DataFlowSanitizer/callback-loongarch64.ll @@ -0,0 +1,42 @@ +; RUN: opt < %s -passes=dfsan -dfsan-event-callbacks=1 -S | FileCheck %s +target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128" +target triple = "loongarch64-unknown-linux-gnu" + +; CHECK: @__dfsan_shadow_width_bits = weak_odr constant i32 [[#SBITS:]] +; CHECK: @__dfsan_shadow_width_bytes = weak_odr constant i32 [[#SBYTES:]] + +define i8 @load8(ptr %p) { + ; CHECK: call void @__dfsan_load_callback(i[[#SBITS]] zeroext %[[LABEL:.*]], ptr %p) + ; CHECK: %a = load i8, ptr %p + ; CHECK: store i[[#SBITS]] %[[LABEL]], ptr @__dfsan_retval_tls + + %a = load i8, ptr %p + ret i8 %a +} + +define void @store8(ptr %p, i8 %a) { + ; CHECK: store i[[#SBITS]] %[[LABEL:.*]], ptr %{{.*}} + ; CHECK: call void @__dfsan_store_callback(i[[#SBITS]] zeroext %[[LABEL]], ptr %p) + ; CHECK: store i8 %a, ptr %p + + store i8 %a, ptr %p + ret void +} + +define i1 @cmp(i8 %a, i8 %b) { + ; CHECK: call void @__dfsan_cmp_callback(i[[#SBITS]] zeroext %[[CMPLABEL:.*]]) + ; CHECK: %c = icmp ne i8 %a, %b + ; CHECK: store i[[#SBITS]] %[[CMPLABEL]], ptr @__dfsan_retval_tls + + %c = icmp ne i8 %a, %b + ret i1 %c +} + +; CHECK: declare void @__dfsan_load_callback(i[[#SBITS]] zeroext, ptr) +; CHECK: declare void @__dfsan_store_callback(i[[#SBITS]] zeroext, ptr) +; CHECK: declare void @__dfsan_mem_transfer_callback(ptr, i64) +; CHECK: declare void @__dfsan_cmp_callback(i[[#SBITS]] zeroext) +; CHECK: declare void @__dfsan_conditional_callback(i[[#SBITS]] zeroext) +; CHECK: declare void @__dfsan_conditional_callback_origin(i[[#SBITS]] zeroext, i32) +; CHECK: declare void @__dfsan_reaches_function_callback(i[[#SBITS]] zeroext, ptr, i32, ptr) +; CHECK: declare void @__dfsan_reaches_function_callback_origin(i[[#SBITS]] zeroext, i32, ptr, i32, ptr)