160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany//===-- ThreadSanitizer.cpp - race detector -------------------------------===// 260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// 360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// The LLVM Compiler Infrastructure 460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// 560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// This file is distributed under the University of Illinois Open Source 660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// License. See LICENSE.TXT for details. 760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// 860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany//===----------------------------------------------------------------------===// 960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// 1060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// This file is a part of ThreadSanitizer, a race detector. 1160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// 1260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// The tool is under development, for the details about previous versions see 1360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// http://code.google.com/p/data-race-test 1460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// 1560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// The instrumentation phase is quite simple: 1660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// - Insert calls to run-time library before every memory access. 1760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// - Optimizations may apply to avoid instrumenting some of the accesses. 1860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// - Insert calls at function entry/exit. 1960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// The rest is handled by the run-time library. 2060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany//===----------------------------------------------------------------------===// 2160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 2260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#define DEBUG_TYPE "tsan" 2360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 24d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Transforms/Instrumentation.h" 25d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/SmallSet.h" 26d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/SmallString.h" 27d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/SmallVector.h" 28d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/Statistic.h" 29d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/StringExtras.h" 300b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/DataLayout.h" 310b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Function.h" 320b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/IRBuilder.h" 33f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany#include "llvm/IR/IntrinsicInst.h" 340b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Intrinsics.h" 350b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/LLVMContext.h" 360b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Metadata.h" 370b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Module.h" 380b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Type.h" 396e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryany#include "llvm/Support/CommandLine.h" 4060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/Support/Debug.h" 4160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/Support/MathExtras.h" 4252eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany#include "llvm/Support/raw_ostream.h" 43e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany#include "llvm/Transforms/Utils/BasicBlockUtils.h" 4460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/Transforms/Utils/ModuleUtils.h" 45405515d55f470d04ef75f653b7f1994329c9066bPeter Collingbourne#include "llvm/Transforms/Utils/SpecialCaseList.h" 4660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 4760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanyusing namespace llvm; 4860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 49f045df1b8b7f80e17e34c2b5639082a1d0e289aeAlexey Samsonovstatic cl::opt<std::string> ClBlacklistFile("tsan-blacklist", 506e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryany cl::desc("Blacklist file"), cl::Hidden); 5141d876cea3b5212e5ee8bc25c13c6eab54a4a93cKostya Serebryanystatic cl::opt<bool> ClInstrumentMemoryAccesses( 5241d876cea3b5212e5ee8bc25c13c6eab54a4a93cKostya Serebryany "tsan-instrument-memory-accesses", cl::init(true), 5341d876cea3b5212e5ee8bc25c13c6eab54a4a93cKostya Serebryany cl::desc("Instrument memory accesses"), cl::Hidden); 5441d876cea3b5212e5ee8bc25c13c6eab54a4a93cKostya Serebryanystatic cl::opt<bool> ClInstrumentFuncEntryExit( 5541d876cea3b5212e5ee8bc25c13c6eab54a4a93cKostya Serebryany "tsan-instrument-func-entry-exit", cl::init(true), 5641d876cea3b5212e5ee8bc25c13c6eab54a4a93cKostya Serebryany cl::desc("Instrument function entry and exit"), cl::Hidden); 5741d876cea3b5212e5ee8bc25c13c6eab54a4a93cKostya Serebryanystatic cl::opt<bool> ClInstrumentAtomics( 5841d876cea3b5212e5ee8bc25c13c6eab54a4a93cKostya Serebryany "tsan-instrument-atomics", cl::init(true), 5941d876cea3b5212e5ee8bc25c13c6eab54a4a93cKostya Serebryany cl::desc("Instrument atomics"), cl::Hidden); 60f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryanystatic cl::opt<bool> ClInstrumentMemIntrinsics( 61f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany "tsan-instrument-memintrinsics", cl::init(true), 62f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany cl::desc("Instrument memintrinsics (memset/memcpy/memmove)"), cl::Hidden); 636e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryany 642d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya SerebryanySTATISTIC(NumInstrumentedReads, "Number of instrumented reads"); 652d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya SerebryanySTATISTIC(NumInstrumentedWrites, "Number of instrumented writes"); 661dfe9b52646ce56446ecd3548dbc81068369ef3fAlexey SamsonovSTATISTIC(NumOmittedReadsBeforeWrite, 672d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany "Number of reads ignored due to following writes"); 682d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya SerebryanySTATISTIC(NumAccessesWithBadSize, "Number of accesses with bad size"); 692d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya SerebryanySTATISTIC(NumInstrumentedVtableWrites, "Number of vtable ptr writes"); 70ab78ac1a2d55cd81e42f4688fbaa7bd689e6291fDmitry VyukovSTATISTIC(NumInstrumentedVtableReads, "Number of vtable ptr reads"); 712d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya SerebryanySTATISTIC(NumOmittedReadsFromConstantGlobals, 722d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany "Number of reads from constant globals"); 732d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya SerebryanySTATISTIC(NumOmittedReadsFromVtable, "Number of vtable reads"); 742076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany 7560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanynamespace { 762076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany 7760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany/// ThreadSanitizer: instrument the code in module to find races. 7860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanystruct ThreadSanitizer : public FunctionPass { 79f045df1b8b7f80e17e34c2b5639082a1d0e289aeAlexey Samsonov ThreadSanitizer(StringRef BlacklistFile = StringRef()) 80f045df1b8b7f80e17e34c2b5639082a1d0e289aeAlexey Samsonov : FunctionPass(ID), 81f045df1b8b7f80e17e34c2b5639082a1d0e289aeAlexey Samsonov TD(0), 82f045df1b8b7f80e17e34c2b5639082a1d0e289aeAlexey Samsonov BlacklistFile(BlacklistFile.empty() ? ClBlacklistFile 83f045df1b8b7f80e17e34c2b5639082a1d0e289aeAlexey Samsonov : BlacklistFile) { } 84e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany const char *getPassName() const; 8560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany bool runOnFunction(Function &F); 8660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany bool doInitialization(Module &M); 8760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany static char ID; // Pass identification, replacement for typeid. 8860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 8960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany private: 908b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany void initializeCallbacks(Module &M); 91e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany bool instrumentLoadOrStore(Instruction *I); 92e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany bool instrumentAtomic(Instruction *I); 93f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany bool instrumentMemIntrinsic(Instruction *I); 9437cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryany void chooseInstructionsToInstrument(SmallVectorImpl<Instruction*> &Local, 9537cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryany SmallVectorImpl<Instruction*> &All); 96cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany bool addrPointsToConstantData(Value *Addr); 97e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany int getMemoryAccessFuncIndex(Value *Addr); 982076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany 993574eca1b02600bac4e625297f4ecf745f4c4f32Micah Villmow DataLayout *TD; 100f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany Type *IntptrTy; 101f045df1b8b7f80e17e34c2b5639082a1d0e289aeAlexey Samsonov SmallString<64> BlacklistFile; 102405515d55f470d04ef75f653b7f1994329c9066bPeter Collingbourne OwningPtr<SpecialCaseList> BL; 103e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany IntegerType *OrdTy; 10460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany // Callbacks to run-time library are computed in doInitialization. 105e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Function *TsanFuncEntry; 106e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Function *TsanFuncExit; 10760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany // Accesses sizes are powers of two: 1, 2, 4, 8, 16. 1083eccaa6625a8032bee6b84706cb46ed8eb915acfKostya Serebryany static const size_t kNumberOfAccessSizes = 5; 109e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Function *TsanRead[kNumberOfAccessSizes]; 110e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Function *TsanWrite[kNumberOfAccessSizes]; 111e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Function *TsanAtomicLoad[kNumberOfAccessSizes]; 112e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Function *TsanAtomicStore[kNumberOfAccessSizes]; 1139f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov Function *TsanAtomicRMW[AtomicRMWInst::LAST_BINOP + 1][kNumberOfAccessSizes]; 1149f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov Function *TsanAtomicCAS[kNumberOfAccessSizes]; 1159f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov Function *TsanAtomicThreadFence; 1169f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov Function *TsanAtomicSignalFence; 117e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Function *TsanVptrUpdate; 118ab78ac1a2d55cd81e42f4688fbaa7bd689e6291fDmitry Vyukov Function *TsanVptrLoad; 119f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany Function *MemmoveFn, *MemcpyFn, *MemsetFn; 12060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany}; 12160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany} // namespace 12260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 12360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanychar ThreadSanitizer::ID = 0; 12460ebb1947faed42e493179e569c5db0c01d38a2aKostya SerebryanyINITIALIZE_PASS(ThreadSanitizer, "tsan", 12560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany "ThreadSanitizer: detects data races.", 12660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany false, false) 12760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 128e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryanyconst char *ThreadSanitizer::getPassName() const { 129e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return "ThreadSanitizer"; 130e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany} 131e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany 132f045df1b8b7f80e17e34c2b5639082a1d0e289aeAlexey SamsonovFunctionPass *llvm::createThreadSanitizerPass(StringRef BlacklistFile) { 133f045df1b8b7f80e17e34c2b5639082a1d0e289aeAlexey Samsonov return new ThreadSanitizer(BlacklistFile); 13460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany} 13560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 136e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryanystatic Function *checkInterfaceFunction(Constant *FuncOrBitcast) { 137e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany if (Function *F = dyn_cast<Function>(FuncOrBitcast)) 138e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return F; 139e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany FuncOrBitcast->dump(); 140e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany report_fatal_error("ThreadSanitizer interface function redefined"); 141e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany} 142e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany 1438b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryanyvoid ThreadSanitizer::initializeCallbacks(Module &M) { 14460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany IRBuilder<> IRB(M.getContext()); 14560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany // Initialize the callbacks. 146e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany TsanFuncEntry = checkInterfaceFunction(M.getOrInsertFunction( 147e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany "__tsan_func_entry", IRB.getVoidTy(), IRB.getInt8PtrTy(), NULL)); 148e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany TsanFuncExit = checkInterfaceFunction(M.getOrInsertFunction( 149e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany "__tsan_func_exit", IRB.getVoidTy(), NULL)); 150e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany OrdTy = IRB.getInt32Ty(); 1513eccaa6625a8032bee6b84706cb46ed8eb915acfKostya Serebryany for (size_t i = 0; i < kNumberOfAccessSizes; ++i) { 152e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany const size_t ByteSize = 1 << i; 153e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany const size_t BitSize = ByteSize * 8; 154e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany SmallString<32> ReadName("__tsan_read" + itostr(ByteSize)); 155e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany TsanRead[i] = checkInterfaceFunction(M.getOrInsertFunction( 156e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany ReadName, IRB.getVoidTy(), IRB.getInt8PtrTy(), NULL)); 157e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany 158e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany SmallString<32> WriteName("__tsan_write" + itostr(ByteSize)); 159e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany TsanWrite[i] = checkInterfaceFunction(M.getOrInsertFunction( 160e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany WriteName, IRB.getVoidTy(), IRB.getInt8PtrTy(), NULL)); 161e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany 162e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Type *Ty = Type::getIntNTy(M.getContext(), BitSize); 163e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Type *PtrTy = Ty->getPointerTo(); 164e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany SmallString<32> AtomicLoadName("__tsan_atomic" + itostr(BitSize) + 165e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany "_load"); 166e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany TsanAtomicLoad[i] = checkInterfaceFunction(M.getOrInsertFunction( 167e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany AtomicLoadName, Ty, PtrTy, OrdTy, NULL)); 168e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany 169e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany SmallString<32> AtomicStoreName("__tsan_atomic" + itostr(BitSize) + 170e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany "_store"); 171e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany TsanAtomicStore[i] = checkInterfaceFunction(M.getOrInsertFunction( 172e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany AtomicStoreName, IRB.getVoidTy(), PtrTy, Ty, OrdTy, 173e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany NULL)); 1749f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov 1759f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov for (int op = AtomicRMWInst::FIRST_BINOP; 1769f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov op <= AtomicRMWInst::LAST_BINOP; ++op) { 1779f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov TsanAtomicRMW[op][i] = NULL; 1789f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov const char *NamePart = NULL; 1799f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov if (op == AtomicRMWInst::Xchg) 1809f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov NamePart = "_exchange"; 1819f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov else if (op == AtomicRMWInst::Add) 1829f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov NamePart = "_fetch_add"; 1839f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov else if (op == AtomicRMWInst::Sub) 1849f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov NamePart = "_fetch_sub"; 1859f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov else if (op == AtomicRMWInst::And) 1869f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov NamePart = "_fetch_and"; 1879f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov else if (op == AtomicRMWInst::Or) 1889f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov NamePart = "_fetch_or"; 1899f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov else if (op == AtomicRMWInst::Xor) 1909f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov NamePart = "_fetch_xor"; 191b10675ef14bea530551172547e2111bf707a408eDmitry Vyukov else if (op == AtomicRMWInst::Nand) 192b10675ef14bea530551172547e2111bf707a408eDmitry Vyukov NamePart = "_fetch_nand"; 1939f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov else 1949f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov continue; 1959f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov SmallString<32> RMWName("__tsan_atomic" + itostr(BitSize) + NamePart); 1969f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov TsanAtomicRMW[op][i] = checkInterfaceFunction(M.getOrInsertFunction( 1979f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov RMWName, Ty, PtrTy, Ty, OrdTy, NULL)); 1989f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov } 1999f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov 2009f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov SmallString<32> AtomicCASName("__tsan_atomic" + itostr(BitSize) + 2019f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov "_compare_exchange_val"); 2029f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov TsanAtomicCAS[i] = checkInterfaceFunction(M.getOrInsertFunction( 2036702e53926c2ce04ab4c049930d24a9c42996941Dmitry Vyukov AtomicCASName, Ty, PtrTy, Ty, Ty, OrdTy, OrdTy, NULL)); 20460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany } 205e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany TsanVptrUpdate = checkInterfaceFunction(M.getOrInsertFunction( 206e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany "__tsan_vptr_update", IRB.getVoidTy(), IRB.getInt8PtrTy(), 207e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany IRB.getInt8PtrTy(), NULL)); 208ab78ac1a2d55cd81e42f4688fbaa7bd689e6291fDmitry Vyukov TsanVptrLoad = checkInterfaceFunction(M.getOrInsertFunction( 209ab78ac1a2d55cd81e42f4688fbaa7bd689e6291fDmitry Vyukov "__tsan_vptr_read", IRB.getVoidTy(), IRB.getInt8PtrTy(), NULL)); 2109f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov TsanAtomicThreadFence = checkInterfaceFunction(M.getOrInsertFunction( 2119f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov "__tsan_atomic_thread_fence", IRB.getVoidTy(), OrdTy, NULL)); 2129f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov TsanAtomicSignalFence = checkInterfaceFunction(M.getOrInsertFunction( 2139f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov "__tsan_atomic_signal_fence", IRB.getVoidTy(), OrdTy, NULL)); 214f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany 215f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany MemmoveFn = checkInterfaceFunction(M.getOrInsertFunction( 216f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany "memmove", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), 217f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany IRB.getInt8PtrTy(), IntptrTy, NULL)); 218f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany MemcpyFn = checkInterfaceFunction(M.getOrInsertFunction( 219f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany "memcpy", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), 220f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany IntptrTy, NULL)); 221f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany MemsetFn = checkInterfaceFunction(M.getOrInsertFunction( 222f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany "memset", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IRB.getInt32Ty(), 223f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany IntptrTy, NULL)); 2248b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany} 2258b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany 2268b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryanybool ThreadSanitizer::doInitialization(Module &M) { 2278b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany TD = getAnalysisIfAvailable<DataLayout>(); 2288b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany if (!TD) 2298b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany return false; 230405515d55f470d04ef75f653b7f1994329c9066bPeter Collingbourne BL.reset(new SpecialCaseList(BlacklistFile)); 2318b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany 2328b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany // Always insert a call to __tsan_init into the module's CTORs. 2338b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany IRBuilder<> IRB(M.getContext()); 234f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany IntptrTy = IRB.getIntPtrTy(TD); 2358b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany Value *TsanInit = M.getOrInsertFunction("__tsan_init", 2368b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany IRB.getVoidTy(), NULL); 2378b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany appendToGlobalCtors(M, cast<Function>(TsanInit), 0); 2388b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany 23960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany return true; 24060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany} 24160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 242cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryanystatic bool isVtableAccess(Instruction *I) { 243cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany if (MDNode *Tag = I->getMetadata(LLVMContext::MD_tbaa)) { 244cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany if (Tag->getNumOperands() < 1) return false; 245cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany if (MDString *Tag1 = dyn_cast<MDString>(Tag->getOperand(0))) { 246cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany if (Tag1->getString() == "vtable pointer") return true; 247cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany } 248cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany } 249cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany return false; 250cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany} 251cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany 252cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryanybool ThreadSanitizer::addrPointsToConstantData(Value *Addr) { 253cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany // If this is a GEP, just analyze its pointer operand. 254cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Addr)) 255cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany Addr = GEP->getPointerOperand(); 256cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany 257cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Addr)) { 258cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany if (GV->isConstant()) { 259cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany // Reads from constant globals can not race with any writes. 2602d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany NumOmittedReadsFromConstantGlobals++; 261cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany return true; 262cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany } 2631dfe9b52646ce56446ecd3548dbc81068369ef3fAlexey Samsonov } else if (LoadInst *L = dyn_cast<LoadInst>(Addr)) { 264cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany if (isVtableAccess(L)) { 265cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany // Reads from a vtable pointer can not race with any writes. 2662d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany NumOmittedReadsFromVtable++; 267cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany return true; 268cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany } 269cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany } 270cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany return false; 271cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany} 272cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany 2732076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// Instrumenting some of the accesses may be proven redundant. 2742076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// Currently handled: 2752076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// - read-before-write (within same BB, no calls between) 2762076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// 2772076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// We do not handle some of the patterns that should not survive 2782076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// after the classic compiler optimizations. 2792076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// E.g. two reads from the same temp should be eliminated by CSE, 2802076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// two writes should be eliminated by DSE, etc. 2812076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// 2822076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// 'Local' is a vector of insns within the same BB (no calls between). 2832076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// 'All' is a vector of insns that will be instrumented. 28437cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryanyvoid ThreadSanitizer::chooseInstructionsToInstrument( 2852076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany SmallVectorImpl<Instruction*> &Local, 2862076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany SmallVectorImpl<Instruction*> &All) { 2872076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany SmallSet<Value*, 8> WriteTargets; 2882076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany // Iterate from the end. 2892076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany for (SmallVectorImpl<Instruction*>::reverse_iterator It = Local.rbegin(), 2902076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany E = Local.rend(); It != E; ++It) { 2912076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany Instruction *I = *It; 2922076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany if (StoreInst *Store = dyn_cast<StoreInst>(I)) { 2932076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany WriteTargets.insert(Store->getPointerOperand()); 2942076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany } else { 2952076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany LoadInst *Load = cast<LoadInst>(I); 296cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany Value *Addr = Load->getPointerOperand(); 297cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany if (WriteTargets.count(Addr)) { 2982076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany // We will write to this temp, so no reason to analyze the read. 2992d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany NumOmittedReadsBeforeWrite++; 3002076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany continue; 3012076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany } 302cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany if (addrPointsToConstantData(Addr)) { 303cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany // Addr points to some constant data -- it can not race with any writes. 304cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany continue; 305cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany } 3062076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany } 3072076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany All.push_back(I); 3082076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany } 3092076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany Local.clear(); 3102076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany} 3112076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany 312e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryanystatic bool isAtomic(Instruction *I) { 313e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany if (LoadInst *LI = dyn_cast<LoadInst>(I)) 314e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return LI->isAtomic() && LI->getSynchScope() == CrossThread; 31537cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryany if (StoreInst *SI = dyn_cast<StoreInst>(I)) 316e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return SI->isAtomic() && SI->getSynchScope() == CrossThread; 31737cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryany if (isa<AtomicRMWInst>(I)) 318e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return true; 31937cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryany if (isa<AtomicCmpXchgInst>(I)) 320e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return true; 3219f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov if (isa<FenceInst>(I)) 3229f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov return true; 323e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return false; 324e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany} 325e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany 32660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanybool ThreadSanitizer::runOnFunction(Function &F) { 32760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany if (!TD) return false; 3286e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryany if (BL->isIn(F)) return false; 3298b390ffbfdd52a23a45a21de99aa1c31f3ce623fKostya Serebryany initializeCallbacks(*F.getParent()); 33060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany SmallVector<Instruction*, 8> RetVec; 3312076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany SmallVector<Instruction*, 8> AllLoadsAndStores; 3322076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany SmallVector<Instruction*, 8> LocalLoadsAndStores; 333e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany SmallVector<Instruction*, 8> AtomicAccesses; 334f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany SmallVector<Instruction*, 8> MemIntrinCalls; 33560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany bool Res = false; 33660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany bool HasCalls = false; 33760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 33860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany // Traverse all instructions, collect loads/stores/returns, check for calls. 33960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany for (Function::iterator FI = F.begin(), FE = F.end(); 34060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany FI != FE; ++FI) { 34160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany BasicBlock &BB = *FI; 34260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany for (BasicBlock::iterator BI = BB.begin(), BE = BB.end(); 34360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany BI != BE; ++BI) { 344e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany if (isAtomic(BI)) 345e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany AtomicAccesses.push_back(BI); 346e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany else if (isa<LoadInst>(BI) || isa<StoreInst>(BI)) 3472076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany LocalLoadsAndStores.push_back(BI); 34860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany else if (isa<ReturnInst>(BI)) 34960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany RetVec.push_back(BI); 3502076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany else if (isa<CallInst>(BI) || isa<InvokeInst>(BI)) { 351f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany if (isa<MemIntrinsic>(BI)) 352f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany MemIntrinCalls.push_back(BI); 35360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany HasCalls = true; 35437cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryany chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores); 3552076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany } 35660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany } 35737cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryany chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores); 35860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany } 35960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 36060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany // We have collected all loads and stores. 36160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany // FIXME: many of these accesses do not need to be checked for races 36260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany // (e.g. variables that do not escape, etc). 36360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 36460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany // Instrument memory accesses. 36541d876cea3b5212e5ee8bc25c13c6eab54a4a93cKostya Serebryany if (ClInstrumentMemoryAccesses) 36641d876cea3b5212e5ee8bc25c13c6eab54a4a93cKostya Serebryany for (size_t i = 0, n = AllLoadsAndStores.size(); i < n; ++i) { 36741d876cea3b5212e5ee8bc25c13c6eab54a4a93cKostya Serebryany Res |= instrumentLoadOrStore(AllLoadsAndStores[i]); 36841d876cea3b5212e5ee8bc25c13c6eab54a4a93cKostya Serebryany } 36960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 370e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany // Instrument atomic memory accesses. 37141d876cea3b5212e5ee8bc25c13c6eab54a4a93cKostya Serebryany if (ClInstrumentAtomics) 37241d876cea3b5212e5ee8bc25c13c6eab54a4a93cKostya Serebryany for (size_t i = 0, n = AtomicAccesses.size(); i < n; ++i) { 37341d876cea3b5212e5ee8bc25c13c6eab54a4a93cKostya Serebryany Res |= instrumentAtomic(AtomicAccesses[i]); 37441d876cea3b5212e5ee8bc25c13c6eab54a4a93cKostya Serebryany } 375e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany 376f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany if (ClInstrumentMemIntrinsics) 377f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany for (size_t i = 0, n = MemIntrinCalls.size(); i < n; ++i) { 378f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany Res |= instrumentMemIntrinsic(MemIntrinCalls[i]); 379f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany } 380f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany 38160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany // Instrument function entry/exit points if there were instrumented accesses. 38241d876cea3b5212e5ee8bc25c13c6eab54a4a93cKostya Serebryany if ((Res || HasCalls) && ClInstrumentFuncEntryExit) { 38360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany IRBuilder<> IRB(F.getEntryBlock().getFirstNonPHI()); 38460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany Value *ReturnAddress = IRB.CreateCall( 38560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany Intrinsic::getDeclaration(F.getParent(), Intrinsic::returnaddress), 38660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany IRB.getInt32(0)); 38760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany IRB.CreateCall(TsanFuncEntry, ReturnAddress); 38860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany for (size_t i = 0, n = RetVec.size(); i < n; ++i) { 38960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany IRBuilder<> IRBRet(RetVec[i]); 39060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany IRBRet.CreateCall(TsanFuncExit); 39160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany } 39252eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany Res = true; 39360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany } 39460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany return Res; 39560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany} 39660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 39760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanybool ThreadSanitizer::instrumentLoadOrStore(Instruction *I) { 39860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany IRBuilder<> IRB(I); 39960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany bool IsWrite = isa<StoreInst>(*I); 40060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany Value *Addr = IsWrite 40160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany ? cast<StoreInst>(I)->getPointerOperand() 40260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany : cast<LoadInst>(I)->getPointerOperand(); 403e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany int Idx = getMemoryAccessFuncIndex(Addr); 404e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany if (Idx < 0) 40560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany return false; 40652eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany if (IsWrite && isVtableAccess(I)) { 4074a002ab9c3eb19d33641cf37945a2ed153ee6d77Kostya Serebryany DEBUG(dbgs() << " VPTR : " << *I << "\n"); 40852eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany Value *StoredValue = cast<StoreInst>(I)->getValueOperand(); 4094a002ab9c3eb19d33641cf37945a2ed153ee6d77Kostya Serebryany // StoredValue does not necessary have a pointer type. 4104a002ab9c3eb19d33641cf37945a2ed153ee6d77Kostya Serebryany if (isa<IntegerType>(StoredValue->getType())) 4114a002ab9c3eb19d33641cf37945a2ed153ee6d77Kostya Serebryany StoredValue = IRB.CreateIntToPtr(StoredValue, IRB.getInt8PtrTy()); 4124a002ab9c3eb19d33641cf37945a2ed153ee6d77Kostya Serebryany // Call TsanVptrUpdate. 41352eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany IRB.CreateCall2(TsanVptrUpdate, 41452eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()), 41552eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany IRB.CreatePointerCast(StoredValue, IRB.getInt8PtrTy())); 4162d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany NumInstrumentedVtableWrites++; 41752eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany return true; 41852eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany } 419ab78ac1a2d55cd81e42f4688fbaa7bd689e6291fDmitry Vyukov if (!IsWrite && isVtableAccess(I)) { 420ab78ac1a2d55cd81e42f4688fbaa7bd689e6291fDmitry Vyukov IRB.CreateCall(TsanVptrLoad, 421ab78ac1a2d55cd81e42f4688fbaa7bd689e6291fDmitry Vyukov IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy())); 422ab78ac1a2d55cd81e42f4688fbaa7bd689e6291fDmitry Vyukov NumInstrumentedVtableReads++; 423ab78ac1a2d55cd81e42f4688fbaa7bd689e6291fDmitry Vyukov return true; 424ab78ac1a2d55cd81e42f4688fbaa7bd689e6291fDmitry Vyukov } 42560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany Value *OnAccessFunc = IsWrite ? TsanWrite[Idx] : TsanRead[Idx]; 42660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany IRB.CreateCall(OnAccessFunc, IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy())); 4272d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany if (IsWrite) NumInstrumentedWrites++; 4282d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany else NumInstrumentedReads++; 42960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany return true; 43060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany} 431e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany 432e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryanystatic ConstantInt *createOrdering(IRBuilder<> *IRB, AtomicOrdering ord) { 433e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany uint32_t v = 0; 434e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany switch (ord) { 435e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany case NotAtomic: assert(false); 436e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany case Unordered: // Fall-through. 437c2e9ca15fbb7ce2bc0bc79e44862d74cdd2802b9Dmitry Vyukov case Monotonic: v = 0; break; 4389a33f9f9804126661e87edfe491288b81f5c51e6Dmitry Vyukov // case Consume: v = 1; break; // Not specified yet. 439c2e9ca15fbb7ce2bc0bc79e44862d74cdd2802b9Dmitry Vyukov case Acquire: v = 2; break; 440c2e9ca15fbb7ce2bc0bc79e44862d74cdd2802b9Dmitry Vyukov case Release: v = 3; break; 441c2e9ca15fbb7ce2bc0bc79e44862d74cdd2802b9Dmitry Vyukov case AcquireRelease: v = 4; break; 442c2e9ca15fbb7ce2bc0bc79e44862d74cdd2802b9Dmitry Vyukov case SequentiallyConsistent: v = 5; break; 443e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany } 444c2e9ca15fbb7ce2bc0bc79e44862d74cdd2802b9Dmitry Vyukov return IRB->getInt32(v); 445e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany} 446e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany 4476702e53926c2ce04ab4c049930d24a9c42996941Dmitry Vyukovstatic ConstantInt *createFailOrdering(IRBuilder<> *IRB, AtomicOrdering ord) { 4486702e53926c2ce04ab4c049930d24a9c42996941Dmitry Vyukov uint32_t v = 0; 4496702e53926c2ce04ab4c049930d24a9c42996941Dmitry Vyukov switch (ord) { 4506702e53926c2ce04ab4c049930d24a9c42996941Dmitry Vyukov case NotAtomic: assert(false); 4516702e53926c2ce04ab4c049930d24a9c42996941Dmitry Vyukov case Unordered: // Fall-through. 4526702e53926c2ce04ab4c049930d24a9c42996941Dmitry Vyukov case Monotonic: v = 0; break; 4539a33f9f9804126661e87edfe491288b81f5c51e6Dmitry Vyukov // case Consume: v = 1; break; // Not specified yet. 4546702e53926c2ce04ab4c049930d24a9c42996941Dmitry Vyukov case Acquire: v = 2; break; 4556702e53926c2ce04ab4c049930d24a9c42996941Dmitry Vyukov case Release: v = 0; break; 4566702e53926c2ce04ab4c049930d24a9c42996941Dmitry Vyukov case AcquireRelease: v = 2; break; 4576702e53926c2ce04ab4c049930d24a9c42996941Dmitry Vyukov case SequentiallyConsistent: v = 5; break; 4586702e53926c2ce04ab4c049930d24a9c42996941Dmitry Vyukov } 4596702e53926c2ce04ab4c049930d24a9c42996941Dmitry Vyukov return IRB->getInt32(v); 4606702e53926c2ce04ab4c049930d24a9c42996941Dmitry Vyukov} 4616702e53926c2ce04ab4c049930d24a9c42996941Dmitry Vyukov 462f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany// If a memset intrinsic gets inlined by the code gen, we will miss races on it. 463f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany// So, we either need to ensure the intrinsic is not inlined, or instrument it. 464f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany// We do not instrument memset/memmove/memcpy intrinsics (too complicated), 465f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany// instead we simply replace them with regular function calls, which are then 466f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany// intercepted by the run-time. 467f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany// Since tsan is running after everyone else, the calls should not be 468f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany// replaced back with intrinsics. If that becomes wrong at some point, 469f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany// we will need to call e.g. __tsan_memset to avoid the intrinsics. 470f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryanybool ThreadSanitizer::instrumentMemIntrinsic(Instruction *I) { 471f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany IRBuilder<> IRB(I); 472f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany if (MemSetInst *M = dyn_cast<MemSetInst>(I)) { 473f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany IRB.CreateCall3(MemsetFn, 474f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany IRB.CreatePointerCast(M->getArgOperand(0), IRB.getInt8PtrTy()), 475f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany IRB.CreateIntCast(M->getArgOperand(1), IRB.getInt32Ty(), false), 476f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany IRB.CreateIntCast(M->getArgOperand(2), IntptrTy, false)); 477f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany I->eraseFromParent(); 478f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany } else if (MemTransferInst *M = dyn_cast<MemTransferInst>(I)) { 479f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany IRB.CreateCall3(isa<MemCpyInst>(M) ? MemcpyFn : MemmoveFn, 480f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany IRB.CreatePointerCast(M->getArgOperand(0), IRB.getInt8PtrTy()), 481f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany IRB.CreatePointerCast(M->getArgOperand(1), IRB.getInt8PtrTy()), 482f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany IRB.CreateIntCast(M->getArgOperand(2), IntptrTy, false)); 483f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany I->eraseFromParent(); 484f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany } 485f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany return false; 486f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany} 487f464481db0c3b5404004b510921ca454803fd1d0Kostya Serebryany 4886702e53926c2ce04ab4c049930d24a9c42996941Dmitry Vyukov// Both llvm and ThreadSanitizer atomic operations are based on C++11/C1x 4896702e53926c2ce04ab4c049930d24a9c42996941Dmitry Vyukov// standards. For background see C++11 standard. A slightly older, publically 4906702e53926c2ce04ab4c049930d24a9c42996941Dmitry Vyukov// available draft of the standard (not entirely up-to-date, but close enough 4916702e53926c2ce04ab4c049930d24a9c42996941Dmitry Vyukov// for casual browsing) is available here: 49270af909f67565753cbd61886da2b0b7e191d32bfMatt Beaumont-Gay// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf 4936702e53926c2ce04ab4c049930d24a9c42996941Dmitry Vyukov// The following page contains more background information: 4946702e53926c2ce04ab4c049930d24a9c42996941Dmitry Vyukov// http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/ 4956702e53926c2ce04ab4c049930d24a9c42996941Dmitry Vyukov 496e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryanybool ThreadSanitizer::instrumentAtomic(Instruction *I) { 497e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany IRBuilder<> IRB(I); 498e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany if (LoadInst *LI = dyn_cast<LoadInst>(I)) { 499e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Value *Addr = LI->getPointerOperand(); 500e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany int Idx = getMemoryAccessFuncIndex(Addr); 501e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany if (Idx < 0) 502e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return false; 503e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany const size_t ByteSize = 1 << Idx; 504e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany const size_t BitSize = ByteSize * 8; 505e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize); 506b8bce928f4ffdf50eff69334f3e25b27848536b6Micah Villmow Type *PtrTy = Ty->getPointerTo(); 507e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Value *Args[] = {IRB.CreatePointerCast(Addr, PtrTy), 508e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany createOrdering(&IRB, LI->getOrdering())}; 509e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany CallInst *C = CallInst::Create(TsanAtomicLoad[Idx], 510e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany ArrayRef<Value*>(Args)); 511e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany ReplaceInstWithInst(I, C); 512e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany 513e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) { 514e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Value *Addr = SI->getPointerOperand(); 515e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany int Idx = getMemoryAccessFuncIndex(Addr); 516e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany if (Idx < 0) 517e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return false; 518e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany const size_t ByteSize = 1 << Idx; 519e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany const size_t BitSize = ByteSize * 8; 520e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize); 521b8bce928f4ffdf50eff69334f3e25b27848536b6Micah Villmow Type *PtrTy = Ty->getPointerTo(); 522e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Value *Args[] = {IRB.CreatePointerCast(Addr, PtrTy), 523e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany IRB.CreateIntCast(SI->getValueOperand(), Ty, false), 524e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany createOrdering(&IRB, SI->getOrdering())}; 525e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany CallInst *C = CallInst::Create(TsanAtomicStore[Idx], 526e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany ArrayRef<Value*>(Args)); 527e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany ReplaceInstWithInst(I, C); 5289f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov } else if (AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(I)) { 5299f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov Value *Addr = RMWI->getPointerOperand(); 5309f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov int Idx = getMemoryAccessFuncIndex(Addr); 5319f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov if (Idx < 0) 5329f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov return false; 5339f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov Function *F = TsanAtomicRMW[RMWI->getOperation()][Idx]; 5349f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov if (F == NULL) 5359f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov return false; 5369f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov const size_t ByteSize = 1 << Idx; 5379f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov const size_t BitSize = ByteSize * 8; 5389f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize); 5399f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov Type *PtrTy = Ty->getPointerTo(); 5409f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov Value *Args[] = {IRB.CreatePointerCast(Addr, PtrTy), 5419f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov IRB.CreateIntCast(RMWI->getValOperand(), Ty, false), 5429f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov createOrdering(&IRB, RMWI->getOrdering())}; 5439f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov CallInst *C = CallInst::Create(F, ArrayRef<Value*>(Args)); 5449f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov ReplaceInstWithInst(I, C); 5459f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov } else if (AtomicCmpXchgInst *CASI = dyn_cast<AtomicCmpXchgInst>(I)) { 5469f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov Value *Addr = CASI->getPointerOperand(); 5479f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov int Idx = getMemoryAccessFuncIndex(Addr); 5489f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov if (Idx < 0) 5499f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov return false; 5509f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov const size_t ByteSize = 1 << Idx; 5519f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov const size_t BitSize = ByteSize * 8; 5529f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize); 5539f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov Type *PtrTy = Ty->getPointerTo(); 5549f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov Value *Args[] = {IRB.CreatePointerCast(Addr, PtrTy), 5559f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov IRB.CreateIntCast(CASI->getCompareOperand(), Ty, false), 5569f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov IRB.CreateIntCast(CASI->getNewValOperand(), Ty, false), 5576702e53926c2ce04ab4c049930d24a9c42996941Dmitry Vyukov createOrdering(&IRB, CASI->getOrdering()), 5586702e53926c2ce04ab4c049930d24a9c42996941Dmitry Vyukov createFailOrdering(&IRB, CASI->getOrdering())}; 5599f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov CallInst *C = CallInst::Create(TsanAtomicCAS[Idx], ArrayRef<Value*>(Args)); 5609f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov ReplaceInstWithInst(I, C); 5619f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov } else if (FenceInst *FI = dyn_cast<FenceInst>(I)) { 5629f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov Value *Args[] = {createOrdering(&IRB, FI->getOrdering())}; 5639f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov Function *F = FI->getSynchScope() == SingleThread ? 5649f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov TsanAtomicSignalFence : TsanAtomicThreadFence; 5659f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov CallInst *C = CallInst::Create(F, ArrayRef<Value*>(Args)); 5669f8a90b3ce0e248e3b68b056d4c840295facbc02Dmitry Vyukov ReplaceInstWithInst(I, C); 567e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany } 568e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return true; 569e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany} 570e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany 571e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryanyint ThreadSanitizer::getMemoryAccessFuncIndex(Value *Addr) { 572e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Type *OrigPtrTy = Addr->getType(); 573e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Type *OrigTy = cast<PointerType>(OrigPtrTy)->getElementType(); 574e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany assert(OrigTy->isSized()); 575e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany uint32_t TypeSize = TD->getTypeStoreSizeInBits(OrigTy); 576e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany if (TypeSize != 8 && TypeSize != 16 && 577e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany TypeSize != 32 && TypeSize != 64 && TypeSize != 128) { 578e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany NumAccessesWithBadSize++; 579e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany // Ignore all unusual sizes. 580e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return -1; 581e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany } 582c6af2432c802d241c8fffbe0371c023e6c58844eMichael J. Spencer size_t Idx = countTrailingZeros(TypeSize / 8); 583e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany assert(Idx < kNumberOfAccessSizes); 584e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return Idx; 585e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany} 586