19
19
// The rest is handled by the run-time library.
20
20
// ===----------------------------------------------------------------------===//
21
21
22
+ #include " llvm/Transforms/Instrumentation/ThreadSanitizer.h"
22
23
#include " llvm/ADT/SmallPtrSet.h"
23
24
#include " llvm/ADT/SmallString.h"
24
25
#include " llvm/ADT/SmallVector.h"
@@ -86,15 +87,16 @@ static const char *const kTsanInitName = "__tsan_init";
86
87
namespace {
87
88
88
89
// / ThreadSanitizer: instrument the code in module to find races.
89
- struct ThreadSanitizer : public FunctionPass {
90
- ThreadSanitizer () : FunctionPass(ID) {}
91
- StringRef getPassName () const override ;
92
- void getAnalysisUsage (AnalysisUsage &AU) const override ;
93
- bool runOnFunction (Function &F) override ;
94
- bool doInitialization (Module &M) override ;
95
- static char ID; // Pass identification, replacement for typeid.
96
-
97
- private:
90
+ // /
91
+ // / Instantiating ThreadSanitizer inserts the tsan runtime library API function
92
+ // / declarations into the module if they don't exist already. Instantiating
93
+ // / ensures the __tsan_init function is in the list of global constructors for
94
+ // / the module.
95
+ struct ThreadSanitizer {
96
+ ThreadSanitizer (Module &M);
97
+ bool sanitizeFunction (Function &F, const TargetLibraryInfo &TLI);
98
+
99
+ private:
98
100
void initializeCallbacks (Module &M);
99
101
bool instrumentLoadOrStore (Instruction *I, const DataLayout &DL);
100
102
bool instrumentAtomic (Instruction *I, const DataLayout &DL);
@@ -130,27 +132,55 @@ struct ThreadSanitizer : public FunctionPass {
130
132
Function *MemmoveFn, *MemcpyFn, *MemsetFn;
131
133
Function *TsanCtorFunction;
132
134
};
135
+
136
+ struct ThreadSanitizerLegacyPass : FunctionPass {
137
+ ThreadSanitizerLegacyPass () : FunctionPass(ID) {}
138
+ StringRef getPassName () const override ;
139
+ void getAnalysisUsage (AnalysisUsage &AU) const override ;
140
+ bool runOnFunction (Function &F) override ;
141
+ bool doInitialization (Module &M) override ;
142
+ static char ID; // Pass identification, replacement for typeid.
143
+ private:
144
+ Optional<ThreadSanitizer> TSan;
145
+ };
133
146
} // namespace
134
147
135
- char ThreadSanitizer::ID = 0 ;
136
- INITIALIZE_PASS_BEGIN (
137
- ThreadSanitizer, " tsan" ,
138
- " ThreadSanitizer: detects data races." ,
139
- false , false )
148
+ PreservedAnalyses ThreadSanitizerPass::run (Function &F,
149
+ FunctionAnalysisManager &FAM) {
150
+ ThreadSanitizer TSan (*F.getParent ());
151
+ if (TSan.sanitizeFunction (F, FAM.getResult <TargetLibraryAnalysis>(F)))
152
+ return PreservedAnalyses::none ();
153
+ return PreservedAnalyses::all ();
154
+ }
155
+
156
+ char ThreadSanitizerLegacyPass::ID = 0 ;
157
+ INITIALIZE_PASS_BEGIN (ThreadSanitizerLegacyPass, " tsan" ,
158
+ " ThreadSanitizer: detects data races." , false , false )
140
159
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
141
- INITIALIZE_PASS_END(
142
- ThreadSanitizer, " tsan" ,
143
- " ThreadSanitizer: detects data races." ,
144
- false , false )
160
+ INITIALIZE_PASS_END(ThreadSanitizerLegacyPass, " tsan" ,
161
+ " ThreadSanitizer: detects data races." , false , false )
145
162
146
- StringRef ThreadSanitizer::getPassName() const { return " ThreadSanitizer" ; }
163
+ StringRef ThreadSanitizerLegacyPass::getPassName() const {
164
+ return " ThreadSanitizerLegacyPass" ;
165
+ }
147
166
148
- void ThreadSanitizer ::getAnalysisUsage (AnalysisUsage &AU) const {
167
+ void ThreadSanitizerLegacyPass ::getAnalysisUsage (AnalysisUsage &AU) const {
149
168
AU.addRequired <TargetLibraryInfoWrapperPass>();
150
169
}
151
170
152
- FunctionPass *llvm::createThreadSanitizerPass () {
153
- return new ThreadSanitizer ();
171
+ bool ThreadSanitizerLegacyPass::doInitialization (Module &M) {
172
+ TSan.emplace (M);
173
+ return true ;
174
+ }
175
+
176
+ bool ThreadSanitizerLegacyPass::runOnFunction (Function &F) {
177
+ auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI ();
178
+ TSan->sanitizeFunction (F, TLI);
179
+ return true ;
180
+ }
181
+
182
+ FunctionPass *llvm::createThreadSanitizerLegacyPassPass () {
183
+ return new ThreadSanitizerLegacyPass ();
154
184
}
155
185
156
186
void ThreadSanitizer::initializeCallbacks (Module &M) {
@@ -252,16 +282,16 @@ void ThreadSanitizer::initializeCallbacks(Module &M) {
252
282
IRB.getInt32Ty (), IntptrTy));
253
283
}
254
284
255
- bool ThreadSanitizer::doInitialization (Module &M) {
285
+ ThreadSanitizer::ThreadSanitizer (Module &M) {
256
286
const DataLayout &DL = M.getDataLayout ();
257
287
IntptrTy = DL.getIntPtrType (M.getContext ());
258
- std::tie (TsanCtorFunction, std::ignore) = createSanitizerCtorAndInitFunctions (
259
- M, kTsanModuleCtorName , kTsanInitName , /* InitArgTypes= */ {},
260
- /* InitArgs =*/ {});
261
-
262
- appendToGlobalCtors (M, TsanCtorFunction, 0 );
263
-
264
- return true ;
288
+ std::tie (TsanCtorFunction, std::ignore) =
289
+ getOrCreateSanitizerCtorAndInitFunctions (
290
+ M, kTsanModuleCtorName , kTsanInitName , /* InitArgTypes =*/ {},
291
+ /* InitArgs= */ {},
292
+ // This callback is invoked when the functions are created the first
293
+ // time. Hook them into the global ctors list in that case:
294
+ [&](Function *Ctor, Function *) { appendToGlobalCtors (M, Ctor, 0 ); }) ;
265
295
}
266
296
267
297
static bool isVtableAccess (Instruction *I) {
@@ -402,7 +432,8 @@ void ThreadSanitizer::InsertRuntimeIgnores(Function &F) {
402
432
}
403
433
}
404
434
405
- bool ThreadSanitizer::runOnFunction (Function &F) {
435
+ bool ThreadSanitizer::sanitizeFunction (Function &F,
436
+ const TargetLibraryInfo &TLI) {
406
437
// This is required to prevent instrumenting call to __tsan_init from within
407
438
// the module constructor.
408
439
if (&F == TsanCtorFunction)
@@ -416,8 +447,6 @@ bool ThreadSanitizer::runOnFunction(Function &F) {
416
447
bool HasCalls = false ;
417
448
bool SanitizeFunction = F.hasFnAttribute (Attribute::SanitizeThread);
418
449
const DataLayout &DL = F.getParent ()->getDataLayout ();
419
- const TargetLibraryInfo *TLI =
420
- &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI ();
421
450
422
451
// Traverse all instructions, collect loads/stores/returns, check for calls.
423
452
for (auto &BB : F) {
@@ -428,7 +457,7 @@ bool ThreadSanitizer::runOnFunction(Function &F) {
428
457
LocalLoadsAndStores.push_back (&Inst);
429
458
else if (isa<CallInst>(Inst) || isa<InvokeInst>(Inst)) {
430
459
if (CallInst *CI = dyn_cast<CallInst>(&Inst))
431
- maybeMarkSanitizerLibraryCallNoBuiltin (CI, TLI);
460
+ maybeMarkSanitizerLibraryCallNoBuiltin (CI, & TLI);
432
461
if (isa<MemIntrinsic>(Inst))
433
462
MemIntrinCalls.push_back (&Inst);
434
463
HasCalls = true ;
0 commit comments