X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;ds=inline;f=CDSPass.cpp;h=6159585f993697a36ba98755ad6021a5db447c96;hb=refs%2Fheads%2Fvagrant;hp=ecbb9576548d0d1fed211fd6e6e924012358292e;hpb=e8cae0c24bad9afc9be599f9c5e24a89c36821c8;p=c11llvm.git diff --git a/CDSPass.cpp b/CDSPass.cpp index ecbb957..6159585 100644 --- a/CDSPass.cpp +++ b/CDSPass.cpp @@ -25,10 +25,12 @@ #include "llvm/ADT/SmallString.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/Analysis/CaptureTracking.h" +#include "llvm/Analysis/LoopInfo.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" @@ -41,16 +43,16 @@ #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/EscapeEnumerator.h" -// #include "llvm/Transforms/Utils/ModuleUtils.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" #include using namespace llvm; +#define CDS_DEBUG #define DEBUG_TYPE "CDS" #include -Value *getPosition( Instruction * I, IRBuilder <> IRB, bool print = false) +static inline Value *getPosition( Instruction * I, IRBuilder <> IRB, bool print = false) { const DebugLoc & debug_location = I->getDebugLoc (); std::string position_string; @@ -66,6 +68,21 @@ Value *getPosition( Instruction * I, IRBuilder <> IRB, bool print = false) return IRB.CreateGlobalStringPtr (position_string); } +static inline bool checkSignature(Function * func, Value * args[]) { + FunctionType * FType = func->getFunctionType(); + for (unsigned i = 0 ; i < FType->getNumParams(); i++) { + if (FType->getParamType(i) != args[i]->getType()) { +#ifdef CDS_DEBUG + errs() << "expects: " << *FType->getParamType(i) + << "\tbut receives: " << *args[i]->getType() << "\n"; +#endif + return false; + } + } + + return true; +} + STATISTIC(NumInstrumentedReads, "Number of instrumented reads"); STATISTIC(NumInstrumentedWrites, "Number of instrumented writes"); STATISTIC(NumOmittedReadsBeforeWrite, @@ -96,8 +113,8 @@ int getAtomicOrderIndex(AtomicOrdering order) { switch (order) { case AtomicOrdering::Monotonic: return (int)AtomicOrderingCABI::relaxed; - // case AtomicOrdering::Consume: // not specified yet - // return AtomicOrderingCABI::consume; + //case AtomicOrdering::Consume: // not specified yet + // return AtomicOrderingCABI::consume; case AtomicOrdering::Acquire: return (int)AtomicOrderingCABI::acquire; case AtomicOrdering::Release: @@ -153,7 +170,7 @@ static Function * checkCDSPassInterfaceFunction(Constant *FuncOrBitcast) { if (isa(FuncOrBitcast)) return cast(FuncOrBitcast); FuncOrBitcast->print(errs()); - errs() << '\n'; + errs() << "\n"; std::string Err; raw_string_ostream Stream(Err); Stream << "CDSPass interface function redefined: " << *FuncOrBitcast; @@ -172,9 +189,9 @@ namespace { void initializeCallbacks(Module &M); bool instrumentLoadOrStore(Instruction *I, const DataLayout &DL); bool instrumentVolatile(Instruction *I, const DataLayout &DL); - bool isAtomicCall(Instruction *I); + bool instrumentMemIntrinsic(Instruction *I); bool instrumentAtomic(Instruction *I, const DataLayout &DL); - bool instrumentAtomicCall(CallInst *CI, const DataLayout &DL); + bool shouldInstrumentBeforeAtomics(Instruction *I); void chooseInstructionsToInstrument(SmallVectorImpl &Local, SmallVectorImpl &All, const DataLayout &DL); @@ -195,7 +212,8 @@ namespace { Function * CDSAtomicCAS_V1[kNumberOfAccessSizes]; Function * CDSAtomicCAS_V2[kNumberOfAccessSizes]; Function * CDSAtomicThreadFence; - Function * CDSCtorFunction; + Function * MemmoveFn, * MemcpyFn, * MemsetFn; + // Function * CDSCtorFunction; std::vector AtomicFuncNames; std::vector PartialAtomicFuncNames; @@ -208,8 +226,12 @@ StringRef CDSPass::getPassName() const { void CDSPass::initializeCallbacks(Module &M) { LLVMContext &Ctx = M.getContext(); + AttributeList Attr; + Attr = Attr.addAttribute(Ctx, AttributeList::FunctionIndex, + Attribute::NoUnwind); Type * Int1Ty = Type::getInt1Ty(Ctx); + Type * Int32Ty = Type::getInt32Ty(Ctx); OrdTy = Type::getInt32Ty(Ctx); Int8PtrTy = Type::getInt8PtrTy(Ctx); @@ -221,10 +243,10 @@ void CDSPass::initializeCallbacks(Module &M) { CDSFuncEntry = checkCDSPassInterfaceFunction( M.getOrInsertFunction("cds_func_entry", - VoidTy, Int8PtrTy)); + Attr, VoidTy, Int8PtrTy)); CDSFuncExit = checkCDSPassInterfaceFunction( M.getOrInsertFunction("cds_func_exit", - VoidTy, Int8PtrTy)); + Attr, VoidTy, Int8PtrTy)); // Get the function to call from our untime library. for (unsigned i = 0; i < kNumberOfAccessSizes; i++) { @@ -248,24 +270,24 @@ void CDSPass::initializeCallbacks(Module &M) { SmallString<32> AtomicStoreName("cds_atomic_store" + BitSizeStr); CDSLoad[i] = checkCDSPassInterfaceFunction( - M.getOrInsertFunction(LoadName, VoidTy, PtrTy)); + M.getOrInsertFunction(LoadName, Attr, VoidTy, Int8PtrTy)); CDSStore[i] = checkCDSPassInterfaceFunction( - M.getOrInsertFunction(StoreName, VoidTy, PtrTy)); + M.getOrInsertFunction(StoreName, Attr, VoidTy, Int8PtrTy)); CDSVolatileLoad[i] = checkCDSPassInterfaceFunction( M.getOrInsertFunction(VolatileLoadName, - Ty, PtrTy, Int8PtrTy)); + Attr, Ty, PtrTy, Int8PtrTy)); CDSVolatileStore[i] = checkCDSPassInterfaceFunction( M.getOrInsertFunction(VolatileStoreName, - VoidTy, PtrTy, Ty, Int8PtrTy)); + Attr, VoidTy, PtrTy, Ty, Int8PtrTy)); CDSAtomicInit[i] = checkCDSPassInterfaceFunction( M.getOrInsertFunction(AtomicInitName, - VoidTy, PtrTy, Ty, Int8PtrTy)); + Attr, VoidTy, PtrTy, Ty, Int8PtrTy)); CDSAtomicLoad[i] = checkCDSPassInterfaceFunction( M.getOrInsertFunction(AtomicLoadName, - Ty, PtrTy, OrdTy, Int8PtrTy)); + Attr, Ty, PtrTy, OrdTy, Int8PtrTy)); CDSAtomicStore[i] = checkCDSPassInterfaceFunction( M.getOrInsertFunction(AtomicStoreName, - VoidTy, PtrTy, Ty, OrdTy, Int8PtrTy)); + Attr, VoidTy, PtrTy, Ty, OrdTy, Int8PtrTy)); for (int op = AtomicRMWInst::FIRST_BINOP; op <= AtomicRMWInst::LAST_BINOP; ++op) { @@ -290,7 +312,7 @@ void CDSPass::initializeCallbacks(Module &M) { SmallString<32> AtomicRMWName("cds_atomic" + NamePart + BitSizeStr); CDSAtomicRMW[op][i] = checkCDSPassInterfaceFunction( M.getOrInsertFunction(AtomicRMWName, - Ty, PtrTy, Ty, OrdTy, Int8PtrTy)); + Attr, Ty, PtrTy, Ty, OrdTy, Int8PtrTy)); } // only supportes strong version @@ -298,15 +320,24 @@ void CDSPass::initializeCallbacks(Module &M) { SmallString<32> AtomicCASName_V2("cds_atomic_compare_exchange" + BitSizeStr + "_v2"); CDSAtomicCAS_V1[i] = checkCDSPassInterfaceFunction( M.getOrInsertFunction(AtomicCASName_V1, - Ty, PtrTy, Ty, Ty, OrdTy, OrdTy, Int8PtrTy)); + Attr, Ty, PtrTy, Ty, Ty, OrdTy, OrdTy, Int8PtrTy)); CDSAtomicCAS_V2[i] = checkCDSPassInterfaceFunction( M.getOrInsertFunction(AtomicCASName_V2, - Int1Ty, PtrTy, PtrTy, Ty, OrdTy, OrdTy, Int8PtrTy)); + Attr, Int1Ty, PtrTy, PtrTy, Ty, OrdTy, OrdTy, Int8PtrTy)); } CDSAtomicThreadFence = checkCDSPassInterfaceFunction( - M.getOrInsertFunction("cds_atomic_thread_fence", - VoidTy, OrdTy, Int8PtrTy)); + M.getOrInsertFunction("cds_atomic_thread_fence", Attr, VoidTy, OrdTy, Int8PtrTy)); + + MemmoveFn = checkCDSPassInterfaceFunction( + M.getOrInsertFunction("memmove", Attr, Int8PtrTy, Int8PtrTy, + Int8PtrTy, IntPtrTy)); + MemcpyFn = checkCDSPassInterfaceFunction( + M.getOrInsertFunction("memcpy", Attr, Int8PtrTy, Int8PtrTy, + Int8PtrTy, IntPtrTy)); + MemsetFn = checkCDSPassInterfaceFunction( + M.getOrInsertFunction("memset", Attr, Int8PtrTy, Int8PtrTy, + Int32Ty, IntPtrTy)); } bool CDSPass::doInitialization(Module &M) { @@ -396,6 +427,32 @@ bool CDSPass::addrPointsToConstantData(Value *Addr) { return false; } +bool CDSPass::shouldInstrumentBeforeAtomics(Instruction * Inst) { + if (LoadInst *LI = dyn_cast(Inst)) { + AtomicOrdering ordering = LI->getOrdering(); + if ( isAtLeastOrStrongerThan(ordering, AtomicOrdering::Acquire) ) + return true; + } else if (StoreInst *SI = dyn_cast(Inst)) { + AtomicOrdering ordering = SI->getOrdering(); + if ( isAtLeastOrStrongerThan(ordering, AtomicOrdering::Acquire) ) + return true; + } else if (AtomicRMWInst *RMWI = dyn_cast(Inst)) { + AtomicOrdering ordering = RMWI->getOrdering(); + if ( isAtLeastOrStrongerThan(ordering, AtomicOrdering::Acquire) ) + return true; + } else if (AtomicCmpXchgInst *CASI = dyn_cast(Inst)) { + AtomicOrdering ordering = CASI->getSuccessOrdering(); + if ( isAtLeastOrStrongerThan(ordering, AtomicOrdering::Acquire) ) + return true; + } else if (FenceInst *FI = dyn_cast(Inst)) { + AtomicOrdering ordering = FI->getOrdering(); + if ( isAtLeastOrStrongerThan(ordering, AtomicOrdering::Acquire) ) + return true; + } + + return false; +} + void CDSPass::chooseInstructionsToInstrument( SmallVectorImpl &Local, SmallVectorImpl &All, const DataLayout &DL) { @@ -449,28 +506,28 @@ void CDSPass::InsertRuntimeIgnores(Function &F) { }*/ bool CDSPass::runOnFunction(Function &F) { - if (F.getName() == "main") { - F.setName("user_main"); - errs() << "main replaced by user_main\n"; - } - initializeCallbacks( *F.getParent() ); SmallVector AllLoadsAndStores; SmallVector LocalLoadsAndStores; SmallVector VolatileLoadsAndStores; SmallVector AtomicAccesses; + SmallVector MemIntrinCalls; bool Res = false; - bool HasCall = false; bool HasAtomic = false; bool HasVolatile = false; const DataLayout &DL = F.getParent()->getDataLayout(); for (auto &BB : F) { for (auto &Inst : BB) { - if ( (&Inst)->isAtomic() || isAtomicCall(&Inst) ) { + if ( (&Inst)->isAtomic() ) { AtomicAccesses.push_back(&Inst); HasAtomic = true; + + if (shouldInstrumentBeforeAtomics(&Inst)) { + chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores, + DL); + } } else if (isa(Inst) || isa(Inst)) { LoadInst *LI = dyn_cast(&Inst); StoreInst *SI = dyn_cast(&Inst); @@ -482,15 +539,15 @@ bool CDSPass::runOnFunction(Function &F) { } else LocalLoadsAndStores.push_back(&Inst); } else if (isa(Inst) || isa(Inst)) { - /* TODO: To be added - if (CallInst *CI = dyn_cast(&Inst)) - maybeMarkSanitizerLibraryCallNoBuiltin(CI, TLI); if (isa(Inst)) MemIntrinCalls.push_back(&Inst); - HasCalls = true; + + /*if (CallInst *CI = dyn_cast(&Inst)) + maybeMarkSanitizerLibraryCallNoBuiltin(CI, TLI); + */ + chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores, DL); - */ } } @@ -509,13 +566,11 @@ bool CDSPass::runOnFunction(Function &F) { Res |= instrumentAtomic(Inst, DL); } - /* TODO for (auto Inst : MemIntrinCalls) { Res |= instrumentMemIntrinsic(Inst); } - */ - // Only instrument functions that contain atomics or volatiles + // Instrument function entry and exit for functions containing atomics or volatiles if (Res && ( HasAtomic || HasVolatile) ) { IRBuilder<> IRB(F.getEntryBlock().getFirstNonPHI()); /* Unused for now @@ -550,52 +605,46 @@ bool CDSPass::instrumentLoadOrStore(Instruction *I, // As such they cannot have regular uses like an instrumentation function and // it makes no sense to track them as memory. if (Addr->isSwiftError()) - return false; + return false; int Idx = getMemoryAccessFuncIndex(Addr, DL); if (Idx < 0) return false; -// not supported by CDS yet -/* if (IsWrite && isVtableAccess(I)) { - LLVM_DEBUG(dbgs() << " VPTR : " << *I << "\n"); - Value *StoredValue = cast(I)->getValueOperand(); - // StoredValue may be a vector type if we are storing several vptrs at once. - // In this case, just take the first element of the vector since this is - // enough to find vptr races. - if (isa(StoredValue->getType())) - StoredValue = IRB.CreateExtractElement( - StoredValue, ConstantInt::get(IRB.getInt32Ty(), 0)); - if (StoredValue->getType()->isIntegerTy()) - StoredValue = IRB.CreateIntToPtr(StoredValue, IRB.getInt8PtrTy()); - // Call TsanVptrUpdate. - IRB.CreateCall(TsanVptrUpdate, - {IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()), - IRB.CreatePointerCast(StoredValue, IRB.getInt8PtrTy())}); - NumInstrumentedVtableWrites++; - return true; - } - - if (!IsWrite && isVtableAccess(I)) { - IRB.CreateCall(TsanVptrLoad, - IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy())); - NumInstrumentedVtableReads++; - return true; - } -*/ - - Value *OnAccessFunc = nullptr; - OnAccessFunc = IsWrite ? CDSStore[Idx] : CDSLoad[Idx]; - - Type *ArgType = IRB.CreatePointerCast(Addr, Addr->getType())->getType(); + if (IsWrite && isVtableAccess(I)) { + /* TODO + LLVM_DEBUG(dbgs() << " VPTR : " << *I << "\n"); + Value *StoredValue = cast(I)->getValueOperand(); + // StoredValue may be a vector type if we are storing several vptrs at once. + // In this case, just take the first element of the vector since this is + // enough to find vptr races. + if (isa(StoredValue->getType())) + StoredValue = IRB.CreateExtractElement( + StoredValue, ConstantInt::get(IRB.getInt32Ty(), 0)); + if (StoredValue->getType()->isIntegerTy()) + StoredValue = IRB.CreateIntToPtr(StoredValue, IRB.getInt8PtrTy()); + // Call TsanVptrUpdate. + IRB.CreateCall(TsanVptrUpdate, + {IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()), + IRB.CreatePointerCast(StoredValue, IRB.getInt8PtrTy())}); + NumInstrumentedVtableWrites++; + */ + return true; + } - if ( ArgType != Int8PtrTy && ArgType != Int16PtrTy && - ArgType != Int32PtrTy && ArgType != Int64PtrTy ) { - // if other types of load or stores are passed in - return false; + if (!IsWrite && isVtableAccess(I)) { + /* TODO + IRB.CreateCall(TsanVptrLoad, + IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy())); + NumInstrumentedVtableReads++; + */ + return true; } - IRB.CreateCall(OnAccessFunc, IRB.CreatePointerCast(Addr, Addr->getType())); + // TODO: unaligned reads and writes + Value *OnAccessFunc = nullptr; + OnAccessFunc = IsWrite ? CDSStore[Idx] : CDSLoad[Idx]; + IRB.CreateCall(OnAccessFunc, IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy())); if (IsWrite) NumInstrumentedWrites++; else NumInstrumentedReads++; return true; @@ -606,26 +655,34 @@ bool CDSPass::instrumentVolatile(Instruction * I, const DataLayout &DL) { Value *position = getPosition(I, IRB); if (LoadInst *LI = dyn_cast(I)) { - assert( LI->isVolatile() ); Value *Addr = LI->getPointerOperand(); int Idx=getMemoryAccessFuncIndex(Addr, DL); if (Idx < 0) return false; + const unsigned ByteSize = 1U << Idx; + const unsigned BitSize = ByteSize * 8; + Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize); + Type *PtrTy = Ty->getPointerTo(); + Value *Args[] = {IRB.CreatePointerCast(Addr, PtrTy), position}; - Value *args[] = {Addr, position}; - Instruction* funcInst = CallInst::Create(CDSVolatileLoad[Idx], args); - ReplaceInstWithInst(LI, funcInst); + Type *OrigTy = cast(Addr->getType())->getElementType(); + Value *C = IRB.CreateCall(CDSVolatileLoad[Idx], Args); + Value *Cast = IRB.CreateBitOrPointerCast(C, OrigTy); + I->replaceAllUsesWith(Cast); } else if (StoreInst *SI = dyn_cast(I)) { - assert( SI->isVolatile() ); Value *Addr = SI->getPointerOperand(); int Idx=getMemoryAccessFuncIndex(Addr, DL); if (Idx < 0) return false; - - Value *val = SI->getValueOperand(); - Value *args[] = {Addr, val, position}; - Instruction* funcInst = CallInst::Create(CDSVolatileStore[Idx], args); - ReplaceInstWithInst(SI, funcInst); + const unsigned ByteSize = 1U << Idx; + const unsigned BitSize = ByteSize * 8; + Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize); + Type *PtrTy = Ty->getPointerTo(); + Value *Args[] = {IRB.CreatePointerCast(Addr, PtrTy), + IRB.CreateBitOrPointerCast(SI->getValueOperand(), Ty), + position}; + CallInst *C = CallInst::Create(CDSVolatileStore[Idx], Args); + ReplaceInstWithInst(I, C); } else { return false; } @@ -633,13 +690,28 @@ bool CDSPass::instrumentVolatile(Instruction * I, const DataLayout &DL) { return true; } -bool CDSPass::instrumentAtomic(Instruction * I, const DataLayout &DL) { +bool CDSPass::instrumentMemIntrinsic(Instruction *I) { IRBuilder<> IRB(I); - - if (auto *CI = dyn_cast(I)) { - return instrumentAtomicCall(CI, DL); + if (MemSetInst *M = dyn_cast(I)) { + IRB.CreateCall( + MemsetFn, + {IRB.CreatePointerCast(M->getArgOperand(0), IRB.getInt8PtrTy()), + IRB.CreateIntCast(M->getArgOperand(1), IRB.getInt32Ty(), false), + IRB.CreateIntCast(M->getArgOperand(2), IntPtrTy, false)}); + I->eraseFromParent(); + } else if (MemTransferInst *M = dyn_cast(I)) { + IRB.CreateCall( + isa(M) ? MemcpyFn : MemmoveFn, + {IRB.CreatePointerCast(M->getArgOperand(0), IRB.getInt8PtrTy()), + IRB.CreatePointerCast(M->getArgOperand(1), IRB.getInt8PtrTy()), + IRB.CreateIntCast(M->getArgOperand(2), IntPtrTy, false)}); + I->eraseFromParent(); } + return false; +} +bool CDSPass::instrumentAtomic(Instruction * I, const DataLayout &DL) { + IRBuilder<> IRB(I); Value *position = getPosition(I, IRB); if (LoadInst *LI = dyn_cast(I)) { @@ -650,8 +722,8 @@ bool CDSPass::instrumentAtomic(Instruction * I, const DataLayout &DL) { int atomic_order_index = getAtomicOrderIndex(LI->getOrdering()); Value *order = ConstantInt::get(OrdTy, atomic_order_index); - Value *args[] = {Addr, order, position}; - Instruction* funcInst = CallInst::Create(CDSAtomicLoad[Idx], args); + Value *Args[] = {Addr, order, position}; + Instruction* funcInst = CallInst::Create(CDSAtomicLoad[Idx], Args); ReplaceInstWithInst(LI, funcInst); } else if (StoreInst *SI = dyn_cast(I)) { Value *Addr = SI->getPointerOperand(); @@ -662,8 +734,8 @@ bool CDSPass::instrumentAtomic(Instruction * I, const DataLayout &DL) { int atomic_order_index = getAtomicOrderIndex(SI->getOrdering()); Value *val = SI->getValueOperand(); Value *order = ConstantInt::get(OrdTy, atomic_order_index); - Value *args[] = {Addr, val, order, position}; - Instruction* funcInst = CallInst::Create(CDSAtomicStore[Idx], args); + Value *Args[] = {Addr, val, order, position}; + Instruction* funcInst = CallInst::Create(CDSAtomicStore[Idx], Args); ReplaceInstWithInst(SI, funcInst); } else if (AtomicRMWInst *RMWI = dyn_cast(I)) { Value *Addr = RMWI->getPointerOperand(); @@ -674,8 +746,8 @@ bool CDSPass::instrumentAtomic(Instruction * I, const DataLayout &DL) { int atomic_order_index = getAtomicOrderIndex(RMWI->getOrdering()); Value *val = RMWI->getValOperand(); Value *order = ConstantInt::get(OrdTy, atomic_order_index); - Value *args[] = {Addr, val, order, position}; - Instruction* funcInst = CallInst::Create(CDSAtomicRMW[RMWI->getOperation()][Idx], args); + Value *Args[] = {Addr, val, order, position}; + Instruction* funcInst = CallInst::Create(CDSAtomicRMW[RMWI->getOperation()][Idx], Args); ReplaceInstWithInst(RMWI, funcInst); } else if (AtomicCmpXchgInst *CASI = dyn_cast(I)) { IRBuilder<> IRB(CASI); @@ -730,306 +802,6 @@ bool CDSPass::instrumentAtomic(Instruction * I, const DataLayout &DL) { return true; } -bool CDSPass::isAtomicCall(Instruction *I) { - if ( auto *CI = dyn_cast(I) ) { - Function *fun = CI->getCalledFunction(); - if (fun == NULL) - return false; - - StringRef funName = fun->getName(); - - // todo: come up with better rules for function name checking - for (StringRef name : AtomicFuncNames) { - if ( funName.contains(name) ) - return true; - } - - for (StringRef PartialName : PartialAtomicFuncNames) { - if (funName.contains(PartialName) && - funName.contains("atomic") ) - return true; - } - } - - return false; -} - -bool CDSPass::instrumentAtomicCall(CallInst *CI, const DataLayout &DL) { - IRBuilder<> IRB(CI); - Function *fun = CI->getCalledFunction(); - StringRef funName = fun->getName(); - std::vector parameters; - - User::op_iterator begin = CI->arg_begin(); - User::op_iterator end = CI->arg_end(); - for (User::op_iterator it = begin; it != end; ++it) { - Value *param = *it; - parameters.push_back(param); - } - - // obtain source line number of the CallInst - Value *position = getPosition(CI, IRB); - - // the pointer to the address is always the first argument - Value *OrigPtr = parameters[0]; - - int Idx = getMemoryAccessFuncIndex(OrigPtr, DL); - if (Idx < 0) - return false; - - const unsigned ByteSize = 1U << Idx; - const unsigned BitSize = ByteSize * 8; - Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize); - Type *PtrTy = Ty->getPointerTo(); - - // atomic_init; args = {obj, order} - if (funName.contains("atomic_init")) { - Value *OrigVal = parameters[1]; - - Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy); - Value *val; - if (OrigVal->getType()->isPtrOrPtrVectorTy()) - val = IRB.CreatePointerCast(OrigVal, Ty); - else - val = IRB.CreateIntCast(OrigVal, Ty, true); - - Value *args[] = {ptr, val, position}; - - Instruction* funcInst = CallInst::Create(CDSAtomicInit[Idx], args); - ReplaceInstWithInst(CI, funcInst); - - return true; - } - - // atomic_load; args = {obj, order} - if (funName.contains("atomic_load")) { - bool isExplicit = funName.contains("atomic_load_explicit"); - - Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy); - Value *order; - if (isExplicit) - order = IRB.CreateBitOrPointerCast(parameters[1], OrdTy); - else - order = ConstantInt::get(OrdTy, - (int) AtomicOrderingCABI::seq_cst); - Value *args[] = {ptr, order, position}; - - Instruction* funcInst = CallInst::Create(CDSAtomicLoad[Idx], args); - ReplaceInstWithInst(CI, funcInst); - - return true; - } else if (funName.contains("atomic") && - funName.contains("load") ) { - // does this version of call always have an atomic order as an argument? - Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy); - Value *order = IRB.CreateBitOrPointerCast(parameters[1], OrdTy); - Value *args[] = {ptr, order, position}; - - if (!CI->getType()->isPointerTy()) { - return false; - } - - CallInst *funcInst = IRB.CreateCall(CDSAtomicLoad[Idx], args); - Value *RetVal = IRB.CreateIntToPtr(funcInst, CI->getType()); - - CI->replaceAllUsesWith(RetVal); - CI->eraseFromParent(); - - return true; - } - - // atomic_store; args = {obj, val, order} - if (funName.contains("atomic_store")) { - bool isExplicit = funName.contains("atomic_store_explicit"); - Value *OrigVal = parameters[1]; - - Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy); - Value *val = IRB.CreatePointerCast(OrigVal, Ty); - Value *order; - if (isExplicit) - order = IRB.CreateBitOrPointerCast(parameters[2], OrdTy); - else - order = ConstantInt::get(OrdTy, - (int) AtomicOrderingCABI::seq_cst); - Value *args[] = {ptr, val, order, position}; - - Instruction* funcInst = CallInst::Create(CDSAtomicStore[Idx], args); - ReplaceInstWithInst(CI, funcInst); - - return true; - } else if (funName.contains("atomic") && - funName.contains("store") ) { - // does this version of call always have an atomic order as an argument? - Value *OrigVal = parameters[1]; - - Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy); - Value *val; - if (OrigVal->getType()->isPtrOrPtrVectorTy()) - val = IRB.CreatePointerCast(OrigVal, Ty); - else - val = IRB.CreateIntCast(OrigVal, Ty, true); - - Value *order = IRB.CreateBitOrPointerCast(parameters[2], OrdTy); - Value *args[] = {ptr, val, order, position}; - - Instruction* funcInst = CallInst::Create(CDSAtomicStore[Idx], args); - ReplaceInstWithInst(CI, funcInst); - - return true; - } - - // atomic_fetch_*; args = {obj, val, order} - if (funName.contains("atomic_fetch_") || - funName.contains("atomic_exchange")) { - - /* TODO: implement stricter function name checking */ - if (funName.contains("non")) - return false; - - bool isExplicit = funName.contains("_explicit"); - Value *OrigVal = parameters[1]; - - int op; - if ( funName.contains("_fetch_add") ) - op = AtomicRMWInst::Add; - else if ( funName.contains("_fetch_sub") ) - op = AtomicRMWInst::Sub; - else if ( funName.contains("_fetch_and") ) - op = AtomicRMWInst::And; - else if ( funName.contains("_fetch_or") ) - op = AtomicRMWInst::Or; - else if ( funName.contains("_fetch_xor") ) - op = AtomicRMWInst::Xor; - else if ( funName.contains("atomic_exchange") ) - op = AtomicRMWInst::Xchg; - else { - errs() << "Unknown atomic read-modify-write operation\n"; - return false; - } - - Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy); - Value *val; - if (OrigVal->getType()->isPtrOrPtrVectorTy()) - val = IRB.CreatePointerCast(OrigVal, Ty); - else - val = IRB.CreateIntCast(OrigVal, Ty, true); - - Value *order; - if (isExplicit) - order = IRB.CreateBitOrPointerCast(parameters[2], OrdTy); - else - order = ConstantInt::get(OrdTy, - (int) AtomicOrderingCABI::seq_cst); - Value *args[] = {ptr, val, order, position}; - - Instruction* funcInst = CallInst::Create(CDSAtomicRMW[op][Idx], args); - ReplaceInstWithInst(CI, funcInst); - - return true; - } else if (funName.contains("fetch")) { - errs() << "atomic fetch captured. Not implemented yet. "; - errs() << "See source file :"; - getPosition(CI, IRB, true); - return false; - } else if (funName.contains("exchange") && - !funName.contains("compare_exchange") ) { - if (CI->getType()->isPointerTy()) { - // Can not deal with this now - errs() << "atomic exchange captured. Not implemented yet. "; - errs() << "See source file :"; - getPosition(CI, IRB, true); - - return false; - } - - Value *OrigVal = parameters[1]; - - Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy); - Value *val; - if (OrigVal->getType()->isPtrOrPtrVectorTy()) - val = IRB.CreatePointerCast(OrigVal, Ty); - else - val = IRB.CreateIntCast(OrigVal, Ty, true); - - Value *order = IRB.CreateBitOrPointerCast(parameters[2], OrdTy); - Value *args[] = {ptr, val, order, position}; - int op = AtomicRMWInst::Xchg; - - Instruction* funcInst = CallInst::Create(CDSAtomicRMW[op][Idx], args); - ReplaceInstWithInst(CI, funcInst); - } - - /* atomic_compare_exchange_*; - args = {obj, expected, new value, order1, order2} - */ - if ( funName.contains("atomic_compare_exchange_") ) { - bool isExplicit = funName.contains("_explicit"); - - Value *Addr = IRB.CreatePointerCast(OrigPtr, PtrTy); - Value *CmpOperand = IRB.CreatePointerCast(parameters[1], PtrTy); - Value *NewOperand = IRB.CreateBitOrPointerCast(parameters[2], Ty); - - Value *order_succ, *order_fail; - if (isExplicit) { - order_succ = IRB.CreateBitOrPointerCast(parameters[3], OrdTy); - - if (parameters.size() > 4) { - order_fail = IRB.CreateBitOrPointerCast(parameters[4], OrdTy); - } else { - /* The failure order is not provided */ - order_fail = order_succ; - ConstantInt * order_succ_cast = dyn_cast(order_succ); - int index = order_succ_cast->getSExtValue(); - - order_fail = ConstantInt::get(OrdTy, - AtomicCasFailureOrderIndex(index)); - } - } else { - order_succ = ConstantInt::get(OrdTy, - (int) AtomicOrderingCABI::seq_cst); - order_fail = ConstantInt::get(OrdTy, - (int) AtomicOrderingCABI::seq_cst); - } - - Value *args[] = {Addr, CmpOperand, NewOperand, - order_succ, order_fail, position}; - - Instruction* funcInst = CallInst::Create(CDSAtomicCAS_V2[Idx], args); - ReplaceInstWithInst(CI, funcInst); - - return true; - } else if ( funName.contains("compare_exchange_strong") || - funName.contains("compare_exchange_weak") ) { - Value *Addr = IRB.CreatePointerCast(OrigPtr, PtrTy); - Value *CmpOperand = IRB.CreatePointerCast(parameters[1], PtrTy); - Value *NewOperand = IRB.CreateBitOrPointerCast(parameters[2], Ty); - - Value *order_succ, *order_fail; - order_succ = IRB.CreateBitOrPointerCast(parameters[3], OrdTy); - - if (parameters.size() > 4) { - order_fail = IRB.CreateBitOrPointerCast(parameters[4], OrdTy); - } else { - /* The failure order is not provided */ - order_fail = order_succ; - ConstantInt * order_succ_cast = dyn_cast(order_succ); - int index = order_succ_cast->getSExtValue(); - - order_fail = ConstantInt::get(OrdTy, - AtomicCasFailureOrderIndex(index)); - } - - Value *args[] = {Addr, CmpOperand, NewOperand, - order_succ, order_fail, position}; - Instruction* funcInst = CallInst::Create(CDSAtomicCAS_V2[Idx], args); - ReplaceInstWithInst(CI, funcInst); - - return true; - } - - return false; -} - int CDSPass::getMemoryAccessFuncIndex(Value *Addr, const DataLayout &DL) { Type *OrigPtrTy = Addr->getType(); @@ -1050,7 +822,6 @@ int CDSPass::getMemoryAccessFuncIndex(Value *Addr, return Idx; } - char CDSPass::ID = 0; // Automatically enable the pass.