LLVM API Documentation

ThreadSanitizer.cpp
Go to the documentation of this file.
00001 //===-- ThreadSanitizer.cpp - race detector -------------------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file is a part of ThreadSanitizer, a race detector.
00011 //
00012 // The tool is under development, for the details about previous versions see
00013 // http://code.google.com/p/data-race-test
00014 //
00015 // The instrumentation phase is quite simple:
00016 //   - Insert calls to run-time library before every memory access.
00017 //      - Optimizations may apply to avoid instrumenting some of the accesses.
00018 //   - Insert calls at function entry/exit.
00019 // The rest is handled by the run-time library.
00020 //===----------------------------------------------------------------------===//
00021 
00022 #include "llvm/Transforms/Instrumentation.h"
00023 #include "llvm/ADT/SmallSet.h"
00024 #include "llvm/ADT/SmallString.h"
00025 #include "llvm/ADT/SmallVector.h"
00026 #include "llvm/ADT/Statistic.h"
00027 #include "llvm/ADT/StringExtras.h"
00028 #include "llvm/IR/DataLayout.h"
00029 #include "llvm/IR/Function.h"
00030 #include "llvm/IR/IRBuilder.h"
00031 #include "llvm/IR/IntrinsicInst.h"
00032 #include "llvm/IR/Intrinsics.h"
00033 #include "llvm/IR/LLVMContext.h"
00034 #include "llvm/IR/Metadata.h"
00035 #include "llvm/IR/Module.h"
00036 #include "llvm/IR/Type.h"
00037 #include "llvm/Support/CommandLine.h"
00038 #include "llvm/Support/Debug.h"
00039 #include "llvm/Support/MathExtras.h"
00040 #include "llvm/Support/raw_ostream.h"
00041 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
00042 #include "llvm/Transforms/Utils/ModuleUtils.h"
00043 
00044 using namespace llvm;
00045 
00046 #define DEBUG_TYPE "tsan"
00047 
00048 static cl::opt<bool>  ClInstrumentMemoryAccesses(
00049     "tsan-instrument-memory-accesses", cl::init(true),
00050     cl::desc("Instrument memory accesses"), cl::Hidden);
00051 static cl::opt<bool>  ClInstrumentFuncEntryExit(
00052     "tsan-instrument-func-entry-exit", cl::init(true),
00053     cl::desc("Instrument function entry and exit"), cl::Hidden);
00054 static cl::opt<bool>  ClInstrumentAtomics(
00055     "tsan-instrument-atomics", cl::init(true),
00056     cl::desc("Instrument atomics"), cl::Hidden);
00057 static cl::opt<bool>  ClInstrumentMemIntrinsics(
00058     "tsan-instrument-memintrinsics", cl::init(true),
00059     cl::desc("Instrument memintrinsics (memset/memcpy/memmove)"), cl::Hidden);
00060 
00061 STATISTIC(NumInstrumentedReads, "Number of instrumented reads");
00062 STATISTIC(NumInstrumentedWrites, "Number of instrumented writes");
00063 STATISTIC(NumOmittedReadsBeforeWrite,
00064           "Number of reads ignored due to following writes");
00065 STATISTIC(NumAccessesWithBadSize, "Number of accesses with bad size");
00066 STATISTIC(NumInstrumentedVtableWrites, "Number of vtable ptr writes");
00067 STATISTIC(NumInstrumentedVtableReads, "Number of vtable ptr reads");
00068 STATISTIC(NumOmittedReadsFromConstantGlobals,
00069           "Number of reads from constant globals");
00070 STATISTIC(NumOmittedReadsFromVtable, "Number of vtable reads");
00071 
00072 namespace {
00073 
00074 /// ThreadSanitizer: instrument the code in module to find races.
00075 struct ThreadSanitizer : public FunctionPass {
00076   ThreadSanitizer() : FunctionPass(ID), DL(nullptr) {}
00077   const char *getPassName() const override;
00078   bool runOnFunction(Function &F) override;
00079   bool doInitialization(Module &M) override;
00080   static char ID;  // Pass identification, replacement for typeid.
00081 
00082  private:
00083   void initializeCallbacks(Module &M);
00084   bool instrumentLoadOrStore(Instruction *I);
00085   bool instrumentAtomic(Instruction *I);
00086   bool instrumentMemIntrinsic(Instruction *I);
00087   void chooseInstructionsToInstrument(SmallVectorImpl<Instruction*> &Local,
00088                                       SmallVectorImpl<Instruction*> &All);
00089   bool addrPointsToConstantData(Value *Addr);
00090   int getMemoryAccessFuncIndex(Value *Addr);
00091 
00092   const DataLayout *DL;
00093   Type *IntptrTy;
00094   IntegerType *OrdTy;
00095   // Callbacks to run-time library are computed in doInitialization.
00096   Function *TsanFuncEntry;
00097   Function *TsanFuncExit;
00098   // Accesses sizes are powers of two: 1, 2, 4, 8, 16.
00099   static const size_t kNumberOfAccessSizes = 5;
00100   Function *TsanRead[kNumberOfAccessSizes];
00101   Function *TsanWrite[kNumberOfAccessSizes];
00102   Function *TsanAtomicLoad[kNumberOfAccessSizes];
00103   Function *TsanAtomicStore[kNumberOfAccessSizes];
00104   Function *TsanAtomicRMW[AtomicRMWInst::LAST_BINOP + 1][kNumberOfAccessSizes];
00105   Function *TsanAtomicCAS[kNumberOfAccessSizes];
00106   Function *TsanAtomicThreadFence;
00107   Function *TsanAtomicSignalFence;
00108   Function *TsanVptrUpdate;
00109   Function *TsanVptrLoad;
00110   Function *MemmoveFn, *MemcpyFn, *MemsetFn;
00111 };
00112 }  // namespace
00113 
00114 char ThreadSanitizer::ID = 0;
00115 INITIALIZE_PASS(ThreadSanitizer, "tsan",
00116     "ThreadSanitizer: detects data races.",
00117     false, false)
00118 
00119 const char *ThreadSanitizer::getPassName() const {
00120   return "ThreadSanitizer";
00121 }
00122 
00123 FunctionPass *llvm::createThreadSanitizerPass() {
00124   return new ThreadSanitizer();
00125 }
00126 
00127 static Function *checkInterfaceFunction(Constant *FuncOrBitcast) {
00128   if (Function *F = dyn_cast<Function>(FuncOrBitcast))
00129      return F;
00130   FuncOrBitcast->dump();
00131   report_fatal_error("ThreadSanitizer interface function redefined");
00132 }
00133 
00134 void ThreadSanitizer::initializeCallbacks(Module &M) {
00135   IRBuilder<> IRB(M.getContext());
00136   // Initialize the callbacks.
00137   TsanFuncEntry = checkInterfaceFunction(M.getOrInsertFunction(
00138       "__tsan_func_entry", IRB.getVoidTy(), IRB.getInt8PtrTy(), NULL));
00139   TsanFuncExit = checkInterfaceFunction(M.getOrInsertFunction(
00140       "__tsan_func_exit", IRB.getVoidTy(), NULL));
00141   OrdTy = IRB.getInt32Ty();
00142   for (size_t i = 0; i < kNumberOfAccessSizes; ++i) {
00143     const size_t ByteSize = 1 << i;
00144     const size_t BitSize = ByteSize * 8;
00145     SmallString<32> ReadName("__tsan_read" + itostr(ByteSize));
00146     TsanRead[i] = checkInterfaceFunction(M.getOrInsertFunction(
00147         ReadName, IRB.getVoidTy(), IRB.getInt8PtrTy(), NULL));
00148 
00149     SmallString<32> WriteName("__tsan_write" + itostr(ByteSize));
00150     TsanWrite[i] = checkInterfaceFunction(M.getOrInsertFunction(
00151         WriteName, IRB.getVoidTy(), IRB.getInt8PtrTy(), NULL));
00152 
00153     Type *Ty = Type::getIntNTy(M.getContext(), BitSize);
00154     Type *PtrTy = Ty->getPointerTo();
00155     SmallString<32> AtomicLoadName("__tsan_atomic" + itostr(BitSize) +
00156                                    "_load");
00157     TsanAtomicLoad[i] = checkInterfaceFunction(M.getOrInsertFunction(
00158         AtomicLoadName, Ty, PtrTy, OrdTy, NULL));
00159 
00160     SmallString<32> AtomicStoreName("__tsan_atomic" + itostr(BitSize) +
00161                                     "_store");
00162     TsanAtomicStore[i] = checkInterfaceFunction(M.getOrInsertFunction(
00163         AtomicStoreName, IRB.getVoidTy(), PtrTy, Ty, OrdTy,
00164         NULL));
00165 
00166     for (int op = AtomicRMWInst::FIRST_BINOP;
00167         op <= AtomicRMWInst::LAST_BINOP; ++op) {
00168       TsanAtomicRMW[op][i] = nullptr;
00169       const char *NamePart = nullptr;
00170       if (op == AtomicRMWInst::Xchg)
00171         NamePart = "_exchange";
00172       else if (op == AtomicRMWInst::Add)
00173         NamePart = "_fetch_add";
00174       else if (op == AtomicRMWInst::Sub)
00175         NamePart = "_fetch_sub";
00176       else if (op == AtomicRMWInst::And)
00177         NamePart = "_fetch_and";
00178       else if (op == AtomicRMWInst::Or)
00179         NamePart = "_fetch_or";
00180       else if (op == AtomicRMWInst::Xor)
00181         NamePart = "_fetch_xor";
00182       else if (op == AtomicRMWInst::Nand)
00183         NamePart = "_fetch_nand";
00184       else
00185         continue;
00186       SmallString<32> RMWName("__tsan_atomic" + itostr(BitSize) + NamePart);
00187       TsanAtomicRMW[op][i] = checkInterfaceFunction(M.getOrInsertFunction(
00188           RMWName, Ty, PtrTy, Ty, OrdTy, NULL));
00189     }
00190 
00191     SmallString<32> AtomicCASName("__tsan_atomic" + itostr(BitSize) +
00192                                   "_compare_exchange_val");
00193     TsanAtomicCAS[i] = checkInterfaceFunction(M.getOrInsertFunction(
00194         AtomicCASName, Ty, PtrTy, Ty, Ty, OrdTy, OrdTy, NULL));
00195   }
00196   TsanVptrUpdate = checkInterfaceFunction(M.getOrInsertFunction(
00197       "__tsan_vptr_update", IRB.getVoidTy(), IRB.getInt8PtrTy(),
00198       IRB.getInt8PtrTy(), NULL));
00199   TsanVptrLoad = checkInterfaceFunction(M.getOrInsertFunction(
00200       "__tsan_vptr_read", IRB.getVoidTy(), IRB.getInt8PtrTy(), NULL));
00201   TsanAtomicThreadFence = checkInterfaceFunction(M.getOrInsertFunction(
00202       "__tsan_atomic_thread_fence", IRB.getVoidTy(), OrdTy, NULL));
00203   TsanAtomicSignalFence = checkInterfaceFunction(M.getOrInsertFunction(
00204       "__tsan_atomic_signal_fence", IRB.getVoidTy(), OrdTy, NULL));
00205 
00206   MemmoveFn = checkInterfaceFunction(M.getOrInsertFunction(
00207     "memmove", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
00208     IRB.getInt8PtrTy(), IntptrTy, NULL));
00209   MemcpyFn = checkInterfaceFunction(M.getOrInsertFunction(
00210     "memcpy", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
00211     IntptrTy, NULL));
00212   MemsetFn = checkInterfaceFunction(M.getOrInsertFunction(
00213     "memset", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IRB.getInt32Ty(),
00214     IntptrTy, NULL));
00215 }
00216 
00217 bool ThreadSanitizer::doInitialization(Module &M) {
00218   DataLayoutPass *DLP = getAnalysisIfAvailable<DataLayoutPass>();
00219   if (!DLP)
00220     report_fatal_error("data layout missing");
00221   DL = &DLP->getDataLayout();
00222 
00223   // Always insert a call to __tsan_init into the module's CTORs.
00224   IRBuilder<> IRB(M.getContext());
00225   IntptrTy = IRB.getIntPtrTy(DL);
00226   Value *TsanInit = M.getOrInsertFunction("__tsan_init",
00227                                           IRB.getVoidTy(), NULL);
00228   appendToGlobalCtors(M, cast<Function>(TsanInit), 0);
00229 
00230   return true;
00231 }
00232 
00233 static bool isVtableAccess(Instruction *I) {
00234   if (MDNode *Tag = I->getMetadata(LLVMContext::MD_tbaa))
00235     return Tag->isTBAAVtableAccess();
00236   return false;
00237 }
00238 
00239 bool ThreadSanitizer::addrPointsToConstantData(Value *Addr) {
00240   // If this is a GEP, just analyze its pointer operand.
00241   if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Addr))
00242     Addr = GEP->getPointerOperand();
00243 
00244   if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Addr)) {
00245     if (GV->isConstant()) {
00246       // Reads from constant globals can not race with any writes.
00247       NumOmittedReadsFromConstantGlobals++;
00248       return true;
00249     }
00250   } else if (LoadInst *L = dyn_cast<LoadInst>(Addr)) {
00251     if (isVtableAccess(L)) {
00252       // Reads from a vtable pointer can not race with any writes.
00253       NumOmittedReadsFromVtable++;
00254       return true;
00255     }
00256   }
00257   return false;
00258 }
00259 
00260 // Instrumenting some of the accesses may be proven redundant.
00261 // Currently handled:
00262 //  - read-before-write (within same BB, no calls between)
00263 //
00264 // We do not handle some of the patterns that should not survive
00265 // after the classic compiler optimizations.
00266 // E.g. two reads from the same temp should be eliminated by CSE,
00267 // two writes should be eliminated by DSE, etc.
00268 //
00269 // 'Local' is a vector of insns within the same BB (no calls between).
00270 // 'All' is a vector of insns that will be instrumented.
00271 void ThreadSanitizer::chooseInstructionsToInstrument(
00272     SmallVectorImpl<Instruction*> &Local,
00273     SmallVectorImpl<Instruction*> &All) {
00274   SmallSet<Value*, 8> WriteTargets;
00275   // Iterate from the end.
00276   for (SmallVectorImpl<Instruction*>::reverse_iterator It = Local.rbegin(),
00277        E = Local.rend(); It != E; ++It) {
00278     Instruction *I = *It;
00279     if (StoreInst *Store = dyn_cast<StoreInst>(I)) {
00280       WriteTargets.insert(Store->getPointerOperand());
00281     } else {
00282       LoadInst *Load = cast<LoadInst>(I);
00283       Value *Addr = Load->getPointerOperand();
00284       if (WriteTargets.count(Addr)) {
00285         // We will write to this temp, so no reason to analyze the read.
00286         NumOmittedReadsBeforeWrite++;
00287         continue;
00288       }
00289       if (addrPointsToConstantData(Addr)) {
00290         // Addr points to some constant data -- it can not race with any writes.
00291         continue;
00292       }
00293     }
00294     All.push_back(I);
00295   }
00296   Local.clear();
00297 }
00298 
00299 static bool isAtomic(Instruction *I) {
00300   if (LoadInst *LI = dyn_cast<LoadInst>(I))
00301     return LI->isAtomic() && LI->getSynchScope() == CrossThread;
00302   if (StoreInst *SI = dyn_cast<StoreInst>(I))
00303     return SI->isAtomic() && SI->getSynchScope() == CrossThread;
00304   if (isa<AtomicRMWInst>(I))
00305     return true;
00306   if (isa<AtomicCmpXchgInst>(I))
00307     return true;
00308   if (isa<FenceInst>(I))
00309     return true;
00310   return false;
00311 }
00312 
00313 bool ThreadSanitizer::runOnFunction(Function &F) {
00314   if (!DL) return false;
00315   initializeCallbacks(*F.getParent());
00316   SmallVector<Instruction*, 8> RetVec;
00317   SmallVector<Instruction*, 8> AllLoadsAndStores;
00318   SmallVector<Instruction*, 8> LocalLoadsAndStores;
00319   SmallVector<Instruction*, 8> AtomicAccesses;
00320   SmallVector<Instruction*, 8> MemIntrinCalls;
00321   bool Res = false;
00322   bool HasCalls = false;
00323   bool SanitizeFunction = F.hasFnAttribute(Attribute::SanitizeThread);
00324 
00325   // Traverse all instructions, collect loads/stores/returns, check for calls.
00326   for (auto &BB : F) {
00327     for (auto &Inst : BB) {
00328       if (isAtomic(&Inst))
00329         AtomicAccesses.push_back(&Inst);
00330       else if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst))
00331         LocalLoadsAndStores.push_back(&Inst);
00332       else if (isa<ReturnInst>(Inst))
00333         RetVec.push_back(&Inst);
00334       else if (isa<CallInst>(Inst) || isa<InvokeInst>(Inst)) {
00335         if (isa<MemIntrinsic>(Inst))
00336           MemIntrinCalls.push_back(&Inst);
00337         HasCalls = true;
00338         chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores);
00339       }
00340     }
00341     chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores);
00342   }
00343 
00344   // We have collected all loads and stores.
00345   // FIXME: many of these accesses do not need to be checked for races
00346   // (e.g. variables that do not escape, etc).
00347 
00348   // Instrument memory accesses only if we want to report bugs in the function.
00349   if (ClInstrumentMemoryAccesses && SanitizeFunction)
00350     for (auto Inst : AllLoadsAndStores) {
00351       Res |= instrumentLoadOrStore(Inst);
00352     }
00353 
00354   // Instrument atomic memory accesses in any case (they can be used to
00355   // implement synchronization).
00356   if (ClInstrumentAtomics)
00357     for (auto Inst : AtomicAccesses) {
00358       Res |= instrumentAtomic(Inst);
00359     }
00360 
00361   if (ClInstrumentMemIntrinsics && SanitizeFunction)
00362     for (auto Inst : MemIntrinCalls) {
00363       Res |= instrumentMemIntrinsic(Inst);
00364     }
00365 
00366   // Instrument function entry/exit points if there were instrumented accesses.
00367   if ((Res || HasCalls) && ClInstrumentFuncEntryExit) {
00368     IRBuilder<> IRB(F.getEntryBlock().getFirstNonPHI());
00369     Value *ReturnAddress = IRB.CreateCall(
00370         Intrinsic::getDeclaration(F.getParent(), Intrinsic::returnaddress),
00371         IRB.getInt32(0));
00372     IRB.CreateCall(TsanFuncEntry, ReturnAddress);
00373     for (auto RetInst : RetVec) {
00374       IRBuilder<> IRBRet(RetInst);
00375       IRBRet.CreateCall(TsanFuncExit);
00376     }
00377     Res = true;
00378   }
00379   return Res;
00380 }
00381 
00382 bool ThreadSanitizer::instrumentLoadOrStore(Instruction *I) {
00383   IRBuilder<> IRB(I);
00384   bool IsWrite = isa<StoreInst>(*I);
00385   Value *Addr = IsWrite
00386       ? cast<StoreInst>(I)->getPointerOperand()
00387       : cast<LoadInst>(I)->getPointerOperand();
00388   int Idx = getMemoryAccessFuncIndex(Addr);
00389   if (Idx < 0)
00390     return false;
00391   if (IsWrite && isVtableAccess(I)) {
00392     DEBUG(dbgs() << "  VPTR : " << *I << "\n");
00393     Value *StoredValue = cast<StoreInst>(I)->getValueOperand();
00394     // StoredValue may be a vector type if we are storing several vptrs at once.
00395     // In this case, just take the first element of the vector since this is
00396     // enough to find vptr races.
00397     if (isa<VectorType>(StoredValue->getType()))
00398       StoredValue = IRB.CreateExtractElement(
00399           StoredValue, ConstantInt::get(IRB.getInt32Ty(), 0));
00400     if (StoredValue->getType()->isIntegerTy())
00401       StoredValue = IRB.CreateIntToPtr(StoredValue, IRB.getInt8PtrTy());
00402     // Call TsanVptrUpdate.
00403     IRB.CreateCall2(TsanVptrUpdate,
00404                     IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()),
00405                     IRB.CreatePointerCast(StoredValue, IRB.getInt8PtrTy()));
00406     NumInstrumentedVtableWrites++;
00407     return true;
00408   }
00409   if (!IsWrite && isVtableAccess(I)) {
00410     IRB.CreateCall(TsanVptrLoad,
00411                    IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()));
00412     NumInstrumentedVtableReads++;
00413     return true;
00414   }
00415   Value *OnAccessFunc = IsWrite ? TsanWrite[Idx] : TsanRead[Idx];
00416   IRB.CreateCall(OnAccessFunc, IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()));
00417   if (IsWrite) NumInstrumentedWrites++;
00418   else         NumInstrumentedReads++;
00419   return true;
00420 }
00421 
00422 static ConstantInt *createOrdering(IRBuilder<> *IRB, AtomicOrdering ord) {
00423   uint32_t v = 0;
00424   switch (ord) {
00425     case NotAtomic:              assert(false);
00426     case Unordered:              // Fall-through.
00427     case Monotonic:              v = 0; break;
00428     // case Consume:                v = 1; break;  // Not specified yet.
00429     case Acquire:                v = 2; break;
00430     case Release:                v = 3; break;
00431     case AcquireRelease:         v = 4; break;
00432     case SequentiallyConsistent: v = 5; break;
00433   }
00434   return IRB->getInt32(v);
00435 }
00436 
00437 // If a memset intrinsic gets inlined by the code gen, we will miss races on it.
00438 // So, we either need to ensure the intrinsic is not inlined, or instrument it.
00439 // We do not instrument memset/memmove/memcpy intrinsics (too complicated),
00440 // instead we simply replace them with regular function calls, which are then
00441 // intercepted by the run-time.
00442 // Since tsan is running after everyone else, the calls should not be
00443 // replaced back with intrinsics. If that becomes wrong at some point,
00444 // we will need to call e.g. __tsan_memset to avoid the intrinsics.
00445 bool ThreadSanitizer::instrumentMemIntrinsic(Instruction *I) {
00446   IRBuilder<> IRB(I);
00447   if (MemSetInst *M = dyn_cast<MemSetInst>(I)) {
00448     IRB.CreateCall3(MemsetFn,
00449       IRB.CreatePointerCast(M->getArgOperand(0), IRB.getInt8PtrTy()),
00450       IRB.CreateIntCast(M->getArgOperand(1), IRB.getInt32Ty(), false),
00451       IRB.CreateIntCast(M->getArgOperand(2), IntptrTy, false));
00452     I->eraseFromParent();
00453   } else if (MemTransferInst *M = dyn_cast<MemTransferInst>(I)) {
00454     IRB.CreateCall3(isa<MemCpyInst>(M) ? MemcpyFn : MemmoveFn,
00455       IRB.CreatePointerCast(M->getArgOperand(0), IRB.getInt8PtrTy()),
00456       IRB.CreatePointerCast(M->getArgOperand(1), IRB.getInt8PtrTy()),
00457       IRB.CreateIntCast(M->getArgOperand(2), IntptrTy, false));
00458     I->eraseFromParent();
00459   }
00460   return false;
00461 }
00462 
00463 // Both llvm and ThreadSanitizer atomic operations are based on C++11/C1x
00464 // standards.  For background see C++11 standard.  A slightly older, publicly
00465 // available draft of the standard (not entirely up-to-date, but close enough
00466 // for casual browsing) is available here:
00467 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf
00468 // The following page contains more background information:
00469 // http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/
00470 
00471 bool ThreadSanitizer::instrumentAtomic(Instruction *I) {
00472   IRBuilder<> IRB(I);
00473   if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
00474     Value *Addr = LI->getPointerOperand();
00475     int Idx = getMemoryAccessFuncIndex(Addr);
00476     if (Idx < 0)
00477       return false;
00478     const size_t ByteSize = 1 << Idx;
00479     const size_t BitSize = ByteSize * 8;
00480     Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize);
00481     Type *PtrTy = Ty->getPointerTo();
00482     Value *Args[] = {IRB.CreatePointerCast(Addr, PtrTy),
00483                      createOrdering(&IRB, LI->getOrdering())};
00484     CallInst *C = CallInst::Create(TsanAtomicLoad[Idx], Args);
00485     ReplaceInstWithInst(I, C);
00486 
00487   } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
00488     Value *Addr = SI->getPointerOperand();
00489     int Idx = getMemoryAccessFuncIndex(Addr);
00490     if (Idx < 0)
00491       return false;
00492     const size_t ByteSize = 1 << Idx;
00493     const size_t BitSize = ByteSize * 8;
00494     Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize);
00495     Type *PtrTy = Ty->getPointerTo();
00496     Value *Args[] = {IRB.CreatePointerCast(Addr, PtrTy),
00497                      IRB.CreateIntCast(SI->getValueOperand(), Ty, false),
00498                      createOrdering(&IRB, SI->getOrdering())};
00499     CallInst *C = CallInst::Create(TsanAtomicStore[Idx], Args);
00500     ReplaceInstWithInst(I, C);
00501   } else if (AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(I)) {
00502     Value *Addr = RMWI->getPointerOperand();
00503     int Idx = getMemoryAccessFuncIndex(Addr);
00504     if (Idx < 0)
00505       return false;
00506     Function *F = TsanAtomicRMW[RMWI->getOperation()][Idx];
00507     if (!F)
00508       return false;
00509     const size_t ByteSize = 1 << Idx;
00510     const size_t BitSize = ByteSize * 8;
00511     Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize);
00512     Type *PtrTy = Ty->getPointerTo();
00513     Value *Args[] = {IRB.CreatePointerCast(Addr, PtrTy),
00514                      IRB.CreateIntCast(RMWI->getValOperand(), Ty, false),
00515                      createOrdering(&IRB, RMWI->getOrdering())};
00516     CallInst *C = CallInst::Create(F, Args);
00517     ReplaceInstWithInst(I, C);
00518   } else if (AtomicCmpXchgInst *CASI = dyn_cast<AtomicCmpXchgInst>(I)) {
00519     Value *Addr = CASI->getPointerOperand();
00520     int Idx = getMemoryAccessFuncIndex(Addr);
00521     if (Idx < 0)
00522       return false;
00523     const size_t ByteSize = 1 << Idx;
00524     const size_t BitSize = ByteSize * 8;
00525     Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize);
00526     Type *PtrTy = Ty->getPointerTo();
00527     Value *Args[] = {IRB.CreatePointerCast(Addr, PtrTy),
00528                      IRB.CreateIntCast(CASI->getCompareOperand(), Ty, false),
00529                      IRB.CreateIntCast(CASI->getNewValOperand(), Ty, false),
00530                      createOrdering(&IRB, CASI->getSuccessOrdering()),
00531                      createOrdering(&IRB, CASI->getFailureOrdering())};
00532     CallInst *C = IRB.CreateCall(TsanAtomicCAS[Idx], Args);
00533     Value *Success = IRB.CreateICmpEQ(C, CASI->getCompareOperand());
00534 
00535     Value *Res = IRB.CreateInsertValue(UndefValue::get(CASI->getType()), C, 0);
00536     Res = IRB.CreateInsertValue(Res, Success, 1);
00537 
00538     I->replaceAllUsesWith(Res);
00539     I->eraseFromParent();
00540   } else if (FenceInst *FI = dyn_cast<FenceInst>(I)) {
00541     Value *Args[] = {createOrdering(&IRB, FI->getOrdering())};
00542     Function *F = FI->getSynchScope() == SingleThread ?
00543         TsanAtomicSignalFence : TsanAtomicThreadFence;
00544     CallInst *C = CallInst::Create(F, Args);
00545     ReplaceInstWithInst(I, C);
00546   }
00547   return true;
00548 }
00549 
00550 int ThreadSanitizer::getMemoryAccessFuncIndex(Value *Addr) {
00551   Type *OrigPtrTy = Addr->getType();
00552   Type *OrigTy = cast<PointerType>(OrigPtrTy)->getElementType();
00553   assert(OrigTy->isSized());
00554   uint32_t TypeSize = DL->getTypeStoreSizeInBits(OrigTy);
00555   if (TypeSize != 8  && TypeSize != 16 &&
00556       TypeSize != 32 && TypeSize != 64 && TypeSize != 128) {
00557     NumAccessesWithBadSize++;
00558     // Ignore all unusual sizes.
00559     return -1;
00560   }
00561   size_t Idx = countTrailingZeros(TypeSize / 8);
00562   assert(Idx < kNumberOfAccessSizes);
00563   return Idx;
00564 }