Skip to content

Commit 8d9fb48

Browse files
committed
Add sanitizer support
1 parent 1c10e09 commit 8d9fb48

File tree

4 files changed

+87
-8
lines changed

4 files changed

+87
-8
lines changed

src/librustc_codegen_llvm/back/write.rs

+5
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,11 @@ pub(crate) unsafe fn optimize(
362362
config.vectorize_slp,
363363
config.vectorize_loop,
364364
config.no_builtins,
365+
Some(Sanitizer::Memory) == config.sanitizer,
366+
Some(Sanitizer::Thread) == config.sanitizer,
367+
Some(Sanitizer::Address) == config.sanitizer,
368+
config.sanitizer.as_ref().map_or(false, |s| config.sanitizer_recover.contains(s)),
369+
config.sanitizer_memory_track_origins as c_int,
365370
);
366371
return Ok(());
367372
}

src/librustc_codegen_llvm/llvm/ffi.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1919,6 +1919,11 @@ extern "C" {
19191919
SLPVectorize: bool,
19201920
LoopVectorize: bool,
19211921
DisableSimplifyLibCalls: bool,
1922+
SanitizeMemory: bool,
1923+
SanitizeThread: bool,
1924+
SanitizeAddress: bool,
1925+
SanitizeRecover: bool,
1926+
SanitizeMemoryTrackOrigins: c_int,
19221927
);
19231928
pub fn LLVMRustPrintModule(
19241929
M: &'a Module,

src/rustllvm/PassWrapper.cpp

+75-6
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
#include "llvm/Transforms/Utils/NameAnonGlobals.h"
3838

3939
using namespace llvm;
40-
using namespace llvm::legacy;
4140

4241
typedef struct LLVMOpaquePass *LLVMPassRef;
4342
typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef;
@@ -612,7 +611,9 @@ LLVMRustOptimizeWithNewPassManager(
612611
bool NoPrepopulatePasses, bool VerifyIR,
613612
bool PrepareForThinLTO, bool PrepareForLTO, bool UseThinLTOBuffers,
614613
bool MergeFunctions, bool UnrollLoops, bool SLPVectorize, bool LoopVectorize,
615-
bool DisableSimplifyLibCalls) {
614+
bool DisableSimplifyLibCalls,
615+
bool SanitizeMemory, bool SanitizeThread, bool SanitizeAddress,
616+
bool SanitizeRecover, int SanitizeMemoryTrackOrigins) {
616617
Module *TheModule = unwrap(ModuleRef);
617618
TargetMachine *TM = unwrap(TMRef);
618619
PassBuilder::OptimizationLevel OptLevel = fromRust(OptLevelRust);
@@ -654,17 +655,85 @@ LLVMRustOptimizeWithNewPassManager(
654655
PB.registerFunctionAnalyses(FAM);
655656
PB.registerLoopAnalyses(LAM);
656657
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
657-
PB.registerPipelineStartEPCallback([VerifyIR](ModulePassManager &MPM) {
658-
if (VerifyIR)
659-
MPM.addPass(VerifierPass());
660-
});
658+
659+
// We manually collect pipeline callbacks so we can apply them at O0, where the
660+
// PassBuilder does not create a pipeline.
661+
std::vector<std::function<void(ModulePassManager &)>> PipelineStartEPCallbacks;
662+
std::vector<std::function<void(FunctionPassManager &, PassBuilder::OptimizationLevel)>>
663+
OptimizerLastEPCallbacks;
664+
665+
if (VerifyIR) {
666+
PipelineStartEPCallbacks.push_back([VerifyIR](ModulePassManager &MPM) {
667+
MPM.addPass(VerifierPass());
668+
});
669+
}
670+
671+
if (SanitizeMemory) {
672+
MemorySanitizerOptions Options(
673+
SanitizeMemoryTrackOrigins,
674+
SanitizeRecover,
675+
/*CompileKernel=*/false);
676+
#if LLVM_VERSION_GE(10, 0)
677+
PipelineStartEPCallbacks.push_back([Options](ModulePassManager &MPM) {
678+
MPM.addPass(MemorySanitizerPass(Options));
679+
});
680+
#endif
681+
OptimizerLastEPCallbacks.push_back(
682+
[Options](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) {
683+
FPM.addPass(MemorySanitizerPass(Options));
684+
}
685+
);
686+
}
687+
688+
if (SanitizeThread) {
689+
#if LLVM_VERSION_GE(10, 0)
690+
PipelineStartEPCallbacks.push_back([](ModulePassManager &MPM) {
691+
MPM.addPass(ThreadSanitizerPass());
692+
});
693+
#endif
694+
OptimizerLastEPCallbacks.push_back(
695+
[](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) {
696+
FPM.addPass(ThreadSanitizerPass());
697+
}
698+
);
699+
}
700+
701+
if (SanitizeAddress) {
702+
// FIXME: Rust does not expose the UseAfterScope option.
703+
PipelineStartEPCallbacks.push_back([&](ModulePassManager &MPM) {
704+
MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
705+
});
706+
OptimizerLastEPCallbacks.push_back(
707+
[SanitizeRecover](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) {
708+
FPM.addPass(AddressSanitizerPass(/*CompileKernel=*/false, SanitizeRecover));
709+
}
710+
);
711+
PipelineStartEPCallbacks.push_back(
712+
[SanitizeRecover](ModulePassManager &MPM) {
713+
MPM.addPass(ModuleAddressSanitizerPass(/*CompileKernel=*/false, SanitizeRecover));
714+
}
715+
);
716+
}
661717

662718
ModulePassManager MPM(DebugPassManager);
663719
if (!NoPrepopulatePasses) {
664720
if (OptLevel == PassBuilder::O0) {
721+
for (const auto &C : PipelineStartEPCallbacks)
722+
C(MPM);
723+
724+
FunctionPassManager FPM(DebugPassManager);
725+
for (const auto &C : OptimizerLastEPCallbacks)
726+
C(FPM, OptLevel);
727+
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
728+
665729
MPM.addPass(AlwaysInlinerPass(/*InsertLifetimeIntrinsics=*/false));
666730
// FIXME: PGO?
667731
} else {
732+
for (const auto &C : PipelineStartEPCallbacks)
733+
PB.registerPipelineStartEPCallback(C);
734+
for (const auto &C : OptimizerLastEPCallbacks)
735+
PB.registerOptimizerLastEPCallback(C);
736+
668737
// FIXME: Sanitizers? PGO?
669738
if (PrepareForThinLTO) {
670739
MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager);

src/test/codegen/sanitizer-memory-track-orgins.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
#![crate_type="lib"]
1414

1515
// MSAN-0-NOT: @__msan_track_origins
16-
// MSAN-1: @__msan_track_origins = weak_odr local_unnamed_addr constant i32 1
17-
// MSAN-2: @__msan_track_origins = weak_odr local_unnamed_addr constant i32 2
16+
// MSAN-1: @__msan_track_origins = weak_odr {{.*}}constant i32 1
17+
// MSAN-2: @__msan_track_origins = weak_odr {{.*}}constant i32 2
1818
//
1919
// MSAN-0-LABEL: define void @copy(
2020
// MSAN-1-LABEL: define void @copy(

0 commit comments

Comments
 (0)