diff --git a/src/V3Ast.h b/src/V3Ast.h index 8e97c4e34..8c6282876 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -1502,7 +1502,7 @@ public: // nodes needs to be deferred to a later time, because pointers to the // removed nodes might still exist. -class VNDeleter VL_NOT_FINAL { +class VNDeleter final { // MEMBERS std::vector m_deleteps; // Nodes to delete @@ -1515,11 +1515,11 @@ public: m_deleteps.push_back(nodep); } - // Delete all previously pushed nodes (by callint deleteTree) + // Delete all previously pushed nodes (by calling deleteTree) void doDeletes(); // Do the deletions on destruction - virtual ~VNDeleter() { doDeletes(); } + ~VNDeleter() { doDeletes(); } }; //###################################################################### @@ -1528,7 +1528,7 @@ public: // This only has the constant fuctions for non-modifying visitors. // For more typical usage see VNVisitor -class VNVisitorConst VL_NOT_FINAL : public VNDeleter { +class VNVisitorConst VL_NOT_FINAL { friend class AstNode; public: @@ -1546,6 +1546,7 @@ public: inline void iterateAndNextConstNullBackwards(AstNode* nodep); virtual void visit(AstNode* nodep) = 0; + virtual ~VNVisitorConst() {} #include "V3Ast__gen_visitor_decls.h" // From ./astgen }; @@ -1554,6 +1555,7 @@ public: // type without changing the base classes. See "Modern C++ Design". class VNVisitor VL_NOT_FINAL : public VNVisitorConst { + VNDeleter m_deleter; // Used to delay deletion of nodes public: /// Call visit()s on nodep inline void iterate(AstNode* nodep); @@ -1565,6 +1567,10 @@ public: inline void iterateAndNextNull(AstNode* nodep); /// Return edited nodep; see comments in V3Ast.cpp inline AstNode* iterateSubtreeReturnEdits(AstNode* nodep); + + VNDeleter& deleter() { return m_deleter; } + void pushDeletep(AstNode* nodep) { deleter().pushDeletep(nodep); } + void doDeletes() { deleter().doDeletes(); } }; //###################################################################### diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 1435d3ab0..c2b3e1b1b 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -673,7 +673,7 @@ public: // Reduction ops are transformed in the same way. // &{v[0], v[1]} => 2'b11 == (2'b11 & v) static AstNodeExpr* simplify(AstNodeExpr* nodep, int resultWidth, unsigned externalOps, - VDouble0& reduction) { + VDouble0& reduction, VNDeleter& deleterr) { UASSERT_OBJ(1 <= resultWidth && resultWidth <= 64, nodep, "resultWidth out of range"); // Walk tree, gathering all terms referenced in expression @@ -716,7 +716,7 @@ public: } // Set width and widthMin precisely resultp->dtypeChgWidth(resultWidth, 1); - for (AstNode* const termp : termps) termp->deleteTree(); + for (AstNode* const termp : termps) deleterr.pushDeletep(termp); return resultp; } const ResultTerm result = v->getResultTerm(); @@ -792,7 +792,7 @@ public: // Only substitute the result if beneficial as determined by operation count if (visitor.m_ops <= resultOps) { - for (AstNode* const termp : termps) termp->deleteTree(); + for (AstNode* const termp : termps) deleterr.pushDeletep(termp); return nullptr; } @@ -1012,7 +1012,7 @@ private: return (lp && rp && lp->width() == rp->width() && lp->type() == rp->type() && (operandsSame(lp->lhsp(), rp->lhsp()) || operandsSame(lp->rhsp(), rp->rhsp()))); } - static bool matchOrAndNot(AstNodeBiop* nodep) { + bool matchOrAndNot(AstNodeBiop* nodep) { // AstOr{$a, AstAnd{AstNot{$b}, $c}} if $a.width1, $a==$b => AstOr{$a,$c} // Someday we'll sort the biops completely and this can be simplified // This often results from our simplified clock generation: @@ -1043,7 +1043,7 @@ private: if (!operandsSame(ap, bp)) return false; // Do it cp->unlinkFrBack(); - VL_DO_DANGLING(andp->unlinkFrBack()->deleteTree(), andp); + VL_DO_DANGLING(pushDeletep(andp->unlinkFrBack()), andp); VL_DANGLING(notp); // Replace whichever branch is now dangling if (nodep->rhsp()) { @@ -1175,9 +1175,11 @@ private: const AstAnd* const andp = VN_CAST(nodep, And); const int width = nodep->width(); if (andp && isConst(andp->lhsp(), 1)) { // 1 & BitOpTree - newp = ConstBitOpTreeVisitor::simplify(andp->rhsp(), width, 1, m_statBitOpReduction); + newp = ConstBitOpTreeVisitor::simplify(andp->rhsp(), width, 1, m_statBitOpReduction, + deleter()); } else { // BitOpTree - newp = ConstBitOpTreeVisitor::simplify(nodep, width, 0, m_statBitOpReduction); + newp = ConstBitOpTreeVisitor::simplify(nodep, width, 0, m_statBitOpReduction, + deleter()); } if (newp) { diff --git a/src/V3Order.cpp b/src/V3Order.cpp index f0047b81e..c3ba10a93 100644 --- a/src/V3Order.cpp +++ b/src/V3Order.cpp @@ -801,7 +801,7 @@ struct MTaskVxIdLessThan final { //###################################################################### // OrderProcess class -class OrderProcess final : VNDeleter { +class OrderProcess final { // NODE STATE // AstNode::user4 -> Used by V3Const::constifyExpensiveEdit @@ -829,6 +829,7 @@ class OrderProcess final : VNDeleter { friend class OrderMoveDomScope; V3List m_pomReadyDomScope; // List of ready domain/scope pairs, by loopId std::map, unsigned> m_funcNums; // Function ordinals + VNDeleter m_deleter; // Used to delay deletion of nodes // METHODS @@ -900,10 +901,10 @@ class OrderProcess final : VNDeleter { , m_deleteDomainp{makeDeleteDomainSenTree(netlistp->fileline())} , m_tag{tag} , m_slow{slow} { - pushDeletep(m_deleteDomainp); + m_deleter.pushDeletep(m_deleteDomainp); } - ~OrderProcess() override = default; + ~OrderProcess() = default; public: // Order the logic @@ -1223,7 +1224,7 @@ AstActive* OrderProcess::processMoveOneLogic(const OrderLogicVertex* lvertexp, needProcess = procp->needProcess(); if (suspendable) slow = slow && !VN_IS(procp, Always); nodep = procp->stmtsp(); - pushDeletep(procp); + m_deleter.pushDeletep(procp); } // Put suspendable processes into individual functions on their own @@ -1270,7 +1271,7 @@ AstActive* OrderProcess::processMoveOneLogic(const OrderLogicVertex* lvertexp, if (nodep->backp()) nodep->unlinkFrBack(); if (domainp == m_deleteDomainp) { - VL_DO_DANGLING(pushDeletep(nodep), nodep); + VL_DO_DANGLING(m_deleter.pushDeletep(nodep), nodep); } else { newFuncpr->addStmtsp(nodep); // Add in the number of nodes we're adding diff --git a/src/V3Param.cpp b/src/V3Param.cpp index 8bc5358a6..2479c7f0d 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -223,7 +223,7 @@ public: //###################################################################### // Remove parameters from cells and build new modules -class ParamProcessor final : public VNDeleter { +class ParamProcessor final { // NODE STATE - Local // AstVar::user4() // int Global parameter number (for naming new module) // // (0=not processed, 1=iterated, but no number, @@ -277,6 +277,7 @@ class ParamProcessor final : public VNDeleter { using DefaultValueMap = std::map; // Default parameter values of hierarchical blocks std::map m_defaultParameterValues; + VNDeleter m_deleter; // Used to delay deletion of nodes // METHODS @@ -868,7 +869,7 @@ class ParamProcessor final : public VNDeleter { AstClass* classCopyp = VN_AS(srcModpr, Class)->cloneTree(false); // It is a temporary copy of the original class node, stored in order to create // another instances. It is needed only during class instantiation. - pushDeletep(classCopyp); + m_deleter.pushDeletep(classCopyp); srcModpr->user4p(classCopyp); storeOriginalParams(classCopyp); }