Internal cleanups towards recursive functions (#3267)

This commit is contained in:
Wilson Snyder
2022-01-04 20:19:58 -05:00
parent 4e5f30858b
commit 41a563bdc8
2 changed files with 51 additions and 12 deletions
+12 -4
View File
@@ -39,6 +39,7 @@ private:
V3Hash hashNodeAndIterate(AstNode* nodep, bool hashDType, bool hashChildren,
std::function<void()>&& f) {
// See comments in visit(AstCFunc) about this breaking recursion
if (m_cacheInUser4 && nodep->user4()) {
return V3Hash(nodep->user4());
} else {
@@ -393,6 +394,12 @@ private:
}
virtual void visit(AstCFunc* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { //
// We might be in a recursive function, if so on *second* call
// here we need to break what would be an infinite loop.
nodep->user4(V3Hash(1).value()); // Set this "first" call
// So that a second call will then exit hashNodeAndIterate
// Having a constant in the hash just means the recursion will
// end, it shouldn't change the CFunc having a unique hash itself.
m_hash += nodep->isLoose();
});
}
@@ -488,11 +495,12 @@ private:
public:
// CONSTRUCTORS
explicit HasherVisitor(AstNode* nodep)
HasherVisitor(AstNode* nodep)
: m_cacheInUser4{true} {
iterate(nodep);
}
explicit HasherVisitor(const AstNode* nodep)
class Uncached {};
HasherVisitor(const AstNode* nodep, Uncached)
: m_cacheInUser4{false} {
iterate(const_cast<AstNode*>(nodep));
}
@@ -504,11 +512,11 @@ public:
// V3Hasher methods
V3Hash V3Hasher::operator()(AstNode* nodep) const {
if (!nodep->user4()) { HasherVisitor{nodep}; }
if (!nodep->user4()) HasherVisitor{nodep};
return V3Hash(nodep->user4());
}
V3Hash V3Hasher::uncachedHash(const AstNode* nodep) {
const HasherVisitor visitor{nodep};
const HasherVisitor visitor{nodep, HasherVisitor::Uncached{}};
return visitor.finalHash();
}