aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/DataStructure/Local.cpp
diff options
context:
space:
mode:
authorJohn Criswell <criswell@uiuc.edu>2006-12-13 19:41:57 +0000
committerJohn Criswell <criswell@uiuc.edu>2006-12-13 19:41:57 +0000
commit2957f129a7390a068610e9af5a079c6fa1bead24 (patch)
tree5e33193ba255f6f8872fb0e56f0d2bed37158878 /lib/Analysis/DataStructure/Local.cpp
parent64225643331b608ea3558623b6eee6649bca7c6c (diff)
Remove DSA.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@32550 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/DataStructure/Local.cpp')
-rw-r--r--lib/Analysis/DataStructure/Local.cpp1333
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;