As much as I hate to say it, the whole setNode interface for DSNodeHandles

is HOPELESSLY broken.  The problem is that the embedded getNode call can
change the offset of the node handle in unpredictable ways.

As it turns out, all of the clients of this method really want to set
both the node and the offset, thus it is more efficient (and less buggy)
to just do both of them in one method call.  This fixes some obscure bugs
handling non-forwarded node handles.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@14660 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2004-07-07 06:12:52 +00:00
parent d340867964
commit efffdc9408
6 changed files with 43 additions and 45 deletions

View File

@ -175,7 +175,7 @@ public:
void stopForwarding() { void stopForwarding() {
assert(isForwarding() && assert(isForwarding() &&
"Node isn't forwarding, cannot stopForwarding()!"); "Node isn't forwarding, cannot stopForwarding()!");
ForwardNH.setNode(0); ForwardNH.setTo(0, 0);
assert(ParentGraph == 0 && assert(ParentGraph == 0 &&
"Forwarding nodes must have been removed from graph!"); "Forwarding nodes must have been removed from graph!");
delete this; delete this;
@ -336,7 +336,7 @@ public:
void dropAllReferences() { void dropAllReferences() {
Links.clear(); Links.clear();
if (isForwarding()) if (isForwarding())
ForwardNH.setNode(0); ForwardNH.setTo(0, 0);
} }
/// remapLinks - Change all of the Links in the current node according to the /// remapLinks - Change all of the Links in the current node according to the
@ -401,10 +401,11 @@ inline DSNode *DSNodeHandle::getNode() const {
return HandleForwarding(); return HandleForwarding();
} }
inline void DSNodeHandle::setNode(DSNode *n) const { inline void DSNodeHandle::setTo(DSNode *n, unsigned NewOffset) const {
assert(!n || !n->isForwarding() && "Cannot set node to a forwarded node!"); assert(!n || !n->isForwarding() && "Cannot set node to a forwarded node!");
if (N) getNode()->NumReferrers--; if (N) getNode()->NumReferrers--;
N = n; N = n;
Offset = NewOffset;
if (N) { if (N) {
N->NumReferrers++; N->NumReferrers++;
if (Offset >= N->Size) { if (Offset >= N->Size) {
@ -457,8 +458,8 @@ inline void DSNodeHandle::mergeWith(const DSNodeHandle &Node) const {
getNode()->mergeWith(Node, Offset); getNode()->mergeWith(Node, Offset);
else { // No node to merge with, so just point to Node else { // No node to merge with, so just point to Node
Offset = 0; Offset = 0;
setNode(Node.getNode()); DSNode *NN = Node.getNode();
Offset = Node.getOffset(); setTo(NN, Node.getOffset());
} }
} }

View File

@ -58,17 +58,18 @@ class DSNodeHandle {
void operator==(const DSNode *N); // DISALLOW, use to promote N to nodehandle void operator==(const DSNode *N); // DISALLOW, use to promote N to nodehandle
public: public:
// Allow construction, destruction, and assignment... // Allow construction, destruction, and assignment...
DSNodeHandle(DSNode *n = 0, unsigned offs = 0) : N(0), Offset(offs) { DSNodeHandle(DSNode *n = 0, unsigned offs = 0) : N(0), Offset(0) {
setNode(n); setTo(n, offs);
} }
DSNodeHandle(const DSNodeHandle &H) : N(0), Offset(0) { DSNodeHandle(const DSNodeHandle &H) : N(0), Offset(0) {
setNode(H.getNode()); DSNode *NN = H.getNode();
Offset = H.Offset; // Must read offset AFTER the getNode() setTo(NN, H.Offset); // Must read offset AFTER the getNode()
} }
~DSNodeHandle() { setNode((DSNode*)0); } ~DSNodeHandle() { setTo(0, 0); }
DSNodeHandle &operator=(const DSNodeHandle &H) { DSNodeHandle &operator=(const DSNodeHandle &H) {
if (&H == this) return *this; // Don't set offset to 0 if self assigning. if (&H == this) return *this; // Don't set offset to 0 if self assigning.
Offset = 0; setNode(H.getNode()); Offset = H.Offset; DSNode *NN = H.getNode(); // Call getNode() before .Offset
setTo(NN, H.Offset);
return *this; return *this;
} }
@ -96,7 +97,6 @@ public:
inline DSNode *getNode() const; // Defined inline in DSNode.h inline DSNode *getNode() const; // Defined inline in DSNode.h
unsigned getOffset() const { return Offset; } unsigned getOffset() const { return Offset; }
inline void setNode(DSNode *N) const; // Defined inline in DSNode.h
void setOffset(unsigned O) { void setOffset(unsigned O) {
//assert((!N || Offset < N->Size || (N->Size == 0 && Offset == 0) || //assert((!N || Offset < N->Size || (N->Size == 0 && Offset == 0) ||
// !N->ForwardNH.isNull()) && "Node handle offset out of range!"); // !N->ForwardNH.isNull()) && "Node handle offset out of range!");
@ -105,6 +105,8 @@ public:
Offset = O; Offset = O;
} }
inline void setTo(DSNode *N, unsigned O) const; // Defined inline in DSNode.h
void addEdgeTo(unsigned LinkNo, const DSNodeHandle &N); void addEdgeTo(unsigned LinkNo, const DSNodeHandle &N);
void addEdgeTo(const DSNodeHandle &N) { addEdgeTo(0, N); } void addEdgeTo(const DSNodeHandle &N) { addEdgeTo(0, N); }
@ -154,9 +156,7 @@ class DSCallSite {
if (DSNode *N = Src.getNode()) { if (DSNode *N = Src.getNode()) {
hash_map<const DSNode*, DSNode*>::const_iterator I = NodeMap.find(N); hash_map<const DSNode*, DSNode*>::const_iterator I = NodeMap.find(N);
assert(I != NodeMap.end() && "Node not in mapping!"); assert(I != NodeMap.end() && "Node not in mapping!");
NH.setTo(I->second, Src.getOffset());
NH.setOffset(Src.getOffset());
NH.setNode(I->second);
} }
} }
@ -166,8 +166,8 @@ class DSCallSite {
hash_map<const DSNode*, DSNodeHandle>::const_iterator I = NodeMap.find(N); hash_map<const DSNode*, DSNodeHandle>::const_iterator I = NodeMap.find(N);
assert(I != NodeMap.end() && "Node not in mapping!"); assert(I != NodeMap.end() && "Node not in mapping!");
NH.setOffset(Src.getOffset()+I->second.getOffset()); DSNode *NN = I->second.getNode(); // Call getNode before getOffset()
NH.setNode(I->second.getNode()); NH.setTo(NN, Src.getOffset()+I->second.getOffset());
} }
} }

View File

@ -175,7 +175,7 @@ public:
void stopForwarding() { void stopForwarding() {
assert(isForwarding() && assert(isForwarding() &&
"Node isn't forwarding, cannot stopForwarding()!"); "Node isn't forwarding, cannot stopForwarding()!");
ForwardNH.setNode(0); ForwardNH.setTo(0, 0);
assert(ParentGraph == 0 && assert(ParentGraph == 0 &&
"Forwarding nodes must have been removed from graph!"); "Forwarding nodes must have been removed from graph!");
delete this; delete this;
@ -336,7 +336,7 @@ public:
void dropAllReferences() { void dropAllReferences() {
Links.clear(); Links.clear();
if (isForwarding()) if (isForwarding())
ForwardNH.setNode(0); ForwardNH.setTo(0, 0);
} }
/// remapLinks - Change all of the Links in the current node according to the /// remapLinks - Change all of the Links in the current node according to the
@ -401,10 +401,11 @@ inline DSNode *DSNodeHandle::getNode() const {
return HandleForwarding(); return HandleForwarding();
} }
inline void DSNodeHandle::setNode(DSNode *n) const { inline void DSNodeHandle::setTo(DSNode *n, unsigned NewOffset) const {
assert(!n || !n->isForwarding() && "Cannot set node to a forwarded node!"); assert(!n || !n->isForwarding() && "Cannot set node to a forwarded node!");
if (N) getNode()->NumReferrers--; if (N) getNode()->NumReferrers--;
N = n; N = n;
Offset = NewOffset;
if (N) { if (N) {
N->NumReferrers++; N->NumReferrers++;
if (Offset >= N->Size) { if (Offset >= N->Size) {
@ -457,8 +458,8 @@ inline void DSNodeHandle::mergeWith(const DSNodeHandle &Node) const {
getNode()->mergeWith(Node, Offset); getNode()->mergeWith(Node, Offset);
else { // No node to merge with, so just point to Node else { // No node to merge with, so just point to Node
Offset = 0; Offset = 0;
setNode(Node.getNode()); DSNode *NN = Node.getNode();
Offset = Node.getOffset(); setTo(NN, Node.getOffset());
} }
} }

View File

@ -58,17 +58,18 @@ class DSNodeHandle {
void operator==(const DSNode *N); // DISALLOW, use to promote N to nodehandle void operator==(const DSNode *N); // DISALLOW, use to promote N to nodehandle
public: public:
// Allow construction, destruction, and assignment... // Allow construction, destruction, and assignment...
DSNodeHandle(DSNode *n = 0, unsigned offs = 0) : N(0), Offset(offs) { DSNodeHandle(DSNode *n = 0, unsigned offs = 0) : N(0), Offset(0) {
setNode(n); setTo(n, offs);
} }
DSNodeHandle(const DSNodeHandle &H) : N(0), Offset(0) { DSNodeHandle(const DSNodeHandle &H) : N(0), Offset(0) {
setNode(H.getNode()); DSNode *NN = H.getNode();
Offset = H.Offset; // Must read offset AFTER the getNode() setTo(NN, H.Offset); // Must read offset AFTER the getNode()
} }
~DSNodeHandle() { setNode((DSNode*)0); } ~DSNodeHandle() { setTo(0, 0); }
DSNodeHandle &operator=(const DSNodeHandle &H) { DSNodeHandle &operator=(const DSNodeHandle &H) {
if (&H == this) return *this; // Don't set offset to 0 if self assigning. if (&H == this) return *this; // Don't set offset to 0 if self assigning.
Offset = 0; setNode(H.getNode()); Offset = H.Offset; DSNode *NN = H.getNode(); // Call getNode() before .Offset
setTo(NN, H.Offset);
return *this; return *this;
} }
@ -96,7 +97,6 @@ public:
inline DSNode *getNode() const; // Defined inline in DSNode.h inline DSNode *getNode() const; // Defined inline in DSNode.h
unsigned getOffset() const { return Offset; } unsigned getOffset() const { return Offset; }
inline void setNode(DSNode *N) const; // Defined inline in DSNode.h
void setOffset(unsigned O) { void setOffset(unsigned O) {
//assert((!N || Offset < N->Size || (N->Size == 0 && Offset == 0) || //assert((!N || Offset < N->Size || (N->Size == 0 && Offset == 0) ||
// !N->ForwardNH.isNull()) && "Node handle offset out of range!"); // !N->ForwardNH.isNull()) && "Node handle offset out of range!");
@ -105,6 +105,8 @@ public:
Offset = O; Offset = O;
} }
inline void setTo(DSNode *N, unsigned O) const; // Defined inline in DSNode.h
void addEdgeTo(unsigned LinkNo, const DSNodeHandle &N); void addEdgeTo(unsigned LinkNo, const DSNodeHandle &N);
void addEdgeTo(const DSNodeHandle &N) { addEdgeTo(0, N); } void addEdgeTo(const DSNodeHandle &N) { addEdgeTo(0, N); }
@ -154,9 +156,7 @@ class DSCallSite {
if (DSNode *N = Src.getNode()) { if (DSNode *N = Src.getNode()) {
hash_map<const DSNode*, DSNode*>::const_iterator I = NodeMap.find(N); hash_map<const DSNode*, DSNode*>::const_iterator I = NodeMap.find(N);
assert(I != NodeMap.end() && "Node not in mapping!"); assert(I != NodeMap.end() && "Node not in mapping!");
NH.setTo(I->second, Src.getOffset());
NH.setOffset(Src.getOffset());
NH.setNode(I->second);
} }
} }
@ -166,8 +166,8 @@ class DSCallSite {
hash_map<const DSNode*, DSNodeHandle>::const_iterator I = NodeMap.find(N); hash_map<const DSNode*, DSNodeHandle>::const_iterator I = NodeMap.find(N);
assert(I != NodeMap.end() && "Node not in mapping!"); assert(I != NodeMap.end() && "Node not in mapping!");
NH.setOffset(Src.getOffset()+I->second.getOffset()); DSNode *NN = I->second.getNode(); // Call getNode before getOffset()
NH.setNode(I->second.getNode()); NH.setTo(NN, Src.getOffset()+I->second.getOffset());
} }
} }

View File

@ -120,8 +120,7 @@ void DSNode::forwardNode(DSNode *To, unsigned Offset) {
if (To->Size <= 1) Offset = 0; if (To->Size <= 1) Offset = 0;
assert((Offset < To->Size || (Offset == To->Size && Offset == 0)) && assert((Offset < To->Size || (Offset == To->Size && Offset == 0)) &&
"Forwarded offset is wrong!"); "Forwarded offset is wrong!");
ForwardNH.setNode(To); ForwardNH.setTo(To, Offset);
ForwardNH.setOffset(Offset);
NodeType = DEAD; NodeType = DEAD;
Size = 0; Size = 0;
Ty = Type::VoidTy; Ty = Type::VoidTy;
@ -1096,10 +1095,9 @@ void DSNode::remapLinks(DSGraph::NodeMapTy &OldNodeMap) {
for (unsigned i = 0, e = Links.size(); i != e; ++i) for (unsigned i = 0, e = Links.size(); i != e; ++i)
if (DSNode *N = Links[i].getNode()) { if (DSNode *N = Links[i].getNode()) {
DSGraph::NodeMapTy::const_iterator ONMI = OldNodeMap.find(N); DSGraph::NodeMapTy::const_iterator ONMI = OldNodeMap.find(N);
if (ONMI != OldNodeMap.end()) { if (ONMI != OldNodeMap.end())
Links[i].setNode(ONMI->second.getNode()); Links[i].setTo(ONMI->second.getNode(),
Links[i].setOffset(Links[i].getOffset()+ONMI->second.getOffset()); Links[i].getOffset()+ONMI->second.getOffset());
}
} }
} }
@ -1475,7 +1473,7 @@ static inline void killIfUselessEdge(DSNodeHandle &Edge) {
// No interesting info? // No interesting info?
if ((N->getNodeFlags() & ~DSNode::Incomplete) == 0 && if ((N->getNodeFlags() & ~DSNode::Incomplete) == 0 &&
N->getType() == Type::VoidTy && !N->isNodeCompletelyFolded()) N->getType() == Type::VoidTy && !N->isNodeCompletelyFolded())
Edge.setNode(0); // Kill the edge! Edge.setTo(0, 0); // Kill the edge!
} }
static inline bool nodeContainsExternalFunction(const DSNode *N) { static inline bool nodeContainsExternalFunction(const DSNode *N) {
@ -1979,8 +1977,7 @@ void DSGraph::computeNodeMapping(const DSNodeHandle &NH1,
return; return;
} }
Entry.setNode(N2); Entry.setTo(N2, NH2.getOffset()-NH1.getOffset());
Entry.setOffset(NH2.getOffset()-NH1.getOffset());
// Loop over all of the fields that N1 and N2 have in common, recursively // Loop over all of the fields that N1 and N2 have in common, recursively
// mapping the edges together now. // mapping the edges together now.

View File

@ -259,8 +259,7 @@ DSNodeHandle GraphBuilder::getValueDest(Value &Val) {
N = createNode(); N = createNode();
} }
NH.setNode(N); // Remember that we are pointing to it... NH.setTo(N, 0); // Remember that we are pointing to it...
NH.setOffset(0);
return NH; return NH;
} }