Summary: This patch enables passing options to msan via the passes pipeline, e.e., -passes=msan<recover;kernel;track-origins=4>.
Reviewers: chandlerc, fedor.sergeev, leonardchan
Subscribers: hiraditya, bollu, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D57640
llvm-svn: 353090
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.
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(
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.
///
/// yet, the pass inserts the declarations. Otherwise the existing globals are
/// used.
struct MemorySanitizerPass : public PassInfoMixin<MemorySanitizerPass> {
- 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;
};
}
return UnrollOpts;
}
+Expected<MemorySanitizerOptions> 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<StringError>(
+ formatv("invalid argument to MemorySanitizer pass track-origins "
+ "parameter: '{0}' ",
+ ParamName)
+ .str(),
+ inconvertibleErrorCode());
+ } else {
+ return make_error<StringError>(
+ 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
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
#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
/// 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);
}
// 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 {
bool doInitialization(Module &M) override;
Optional<MemorySanitizer> 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<TargetLibraryAnalysis>(F)))
return PreservedAnalyses::none();
return PreservedAnalyses::all();
"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.
}
bool MemorySanitizerLegacyPass::doInitialization(Module &M) {
- MSan.emplace(M, TrackOrigins, Recover, EnableKmsan);
+ MSan.emplace(M, Options);
return true;
}
; 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<track-origins=1>" 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"
; 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<kernel>" 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