diff options
Diffstat (limited to 'lib/Analysis/DataStructure/Local.cpp')
-rw-r--r-- | lib/Analysis/DataStructure/Local.cpp | 1333 |
1 files changed, 0 insertions, 1333 deletions
diff --git a/lib/Analysis/DataStructure/Local.cpp b/lib/Analysis/DataStructure/Local.cpp deleted file mode 100644 index 66ca33d876..0000000000 --- a/lib/Analysis/DataStructure/Local.cpp +++ /dev/null @@ -1,1333 +0,0 @@ -//===- Local.cpp - Compute a local data structure graph for a function ----===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Compute the local version of the data structure graph for a function. The -// external interface to this file is the DSGraph constructor. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Analysis/DataStructure/DataStructure.h" -#include "llvm/Analysis/DataStructure/DSGraph.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Instructions.h" -#include "llvm/Intrinsics.h" -#include "llvm/Support/GetElementPtrTypeIterator.h" -#include "llvm/Support/InstVisitor.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/Timer.h" - -// FIXME: This should eventually be a FunctionPass that is automatically -// aggregated into a Pass. -// -#include "llvm/Module.h" - -using namespace llvm; - -static RegisterPass<LocalDataStructures> -X("datastructure", "Local Data Structure Analysis"); - -static cl::opt<bool> -TrackIntegersAsPointers("dsa-track-integers", cl::Hidden, - cl::desc("If this is set, track integers as potential pointers")); - -static cl::opt<bool> -IgnoreSetCC("dsa-ignore-setcc", cl::Hidden, - cl::desc("If this is set, do nothing at pointer comparisons")); - -static cl::list<std::string> -AllocList("dsa-alloc-list", - cl::value_desc("list"), - cl::desc("List of functions that allocate memory from the heap"), - cl::CommaSeparated, cl::Hidden); - -static cl::list<std::string> -FreeList("dsa-free-list", - cl::value_desc("list"), - cl::desc("List of functions that free memory from the heap"), - cl::CommaSeparated, cl::Hidden); - -namespace llvm { -namespace DS { - // isPointerType - Return true if this type is big enough to hold a pointer. - bool isPointerType(const Type *Ty) { - if (isa<PointerType>(Ty)) - return true; - else if (TrackIntegersAsPointers && Ty->isPrimitiveType() &&Ty->isInteger()) - return Ty->getPrimitiveSize() >= PointerSize; - return false; - } -}} - -using namespace DS; - -namespace { - cl::opt<bool> - DisableDirectCallOpt("disable-direct-call-dsopt", cl::Hidden, - cl::desc("Disable direct call optimization in " - "DSGraph construction")); - cl::opt<bool> - DisableFieldSensitivity("disable-ds-field-sensitivity", cl::Hidden, - cl::desc("Disable field sensitivity in DSGraphs")); - - //===--------------------------------------------------------------------===// - // GraphBuilder Class - //===--------------------------------------------------------------------===// - // - /// This class is the builder class that constructs the local data structure - /// graph by performing a single pass over the function in question. - /// - class GraphBuilder : InstVisitor<GraphBuilder> { - DSGraph &G; - DSNodeHandle *RetNode; // Node that gets returned... - DSScalarMap &ScalarMap; - std::list<DSCallSite> *FunctionCalls; - - public: - GraphBuilder(Function &f, DSGraph &g, DSNodeHandle &retNode, - std::list<DSCallSite> &fc) - : G(g), RetNode(&retNode), ScalarMap(G.getScalarMap()), - FunctionCalls(&fc) { - - // Create scalar nodes for all pointer arguments... - for (Function::arg_iterator I = f.arg_begin(), E = f.arg_end(); - I != E; ++I) - if (isPointerType(I->getType())) - getValueDest(*I); - - visit(f); // Single pass over the function - } - - // GraphBuilder ctor for working on the globals graph - GraphBuilder(DSGraph &g) - : G(g), RetNode(0), ScalarMap(G.getScalarMap()), FunctionCalls(0) { - } - - void mergeInGlobalInitializer(GlobalVariable *GV); - - private: - // Visitor functions, used to handle each instruction type we encounter... - friend class InstVisitor<GraphBuilder>; - void visitMallocInst(MallocInst &MI) { handleAlloc(MI, true); } - void visitAllocaInst(AllocaInst &AI) { handleAlloc(AI, false); } - void handleAlloc(AllocationInst &AI, bool isHeap); - - void visitPHINode(PHINode &PN); - void visitSelectInst(SelectInst &SI); - - void visitGetElementPtrInst(User &GEP); - void visitReturnInst(ReturnInst &RI); - void visitLoadInst(LoadInst &LI); - void visitStoreInst(StoreInst &SI); - void visitCallInst(CallInst &CI); - void visitInvokeInst(InvokeInst &II); - void visitSetCondInst(SetCondInst &SCI); - void visitFreeInst(FreeInst &FI); - void visitCastInst(CastInst &CI); - void visitInstruction(Instruction &I); - - bool visitIntrinsic(CallSite CS, Function* F); - bool visitExternal(CallSite CS, Function* F); - void visitCallSite(CallSite CS); - void visitVAArgInst(VAArgInst &I); - - void MergeConstantInitIntoNode(DSNodeHandle &NH, Constant *C); - private: - // Helper functions used to implement the visitation functions... - - /// createNode - Create a new DSNode, ensuring that it is properly added to - /// the graph. - /// - DSNode *createNode(const Type *Ty = 0) { - DSNode *N = new DSNode(Ty, &G); // Create the node - if (DisableFieldSensitivity) { - // Create node handle referring to the old node so that it is - // immediately removed from the graph when the node handle is destroyed. - DSNodeHandle OldNNH = N; - N->foldNodeCompletely(); - if (DSNode *FN = N->getForwardNode()) - N = FN; - } - return N; - } - - /// setDestTo - Set the ScalarMap entry for the specified value to point to - /// the specified destination. If the Value already points to a node, make - /// sure to merge the two destinations together. - /// - void setDestTo(Value &V, const DSNodeHandle &NH); - - /// getValueDest - Return the DSNode that the actual value points to. - /// - DSNodeHandle getValueDest(Value &V); - - /// getLink - This method is used to return the specified link in the - /// specified node if one exists. If a link does not already exist (it's - /// null), then we create a new node, link it, then return it. - /// - DSNodeHandle &getLink(const DSNodeHandle &Node, unsigned Link = 0); - }; -} - -using namespace DS; - -//===----------------------------------------------------------------------===// -// DSGraph constructor - Simply use the GraphBuilder to construct the local -// graph. -DSGraph::DSGraph(EquivalenceClasses<GlobalValue*> &ECs, const TargetData &td, - Function &F, DSGraph *GG) - : GlobalsGraph(GG), ScalarMap(ECs), TD(td) { - PrintAuxCalls = false; - - DOUT << " [Loc] Calculating graph for: " << F.getName() << "\n"; - - // Use the graph builder to construct the local version of the graph - GraphBuilder B(F, *this, ReturnNodes[&F], FunctionCalls); -#ifndef NDEBUG - Timer::addPeakMemoryMeasurement(); -#endif - - // If there are any constant globals referenced in this function, merge their - // initializers into the local graph from the globals graph. - if (ScalarMap.global_begin() != ScalarMap.global_end()) { - ReachabilityCloner RC(*this, *GG, 0); - - for (DSScalarMap::global_iterator I = ScalarMap.global_begin(); - I != ScalarMap.global_end(); ++I) - if (GlobalVariable *GV = dyn_cast<GlobalVariable>(*I)) - if (!GV->isExternal() && GV->isConstant()) - RC.merge(ScalarMap[GV], GG->ScalarMap[GV]); - } - - markIncompleteNodes(DSGraph::MarkFormalArgs); - - // Remove any nodes made dead due to merging... - removeDeadNodes(DSGraph::KeepUnreachableGlobals); -} - - -//===----------------------------------------------------------------------===// -// Helper method implementations... -// - -/// getValueDest - Return the DSNode that the actual value points to. -/// -DSNodeHandle GraphBuilder::getValueDest(Value &Val) { - Value *V = &Val; - if (isa<Constant>(V) && cast<Constant>(V)->isNullValue()) - return 0; // Null doesn't point to anything, don't add to ScalarMap! - - DSNodeHandle &NH = ScalarMap[V]; - if (!NH.isNull()) - return NH; // Already have a node? Just return it... - - // Otherwise we need to create a new node to point to. - // Check first for constant expressions that must be traversed to - // extract the actual value. - DSNode* N; - if (GlobalValue* GV = dyn_cast<GlobalValue>(V)) { - // Create a new global node for this global variable. - N = createNode(GV->getType()->getElementType()); - N->addGlobal(GV); - } else if (Constant *C = dyn_cast<Constant>(V)) { - if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) { - if (CE->isCast()) { - if (isa<PointerType>(CE->getOperand(0)->getType())) - NH = getValueDest(*CE->getOperand(0)); - else - NH = createNode()->setUnknownNodeMarker(); - } else if (CE->getOpcode() == Instruction::GetElementPtr) { - visitGetElementPtrInst(*CE); - DSScalarMap::iterator I = ScalarMap.find(CE); - assert(I != ScalarMap.end() && "GEP didn't get processed right?"); - NH = I->second; - } else { - // This returns a conservative unknown node for any unhandled ConstExpr - return NH = createNode()->setUnknownNodeMarker(); - } - if (NH.isNull()) { // (getelementptr null, X) returns null - ScalarMap.erase(V); - return 0; - } - return NH; - } else if (isa<UndefValue>(C)) { - ScalarMap.erase(V); - return 0; - } else { - assert(0 && "Unknown constant type!"); - } - N = createNode(); // just create a shadow node - } else { - // Otherwise just create a shadow node - N = createNode(); - } - - NH.setTo(N, 0); // Remember that we are pointing to it... - return NH; -} - - -/// getLink - This method is used to return the specified link in the -/// specified node if one exists. If a link does not already exist (it's -/// null), then we create a new node, link it, then return it. We must -/// specify the type of the Node field we are accessing so that we know what -/// type should be linked to if we need to create a new node. -/// -DSNodeHandle &GraphBuilder::getLink(const DSNodeHandle &node, unsigned LinkNo) { - DSNodeHandle &Node = const_cast<DSNodeHandle&>(node); - DSNodeHandle &Link = Node.getLink(LinkNo); - if (Link.isNull()) { - // If the link hasn't been created yet, make and return a new shadow node - Link = createNode(); - } - return Link; -} - - -/// setDestTo - Set the ScalarMap entry for the specified value to point to the -/// specified destination. If the Value already points to a node, make sure to -/// merge the two destinations together. -/// -void GraphBuilder::setDestTo(Value &V, const DSNodeHandle &NH) { - ScalarMap[&V].mergeWith(NH); -} - - -//===----------------------------------------------------------------------===// -// Specific instruction type handler implementations... -// - -/// Alloca & Malloc instruction implementation - Simply create a new memory -/// object, pointing the scalar to it. -/// -void GraphBuilder::handleAlloc(AllocationInst &AI, bool isHeap) { - DSNode *N = createNode(); - if (isHeap) - N->setHeapNodeMarker(); - else - N->setAllocaNodeMarker(); - setDestTo(AI, N); -} - -// PHINode - Make the scalar for the PHI node point to all of the things the -// incoming values point to... which effectively causes them to be merged. -// -void GraphBuilder::visitPHINode(PHINode &PN) { - if (!isPointerType(PN.getType())) return; // Only pointer PHIs - - DSNodeHandle &PNDest = ScalarMap[&PN]; - for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) - PNDest.mergeWith(getValueDest(*PN.getIncomingValue(i))); -} - -void GraphBuilder::visitSelectInst(SelectInst &SI) { - if (!isPointerType(SI.getType())) return; // Only pointer Selects - - DSNodeHandle &Dest = ScalarMap[&SI]; - Dest.mergeWith(getValueDest(*SI.getOperand(1))); - Dest.mergeWith(getValueDest(*SI.getOperand(2))); -} - -void GraphBuilder::visitSetCondInst(SetCondInst &SCI) { - if (!isPointerType(SCI.getOperand(0)->getType()) || - isa<ConstantPointerNull>(SCI.getOperand(1))) return; // Only pointers - if(!IgnoreSetCC) - ScalarMap[SCI.getOperand(0)].mergeWith(getValueDest(*SCI.getOperand(1))); -} - - -void GraphBuilder::visitGetElementPtrInst(User &GEP) { - DSNodeHandle Value = getValueDest(*GEP.getOperand(0)); - if (Value.isNull()) - Value = createNode(); - - // As a special case, if all of the index operands of GEP are constant zeros, - // handle this just like we handle casts (ie, don't do much). - bool AllZeros = true; - for (unsigned i = 1, e = GEP.getNumOperands(); i != e; ++i) - if (GEP.getOperand(i) != - Constant::getNullValue(GEP.getOperand(i)->getType())) { - AllZeros = false; - break; - } - - // If all of the indices are zero, the result points to the operand without - // applying the type. - if (AllZeros || (!Value.isNull() && - Value.getNode()->isNodeCompletelyFolded())) { - setDestTo(GEP, Value); - return; - } - - - const PointerType *PTy = cast<PointerType>(GEP.getOperand(0)->getType()); - const Type *CurTy = PTy->getElementType(); - - if (Value.getNode()->mergeTypeInfo(CurTy, Value.getOffset())) { - // If the node had to be folded... exit quickly - setDestTo(GEP, Value); // GEP result points to folded node - return; - } - - const TargetData &TD = Value.getNode()->getTargetData(); - -#if 0 - // Handle the pointer index specially... - if (GEP.getNumOperands() > 1 && - (!isa<Constant>(GEP.getOperand(1)) || - !cast<Constant>(GEP.getOperand(1))->isNullValue())) { - - // If we already know this is an array being accessed, don't do anything... - if (!TopTypeRec.isArray) { - TopTypeRec.isArray = true; - - // If we are treating some inner field pointer as an array, fold the node - // up because we cannot handle it right. This can come because of - // something like this: &((&Pt->X)[1]) == &Pt->Y - // - if (Value.getOffset()) { - // Value is now the pointer we want to GEP to be... - Value.getNode()->foldNodeCompletely(); - setDestTo(GEP, Value); // GEP result points to folded node - return; - } else { - // This is a pointer to the first byte of the node. Make sure that we - // are pointing to the outter most type in the node. - // FIXME: We need to check one more case here... - } - } - } -#endif - - // All of these subscripts are indexing INTO the elements we have... - unsigned Offset = 0; - for (gep_type_iterator I = gep_type_begin(GEP), E = gep_type_end(GEP); - I != E; ++I) - if (const StructType *STy = dyn_cast<StructType>(*I)) { - const ConstantInt* CUI = cast<ConstantInt>(I.getOperand()); - unsigned FieldNo = - CUI->getType()->isSigned() ? CUI->getSExtValue() : CUI->getZExtValue(); - Offset += (unsigned)TD.getStructLayout(STy)->MemberOffsets[FieldNo]; - } else if (isa<PointerType>(*I)) { - if (!isa<Constant>(I.getOperand()) || - !cast<Constant>(I.getOperand())->isNullValue()) - Value.getNode()->setArrayMarker(); - } - - -#if 0 - if (const SequentialType *STy = cast<SequentialType>(*I)) { - CurTy = STy->getElementType(); - if (ConstantInt *CS = dyn_cast<ConstantInt>(GEP.getOperand(i))) { - Offset += - (CS->getType()->isSigned() ? CS->getSExtValue() : CS->getZExtValue()) - * TD.getTypeSize(CurTy); - } else { - // Variable index into a node. We must merge all of the elements of the - // sequential type here. - if (isa<PointerType>(STy)) - cerr << "Pointer indexing not handled yet!\n"; - else { - const ArrayType *ATy = cast<ArrayType>(STy); - unsigned ElSize = TD.getTypeSize(CurTy); - DSNode *N = Value.getNode(); - assert(N && "Value must have a node!"); - unsigned RawOffset = Offset+Value.getOffset(); - - // Loop over all of the elements of the array, merging them into the - // zeroth element. - for (unsigned i = 1, e = ATy->getNumElements(); i != e; ++i) - // Merge all of the byte components of this array element - for (unsigned j = 0; j != ElSize; ++j) - N->mergeIndexes(RawOffset+j, RawOffset+i*ElSize+j); - } - } - } -#endif - - // Add in the offset calculated... - Value.setOffset(Value.getOffset()+Offset); - - // Check the offset - DSNode *N = Value.getNode(); - if (N && - !N->isNodeCompletelyFolded() && - (N->getSize() != 0 || Offset != 0) && - !N->isForwarding()) { - if ((Offset >= N->getSize()) || int(Offset) < 0) { - // Accessing offsets out of node size range - // This is seen in the "magic" struct in named (from bind), where the - // fourth field is an array of length 0, presumably used to create struct - // instances of different sizes - - // Collapse the node since its size is now variable - N->foldNodeCompletely(); - } - } - - // Value is now the pointer we want to GEP to be... - setDestTo(GEP, Value); -} - -void GraphBuilder::visitLoadInst(LoadInst &LI) { - DSNodeHandle Ptr = getValueDest(*LI.getOperand(0)); - if (Ptr.isNull()) - Ptr = createNode(); - - // Make that the node is read from... - Ptr.getNode()->setReadMarker(); - - // Ensure a typerecord exists... - Ptr.getNode()->mergeTypeInfo(LI.getType(), Ptr.getOffset(), false); - - if (isPointerType(LI.getType())) - setDestTo(LI, getLink(Ptr)); -} - -void GraphBuilder::visitStoreInst(StoreInst &SI) { - const Type *StoredTy = SI.getOperand(0)->getType(); - DSNodeHandle Dest = getValueDest(*SI.getOperand(1)); - if (Dest.isNull()) return; - - // Mark that the node is written to... - Dest.getNode()->setModifiedMarker(); - - // Ensure a type-record exists... - Dest.getNode()->mergeTypeInfo(StoredTy, Dest.getOffset()); - - // Avoid adding edges from null, or processing non-"pointer" stores - if (isPointerType(StoredTy)) - Dest.addEdgeTo(getValueDest(*SI.getOperand(0))); -} - -void GraphBuilder::visitReturnInst(ReturnInst &RI) { - if (RI.getNumOperands() && isPointerType(RI.getOperand(0)->getType())) - RetNode->mergeWith(getValueDest(*RI.getOperand(0))); -} - -void GraphBuilder::visitVAArgInst(VAArgInst &I) { - //FIXME: also updates the argument - DSNodeHandle Ptr = getValueDest(*I.getOperand(0)); - if (Ptr.isNull()) return; - - // Make that the node is read from. - Ptr.getNode()->setReadMarker(); - - // Ensure a type record exists. - DSNode *PtrN = Ptr.getNode(); - PtrN->mergeTypeInfo(I.getType(), Ptr.getOffset(), false); - - if (isPointerType(I.getType())) - setDestTo(I, getLink(Ptr)); -} - - -void GraphBuilder::visitCallInst(CallInst &CI) { - visitCallSite(&CI); -} - -void GraphBuilder::visitInvokeInst(InvokeInst &II) { - visitCallSite(&II); -} - -/// returns true if the intrinsic is handled -bool GraphBuilder::visitIntrinsic(CallSite CS, Function *F) { - switch (F->getIntrinsicID()) { - case Intrinsic::vastart: - getValueDest(*CS.getInstruction()).getNode()->setAllocaNodeMarker(); - return true; - case Intrinsic::vacopy: - getValueDest(*CS.getInstruction()). - mergeWith(getValueDest(**(CS.arg_begin()))); - return true; - case Intrinsic::vaend: - case Intrinsic::dbg_func_start: - case Intrinsic::dbg_region_end: - case Intrinsic::dbg_stoppoint: - return true; // noop - case Intrinsic::memcpy_i32: - case Intrinsic::memcpy_i64: - case Intrinsic::memmove_i32: - case Intrinsic::memmove_i64: { - // Merge the first & second arguments, and mark the memory read and - // modified. - DSNodeHandle RetNH = getValueDest(**CS.arg_begin()); - RetNH.mergeWith(getValueDest(**(CS.arg_begin()+1))); - if (DSNode *N = RetNH.getNode()) - N->setModifiedMarker()->setReadMarker(); - return true; - } - case Intrinsic::memset_i32: - case Intrinsic::memset_i64: - // Mark the memory modified. - if (DSNode *N = getValueDest(**CS.arg_begin()).getNode()) - N->setModifiedMarker(); - return true; - default: - DOUT << "[dsa:local] Unhandled intrinsic: " << F->getName() << "\n"; - return false; - } -} - -/// returns true if the external is a recognized libc function with a -/// known (and generated) graph -bool GraphBuilder::visitExternal(CallSite CS, Function *F) { - if (F->getName() == "calloc" - || F->getName() == "posix_memalign" - || F->getName() == "memalign" || F->getName() == "valloc") { - setDestTo(*CS.getInstruction(), - createNode()->setHeapNodeMarker()->setModifiedMarker()); - return true; - } else if (F->getName() == "realloc") { - DSNodeHandle RetNH = getValueDest(*CS.getInstruction()); - if (CS.arg_begin() != CS.arg_end()) - RetNH.mergeWith(getValueDest(**CS.arg_begin())); - if (DSNode *N = RetNH.getNode()) - N->setHeapNodeMarker()->setModifiedMarker()->setReadMarker(); - return true; - } else if (F->getName() == "memmove") { - // Merge the first & second arguments, and mark the memory read and - // modified. - DSNodeHandle RetNH = getValueDest(**CS.arg_begin()); - RetNH.mergeWith(getValueDest(**(CS.arg_begin()+1))); - if (DSNode *N = RetNH.getNode()) - N->setModifiedMarker()->setReadMarker(); - return true; - } else if (F->getName() == "free") { - // Mark that the node is written to... - if (DSNode *N = getValueDest(**CS.arg_begin()).getNode()) - N->setModifiedMarker()->setHeapNodeMarker(); - } else if (F->getName() == "atoi" || F->getName() == "atof" || - F->getName() == "atol" || F->getName() == "atoll" || - F->getName() == "remove" || F->getName() == "unlink" || - F->getName() == "rename" || F->getName() == "memcmp" || - F->getName() == "strcmp" || F->getName() == "strncmp" || - F->getName() == "execl" || F->getName() == "execlp" || - F->getName() == "execle" || F->getName() == "execv" || - F->getName() == "execvp" || F->getName() == "chmod" || - F->getName() == "puts" || F->getName() == "write" || - F->getName() == "open" || F->getName() == "create" || - F->getName() == "truncate" || F->getName() == "chdir" || - F->getName() == "mkdir" || F->getName() == "rmdir" || - F->getName() == "strlen") { - // These functions read all of their pointer operands. - for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end(); - AI != E; ++AI) { - if (isPointerType((*AI)->getType())) - if (DSNode *N = getValueDest(**AI).getNode()) - N->setReadMarker(); - } - return true; - } else if (F->getName() == "memchr") { - DSNodeHandle RetNH = getValueDest(**CS.arg_begin()); - DSNodeHandle Result = getValueDest(*CS.getInstruction()); - RetNH.mergeWith(Result); - if (DSNode *N = RetNH.getNode()) - N->setReadMarker(); - return true; - } else if (F->getName() == "read" || F->getName() == "pipe" || - F->getName() == "wait" || F->getName() == "time" || - F->getName() == "getrusage") { - // These functions write all of their pointer operands. - for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end(); - AI != E; ++AI) { - if (isPointerType((*AI)->getType())) - if (DSNode *N = getValueDest(**AI).getNode()) - N->setModifiedMarker(); - } - return true; - } else if (F->getName() == "stat" || F->getName() == "fstat" || - F->getName() == "lstat") { - // These functions read their first operand if its a pointer. - CallSite::arg_iterator AI = CS.arg_begin(); - if (isPointerType((*AI)->getType())) { - DSNodeHandle Path = getValueDest(**AI); - if (DSNode *N = Path.getNode()) N->setReadMarker(); - } - - // Then they write into the stat buffer. - DSNodeHandle StatBuf = getValueDest(**++AI); - if (DSNode *N = StatBuf.getNode()) { - N->setModifiedMarker(); - const Type *StatTy = F->getFunctionType()->getParamType(1); - if (const PointerType *PTy = dyn_cast<PointerType>(StatTy)) - N->mergeTypeInfo(PTy->getElementType(), StatBuf.getOffset()); - } - return true; - } else if (F->getName() == "strtod" || F->getName() == "strtof" || - F->getName() == "strtold") { - // These functions read the first pointer - if (DSNode *Str = getValueDest(**CS.arg_begin()).getNode()) { - Str->setReadMarker(); - // If the second parameter is passed, it will point to the first - // argument node. - const DSNodeHandle &EndPtrNH = getValueDest(**(CS.arg_begin()+1)); - if (DSNode *End = EndPtrNH.getNode()) { - End->mergeTypeInfo(PointerType::get(Type::SByteTy), - EndPtrNH.getOffset(), false); - End->setModifiedMarker(); - DSNodeHandle &Link = getLink(EndPtrNH); - Link.mergeWith(getValueDest(**CS.arg_begin())); - } - } - return true; - } else if (F->getName() == "fopen" || F->getName() == "fdopen" || - F->getName() == "freopen") { - // These functions read all of their pointer operands. - for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end(); - AI != E; ++AI) - if (isPointerType((*AI)->getType())) - if (DSNode *N = getValueDest(**AI).getNode()) - N->setReadMarker(); - - // fopen allocates in an unknown way and writes to the file - // descriptor. Also, merge the allocated type into the node. - DSNodeHandle Result = getValueDest(*CS.getInstruction()); - if (DSNode *N = Result.getNode()) { - N->setModifiedMarker()->setUnknownNodeMarker(); - const Type *RetTy = F->getFunctionType()->getReturnType(); - if (const PointerType *PTy = dyn_cast<PointerType>(RetTy)) - N->mergeTypeInfo(PTy->getElementType(), Result.getOffset()); - } - - // If this is freopen, merge the file descriptor passed in with the - // result. - if (F->getName() == "freopen") { - // ICC doesn't handle getting the iterator, decrementing and - // dereferencing it in one operation without error. Do it in 2 steps - CallSite::arg_iterator compit = CS.arg_end(); - Result.mergeWith(getValueDest(**--compit)); - } - return true; - } else if (F->getName() == "fclose" && CS.arg_end()-CS.arg_begin() ==1){ - // fclose reads and deallocates the memory in an unknown way for the - // file descriptor. It merges the FILE type into the descriptor. - DSNodeHandle H = getValueDest(**CS.arg_begin()); - if (DSNode *N = H.getNode()) { - N->setReadMarker()->setUnknownNodeMarker(); - const Type *ArgTy = F->getFunctionType()->getParamType(0); - if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy)) - N->mergeTypeInfo(PTy->getElementType(), H.getOffset()); - } - return true; - } else if (CS.arg_end()-CS.arg_begin() == 1 && - (F->getName() == "fflush" || F->getName() == "feof" || - F->getName() == "fileno" || F->getName() == "clearerr" || - F->getName() == "rewind" || F->getName() == "ftell" || - F->getName() == "ferror" || F->getName() == "fgetc" || - F->getName() == "fgetc" || F->getName() == "_IO_getc")) { - // fflush reads and writes the memory for the file descriptor. It - // merges the FILE type into the descriptor. - DSNodeHandle H = getValueDest(**CS.arg_begin()); - if (DSNode *N = H.getNode()) { - N->setReadMarker()->setModifiedMarker(); - - const Type *ArgTy = F->getFunctionType()->getParamType(0); - if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy)) - N->mergeTypeInfo(PTy->getElementType(), H.getOffset()); - } - return true; - } else if (CS.arg_end()-CS.arg_begin() == 4 && - (F->getName() == "fwrite" || F->getName() == "fread")) { - // fread writes the first operand, fwrite reads it. They both - // read/write the FILE descriptor, and merges the FILE type. - CallSite::arg_iterator compit = CS.arg_end(); - DSNodeHandle H = getValueDest(**--compit); - if (DSNode *N = H.getNode()) { - N->setReadMarker()->setModifiedMarker(); - const Type *ArgTy = F->getFunctionType()->getParamType(3); - if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy)) - N->mergeTypeInfo(PTy->getElementType(), H.getOffset()); - } - - H = getValueDest(**CS.arg_begin()); - if (DSNode *N = H.getNode()) - if (F->getName() == "fwrite") - N->setReadMarker(); - else - N->setModifiedMarker(); - return true; - } else if (F->getName() == "fgets" && CS.arg_end()-CS.arg_begin() == 3){ - // fgets reads and writes the memory for the file descriptor. It - // merges the FILE type into the descriptor, and writes to the - // argument. It returns the argument as well. - CallSite::arg_iterator AI = CS.arg_begin(); - DSNodeHandle H = getValueDest(**AI); - if (DSNode *N = H.getNode()) - N->setModifiedMarker(); // Writes buffer - H.mergeWith(getValueDest(*CS.getInstruction())); // Returns buffer - ++AI; ++AI; - - // Reads and writes file descriptor, merge in FILE type. - H = getValueDest(**AI); - if (DSNode *N = H.getNode()) { - N->setReadMarker()->setModifiedMarker(); - const Type *ArgTy = F->getFunctionType()->getParamType(2); - if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy)) - N->mergeTypeInfo(PTy->getElementType(), H.getOffset()); - } - return true; - } else if (F->getName() == "ungetc" || F->getName() == "fputc" || - F->getName() == "fputs" || F->getName() == "putc" || - F->getName() == "ftell" || F->getName() == "rewind" || - F->getName() == "_IO_putc") { - // These functions read and write the memory for the file descriptor, - // which is passes as the last argument. - CallSite::arg_iterator compit = CS.arg_end(); - DSNodeHandle H = getValueDest(**--compit); - if (DSNode *N = H.getNode()) { - N->setReadMarker()->setModifiedMarker(); - FunctionType::param_iterator compit2 = F->getFunctionType()->param_end(); - const Type *ArgTy = *--compit2; - if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy)) - N->mergeTypeInfo(PTy->getElementType(), H.getOffset()); - } - - // Any pointer arguments are read. - for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end(); - AI != E; ++AI) - if (isPointerType((*AI)->getType())) - if (DSNode *N = getValueDest(**AI).getNode()) - N->setReadMarker(); - return true; - } else if (F->getName() == "fseek" || F->getName() == "fgetpos" || - F->getName() == "fsetpos") { - // These functions read and write the memory for the file descriptor, - // and read/write all other arguments. - DSNodeHandle H = getValueDest(**CS.arg_begin()); - if (DSNode *N = H.getNode()) { - FunctionType::param_iterator compit2 = F->getFunctionType()->param_end(); - const Type *ArgTy = *--compit2; - if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy)) - N->mergeTypeInfo(PTy->getElementType(), H.getOffset()); - } - - // Any pointer arguments are read. - for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end(); - AI != E; ++AI) - if (isPointerType((*AI)->getType())) - if (DSNode *N = getValueDest(**AI).getNode()) - N->setReadMarker()->setModifiedMarker(); - return true; - } else if (F->getName() == "printf" || F->getName() == "fprintf" || - F->getName() == "sprintf") { - CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end(); - - if (F->getName() == "fprintf") { - // fprintf reads and writes the FILE argument, and applies the type - // to it. - DSNodeHandle H = getValueDest(**AI); - if (DSNode *N = H.getNode()) { - N->setModifiedMarker(); - const Type *ArgTy = (*AI)->getType(); - if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy)) - N->mergeTypeInfo(PTy->getElementType(), H.getOffset()); - } - } else if (F->getName() == "sprintf") { - // sprintf writes the first string argument. - DSNodeHandle H = getValueDest(**AI++); - if (DSNode *N = H.getNode()) { - N->setModifiedMarker(); - const Type *ArgTy = (*AI)->getType(); - if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy)) - N->mergeTypeInfo(PTy->getElementType(), H.getOffset()); - } - } - - for (; AI != E; ++AI) { - // printf reads all pointer arguments. - if (isPointerType((*AI)->getType())) - if (DSNode *N = getValueDest(**AI).getNode()) - N->setReadMarker(); - } - return true; - } else if (F->getName() == "vprintf" || F->getName() == "vfprintf" || - F->getName() == "vsprintf") { - CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end(); - - if (F->getName() == "vfprintf") { - // ffprintf reads and writes the FILE argument, and applies the type - // to it. - DSNodeHandle H = getValueDest(**AI); - if (DSNode *N = H.getNode()) { - N->setModifiedMarker()->setReadMarker(); - const Type *ArgTy = (*AI)->getType(); - if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy)) - N->mergeTypeInfo(PTy->getElementType(), H.getOffset()); - } - ++AI; - } else if (F->getName() == "vsprintf") { - // vsprintf writes the first string argument. - DSNodeHandle H = getValueDest(**AI++); - if (DSNode *N = H.getNode()) { - N->setModifiedMarker(); - const Type *ArgTy = (*AI)->getType(); - if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy)) - N->mergeTypeInfo(PTy->getElementType(), H.getOffset()); - } - } - - // Read the format - if (AI != E) { - if (isPointerType((*AI)->getType())) - if (DSNode *N = getValueDest(**AI).getNode()) - N->setReadMarker(); - ++AI; - } - - // Read the valist, and the pointed-to objects. - if (AI != E && isPointerType((*AI)->getType())) { - const DSNodeHandle &VAList = getValueDest(**AI); - if (DSNode *N = VAList.getNode()) { - N->setReadMarker(); - N->mergeTypeInfo(PointerType::get(Type::SByteTy), - VAList.getOffset(), false); - - DSNodeHandle &VAListObjs = getLink(VAList); - VAListObjs.getNode()->setReadMarker(); - } - } - - return true; - } else if (F->getName() == "scanf" || F->getName() == "fscanf" || - F->getName() == "sscanf") { - CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end(); - - if (F->getName() == "fscanf") { - // fscanf reads and writes the FILE argument, and applies the type - // to it. - DSNodeHandle H = getValueDest(**AI); - if (DSNode *N = H.getNode()) { - N->setReadMarker(); - const Type *ArgTy = (*AI)->getType(); - if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy)) - N->mergeTypeInfo(PTy->getElementType(), H.getOffset()); - } - } else if (F->getName() == "sscanf") { - // sscanf reads the first string argument. - DSNodeHandle H = getValueDest(**AI++); - if (DSNode *N = H.getNode()) { - N->setReadMarker(); - const Type *ArgTy = (*AI)->getType(); - if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy)) - N->mergeTypeInfo(PTy->getElementType(), H.getOffset()); - } |