diff options
author | Philip Pfaffe <philip.pfaffe@gmail.com> | 2019-01-08 19:21:57 +0000 |
---|---|---|
committer | Philip Pfaffe <philip.pfaffe@gmail.com> | 2019-01-08 19:21:57 +0000 |
commit | 82f995db754074a747221d91840568f2612313f8 (patch) | |
tree | 2324f18f9c810bf6d0f84a8935abfbdcc83d1ffc /llvm/lib | |
parent | 6a18c531ae3f267c354b9dda8df7fa0181955b97 (diff) | |
download | bcm5719-llvm-82f995db754074a747221d91840568f2612313f8.tar.gz bcm5719-llvm-82f995db754074a747221d91840568f2612313f8.zip |
[NewPM] Port tsan
A straightforward port of tsan to the new PM, following the same path
as D55647.
Differential Revision: https://reviews.llvm.org/D56433
llvm-svn: 350647
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Passes/PassBuilder.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/Passes/PassRegistry.def | 1 | ||||
-rw-r--r-- | llvm/lib/Transforms/Instrumentation/Instrumentation.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp | 97 |
4 files changed, 60 insertions, 41 deletions
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index e1d0a47fb6d..61b16f1d6b9 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -95,6 +95,7 @@ #include "llvm/Transforms/Instrumentation/GCOVProfiler.h" #include "llvm/Transforms/Instrumentation/InstrProfiling.h" #include "llvm/Transforms/Instrumentation/MemorySanitizer.h" +#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" #include "llvm/Transforms/Instrumentation/PGOInstrumentation.h" #include "llvm/Transforms/Scalar/ADCE.h" #include "llvm/Transforms/Scalar/AlignmentFromAssumptions.h" diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index a8c03ad0596..b1b7abe16c7 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -234,6 +234,7 @@ FUNCTION_PASS("view-cfg", CFGViewerPass()) FUNCTION_PASS("view-cfg-only", CFGOnlyViewerPass()) FUNCTION_PASS("transform-warning", WarnMissedTransformationsPass()) FUNCTION_PASS("msan", MemorySanitizerPass()) +FUNCTION_PASS("tsan", ThreadSanitizerPass()) #undef FUNCTION_PASS #ifndef LOOP_ANALYSIS diff --git a/llvm/lib/Transforms/Instrumentation/Instrumentation.cpp b/llvm/lib/Transforms/Instrumentation/Instrumentation.cpp index 5828019a03a..c3e323613c7 100644 --- a/llvm/lib/Transforms/Instrumentation/Instrumentation.cpp +++ b/llvm/lib/Transforms/Instrumentation/Instrumentation.cpp @@ -113,7 +113,7 @@ void llvm::initializeInstrumentation(PassRegistry &Registry) { initializeInstrProfilingLegacyPassPass(Registry); initializeMemorySanitizerLegacyPassPass(Registry); initializeHWAddressSanitizerPass(Registry); - initializeThreadSanitizerPass(Registry); + initializeThreadSanitizerLegacyPassPass(Registry); initializeSanitizerCoverageModulePass(Registry); initializeDataFlowSanitizerPass(Registry); initializeEfficiencySanitizerPass(Registry); diff --git a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp index fa1e5a157a0..7d535db9d6a 100644 --- a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp @@ -19,6 +19,7 @@ // The rest is handled by the run-time library. //===----------------------------------------------------------------------===// +#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" @@ -80,21 +81,21 @@ STATISTIC(NumOmittedReadsFromConstantGlobals, STATISTIC(NumOmittedReadsFromVtable, "Number of vtable reads"); STATISTIC(NumOmittedNonCaptured, "Number of accesses ignored due to capturing"); -static const char *const kTsanModuleCtorName = "tsan.module_ctor"; static const char *const kTsanInitName = "__tsan_init"; namespace { /// ThreadSanitizer: instrument the code in module to find races. -struct ThreadSanitizer : public FunctionPass { - ThreadSanitizer() : FunctionPass(ID) {} - StringRef getPassName() const override; - void getAnalysisUsage(AnalysisUsage &AU) const override; - bool runOnFunction(Function &F) override; - bool doInitialization(Module &M) override; - static char ID; // Pass identification, replacement for typeid. - - private: +/// +/// Instantiating ThreadSanitizer inserts the msan runtime library API function +/// declarations into the module if they don't exist already. Instantiating +/// ensures the __tsan_init function is in the list of global constructors for +/// the module. +struct ThreadSanitizer { + ThreadSanitizer(Module &M); + bool sanitizeFunction(Function &F, const TargetLibraryInfo &TLI); + +private: void initializeCallbacks(Module &M); bool instrumentLoadOrStore(Instruction *I, const DataLayout &DL); bool instrumentAtomic(Instruction *I, const DataLayout &DL); @@ -128,29 +129,56 @@ struct ThreadSanitizer : public FunctionPass { Function *TsanVptrUpdate; Function *TsanVptrLoad; Function *MemmoveFn, *MemcpyFn, *MemsetFn; - Function *TsanCtorFunction; +}; + +struct ThreadSanitizerLegacyPass : FunctionPass { + ThreadSanitizerLegacyPass() : FunctionPass(ID) {} + StringRef getPassName() const override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + bool runOnFunction(Function &F) override; + bool doInitialization(Module &M) override; + static char ID; // Pass identification, replacement for typeid. +private: + Optional<ThreadSanitizer> TSan; }; } // namespace -char ThreadSanitizer::ID = 0; -INITIALIZE_PASS_BEGIN( - ThreadSanitizer, "tsan", - "ThreadSanitizer: detects data races.", - false, false) +PreservedAnalyses ThreadSanitizerPass::run(Function &F, + FunctionAnalysisManager &FAM) { + ThreadSanitizer TSan(*F.getParent()); + if (TSan.sanitizeFunction(F, FAM.getResult<TargetLibraryAnalysis>(F))) + return PreservedAnalyses::none(); + return PreservedAnalyses::all(); +} + +char ThreadSanitizerLegacyPass::ID = 0; +INITIALIZE_PASS_BEGIN(ThreadSanitizerLegacyPass, "tsan", + "ThreadSanitizer: detects data races.", false, false) INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) -INITIALIZE_PASS_END( - ThreadSanitizer, "tsan", - "ThreadSanitizer: detects data races.", - false, false) +INITIALIZE_PASS_END(ThreadSanitizerLegacyPass, "tsan", + "ThreadSanitizer: detects data races.", false, false) -StringRef ThreadSanitizer::getPassName() const { return "ThreadSanitizer"; } +StringRef ThreadSanitizerLegacyPass::getPassName() const { + return "ThreadSanitizerLegacyPass"; +} -void ThreadSanitizer::getAnalysisUsage(AnalysisUsage &AU) const { +void ThreadSanitizerLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired<TargetLibraryInfoWrapperPass>(); } -FunctionPass *llvm::createThreadSanitizerPass() { - return new ThreadSanitizer(); +bool ThreadSanitizerLegacyPass::doInitialization(Module &M) { + TSan.emplace(M); + return true; +} + +bool ThreadSanitizerLegacyPass::runOnFunction(Function &F) { + auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(); + TSan->sanitizeFunction(F, TLI); + return true; +} + +FunctionPass *llvm::createThreadSanitizerLegacyPassPass() { + return new ThreadSanitizerLegacyPass(); } void ThreadSanitizer::initializeCallbacks(Module &M) { @@ -252,16 +280,10 @@ void ThreadSanitizer::initializeCallbacks(Module &M) { IRB.getInt32Ty(), IntptrTy)); } -bool ThreadSanitizer::doInitialization(Module &M) { +ThreadSanitizer::ThreadSanitizer(Module &M) { const DataLayout &DL = M.getDataLayout(); IntptrTy = DL.getIntPtrType(M.getContext()); - std::tie(TsanCtorFunction, std::ignore) = createSanitizerCtorAndInitFunctions( - M, kTsanModuleCtorName, kTsanInitName, /*InitArgTypes=*/{}, - /*InitArgs=*/{}); - - appendToGlobalCtors(M, TsanCtorFunction, 0); - - return true; + getOrCreateInitFunction(M, kTsanInitName); } static bool isVtableAccess(Instruction *I) { @@ -402,11 +424,8 @@ void ThreadSanitizer::InsertRuntimeIgnores(Function &F) { } } -bool ThreadSanitizer::runOnFunction(Function &F) { - // This is required to prevent instrumenting call to __tsan_init from within - // the module constructor. - if (&F == TsanCtorFunction) - return false; +bool ThreadSanitizer::sanitizeFunction(Function &F, + const TargetLibraryInfo &TLI) { initializeCallbacks(*F.getParent()); SmallVector<Instruction*, 8> AllLoadsAndStores; SmallVector<Instruction*, 8> LocalLoadsAndStores; @@ -416,8 +435,6 @@ bool ThreadSanitizer::runOnFunction(Function &F) { bool HasCalls = false; bool SanitizeFunction = F.hasFnAttribute(Attribute::SanitizeThread); const DataLayout &DL = F.getParent()->getDataLayout(); - const TargetLibraryInfo *TLI = - &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(); // Traverse all instructions, collect loads/stores/returns, check for calls. for (auto &BB : F) { @@ -428,7 +445,7 @@ bool ThreadSanitizer::runOnFunction(Function &F) { LocalLoadsAndStores.push_back(&Inst); else if (isa<CallInst>(Inst) || isa<InvokeInst>(Inst)) { if (CallInst *CI = dyn_cast<CallInst>(&Inst)) - maybeMarkSanitizerLibraryCallNoBuiltin(CI, TLI); + maybeMarkSanitizerLibraryCallNoBuiltin(CI, &TLI); if (isa<MemIntrinsic>(Inst)) MemIntrinCalls.push_back(&Inst); HasCalls = true; |