From: Florian Hahn Date: Wed, 9 Jan 2019 13:32:16 +0000 (+0000) Subject: Revert r350647: "[NewPM] Port tsan" X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c547d68a5684f69cc3c59727e09a41bfaf1a97f2;p=llvm 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/ git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@350719 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index 24de5cb4b52..293f37ee40c 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -391,7 +391,7 @@ void initializeTailDuplicatePass(PassRegistry&); void initializeTargetLibraryInfoWrapperPassPass(PassRegistry&); void initializeTargetPassConfigPass(PassRegistry&); void initializeTargetTransformInfoWrapperPassPass(PassRegistry&); -void initializeThreadSanitizerLegacyPassPass(PassRegistry&); +void initializeThreadSanitizerPass(PassRegistry&); void initializeTwoAddressInstructionPassPass(PassRegistry&); void initializeTypeBasedAAWrapperPassPass(PassRegistry&); void initializeUnifyFunctionExitNodesPass(PassRegistry&); diff --git a/include/llvm/Transforms/Instrumentation.h b/include/llvm/Transforms/Instrumentation.h index 017cab0a775..34b52072012 100644 --- a/include/llvm/Transforms/Instrumentation.h +++ b/include/llvm/Transforms/Instrumentation.h @@ -155,6 +155,9 @@ ModulePass *createAddressSanitizerModulePass(bool CompileKernel = false, FunctionPass *createHWAddressSanitizerPass(bool CompileKernel = false, bool Recover = false); +// Insert ThreadSanitizer (race detection) instrumentation +FunctionPass *createThreadSanitizerPass(); + // Insert DataFlowSanitizer (dynamic data flow analysis) instrumentation ModulePass *createDataFlowSanitizerPass( const std::vector &ABIListFiles = std::vector(), diff --git a/include/llvm/Transforms/Instrumentation/ThreadSanitizer.h b/include/llvm/Transforms/Instrumentation/ThreadSanitizer.h deleted file mode 100644 index 56874e372a6..00000000000 --- a/include/llvm/Transforms/Instrumentation/ThreadSanitizer.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef LLVM_TRANSFORMS_INSTRUMENTATION_THREADSANITIZER_H -#define LLVM_TRANSFORMS_INSTRUMENTATION_THREADSANITIZER_H - -#include "llvm/IR/PassManager.h" - -namespace llvm { -// Insert ThreadSanitizer (race detection) instrumentation -FunctionPass *createThreadSanitizerLegacyPassPass(); - -/// A function pass for tsan instrumentation. -/// -/// Instruments functions to detect race conditions reads. This function pass -/// inserts calls to runtime library functions. If the functions aren't declared -/// yet, the pass inserts the declarations. Otherwise the existing globals are -struct ThreadSanitizerPass : public PassInfoMixin { - PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM); -}; -} -#endif /* LLVM_TRANSFORMS_INSTRUMENTATION_THREADSANITIZER_H */ diff --git a/lib/Passes/PassBuilder.cpp b/lib/Passes/PassBuilder.cpp index 61b16f1d6b9..e1d0a47fb6d 100644 --- a/lib/Passes/PassBuilder.cpp +++ b/lib/Passes/PassBuilder.cpp @@ -95,7 +95,6 @@ #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/lib/Passes/PassRegistry.def b/lib/Passes/PassRegistry.def index b1b7abe16c7..a8c03ad0596 100644 --- a/lib/Passes/PassRegistry.def +++ b/lib/Passes/PassRegistry.def @@ -234,7 +234,6 @@ 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/lib/Transforms/Instrumentation/Instrumentation.cpp b/lib/Transforms/Instrumentation/Instrumentation.cpp index c3e323613c7..5828019a03a 100644 --- a/lib/Transforms/Instrumentation/Instrumentation.cpp +++ b/lib/Transforms/Instrumentation/Instrumentation.cpp @@ -113,7 +113,7 @@ void llvm::initializeInstrumentation(PassRegistry &Registry) { initializeInstrProfilingLegacyPassPass(Registry); initializeMemorySanitizerLegacyPassPass(Registry); initializeHWAddressSanitizerPass(Registry); - initializeThreadSanitizerLegacyPassPass(Registry); + initializeThreadSanitizerPass(Registry); initializeSanitizerCoverageModulePass(Registry); initializeDataFlowSanitizerPass(Registry); initializeEfficiencySanitizerPass(Registry); diff --git a/lib/Transforms/Instrumentation/ThreadSanitizer.cpp b/lib/Transforms/Instrumentation/ThreadSanitizer.cpp index 7d535db9d6a..fa1e5a157a0 100644 --- a/lib/Transforms/Instrumentation/ThreadSanitizer.cpp +++ b/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 TSan; + Function *TsanCtorFunction; }; } // namespace -PreservedAnalyses ThreadSanitizerPass::run(Function &F, - FunctionAnalysisManager &FAM) { - ThreadSanitizer TSan(*F.getParent()); - if (TSan.sanitizeFunction(F, FAM.getResult(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(); } -bool ThreadSanitizerLegacyPass::doInitialization(Module &M) { - TSan.emplace(M); - return true; -} - -bool ThreadSanitizerLegacyPass::runOnFunction(Function &F) { - auto &TLI = getAnalysis().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 AllLoadsAndStores; SmallVector 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().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(Inst) || isa(Inst)) { if (CallInst *CI = dyn_cast(&Inst)) - maybeMarkSanitizerLibraryCallNoBuiltin(CI, &TLI); + maybeMarkSanitizerLibraryCallNoBuiltin(CI, TLI); if (isa(Inst)) MemIntrinCalls.push_back(&Inst); HasCalls = true; diff --git a/test/Instrumentation/ThreadSanitizer/tsan_basic.ll b/test/Instrumentation/ThreadSanitizer/tsan_basic.ll index cce7f467f41..69d4117399b 100644 --- a/test/Instrumentation/ThreadSanitizer/tsan_basic.ll +++ b/test/Instrumentation/ThreadSanitizer/tsan_basic.ll @@ -1,5 +1,4 @@ ; RUN: opt < %s -tsan -S | FileCheck %s -; RUN: opt < %s -passes=tsan -S | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" @@ -10,7 +9,7 @@ entry: ret i32 %tmp1 } -; CHECK: @llvm.global_ctors = {{.*}}@__tsan_init +; CHECK: @llvm.global_ctors = {{.*}}@tsan.module_ctor ; CHECK: define i32 @read_4_bytes(i32* %a) ; CHECK: call void @__tsan_func_entry(i8* %0) @@ -78,3 +77,6 @@ define void @SwiftErrorCall(i8** swifterror) sanitize_thread { call void @SwiftError(i8** %0) ret void } + +; CHECK: define internal void @tsan.module_ctor() +; CHECK: call void @__tsan_init()