//===- DataStructure.cpp - Implement the core data structure analysis -----===//
//
// This file implements the core data structure functionality.
//
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/DSGraph.h"
#include "llvm/Function.h"
#include "llvm/iOther.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Target/TargetData.h"
#include "Support/STLExtras.h"
#include "Support/Statistic.h"
#include <algorithm>
#include <set>
using std::vector;
namespace {
Statistic<> NumFolds("dsnode", "Number of nodes completely folded");
};
namespace DS { // TODO: FIXME
extern TargetData TD;
}
using namespace DS;
//===----------------------------------------------------------------------===//
// DSNode Implementation
//===----------------------------------------------------------------------===//
DSNode::DSNode(enum NodeTy NT, const Type *T)
: Ty(Type::VoidTy), Size(0), NodeType(NT) {
// Add the type entry if it is specified...
if (T) mergeTypeInfo(T, 0);
}
// DSNode copy constructor... do not copy over the referrers list!
DSNode::DSNode(const DSNode &N)
: Links(N.Links), Globals(N.Globals), Ty(N.Ty), Size(N.Size),
NodeType(N.NodeType) {
}
void DSNode::removeReferrer(DSNodeHandle *H) {
// Search backwards, because we depopulate the list from the back for
// efficiency (because it's a vector).
vector<DSNodeHandle*>::reverse_iterator I =
std::find(Referrers.rbegin(), Referrers.rend(), H);
assert(I != Referrers.rend() && "Referrer not pointing to node!");
Referrers.erase(I.base()-1);
}
// addGlobal - Add an entry for a global value to the Globals list. This also
// marks the node with the 'G' flag if it does not already have it.
//
void DSNode::addGlobal(GlobalValue *GV) {
// Keep the list sorted.
vector<GlobalValue*>::iterator I =
std::lower_bound(Globals.begin(), Globals.end(), GV);
if (I == Globals.end() || *I != GV) {
//assert(GV->getType()->getElementType() == Ty);
Globals.insert(I, GV);
NodeType |= GlobalNode;
}
}
/// foldNodeCompletely - If we determine that this node has some funny
/// behavior happening to it that we cannot represent, we fold it down to a
/// single, completely pessimistic, node. This node is represented as a
/// single byte with a single TypeEntry of "void".
///
void DSNode::foldNodeCompletely() {
if (isNodeCompletelyFolded()) return;
++NumFolds;
// We are no longer typed at all...
Ty = DSTypeRec(Type::VoidTy, true);
Size = 1;
// Loop over all of our referrers, making them point to our zero bytes of
// space.
for (vector<DSNodeHandle*>::iterator I = Referrers.begin(), E=Referrers.end();
I != E; ++I)
(*I)->setOffset(0);
// If we have links, merge all of our outgoing links together...
for (unsigned i = 1, e = Links.size(); i < e; ++i)
Links[0].mergeWith(Links[i]);
Links.resize(1);
}
/// isNodeCompletelyFolded - Return true if this node has been completely
/// folded down to something that can never be expanded, effectively losing
/// all of the field sensitivity that may be present in the node.
///
bool DSNode::isNodeCompletelyFolded() const {
return getSize() == 1 && Ty.Ty == Type::VoidTy && Ty.isArray;
}
/// mergeTypeInfo - This method merges the specified type into the current node
/// at the specified offset. This may update the current node's type record if
/// this gives more information to the node, it may do nothing to the node if
/// this information is already known, or it may merge the node completely (and
/// return true) if the information is incompatible with what is already known.
///
/// This method returns true if the node is completely folded, otherwise false.
///
bool DSNode::mergeTypeInfo(const Type *NewTy, unsigned Offset) {
// Check to make sure the Size member is up-to-date. Size can be one of the
// following:
// Size = 0, Ty = Void: Nothing is known about this node.
// Size = 0, Ty = FnTy: FunctionPtr doesn't have a size, so we use zero
// Size = 1, Ty = Void, Array = 1: The node is collapsed
// Otherwise, sizeof(Ty) = Size
//
assert(((Size == 0 && Ty.Ty == Type::VoidTy && !Ty.isArray