forked from OSchip/llvm-project
[NewPM][MSan] Add Options Handling
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
This commit is contained in:
parent
90d856cd5f
commit
0ee6a933ce
|
@ -279,7 +279,8 @@ static void addGeneralOptsForMemorySanitizer(const PassManagerBuilder &Builder,
|
||||||
const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
|
const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
|
||||||
int TrackOrigins = CGOpts.SanitizeMemoryTrackOrigins;
|
int TrackOrigins = CGOpts.SanitizeMemoryTrackOrigins;
|
||||||
bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::Memory);
|
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
|
// MemorySanitizer inserts complex instrumentation that mostly follows
|
||||||
// the logic of the original code, but operates on "shadow" values.
|
// the logic of the original code, but operates on "shadow" values.
|
||||||
|
@ -1035,7 +1036,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
|
||||||
if (LangOpts.Sanitize.has(SanitizerKind::Memory))
|
if (LangOpts.Sanitize.has(SanitizerKind::Memory))
|
||||||
PB.registerOptimizerLastEPCallback(
|
PB.registerOptimizerLastEPCallback(
|
||||||
[](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) {
|
[](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) {
|
||||||
FPM.addPass(MemorySanitizerPass());
|
FPM.addPass(MemorySanitizerPass({}));
|
||||||
});
|
});
|
||||||
if (LangOpts.Sanitize.has(SanitizerKind::Thread))
|
if (LangOpts.Sanitize.has(SanitizerKind::Thread))
|
||||||
PB.registerOptimizerLastEPCallback(
|
PB.registerOptimizerLastEPCallback(
|
||||||
|
|
|
@ -18,10 +18,18 @@
|
||||||
|
|
||||||
namespace llvm {
|
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)
|
// Insert MemorySanitizer instrumentation (detection of uninitialized reads)
|
||||||
FunctionPass *createMemorySanitizerLegacyPassPass(int TrackOrigins = 0,
|
FunctionPass *
|
||||||
bool Recover = false,
|
createMemorySanitizerLegacyPassPass(MemorySanitizerOptions Options = {});
|
||||||
bool EnableKmsan = false);
|
|
||||||
|
|
||||||
/// A function pass for msan instrumentation.
|
/// A function pass for msan instrumentation.
|
||||||
///
|
///
|
||||||
|
@ -30,17 +38,12 @@ FunctionPass *createMemorySanitizerLegacyPassPass(int TrackOrigins = 0,
|
||||||
/// yet, the pass inserts the declarations. Otherwise the existing globals are
|
/// yet, the pass inserts the declarations. Otherwise the existing globals are
|
||||||
/// used.
|
/// used.
|
||||||
struct MemorySanitizerPass : public PassInfoMixin<MemorySanitizerPass> {
|
struct MemorySanitizerPass : public PassInfoMixin<MemorySanitizerPass> {
|
||||||
MemorySanitizerPass(int TrackOrigins = 0, bool Recover = false,
|
MemorySanitizerPass(MemorySanitizerOptions Options) : Options(Options) {}
|
||||||
bool EnableKmsan = false)
|
|
||||||
: TrackOrigins(TrackOrigins), Recover(Recover), EnableKmsan(EnableKmsan) {
|
|
||||||
}
|
|
||||||
|
|
||||||
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
|
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int TrackOrigins;
|
MemorySanitizerOptions Options;
|
||||||
bool Recover;
|
|
||||||
bool EnableKmsan;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1335,6 +1335,34 @@ Expected<LoopUnrollOptions> parseLoopUnrollOptions(StringRef Params) {
|
||||||
return UnrollOpts;
|
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
|
} // namespace
|
||||||
|
|
||||||
/// Tests whether a pass name starts with a valid prefix for a default pipeline
|
/// Tests whether a pass name starts with a valid prefix for a default pipeline
|
||||||
|
|
|
@ -231,7 +231,7 @@ FUNCTION_PASS("verify<regions>", RegionInfoVerifierPass())
|
||||||
FUNCTION_PASS("view-cfg", CFGViewerPass())
|
FUNCTION_PASS("view-cfg", CFGViewerPass())
|
||||||
FUNCTION_PASS("view-cfg-only", CFGOnlyViewerPass())
|
FUNCTION_PASS("view-cfg-only", CFGOnlyViewerPass())
|
||||||
FUNCTION_PASS("transform-warning", WarnMissedTransformationsPass())
|
FUNCTION_PASS("transform-warning", WarnMissedTransformationsPass())
|
||||||
FUNCTION_PASS("msan", MemorySanitizerPass())
|
FUNCTION_PASS("msan", MemorySanitizerPass({}))
|
||||||
FUNCTION_PASS("tsan", ThreadSanitizerPass())
|
FUNCTION_PASS("tsan", ThreadSanitizerPass())
|
||||||
#undef FUNCTION_PASS
|
#undef FUNCTION_PASS
|
||||||
|
|
||||||
|
@ -239,8 +239,15 @@ FUNCTION_PASS("tsan", ThreadSanitizerPass())
|
||||||
#define FUNCTION_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER)
|
#define FUNCTION_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER)
|
||||||
#endif
|
#endif
|
||||||
FUNCTION_PASS_WITH_PARAMS("unroll",
|
FUNCTION_PASS_WITH_PARAMS("unroll",
|
||||||
[](LoopUnrollOptions Opts) { return LoopUnrollPass(Opts); },
|
[](LoopUnrollOptions Opts) {
|
||||||
parseLoopUnrollOptions)
|
return LoopUnrollPass(Opts);
|
||||||
|
},
|
||||||
|
parseLoopUnrollOptions)
|
||||||
|
FUNCTION_PASS_WITH_PARAMS("msan",
|
||||||
|
[](MemorySanitizerOptions Opts) {
|
||||||
|
return MemorySanitizerPass(Opts);
|
||||||
|
},
|
||||||
|
parseMSanPassOptions)
|
||||||
#undef FUNCTION_PASS_WITH_PARAMS
|
#undef FUNCTION_PASS_WITH_PARAMS
|
||||||
|
|
||||||
#ifndef LOOP_ANALYSIS
|
#ifndef LOOP_ANALYSIS
|
||||||
|
|
|
@ -454,17 +454,16 @@ namespace {
|
||||||
/// the module.
|
/// the module.
|
||||||
class MemorySanitizer {
|
class MemorySanitizer {
|
||||||
public:
|
public:
|
||||||
MemorySanitizer(Module &M, int TrackOrigins = 0, bool Recover = false,
|
MemorySanitizer(Module &M, MemorySanitizerOptions Options) {
|
||||||
bool EnableKmsan = false) {
|
|
||||||
this->CompileKernel =
|
this->CompileKernel =
|
||||||
ClEnableKmsan.getNumOccurrences() > 0 ? ClEnableKmsan : EnableKmsan;
|
ClEnableKmsan.getNumOccurrences() > 0 ? ClEnableKmsan : Options.Kernel;
|
||||||
if (ClTrackOrigins.getNumOccurrences() > 0)
|
if (ClTrackOrigins.getNumOccurrences() > 0)
|
||||||
this->TrackOrigins = ClTrackOrigins;
|
this->TrackOrigins = ClTrackOrigins;
|
||||||
else
|
else
|
||||||
this->TrackOrigins = this->CompileKernel ? 2 : TrackOrigins;
|
this->TrackOrigins = this->CompileKernel ? 2 : Options.TrackOrigins;
|
||||||
this->Recover = ClKeepGoing.getNumOccurrences() > 0
|
this->Recover = ClKeepGoing.getNumOccurrences() > 0
|
||||||
? ClKeepGoing
|
? ClKeepGoing
|
||||||
: (this->CompileKernel | Recover);
|
: (this->CompileKernel | Options.Recover);
|
||||||
initializeModule(M);
|
initializeModule(M);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -598,10 +597,8 @@ struct MemorySanitizerLegacyPass : public FunctionPass {
|
||||||
// Pass identification, replacement for typeid.
|
// Pass identification, replacement for typeid.
|
||||||
static char ID;
|
static char ID;
|
||||||
|
|
||||||
MemorySanitizerLegacyPass(int TrackOrigins = 0, bool Recover = false,
|
MemorySanitizerLegacyPass(MemorySanitizerOptions Options = {})
|
||||||
bool EnableKmsan = false)
|
: FunctionPass(ID), Options(Options) {}
|
||||||
: FunctionPass(ID), TrackOrigins(TrackOrigins), Recover(Recover),
|
|
||||||
EnableKmsan(EnableKmsan) {}
|
|
||||||
StringRef getPassName() const override { return "MemorySanitizerLegacyPass"; }
|
StringRef getPassName() const override { return "MemorySanitizerLegacyPass"; }
|
||||||
|
|
||||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||||
|
@ -615,16 +612,14 @@ struct MemorySanitizerLegacyPass : public FunctionPass {
|
||||||
bool doInitialization(Module &M) override;
|
bool doInitialization(Module &M) override;
|
||||||
|
|
||||||
Optional<MemorySanitizer> MSan;
|
Optional<MemorySanitizer> MSan;
|
||||||
int TrackOrigins;
|
MemorySanitizerOptions Options;
|
||||||
bool Recover;
|
|
||||||
bool EnableKmsan;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
PreservedAnalyses MemorySanitizerPass::run(Function &F,
|
PreservedAnalyses MemorySanitizerPass::run(Function &F,
|
||||||
FunctionAnalysisManager &FAM) {
|
FunctionAnalysisManager &FAM) {
|
||||||
MemorySanitizer Msan(*F.getParent(), TrackOrigins, Recover, EnableKmsan);
|
MemorySanitizer Msan(*F.getParent(), Options);
|
||||||
if (Msan.sanitizeFunction(F, FAM.getResult<TargetLibraryAnalysis>(F)))
|
if (Msan.sanitizeFunction(F, FAM.getResult<TargetLibraryAnalysis>(F)))
|
||||||
return PreservedAnalyses::none();
|
return PreservedAnalyses::none();
|
||||||
return PreservedAnalyses::all();
|
return PreservedAnalyses::all();
|
||||||
|
@ -640,10 +635,9 @@ INITIALIZE_PASS_END(MemorySanitizerLegacyPass, "msan",
|
||||||
"MemorySanitizer: detects uninitialized reads.", false,
|
"MemorySanitizer: detects uninitialized reads.", false,
|
||||||
false)
|
false)
|
||||||
|
|
||||||
FunctionPass *llvm::createMemorySanitizerLegacyPassPass(int TrackOrigins,
|
FunctionPass *
|
||||||
bool Recover,
|
llvm::createMemorySanitizerLegacyPassPass(MemorySanitizerOptions Options) {
|
||||||
bool CompileKernel) {
|
return new MemorySanitizerLegacyPass(Options);
|
||||||
return new MemorySanitizerLegacyPass(TrackOrigins, Recover, CompileKernel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a non-const global initialized with the given string.
|
/// Create a non-const global initialized with the given string.
|
||||||
|
@ -950,7 +944,7 @@ void MemorySanitizer::initializeModule(Module &M) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemorySanitizerLegacyPass::doInitialization(Module &M) {
|
bool MemorySanitizerLegacyPass::doInitialization(Module &M) {
|
||||||
MSan.emplace(M, TrackOrigins, Recover, EnableKmsan);
|
MSan.emplace(M, Options);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
; RUN: opt < %s -msan -msan-check-access-address=0 -S | FileCheck %s
|
; 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: 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: -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 -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: 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: -passes=msan 2>&1 | FileCheck %s "--check-prefixes=CHECK,CHECK-ORIGIN"
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=2 -S \
|
; 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: -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 -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: opt < %s -msan-kernel=1 -S -passes=msan 2>&1 | FileCheck %s \
|
||||||
; RUN: "--check-prefixes=CHECK,KMSAN"
|
; RUN: "--check-prefixes=CHECK,KMSAN"
|
||||||
; RUN: opt < %s -msan -msan-kernel=1 -S | FileCheck %s --check-prefixes=CHECK,KMSAN
|
; RUN: opt < %s -msan -msan-kernel=1 -S | FileCheck %s --check-prefixes=CHECK,KMSAN
|
||||||
|
|
Loading…
Reference in New Issue