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