static uint64_t getPointerSize(const Value *V, AliasAnalysis &AA) { uint64_t Size; if (getObjectSize(V, Size, AA.getDataLayout(), AA.getTargetLibraryInfo())) return Size; else { return AA.getTypeStoreSize(V->getType()); } }
/// getLocForWrite - Return a Location stored to by the specified instruction. /// If isRemovable returns true, this function and getLocForRead completely /// describe the memory operations for this instruction. static AliasAnalysis::Location getLocForWrite(Instruction *Inst, AliasAnalysis &AA) { if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) return AA.getLocation(SI); if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(Inst)) { // memcpy/memmove/memset. AliasAnalysis::Location Loc = AA.getLocationForDest(MI); // If we don't have target data around, an unknown size in Location means // that we should use the size of the pointee type. This isn't valid for // memset/memcpy, which writes more than an i8. if (Loc.Size == AliasAnalysis::UnknownSize && AA.getDataLayout() == 0) return AliasAnalysis::Location(); return Loc; } IntrinsicInst *II = dyn_cast<IntrinsicInst>(Inst); if (II == 0) return AliasAnalysis::Location(); switch (II->getIntrinsicID()) { default: return AliasAnalysis::Location(); // Unhandled intrinsic. case Intrinsic::init_trampoline: // If we don't have target data around, an unknown size in Location means // that we should use the size of the pointee type. This isn't valid for // init.trampoline, which writes more than an i8. if (AA.getDataLayout() == 0) return AliasAnalysis::Location(); // FIXME: We don't know the size of the trampoline, so we can't really // handle it here. return AliasAnalysis::Location(II->getArgOperand(0)); case Intrinsic::lifetime_end: { uint64_t Len = cast<ConstantInt>(II->getArgOperand(0))->getZExtValue(); return AliasAnalysis::Location(II->getArgOperand(1), Len); } } }
/// isOverwrite - Return 'OverwriteComplete' if a store to the 'Later' location /// completely overwrites a store to the 'Earlier' location. /// 'OverwriteEnd' if the end of the 'Earlier' location is completely /// overwritten by 'Later', or 'OverwriteUnknown' if nothing can be determined static OverwriteResult isOverwrite(const AliasAnalysis::Location &Later, const AliasAnalysis::Location &Earlier, AliasAnalysis &AA, int64_t &EarlierOff, int64_t &LaterOff) { const DataLayout *DL = AA.getDataLayout(); const Value *P1 = Earlier.Ptr->stripPointerCasts(); const Value *P2 = Later.Ptr->stripPointerCasts(); // If the start pointers are the same, we just have to compare sizes to see if // the later store was larger than the earlier store. if (P1 == P2) { // If we don't know the sizes of either access, then we can't do a // comparison. if (Later.Size == AliasAnalysis::UnknownSize || Earlier.Size == AliasAnalysis::UnknownSize) return OverwriteUnknown; // Make sure that the Later size is >= the Earlier size. if (Later.Size >= Earlier.Size) return OverwriteComplete; } // Otherwise, we have to have size information, and the later store has to be // larger than the earlier one. if (Later.Size == AliasAnalysis::UnknownSize || Earlier.Size == AliasAnalysis::UnknownSize || DL == nullptr) return OverwriteUnknown; // Check to see if the later store is to the entire object (either a global, // an alloca, or a byval/inalloca argument). If so, then it clearly // overwrites any other store to the same object. const Value *UO1 = GetUnderlyingObject(P1, DL), *UO2 = GetUnderlyingObject(P2, DL); // If we can't resolve the same pointers to the same object, then we can't // analyze them at all. if (UO1 != UO2) return OverwriteUnknown; // If the "Later" store is to a recognizable object, get its size. uint64_t ObjectSize = getPointerSize(UO2, AA); if (ObjectSize != AliasAnalysis::UnknownSize) if (ObjectSize == Later.Size && ObjectSize >= Earlier.Size) return OverwriteComplete; // Okay, we have stores to two completely different pointers. Try to // decompose the pointer into a "base + constant_offset" form. If the base // pointers are equal, then we can reason about the two stores. EarlierOff = 0; LaterOff = 0; const Value *BP1 = GetPointerBaseWithConstantOffset(P1, EarlierOff, DL); const Value *BP2 = GetPointerBaseWithConstantOffset(P2, LaterOff, DL); // If the base pointers still differ, we have two completely different stores. if (BP1 != BP2) return OverwriteUnknown; // The later store completely overlaps the earlier store if: // // 1. Both start at the same offset and the later one's size is greater than // or equal to the earlier one's, or // // |--earlier--| // |-- later --| // // 2. The earlier store has an offset greater than the later offset, but which // still lies completely within the later store. // // |--earlier--| // |----- later ------| // // We have to be careful here as *Off is signed while *.Size is unsigned. if (EarlierOff >= LaterOff && Later.Size >= Earlier.Size && uint64_t(EarlierOff - LaterOff) + Earlier.Size <= Later.Size) return OverwriteComplete; // The other interesting case is if the later store overwrites the end of // the earlier store // // |--earlier--| // |-- later --| // // In this case we may want to trim the size of earlier to avoid generating // writes to addresses which will definitely be overwritten later if (LaterOff > EarlierOff && LaterOff < int64_t(EarlierOff + Earlier.Size) && int64_t(LaterOff + Later.Size) >= int64_t(EarlierOff + Earlier.Size)) return OverwriteEnd; // Otherwise, they don't completely overlap. return OverwriteUnknown; }
static uint64_t getPointerSize(const Value *V, AliasAnalysis &AA) { uint64_t Size; if (getObjectSize(V, Size, AA.getDataLayout(), AA.getTargetLibraryInfo())) return Size; return AliasAnalysis::UnknownSize; }
void Transformer4Trace::beforeTransform(Module* module, AliasAnalysis& AA) { // do not remove it, it is used in the macro ptrsize = AA.getDataLayout()->getPointerSize(); ///initialize functions // do not remove context, it is used in the macro FUNCTION_ARG_TYPE Module * m = module; LLVMContext& context = m->getContext(); F_init = cast<Function>(m->getOrInsertFunction("OnInit", FUNCTION_VOID_ARG_TYPE)); F_exit = cast<Function>(m->getOrInsertFunction("OnExit", FUNCTION_VOID_ARG_TYPE)); //F_thread_init = cast<Function>(m->getOrInsertFunction("OnThreadInit", FUNCTION_ARG_TYPE)); //F_thread_exit = cast<Function>(m->getOrInsertFunction("OnThreadExit", FUNCTION_ARG_TYPE)); F_preload = cast<Function>(m->getOrInsertFunction("OnPreLoad", FUNCTION_MEM_LN_ARG_TYPE)); F_load = cast<Function>(m->getOrInsertFunction("OnLoad", FUNCTION_MEM_LN_ARG_TYPE)); F_prestore = cast<Function>(m->getOrInsertFunction("OnPreStore", FUNCTION_MEM_LN_ARG_TYPE)); F_store = cast<Function>(m->getOrInsertFunction("OnStore", FUNCTION_MEM_LN_ARG_TYPE)); F_prelock = cast<Function>(m->getOrInsertFunction("OnPreLock", FUNCTION_MEM_LN_ARG_TYPE)); F_lock = cast<Function>(m->getOrInsertFunction("OnLock", FUNCTION_MEM_LN_ARG_TYPE)); F_preunlock = cast<Function>(m->getOrInsertFunction("OnPreUnlock", FUNCTION_MEM_LN_ARG_TYPE)); F_unlock = cast<Function>(m->getOrInsertFunction("OnUnlock", FUNCTION_MEM_LN_ARG_TYPE)); F_prefork = cast<Function>(m->getOrInsertFunction("OnPreFork", FUNCTION_MEM_LN_ARG_TYPE)); F_fork = cast<Function>(m->getOrInsertFunction("OnFork", FUNCTION_MEM_LN_ARG_TYPE)); F_prejoin = cast<Function>(m->getOrInsertFunction("OnPreJoin", FUNCTION_TID_LN_ARG_TYPE)); F_join = cast<Function>(m->getOrInsertFunction("OnJoin", FUNCTION_TID_LN_ARG_TYPE)); F_prenotify = cast<Function>(m->getOrInsertFunction("OnPreNotify", FUNCTION_2MEM_LN_ARG_TYPE)); F_notify = cast<Function>(m->getOrInsertFunction("OnNotify", FUNCTION_2MEM_LN_ARG_TYPE)); F_prewait = cast<Function>(m->getOrInsertFunction("OnPreWait", FUNCTION_2MEM_LN_ARG_TYPE)); F_wait = cast<Function>(m->getOrInsertFunction("OnWait", FUNCTION_2MEM_LN_ARG_TYPE)); if (debug()) { errs() << "Start Preprocessing...\n"; errs().flush(); } for (ilist_iterator<Function> iterF = module->getFunctionList().begin(); iterF != module->getFunctionList().end(); iterF++) { Function& f = *iterF; bool ignored = true; for (ilist_iterator<BasicBlock> iterB = f.getBasicBlockList().begin(); iterB != f.getBasicBlockList().end(); iterB++) { BasicBlock &b = *iterB; for (ilist_iterator<Instruction> iterI = b.getInstList().begin(); iterI != b.getInstList().end(); iterI++) { Instruction &inst = *iterI; // std::string &filename=getInstructionFileName(&inst) ; // unsigned ln = LOC.getLineNumber(); // errs() << inst << "\n"; // errs() << f.getName() << "\n"; // errs() << filename; // errs() << " : " << ln << "\n"; // errs() <<"************************"<< "\n"; // errs().flush(); //if (filename == "pbzip2.cpp") { ignored = false; break; //} } if (!ignored) { break; } } if (ignored) { ignored_funcs.insert(&f); } } if (debug()) { errs() << "End Preprocessing...\n"; errs().flush(); } }