e6449788d05ad637762e9db0e16f0f113ad3d239
[c11llvm.git] / CDSPass.cpp
1 //===-- CDSPass.cpp - xxx -------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 // This file is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details.
8 //
9 //===----------------------------------------------------------------------===//
10 //
11 // This file is a modified version of ThreadSanitizer.cpp, a part of a race detector.
12 //
13 // The tool is under development, for the details about previous versions see
14 // http://code.google.com/p/data-race-test
15 //
16 // The instrumentation phase is quite simple:
17 //   - Insert calls to run-time library before every memory access.
18 //      - Optimizations may apply to avoid instrumenting some of the accesses.
19 //   - Insert calls at function entry/exit.
20 // The rest is handled by the run-time library.
21 //===----------------------------------------------------------------------===//
22
23 #include "llvm/ADT/Statistic.h"
24 #include "llvm/ADT/StringExtras.h"
25 #include "llvm/ADT/SmallString.h"
26 #include "llvm/Analysis/ValueTracking.h"
27 #include "llvm/Analysis/CaptureTracking.h"
28 #include "llvm/Analysis/LoopInfo.h"
29 #include "llvm/IR/BasicBlock.h"
30 #include "llvm/IR/Function.h"
31 #include "llvm/IR/IRBuilder.h"
32 #include "llvm/IR/Instructions.h"
33 #include "llvm/IR/IntrinsicInst.h"
34 #include "llvm/IR/LLVMContext.h"
35 #include "llvm/IR/LegacyPassManager.h"
36 #include "llvm/IR/Module.h"
37 #include "llvm/IR/PassManager.h"
38 #include "llvm/Pass.h"
39 #include "llvm/ProfileData/InstrProf.h"
40 #include "llvm/Support/raw_ostream.h"
41 #include "llvm/Support/AtomicOrdering.h"
42 #include "llvm/Support/Debug.h"
43 #include "llvm/Transforms/Scalar.h"
44 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
45 #include "llvm/Transforms/Utils/EscapeEnumerator.h"
46 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
47 #include <vector>
48
49 using namespace llvm;
50
51 #define CDS_DEBUG
52 #define DEBUG_TYPE "CDS"
53 #include <llvm/IR/DebugLoc.h>
54
55 Value *getPosition( Instruction * I, IRBuilder <> &IRB, bool print = false)
56 {
57         const DebugLoc & debug_location = I->getDebugLoc ();
58         std::string position_string;
59         {
60                 llvm::raw_string_ostream position_stream (position_string);
61                 debug_location . print (position_stream);
62         }
63
64         if (print) {
65                 errs() << position_string << "\n";
66         }
67
68         return IRB.CreateGlobalStringPtr (position_string);
69 }
70
71 static inline bool checkSignature(Function * func, Value * args[]) {
72         FunctionType * FType = func->getFunctionType();
73         for (unsigned i = 0 ; i < FType->getNumParams(); i++) {
74                 if (FType->getParamType(i) != args[i]->getType()) {
75 #ifdef CDS_DEBUG
76                         errs() << "expects: " << *FType->getParamType(i)
77                                         << "\tbut receives: " << *args[i]->getType() << "\n";
78 #endif
79                         return false;
80                 }
81         }
82
83         return true;
84 }
85
86 STATISTIC(NumInstrumentedReads, "Number of instrumented reads");
87 STATISTIC(NumInstrumentedWrites, "Number of instrumented writes");
88 STATISTIC(NumOmittedReadsBeforeWrite,
89           "Number of reads ignored due to following writes");
90 STATISTIC(NumAccessesWithBadSize, "Number of accesses with bad size");
91 // STATISTIC(NumInstrumentedVtableWrites, "Number of vtable ptr writes");
92 // STATISTIC(NumInstrumentedVtableReads, "Number of vtable ptr reads");
93 STATISTIC(NumOmittedReadsFromConstantGlobals,
94           "Number of reads from constant globals");
95 STATISTIC(NumOmittedReadsFromVtable, "Number of vtable reads");
96 STATISTIC(NumOmittedNonCaptured, "Number of accesses ignored due to capturing");
97
98 // static const char *const kCDSModuleCtorName = "cds.module_ctor";
99 // static const char *const kCDSInitName = "cds_init";
100
101 Type * OrdTy;
102 Type * IntPtrTy;
103 Type * Int8PtrTy;
104 Type * Int16PtrTy;
105 Type * Int32PtrTy;
106 Type * Int64PtrTy;
107
108 Type * VoidTy;
109
110 static const size_t kNumberOfAccessSizes = 4;
111
112 int getAtomicOrderIndex(AtomicOrdering order) {
113         switch (order) {
114                 case AtomicOrdering::Monotonic: 
115                         return (int)AtomicOrderingCABI::relaxed;
116                 //case AtomicOrdering::Consume:         // not specified yet
117                 //      return AtomicOrderingCABI::consume;
118                 case AtomicOrdering::Acquire: 
119                         return (int)AtomicOrderingCABI::acquire;
120                 case AtomicOrdering::Release: 
121                         return (int)AtomicOrderingCABI::release;
122                 case AtomicOrdering::AcquireRelease: 
123                         return (int)AtomicOrderingCABI::acq_rel;
124                 case AtomicOrdering::SequentiallyConsistent: 
125                         return (int)AtomicOrderingCABI::seq_cst;
126                 default:
127                         // unordered or Not Atomic
128                         return -1;
129         }
130 }
131
132 AtomicOrderingCABI indexToAtomicOrder(int index) {
133         switch (index) {
134                 case 0:
135                         return AtomicOrderingCABI::relaxed;
136                 case 1:
137                         return AtomicOrderingCABI::consume;
138                 case 2:
139                         return AtomicOrderingCABI::acquire;
140                 case 3:
141                         return AtomicOrderingCABI::release;
142                 case 4:
143                         return AtomicOrderingCABI::acq_rel;
144                 case 5:
145                         return AtomicOrderingCABI::seq_cst;
146                 default:
147                         errs() << "Bad Atomic index\n";
148                         return AtomicOrderingCABI::seq_cst;
149         }
150 }
151
152 /* According to atomic_base.h: __cmpexch_failure_order */
153 int AtomicCasFailureOrderIndex(int index) {
154         AtomicOrderingCABI succ_order = indexToAtomicOrder(index);
155         AtomicOrderingCABI fail_order;
156         if (succ_order == AtomicOrderingCABI::acq_rel)
157                 fail_order = AtomicOrderingCABI::acquire;
158         else if (succ_order == AtomicOrderingCABI::release) 
159                 fail_order = AtomicOrderingCABI::relaxed;
160         else
161                 fail_order = succ_order;
162
163         return (int) fail_order;
164 }
165
166 /* The original function checkSanitizerInterfaceFunction was defined
167  * in llvm/Transforms/Utils/ModuleUtils.h
168  */
169 static Function * checkCDSPassInterfaceFunction(Value *FuncOrBitcast) {
170         if (isa<Function>(FuncOrBitcast))
171                 return cast<Function>(FuncOrBitcast);
172         FuncOrBitcast->print(errs());
173         errs() << "\n";
174         std::string Err;
175         raw_string_ostream Stream(Err);
176         Stream << "CDSPass interface function redefined: " << *FuncOrBitcast;
177         report_fatal_error(Err);
178 }
179
180 namespace {
181         struct CDSPass : public FunctionPass {
182                 CDSPass() : FunctionPass(ID) {}
183                 StringRef getPassName() const override;
184                 bool runOnFunction(Function &F) override;
185                 bool doInitialization(Module &M) override;
186                 static char ID;
187
188         private:
189                 void initializeCallbacks(Module &M);
190                 bool instrumentLoadOrStore(Instruction *I, const DataLayout &DL);
191                 bool instrumentVolatile(Instruction *I, const DataLayout &DL);
192                 bool instrumentMemIntrinsic(Instruction *I);
193                 bool isAtomicCall(Instruction *I);
194                 bool instrumentAtomic(Instruction *I, const DataLayout &DL);
195                 bool instrumentAtomicCall(CallInst *CI, const DataLayout &DL);
196                 bool shouldInstrumentBeforeAtomics(Instruction *I);
197                 void chooseInstructionsToInstrument(SmallVectorImpl<Instruction *> &Local,
198                                                                                         SmallVectorImpl<Instruction *> &All,
199                                                                                         const DataLayout &DL);
200                 bool addrPointsToConstantData(Value *Addr);
201                 int getMemoryAccessFuncIndex(Value *Addr, const DataLayout &DL);
202                 bool instrumentLoops(Function &F);
203
204                 Function * CDSFuncEntry;
205                 Function * CDSFuncExit;
206
207                 Function * CDSLoad[kNumberOfAccessSizes];
208                 Function * CDSStore[kNumberOfAccessSizes];
209                 Function * CDSVolatileLoad[kNumberOfAccessSizes];
210                 Function * CDSVolatileStore[kNumberOfAccessSizes];
211                 Function * CDSAtomicInit[kNumberOfAccessSizes];
212                 Function * CDSAtomicLoad[kNumberOfAccessSizes];
213                 Function * CDSAtomicStore[kNumberOfAccessSizes];
214                 Function * CDSAtomicRMW[AtomicRMWInst::LAST_BINOP + 1][kNumberOfAccessSizes];
215                 Function * CDSAtomicCAS_V1[kNumberOfAccessSizes];
216                 Function * CDSAtomicCAS_V2[kNumberOfAccessSizes];
217                 Function * CDSAtomicThreadFence;
218                 Function * MemmoveFn, * MemcpyFn, * MemsetFn;
219                 // Function * CDSCtorFunction;
220
221                 std::vector<StringRef> AtomicFuncNames;
222                 std::vector<StringRef> PartialAtomicFuncNames;
223         };
224 }
225
226 StringRef CDSPass::getPassName() const {
227         return "CDSPass";
228 }
229
230 void CDSPass::initializeCallbacks(Module &M) {
231         LLVMContext &Ctx = M.getContext();
232         AttributeList Attr;
233         Attr = Attr.addAttribute(Ctx, AttributeList::FunctionIndex,
234                         Attribute::NoUnwind);
235
236         Type * Int1Ty = Type::getInt1Ty(Ctx);
237         Type * Int32Ty = Type::getInt32Ty(Ctx);
238         OrdTy = Type::getInt32Ty(Ctx);
239
240         Int8PtrTy  = Type::getInt8PtrTy(Ctx);
241         Int16PtrTy = Type::getInt16PtrTy(Ctx);
242         Int32PtrTy = Type::getInt32PtrTy(Ctx);
243         Int64PtrTy = Type::getInt64PtrTy(Ctx);
244
245         VoidTy = Type::getVoidTy(Ctx);
246
247         CDSFuncEntry = checkCDSPassInterfaceFunction(
248                                                 M.getOrInsertFunction("cds_func_entry", 
249                                   Attr, VoidTy, Int8PtrTy).getCallee());
250         CDSFuncExit = checkCDSPassInterfaceFunction(
251                                                 M.getOrInsertFunction("cds_func_exit", 
252                                   Attr, VoidTy, Int8PtrTy).getCallee());
253
254         // Get the function to call from our untime library.
255         for (unsigned i = 0; i < kNumberOfAccessSizes; i++) {
256                 const unsigned ByteSize = 1U << i;
257                 const unsigned BitSize = ByteSize * 8;
258
259                 std::string ByteSizeStr = utostr(ByteSize);
260                 std::string BitSizeStr = utostr(BitSize);
261
262                 Type *Ty = Type::getIntNTy(Ctx, BitSize);
263                 Type *PtrTy = Ty->getPointerTo();
264
265                 // uint8_t cds_atomic_load8 (void * obj, int atomic_index)
266                 // void cds_atomic_store8 (void * obj, int atomic_index, uint8_t val)
267                 SmallString<32> LoadName("cds_load" + BitSizeStr);
268                 SmallString<32> StoreName("cds_store" + BitSizeStr);
269                 SmallString<32> VolatileLoadName("cds_volatile_load" + BitSizeStr);
270                 SmallString<32> VolatileStoreName("cds_volatile_store" + BitSizeStr);
271                 SmallString<32> AtomicInitName("cds_atomic_init" + BitSizeStr);
272                 SmallString<32> AtomicLoadName("cds_atomic_load" + BitSizeStr);
273                 SmallString<32> AtomicStoreName("cds_atomic_store" + BitSizeStr);
274
275                 CDSLoad[i]  = checkCDSPassInterfaceFunction(
276                                                 M.getOrInsertFunction(LoadName, Attr, VoidTy, Int8PtrTy).getCallee());
277                 CDSStore[i] = checkCDSPassInterfaceFunction(
278                                                 M.getOrInsertFunction(StoreName, Attr, VoidTy, Int8PtrTy).getCallee());
279                 CDSVolatileLoad[i]  = checkCDSPassInterfaceFunction(
280                                                                 M.getOrInsertFunction(VolatileLoadName,
281                                       Attr, Ty, PtrTy, Int8PtrTy).getCallee());
282                 CDSVolatileStore[i] = checkCDSPassInterfaceFunction(
283                                                                 M.getOrInsertFunction(VolatileStoreName, 
284                                       Attr, VoidTy, PtrTy, Ty, Int8PtrTy).getCallee());
285                 CDSAtomicInit[i] = checkCDSPassInterfaceFunction(
286                                                         M.getOrInsertFunction(AtomicInitName, 
287                                     Attr, VoidTy, PtrTy, Ty, Int8PtrTy).getCallee());
288                 CDSAtomicLoad[i]  = checkCDSPassInterfaceFunction(
289                                                                 M.getOrInsertFunction(AtomicLoadName, 
290                                       Attr, Ty, PtrTy, OrdTy, Int8PtrTy).getCallee());
291                 CDSAtomicStore[i] = checkCDSPassInterfaceFunction(
292                                                                 M.getOrInsertFunction(AtomicStoreName, 
293                                       Attr, VoidTy, PtrTy, Ty, OrdTy, Int8PtrTy).getCallee());
294
295                 for (int op = AtomicRMWInst::FIRST_BINOP; 
296                         op <= AtomicRMWInst::LAST_BINOP; ++op) {
297                         CDSAtomicRMW[op][i] = nullptr;
298                         std::string NamePart;
299
300                         if (op == AtomicRMWInst::Xchg)
301                                 NamePart = "_exchange";
302                         else if (op == AtomicRMWInst::Add) 
303                                 NamePart = "_fetch_add";
304                         else if (op == AtomicRMWInst::Sub)
305                                 NamePart = "_fetch_sub";
306                         else if (op == AtomicRMWInst::And)
307                                 NamePart = "_fetch_and";
308                         else if (op == AtomicRMWInst::Or)
309                                 NamePart = "_fetch_or";
310                         else if (op == AtomicRMWInst::Xor)
311                                 NamePart = "_fetch_xor";
312                         else
313                                 continue;
314
315                         SmallString<32> AtomicRMWName("cds_atomic" + NamePart + BitSizeStr);
316                         CDSAtomicRMW[op][i] = checkCDSPassInterfaceFunction(
317                                                                         M.getOrInsertFunction(AtomicRMWName, 
318                                         Attr, Ty, PtrTy, Ty, OrdTy, Int8PtrTy).getCallee());
319                 }
320
321                 // only supportes strong version
322                 SmallString<32> AtomicCASName_V1("cds_atomic_compare_exchange" + BitSizeStr + "_v1");
323                 SmallString<32> AtomicCASName_V2("cds_atomic_compare_exchange" + BitSizeStr + "_v2");
324                 CDSAtomicCAS_V1[i] = checkCDSPassInterfaceFunction(
325                                                                 M.getOrInsertFunction(AtomicCASName_V1, 
326                                       Attr, Ty, PtrTy, Ty, Ty, OrdTy, OrdTy, Int8PtrTy).getCallee());
327                 CDSAtomicCAS_V2[i] = checkCDSPassInterfaceFunction(
328                                                                 M.getOrInsertFunction(AtomicCASName_V2, 
329                                       Attr, Int1Ty, PtrTy, PtrTy, Ty, OrdTy, OrdTy, Int8PtrTy).getCallee());
330         }
331
332         CDSAtomicThreadFence = checkCDSPassInterfaceFunction(
333                                                        M.getOrInsertFunction("cds_atomic_thread_fence", Attr, VoidTy, OrdTy, Int8PtrTy).getCallee());
334
335         MemmoveFn = checkCDSPassInterfaceFunction(
336                                         M.getOrInsertFunction("memmove", Attr, Int8PtrTy, Int8PtrTy,
337                                 Int8PtrTy, IntPtrTy).getCallee());
338         MemcpyFn = checkCDSPassInterfaceFunction(
339                                         M.getOrInsertFunction("memcpy", Attr, Int8PtrTy, Int8PtrTy,
340                                 Int8PtrTy, IntPtrTy).getCallee());
341         MemsetFn = checkCDSPassInterfaceFunction(
342                                         M.getOrInsertFunction("memset", Attr, Int8PtrTy, Int8PtrTy,
343                                 Int32Ty, IntPtrTy).getCallee());
344 }
345
346 bool CDSPass::doInitialization(Module &M) {
347         const DataLayout &DL = M.getDataLayout();
348         IntPtrTy = DL.getIntPtrType(M.getContext());
349         
350         // createSanitizerCtorAndInitFunctions is defined in "llvm/Transforms/Utils/ModuleUtils.h"
351         // We do not support it yet
352         /*
353         std::tie(CDSCtorFunction, std::ignore) = createSanitizerCtorAndInitFunctions(
354                         M, kCDSModuleCtorName, kCDSInitName, {}, {});
355
356         appendToGlobalCtors(M, CDSCtorFunction, 0);
357         */
358
359         AtomicFuncNames = 
360         {
361                 "atomic_init", "atomic_load", "atomic_store", 
362                 "atomic_fetch_", "atomic_exchange", "atomic_compare_exchange_"
363         };
364
365         PartialAtomicFuncNames = 
366         { 
367                 "load", "store", "fetch", "exchange", "compare_exchange_" 
368         };
369
370         return true;
371 }
372
373 static bool isVtableAccess(Instruction *I) {
374         if (MDNode *Tag = I->getMetadata(LLVMContext::MD_tbaa))
375                 return Tag->isTBAAVtableAccess();
376         return false;
377 }
378
379 // Do not instrument known races/"benign races" that come from compiler
380 // instrumentatin. The user has no way of suppressing them.
381 static bool shouldInstrumentReadWriteFromAddress(const Module *M, Value *Addr) {
382         // Peel off GEPs and BitCasts.
383         Addr = Addr->stripInBoundsOffsets();
384
385         if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Addr)) {
386                 if (GV->hasSection()) {
387                         StringRef SectionName = GV->getSection();
388                         // Check if the global is in the PGO counters section.
389                         auto OF = Triple(M->getTargetTriple()).getObjectFormat();
390                         if (SectionName.endswith(
391                               getInstrProfSectionName(IPSK_cnts, OF, /*AddSegmentInfo=*/false)))
392                                 return false;
393                 }
394
395                 // Check if the global is private gcov data.
396                 if (GV->getName().startswith("__llvm_gcov") ||
397                 GV->getName().startswith("__llvm_gcda"))
398                 return false;
399         }
400
401         // Do not instrument acesses from different address spaces; we cannot deal
402         // with them.
403         if (Addr) {
404                 Type *PtrTy = cast<PointerType>(Addr->getType()->getScalarType());
405                 if (PtrTy->getPointerAddressSpace() != 0)
406                         return false;
407         }
408
409         return true;
410 }
411
412 bool CDSPass::addrPointsToConstantData(Value *Addr) {
413         // If this is a GEP, just analyze its pointer operand.
414         if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Addr))
415                 Addr = GEP->getPointerOperand();
416
417         if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Addr)) {
418                 if (GV->isConstant()) {
419                         // Reads from constant globals can not race with any writes.
420                         NumOmittedReadsFromConstantGlobals++;
421                         return true;
422                 }
423         } else if (LoadInst *L = dyn_cast<LoadInst>(Addr)) {
424                 if (isVtableAccess(L)) {
425                         // Reads from a vtable pointer can not race with any writes.
426                         NumOmittedReadsFromVtable++;
427                         return true;
428                 }
429         }
430         return false;
431 }
432
433 bool CDSPass::shouldInstrumentBeforeAtomics(Instruction * Inst) {
434         if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
435                 AtomicOrdering ordering = LI->getOrdering();
436                 if ( isAtLeastOrStrongerThan(ordering, AtomicOrdering::Acquire) )
437                         return true;
438         } else if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
439                 AtomicOrdering ordering = SI->getOrdering();
440                 if ( isAtLeastOrStrongerThan(ordering, AtomicOrdering::Acquire) )
441                         return true;
442         } else if (AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(Inst)) {
443                 AtomicOrdering ordering = RMWI->getOrdering();
444                 if ( isAtLeastOrStrongerThan(ordering, AtomicOrdering::Acquire) )
445                         return true;
446         } else if (AtomicCmpXchgInst *CASI = dyn_cast<AtomicCmpXchgInst>(Inst)) {
447                 AtomicOrdering ordering = CASI->getSuccessOrdering();
448                 if ( isAtLeastOrStrongerThan(ordering, AtomicOrdering::Acquire) )
449                         return true;
450         } else if (FenceInst *FI = dyn_cast<FenceInst>(Inst)) {
451                 AtomicOrdering ordering = FI->getOrdering();
452                 if ( isAtLeastOrStrongerThan(ordering, AtomicOrdering::Acquire) )
453                         return true;
454         }
455
456         return false;
457 }
458
459 void CDSPass::chooseInstructionsToInstrument(
460         SmallVectorImpl<Instruction *> &Local, SmallVectorImpl<Instruction *> &All,
461         const DataLayout &DL) {
462         SmallPtrSet<Value*, 8> WriteTargets;
463         // Iterate from the end.
464         for (Instruction *I : reverse(Local)) {
465                 if (StoreInst *Store = dyn_cast<StoreInst>(I)) {
466                         Value *Addr = Store->getPointerOperand();
467                         if (!shouldInstrumentReadWriteFromAddress(I->getModule(), Addr))
468                                 continue;
469                         WriteTargets.insert(Addr);
470                 } else {
471                         LoadInst *Load = cast<LoadInst>(I);
472                         Value *Addr = Load->getPointerOperand();
473                         if (!shouldInstrumentReadWriteFromAddress(I->getModule(), Addr))
474                                 continue;
475                         if (WriteTargets.count(Addr)) {
476                                 // We will write to this temp, so no reason to analyze the read.
477                                 NumOmittedReadsBeforeWrite++;
478                                 continue;
479                         }
480                         if (addrPointsToConstantData(Addr)) {
481                                 // Addr points to some constant data -- it can not race with any writes.
482                                 continue;
483                         }
484                 }
485                 Value *Addr = isa<StoreInst>(*I)
486                         ? cast<StoreInst>(I)->getPointerOperand()
487                         : cast<LoadInst>(I)->getPointerOperand();
488                 if (isa<AllocaInst>(GetUnderlyingObject(Addr, DL)) &&
489                                 !PointerMayBeCaptured(Addr, true, true)) {
490                         // The variable is addressable but not captured, so it cannot be
491                         // referenced from a different thread and participate in a data race
492                         // (see llvm/Analysis/CaptureTracking.h for details).
493                         NumOmittedNonCaptured++;
494                         continue;
495                 }
496                 All.push_back(I);
497         }
498         Local.clear();
499 }
500
501 /* Not implemented
502 void CDSPass::InsertRuntimeIgnores(Function &F) {
503         IRBuilder<> IRB(F.getEntryBlock().getFirstNonPHI());
504         IRB.CreateCall(CDSIgnoreBegin);
505         EscapeEnumerator EE(F, "cds_ignore_cleanup", ClHandleCxxExceptions);
506         while (IRBuilder<> *AtExit = EE.Next()) {
507                 AtExit->CreateCall(CDSIgnoreEnd);
508         }
509 }*/
510
511 bool CDSPass::runOnFunction(Function &F) {
512         initializeCallbacks( *F.getParent() );
513         SmallVector<Instruction*, 8> AllLoadsAndStores;
514         SmallVector<Instruction*, 8> LocalLoadsAndStores;
515         SmallVector<Instruction*, 8> VolatileLoadsAndStores;
516         SmallVector<Instruction*, 8> AtomicAccesses;
517         SmallVector<Instruction*, 8> MemIntrinCalls;
518
519         bool Res = false;
520         bool HasAtomic = false;
521         bool HasVolatile = false;
522         const DataLayout &DL = F.getParent()->getDataLayout();
523
524         // instrumentLoops(F);
525
526         for (auto &BB : F) {
527                 for (auto &Inst : BB) {
528                         if ( (&Inst)->isAtomic() ) {
529                                 AtomicAccesses.push_back(&Inst);
530                                 HasAtomic = true;
531
532                                 if (shouldInstrumentBeforeAtomics(&Inst)) {
533                                         chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores,
534                                                 DL);
535                                 }
536                         } else if (isAtomicCall(&Inst) ) {
537                                 AtomicAccesses.push_back(&Inst);
538                                 HasAtomic = true;
539                                 chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores,
540                                         DL);
541                         } else if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst)) {
542                                 LoadInst *LI = dyn_cast<LoadInst>(&Inst);
543                                 StoreInst *SI = dyn_cast<StoreInst>(&Inst);
544                                 bool isVolatile = ( LI ? LI->isVolatile() : SI->isVolatile() );
545
546                                 if (isVolatile) {
547                                         VolatileLoadsAndStores.push_back(&Inst);
548                                         HasVolatile = true;
549                                 } else
550                                         LocalLoadsAndStores.push_back(&Inst);
551                         } else if (isa<CallInst>(Inst) || isa<InvokeInst>(Inst)) {
552                                 if (isa<MemIntrinsic>(Inst))
553                                         MemIntrinCalls.push_back(&Inst);
554
555                                 /*if (CallInst *CI = dyn_cast<CallInst>(&Inst))
556                                         maybeMarkSanitizerLibraryCallNoBuiltin(CI, TLI);
557                                 */
558
559                                 chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores,
560                                         DL);
561                         }
562                 }
563
564                 chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores, DL);
565         }
566
567         for (auto Inst : AllLoadsAndStores) {
568                 Res |= instrumentLoadOrStore(Inst, DL);
569         }
570
571         for (auto Inst : VolatileLoadsAndStores) {
572                 Res |= instrumentVolatile(Inst, DL);
573         }
574
575         for (auto Inst : AtomicAccesses) {
576                 Res |= instrumentAtomic(Inst, DL);
577         }
578
579         for (auto Inst : MemIntrinCalls) {
580                 Res |= instrumentMemIntrinsic(Inst);
581         }
582
583         // Instrument function entry and exit for functions containing atomics or volatiles
584         if (Res && ( HasAtomic || HasVolatile) ) {
585                 IRBuilder<> IRB(F.getEntryBlock().getFirstNonPHI());
586                 /* Unused for now
587                 Value *ReturnAddress = IRB.CreateCall(
588                         Intrinsic::getDeclaration(F.getParent(), Intrinsic::returnaddress),
589                         IRB.getInt32(0));
590                 */
591
592                 Value * FuncName = IRB.CreateGlobalStringPtr(F.getName());
593                 IRB.CreateCall(CDSFuncEntry, FuncName);
594
595                 EscapeEnumerator EE(F, "cds_cleanup", true);
596                 while (IRBuilder<> *AtExit = EE.Next()) {
597                   AtExit->CreateCall(CDSFuncExit, FuncName);
598                 }
599
600                 Res = true;
601         }
602
603         return false;
604 }
605
606 bool CDSPass::instrumentLoadOrStore(Instruction *I,
607                                                                         const DataLayout &DL) {
608         IRBuilder<> IRB(I);
609         bool IsWrite = isa<StoreInst>(*I);
610         Value *Addr = IsWrite
611                 ? cast<StoreInst>(I)->getPointerOperand()
612                 : cast<LoadInst>(I)->getPointerOperand();
613
614         // swifterror memory addresses are mem2reg promoted by instruction selection.
615         // As such they cannot have regular uses like an instrumentation function and
616         // it makes no sense to track them as memory.
617         if (Addr->isSwiftError())
618                 return false;
619
620         int Idx = getMemoryAccessFuncIndex(Addr, DL);
621         if (Idx < 0)
622                 return false;
623
624         if (IsWrite && isVtableAccess(I)) {
625                 /* TODO
626                 LLVM_DEBUG(dbgs() << "  VPTR : " << *I << "\n");
627                 Value *StoredValue = cast<StoreInst>(I)->getValueOperand();
628                 // StoredValue may be a vector type if we are storing several vptrs at once.
629                 // In this case, just take the first element of the vector since this is
630                 // enough to find vptr races.
631                 if (isa<VectorType>(StoredValue->getType()))
632                         StoredValue = IRB.CreateExtractElement(
633                                         StoredValue, ConstantInt::get(IRB.getInt32Ty(), 0));
634                 if (StoredValue->getType()->isIntegerTy())
635                         StoredValue = IRB.CreateIntToPtr(StoredValue, IRB.getInt8PtrTy());
636                 // Call TsanVptrUpdate.
637                 IRB.CreateCall(TsanVptrUpdate,
638                                                 {IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()),
639                                                         IRB.CreatePointerCast(StoredValue, IRB.getInt8PtrTy())});
640                 NumInstrumentedVtableWrites++;
641                 */
642                 return true;
643         }
644
645         if (!IsWrite && isVtableAccess(I)) {
646                 /* TODO
647                 IRB.CreateCall(TsanVptrLoad,
648                                                  IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()));
649                 NumInstrumentedVtableReads++;
650                 */
651                 return true;
652         }
653
654         // TODO: unaligned reads and writes
655         Value *OnAccessFunc = nullptr;
656         OnAccessFunc = IsWrite ? CDSStore[Idx] : CDSLoad[Idx];
657         IRB.CreateCall(OnAccessFunc, IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()));
658         if (IsWrite) NumInstrumentedWrites++;
659         else         NumInstrumentedReads++;
660         return true;
661 }
662
663 bool CDSPass::instrumentVolatile(Instruction * I, const DataLayout &DL) {
664         IRBuilder<> IRB(I);
665         Value *position = getPosition(I, IRB);
666
667         if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
668                 Value *Addr = LI->getPointerOperand();
669                 int Idx=getMemoryAccessFuncIndex(Addr, DL);
670                 if (Idx < 0)
671                         return false;
672                 const unsigned ByteSize = 1U << Idx;
673                 const unsigned BitSize = ByteSize * 8;
674                 Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize);
675                 Type *PtrTy = Ty->getPointerTo();
676                 Value *Args[] = {IRB.CreatePointerCast(Addr, PtrTy), position};
677
678                 Type *OrigTy = cast<PointerType>(Addr->getType())->getElementType();
679                 Value *C = IRB.CreateCall(CDSVolatileLoad[Idx], Args);
680                 Value *Cast = IRB.CreateBitOrPointerCast(C, OrigTy);
681                 I->replaceAllUsesWith(Cast);
682         } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
683                 Value *Addr = SI->getPointerOperand();
684                 int Idx=getMemoryAccessFuncIndex(Addr, DL);
685                 if (Idx < 0)
686                         return false;
687                 const unsigned ByteSize = 1U << Idx;
688                 const unsigned BitSize = ByteSize * 8;
689                 Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize);
690                 Type *PtrTy = Ty->getPointerTo();
691                 Value *Args[] = {IRB.CreatePointerCast(Addr, PtrTy),
692                                           IRB.CreateBitOrPointerCast(SI->getValueOperand(), Ty),
693                                           position};
694                 CallInst *C = CallInst::Create(CDSVolatileStore[Idx], Args);
695                 ReplaceInstWithInst(I, C);
696         } else {
697                 return false;
698         }
699
700         return true;
701 }
702
703 bool CDSPass::instrumentMemIntrinsic(Instruction *I) {
704         IRBuilder<> IRB(I);
705         if (MemSetInst *M = dyn_cast<MemSetInst>(I)) {
706                 IRB.CreateCall(
707                         MemsetFn,
708                         {IRB.CreatePointerCast(M->getArgOperand(0), IRB.getInt8PtrTy()),
709                          IRB.CreateIntCast(M->getArgOperand(1), IRB.getInt32Ty(), false),
710                          IRB.CreateIntCast(M->getArgOperand(2), IntPtrTy, false)});
711                 I->eraseFromParent();
712         } else if (MemTransferInst *M = dyn_cast<MemTransferInst>(I)) {
713                 IRB.CreateCall(
714                         isa<MemCpyInst>(M) ? MemcpyFn : MemmoveFn,
715                         {IRB.CreatePointerCast(M->getArgOperand(0), IRB.getInt8PtrTy()),
716                          IRB.CreatePointerCast(M->getArgOperand(1), IRB.getInt8PtrTy()),
717                          IRB.CreateIntCast(M->getArgOperand(2), IntPtrTy, false)});
718                 I->eraseFromParent();
719         }
720         return false;
721 }
722
723 bool CDSPass::instrumentAtomic(Instruction * I, const DataLayout &DL) {
724         IRBuilder<> IRB(I);
725
726         if (auto *CI = dyn_cast<CallInst>(I)) {
727                 return instrumentAtomicCall(CI, DL);
728         }
729
730         Value *position = getPosition(I, IRB);
731         if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
732                 Value *Addr = LI->getPointerOperand();
733                 int Idx=getMemoryAccessFuncIndex(Addr, DL);
734                 if (Idx < 0)
735                         return false;
736
737                 int atomic_order_index = getAtomicOrderIndex(LI->getOrdering());
738                 Value *order = ConstantInt::get(OrdTy, atomic_order_index);
739                 Value *Args[] = {Addr, order, position};
740                 Instruction* funcInst = CallInst::Create(CDSAtomicLoad[Idx], Args);
741                 ReplaceInstWithInst(LI, funcInst);
742         } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
743                 Value *Addr = SI->getPointerOperand();
744                 int Idx=getMemoryAccessFuncIndex(Addr, DL);
745                 if (Idx < 0)
746                         return false;
747
748                 int atomic_order_index = getAtomicOrderIndex(SI->getOrdering());
749                 Value *val = SI->getValueOperand();
750                 Value *order = ConstantInt::get(OrdTy, atomic_order_index);
751                 Value *Args[] = {Addr, val, order, position};
752                 Instruction* funcInst = CallInst::Create(CDSAtomicStore[Idx], Args);
753                 ReplaceInstWithInst(SI, funcInst);
754         } else if (AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(I)) {
755                 Value *Addr = RMWI->getPointerOperand();
756                 int Idx=getMemoryAccessFuncIndex(Addr, DL);
757                 if (Idx < 0)
758                         return false;
759
760                 int atomic_order_index = getAtomicOrderIndex(RMWI->getOrdering());
761                 Value *val = RMWI->getValOperand();
762                 Value *order = ConstantInt::get(OrdTy, atomic_order_index);
763                 Value *Args[] = {Addr, val, order, position};
764                 Instruction* funcInst = CallInst::Create(CDSAtomicRMW[RMWI->getOperation()][Idx], Args);
765                 ReplaceInstWithInst(RMWI, funcInst);
766         } else if (AtomicCmpXchgInst *CASI = dyn_cast<AtomicCmpXchgInst>(I)) {
767                 IRBuilder<> IRB(CASI);
768
769                 Value *Addr = CASI->getPointerOperand();
770                 int Idx=getMemoryAccessFuncIndex(Addr, DL);
771                 if (Idx < 0)
772                         return false;
773
774                 const unsigned ByteSize = 1U << Idx;
775                 const unsigned BitSize = ByteSize * 8;
776                 Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize);
777                 Type *PtrTy = Ty->getPointerTo();
778
779                 Value *CmpOperand = IRB.CreateBitOrPointerCast(CASI->getCompareOperand(), Ty);
780                 Value *NewOperand = IRB.CreateBitOrPointerCast(CASI->getNewValOperand(), Ty);
781
782                 int atomic_order_index_succ = getAtomicOrderIndex(CASI->getSuccessOrdering());
783                 int atomic_order_index_fail = getAtomicOrderIndex(CASI->getFailureOrdering());
784                 Value *order_succ = ConstantInt::get(OrdTy, atomic_order_index_succ);
785                 Value *order_fail = ConstantInt::get(OrdTy, atomic_order_index_fail);
786
787                 Value *Args[] = {IRB.CreatePointerCast(Addr, PtrTy),
788                                                  CmpOperand, NewOperand,
789                                                  order_succ, order_fail, position};
790
791                 CallInst *funcInst = IRB.CreateCall(CDSAtomicCAS_V1[Idx], Args);
792                 Value *Success = IRB.CreateICmpEQ(funcInst, CmpOperand);
793
794                 Value *OldVal = funcInst;
795                 Type *OrigOldValTy = CASI->getNewValOperand()->getType();
796                 if (Ty != OrigOldValTy) {
797                         // The value is a pointer, so we need to cast the return value.
798                         OldVal = IRB.CreateIntToPtr(funcInst, OrigOldValTy);
799                 }
800
801                 Value *Res =
802                   IRB.CreateInsertValue(UndefValue::get(CASI->getType()), OldVal, 0);
803                 Res = IRB.CreateInsertValue(Res, Success, 1);
804
805                 I->replaceAllUsesWith(Res);
806                 I->eraseFromParent();
807         } else if (FenceInst *FI = dyn_cast<FenceInst>(I)) {
808                 int atomic_order_index = getAtomicOrderIndex(FI->getOrdering());
809                 Value *order = ConstantInt::get(OrdTy, atomic_order_index);
810                 Value *Args[] = {order, position};
811
812                 CallInst *funcInst = CallInst::Create(CDSAtomicThreadFence, Args);
813                 ReplaceInstWithInst(FI, funcInst);
814                 // errs() << "Thread Fences replaced\n";
815         }
816         return true;
817 }
818
819 bool CDSPass::isAtomicCall(Instruction *I) {
820         if ( auto *CI = dyn_cast<CallInst>(I) ) {
821                 Function *fun = CI->getCalledFunction();
822                 if (fun == NULL)
823                         return false;
824
825                 StringRef funName = fun->getName();
826
827                 // TODO: come up with better rules for function name checking
828                 for (StringRef name : AtomicFuncNames) {
829                         if ( funName.contains(name) ) 
830                                 return true;
831                 }
832                 
833                 for (StringRef PartialName : PartialAtomicFuncNames) {
834                         if (funName.contains(PartialName) && 
835                                         funName.contains("atomic") )
836                                 return true;
837                 }
838         }
839
840         return false;
841 }
842
843 bool CDSPass::instrumentAtomicCall(CallInst *CI, const DataLayout &DL) {
844         IRBuilder<> IRB(CI);
845         Function *fun = CI->getCalledFunction();
846         StringRef funName = fun->getName();
847         std::vector<Value *> parameters;
848
849         User::op_iterator begin = CI->arg_begin();
850         User::op_iterator end = CI->arg_end();
851         for (User::op_iterator it = begin; it != end; ++it) {
852                 Value *param = *it;
853                 parameters.push_back(param);
854         }
855
856         // obtain source line number of the CallInst
857         Value *position = getPosition(CI, IRB);
858
859         // the pointer to the address is always the first argument
860         Value *OrigPtr = parameters[0];
861
862         int Idx = getMemoryAccessFuncIndex(OrigPtr, DL);
863         if (Idx < 0)
864                 return false;
865
866         const unsigned ByteSize = 1U << Idx;
867         const unsigned BitSize = ByteSize * 8;
868         Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize);
869         Type *PtrTy = Ty->getPointerTo();
870
871         // atomic_init; args = {obj, order}
872         if (funName.contains("atomic_init")) {
873                 Value *OrigVal = parameters[1];
874
875                 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
876                 Value *val;
877                 if (OrigVal->getType()->isPtrOrPtrVectorTy())
878                         val = IRB.CreatePointerCast(OrigVal, Ty);
879                 else
880                         val = IRB.CreateIntCast(OrigVal, Ty, true);
881
882                 Value *args[] = {ptr, val, position};
883
884                 if (!checkSignature(CDSAtomicInit[Idx], args))
885                         return false;
886
887                 Instruction* funcInst = CallInst::Create(CDSAtomicInit[Idx], args);
888                 ReplaceInstWithInst(CI, funcInst);
889                 return true;
890         }
891
892         // atomic_load; args = {obj, order}
893         if (funName.contains("atomic_load")) {
894                 bool isExplicit = funName.contains("atomic_load_explicit");
895
896                 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
897                 Value *order;
898                 if (isExplicit)
899                         order = IRB.CreateBitOrPointerCast(parameters[1], OrdTy);
900                 else 
901                         order = ConstantInt::get(OrdTy, 
902                                                         (int) AtomicOrderingCABI::seq_cst);
903                 Value *args[] = {ptr, order, position};
904
905                 if (!checkSignature(CDSAtomicLoad[Idx], args))
906                         return false;
907
908                 Instruction* funcInst = CallInst::Create(CDSAtomicLoad[Idx], args);
909                 ReplaceInstWithInst(CI, funcInst);
910
911                 return true;
912         } else if (funName.contains("atomic") && 
913                                         funName.contains("load") ) {
914                 // does this version of call always have an atomic order as an argument?
915                 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
916                 Value *order = IRB.CreateBitOrPointerCast(parameters[1], OrdTy);
917                 Value *args[] = {ptr, order, position};
918
919                 // Without this check, gdax does not compile :(
920                 if (!CI->getType()->isPointerTy()) {
921                         return false;   
922                 } 
923
924                 if (!checkSignature(CDSAtomicLoad[Idx], args))
925                         return false;
926
927                 CallInst *funcInst = IRB.CreateCall(CDSAtomicLoad[Idx], args);
928                 Value *RetVal = IRB.CreateIntToPtr(funcInst, CI->getType());
929
930                 CI->replaceAllUsesWith(RetVal);
931                 CI->eraseFromParent();
932
933                 return true;
934         }
935
936         // atomic_store; args = {obj, val, order}
937         if (funName.contains("atomic_store")) {
938                 bool isExplicit = funName.contains("atomic_store_explicit");
939                 Value *OrigVal = parameters[1];
940
941                 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
942                 Value *val = IRB.CreatePointerCast(OrigVal, Ty);
943                 Value *order;
944                 if (isExplicit)
945                         order = IRB.CreateBitOrPointerCast(parameters[2], OrdTy);
946                 else 
947                         order = ConstantInt::get(OrdTy, 
948                                                         (int) AtomicOrderingCABI::seq_cst);
949                 Value *args[] = {ptr, val, order, position};
950
951                 if (!checkSignature(CDSAtomicStore[Idx], args))
952                         return false;
953
954                 Instruction* funcInst = CallInst::Create(CDSAtomicStore[Idx], args);
955                 ReplaceInstWithInst(CI, funcInst);
956
957                 return true;
958         } else if (funName.contains("atomic") && 
959                                         funName.contains("store") ) {
960                 // Does this version of call always have an atomic order as an argument?
961                 if (parameters.size() < 3)
962                         return false;
963
964                 Value *OrigVal = parameters[1];
965                 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
966
967                 Value *val;
968                 if (OrigVal->getType()->isPtrOrPtrVectorTy())
969                         val = IRB.CreatePointerCast(OrigVal, Ty);
970                 else
971                         val = IRB.CreateIntCast(OrigVal, Ty, true);
972
973                 Value *order = IRB.CreateBitOrPointerCast(parameters[2], OrdTy);
974                 Value *args[] = {ptr, val, order, position};
975
976                 if (!checkSignature(CDSAtomicStore[Idx], args))
977                         return false;
978
979                 Instruction* funcInst = CallInst::Create(CDSAtomicStore[Idx], args);
980                 ReplaceInstWithInst(CI, funcInst);
981
982                 return true;
983         }
984
985         // atomic_fetch_*; args = {obj, val, order}
986         if (funName.contains("atomic_fetch_") || 
987                 funName.contains("atomic_exchange")) {
988
989                 bool isExplicit = funName.contains("_explicit");
990                 Value *OrigVal = parameters[1];
991
992                 int op;
993                 if ( funName.contains("_fetch_add") )
994                         op = AtomicRMWInst::Add;
995                 else if ( funName.contains("_fetch_sub") )
996                         op = AtomicRMWInst::Sub;
997                 else if ( funName.contains("_fetch_and") )
998                         op = AtomicRMWInst::And;
999                 else if ( funName.contains("_fetch_or") )
1000                         op = AtomicRMWInst::Or;
1001                 else if ( funName.contains("_fetch_xor") )
1002                         op = AtomicRMWInst::Xor;
1003                 else if ( funName.contains("atomic_exchange") )
1004                         op = AtomicRMWInst::Xchg;
1005                 else {
1006                         errs() << "Unknown atomic read-modify-write operation\n";
1007                         return false;
1008                 }
1009
1010                 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
1011                 Value *val;
1012                 if (OrigVal->getType()->isPtrOrPtrVectorTy())
1013                         val = IRB.CreatePointerCast(OrigVal, Ty);
1014                 else
1015                         val = IRB.CreateIntCast(OrigVal, Ty, true);
1016
1017                 Value *order;
1018                 if (isExplicit)
1019                         order = IRB.CreateBitOrPointerCast(parameters[2], OrdTy);
1020                 else 
1021                         order = ConstantInt::get(OrdTy, 
1022                                                         (int) AtomicOrderingCABI::seq_cst);
1023                 Value *args[] = {ptr, val, order, position};
1024
1025                 if (!checkSignature(CDSAtomicRMW[op][Idx], args))
1026                         return false;
1027
1028                 Instruction* funcInst = CallInst::Create(CDSAtomicRMW[op][Idx], args);
1029                 ReplaceInstWithInst(CI, funcInst);
1030
1031                 return true;
1032         } else if (funName.contains("fetch")) {
1033                 errs() << "atomic fetch captured. Not implemented yet. ";
1034                 errs() << "See source file :";
1035                 getPosition(CI, IRB, true);
1036                 return false;
1037         } else if (funName.contains("exchange") &&
1038                         !funName.contains("compare_exchange") ) {
1039                 if (CI->getType()->isPointerTy()) {
1040                         /**
1041                          * TODO: instrument the following case
1042                          * mcs-lock.h
1043                          * std::atomic<struct T *> m_tail;
1044                          * struct T * me;
1045                          * struct T * pred = m_tail.exchange(me, memory_order_*);
1046                          */
1047                         errs() << "atomic exchange captured. Not implemented yet. ";
1048                         errs() << "See source file :";
1049                         getPosition(CI, IRB, true);
1050
1051                         return false;
1052                 }
1053
1054                 Value *OrigVal = parameters[1];
1055
1056                 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
1057                 Value *val;
1058                 if (OrigVal->getType()->isPtrOrPtrVectorTy())
1059                         val = IRB.CreatePointerCast(OrigVal, Ty);
1060                 else
1061                         val = IRB.CreateIntCast(OrigVal, Ty, true);
1062
1063                 Value *order = IRB.CreateBitOrPointerCast(parameters[2], OrdTy);
1064                 Value *args[] = {ptr, val, order, position};
1065
1066                 int op = AtomicRMWInst::Xchg;
1067
1068                 if (!checkSignature(CDSAtomicRMW[op][Idx], args))
1069                         return false;
1070
1071                 Instruction* funcInst = CallInst::Create(CDSAtomicRMW[op][Idx], args);
1072                 ReplaceInstWithInst(CI, funcInst);
1073
1074                 return true;
1075         }
1076
1077         /* atomic_compare_exchange_*; 
1078            args = {obj, expected, new value, order1, order2}
1079         */
1080         if ( funName.contains("atomic_compare_exchange_") ) {
1081                 bool isExplicit = funName.contains("_explicit");
1082
1083                 Value *Addr = IRB.CreatePointerCast(OrigPtr, PtrTy);
1084                 Value *CmpOperand = IRB.CreatePointerCast(parameters[1], PtrTy);
1085                 Value *NewOperand = IRB.CreateBitOrPointerCast(parameters[2], Ty);
1086
1087                 Value *order_succ, *order_fail;
1088                 if (isExplicit) {
1089                         order_succ = IRB.CreateBitOrPointerCast(parameters[3], OrdTy);
1090
1091                         if (parameters.size() > 4) {
1092                                 order_fail = IRB.CreateBitOrPointerCast(parameters[4], OrdTy);
1093                         } else {
1094                                 /* The failure order is not provided */
1095                                 order_fail = order_succ;
1096                                 ConstantInt * order_succ_cast = dyn_cast<ConstantInt>(order_succ);
1097                                 int index = order_succ_cast->getSExtValue();
1098
1099                                 order_fail = ConstantInt::get(OrdTy,
1100                                                                 AtomicCasFailureOrderIndex(index));
1101                         }
1102                 } else  {
1103                         order_succ = ConstantInt::get(OrdTy, 
1104                                                         (int) AtomicOrderingCABI::seq_cst);
1105                         order_fail = ConstantInt::get(OrdTy, 
1106                                                         (int) AtomicOrderingCABI::seq_cst);
1107                 }
1108
1109                 Value *args[] = {Addr, CmpOperand, NewOperand, 
1110                                                         order_succ, order_fail, position};
1111
1112                 if (!checkSignature(CDSAtomicCAS_V2[Idx], args))
1113                         return false;
1114
1115                 Instruction* funcInst = CallInst::Create(CDSAtomicCAS_V2[Idx], args);
1116                 ReplaceInstWithInst(CI, funcInst);
1117
1118                 return true;
1119         } else if ( funName.contains("compare_exchange_strong") ||
1120                                 funName.contains("compare_exchange_weak") ) {
1121                 Value *Addr = IRB.CreatePointerCast(OrigPtr, PtrTy);
1122                 Value *CmpOperand = IRB.CreatePointerCast(parameters[1], PtrTy);
1123                 Value *NewOperand = IRB.CreateBitOrPointerCast(parameters[2], Ty);
1124
1125                 Value *order_succ, *order_fail;
1126                 order_succ = IRB.CreateBitOrPointerCast(parameters[3], OrdTy);
1127
1128                 if (parameters.size() > 4) {
1129                         order_fail = IRB.CreateBitOrPointerCast(parameters[4], OrdTy);
1130                 } else {
1131                         /* The failure order is not provided */
1132                         order_fail = order_succ;
1133                         ConstantInt * order_succ_cast = dyn_cast<ConstantInt>(order_succ);
1134                         int index = order_succ_cast->getSExtValue();
1135
1136                         order_fail = ConstantInt::get(OrdTy,
1137                                                         AtomicCasFailureOrderIndex(index));
1138                 }
1139
1140                 Value *args[] = {Addr, CmpOperand, NewOperand, 
1141                                                         order_succ, order_fail, position};
1142
1143                 if (!checkSignature(CDSAtomicCAS_V2[Idx], args))
1144                         return false;
1145
1146                 Instruction* funcInst = CallInst::Create(CDSAtomicCAS_V2[Idx], args);
1147                 ReplaceInstWithInst(CI, funcInst);
1148
1149                 return true;
1150         }
1151
1152         return false;
1153 }
1154
1155 int CDSPass::getMemoryAccessFuncIndex(Value *Addr,
1156                                                                                 const DataLayout &DL) {
1157         Type *OrigPtrTy = Addr->getType();
1158         Type *OrigTy = cast<PointerType>(OrigPtrTy)->getElementType();
1159         assert(OrigTy->isSized());
1160         uint32_t TypeSize = DL.getTypeStoreSizeInBits(OrigTy);
1161         if (TypeSize != 8  && TypeSize != 16 &&
1162                 TypeSize != 32 && TypeSize != 64 && TypeSize != 128) {
1163                 NumAccessesWithBadSize++;
1164                 // Ignore all unusual sizes.
1165                 return -1;
1166         }
1167         size_t Idx = countTrailingZeros(TypeSize / 8);
1168         //assert(Idx < kNumberOfAccessSizes);
1169         if (Idx >= kNumberOfAccessSizes) {
1170                 return -1;
1171         }
1172         return Idx;
1173 }
1174
1175 bool CDSPass::instrumentLoops(Function &F)
1176 {
1177         DominatorTree DT(F);
1178         LoopInfo LI(DT);
1179
1180         SmallVector<Loop *, 4> Loops = LI.getLoopsInPreorder();
1181         bool instrumented = false;
1182
1183         // Do a post-order traversal of the loops so that counter updates can be
1184         // iteratively hoisted outside the loop nest.
1185         for (auto *Loop : llvm::reverse(Loops)) {
1186                 bool instrument_loop = false;
1187
1188                 // Iterator over loop blocks and search for atomics and volatiles
1189                 Loop::block_iterator it;
1190                 for (it = Loop->block_begin(); it != Loop->block_end(); it++) {
1191                         BasicBlock * block = *it;
1192                         for (auto &Inst : *block) {
1193                                 if ( (&Inst)->isAtomic() ) {
1194                                         instrument_loop = true;
1195                                         break;
1196                                 } else if (isAtomicCall(&Inst)) {
1197                                         instrument_loop = true;
1198                                         break;
1199                                 } else if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst)) {
1200                                         LoadInst *LI = dyn_cast<LoadInst>(&Inst);
1201                                         StoreInst *SI = dyn_cast<StoreInst>(&Inst);
1202                                         bool isVolatile = ( LI ? LI->isVolatile() : SI->isVolatile() );
1203
1204                                         if (isVolatile) {
1205                                                 instrument_loop = true;
1206                                                 break;
1207                                         }
1208                                 }
1209                         }
1210
1211                         if (instrument_loop)
1212                                 break;
1213                 }
1214
1215                 if (instrument_loop) {
1216                         // TODO: what to instrument?
1217                         errs() << "Function: " << F.getName() << "\n";
1218                         BasicBlock * header = Loop->getHeader();
1219                         header->dump();
1220
1221                         instrumented = true;
1222                 }
1223         }
1224
1225         return instrumented;
1226 }
1227
1228 char CDSPass::ID = 0;
1229
1230 // Automatically enable the pass.
1231 static void registerCDSPass(const PassManagerBuilder &,
1232                                                         legacy::PassManagerBase &PM) {
1233         PM.add(new CDSPass());
1234 }
1235
1236 /* Enable the pass when opt level is greater than 0 */
1237 static RegisterStandardPasses 
1238         RegisterMyPass1(PassManagerBuilder::EP_OptimizerLast,
1239 registerCDSPass);
1240
1241 /* Enable the pass when opt level is 0 */
1242 static RegisterStandardPasses 
1243         RegisterMyPass2(PassManagerBuilder::EP_EnabledOnOptLevel0,
1244 registerCDSPass);