10b57cec5SDimitry Andric //===-- ThreadSanitizer.cpp - race detector -------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file is a part of ThreadSanitizer, a race detector. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric // The tool is under development, for the details about previous versions see 120b57cec5SDimitry Andric // http://code.google.com/p/data-race-test 130b57cec5SDimitry Andric // 140b57cec5SDimitry Andric // The instrumentation phase is quite simple: 150b57cec5SDimitry Andric // - Insert calls to run-time library before every memory access. 160b57cec5SDimitry Andric // - Optimizations may apply to avoid instrumenting some of the accesses. 170b57cec5SDimitry Andric // - Insert calls at function entry/exit. 180b57cec5SDimitry Andric // The rest is handled by the run-time library. 190b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" 22e8d8bef9SDimitry Andric #include "llvm/ADT/DenseMap.h" 230b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 240b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 250b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 260b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h" 270b57cec5SDimitry Andric #include "llvm/Analysis/CaptureTracking.h" 280b57cec5SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h" 290b57cec5SDimitry Andric #include "llvm/Analysis/ValueTracking.h" 300b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 310b57cec5SDimitry Andric #include "llvm/IR/Function.h" 320b57cec5SDimitry Andric #include "llvm/IR/IRBuilder.h" 33fe6060f1SDimitry Andric #include "llvm/IR/Instructions.h" 340b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h" 350b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h" 360b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h" 370b57cec5SDimitry Andric #include "llvm/IR/Metadata.h" 380b57cec5SDimitry Andric #include "llvm/IR/Module.h" 390b57cec5SDimitry Andric #include "llvm/IR/Type.h" 400b57cec5SDimitry Andric #include "llvm/ProfileData/InstrProf.h" 410b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 420b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 430b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 440b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 450b57cec5SDimitry Andric #include "llvm/Transforms/Instrumentation.h" 460b57cec5SDimitry Andric #include "llvm/Transforms/Utils/EscapeEnumerator.h" 47480093f4SDimitry Andric #include "llvm/Transforms/Utils/Local.h" 480b57cec5SDimitry Andric #include "llvm/Transforms/Utils/ModuleUtils.h" 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric using namespace llvm; 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric #define DEBUG_TYPE "tsan" 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric static cl::opt<bool> ClInstrumentMemoryAccesses( 550b57cec5SDimitry Andric "tsan-instrument-memory-accesses", cl::init(true), 560b57cec5SDimitry Andric cl::desc("Instrument memory accesses"), cl::Hidden); 57e8d8bef9SDimitry Andric static cl::opt<bool> 58e8d8bef9SDimitry Andric ClInstrumentFuncEntryExit("tsan-instrument-func-entry-exit", cl::init(true), 59e8d8bef9SDimitry Andric cl::desc("Instrument function entry and exit"), 60e8d8bef9SDimitry Andric cl::Hidden); 610b57cec5SDimitry Andric static cl::opt<bool> ClHandleCxxExceptions( 620b57cec5SDimitry Andric "tsan-handle-cxx-exceptions", cl::init(true), 630b57cec5SDimitry Andric cl::desc("Handle C++ exceptions (insert cleanup blocks for unwinding)"), 640b57cec5SDimitry Andric cl::Hidden); 65e8d8bef9SDimitry Andric static cl::opt<bool> ClInstrumentAtomics("tsan-instrument-atomics", 66e8d8bef9SDimitry Andric cl::init(true), 67e8d8bef9SDimitry Andric cl::desc("Instrument atomics"), 68e8d8bef9SDimitry Andric cl::Hidden); 690b57cec5SDimitry Andric static cl::opt<bool> ClInstrumentMemIntrinsics( 700b57cec5SDimitry Andric "tsan-instrument-memintrinsics", cl::init(true), 710b57cec5SDimitry Andric cl::desc("Instrument memintrinsics (memset/memcpy/memmove)"), cl::Hidden); 725ffd83dbSDimitry Andric static cl::opt<bool> ClDistinguishVolatile( 735ffd83dbSDimitry Andric "tsan-distinguish-volatile", cl::init(false), 745ffd83dbSDimitry Andric cl::desc("Emit special instrumentation for accesses to volatiles"), 755ffd83dbSDimitry Andric cl::Hidden); 765ffd83dbSDimitry Andric static cl::opt<bool> ClInstrumentReadBeforeWrite( 775ffd83dbSDimitry Andric "tsan-instrument-read-before-write", cl::init(false), 785ffd83dbSDimitry Andric cl::desc("Do not eliminate read instrumentation for read-before-writes"), 795ffd83dbSDimitry Andric cl::Hidden); 80e8d8bef9SDimitry Andric static cl::opt<bool> ClCompoundReadBeforeWrite( 81e8d8bef9SDimitry Andric "tsan-compound-read-before-write", cl::init(false), 82e8d8bef9SDimitry Andric cl::desc("Emit special compound instrumentation for reads-before-writes"), 83e8d8bef9SDimitry Andric cl::Hidden); 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric STATISTIC(NumInstrumentedReads, "Number of instrumented reads"); 860b57cec5SDimitry Andric STATISTIC(NumInstrumentedWrites, "Number of instrumented writes"); 870b57cec5SDimitry Andric STATISTIC(NumOmittedReadsBeforeWrite, 880b57cec5SDimitry Andric "Number of reads ignored due to following writes"); 890b57cec5SDimitry Andric STATISTIC(NumAccessesWithBadSize, "Number of accesses with bad size"); 900b57cec5SDimitry Andric STATISTIC(NumInstrumentedVtableWrites, "Number of vtable ptr writes"); 910b57cec5SDimitry Andric STATISTIC(NumInstrumentedVtableReads, "Number of vtable ptr reads"); 920b57cec5SDimitry Andric STATISTIC(NumOmittedReadsFromConstantGlobals, 930b57cec5SDimitry Andric "Number of reads from constant globals"); 940b57cec5SDimitry Andric STATISTIC(NumOmittedReadsFromVtable, "Number of vtable reads"); 950b57cec5SDimitry Andric STATISTIC(NumOmittedNonCaptured, "Number of accesses ignored due to capturing"); 960b57cec5SDimitry Andric 97e8d8bef9SDimitry Andric const char kTsanModuleCtorName[] = "tsan.module_ctor"; 98e8d8bef9SDimitry Andric const char kTsanInitName[] = "__tsan_init"; 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric namespace { 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric /// ThreadSanitizer: instrument the code in module to find races. 1030b57cec5SDimitry Andric /// 1040b57cec5SDimitry Andric /// Instantiating ThreadSanitizer inserts the tsan runtime library API function 1050b57cec5SDimitry Andric /// declarations into the module if they don't exist already. Instantiating 1060b57cec5SDimitry Andric /// ensures the __tsan_init function is in the list of global constructors for 1070b57cec5SDimitry Andric /// the module. 1080b57cec5SDimitry Andric struct ThreadSanitizer { 109e8d8bef9SDimitry Andric ThreadSanitizer() { 1104824e7fdSDimitry Andric // Check options and warn user. 111e8d8bef9SDimitry Andric if (ClInstrumentReadBeforeWrite && ClCompoundReadBeforeWrite) { 112e8d8bef9SDimitry Andric errs() 113e8d8bef9SDimitry Andric << "warning: Option -tsan-compound-read-before-write has no effect " 114e8d8bef9SDimitry Andric "when -tsan-instrument-read-before-write is set.\n"; 115e8d8bef9SDimitry Andric } 116e8d8bef9SDimitry Andric } 117e8d8bef9SDimitry Andric 1180b57cec5SDimitry Andric bool sanitizeFunction(Function &F, const TargetLibraryInfo &TLI); 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric private: 121e8d8bef9SDimitry Andric // Internal Instruction wrapper that contains more information about the 122e8d8bef9SDimitry Andric // Instruction from prior analysis. 123e8d8bef9SDimitry Andric struct InstructionInfo { 124e8d8bef9SDimitry Andric // Instrumentation emitted for this instruction is for a compounded set of 125e8d8bef9SDimitry Andric // read and write operations in the same basic block. 126e8d8bef9SDimitry Andric static constexpr unsigned kCompoundRW = (1U << 0); 127e8d8bef9SDimitry Andric 128e8d8bef9SDimitry Andric explicit InstructionInfo(Instruction *Inst) : Inst(Inst) {} 129e8d8bef9SDimitry Andric 130e8d8bef9SDimitry Andric Instruction *Inst; 131e8d8bef9SDimitry Andric unsigned Flags = 0; 132e8d8bef9SDimitry Andric }; 133e8d8bef9SDimitry Andric 134bdd1243dSDimitry Andric void initialize(Module &M, const TargetLibraryInfo &TLI); 135e8d8bef9SDimitry Andric bool instrumentLoadOrStore(const InstructionInfo &II, const DataLayout &DL); 1360b57cec5SDimitry Andric bool instrumentAtomic(Instruction *I, const DataLayout &DL); 1370b57cec5SDimitry Andric bool instrumentMemIntrinsic(Instruction *I); 1380b57cec5SDimitry Andric void chooseInstructionsToInstrument(SmallVectorImpl<Instruction *> &Local, 139e8d8bef9SDimitry Andric SmallVectorImpl<InstructionInfo> &All, 1400b57cec5SDimitry Andric const DataLayout &DL); 1410b57cec5SDimitry Andric bool addrPointsToConstantData(Value *Addr); 142fe6060f1SDimitry Andric int getMemoryAccessFuncIndex(Type *OrigTy, Value *Addr, const DataLayout &DL); 1430b57cec5SDimitry Andric void InsertRuntimeIgnores(Function &F); 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric Type *IntptrTy; 1460b57cec5SDimitry Andric FunctionCallee TsanFuncEntry; 1470b57cec5SDimitry Andric FunctionCallee TsanFuncExit; 1480b57cec5SDimitry Andric FunctionCallee TsanIgnoreBegin; 1490b57cec5SDimitry Andric FunctionCallee TsanIgnoreEnd; 1500b57cec5SDimitry Andric // Accesses sizes are powers of two: 1, 2, 4, 8, 16. 1510b57cec5SDimitry Andric static const size_t kNumberOfAccessSizes = 5; 1520b57cec5SDimitry Andric FunctionCallee TsanRead[kNumberOfAccessSizes]; 1530b57cec5SDimitry Andric FunctionCallee TsanWrite[kNumberOfAccessSizes]; 1540b57cec5SDimitry Andric FunctionCallee TsanUnalignedRead[kNumberOfAccessSizes]; 1550b57cec5SDimitry Andric FunctionCallee TsanUnalignedWrite[kNumberOfAccessSizes]; 1565ffd83dbSDimitry Andric FunctionCallee TsanVolatileRead[kNumberOfAccessSizes]; 1575ffd83dbSDimitry Andric FunctionCallee TsanVolatileWrite[kNumberOfAccessSizes]; 1585ffd83dbSDimitry Andric FunctionCallee TsanUnalignedVolatileRead[kNumberOfAccessSizes]; 1595ffd83dbSDimitry Andric FunctionCallee TsanUnalignedVolatileWrite[kNumberOfAccessSizes]; 160e8d8bef9SDimitry Andric FunctionCallee TsanCompoundRW[kNumberOfAccessSizes]; 161e8d8bef9SDimitry Andric FunctionCallee TsanUnalignedCompoundRW[kNumberOfAccessSizes]; 1620b57cec5SDimitry Andric FunctionCallee TsanAtomicLoad[kNumberOfAccessSizes]; 1630b57cec5SDimitry Andric FunctionCallee TsanAtomicStore[kNumberOfAccessSizes]; 1640b57cec5SDimitry Andric FunctionCallee TsanAtomicRMW[AtomicRMWInst::LAST_BINOP + 1] 1650b57cec5SDimitry Andric [kNumberOfAccessSizes]; 1660b57cec5SDimitry Andric FunctionCallee TsanAtomicCAS[kNumberOfAccessSizes]; 1670b57cec5SDimitry Andric FunctionCallee TsanAtomicThreadFence; 1680b57cec5SDimitry Andric FunctionCallee TsanAtomicSignalFence; 1690b57cec5SDimitry Andric FunctionCallee TsanVptrUpdate; 1700b57cec5SDimitry Andric FunctionCallee TsanVptrLoad; 1710b57cec5SDimitry Andric FunctionCallee MemmoveFn, MemcpyFn, MemsetFn; 1720b57cec5SDimitry Andric }; 1730b57cec5SDimitry Andric 1748bcb0991SDimitry Andric void insertModuleCtor(Module &M) { 1758bcb0991SDimitry Andric getOrCreateSanitizerCtorAndInitFunctions( 1768bcb0991SDimitry Andric M, kTsanModuleCtorName, kTsanInitName, /*InitArgTypes=*/{}, 1778bcb0991SDimitry Andric /*InitArgs=*/{}, 1788bcb0991SDimitry Andric // This callback is invoked when the functions are created the first 1798bcb0991SDimitry Andric // time. Hook them into the global ctors list in that case: 1808bcb0991SDimitry Andric [&](Function *Ctor, FunctionCallee) { appendToGlobalCtors(M, Ctor, 0); }); 1818bcb0991SDimitry Andric } 1820b57cec5SDimitry Andric } // namespace 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric PreservedAnalyses ThreadSanitizerPass::run(Function &F, 1850b57cec5SDimitry Andric FunctionAnalysisManager &FAM) { 1868bcb0991SDimitry Andric ThreadSanitizer TSan; 1870b57cec5SDimitry Andric if (TSan.sanitizeFunction(F, FAM.getResult<TargetLibraryAnalysis>(F))) 1880b57cec5SDimitry Andric return PreservedAnalyses::none(); 1890b57cec5SDimitry Andric return PreservedAnalyses::all(); 1900b57cec5SDimitry Andric } 1910b57cec5SDimitry Andric 192349cc55cSDimitry Andric PreservedAnalyses ModuleThreadSanitizerPass::run(Module &M, 1938bcb0991SDimitry Andric ModuleAnalysisManager &MAM) { 1948bcb0991SDimitry Andric insertModuleCtor(M); 1958bcb0991SDimitry Andric return PreservedAnalyses::none(); 1968bcb0991SDimitry Andric } 197bdd1243dSDimitry Andric void ThreadSanitizer::initialize(Module &M, const TargetLibraryInfo &TLI) { 1988bcb0991SDimitry Andric const DataLayout &DL = M.getDataLayout(); 199bdd1243dSDimitry Andric LLVMContext &Ctx = M.getContext(); 200bdd1243dSDimitry Andric IntptrTy = DL.getIntPtrType(Ctx); 2018bcb0991SDimitry Andric 202bdd1243dSDimitry Andric IRBuilder<> IRB(Ctx); 2030b57cec5SDimitry Andric AttributeList Attr; 204bdd1243dSDimitry Andric Attr = Attr.addFnAttribute(Ctx, Attribute::NoUnwind); 2050b57cec5SDimitry Andric // Initialize the callbacks. 2060b57cec5SDimitry Andric TsanFuncEntry = M.getOrInsertFunction("__tsan_func_entry", Attr, 2075f757f3fSDimitry Andric IRB.getVoidTy(), IRB.getPtrTy()); 2080b57cec5SDimitry Andric TsanFuncExit = 2090b57cec5SDimitry Andric M.getOrInsertFunction("__tsan_func_exit", Attr, IRB.getVoidTy()); 2100b57cec5SDimitry Andric TsanIgnoreBegin = M.getOrInsertFunction("__tsan_ignore_thread_begin", Attr, 2110b57cec5SDimitry Andric IRB.getVoidTy()); 2120b57cec5SDimitry Andric TsanIgnoreEnd = 2130b57cec5SDimitry Andric M.getOrInsertFunction("__tsan_ignore_thread_end", Attr, IRB.getVoidTy()); 2148bcb0991SDimitry Andric IntegerType *OrdTy = IRB.getInt32Ty(); 2150b57cec5SDimitry Andric for (size_t i = 0; i < kNumberOfAccessSizes; ++i) { 2160b57cec5SDimitry Andric const unsigned ByteSize = 1U << i; 2170b57cec5SDimitry Andric const unsigned BitSize = ByteSize * 8; 2180b57cec5SDimitry Andric std::string ByteSizeStr = utostr(ByteSize); 2190b57cec5SDimitry Andric std::string BitSizeStr = utostr(BitSize); 2200b57cec5SDimitry Andric SmallString<32> ReadName("__tsan_read" + ByteSizeStr); 2210b57cec5SDimitry Andric TsanRead[i] = M.getOrInsertFunction(ReadName, Attr, IRB.getVoidTy(), 2225f757f3fSDimitry Andric IRB.getPtrTy()); 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric SmallString<32> WriteName("__tsan_write" + ByteSizeStr); 2250b57cec5SDimitry Andric TsanWrite[i] = M.getOrInsertFunction(WriteName, Attr, IRB.getVoidTy(), 2265f757f3fSDimitry Andric IRB.getPtrTy()); 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric SmallString<64> UnalignedReadName("__tsan_unaligned_read" + ByteSizeStr); 2290b57cec5SDimitry Andric TsanUnalignedRead[i] = M.getOrInsertFunction( 2305f757f3fSDimitry Andric UnalignedReadName, Attr, IRB.getVoidTy(), IRB.getPtrTy()); 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric SmallString<64> UnalignedWriteName("__tsan_unaligned_write" + ByteSizeStr); 2330b57cec5SDimitry Andric TsanUnalignedWrite[i] = M.getOrInsertFunction( 2345f757f3fSDimitry Andric UnalignedWriteName, Attr, IRB.getVoidTy(), IRB.getPtrTy()); 2350b57cec5SDimitry Andric 2365ffd83dbSDimitry Andric SmallString<64> VolatileReadName("__tsan_volatile_read" + ByteSizeStr); 2375ffd83dbSDimitry Andric TsanVolatileRead[i] = M.getOrInsertFunction( 2385f757f3fSDimitry Andric VolatileReadName, Attr, IRB.getVoidTy(), IRB.getPtrTy()); 2395ffd83dbSDimitry Andric 2405ffd83dbSDimitry Andric SmallString<64> VolatileWriteName("__tsan_volatile_write" + ByteSizeStr); 2415ffd83dbSDimitry Andric TsanVolatileWrite[i] = M.getOrInsertFunction( 2425f757f3fSDimitry Andric VolatileWriteName, Attr, IRB.getVoidTy(), IRB.getPtrTy()); 2435ffd83dbSDimitry Andric 2445ffd83dbSDimitry Andric SmallString<64> UnalignedVolatileReadName("__tsan_unaligned_volatile_read" + 2455ffd83dbSDimitry Andric ByteSizeStr); 2465ffd83dbSDimitry Andric TsanUnalignedVolatileRead[i] = M.getOrInsertFunction( 2475f757f3fSDimitry Andric UnalignedVolatileReadName, Attr, IRB.getVoidTy(), IRB.getPtrTy()); 2485ffd83dbSDimitry Andric 2495ffd83dbSDimitry Andric SmallString<64> UnalignedVolatileWriteName( 2505ffd83dbSDimitry Andric "__tsan_unaligned_volatile_write" + ByteSizeStr); 2515ffd83dbSDimitry Andric TsanUnalignedVolatileWrite[i] = M.getOrInsertFunction( 2525f757f3fSDimitry Andric UnalignedVolatileWriteName, Attr, IRB.getVoidTy(), IRB.getPtrTy()); 2535ffd83dbSDimitry Andric 254e8d8bef9SDimitry Andric SmallString<64> CompoundRWName("__tsan_read_write" + ByteSizeStr); 255e8d8bef9SDimitry Andric TsanCompoundRW[i] = M.getOrInsertFunction( 2565f757f3fSDimitry Andric CompoundRWName, Attr, IRB.getVoidTy(), IRB.getPtrTy()); 257e8d8bef9SDimitry Andric 258e8d8bef9SDimitry Andric SmallString<64> UnalignedCompoundRWName("__tsan_unaligned_read_write" + 259e8d8bef9SDimitry Andric ByteSizeStr); 260e8d8bef9SDimitry Andric TsanUnalignedCompoundRW[i] = M.getOrInsertFunction( 2615f757f3fSDimitry Andric UnalignedCompoundRWName, Attr, IRB.getVoidTy(), IRB.getPtrTy()); 262e8d8bef9SDimitry Andric 263bdd1243dSDimitry Andric Type *Ty = Type::getIntNTy(Ctx, BitSize); 2645f757f3fSDimitry Andric Type *PtrTy = PointerType::get(Ctx, 0); 2650b57cec5SDimitry Andric SmallString<32> AtomicLoadName("__tsan_atomic" + BitSizeStr + "_load"); 2660b57cec5SDimitry Andric TsanAtomicLoad[i] = 267bdd1243dSDimitry Andric M.getOrInsertFunction(AtomicLoadName, 268bdd1243dSDimitry Andric TLI.getAttrList(&Ctx, {1}, /*Signed=*/true, 269bdd1243dSDimitry Andric /*Ret=*/BitSize <= 32, Attr), 270bdd1243dSDimitry Andric Ty, PtrTy, OrdTy); 2710b57cec5SDimitry Andric 272bdd1243dSDimitry Andric // Args of type Ty need extension only when BitSize is 32 or less. 273bdd1243dSDimitry Andric using Idxs = std::vector<unsigned>; 274bdd1243dSDimitry Andric Idxs Idxs2Or12 ((BitSize <= 32) ? Idxs({1, 2}) : Idxs({2})); 275bdd1243dSDimitry Andric Idxs Idxs34Or1234((BitSize <= 32) ? Idxs({1, 2, 3, 4}) : Idxs({3, 4})); 2760b57cec5SDimitry Andric SmallString<32> AtomicStoreName("__tsan_atomic" + BitSizeStr + "_store"); 2770b57cec5SDimitry Andric TsanAtomicStore[i] = M.getOrInsertFunction( 278bdd1243dSDimitry Andric AtomicStoreName, 279bdd1243dSDimitry Andric TLI.getAttrList(&Ctx, Idxs2Or12, /*Signed=*/true, /*Ret=*/false, Attr), 280bdd1243dSDimitry Andric IRB.getVoidTy(), PtrTy, Ty, OrdTy); 2810b57cec5SDimitry Andric 2825ffd83dbSDimitry Andric for (unsigned Op = AtomicRMWInst::FIRST_BINOP; 2835ffd83dbSDimitry Andric Op <= AtomicRMWInst::LAST_BINOP; ++Op) { 2845ffd83dbSDimitry Andric TsanAtomicRMW[Op][i] = nullptr; 2850b57cec5SDimitry Andric const char *NamePart = nullptr; 2865ffd83dbSDimitry Andric if (Op == AtomicRMWInst::Xchg) 2870b57cec5SDimitry Andric NamePart = "_exchange"; 2885ffd83dbSDimitry Andric else if (Op == AtomicRMWInst::Add) 2890b57cec5SDimitry Andric NamePart = "_fetch_add"; 2905ffd83dbSDimitry Andric else if (Op == AtomicRMWInst::Sub) 2910b57cec5SDimitry Andric NamePart = "_fetch_sub"; 2925ffd83dbSDimitry Andric else if (Op == AtomicRMWInst::And) 2930b57cec5SDimitry Andric NamePart = "_fetch_and"; 2945ffd83dbSDimitry Andric else if (Op == AtomicRMWInst::Or) 2950b57cec5SDimitry Andric NamePart = "_fetch_or"; 2965ffd83dbSDimitry Andric else if (Op == AtomicRMWInst::Xor) 2970b57cec5SDimitry Andric NamePart = "_fetch_xor"; 2985ffd83dbSDimitry Andric else if (Op == AtomicRMWInst::Nand) 2990b57cec5SDimitry Andric NamePart = "_fetch_nand"; 3000b57cec5SDimitry Andric else 3010b57cec5SDimitry Andric continue; 3020b57cec5SDimitry Andric SmallString<32> RMWName("__tsan_atomic" + itostr(BitSize) + NamePart); 303bdd1243dSDimitry Andric TsanAtomicRMW[Op][i] = M.getOrInsertFunction( 304bdd1243dSDimitry Andric RMWName, 305bdd1243dSDimitry Andric TLI.getAttrList(&Ctx, Idxs2Or12, /*Signed=*/true, 306bdd1243dSDimitry Andric /*Ret=*/BitSize <= 32, Attr), 307bdd1243dSDimitry Andric Ty, PtrTy, Ty, OrdTy); 3080b57cec5SDimitry Andric } 3090b57cec5SDimitry Andric 3100b57cec5SDimitry Andric SmallString<32> AtomicCASName("__tsan_atomic" + BitSizeStr + 3110b57cec5SDimitry Andric "_compare_exchange_val"); 312bdd1243dSDimitry Andric TsanAtomicCAS[i] = M.getOrInsertFunction( 313bdd1243dSDimitry Andric AtomicCASName, 314bdd1243dSDimitry Andric TLI.getAttrList(&Ctx, Idxs34Or1234, /*Signed=*/true, 315bdd1243dSDimitry Andric /*Ret=*/BitSize <= 32, Attr), 316bdd1243dSDimitry Andric Ty, PtrTy, Ty, Ty, OrdTy, OrdTy); 317fe6060f1SDimitry Andric } 3180b57cec5SDimitry Andric TsanVptrUpdate = 3190b57cec5SDimitry Andric M.getOrInsertFunction("__tsan_vptr_update", Attr, IRB.getVoidTy(), 3205f757f3fSDimitry Andric IRB.getPtrTy(), IRB.getPtrTy()); 3210b57cec5SDimitry Andric TsanVptrLoad = M.getOrInsertFunction("__tsan_vptr_read", Attr, 3225f757f3fSDimitry Andric IRB.getVoidTy(), IRB.getPtrTy()); 323bdd1243dSDimitry Andric TsanAtomicThreadFence = M.getOrInsertFunction( 324bdd1243dSDimitry Andric "__tsan_atomic_thread_fence", 325bdd1243dSDimitry Andric TLI.getAttrList(&Ctx, {0}, /*Signed=*/true, /*Ret=*/false, Attr), 326bdd1243dSDimitry Andric IRB.getVoidTy(), OrdTy); 327bdd1243dSDimitry Andric 328bdd1243dSDimitry Andric TsanAtomicSignalFence = M.getOrInsertFunction( 329bdd1243dSDimitry Andric "__tsan_atomic_signal_fence", 330bdd1243dSDimitry Andric TLI.getAttrList(&Ctx, {0}, /*Signed=*/true, /*Ret=*/false, Attr), 331bdd1243dSDimitry Andric IRB.getVoidTy(), OrdTy); 3320b57cec5SDimitry Andric 3330b57cec5SDimitry Andric MemmoveFn = 3345f757f3fSDimitry Andric M.getOrInsertFunction("__tsan_memmove", Attr, IRB.getPtrTy(), 3355f757f3fSDimitry Andric IRB.getPtrTy(), IRB.getPtrTy(), IntptrTy); 3360b57cec5SDimitry Andric MemcpyFn = 3375f757f3fSDimitry Andric M.getOrInsertFunction("__tsan_memcpy", Attr, IRB.getPtrTy(), 3385f757f3fSDimitry Andric IRB.getPtrTy(), IRB.getPtrTy(), IntptrTy); 339bdd1243dSDimitry Andric MemsetFn = M.getOrInsertFunction( 340bdd1243dSDimitry Andric "__tsan_memset", 341bdd1243dSDimitry Andric TLI.getAttrList(&Ctx, {1}, /*Signed=*/true, /*Ret=*/false, Attr), 3425f757f3fSDimitry Andric IRB.getPtrTy(), IRB.getPtrTy(), IRB.getInt32Ty(), IntptrTy); 3430b57cec5SDimitry Andric } 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric static bool isVtableAccess(Instruction *I) { 3460b57cec5SDimitry Andric if (MDNode *Tag = I->getMetadata(LLVMContext::MD_tbaa)) 3470b57cec5SDimitry Andric return Tag->isTBAAVtableAccess(); 3480b57cec5SDimitry Andric return false; 3490b57cec5SDimitry Andric } 3500b57cec5SDimitry Andric 3510b57cec5SDimitry Andric // Do not instrument known races/"benign races" that come from compiler 3520b57cec5SDimitry Andric // instrumentatin. The user has no way of suppressing them. 3530b57cec5SDimitry Andric static bool shouldInstrumentReadWriteFromAddress(const Module *M, Value *Addr) { 3540b57cec5SDimitry Andric // Peel off GEPs and BitCasts. 3550b57cec5SDimitry Andric Addr = Addr->stripInBoundsOffsets(); 3560b57cec5SDimitry Andric 3570b57cec5SDimitry Andric if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Addr)) { 3580b57cec5SDimitry Andric if (GV->hasSection()) { 3590b57cec5SDimitry Andric StringRef SectionName = GV->getSection(); 3600b57cec5SDimitry Andric // Check if the global is in the PGO counters section. 3610b57cec5SDimitry Andric auto OF = Triple(M->getTargetTriple()).getObjectFormat(); 3625f757f3fSDimitry Andric if (SectionName.ends_with( 3630b57cec5SDimitry Andric getInstrProfSectionName(IPSK_cnts, OF, /*AddSegmentInfo=*/false))) 3640b57cec5SDimitry Andric return false; 3650b57cec5SDimitry Andric } 3660b57cec5SDimitry Andric } 3670b57cec5SDimitry Andric 368bdd1243dSDimitry Andric // Do not instrument accesses from different address spaces; we cannot deal 3690b57cec5SDimitry Andric // with them. 3700b57cec5SDimitry Andric if (Addr) { 3710b57cec5SDimitry Andric Type *PtrTy = cast<PointerType>(Addr->getType()->getScalarType()); 3720b57cec5SDimitry Andric if (PtrTy->getPointerAddressSpace() != 0) 3730b57cec5SDimitry Andric return false; 3740b57cec5SDimitry Andric } 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andric return true; 3770b57cec5SDimitry Andric } 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric bool ThreadSanitizer::addrPointsToConstantData(Value *Addr) { 3800b57cec5SDimitry Andric // If this is a GEP, just analyze its pointer operand. 3810b57cec5SDimitry Andric if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Addr)) 3820b57cec5SDimitry Andric Addr = GEP->getPointerOperand(); 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andric if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Addr)) { 3850b57cec5SDimitry Andric if (GV->isConstant()) { 3860b57cec5SDimitry Andric // Reads from constant globals can not race with any writes. 3870b57cec5SDimitry Andric NumOmittedReadsFromConstantGlobals++; 3880b57cec5SDimitry Andric return true; 3890b57cec5SDimitry Andric } 3900b57cec5SDimitry Andric } else if (LoadInst *L = dyn_cast<LoadInst>(Addr)) { 3910b57cec5SDimitry Andric if (isVtableAccess(L)) { 3920b57cec5SDimitry Andric // Reads from a vtable pointer can not race with any writes. 3930b57cec5SDimitry Andric NumOmittedReadsFromVtable++; 3940b57cec5SDimitry Andric return true; 3950b57cec5SDimitry Andric } 3960b57cec5SDimitry Andric } 3970b57cec5SDimitry Andric return false; 3980b57cec5SDimitry Andric } 3990b57cec5SDimitry Andric 4000b57cec5SDimitry Andric // Instrumenting some of the accesses may be proven redundant. 4010b57cec5SDimitry Andric // Currently handled: 4020b57cec5SDimitry Andric // - read-before-write (within same BB, no calls between) 4030b57cec5SDimitry Andric // - not captured variables 4040b57cec5SDimitry Andric // 4050b57cec5SDimitry Andric // We do not handle some of the patterns that should not survive 4060b57cec5SDimitry Andric // after the classic compiler optimizations. 4070b57cec5SDimitry Andric // E.g. two reads from the same temp should be eliminated by CSE, 4080b57cec5SDimitry Andric // two writes should be eliminated by DSE, etc. 4090b57cec5SDimitry Andric // 4100b57cec5SDimitry Andric // 'Local' is a vector of insns within the same BB (no calls between). 4110b57cec5SDimitry Andric // 'All' is a vector of insns that will be instrumented. 4120b57cec5SDimitry Andric void ThreadSanitizer::chooseInstructionsToInstrument( 413e8d8bef9SDimitry Andric SmallVectorImpl<Instruction *> &Local, 414e8d8bef9SDimitry Andric SmallVectorImpl<InstructionInfo> &All, const DataLayout &DL) { 415e8d8bef9SDimitry Andric DenseMap<Value *, size_t> WriteTargets; // Map of addresses to index in All 4160b57cec5SDimitry Andric // Iterate from the end. 4170b57cec5SDimitry Andric for (Instruction *I : reverse(Local)) { 418e8d8bef9SDimitry Andric const bool IsWrite = isa<StoreInst>(*I); 419e8d8bef9SDimitry Andric Value *Addr = IsWrite ? cast<StoreInst>(I)->getPointerOperand() 420e8d8bef9SDimitry Andric : cast<LoadInst>(I)->getPointerOperand(); 421e8d8bef9SDimitry Andric 4220b57cec5SDimitry Andric if (!shouldInstrumentReadWriteFromAddress(I->getModule(), Addr)) 4230b57cec5SDimitry Andric continue; 424e8d8bef9SDimitry Andric 425e8d8bef9SDimitry Andric if (!IsWrite) { 426e8d8bef9SDimitry Andric const auto WriteEntry = WriteTargets.find(Addr); 427e8d8bef9SDimitry Andric if (!ClInstrumentReadBeforeWrite && WriteEntry != WriteTargets.end()) { 428e8d8bef9SDimitry Andric auto &WI = All[WriteEntry->second]; 429e8d8bef9SDimitry Andric // If we distinguish volatile accesses and if either the read or write 430e8d8bef9SDimitry Andric // is volatile, do not omit any instrumentation. 431e8d8bef9SDimitry Andric const bool AnyVolatile = 432e8d8bef9SDimitry Andric ClDistinguishVolatile && (cast<LoadInst>(I)->isVolatile() || 433e8d8bef9SDimitry Andric cast<StoreInst>(WI.Inst)->isVolatile()); 434e8d8bef9SDimitry Andric if (!AnyVolatile) { 4350b57cec5SDimitry Andric // We will write to this temp, so no reason to analyze the read. 436e8d8bef9SDimitry Andric // Mark the write instruction as compound. 437e8d8bef9SDimitry Andric WI.Flags |= InstructionInfo::kCompoundRW; 4380b57cec5SDimitry Andric NumOmittedReadsBeforeWrite++; 4390b57cec5SDimitry Andric continue; 4400b57cec5SDimitry Andric } 441e8d8bef9SDimitry Andric } 442e8d8bef9SDimitry Andric 4430b57cec5SDimitry Andric if (addrPointsToConstantData(Addr)) { 4440b57cec5SDimitry Andric // Addr points to some constant data -- it can not race with any writes. 4450b57cec5SDimitry Andric continue; 4460b57cec5SDimitry Andric } 4470b57cec5SDimitry Andric } 448e8d8bef9SDimitry Andric 449e8d8bef9SDimitry Andric if (isa<AllocaInst>(getUnderlyingObject(Addr)) && 4500b57cec5SDimitry Andric !PointerMayBeCaptured(Addr, true, true)) { 4510b57cec5SDimitry Andric // The variable is addressable but not captured, so it cannot be 4520b57cec5SDimitry Andric // referenced from a different thread and participate in a data race 4530b57cec5SDimitry Andric // (see llvm/Analysis/CaptureTracking.h for details). 4540b57cec5SDimitry Andric NumOmittedNonCaptured++; 4550b57cec5SDimitry Andric continue; 4560b57cec5SDimitry Andric } 457e8d8bef9SDimitry Andric 458e8d8bef9SDimitry Andric // Instrument this instruction. 459e8d8bef9SDimitry Andric All.emplace_back(I); 460e8d8bef9SDimitry Andric if (IsWrite) { 461e8d8bef9SDimitry Andric // For read-before-write and compound instrumentation we only need one 462e8d8bef9SDimitry Andric // write target, and we can override any previous entry if it exists. 463e8d8bef9SDimitry Andric WriteTargets[Addr] = All.size() - 1; 464e8d8bef9SDimitry Andric } 4650b57cec5SDimitry Andric } 4660b57cec5SDimitry Andric Local.clear(); 4670b57cec5SDimitry Andric } 4680b57cec5SDimitry Andric 46981ad6265SDimitry Andric static bool isTsanAtomic(const Instruction *I) { 4700b57cec5SDimitry Andric // TODO: Ask TTI whether synchronization scope is between threads. 47181ad6265SDimitry Andric auto SSID = getAtomicSyncScopeID(I); 47281ad6265SDimitry Andric if (!SSID) 4730b57cec5SDimitry Andric return false; 47481ad6265SDimitry Andric if (isa<LoadInst>(I) || isa<StoreInst>(I)) 475bdd1243dSDimitry Andric return *SSID != SyncScope::SingleThread; 47681ad6265SDimitry Andric return true; 4770b57cec5SDimitry Andric } 4780b57cec5SDimitry Andric 4790b57cec5SDimitry Andric void ThreadSanitizer::InsertRuntimeIgnores(Function &F) { 48081ad6265SDimitry Andric InstrumentationIRBuilder IRB(F.getEntryBlock().getFirstNonPHI()); 4810b57cec5SDimitry Andric IRB.CreateCall(TsanIgnoreBegin); 4820b57cec5SDimitry Andric EscapeEnumerator EE(F, "tsan_ignore_cleanup", ClHandleCxxExceptions); 4830b57cec5SDimitry Andric while (IRBuilder<> *AtExit = EE.Next()) { 48481ad6265SDimitry Andric InstrumentationIRBuilder::ensureDebugInfo(*AtExit, F); 4850b57cec5SDimitry Andric AtExit->CreateCall(TsanIgnoreEnd); 4860b57cec5SDimitry Andric } 4870b57cec5SDimitry Andric } 4880b57cec5SDimitry Andric 4890b57cec5SDimitry Andric bool ThreadSanitizer::sanitizeFunction(Function &F, 4900b57cec5SDimitry Andric const TargetLibraryInfo &TLI) { 4910b57cec5SDimitry Andric // This is required to prevent instrumenting call to __tsan_init from within 4920b57cec5SDimitry Andric // the module constructor. 4938bcb0991SDimitry Andric if (F.getName() == kTsanModuleCtorName) 4940b57cec5SDimitry Andric return false; 4955ffd83dbSDimitry Andric // Naked functions can not have prologue/epilogue 4965ffd83dbSDimitry Andric // (__tsan_func_entry/__tsan_func_exit) generated, so don't instrument them at 4975ffd83dbSDimitry Andric // all. 4985ffd83dbSDimitry Andric if (F.hasFnAttribute(Attribute::Naked)) 4995ffd83dbSDimitry Andric return false; 500349cc55cSDimitry Andric 501349cc55cSDimitry Andric // __attribute__(disable_sanitizer_instrumentation) prevents all kinds of 502349cc55cSDimitry Andric // instrumentation. 503349cc55cSDimitry Andric if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) 504349cc55cSDimitry Andric return false; 505349cc55cSDimitry Andric 506bdd1243dSDimitry Andric initialize(*F.getParent(), TLI); 507e8d8bef9SDimitry Andric SmallVector<InstructionInfo, 8> AllLoadsAndStores; 5080b57cec5SDimitry Andric SmallVector<Instruction*, 8> LocalLoadsAndStores; 5090b57cec5SDimitry Andric SmallVector<Instruction*, 8> AtomicAccesses; 5100b57cec5SDimitry Andric SmallVector<Instruction*, 8> MemIntrinCalls; 5110b57cec5SDimitry Andric bool Res = false; 5120b57cec5SDimitry Andric bool HasCalls = false; 5130b57cec5SDimitry Andric bool SanitizeFunction = F.hasFnAttribute(Attribute::SanitizeThread); 514*0fca6ea1SDimitry Andric const DataLayout &DL = F.getDataLayout(); 5150b57cec5SDimitry Andric 5160b57cec5SDimitry Andric // Traverse all instructions, collect loads/stores/returns, check for calls. 5170b57cec5SDimitry Andric for (auto &BB : F) { 5180b57cec5SDimitry Andric for (auto &Inst : BB) { 5195f757f3fSDimitry Andric // Skip instructions inserted by another instrumentation. 5205f757f3fSDimitry Andric if (Inst.hasMetadata(LLVMContext::MD_nosanitize)) 5215f757f3fSDimitry Andric continue; 52281ad6265SDimitry Andric if (isTsanAtomic(&Inst)) 5230b57cec5SDimitry Andric AtomicAccesses.push_back(&Inst); 5240b57cec5SDimitry Andric else if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst)) 5250b57cec5SDimitry Andric LocalLoadsAndStores.push_back(&Inst); 526349cc55cSDimitry Andric else if ((isa<CallInst>(Inst) && !isa<DbgInfoIntrinsic>(Inst)) || 527349cc55cSDimitry Andric isa<InvokeInst>(Inst)) { 5280b57cec5SDimitry Andric if (CallInst *CI = dyn_cast<CallInst>(&Inst)) 5290b57cec5SDimitry Andric maybeMarkSanitizerLibraryCallNoBuiltin(CI, &TLI); 5300b57cec5SDimitry Andric if (isa<MemIntrinsic>(Inst)) 5310b57cec5SDimitry Andric MemIntrinCalls.push_back(&Inst); 5320b57cec5SDimitry Andric HasCalls = true; 5330b57cec5SDimitry Andric chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores, 5340b57cec5SDimitry Andric DL); 5350b57cec5SDimitry Andric } 5360b57cec5SDimitry Andric } 5370b57cec5SDimitry Andric chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores, DL); 5380b57cec5SDimitry Andric } 5390b57cec5SDimitry Andric 5400b57cec5SDimitry Andric // We have collected all loads and stores. 5410b57cec5SDimitry Andric // FIXME: many of these accesses do not need to be checked for races 5420b57cec5SDimitry Andric // (e.g. variables that do not escape, etc). 5430b57cec5SDimitry Andric 5440b57cec5SDimitry Andric // Instrument memory accesses only if we want to report bugs in the function. 5450b57cec5SDimitry Andric if (ClInstrumentMemoryAccesses && SanitizeFunction) 546e8d8bef9SDimitry Andric for (const auto &II : AllLoadsAndStores) { 547e8d8bef9SDimitry Andric Res |= instrumentLoadOrStore(II, DL); 5480b57cec5SDimitry Andric } 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric // Instrument atomic memory accesses in any case (they can be used to 5510b57cec5SDimitry Andric // implement synchronization). 5520b57cec5SDimitry Andric if (ClInstrumentAtomics) 553bdd1243dSDimitry Andric for (auto *Inst : AtomicAccesses) { 5540b57cec5SDimitry Andric Res |= instrumentAtomic(Inst, DL); 5550b57cec5SDimitry Andric } 5560b57cec5SDimitry Andric 5570b57cec5SDimitry Andric if (ClInstrumentMemIntrinsics && SanitizeFunction) 558bdd1243dSDimitry Andric for (auto *Inst : MemIntrinCalls) { 5590b57cec5SDimitry Andric Res |= instrumentMemIntrinsic(Inst); 5600b57cec5SDimitry Andric } 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric if (F.hasFnAttribute("sanitize_thread_no_checking_at_run_time")) { 5630b57cec5SDimitry Andric assert(!F.hasFnAttribute(Attribute::SanitizeThread)); 5640b57cec5SDimitry Andric if (HasCalls) 5650b57cec5SDimitry Andric InsertRuntimeIgnores(F); 5660b57cec5SDimitry Andric } 5670b57cec5SDimitry Andric 5680b57cec5SDimitry Andric // Instrument function entry/exit points if there were instrumented accesses. 5690b57cec5SDimitry Andric if ((Res || HasCalls) && ClInstrumentFuncEntryExit) { 57081ad6265SDimitry Andric InstrumentationIRBuilder IRB(F.getEntryBlock().getFirstNonPHI()); 5710b57cec5SDimitry Andric Value *ReturnAddress = IRB.CreateCall( 5720b57cec5SDimitry Andric Intrinsic::getDeclaration(F.getParent(), Intrinsic::returnaddress), 5730b57cec5SDimitry Andric IRB.getInt32(0)); 5740b57cec5SDimitry Andric IRB.CreateCall(TsanFuncEntry, ReturnAddress); 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric EscapeEnumerator EE(F, "tsan_cleanup", ClHandleCxxExceptions); 5770b57cec5SDimitry Andric while (IRBuilder<> *AtExit = EE.Next()) { 57881ad6265SDimitry Andric InstrumentationIRBuilder::ensureDebugInfo(*AtExit, F); 5790b57cec5SDimitry Andric AtExit->CreateCall(TsanFuncExit, {}); 5800b57cec5SDimitry Andric } 5810b57cec5SDimitry Andric Res = true; 5820b57cec5SDimitry Andric } 5830b57cec5SDimitry Andric return Res; 5840b57cec5SDimitry Andric } 5850b57cec5SDimitry Andric 586e8d8bef9SDimitry Andric bool ThreadSanitizer::instrumentLoadOrStore(const InstructionInfo &II, 5870b57cec5SDimitry Andric const DataLayout &DL) { 58881ad6265SDimitry Andric InstrumentationIRBuilder IRB(II.Inst); 589e8d8bef9SDimitry Andric const bool IsWrite = isa<StoreInst>(*II.Inst); 590e8d8bef9SDimitry Andric Value *Addr = IsWrite ? cast<StoreInst>(II.Inst)->getPointerOperand() 591e8d8bef9SDimitry Andric : cast<LoadInst>(II.Inst)->getPointerOperand(); 592fe6060f1SDimitry Andric Type *OrigTy = getLoadStoreType(II.Inst); 5930b57cec5SDimitry Andric 5940b57cec5SDimitry Andric // swifterror memory addresses are mem2reg promoted by instruction selection. 5950b57cec5SDimitry Andric // As such they cannot have regular uses like an instrumentation function and 5960b57cec5SDimitry Andric // it makes no sense to track them as memory. 5970b57cec5SDimitry Andric if (Addr->isSwiftError()) 5980b57cec5SDimitry Andric return false; 5990b57cec5SDimitry Andric 600fe6060f1SDimitry Andric int Idx = getMemoryAccessFuncIndex(OrigTy, Addr, DL); 6010b57cec5SDimitry Andric if (Idx < 0) 6020b57cec5SDimitry Andric return false; 603e8d8bef9SDimitry Andric if (IsWrite && isVtableAccess(II.Inst)) { 604e8d8bef9SDimitry Andric LLVM_DEBUG(dbgs() << " VPTR : " << *II.Inst << "\n"); 605e8d8bef9SDimitry Andric Value *StoredValue = cast<StoreInst>(II.Inst)->getValueOperand(); 6060b57cec5SDimitry Andric // StoredValue may be a vector type if we are storing several vptrs at once. 6070b57cec5SDimitry Andric // In this case, just take the first element of the vector since this is 6080b57cec5SDimitry Andric // enough to find vptr races. 6090b57cec5SDimitry Andric if (isa<VectorType>(StoredValue->getType())) 6100b57cec5SDimitry Andric StoredValue = IRB.CreateExtractElement( 6110b57cec5SDimitry Andric StoredValue, ConstantInt::get(IRB.getInt32Ty(), 0)); 6120b57cec5SDimitry Andric if (StoredValue->getType()->isIntegerTy()) 6135f757f3fSDimitry Andric StoredValue = IRB.CreateIntToPtr(StoredValue, IRB.getPtrTy()); 6140b57cec5SDimitry Andric // Call TsanVptrUpdate. 6155f757f3fSDimitry Andric IRB.CreateCall(TsanVptrUpdate, {Addr, StoredValue}); 6160b57cec5SDimitry Andric NumInstrumentedVtableWrites++; 6170b57cec5SDimitry Andric return true; 6180b57cec5SDimitry Andric } 619e8d8bef9SDimitry Andric if (!IsWrite && isVtableAccess(II.Inst)) { 6205f757f3fSDimitry Andric IRB.CreateCall(TsanVptrLoad, Addr); 6210b57cec5SDimitry Andric NumInstrumentedVtableReads++; 6220b57cec5SDimitry Andric return true; 6230b57cec5SDimitry Andric } 624e8d8bef9SDimitry Andric 62581ad6265SDimitry Andric const Align Alignment = IsWrite ? cast<StoreInst>(II.Inst)->getAlign() 62681ad6265SDimitry Andric : cast<LoadInst>(II.Inst)->getAlign(); 627e8d8bef9SDimitry Andric const bool IsCompoundRW = 628e8d8bef9SDimitry Andric ClCompoundReadBeforeWrite && (II.Flags & InstructionInfo::kCompoundRW); 629e8d8bef9SDimitry Andric const bool IsVolatile = ClDistinguishVolatile && 630e8d8bef9SDimitry Andric (IsWrite ? cast<StoreInst>(II.Inst)->isVolatile() 631e8d8bef9SDimitry Andric : cast<LoadInst>(II.Inst)->isVolatile()); 632e8d8bef9SDimitry Andric assert((!IsVolatile || !IsCompoundRW) && "Compound volatile invalid!"); 633e8d8bef9SDimitry Andric 6340b57cec5SDimitry Andric const uint32_t TypeSize = DL.getTypeStoreSizeInBits(OrigTy); 6350b57cec5SDimitry Andric FunctionCallee OnAccessFunc = nullptr; 63681ad6265SDimitry Andric if (Alignment >= Align(8) || (Alignment.value() % (TypeSize / 8)) == 0) { 637e8d8bef9SDimitry Andric if (IsCompoundRW) 638e8d8bef9SDimitry Andric OnAccessFunc = TsanCompoundRW[Idx]; 639e8d8bef9SDimitry Andric else if (IsVolatile) 6405ffd83dbSDimitry Andric OnAccessFunc = IsWrite ? TsanVolatileWrite[Idx] : TsanVolatileRead[Idx]; 6415ffd83dbSDimitry Andric else 6420b57cec5SDimitry Andric OnAccessFunc = IsWrite ? TsanWrite[Idx] : TsanRead[Idx]; 6435ffd83dbSDimitry Andric } else { 644e8d8bef9SDimitry Andric if (IsCompoundRW) 645e8d8bef9SDimitry Andric OnAccessFunc = TsanUnalignedCompoundRW[Idx]; 646e8d8bef9SDimitry Andric else if (IsVolatile) 6475ffd83dbSDimitry Andric OnAccessFunc = IsWrite ? TsanUnalignedVolatileWrite[Idx] 6485ffd83dbSDimitry Andric : TsanUnalignedVolatileRead[Idx]; 6490b57cec5SDimitry Andric else 6500b57cec5SDimitry Andric OnAccessFunc = IsWrite ? TsanUnalignedWrite[Idx] : TsanUnalignedRead[Idx]; 6515ffd83dbSDimitry Andric } 6525f757f3fSDimitry Andric IRB.CreateCall(OnAccessFunc, Addr); 653e8d8bef9SDimitry Andric if (IsCompoundRW || IsWrite) 654e8d8bef9SDimitry Andric NumInstrumentedWrites++; 655e8d8bef9SDimitry Andric if (IsCompoundRW || !IsWrite) 656e8d8bef9SDimitry Andric NumInstrumentedReads++; 6570b57cec5SDimitry Andric return true; 6580b57cec5SDimitry Andric } 6590b57cec5SDimitry Andric 6600b57cec5SDimitry Andric static ConstantInt *createOrdering(IRBuilder<> *IRB, AtomicOrdering ord) { 6610b57cec5SDimitry Andric uint32_t v = 0; 6620b57cec5SDimitry Andric switch (ord) { 6630b57cec5SDimitry Andric case AtomicOrdering::NotAtomic: 6640b57cec5SDimitry Andric llvm_unreachable("unexpected atomic ordering!"); 665bdd1243dSDimitry Andric case AtomicOrdering::Unordered: [[fallthrough]]; 6660b57cec5SDimitry Andric case AtomicOrdering::Monotonic: v = 0; break; 6670b57cec5SDimitry Andric // Not specified yet: 6680b57cec5SDimitry Andric // case AtomicOrdering::Consume: v = 1; break; 6690b57cec5SDimitry Andric case AtomicOrdering::Acquire: v = 2; break; 6700b57cec5SDimitry Andric case AtomicOrdering::Release: v = 3; break; 6710b57cec5SDimitry Andric case AtomicOrdering::AcquireRelease: v = 4; break; 6720b57cec5SDimitry Andric case AtomicOrdering::SequentiallyConsistent: v = 5; break; 6730b57cec5SDimitry Andric } 6740b57cec5SDimitry Andric return IRB->getInt32(v); 6750b57cec5SDimitry Andric } 6760b57cec5SDimitry Andric 6770b57cec5SDimitry Andric // If a memset intrinsic gets inlined by the code gen, we will miss races on it. 6780b57cec5SDimitry Andric // So, we either need to ensure the intrinsic is not inlined, or instrument it. 6790b57cec5SDimitry Andric // We do not instrument memset/memmove/memcpy intrinsics (too complicated), 6800b57cec5SDimitry Andric // instead we simply replace them with regular function calls, which are then 6810b57cec5SDimitry Andric // intercepted by the run-time. 6820b57cec5SDimitry Andric // Since tsan is running after everyone else, the calls should not be 6830b57cec5SDimitry Andric // replaced back with intrinsics. If that becomes wrong at some point, 6840b57cec5SDimitry Andric // we will need to call e.g. __tsan_memset to avoid the intrinsics. 6850b57cec5SDimitry Andric bool ThreadSanitizer::instrumentMemIntrinsic(Instruction *I) { 68606c3fb27SDimitry Andric InstrumentationIRBuilder IRB(I); 6870b57cec5SDimitry Andric if (MemSetInst *M = dyn_cast<MemSetInst>(I)) { 6885f757f3fSDimitry Andric Value *Cast1 = IRB.CreateIntCast(M->getArgOperand(1), IRB.getInt32Ty(), false); 6895f757f3fSDimitry Andric Value *Cast2 = IRB.CreateIntCast(M->getArgOperand(2), IntptrTy, false); 6900b57cec5SDimitry Andric IRB.CreateCall( 6910b57cec5SDimitry Andric MemsetFn, 6925f757f3fSDimitry Andric {M->getArgOperand(0), 6935f757f3fSDimitry Andric Cast1, 6945f757f3fSDimitry Andric Cast2}); 6950b57cec5SDimitry Andric I->eraseFromParent(); 6960b57cec5SDimitry Andric } else if (MemTransferInst *M = dyn_cast<MemTransferInst>(I)) { 6970b57cec5SDimitry Andric IRB.CreateCall( 6980b57cec5SDimitry Andric isa<MemCpyInst>(M) ? MemcpyFn : MemmoveFn, 6995f757f3fSDimitry Andric {M->getArgOperand(0), 7005f757f3fSDimitry Andric M->getArgOperand(1), 7010b57cec5SDimitry Andric IRB.CreateIntCast(M->getArgOperand(2), IntptrTy, false)}); 7020b57cec5SDimitry Andric I->eraseFromParent(); 7030b57cec5SDimitry Andric } 7040b57cec5SDimitry Andric return false; 7050b57cec5SDimitry Andric } 7060b57cec5SDimitry Andric 7070b57cec5SDimitry Andric // Both llvm and ThreadSanitizer atomic operations are based on C++11/C1x 7080b57cec5SDimitry Andric // standards. For background see C++11 standard. A slightly older, publicly 7090b57cec5SDimitry Andric // available draft of the standard (not entirely up-to-date, but close enough 7100b57cec5SDimitry Andric // for casual browsing) is available here: 7110b57cec5SDimitry Andric // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf 7120b57cec5SDimitry Andric // The following page contains more background information: 7130b57cec5SDimitry Andric // http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/ 7140b57cec5SDimitry Andric 7150b57cec5SDimitry Andric bool ThreadSanitizer::instrumentAtomic(Instruction *I, const DataLayout &DL) { 71681ad6265SDimitry Andric InstrumentationIRBuilder IRB(I); 7170b57cec5SDimitry Andric if (LoadInst *LI = dyn_cast<LoadInst>(I)) { 7180b57cec5SDimitry Andric Value *Addr = LI->getPointerOperand(); 719fe6060f1SDimitry Andric Type *OrigTy = LI->getType(); 720fe6060f1SDimitry Andric int Idx = getMemoryAccessFuncIndex(OrigTy, Addr, DL); 7210b57cec5SDimitry Andric if (Idx < 0) 7220b57cec5SDimitry Andric return false; 7235f757f3fSDimitry Andric Value *Args[] = {Addr, 7240b57cec5SDimitry Andric createOrdering(&IRB, LI->getOrdering())}; 7250b57cec5SDimitry Andric Value *C = IRB.CreateCall(TsanAtomicLoad[Idx], Args); 7260b57cec5SDimitry Andric Value *Cast = IRB.CreateBitOrPointerCast(C, OrigTy); 7270b57cec5SDimitry Andric I->replaceAllUsesWith(Cast); 7280b57cec5SDimitry Andric } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) { 7290b57cec5SDimitry Andric Value *Addr = SI->getPointerOperand(); 730fe6060f1SDimitry Andric int Idx = 731fe6060f1SDimitry Andric getMemoryAccessFuncIndex(SI->getValueOperand()->getType(), Addr, DL); 7320b57cec5SDimitry Andric if (Idx < 0) 7330b57cec5SDimitry Andric return false; 7340b57cec5SDimitry Andric const unsigned ByteSize = 1U << Idx; 7350b57cec5SDimitry Andric const unsigned BitSize = ByteSize * 8; 7360b57cec5SDimitry Andric Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize); 7375f757f3fSDimitry Andric Value *Args[] = {Addr, 7380b57cec5SDimitry Andric IRB.CreateBitOrPointerCast(SI->getValueOperand(), Ty), 7390b57cec5SDimitry Andric createOrdering(&IRB, SI->getOrdering())}; 740*0fca6ea1SDimitry Andric IRB.CreateCall(TsanAtomicStore[Idx], Args); 741*0fca6ea1SDimitry Andric SI->eraseFromParent(); 7420b57cec5SDimitry Andric } else if (AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(I)) { 7430b57cec5SDimitry Andric Value *Addr = RMWI->getPointerOperand(); 744fe6060f1SDimitry Andric int Idx = 745fe6060f1SDimitry Andric getMemoryAccessFuncIndex(RMWI->getValOperand()->getType(), Addr, DL); 7460b57cec5SDimitry Andric if (Idx < 0) 7470b57cec5SDimitry Andric return false; 7480b57cec5SDimitry Andric FunctionCallee F = TsanAtomicRMW[RMWI->getOperation()][Idx]; 7490b57cec5SDimitry Andric if (!F) 7500b57cec5SDimitry Andric return false; 7510b57cec5SDimitry Andric const unsigned ByteSize = 1U << Idx; 7520b57cec5SDimitry Andric const unsigned BitSize = ByteSize * 8; 7530b57cec5SDimitry Andric Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize); 754439352acSDimitry Andric Value *Val = RMWI->getValOperand(); 755439352acSDimitry Andric Value *Args[] = {Addr, IRB.CreateBitOrPointerCast(Val, Ty), 7560b57cec5SDimitry Andric createOrdering(&IRB, RMWI->getOrdering())}; 757439352acSDimitry Andric Value *C = IRB.CreateCall(F, Args); 758439352acSDimitry Andric I->replaceAllUsesWith(IRB.CreateBitOrPointerCast(C, Val->getType())); 759439352acSDimitry Andric I->eraseFromParent(); 7600b57cec5SDimitry Andric } else if (AtomicCmpXchgInst *CASI = dyn_cast<AtomicCmpXchgInst>(I)) { 7610b57cec5SDimitry Andric Value *Addr = CASI->getPointerOperand(); 762fe6060f1SDimitry Andric Type *OrigOldValTy = CASI->getNewValOperand()->getType(); 763fe6060f1SDimitry Andric int Idx = getMemoryAccessFuncIndex(OrigOldValTy, Addr, DL); 7640b57cec5SDimitry Andric if (Idx < 0) 7650b57cec5SDimitry Andric return false; 7660b57cec5SDimitry Andric const unsigned ByteSize = 1U << Idx; 7670b57cec5SDimitry Andric const unsigned BitSize = ByteSize * 8; 7680b57cec5SDimitry Andric Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize); 7690b57cec5SDimitry Andric Value *CmpOperand = 7700b57cec5SDimitry Andric IRB.CreateBitOrPointerCast(CASI->getCompareOperand(), Ty); 7710b57cec5SDimitry Andric Value *NewOperand = 7720b57cec5SDimitry Andric IRB.CreateBitOrPointerCast(CASI->getNewValOperand(), Ty); 7735f757f3fSDimitry Andric Value *Args[] = {Addr, 7740b57cec5SDimitry Andric CmpOperand, 7750b57cec5SDimitry Andric NewOperand, 7760b57cec5SDimitry Andric createOrdering(&IRB, CASI->getSuccessOrdering()), 7770b57cec5SDimitry Andric createOrdering(&IRB, CASI->getFailureOrdering())}; 7780b57cec5SDimitry Andric CallInst *C = IRB.CreateCall(TsanAtomicCAS[Idx], Args); 7790b57cec5SDimitry Andric Value *Success = IRB.CreateICmpEQ(C, CmpOperand); 7800b57cec5SDimitry Andric Value *OldVal = C; 7810b57cec5SDimitry Andric if (Ty != OrigOldValTy) { 7820b57cec5SDimitry Andric // The value is a pointer, so we need to cast the return value. 7830b57cec5SDimitry Andric OldVal = IRB.CreateIntToPtr(C, OrigOldValTy); 7840b57cec5SDimitry Andric } 7850b57cec5SDimitry Andric 7860b57cec5SDimitry Andric Value *Res = 787bdd1243dSDimitry Andric IRB.CreateInsertValue(PoisonValue::get(CASI->getType()), OldVal, 0); 7880b57cec5SDimitry Andric Res = IRB.CreateInsertValue(Res, Success, 1); 7890b57cec5SDimitry Andric 7900b57cec5SDimitry Andric I->replaceAllUsesWith(Res); 7910b57cec5SDimitry Andric I->eraseFromParent(); 7920b57cec5SDimitry Andric } else if (FenceInst *FI = dyn_cast<FenceInst>(I)) { 7930b57cec5SDimitry Andric Value *Args[] = {createOrdering(&IRB, FI->getOrdering())}; 7940b57cec5SDimitry Andric FunctionCallee F = FI->getSyncScopeID() == SyncScope::SingleThread 7950b57cec5SDimitry Andric ? TsanAtomicSignalFence 7960b57cec5SDimitry Andric : TsanAtomicThreadFence; 797*0fca6ea1SDimitry Andric IRB.CreateCall(F, Args); 798*0fca6ea1SDimitry Andric FI->eraseFromParent(); 7990b57cec5SDimitry Andric } 8000b57cec5SDimitry Andric return true; 8010b57cec5SDimitry Andric } 8020b57cec5SDimitry Andric 803fe6060f1SDimitry Andric int ThreadSanitizer::getMemoryAccessFuncIndex(Type *OrigTy, Value *Addr, 8040b57cec5SDimitry Andric const DataLayout &DL) { 8050b57cec5SDimitry Andric assert(OrigTy->isSized()); 806*0fca6ea1SDimitry Andric if (OrigTy->isScalableTy()) { 807*0fca6ea1SDimitry Andric // FIXME: support vscale. 808*0fca6ea1SDimitry Andric return -1; 809*0fca6ea1SDimitry Andric } 8100b57cec5SDimitry Andric uint32_t TypeSize = DL.getTypeStoreSizeInBits(OrigTy); 8110b57cec5SDimitry Andric if (TypeSize != 8 && TypeSize != 16 && 8120b57cec5SDimitry Andric TypeSize != 32 && TypeSize != 64 && TypeSize != 128) { 8130b57cec5SDimitry Andric NumAccessesWithBadSize++; 8140b57cec5SDimitry Andric // Ignore all unusual sizes. 8150b57cec5SDimitry Andric return -1; 8160b57cec5SDimitry Andric } 81706c3fb27SDimitry Andric size_t Idx = llvm::countr_zero(TypeSize / 8); 8180b57cec5SDimitry Andric assert(Idx < kNumberOfAccessSizes); 8190b57cec5SDimitry Andric return Idx; 8200b57cec5SDimitry Andric } 821