Index: clang/lib/CodeGen/BackendUtil.cpp =================================================================== --- clang/lib/CodeGen/BackendUtil.cpp +++ clang/lib/CodeGen/BackendUtil.cpp @@ -278,7 +278,8 @@ const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); int TrackOrigins = CGOpts.SanitizeMemoryTrackOrigins; bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::Memory); - PM.add(createMemorySanitizerLegacyPassPass(TrackOrigins, Recover, CompileKernel)); + PM.add(createMemorySanitizerLegacyPassPass( + MemorySanitizerOptions{TrackOrigins, Recover, CompileKernel})); // MemorySanitizer inserts complex instrumentation that mostly follows // the logic of the original code, but operates on "shadow" values. @@ -1023,7 +1024,7 @@ if (LangOpts.Sanitize.has(SanitizerKind::Memory)) PB.registerOptimizerLastEPCallback( [](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) { - FPM.addPass(MemorySanitizerPass()); + FPM.addPass(MemorySanitizerPass({})); }); if (LangOpts.Sanitize.has(SanitizerKind::Thread)) PB.registerOptimizerLastEPCallback( Index: llvm/include/llvm/Transforms/Instrumentation/MemorySanitizer.h =================================================================== --- llvm/include/llvm/Transforms/Instrumentation/MemorySanitizer.h +++ llvm/include/llvm/Transforms/Instrumentation/MemorySanitizer.h @@ -18,10 +18,18 @@ namespace llvm { +struct MemorySanitizerOptions { + MemorySanitizerOptions() = default; + MemorySanitizerOptions(int TrackOrigins, bool Recover, bool Kernel) + : TrackOrigins(TrackOrigins), Recover(Recover), Kernel(Kernel) {} + int TrackOrigins = 0; + bool Recover = false; + bool Kernel = false; +}; + // Insert MemorySanitizer instrumentation (detection of uninitialized reads) -FunctionPass *createMemorySanitizerLegacyPassPass(int TrackOrigins = 0, - bool Recover = false, - bool EnableKmsan = false); +FunctionPass * +createMemorySanitizerLegacyPassPass(MemorySanitizerOptions Options); /// A function pass for msan instrumentation. /// @@ -30,17 +38,12 @@ /// yet, the pass inserts the declarations. Otherwise the existing globals are /// used. struct MemorySanitizerPass : public PassInfoMixin { - MemorySanitizerPass(int TrackOrigins = 0, bool Recover = false, - bool EnableKmsan = false) - : TrackOrigins(TrackOrigins), Recover(Recover), EnableKmsan(EnableKmsan) { - } + MemorySanitizerPass(MemorySanitizerOptions Options) : Options(Options) {} PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM); private: - int TrackOrigins; - bool Recover; - bool EnableKmsan; + MemorySanitizerOptions Options; }; } Index: llvm/lib/Passes/PassBuilder.cpp =================================================================== --- llvm/lib/Passes/PassBuilder.cpp +++ llvm/lib/Passes/PassBuilder.cpp @@ -1335,6 +1335,34 @@ return UnrollOpts; } +Expected parseMSanPassOptions(StringRef Params) { + MemorySanitizerOptions Result; + while (!Params.empty()) { + StringRef ParamName; + std::tie(ParamName, Params) = Params.split(';'); + + if (ParamName == "recover") { + Result.Recover = true; + } else if (ParamName == "kernel") { + Result.Kernel = true; + } else if (ParamName.consume_front("track-origins=")) { + if (ParamName.getAsInteger(0, Result.TrackOrigins)) + return make_error( + formatv("invalid argument to MemorySanitizer pass track-origins " + "parameter: '{0}' ", + ParamName) + .str(), + inconvertibleErrorCode()); + } else { + return make_error( + formatv("invalid MemorySanitizer pass parameter '{0}' ", ParamName) + .str(), + inconvertibleErrorCode()); + } + } + return Result; +} + } // namespace /// Tests whether a pass name starts with a valid prefix for a default pipeline Index: llvm/lib/Passes/PassRegistry.def =================================================================== --- llvm/lib/Passes/PassRegistry.def +++ llvm/lib/Passes/PassRegistry.def @@ -231,7 +231,7 @@ FUNCTION_PASS("view-cfg", CFGViewerPass()) FUNCTION_PASS("view-cfg-only", CFGOnlyViewerPass()) FUNCTION_PASS("transform-warning", WarnMissedTransformationsPass()) -FUNCTION_PASS("msan", MemorySanitizerPass()) +FUNCTION_PASS("msan", MemorySanitizerPass({})) FUNCTION_PASS("tsan", ThreadSanitizerPass()) #undef FUNCTION_PASS @@ -239,8 +239,15 @@ #define FUNCTION_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) #endif FUNCTION_PASS_WITH_PARAMS("unroll", - [](LoopUnrollOptions Opts) { return LoopUnrollPass(Opts); }, - parseLoopUnrollOptions) + [](LoopUnrollOptions Opts) { + return LoopUnrollPass(Opts); + }, + parseLoopUnrollOptions) +FUNCTION_PASS_WITH_PARAMS("msan", + [](MemorySanitizerOptions Opts) { + return MemorySanitizerPass(Opts); + }, + parseMSanPassOptions) #undef FUNCTION_PASS_WITH_PARAMS #ifndef LOOP_ANALYSIS Index: llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -454,17 +454,16 @@ /// the module. class MemorySanitizer { public: - MemorySanitizer(Module &M, int TrackOrigins = 0, bool Recover = false, - bool EnableKmsan = false) { + MemorySanitizer(Module &M, MemorySanitizerOptions Options) { this->CompileKernel = - ClEnableKmsan.getNumOccurrences() > 0 ? ClEnableKmsan : EnableKmsan; + ClEnableKmsan.getNumOccurrences() > 0 ? ClEnableKmsan : Options.Kernel; if (ClTrackOrigins.getNumOccurrences() > 0) this->TrackOrigins = ClTrackOrigins; else - this->TrackOrigins = this->CompileKernel ? 2 : TrackOrigins; + this->TrackOrigins = this->CompileKernel ? 2 : Options.TrackOrigins; this->Recover = ClKeepGoing.getNumOccurrences() > 0 ? ClKeepGoing - : (this->CompileKernel | Recover); + : (this->CompileKernel | Options.Recover); initializeModule(M); } @@ -598,10 +597,8 @@ // Pass identification, replacement for typeid. static char ID; - MemorySanitizerLegacyPass(int TrackOrigins = 0, bool Recover = false, - bool EnableKmsan = false) - : FunctionPass(ID), TrackOrigins(TrackOrigins), Recover(Recover), - EnableKmsan(EnableKmsan) {} + MemorySanitizerLegacyPass(MemorySanitizerOptions Options = {}) + : FunctionPass(ID), Options(Options) {} StringRef getPassName() const override { return "MemorySanitizerLegacyPass"; } void getAnalysisUsage(AnalysisUsage &AU) const override { @@ -615,16 +612,14 @@ bool doInitialization(Module &M) override; Optional MSan; - int TrackOrigins; - bool Recover; - bool EnableKmsan; + MemorySanitizerOptions Options; }; } // end anonymous namespace PreservedAnalyses MemorySanitizerPass::run(Function &F, FunctionAnalysisManager &FAM) { - MemorySanitizer Msan(*F.getParent(), TrackOrigins, Recover, EnableKmsan); + MemorySanitizer Msan(*F.getParent(), Options); if (Msan.sanitizeFunction(F, FAM.getResult(F))) return PreservedAnalyses::none(); return PreservedAnalyses::all(); @@ -640,10 +635,9 @@ "MemorySanitizer: detects uninitialized reads.", false, false) -FunctionPass *llvm::createMemorySanitizerLegacyPassPass(int TrackOrigins, - bool Recover, - bool CompileKernel) { - return new MemorySanitizerLegacyPass(TrackOrigins, Recover, CompileKernel); +FunctionPass * +llvm::createMemorySanitizerLegacyPassPass(MemorySanitizerOptions Options) { + return new MemorySanitizerLegacyPass(Options); } /// Create a non-const global initialized with the given string. @@ -950,7 +944,7 @@ } bool MemorySanitizerLegacyPass::doInitialization(Module &M) { - MSan.emplace(M, TrackOrigins, Recover, EnableKmsan); + MSan.emplace(M, Options); return true; } Index: llvm/test/Instrumentation/MemorySanitizer/X86/vararg_call.ll =================================================================== --- llvm/test/Instrumentation/MemorySanitizer/X86/vararg_call.ll +++ llvm/test/Instrumentation/MemorySanitizer/X86/vararg_call.ll @@ -3,6 +3,8 @@ ; RUN: opt < %s -msan -msan-check-access-address=0 -S | FileCheck %s ; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=1 -S \ ; RUN: -passes=msan 2>&1 | FileCheck %s "--check-prefixes=CHECK,CHECK-ORIGIN" +; RUN: opt < %s -msan-check-access-address=0 -S \ +; RUN: -passes="msan" 2>&1 | FileCheck %s "--check-prefixes=CHECK,CHECK-ORIGIN" ; RUN: opt < %s -msan -msan-check-access-address=0 -msan-track-origins=1 -S | FileCheck %s --check-prefixes=CHECK,CHECK-ORIGIN ; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=2 -S \ ; RUN: -passes=msan 2>&1 | FileCheck %s "--check-prefixes=CHECK,CHECK-ORIGIN" Index: llvm/test/Instrumentation/MemorySanitizer/alloca.ll =================================================================== --- llvm/test/Instrumentation/MemorySanitizer/alloca.ll +++ llvm/test/Instrumentation/MemorySanitizer/alloca.ll @@ -10,6 +10,8 @@ ; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=2 -S \ ; RUN: -passes=msan 2>&1 | FileCheck %s "--check-prefixes=CHECK,ORIGIN" ; RUN: opt < %s -msan -msan-check-access-address=0 -msan-track-origins=2 -S | FileCheck %s --check-prefixes=CHECK,ORIGIN +; RUN: opt < %s -S -passes="msan" 2>&1 | FileCheck %s \ +; RUN: "--check-prefixes=CHECK,KMSAN" ; RUN: opt < %s -msan-kernel=1 -S -passes=msan 2>&1 | FileCheck %s \ ; RUN: "--check-prefixes=CHECK,KMSAN" ; RUN: opt < %s -msan -msan-kernel=1 -S | FileCheck %s --check-prefixes=CHECK,KMSAN