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
24b5b86d263a651566cb25c0f406f75ceffb771029Kostya Serebryany#include "BlackList.h"
2506cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/Function.h"
2606cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/IRBuilder.h"
2706cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/Intrinsics.h"
2806cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/LLVMContext.h"
2906cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/Metadata.h"
3006cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/Module.h"
3106cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/Type.h"
322076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany#include "llvm/ADT/SmallSet.h"
3360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/ADT/SmallString.h"
3460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/ADT/SmallVector.h"
352d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany#include "llvm/ADT/Statistic.h"
3660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/ADT/StringExtras.h"
376e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryany#include "llvm/Support/CommandLine.h"
3860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/Support/Debug.h"
3960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/Support/MathExtras.h"
4052eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany#include "llvm/Support/raw_ostream.h"
4160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/Target/TargetData.h"
4260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/Transforms/Instrumentation.h"
43e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany#include "llvm/Transforms/Utils/BasicBlockUtils.h"
4460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/Transforms/Utils/ModuleUtils.h"
4560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
4660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanyusing namespace llvm;
4760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
486e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryanystatic cl::opt<std::string>  ClBlackListFile("tsan-blacklist",
496e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryany       cl::desc("Blacklist file"), cl::Hidden);
506e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryany
512d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya SerebryanySTATISTIC(NumInstrumentedReads, "Number of instrumented reads");
522d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya SerebryanySTATISTIC(NumInstrumentedWrites, "Number of instrumented writes");
531dfe9b52646ce56446ecd3548dbc81068369ef3fAlexey SamsonovSTATISTIC(NumOmittedReadsBeforeWrite,
542d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany          "Number of reads ignored due to following writes");
552d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya SerebryanySTATISTIC(NumAccessesWithBadSize, "Number of accesses with bad size");
562d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya SerebryanySTATISTIC(NumInstrumentedVtableWrites, "Number of vtable ptr writes");
572d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya SerebryanySTATISTIC(NumOmittedReadsFromConstantGlobals,
582d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany          "Number of reads from constant globals");
592d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya SerebryanySTATISTIC(NumOmittedReadsFromVtable, "Number of vtable reads");
602076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany
6160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanynamespace {
622076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany
6360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany/// ThreadSanitizer: instrument the code in module to find races.
6460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanystruct ThreadSanitizer : public FunctionPass {
6560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  ThreadSanitizer();
66e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  const char *getPassName() const;
6760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  bool runOnFunction(Function &F);
6860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  bool doInitialization(Module &M);
6960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  static char ID;  // Pass identification, replacement for typeid.
7060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
7160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany private:
72e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  bool instrumentLoadOrStore(Instruction *I);
73e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  bool instrumentAtomic(Instruction *I);
7437cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryany  void chooseInstructionsToInstrument(SmallVectorImpl<Instruction*> &Local,
7537cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryany                                      SmallVectorImpl<Instruction*> &All);
76cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany  bool addrPointsToConstantData(Value *Addr);
77e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  int getMemoryAccessFuncIndex(Value *Addr);
782076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany
7960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  TargetData *TD;
80b5b86d263a651566cb25c0f406f75ceffb771029Kostya Serebryany  OwningPtr<BlackList> BL;
81e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  IntegerType *OrdTy;
8260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  // Callbacks to run-time library are computed in doInitialization.
83e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  Function *TsanFuncEntry;
84e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  Function *TsanFuncExit;
8560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  // Accesses sizes are powers of two: 1, 2, 4, 8, 16.
863eccaa6625a8032bee6b84706cb46ed8eb915acfKostya Serebryany  static const size_t kNumberOfAccessSizes = 5;
87e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  Function *TsanRead[kNumberOfAccessSizes];
88e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  Function *TsanWrite[kNumberOfAccessSizes];
89e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  Function *TsanAtomicLoad[kNumberOfAccessSizes];
90e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  Function *TsanAtomicStore[kNumberOfAccessSizes];
91e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  Function *TsanVptrUpdate;
9260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany};
9360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany}  // namespace
9460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
9560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanychar ThreadSanitizer::ID = 0;
9660ebb1947faed42e493179e569c5db0c01d38a2aKostya SerebryanyINITIALIZE_PASS(ThreadSanitizer, "tsan",
9760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    "ThreadSanitizer: detects data races.",
9860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    false, false)
9960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
100e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryanyconst char *ThreadSanitizer::getPassName() const {
101e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  return "ThreadSanitizer";
102e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany}
103e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany
10460ebb1947faed42e493179e569c5db0c01d38a2aKostya SerebryanyThreadSanitizer::ThreadSanitizer()
10560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  : FunctionPass(ID),
10660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  TD(NULL) {
10760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany}
10860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
10960ebb1947faed42e493179e569c5db0c01d38a2aKostya SerebryanyFunctionPass *llvm::createThreadSanitizerPass() {
11060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  return new ThreadSanitizer();
11160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany}
11260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
113e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryanystatic Function *checkInterfaceFunction(Constant *FuncOrBitcast) {
114e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  if (Function *F = dyn_cast<Function>(FuncOrBitcast))
115e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany     return F;
116e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  FuncOrBitcast->dump();
117e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  report_fatal_error("ThreadSanitizer interface function redefined");
118e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany}
119e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany
12060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanybool ThreadSanitizer::doInitialization(Module &M) {
12160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  TD = getAnalysisIfAvailable<TargetData>();
12260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  if (!TD)
12360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    return false;
124b5b86d263a651566cb25c0f406f75ceffb771029Kostya Serebryany  BL.reset(new BlackList(ClBlackListFile));
1256e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryany
12660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  // Always insert a call to __tsan_init into the module's CTORs.
12760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  IRBuilder<> IRB(M.getContext());
12860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  Value *TsanInit = M.getOrInsertFunction("__tsan_init",
12960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany                                          IRB.getVoidTy(), NULL);
13060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  appendToGlobalCtors(M, cast<Function>(TsanInit), 0);
13160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
13260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  // Initialize the callbacks.
133e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  TsanFuncEntry = checkInterfaceFunction(M.getOrInsertFunction(
134e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany      "__tsan_func_entry", IRB.getVoidTy(), IRB.getInt8PtrTy(), NULL));
135e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  TsanFuncExit = checkInterfaceFunction(M.getOrInsertFunction(
136e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany      "__tsan_func_exit", IRB.getVoidTy(), NULL));
137e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  OrdTy = IRB.getInt32Ty();
1383eccaa6625a8032bee6b84706cb46ed8eb915acfKostya Serebryany  for (size_t i = 0; i < kNumberOfAccessSizes; ++i) {
139e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    const size_t ByteSize = 1 << i;
140e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    const size_t BitSize = ByteSize * 8;
141e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    SmallString<32> ReadName("__tsan_read" + itostr(ByteSize));
142e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    TsanRead[i] = checkInterfaceFunction(M.getOrInsertFunction(
143e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany        ReadName, IRB.getVoidTy(), IRB.getInt8PtrTy(), NULL));
144e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany
145e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    SmallString<32> WriteName("__tsan_write" + itostr(ByteSize));
146e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    TsanWrite[i] = checkInterfaceFunction(M.getOrInsertFunction(
147e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany        WriteName, IRB.getVoidTy(), IRB.getInt8PtrTy(), NULL));
148e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany
149e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    Type *Ty = Type::getIntNTy(M.getContext(), BitSize);
150e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    Type *PtrTy = Ty->getPointerTo();
151e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    SmallString<32> AtomicLoadName("__tsan_atomic" + itostr(BitSize) +
152e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany                                   "_load");
153e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    TsanAtomicLoad[i] = checkInterfaceFunction(M.getOrInsertFunction(
154e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany        AtomicLoadName, Ty, PtrTy, OrdTy, NULL));
155e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany
156e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    SmallString<32> AtomicStoreName("__tsan_atomic" + itostr(BitSize) +
157e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany                                    "_store");
158e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    TsanAtomicStore[i] = checkInterfaceFunction(M.getOrInsertFunction(
159e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany        AtomicStoreName, IRB.getVoidTy(), PtrTy, Ty, OrdTy,
160e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany        NULL));
16160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  }
162e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  TsanVptrUpdate = checkInterfaceFunction(M.getOrInsertFunction(
163e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany      "__tsan_vptr_update", IRB.getVoidTy(), IRB.getInt8PtrTy(),
164e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany      IRB.getInt8PtrTy(), NULL));
16560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  return true;
16660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany}
16760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
168cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryanystatic bool isVtableAccess(Instruction *I) {
169cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany  if (MDNode *Tag = I->getMetadata(LLVMContext::MD_tbaa)) {
170cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany    if (Tag->getNumOperands() < 1) return false;
171cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany    if (MDString *Tag1 = dyn_cast<MDString>(Tag->getOperand(0))) {
172cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany      if (Tag1->getString() == "vtable pointer") return true;
173cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany    }
174cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany  }
175cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany  return false;
176cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany}
177cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany
178cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryanybool ThreadSanitizer::addrPointsToConstantData(Value *Addr) {
179cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany  // If this is a GEP, just analyze its pointer operand.
180cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany  if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Addr))
181cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany    Addr = GEP->getPointerOperand();
182cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany
183cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany  if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Addr)) {
184cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany    if (GV->isConstant()) {
185cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany      // Reads from constant globals can not race with any writes.
1862d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany      NumOmittedReadsFromConstantGlobals++;
187cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany      return true;
188cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany    }
1891dfe9b52646ce56446ecd3548dbc81068369ef3fAlexey Samsonov  } else if (LoadInst *L = dyn_cast<LoadInst>(Addr)) {
190cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany    if (isVtableAccess(L)) {
191cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany      // Reads from a vtable pointer can not race with any writes.
1922d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany      NumOmittedReadsFromVtable++;
193cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany      return true;
194cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany    }
195cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany  }
196cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany  return false;
197cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany}
198cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany
1992076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// Instrumenting some of the accesses may be proven redundant.
2002076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// Currently handled:
2012076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany//  - read-before-write (within same BB, no calls between)
2022076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany//
2032076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// We do not handle some of the patterns that should not survive
2042076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// after the classic compiler optimizations.
2052076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// E.g. two reads from the same temp should be eliminated by CSE,
2062076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// two writes should be eliminated by DSE, etc.
2072076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany//
2082076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// 'Local' is a vector of insns within the same BB (no calls between).
2092076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// 'All' is a vector of insns that will be instrumented.
21037cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryanyvoid ThreadSanitizer::chooseInstructionsToInstrument(
2112076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany    SmallVectorImpl<Instruction*> &Local,
2122076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany    SmallVectorImpl<Instruction*> &All) {
2132076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany  SmallSet<Value*, 8> WriteTargets;
2142076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany  // Iterate from the end.
2152076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany  for (SmallVectorImpl<Instruction*>::reverse_iterator It = Local.rbegin(),
2162076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany       E = Local.rend(); It != E; ++It) {
2172076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany    Instruction *I = *It;
2182076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany    if (StoreInst *Store = dyn_cast<StoreInst>(I)) {
2192076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany      WriteTargets.insert(Store->getPointerOperand());
2202076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany    } else {
2212076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany      LoadInst *Load = cast<LoadInst>(I);
222cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany      Value *Addr = Load->getPointerOperand();
223cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany      if (WriteTargets.count(Addr)) {
2242076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany        // We will write to this temp, so no reason to analyze the read.
2252d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany        NumOmittedReadsBeforeWrite++;
2262076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany        continue;
2272076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany      }
228cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany      if (addrPointsToConstantData(Addr)) {
229cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany        // Addr points to some constant data -- it can not race with any writes.
230cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany        continue;
231cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany      }
2322076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany    }
2332076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany    All.push_back(I);
2342076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany  }
2352076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany  Local.clear();
2362076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany}
2372076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany
238e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryanystatic bool isAtomic(Instruction *I) {
239e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  if (LoadInst *LI = dyn_cast<LoadInst>(I))
240e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    return LI->isAtomic() && LI->getSynchScope() == CrossThread;
24137cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryany  if (StoreInst *SI = dyn_cast<StoreInst>(I))
242e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    return SI->isAtomic() && SI->getSynchScope() == CrossThread;
24337cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryany  if (isa<AtomicRMWInst>(I))
244e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    return true;
24537cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryany  if (isa<AtomicCmpXchgInst>(I))
246e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    return true;
24737cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryany  if (FenceInst *FI = dyn_cast<FenceInst>(I))
248e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    return FI->getSynchScope() == CrossThread;
249e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  return false;
250e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany}
251e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany
25260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanybool ThreadSanitizer::runOnFunction(Function &F) {
25360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  if (!TD) return false;
2546e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryany  if (BL->isIn(F)) return false;
25560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  SmallVector<Instruction*, 8> RetVec;
2562076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany  SmallVector<Instruction*, 8> AllLoadsAndStores;
2572076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany  SmallVector<Instruction*, 8> LocalLoadsAndStores;
258e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  SmallVector<Instruction*, 8> AtomicAccesses;
25960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  bool Res = false;
26060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  bool HasCalls = false;
26160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
26260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  // Traverse all instructions, collect loads/stores/returns, check for calls.
26360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  for (Function::iterator FI = F.begin(), FE = F.end();
26460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany       FI != FE; ++FI) {
26560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    BasicBlock &BB = *FI;
26660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    for (BasicBlock::iterator BI = BB.begin(), BE = BB.end();
26760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany         BI != BE; ++BI) {
268e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany      if (isAtomic(BI))
269e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany        AtomicAccesses.push_back(BI);
270e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany      else if (isa<LoadInst>(BI) || isa<StoreInst>(BI))
2712076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany        LocalLoadsAndStores.push_back(BI);
27260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany      else if (isa<ReturnInst>(BI))
27360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany        RetVec.push_back(BI);
2742076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany      else if (isa<CallInst>(BI) || isa<InvokeInst>(BI)) {
27560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany        HasCalls = true;
27637cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryany        chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores);
2772076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany      }
27860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    }
27937cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryany    chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores);
28060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  }
28160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
28260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  // We have collected all loads and stores.
28360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  // FIXME: many of these accesses do not need to be checked for races
28460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  // (e.g. variables that do not escape, etc).
28560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
28660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  // Instrument memory accesses.
2872076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany  for (size_t i = 0, n = AllLoadsAndStores.size(); i < n; ++i) {
2882076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany    Res |= instrumentLoadOrStore(AllLoadsAndStores[i]);
28960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  }
29060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
291e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  // Instrument atomic memory accesses.
292e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  for (size_t i = 0, n = AtomicAccesses.size(); i < n; ++i) {
293e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    Res |= instrumentAtomic(AtomicAccesses[i]);
294e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  }
295e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany
29660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  // Instrument function entry/exit points if there were instrumented accesses.
29760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  if (Res || HasCalls) {
29860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    IRBuilder<> IRB(F.getEntryBlock().getFirstNonPHI());
29960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    Value *ReturnAddress = IRB.CreateCall(
30060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany        Intrinsic::getDeclaration(F.getParent(), Intrinsic::returnaddress),
30160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany        IRB.getInt32(0));
30260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    IRB.CreateCall(TsanFuncEntry, ReturnAddress);
30360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    for (size_t i = 0, n = RetVec.size(); i < n; ++i) {
30460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany      IRBuilder<> IRBRet(RetVec[i]);
30560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany      IRBRet.CreateCall(TsanFuncExit);
30660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    }
30752eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany    Res = true;
30860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  }
30960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  return Res;
31060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany}
31160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany
31260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanybool ThreadSanitizer::instrumentLoadOrStore(Instruction *I) {
31360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  IRBuilder<> IRB(I);
31460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  bool IsWrite = isa<StoreInst>(*I);
31560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  Value *Addr = IsWrite
31660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany      ? cast<StoreInst>(I)->getPointerOperand()
31760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany      : cast<LoadInst>(I)->getPointerOperand();
318e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  int Idx = getMemoryAccessFuncIndex(Addr);
319e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  if (Idx < 0)
32060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany    return false;
32152eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany  if (IsWrite && isVtableAccess(I)) {
3224a002ab9c3eb19d33641cf37945a2ed153ee6d77Kostya Serebryany    DEBUG(dbgs() << "  VPTR : " << *I << "\n");
32352eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany    Value *StoredValue = cast<StoreInst>(I)->getValueOperand();
3244a002ab9c3eb19d33641cf37945a2ed153ee6d77Kostya Serebryany    // StoredValue does not necessary have a pointer type.
3254a002ab9c3eb19d33641cf37945a2ed153ee6d77Kostya Serebryany    if (isa<IntegerType>(StoredValue->getType()))
3264a002ab9c3eb19d33641cf37945a2ed153ee6d77Kostya Serebryany      StoredValue = IRB.CreateIntToPtr(StoredValue, IRB.getInt8PtrTy());
3274a002ab9c3eb19d33641cf37945a2ed153ee6d77Kostya Serebryany    // Call TsanVptrUpdate.
32852eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany    IRB.CreateCall2(TsanVptrUpdate,
32952eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany                    IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()),
33052eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany                    IRB.CreatePointerCast(StoredValue, IRB.getInt8PtrTy()));
3312d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany    NumInstrumentedVtableWrites++;
33252eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany    return true;
33352eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany  }
33460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  Value *OnAccessFunc = IsWrite ? TsanWrite[Idx] : TsanRead[Idx];
33560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  IRB.CreateCall(OnAccessFunc, IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()));
3362d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany  if (IsWrite) NumInstrumentedWrites++;
3372d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany  else         NumInstrumentedReads++;
33860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany  return true;
33960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany}
340e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany
341e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryanystatic ConstantInt *createOrdering(IRBuilder<> *IRB, AtomicOrdering ord) {
342e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  uint32_t v = 0;
343e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  switch (ord) {
344e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    case NotAtomic:              assert(false);
345e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    case Unordered:              // Fall-through.
346e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    case Monotonic:              v = 1 << 0; break;
3471dfe9b52646ce56446ecd3548dbc81068369ef3fAlexey Samsonov    // case Consume:                v = 1 << 1; break;  // Not specified yet.
348e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    case Acquire:                v = 1 << 2; break;
349e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    case Release:                v = 1 << 3; break;
350e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    case AcquireRelease:         v = 1 << 4; break;
351e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    case SequentiallyConsistent: v = 1 << 5; break;
352e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  }
353e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  return IRB->getInt32(v);
354e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany}
355e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany
356e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryanybool ThreadSanitizer::instrumentAtomic(Instruction *I) {
357e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  IRBuilder<> IRB(I);
358e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
359e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    Value *Addr = LI->getPointerOperand();
360e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    int Idx = getMemoryAccessFuncIndex(Addr);
361e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    if (Idx < 0)
362e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany      return false;
363e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    const size_t ByteSize = 1 << Idx;
364e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    const size_t BitSize = ByteSize * 8;
365e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize);
366e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    Type *PtrTy = Ty->getPointerTo();
367e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    Value *Args[] = {IRB.CreatePointerCast(Addr, PtrTy),
368e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany                     createOrdering(&IRB, LI->getOrdering())};
369e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    CallInst *C = CallInst::Create(TsanAtomicLoad[Idx],
370e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany                                   ArrayRef<Value*>(Args));
371e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    ReplaceInstWithInst(I, C);
372e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany
373e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
374e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    Value *Addr = SI->getPointerOperand();
375e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    int Idx = getMemoryAccessFuncIndex(Addr);
376e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    if (Idx < 0)
377e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany      return false;
378e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    const size_t ByteSize = 1 << Idx;
379e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    const size_t BitSize = ByteSize * 8;
380e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize);
381e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    Type *PtrTy = Ty->getPointerTo();
382e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    Value *Args[] = {IRB.CreatePointerCast(Addr, PtrTy),
383e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany                     IRB.CreateIntCast(SI->getValueOperand(), Ty, false),
384e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany                     createOrdering(&IRB, SI->getOrdering())};
385e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    CallInst *C = CallInst::Create(TsanAtomicStore[Idx],
386e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany                                   ArrayRef<Value*>(Args));
387e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    ReplaceInstWithInst(I, C);
388e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  } else if (isa<AtomicRMWInst>(I)) {
389e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    // FIXME: Not yet supported.
390e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  } else if (isa<AtomicCmpXchgInst>(I)) {
391e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    // FIXME: Not yet supported.
392e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  } else if (isa<FenceInst>(I)) {
393e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    // FIXME: Not yet supported.
394e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  }
395e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  return true;
396e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany}
397e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany
398e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryanyint ThreadSanitizer::getMemoryAccessFuncIndex(Value *Addr) {
399e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  Type *OrigPtrTy = Addr->getType();
400e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  Type *OrigTy = cast<PointerType>(OrigPtrTy)->getElementType();
401e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  assert(OrigTy->isSized());
402e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  uint32_t TypeSize = TD->getTypeStoreSizeInBits(OrigTy);
403e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  if (TypeSize != 8  && TypeSize != 16 &&
404e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany      TypeSize != 32 && TypeSize != 64 && TypeSize != 128) {
405e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    NumAccessesWithBadSize++;
406e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    // Ignore all unusual sizes.
407e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany    return -1;
408e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  }
409e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  size_t Idx = CountTrailingZeros_32(TypeSize / 8);
410e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  assert(Idx < kNumberOfAccessSizes);
411e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany  return Idx;
412e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany}
413