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