diff options
author | Florian Hahn <flo@fhahn.com> | 2019-01-09 13:32:16 +0000 |
---|---|---|
committer | Florian Hahn <flo@fhahn.com> | 2019-01-09 13:32:16 +0000 |
commit | 9697d2a764c9e26099396d4618f9a8105e4b63fe (patch) | |
tree | 7c2dce67fc90fb1fc436bddccec2c979fb6e6c6e /llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp | |
parent | 603467a9a4c5613b8d7f65e14b3e0fe1e40dd4e2 (diff) | |
download | bcm5719-llvm-9697d2a764c9e26099396d4618f9a8105e4b63fe.tar.gz bcm5719-llvm-9697d2a764c9e26099396d4618f9a8105e4b63fe.zip |
Revert r350647: "[NewPM] Port tsan"
This patch breaks thread sanitizer on some macOS builders, e.g.
http://green.lab.llvm.org/green/job/clang-stage1-configure-RA/52725/
llvm-svn: 350719
Diffstat (limited to 'llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp')
-rw-r--r-- | llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp | 97 |
1 files changed, 40 insertions, 57 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp index 7d535db9d6a..fa1e5a157a0 100644 --- a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp @@ -19,7 +19,6 @@ // 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" @@ -81,21 +80,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. -/// -/// 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: +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: void initializeCallbacks(Module &M); bool instrumentLoadOrStore(Instruction *I, const DataLayout &DL); bool instrumentAtomic(Instruction *I, const DataLayout &DL); @@ -129,56 +128,29 @@ private: Function *TsanVptrUpdate; Function *TsanVptrLoad; Function *MemmoveFn, *MemcpyFn, *MemsetFn; -}; - -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; + Function *TsanCtorFunction; }; } // namespace -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) +char ThreadSanitizer::ID = 0; +INITIALIZE_PASS_BEGIN( + ThreadSanitizer, "tsan", + "ThreadSanitizer: detects data races.", + false, false) INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) -INITIALIZE_PASS_END(ThreadSanitizerLegacyPass, "tsan", - "ThreadSanitizer: detects data races.", false, false) +INITIALIZE_PASS_END( + ThreadSanitizer, "tsan", + "ThreadSanitizer: detects data races.", + false, false) -StringRef ThreadSanitizerLegacyPass::getPassName() const { - return "ThreadSanitizerLegacyPass"; -} +StringRef ThreadSanitizer::getPassName() const { return "ThreadSanitizer"; } -void ThreadSanitizerLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const { +void ThreadSanitizer::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired<TargetLibraryInfoWrapperPass>(); } -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(); +FunctionPass *llvm::createThreadSanitizerPass() { + return new ThreadSanitizer(); } void ThreadSanitizer::initializeCallbacks(Module &M) { @@ -280,10 +252,16 @@ void ThreadSanitizer::initializeCallbacks(Module &M) { IRB.getInt32Ty(), IntptrTy)); } -ThreadSanitizer::ThreadSanitizer(Module &M) { +bool ThreadSanitizer::doInitialization(Module &M) { const DataLayout &DL = M.getDataLayout(); IntptrTy = DL.getIntPtrType(M.getContext()); - getOrCreateInitFunction(M, kTsanInitName); + std::tie(TsanCtorFunction, std::ignore) = createSanitizerCtorAndInitFunctions( + M, kTsanModuleCtorName, kTsanInitName, /*InitArgTypes=*/{}, + /*InitArgs=*/{}); + + appendToGlobalCtors(M, TsanCtorFunction, 0); + + return true; } static bool isVtableAccess(Instruction *I) { @@ -424,8 +402,11 @@ void ThreadSanitizer::InsertRuntimeIgnores(Function &F) { } } -bool ThreadSanitizer::sanitizeFunction(Function &F, - const TargetLibraryInfo &TLI) { +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; initializeCallbacks(*F.getParent()); SmallVector<Instruction*, 8> AllLoadsAndStores; SmallVector<Instruction*, 8> LocalLoadsAndStores; @@ -435,6 +416,8 @@ bool ThreadSanitizer::sanitizeFunction(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) { @@ -445,7 +428,7 @@ bool ThreadSanitizer::sanitizeFunction(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; |