diff --git a/llvm/include/llvm/Transforms/Instrumentation/MemorySanitizer.h b/llvm/include/llvm/Transforms/Instrumentation/MemorySanitizer.h --- a/llvm/include/llvm/Transforms/Instrumentation/MemorySanitizer.h +++ b/llvm/include/llvm/Transforms/Instrumentation/MemorySanitizer.h @@ -19,11 +19,15 @@ namespace llvm { struct MemorySanitizerOptions { - MemorySanitizerOptions() : MemorySanitizerOptions(0, false, false){}; - MemorySanitizerOptions(int TrackOrigins, bool Recover, bool Kernel); + MemorySanitizerOptions() : MemorySanitizerOptions(0, false, false, false){}; + MemorySanitizerOptions(int TrackOrigins, bool Recover, bool Kernel) + : MemorySanitizerOptions(TrackOrigins, Recover, Kernel, false) {} + MemorySanitizerOptions(int TrackOrigins, bool Recover, bool Kernel, + bool EagerChecks); bool Kernel; int TrackOrigins; bool Recover; + bool EagerChecks; }; // Insert MemorySanitizer instrumentation (detection of uninitialized reads) diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -656,6 +656,8 @@ ParamName) .str(), inconvertibleErrorCode()); + } else if (ParamName == "eager-checks") { + Result.EagerChecks = true; } else { return make_error( formatv("invalid MemorySanitizer pass parameter '{0}' ", ParamName) diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -412,7 +412,7 @@ return MemorySanitizerPass(Opts); }, parseMSanPassOptions, - "recover;kernel;track-origins=N") + "recover;kernel;eager-checks;track-origins=N") FUNCTION_PASS_WITH_PARAMS("simplifycfg", "SimplifyCFGPass", [](SimplifyCFGOptions Opts) { diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -492,7 +492,7 @@ public: MemorySanitizer(Module &M, MemorySanitizerOptions Options) : CompileKernel(Options.Kernel), TrackOrigins(Options.TrackOrigins), - Recover(Options.Recover) { + Recover(Options.Recover), EagerChecks(Options.EagerChecks) { initializeModule(M); } @@ -522,6 +522,7 @@ /// Track origins (allocation points) of uninitialized values. int TrackOrigins; bool Recover; + bool EagerChecks; LLVMContext *C; Type *IntptrTy; @@ -665,10 +666,12 @@ } // end anonymous namespace -MemorySanitizerOptions::MemorySanitizerOptions(int TO, bool R, bool K) +MemorySanitizerOptions::MemorySanitizerOptions(int TO, bool R, bool K, + bool EagerChecks) : Kernel(getOptOrDefault(ClEnableKmsan, K)), TrackOrigins(getOptOrDefault(ClTrackOrigins, Kernel ? 2 : TO)), - Recover(getOptOrDefault(ClKeepGoing, Kernel || R)) {} + Recover(getOptOrDefault(ClKeepGoing, Kernel || R)), + EagerChecks(getOptOrDefault(ClEagerChecks, EagerChecks)) {} PreservedAnalyses MemorySanitizerPass::run(Function &F, FunctionAnalysisManager &FAM) { @@ -695,6 +698,8 @@ OS << "recover;"; if (Options.Kernel) OS << "kernel;"; + if (Options.EagerChecks) + OS << "eager-checks;"; OS << "track-origins=" << Options.TrackOrigins; OS << ">"; } @@ -1703,7 +1708,7 @@ bool FArgByVal = FArg.hasByValAttr(); bool FArgNoUndef = FArg.hasAttribute(Attribute::NoUndef); - bool FArgEagerCheck = ClEagerChecks && !FArgByVal && FArgNoUndef; + bool FArgEagerCheck = MS.EagerChecks && !FArgByVal && FArgNoUndef; unsigned Size = FArg.hasByValAttr() ? DL.getTypeAllocSize(FArg.getParamByValType()) @@ -3679,7 +3684,7 @@ maybeMarkSanitizerLibraryCallNoBuiltin(Call, TLI); } IRBuilder<> IRB(&CB); - bool MayCheckCall = ClEagerChecks; + bool MayCheckCall = MS.EagerChecks; if (Function *Func = CB.getCalledFunction()) { // __sanitizer_unaligned_{load,store} functions may be called by users // and always expects shadows in the TLS. So don't check them. @@ -3832,10 +3837,10 @@ Value *ShadowPtr = getShadowPtrForRetval(RetVal, IRB); bool HasNoUndef = F.hasRetAttribute(Attribute::NoUndef); - bool StoreShadow = !(ClEagerChecks && HasNoUndef); + bool StoreShadow = !(MS.EagerChecks && HasNoUndef); // FIXME: Consider using SpecialCaseList to specify a list of functions that // must always return fully initialized values. For now, we hardcode "main". - bool EagerCheck = (ClEagerChecks && HasNoUndef) || (F.getName() == "main"); + bool EagerCheck = (MS.EagerChecks && HasNoUndef) || (F.getName() == "main"); Value *Shadow = getShadow(RetVal); bool StoreOrigin = true; diff --git a/llvm/test/Instrumentation/MemorySanitizer/msan_eager.ll b/llvm/test/Instrumentation/MemorySanitizer/msan_eager.ll --- a/llvm/test/Instrumentation/MemorySanitizer/msan_eager.ll +++ b/llvm/test/Instrumentation/MemorySanitizer/msan_eager.ll @@ -1,6 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=1 -msan-eager-checks -S -passes='module(msan-module),function(msan)' 2>&1 | \ ; RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK %s +; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=1 -S -passes='msan' 2>&1 | \ +; RUN: FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Other/new-pm-print-pipeline.ll b/llvm/test/Other/new-pm-print-pipeline.ll --- a/llvm/test/Other/new-pm-print-pipeline.ll +++ b/llvm/test/Other/new-pm-print-pipeline.ll @@ -40,8 +40,8 @@ ; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='function(early-cse<>,early-cse)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-12 ; CHECK-12: function(early-cse<>,early-cse) -; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='msan-module,function(msan,msan<>,msan)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-13 -; CHECK-13: msan-module,function(msan,msan,msan) +; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='msan-module,function(msan,msan<>,msan)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-13 +; CHECK-13: msan-module,function(msan,msan,msan) ; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='module(hwasan<>,hwasan)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-14 ; CHECK-14: hwasan<>,hwasan