#include "FunctionRepBuilder.h"
#include "llvm/Function.h"
+#include "llvm/BasicBlock.h"
#include "llvm/iMemory.h"
#include "llvm/iPHINode.h"
#include "llvm/iOther.h"
#include "llvm/iTerminators.h"
#include "llvm/DerivedTypes.h"
+#include "llvm/ConstantVals.h"
#include "Support/STLExtras.h"
#include <algorithm>
// chain..
// FIXME: This should not take a FunctionRepBuilder as an argument!
//
-ShadowDSNode *ShadowDSNode::synthesizeNode(const Type *Ty,
- FunctionRepBuilder *Rep) {
+ShadowDSNode *DSNode::synthesizeNode(const Type *Ty,
+ FunctionRepBuilder *Rep) {
// If we are a derived shadow node, defer to our parent to synthesize the node
- if (ShadowParent) return ShadowParent->synthesizeNode(Ty, Rep);
+ if (ShadowDSNode *Th = dyn_cast<ShadowDSNode>(this))
+ if (Th->getShadowParent())
+ return Th->getShadowParent()->synthesizeNode(Ty, Rep);
// See if we have already synthesized a node of this type...
for (unsigned i = 0, e = SynthNodes.size(); i != e; ++i)
if (SynthNodes[i].first == Ty) return SynthNodes[i].second;
// No we haven't. Do so now and add it to our list of saved nodes...
- ShadowDSNode *SN = new ShadowDSNode(Ty, Mod, this);
+ ShadowDSNode *SN = Rep->makeSynthesizedShadow(Ty, this);
SynthNodes.push_back(make_pair(Ty, SN));
- Rep->addShadowNode(SN);
return SN;
}
+ShadowDSNode *FunctionRepBuilder::makeSynthesizedShadow(const Type *Ty,
+ DSNode *Parent) {
+ ShadowDSNode *Result = new ShadowDSNode(Ty, F->getFunction()->getParent(),
+ Parent);
+ ShadowNodes.push_back(Result);
+ return Result;
+}
// Create a critical shadow node to represent the memory object that the
// return value points to...
ShadowDSNode *Shad = new ShadowDSNode(PT->getElementType(),
- Func->getParent(), true);
+ Func->getParent());
Rep->ShadowNodes.push_back(Shad);
// The return value of the function is a pointer to the shadow value
// Loop over all of the operands of the call instruction (except the first
// one), to look for global variable references...
//
- for_each(CI->op_begin()+1, CI->op_end(), // Skip first arg
+ for_each(CI->op_begin(), CI->op_end(),
bind_obj(this, &InitVisitor::visitOperand));
}
// the worklists...
//
for (Function::ArgumentListType::iterator I = Func->getArgumentList().begin(),
- E = Func->getArgumentList().end(); I != E; ++I)
+ E = Func->getArgumentList().end(); I != E; ++I) {
+ Value *Arg = (Value*)(*I);
// Only process arguments that are of pointer type...
- if (PointerType *PT = dyn_cast<PointerType>((*I)->getType())) {
- ArgDSNode *Arg = new ArgDSNode(*I);
- ArgNodes.push_back(Arg);
-
- // Add a critical shadow value for it to represent what it is pointing
- // to and add this to the value map...
+ if (PointerType *PT = dyn_cast<PointerType>(Arg->getType())) {
+ // Add a shadow value for it to represent what it is pointing to and add
+ // this to the value map...
ShadowDSNode *Shad = new ShadowDSNode(PT->getElementType(),
- Func->getParent(), true);
+ Func->getParent());
ShadowNodes.push_back(Shad);
- ValueMap[*I].add(PointerVal(Shad), *I);
-
- // The value of the argument is the shadow value...
- Arg->getLink(0).add(Shad);
+ ValueMap[Arg].add(PointerVal(Shad), Arg);
// Make sure that all users of the argument are processed...
- addAllUsesToWorkList(*I);
+ addAllUsesToWorkList(Arg);
}
-
+ }
+
// Iterate over the instructions in the method. Create nodes for malloc and
// call instructions. Add all uses of these to the worklist of instructions
// to process.
static PointerValSet &getField(const PointerVal &DestPtr) {
assert(DestPtr.Node != 0);
-
return DestPtr.Node->getLink(DestPtr.Index);
}
void FunctionRepBuilder::visitLoadInst(LoadInst *LI) {
// Only loads that return pointers are interesting...
- if (!isa<PointerType>(LI->getType())) return;
- const PointerType *DestTy = cast<PointerType>(LI->getType());
+ const PointerType *DestTy = dyn_cast<PointerType>(LI->getType());
+ if (DestTy == 0) return;
const PointerValSet &SrcPVS = ValueMap[LI->getOperand(0)];
PointerValSet &LIPVS = ValueMap[LI];
if (Field.size()) { // Field loaded wasn't null?
Changed |= LIPVS.add(Field);
- } else if (ShadowDSNode *Shad = dyn_cast<ShadowDSNode>(Ptr.Node)) {
+ } else {
// If we are loading a null field out of a shadow node, we need to
// synthesize a new shadow node and link it in...
//
ShadowDSNode *SynthNode =
- Shad->synthesizeNode(DestTy->getElementType(), this);
+ Ptr.Node->synthesizeNode(DestTy->getElementType(), this);
Field.add(SynthNode);
Changed |= LIPVS.add(Field);
void FunctionRepBuilder::visitCallInst(CallInst *CI) {
CallDSNode *DSN = CallMap[CI];
-
- unsigned PtrNum = 0, i = 0;
- if (isa<Function>(CI->getOperand(0)))
- ++i; // Not an Indirect function call? Skip the function pointer...
-
- for (unsigned e = CI->getNumOperands(); i != e; ++i)
+ unsigned PtrNum = 0;
+ for (unsigned i = 0, e = CI->getNumOperands(); i != e; ++i)
if (isa<PointerType>(CI->getOperand(i)->getType()))
DSN->addArgValue(PtrNum++, ValueMap[CI->getOperand(i)]);
}
//
FunctionDSGraph::FunctionDSGraph(Function *F) : Func(F) {
FunctionRepBuilder Builder(this);
- ArgNodes = Builder.getArgNodes();
AllocNodes = Builder.getAllocNodes();
ShadowNodes = Builder.getShadowNodes();
GlobalNodes = Builder.getGlobalNodes();
RetNode = Builder.getRetNode();
ValueMap = Builder.getValueMap();
+ // Remove all entries in the value map that consist of global values pointing
+ // at things. They can only point to their node, so there is no use keeping
+ // them.
+ //
+ for (map<Value*, PointerValSet>::iterator I = ValueMap.begin(),
+ E = ValueMap.end(); I != E;)
+ if (isa<GlobalValue>(I->first)) {
+#if MAP_DOESNT_HAVE_BROKEN_ERASE_MEMBER
+ I = ValueMap.erase(I);
+#else
+ ValueMap.erase(I); // This is really lame.
+ I = ValueMap.begin(); // GCC's stdc++ lib doesn't return an it!
+#endif
+ } else
+ ++I;
+
bool Changed = true;
while (Changed) {
// Eliminate shadow nodes that are not distinguishable from some other
Changed |= RemoveUnreachableNodes();
}
}
-