#define DEBUG_TYPE "CDS"
#include <llvm/IR/DebugLoc.h>
-static inline Value *getPosition( Instruction * I, IRBuilder <> IRB, bool print = false)
+Value *getPosition( Instruction * I, IRBuilder <> &IRB, bool print = false)
{
const DebugLoc & debug_location = I->getDebugLoc ();
std::string position_string;
/* The original function checkSanitizerInterfaceFunction was defined
* in llvm/Transforms/Utils/ModuleUtils.h
*/
-static Function * checkCDSPassInterfaceFunction(Constant *FuncOrBitcast) {
+static Function * checkCDSPassInterfaceFunction(Value *FuncOrBitcast) {
if (isa<Function>(FuncOrBitcast))
return cast<Function>(FuncOrBitcast);
FuncOrBitcast->print(errs());
bool instrumentLoadOrStore(Instruction *I, const DataLayout &DL);
bool instrumentVolatile(Instruction *I, const DataLayout &DL);
bool instrumentMemIntrinsic(Instruction *I);
- bool isAtomicCall(Instruction *I);
bool instrumentAtomic(Instruction *I, const DataLayout &DL);
- bool instrumentAtomicCall(CallInst *CI, const DataLayout &DL);
bool shouldInstrumentBeforeAtomics(Instruction *I);
void chooseInstructionsToInstrument(SmallVectorImpl<Instruction *> &Local,
SmallVectorImpl<Instruction *> &All,
const DataLayout &DL);
bool addrPointsToConstantData(Value *Addr);
int getMemoryAccessFuncIndex(Value *Addr, const DataLayout &DL);
- bool instrumentLoops(Function &F);
Function * CDSFuncEntry;
Function * CDSFuncExit;
CDSFuncEntry = checkCDSPassInterfaceFunction(
M.getOrInsertFunction("cds_func_entry",
- Attr, VoidTy, Int8PtrTy));
+ Attr, VoidTy, Int8PtrTy).getCallee());
CDSFuncExit = checkCDSPassInterfaceFunction(
M.getOrInsertFunction("cds_func_exit",
- Attr, VoidTy, Int8PtrTy));
+ Attr, VoidTy, Int8PtrTy).getCallee());
// Get the function to call from our untime library.
for (unsigned i = 0; i < kNumberOfAccessSizes; i++) {
SmallString<32> AtomicStoreName("cds_atomic_store" + BitSizeStr);
CDSLoad[i] = checkCDSPassInterfaceFunction(
- M.getOrInsertFunction(LoadName, Attr, VoidTy, PtrTy));
+ M.getOrInsertFunction(LoadName, Attr, VoidTy, Int8PtrTy).getCallee());
CDSStore[i] = checkCDSPassInterfaceFunction(
- M.getOrInsertFunction(StoreName, Attr, VoidTy, PtrTy));
+ M.getOrInsertFunction(StoreName, Attr, VoidTy, Int8PtrTy).getCallee());
CDSVolatileLoad[i] = checkCDSPassInterfaceFunction(
M.getOrInsertFunction(VolatileLoadName,
- Attr, Ty, PtrTy, Int8PtrTy));
+ Attr, Ty, PtrTy, Int8PtrTy).getCallee());
CDSVolatileStore[i] = checkCDSPassInterfaceFunction(
M.getOrInsertFunction(VolatileStoreName,
- Attr, VoidTy, PtrTy, Ty, Int8PtrTy));
+ Attr, VoidTy, PtrTy, Ty, Int8PtrTy).getCallee());
CDSAtomicInit[i] = checkCDSPassInterfaceFunction(
M.getOrInsertFunction(AtomicInitName,
- Attr, VoidTy, PtrTy, Ty, Int8PtrTy));
+ Attr, VoidTy, PtrTy, Ty, Int8PtrTy).getCallee());
CDSAtomicLoad[i] = checkCDSPassInterfaceFunction(
M.getOrInsertFunction(AtomicLoadName,
- Attr, Ty, PtrTy, OrdTy, Int8PtrTy));
+ Attr, Ty, PtrTy, OrdTy, Int8PtrTy).getCallee());
CDSAtomicStore[i] = checkCDSPassInterfaceFunction(
M.getOrInsertFunction(AtomicStoreName,
- Attr, VoidTy, PtrTy, Ty, OrdTy, Int8PtrTy));
+ Attr, VoidTy, PtrTy, Ty, OrdTy, Int8PtrTy).getCallee());
- for (int op = AtomicRMWInst::FIRST_BINOP;
+ for (unsigned op = AtomicRMWInst::FIRST_BINOP;
op <= AtomicRMWInst::LAST_BINOP; ++op) {
CDSAtomicRMW[op][i] = nullptr;
std::string NamePart;
SmallString<32> AtomicRMWName("cds_atomic" + NamePart + BitSizeStr);
CDSAtomicRMW[op][i] = checkCDSPassInterfaceFunction(
M.getOrInsertFunction(AtomicRMWName,
- Attr, Ty, PtrTy, Ty, OrdTy, Int8PtrTy));
+ Attr, Ty, PtrTy, Ty, OrdTy, Int8PtrTy).getCallee());
}
// only supportes strong version
SmallString<32> AtomicCASName_V2("cds_atomic_compare_exchange" + BitSizeStr + "_v2");
CDSAtomicCAS_V1[i] = checkCDSPassInterfaceFunction(
M.getOrInsertFunction(AtomicCASName_V1,
- Attr, Ty, PtrTy, Ty, Ty, OrdTy, OrdTy, Int8PtrTy));
+ Attr, Ty, PtrTy, Ty, Ty, OrdTy, OrdTy, Int8PtrTy).getCallee());
CDSAtomicCAS_V2[i] = checkCDSPassInterfaceFunction(
M.getOrInsertFunction(AtomicCASName_V2,
- Attr, Int1Ty, PtrTy, PtrTy, Ty, OrdTy, OrdTy, Int8PtrTy));
+ Attr, Int1Ty, PtrTy, PtrTy, Ty, OrdTy, OrdTy, Int8PtrTy).getCallee());
}
CDSAtomicThreadFence = checkCDSPassInterfaceFunction(
- M.getOrInsertFunction("cds_atomic_thread_fence", Attr, VoidTy, OrdTy, Int8PtrTy));
+ M.getOrInsertFunction("cds_atomic_thread_fence", Attr, VoidTy, OrdTy, Int8PtrTy).getCallee());
MemmoveFn = checkCDSPassInterfaceFunction(
M.getOrInsertFunction("memmove", Attr, Int8PtrTy, Int8PtrTy,
- Int8PtrTy, IntPtrTy));
+ Int8PtrTy, IntPtrTy).getCallee());
MemcpyFn = checkCDSPassInterfaceFunction(
M.getOrInsertFunction("memcpy", Attr, Int8PtrTy, Int8PtrTy,
- Int8PtrTy, IntPtrTy));
+ Int8PtrTy, IntPtrTy).getCallee());
MemsetFn = checkCDSPassInterfaceFunction(
M.getOrInsertFunction("memset", Attr, Int8PtrTy, Int8PtrTy,
- Int32Ty, IntPtrTy));
+ Int32Ty, IntPtrTy).getCallee());
}
bool CDSPass::doInitialization(Module &M) {
Value *Addr = isa<StoreInst>(*I)
? cast<StoreInst>(I)->getPointerOperand()
: cast<LoadInst>(I)->getPointerOperand();
- if (isa<AllocaInst>(GetUnderlyingObject(Addr, DL)) &&
+ if (isa<AllocaInst>(getUnderlyingObject(Addr)) &&
!PointerMayBeCaptured(Addr, true, true)) {
// The variable is addressable but not captured, so it cannot be
// referenced from a different thread and participate in a data race
bool HasVolatile = false;
const DataLayout &DL = F.getParent()->getDataLayout();
- // instrumentLoops(F);
-
for (auto &BB : F) {
for (auto &Inst : BB) {
if ( (&Inst)->isAtomic() ) {
chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores,
DL);
}
- } else if (isAtomicCall(&Inst) ) {
- AtomicAccesses.push_back(&Inst);
- HasAtomic = true;
- chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores,
- DL);
} else if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst)) {
LoadInst *LI = dyn_cast<LoadInst>(&Inst);
StoreInst *SI = dyn_cast<StoreInst>(&Inst);
}
// TODO: unaligned reads and writes
-
- Value *OnAccessFunc = nullptr;
+ FunctionCallee OnAccessFunc = nullptr;
OnAccessFunc = IsWrite ? CDSStore[Idx] : CDSLoad[Idx];
-
- Type *ArgType = IRB.CreatePointerCast(Addr, Addr->getType())->getType();
-
- if ( ArgType != Int8PtrTy && ArgType != Int16PtrTy &&
- ArgType != Int32PtrTy && ArgType != Int64PtrTy ) {
- // if other types of load or stores are passed in
- return false;
- }
-
- IRB.CreateCall(OnAccessFunc, IRB.CreatePointerCast(Addr, Addr->getType()));
+ IRB.CreateCall(OnAccessFunc, IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()));
if (IsWrite) NumInstrumentedWrites++;
else NumInstrumentedReads++;
return true;
bool CDSPass::instrumentVolatile(Instruction * I, const DataLayout &DL) {
IRBuilder<> IRB(I);
- const unsigned ByteSize = 1U << Idx;
- const unsigned BitSize = ByteSize * 8;
- Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize);
- Type *PtrTy = Ty->getPointerTo();
Value *position = getPosition(I, IRB);
if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
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};
+
Type *OrigTy = cast<PointerType>(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<StoreInst>(I)) {
- assert( SI->isVolatile() );
Value *Addr = SI->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),
IRB.CreateBitOrPointerCast(SI->getValueOperand(), Ty),
position};
bool CDSPass::instrumentAtomic(Instruction * I, const DataLayout &DL) {
IRBuilder<> IRB(I);
- if (auto *CI = dyn_cast<CallInst>(I)) {
- return instrumentAtomicCall(CI, DL);
- }
-
Value *position = getPosition(I, IRB);
if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
Value *Addr = LI->getPointerOperand();
return true;
}
-bool CDSPass::isAtomicCall(Instruction *I) {
- if ( auto *CI = dyn_cast<CallInst>(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<Value *> 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};
-
- if (!checkSignature(CDSAtomicInit[Idx], args))
- return false;
-
- 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};
-
- if (!checkSignature(CDSAtomicLoad[Idx], args))
- return false;
-
- 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};
-
- // Without this check, gdax does not compile :(
- if (!CI->getType()->isPointerTy()) {
- return false;
- }
-
- if (!checkSignature(CDSAtomicLoad[Idx], args))
- 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};
-
- if (!checkSignature(CDSAtomicStore[Idx], args))
- return false;
-
- 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?
- if (parameters.size() < 3)
- 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};
-
- if (!checkSignature(CDSAtomicStore[Idx], args))
- return false;
-
- 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")) {
-
- 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};
-
- if (!checkSignature(CDSAtomicRMW[op][Idx], args))
- return false;
-
- 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()) {
- /**
- * TODO: instrument the following case
- * mcs-lock.h
- * std::atomic<struct T *> m_tail;
- * struct T * me;
- * struct T * pred = m_tail.exchange(me, memory_order_*);
- */
- 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;
-
- if (!checkSignature(CDSAtomicRMW[op][Idx], args))
- return false;
-
- Instruction* funcInst = CallInst::Create(CDSAtomicRMW[op][Idx], args);
- ReplaceInstWithInst(CI, funcInst);
-
- return true;
- }
-
- /* 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<ConstantInt>(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};
-
- if (!checkSignature(CDSAtomicCAS_V2[Idx], args))
- return false;
-
- 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<ConstantInt>(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};
-
- if (!checkSignature(CDSAtomicCAS_V2[Idx], args))
- return false;
-
- 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();
return Idx;
}
-bool CDSPass::instrumentLoops(Function &F)
-{
- DominatorTree DT(F);
- LoopInfo LI(DT);
-
- SmallVector<Loop *, 4> Loops = LI.getLoopsInPreorder();
- bool instrumented = false;
-
- // Do a post-order traversal of the loops so that counter updates can be
- // iteratively hoisted outside the loop nest.
- for (auto *Loop : llvm::reverse(Loops)) {
- bool instrument_loop = false;
-
- // Iterator over loop blocks and search for atomics and volatiles
- Loop::block_iterator it;
- for (it = Loop->block_begin(); it != Loop->block_end(); it++) {
- BasicBlock * block = *it;
- for (auto &Inst : *block) {
- if ( (&Inst)->isAtomic() ) {
- instrument_loop = true;
- break;
- } else if (isAtomicCall(&Inst)) {
- instrument_loop = true;
- break;
- } else if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst)) {
- LoadInst *LI = dyn_cast<LoadInst>(&Inst);
- StoreInst *SI = dyn_cast<StoreInst>(&Inst);
- bool isVolatile = ( LI ? LI->isVolatile() : SI->isVolatile() );
-
- if (isVolatile) {
- instrument_loop = true;
- break;
- }
- }
- }
-
- if (instrument_loop)
- break;
- }
-
- if (instrument_loop) {
- // TODO: what to instrument?
- errs() << "Function: " << F.getName() << "\n";
- BasicBlock * header = Loop->getHeader();
- header->dump();
-
- instrumented = true;
- }
- }
-
- return instrumented;
-}
-
char CDSPass::ID = 0;
// Automatically enable the pass.