summaryrefslogtreecommitdiff
path: root/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Transforms/Instrumentation/ThreadSanitizer.cpp')
-rw-r--r--lib/Transforms/Instrumentation/ThreadSanitizer.cpp54
1 files changed, 28 insertions, 26 deletions
diff --git a/lib/Transforms/Instrumentation/ThreadSanitizer.cpp b/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
index 5be13fa745cb..ac274a155a80 100644
--- a/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
+++ b/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
@@ -92,11 +92,10 @@ namespace {
/// 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);
+ void initialize(Module &M);
bool instrumentLoadOrStore(Instruction *I, const DataLayout &DL);
bool instrumentAtomic(Instruction *I, const DataLayout &DL);
bool instrumentMemIntrinsic(Instruction *I);
@@ -108,8 +107,6 @@ private:
void InsertRuntimeIgnores(Function &F);
Type *IntptrTy;
- IntegerType *OrdTy;
- // Callbacks to run-time library are computed in doInitialization.
FunctionCallee TsanFuncEntry;
FunctionCallee TsanFuncExit;
FunctionCallee TsanIgnoreBegin;
@@ -130,7 +127,6 @@ private:
FunctionCallee TsanVptrUpdate;
FunctionCallee TsanVptrLoad;
FunctionCallee MemmoveFn, MemcpyFn, MemsetFn;
- Function *TsanCtorFunction;
};
struct ThreadSanitizerLegacyPass : FunctionPass {
@@ -143,16 +139,32 @@ struct ThreadSanitizerLegacyPass : FunctionPass {
private:
Optional<ThreadSanitizer> TSan;
};
+
+void insertModuleCtor(Module &M) {
+ getOrCreateSanitizerCtorAndInitFunctions(
+ M, kTsanModuleCtorName, kTsanInitName, /*InitArgTypes=*/{},
+ /*InitArgs=*/{},
+ // This callback is invoked when the functions are created the first
+ // time. Hook them into the global ctors list in that case:
+ [&](Function *Ctor, FunctionCallee) { appendToGlobalCtors(M, Ctor, 0); });
+}
+
} // namespace
PreservedAnalyses ThreadSanitizerPass::run(Function &F,
FunctionAnalysisManager &FAM) {
- ThreadSanitizer TSan(*F.getParent());
+ ThreadSanitizer TSan;
if (TSan.sanitizeFunction(F, FAM.getResult<TargetLibraryAnalysis>(F)))
return PreservedAnalyses::none();
return PreservedAnalyses::all();
}
+PreservedAnalyses ThreadSanitizerPass::run(Module &M,
+ ModuleAnalysisManager &MAM) {
+ insertModuleCtor(M);
+ return PreservedAnalyses::none();
+}
+
char ThreadSanitizerLegacyPass::ID = 0;
INITIALIZE_PASS_BEGIN(ThreadSanitizerLegacyPass, "tsan",
"ThreadSanitizer: detects data races.", false, false)
@@ -169,12 +181,13 @@ void ThreadSanitizerLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const {
}
bool ThreadSanitizerLegacyPass::doInitialization(Module &M) {
- TSan.emplace(M);
+ insertModuleCtor(M);
+ TSan.emplace();
return true;
}
bool ThreadSanitizerLegacyPass::runOnFunction(Function &F) {
- auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
+ auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
TSan->sanitizeFunction(F, TLI);
return true;
}
@@ -183,7 +196,10 @@ FunctionPass *llvm::createThreadSanitizerLegacyPassPass() {
return new ThreadSanitizerLegacyPass();
}
-void ThreadSanitizer::initializeCallbacks(Module &M) {
+void ThreadSanitizer::initialize(Module &M) {
+ const DataLayout &DL = M.getDataLayout();
+ IntptrTy = DL.getIntPtrType(M.getContext());
+
IRBuilder<> IRB(M.getContext());
AttributeList Attr;
Attr = Attr.addAttribute(M.getContext(), AttributeList::FunctionIndex,
@@ -197,7 +213,7 @@ void ThreadSanitizer::initializeCallbacks(Module &M) {
IRB.getVoidTy());
TsanIgnoreEnd =
M.getOrInsertFunction("__tsan_ignore_thread_end", Attr, IRB.getVoidTy());
- OrdTy = IRB.getInt32Ty();
+ IntegerType *OrdTy = IRB.getInt32Ty();
for (size_t i = 0; i < kNumberOfAccessSizes; ++i) {
const unsigned ByteSize = 1U << i;
const unsigned BitSize = ByteSize * 8;
@@ -280,20 +296,6 @@ void ThreadSanitizer::initializeCallbacks(Module &M) {
IRB.getInt8PtrTy(), IRB.getInt32Ty(), IntptrTy);
}
-ThreadSanitizer::ThreadSanitizer(Module &M) {
- const DataLayout &DL = M.getDataLayout();
- IntptrTy = DL.getIntPtrType(M.getContext());
- std::tie(TsanCtorFunction, std::ignore) =
- getOrCreateSanitizerCtorAndInitFunctions(
- M, kTsanModuleCtorName, kTsanInitName, /*InitArgTypes=*/{},
- /*InitArgs=*/{},
- // This callback is invoked when the functions are created the first
- // time. Hook them into the global ctors list in that case:
- [&](Function *Ctor, FunctionCallee) {
- appendToGlobalCtors(M, Ctor, 0);
- });
-}
-
static bool isVtableAccess(Instruction *I) {
if (MDNode *Tag = I->getMetadata(LLVMContext::MD_tbaa))
return Tag->isTBAAVtableAccess();
@@ -436,9 +438,9 @@ bool ThreadSanitizer::sanitizeFunction(Function &F,
const TargetLibraryInfo &TLI) {
// This is required to prevent instrumenting call to __tsan_init from within
// the module constructor.
- if (&F == TsanCtorFunction)
+ if (F.getName() == kTsanModuleCtorName)
return false;
- initializeCallbacks(*F.getParent());
+ initialize(*F.getParent());
SmallVector<Instruction*, 8> AllLoadsAndStores;
SmallVector<Instruction*, 8> LocalLoadsAndStores;
SmallVector<Instruction*, 8> AtomicAccesses;