Internals: Add new VL_RESTORER flavours (#7866)
Restrict VL_RESTORER to be usable only with trivially copyable types. Introduce VL_RESTORER_COPY and VL_RESTORER_CLEAR, which are more efficient versions usable for non trivially copyable types. VL_RESTORER_COPY semantically behaves the same as VL_RESTORER, but only does one copy at initialization, and on scope exit restores via a move. VL_RESTORER_CLEAR swaps the variable with an new one constructed via the no-args constructor (e.g. empty collection), which does not require any copying at any point. Static assertions enforce picking one of the new flavours when copying might be expensive.
This commit is contained in:
parent
83eb54ec7e
commit
566f4e6efc
|
|
@ -1153,12 +1153,11 @@ class AssertVisitor final : public VNVisitor {
|
|||
VL_RESTORER(m_modp);
|
||||
VL_RESTORER(m_modPastNum);
|
||||
VL_RESTORER(m_modStrobeNum);
|
||||
VL_RESTORER(m_modExpr2Sen2DelayedAlwaysp);
|
||||
VL_RESTORER(m_finalp);
|
||||
VL_RESTORER_CLEAR(m_modExpr2Sen2DelayedAlwaysp);
|
||||
m_modp = nodep;
|
||||
m_modPastNum = 0;
|
||||
m_modStrobeNum = 0;
|
||||
m_modExpr2Sen2DelayedAlwaysp.clear();
|
||||
m_finalp = nullptr;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,12 +137,9 @@ class BeginVisitor final : public VNVisitor {
|
|||
UINFO(8, " rename to " << nodep->name());
|
||||
m_statep->userMarkChanged(nodep);
|
||||
}
|
||||
VL_RESTORER(m_displayScope);
|
||||
VL_RESTORER(m_namedScope);
|
||||
VL_RESTORER(m_unnamedScope);
|
||||
m_displayScope = "";
|
||||
m_namedScope = "";
|
||||
m_unnamedScope = "";
|
||||
VL_RESTORER_CLEAR(m_displayScope);
|
||||
VL_RESTORER_CLEAR(m_namedScope);
|
||||
VL_RESTORER_CLEAR(m_unnamedScope);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
void visit(AstNodeProcedure* nodep) override {
|
||||
|
|
@ -163,14 +160,13 @@ class BeginVisitor final : public VNVisitor {
|
|||
// naming; so that any begin's inside the function will rename
|
||||
// inside the function.
|
||||
// Process children
|
||||
VL_RESTORER(m_displayScope);
|
||||
VL_RESTORER_COPY(m_displayScope);
|
||||
VL_RESTORER(m_ftaskp);
|
||||
VL_RESTORER(m_liftedp);
|
||||
VL_RESTORER(m_namedScope);
|
||||
VL_RESTORER(m_unnamedScope);
|
||||
VL_RESTORER_CLEAR(m_namedScope);
|
||||
VL_RESTORER_CLEAR(m_unnamedScope);
|
||||
m_displayScope = dot(m_displayScope, nodep->name());
|
||||
m_namedScope = "";
|
||||
m_unnamedScope = "";
|
||||
|
||||
m_ftaskp = nodep;
|
||||
m_liftedp = nullptr;
|
||||
iterateChildren(nodep);
|
||||
|
|
@ -191,9 +187,9 @@ class BeginVisitor final : public VNVisitor {
|
|||
void visit(AstGenBlock* nodep) override {
|
||||
// GenBlocks were only useful in variable creation, change names and delete
|
||||
UINFO(8, " " << nodep);
|
||||
VL_RESTORER(m_displayScope);
|
||||
VL_RESTORER(m_namedScope);
|
||||
VL_RESTORER(m_unnamedScope);
|
||||
VL_RESTORER_COPY(m_displayScope);
|
||||
VL_RESTORER_COPY(m_namedScope);
|
||||
VL_RESTORER_COPY(m_unnamedScope);
|
||||
UASSERT_OBJ(!m_keepBegins, nodep, "Should be able to eliminate all AstGenBlock");
|
||||
dotNames(nodep->name(), nodep->fileline(), "__BEGIN__");
|
||||
iterateAndNextNull(nodep->itemsp());
|
||||
|
|
@ -227,9 +223,9 @@ class BeginVisitor final : public VNVisitor {
|
|||
void visit(AstBegin* nodep) override {
|
||||
// Begin blocks were only useful in variable creation, change names and delete
|
||||
UINFO(8, " " << nodep);
|
||||
VL_RESTORER(m_displayScope);
|
||||
VL_RESTORER(m_namedScope);
|
||||
VL_RESTORER(m_unnamedScope);
|
||||
VL_RESTORER_COPY(m_displayScope);
|
||||
VL_RESTORER_COPY(m_namedScope);
|
||||
VL_RESTORER_COPY(m_unnamedScope);
|
||||
{
|
||||
VL_RESTORER(m_keepBegins);
|
||||
m_keepBegins = false;
|
||||
|
|
@ -261,9 +257,9 @@ class BeginVisitor final : public VNVisitor {
|
|||
void visit(AstNodeBlock* nodep) override {
|
||||
// Begin/Fork blocks were only useful in variable creation, change names and delete
|
||||
UINFO(8, " " << nodep);
|
||||
VL_RESTORER(m_displayScope);
|
||||
VL_RESTORER(m_namedScope);
|
||||
VL_RESTORER(m_unnamedScope);
|
||||
VL_RESTORER_COPY(m_displayScope);
|
||||
VL_RESTORER_COPY(m_namedScope);
|
||||
VL_RESTORER_COPY(m_unnamedScope);
|
||||
{
|
||||
VL_RESTORER(m_keepBegins);
|
||||
m_keepBegins = VN_IS(nodep, Fork);
|
||||
|
|
|
|||
|
|
@ -252,18 +252,15 @@ private:
|
|||
void visit(AstScope* nodep) override {
|
||||
VL_RESTORER(m_inScope);
|
||||
m_inScope = true;
|
||||
VL_RESTORER(m_cFuncNames);
|
||||
m_cFuncNames.clear();
|
||||
VL_RESTORER_CLEAR(m_cFuncNames);
|
||||
processAndIterate(nodep);
|
||||
}
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
VL_RESTORER(m_cFuncNames);
|
||||
m_cFuncNames.clear();
|
||||
VL_RESTORER_CLEAR(m_cFuncNames);
|
||||
processAndIterate(nodep);
|
||||
}
|
||||
void visit(AstNodeUOrStructDType* nodep) override {
|
||||
VL_RESTORER(m_cFuncNames);
|
||||
m_cFuncNames.clear();
|
||||
VL_RESTORER_CLEAR(m_cFuncNames);
|
||||
processAndIterate(nodep);
|
||||
}
|
||||
void visit(AstNodeVarRef* nodep) override {
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ class ClassVisitor final : public VNVisitor {
|
|||
classScopep->aboveScopep(), classScopep->aboveCellp()};
|
||||
packagep->addStmtsp(scopep);
|
||||
// Iterate
|
||||
VL_RESTORER(m_prefix);
|
||||
VL_RESTORER_CLEAR(m_prefix);
|
||||
VL_RESTORER(m_classPackagep);
|
||||
VL_RESTORER(m_classScopep);
|
||||
VL_RESTORER(m_packageScopep);
|
||||
|
|
@ -129,7 +129,7 @@ class ClassVisitor final : public VNVisitor {
|
|||
void visit(AstNodeModule* nodep) override {
|
||||
// Visit for NodeModules that are not AstClass (AstClass is-a AstNodeModule)
|
||||
// Classes are always under a Package (perhaps $unit) or a module
|
||||
VL_RESTORER(m_prefix);
|
||||
VL_RESTORER_CLEAR(m_prefix);
|
||||
VL_RESTORER(m_modp);
|
||||
m_modp = nodep;
|
||||
m_prefix = nodep->name() + "__03a__03a"; // ::
|
||||
|
|
|
|||
|
|
@ -279,8 +279,8 @@ class CoverageVisitor final : public VNVisitor {
|
|||
const AstNodeModule* const origModp = m_modp;
|
||||
VL_RESTORER(m_modp);
|
||||
VL_RESTORER(m_state);
|
||||
VL_RESTORER(m_exprTempNames);
|
||||
VL_RESTORER(m_funcTemps);
|
||||
VL_RESTORER_COPY(m_exprTempNames);
|
||||
VL_RESTORER_COPY(m_funcTemps);
|
||||
createHandle(nodep);
|
||||
m_modp = nodep;
|
||||
m_state.m_inModOff = false; // Haven't made top shell, so tops are real tops
|
||||
|
|
@ -294,8 +294,8 @@ class CoverageVisitor final : public VNVisitor {
|
|||
void visit(AstClass* nodep) override {
|
||||
VL_RESTORER(m_modp);
|
||||
VL_RESTORER(m_state);
|
||||
VL_RESTORER(m_exprTempNames);
|
||||
VL_RESTORER(m_funcTemps);
|
||||
VL_RESTORER_COPY(m_exprTempNames);
|
||||
VL_RESTORER_COPY(m_funcTemps);
|
||||
createHandle(nodep);
|
||||
m_modp = nodep;
|
||||
// Covergroup declarations are not executable statements; suppress line/expr/toggle
|
||||
|
|
@ -356,8 +356,8 @@ class CoverageVisitor final : public VNVisitor {
|
|||
|
||||
void visit(AstNodeFTask* nodep) override {
|
||||
VL_RESTORER(m_ftaskp);
|
||||
VL_RESTORER(m_exprTempNames);
|
||||
VL_RESTORER(m_funcTemps);
|
||||
VL_RESTORER_COPY(m_exprTempNames);
|
||||
VL_RESTORER_COPY(m_funcTemps);
|
||||
m_ftaskp = nodep;
|
||||
if (!nodep->dpiImport()) iterateProcedure(nodep);
|
||||
}
|
||||
|
|
@ -762,7 +762,7 @@ class CoverageVisitor final : public VNVisitor {
|
|||
}
|
||||
void visit(AstGenBlock* nodep) override {
|
||||
// Similar to AstBegin
|
||||
VL_RESTORER(m_beginHier);
|
||||
VL_RESTORER_COPY(m_beginHier);
|
||||
if (nodep->name() != "") {
|
||||
m_beginHier = m_beginHier + (m_beginHier != "" ? "__DOT__" : "") + nodep->name();
|
||||
}
|
||||
|
|
@ -776,7 +776,7 @@ class CoverageVisitor final : public VNVisitor {
|
|||
// generate blocks; each point should get separate consideration.
|
||||
// (Currently ignored for line coverage, since any generate iteration
|
||||
// covers the code in that line.)
|
||||
VL_RESTORER(m_beginHier);
|
||||
VL_RESTORER_COPY(m_beginHier);
|
||||
VL_RESTORER(m_inToggleOff);
|
||||
VL_RESTORER(m_exprStmtsp);
|
||||
m_exprStmtsp = nodep;
|
||||
|
|
@ -874,7 +874,7 @@ class CoverageVisitor final : public VNVisitor {
|
|||
UASSERT_OBJ(m_exprs.empty(), nodep, "unexpected expression coverage garbage");
|
||||
VL_RESTORER(m_seeking);
|
||||
VL_RESTORER(m_objective);
|
||||
VL_RESTORER(m_exprs);
|
||||
VL_RESTORER_CLEAR(m_exprs); // Already asserted above it's empty.
|
||||
|
||||
m_seeking = SEEKING;
|
||||
m_objective = false;
|
||||
|
|
|
|||
|
|
@ -1727,15 +1727,12 @@ class FunctionalCoverageVisitor final : public VNVisitor {
|
|||
VL_RESTORER(m_covergroupp);
|
||||
VL_RESTORER(m_sampleFuncp);
|
||||
VL_RESTORER(m_constructorp);
|
||||
VL_RESTORER(m_coverpoints);
|
||||
VL_RESTORER(m_coverpointMap);
|
||||
VL_RESTORER(m_coverCrosses);
|
||||
VL_RESTORER_CLEAR(m_coverpoints);
|
||||
VL_RESTORER_CLEAR(m_coverpointMap);
|
||||
VL_RESTORER_CLEAR(m_coverCrosses);
|
||||
m_covergroupp = nodep;
|
||||
m_sampleFuncp = nullptr;
|
||||
m_constructorp = nullptr;
|
||||
m_coverpoints.clear();
|
||||
m_coverpointMap.clear();
|
||||
m_coverCrosses.clear();
|
||||
|
||||
// Extract and store the clocking event from AstCovergroup node
|
||||
// The parser creates this node to preserve the event information
|
||||
|
|
|
|||
|
|
@ -1050,8 +1050,7 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
|
|||
if (nodep->packed()) puts("packed ");
|
||||
{
|
||||
puts("{\n");
|
||||
VL_RESTORER(m_packedps);
|
||||
m_packedps.clear();
|
||||
VL_RESTORER_CLEAR(m_packedps);
|
||||
for (AstMemberDType* itemp = nodep->membersp(); itemp;
|
||||
itemp = VN_AS(itemp->nextp(), MemberDType)) {
|
||||
iterateConst(itemp);
|
||||
|
|
|
|||
|
|
@ -561,10 +561,9 @@ class ForkVisitor final : public VNVisitor {
|
|||
// replace body with a call to that task. Returns true iff wrapped.
|
||||
bool taskify(AstBegin* beginp) {
|
||||
// Visit statement to gather variables (And recursively process)
|
||||
VL_RESTORER(m_forkLocalsp);
|
||||
VL_RESTORER_CLEAR(m_forkLocalsp);
|
||||
VL_RESTORER(m_capturedVarsp);
|
||||
VL_RESTORER(m_capturedArgsp);
|
||||
m_forkLocalsp.clear();
|
||||
m_capturedVarsp = nullptr;
|
||||
m_capturedArgsp = nullptr;
|
||||
iterate(beginp);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
|
|
@ -44,27 +45,90 @@ class V3ThreadPool;
|
|||
//======================================================================
|
||||
// Restorer
|
||||
|
||||
/// Save a given variable's value on the stack, restoring it at end-of-scope.
|
||||
// Object must be named, or it will not persist until end-of-scope.
|
||||
// Constructor needs () or GCC 4.8 false warning.
|
||||
#define VL_RESTORER(var) const VRestorer<typename std::decay_t<decltype(var)>> restorer_##var(var);
|
||||
/// Get the copy of the variable previously saved by VL_RESTORER()
|
||||
// For all flavours, 'var' must be a named scalar variable (simple identifier).
|
||||
|
||||
// Copy given variable's value on the stack, copy saved value back at end-of-scope.
|
||||
// Only usable for trivially copyable types; use VL_RESTORER_COPY/VL_RESTORER_CLEAR for
|
||||
// non-trivially copyable types, which are more efficient.
|
||||
#define VL_RESTORER(var) \
|
||||
const VRestorerTrivial<typename std::decay_t<decltype(var)>> restorer_##var(var);
|
||||
|
||||
// This is the equivalent of VL_RESTORER for non-trivially copyable types. Still more efficient
|
||||
// than VL_RESTORER as uses move to restore.
|
||||
#define VL_RESTORER_COPY(var) \
|
||||
const VRestorerCopy<typename std::decay_t<decltype(var)>> restorer_##var(var);
|
||||
|
||||
// Swap 'var' with a no-args constructed object of the same type, effectively clearing it, then
|
||||
// swap back at end-of-scope. No copying involved. Use this e.g. for std containers where they
|
||||
// would be .clear()'d right after the VL_RESTORER instance.
|
||||
#define VL_RESTORER_CLEAR(var) \
|
||||
const VRestorerClear<typename std::decay_t<decltype(var)>> restorer_##var(var);
|
||||
|
||||
// Get const reference to the saved copy
|
||||
#define VL_RESTORER_PREV(var) restorer_##var.saved()
|
||||
|
||||
// Object used by VL_RESTORER. This object must be an auto variable, not
|
||||
// allocated on the heap or otherwise.
|
||||
// Implementation of VL_RESTORER
|
||||
template <typename T>
|
||||
class VRestorer final {
|
||||
class VRestorerTrivial final {
|
||||
static_assert(std::is_trivially_copyable<T>::value,
|
||||
"Use VL_RESTORER_{COPY,CLEAR} for non trivially copyable types");
|
||||
T& m_ref; // Reference to object we're saving and restoring
|
||||
const T m_saved; // Value saved, for later restore
|
||||
|
||||
public:
|
||||
explicit VRestorer(T& permr)
|
||||
: m_ref{permr}
|
||||
, m_saved{permr} {}
|
||||
~VRestorer() { m_ref = m_saved; }
|
||||
explicit VRestorerTrivial(T& val)
|
||||
: m_ref{val}
|
||||
, m_saved{val} {}
|
||||
~VRestorerTrivial() { m_ref = m_saved; }
|
||||
VL_UNCOPYABLE(VRestorerTrivial);
|
||||
// Must be stack allocated
|
||||
void* operator new(size_t) = delete;
|
||||
void operator delete(void*) = delete;
|
||||
|
||||
const T& saved() const { return m_saved; }
|
||||
};
|
||||
|
||||
// Implementation of VL_RESTORER_COPY
|
||||
template <typename T>
|
||||
class VRestorerCopy final {
|
||||
static_assert(!std::is_trivially_copyable<T>::value,
|
||||
"Use VL_RESTORER for trivially copyable types");
|
||||
T& m_ref; // Reference to object we're saving and restoring
|
||||
T m_saved; // Value saved, for later restore
|
||||
|
||||
public:
|
||||
explicit VRestorerCopy(T& val)
|
||||
: m_ref{val}
|
||||
, m_saved{val} {}
|
||||
~VRestorerCopy() { m_ref = std::move(m_saved); }
|
||||
VL_UNCOPYABLE(VRestorerCopy);
|
||||
// Must be stack allocated
|
||||
void* operator new(size_t) = delete;
|
||||
void operator delete(void*) = delete;
|
||||
|
||||
const T& saved() const { return m_saved; }
|
||||
};
|
||||
|
||||
// Implementation of VL_RESTORER_CLEAR.
|
||||
template <typename T>
|
||||
class VRestorerClear final {
|
||||
static_assert(!std::is_trivially_copyable<T>::value,
|
||||
"Use VL_RESTORER for trivially copyable types");
|
||||
T& m_ref; // Reference to object we're saving and restoring
|
||||
T m_saved{}; // Owns the swapped-out value; starts empty
|
||||
|
||||
public:
|
||||
explicit VRestorerClear(T& val)
|
||||
: m_ref{val} {
|
||||
std::swap(m_ref, m_saved);
|
||||
}
|
||||
~VRestorerClear() { std::swap(m_ref, m_saved); }
|
||||
VL_UNCOPYABLE(VRestorerClear);
|
||||
// Must be stack allocated
|
||||
void* operator new(size_t) = delete;
|
||||
void operator delete(void*) = delete;
|
||||
|
||||
const T& saved() const { return m_saved; }
|
||||
VL_UNCOPYABLE(VRestorer);
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
|
|
@ -331,12 +331,9 @@ class HierBlockUsageCollectVisitor final : public VNVisitorConst {
|
|||
}
|
||||
|
||||
// This is a hierarchical block, gather parts
|
||||
VL_RESTORER(m_params);
|
||||
VL_RESTORER(m_typeParams);
|
||||
VL_RESTORER(m_childrenp);
|
||||
m_params.clear();
|
||||
m_typeParams.clear();
|
||||
m_childrenp.clear();
|
||||
VL_RESTORER_CLEAR(m_params);
|
||||
VL_RESTORER_CLEAR(m_typeParams);
|
||||
VL_RESTORER_CLEAR(m_childrenp);
|
||||
iterateChildrenConst(nodep);
|
||||
// Create the graph vertex for this hier block
|
||||
V3HierBlock* const blockp = new V3HierBlock{m_graphp, nodep, m_params, m_typeParams};
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ class InlineIntfRefVisitor final : public VNVisitor {
|
|||
// VISITORS
|
||||
void visit(AstNetlist* nodep) override { iterateChildren(nodep->topModulep()); }
|
||||
void visit(AstCell* nodep) override {
|
||||
VL_RESTORER(m_scope);
|
||||
VL_RESTORER_COPY(m_scope);
|
||||
if (m_scope.empty()) {
|
||||
m_scope = nodep->name();
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -47,8 +47,8 @@ class LibMapVisitor final : public VNVisitor {
|
|||
}
|
||||
|
||||
void visit(AstLibrary* nodep) override {
|
||||
VL_RESTORER(m_lib);
|
||||
VL_RESTORER(m_rel);
|
||||
VL_RESTORER_CLEAR(m_lib);
|
||||
VL_RESTORER_CLEAR(m_rel);
|
||||
m_lib = nodep->name();
|
||||
m_rel = V3Os::filenameDir(nodep->fileline()->filename());
|
||||
iterateChildren(nodep);
|
||||
|
|
|
|||
|
|
@ -157,11 +157,11 @@ class LinkConfigsVisitor final : public VNVisitor {
|
|||
m_isDefault = true;
|
||||
iterateAndNextNull(nodep->usep());
|
||||
} else if (nodep->isCell()) {
|
||||
VL_RESTORER(m_cell);
|
||||
VL_RESTORER_CLEAR(m_cell);
|
||||
m_cell = nodep->cellp()->name();
|
||||
iterateAndNextNull(nodep->usep());
|
||||
} else {
|
||||
VL_RESTORER(m_hierInst);
|
||||
VL_RESTORER_COPY(m_hierInst);
|
||||
{
|
||||
VL_RESTORER(m_dotp);
|
||||
m_dotp = VN_AS(nodep->cellp(), Dot);
|
||||
|
|
|
|||
|
|
@ -1259,7 +1259,7 @@ class LinkDotFindVisitor final : public VNVisitor {
|
|||
const bool standalonePkg
|
||||
= !m_modSymp && (m_statep->forPrearray() && VN_IS(nodep, Package));
|
||||
const bool doit = (m_modSymp || standalonePkg);
|
||||
VL_RESTORER(m_scope);
|
||||
VL_RESTORER_COPY(m_scope);
|
||||
VL_RESTORER(m_classOrPackagep);
|
||||
VL_RESTORER(m_modSymp);
|
||||
VL_RESTORER(m_curSymp);
|
||||
|
|
@ -1335,7 +1335,7 @@ class LinkDotFindVisitor final : public VNVisitor {
|
|||
void visit(AstClass* nodep) override { // FindVisitor::
|
||||
UASSERT_OBJ(m_curSymp, nodep, "Class not under module/package/$unit");
|
||||
UINFO(8, " " << nodep);
|
||||
VL_RESTORER(m_scope);
|
||||
VL_RESTORER_COPY(m_scope);
|
||||
VL_RESTORER(m_classOrPackagep);
|
||||
VL_RESTORER(m_modSymp);
|
||||
VL_RESTORER(m_curSymp);
|
||||
|
|
@ -1384,7 +1384,7 @@ class LinkDotFindVisitor final : public VNVisitor {
|
|||
if (nodep->recursive() && m_inRecursion) return;
|
||||
iterateChildren(nodep);
|
||||
// Recurse in, preserving state
|
||||
VL_RESTORER(m_scope);
|
||||
VL_RESTORER_COPY(m_scope);
|
||||
VL_RESTORER(m_modSymp);
|
||||
VL_RESTORER(m_curSymp);
|
||||
VL_RESTORER(m_paramNum);
|
||||
|
|
@ -3584,7 +3584,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
|
||||
void symIterateChildren(AstNode* nodep, VSymEnt* symp) {
|
||||
// Iterate children, changing to given context, with restore to old context
|
||||
VL_RESTORER(m_ds);
|
||||
VL_RESTORER_COPY(m_ds);
|
||||
VL_RESTORER(m_curSymp);
|
||||
m_curSymp = symp;
|
||||
m_ds.init(m_curSymp);
|
||||
|
|
@ -3592,7 +3592,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
}
|
||||
void symIterateNull(AstNode* nodep, VSymEnt* symp) {
|
||||
// Iterate node, changing to given context, with restore to old context
|
||||
VL_RESTORER(m_ds);
|
||||
VL_RESTORER_COPY(m_ds);
|
||||
VL_RESTORER(m_curSymp);
|
||||
m_curSymp = symp;
|
||||
m_ds.init(m_curSymp);
|
||||
|
|
@ -3805,10 +3805,8 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
LINKDOT_VISIT_START();
|
||||
UINFO(5, indent() << "visit " << nodep);
|
||||
checkNoDot(nodep);
|
||||
VL_RESTORER(m_usedPins);
|
||||
VL_RESTORER(m_usedDefParamPins);
|
||||
m_usedPins.clear();
|
||||
m_usedDefParamPins.clear();
|
||||
VL_RESTORER_CLEAR(m_usedPins);
|
||||
VL_RESTORER_CLEAR(m_usedDefParamPins);
|
||||
UASSERT_OBJ(nodep->modp(), nodep,
|
||||
"Instance has unlinked module"); // V3LinkCell should have errored out
|
||||
VL_RESTORER(m_cellp);
|
||||
|
|
@ -3845,10 +3843,8 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
LINKDOT_VISIT_START();
|
||||
UINFO(5, indent() << "visit " << nodep);
|
||||
// Can be under dot if called as package::class and that class resolves, so no checkNoDot
|
||||
VL_RESTORER(m_usedPins);
|
||||
VL_RESTORER(m_usedDefParamPins);
|
||||
m_usedPins.clear();
|
||||
m_usedDefParamPins.clear();
|
||||
VL_RESTORER_CLEAR(m_usedPins);
|
||||
VL_RESTORER_CLEAR(m_usedDefParamPins);
|
||||
UASSERT_OBJ(nodep->classp(), nodep, "ClassRef has unlinked class");
|
||||
UASSERT_OBJ(m_statep->forPrimary() || !nodep->paramsp() || V3Error::errorCount(), nodep,
|
||||
"class reference parameter not removed by V3Param");
|
||||
|
|
@ -4753,14 +4749,12 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
LINKDOT_VISIT_START();
|
||||
UINFO(8, indent() << "visit " << nodep);
|
||||
UINFO(9, indent() << m_ds.ascii());
|
||||
VL_RESTORER(m_usedPins);
|
||||
VL_RESTORER(m_usedDefParamPins);
|
||||
m_usedPins.clear();
|
||||
m_usedDefParamPins.clear();
|
||||
VL_RESTORER_CLEAR(m_usedPins);
|
||||
VL_RESTORER_CLEAR(m_usedDefParamPins);
|
||||
UASSERT_OBJ(m_statep->forPrimary() || !nodep->paramsp(), nodep,
|
||||
"class reference parameter not removed by V3Param");
|
||||
{
|
||||
VL_RESTORER(m_ds);
|
||||
VL_RESTORER_COPY(m_ds);
|
||||
VL_RESTORER(m_pinSymp);
|
||||
|
||||
if (!nodep->classOrPackageSkipp() && nodep->name() != "local::") {
|
||||
|
|
@ -4834,7 +4828,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
}
|
||||
}
|
||||
VL_RESTORER(m_curSymp);
|
||||
VL_RESTORER(m_ds);
|
||||
VL_RESTORER_COPY(m_ds);
|
||||
m_ds.m_dotSymp = m_curSymp = m_statep->getNodeSym(nodep);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
|
@ -5054,7 +5048,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
// Created here so should already be resolved.
|
||||
LINKDOT_VISIT_START();
|
||||
UINFO(5, indent() << "visit " << nodep);
|
||||
VL_RESTORER(m_ds);
|
||||
VL_RESTORER_COPY(m_ds);
|
||||
VL_RESTORER(m_randSymp);
|
||||
VL_RESTORER(m_randMethodCallp);
|
||||
{
|
||||
|
|
@ -5509,7 +5503,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
checkNoDot(nodep);
|
||||
{
|
||||
VL_RESTORER(m_curSymp);
|
||||
VL_RESTORER(m_ds);
|
||||
VL_RESTORER_COPY(m_ds);
|
||||
if (nodep->name() != "") {
|
||||
m_ds.m_dotSymp = m_curSymp = m_statep->getNodeSym(nodep);
|
||||
UINFO(5, indent() << "cur=se" << cvtToHex(m_curSymp));
|
||||
|
|
@ -5524,7 +5518,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
checkNoDot(nodep);
|
||||
{
|
||||
VL_RESTORER(m_curSymp);
|
||||
VL_RESTORER(m_ds);
|
||||
VL_RESTORER_COPY(m_ds);
|
||||
if (nodep->name() != "") {
|
||||
m_ds.m_dotSymp = m_curSymp = m_statep->getNodeSym(nodep);
|
||||
UINFO(5, indent() << "cur=se" << cvtToHex(m_curSymp));
|
||||
|
|
@ -5643,7 +5637,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
checkNoDot(nodep);
|
||||
VL_RESTORER(m_curSymp);
|
||||
VL_RESTORER(m_currentWithp);
|
||||
VL_RESTORER(m_restrictedNamesUsed);
|
||||
VL_RESTORER_COPY(m_restrictedNamesUsed);
|
||||
{
|
||||
m_ds.m_dotSymp = m_curSymp = m_statep->getNodeSym(nodep);
|
||||
m_currentWithp = nodep;
|
||||
|
|
@ -5813,7 +5807,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
VL_RESTORER(m_curSymp);
|
||||
VL_RESTORER(m_modSymp);
|
||||
VL_RESTORER(m_modp);
|
||||
VL_RESTORER(m_ifClassImpNames);
|
||||
VL_RESTORER_COPY(m_ifClassImpNames);
|
||||
VL_RESTORER(m_insideClassExtParam);
|
||||
{
|
||||
m_ds.init(m_curSymp);
|
||||
|
|
@ -6169,7 +6163,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
void visit(AstDisable* nodep) override {
|
||||
LINKDOT_VISIT_START();
|
||||
checkNoDot(nodep);
|
||||
VL_RESTORER(m_ds);
|
||||
VL_RESTORER_COPY(m_ds);
|
||||
m_ds.init(m_curSymp);
|
||||
m_ds.m_dotPos = DP_FIRST;
|
||||
m_ds.m_disablep = nodep;
|
||||
|
|
@ -6249,10 +6243,8 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
UASSERT_OBJ(ifacep, nodep, "Port parameters of AstIfaceRefDType without ifacep()");
|
||||
if (ifacep->dead()) return;
|
||||
checkNoDot(nodep);
|
||||
VL_RESTORER(m_usedPins);
|
||||
VL_RESTORER(m_usedDefParamPins);
|
||||
m_usedPins.clear();
|
||||
m_usedDefParamPins.clear();
|
||||
VL_RESTORER_CLEAR(m_usedPins);
|
||||
VL_RESTORER_CLEAR(m_usedDefParamPins);
|
||||
VL_RESTORER(m_pinSymp);
|
||||
m_pinSymp = m_statep->getNodeSym(ifacep);
|
||||
iterateAndNextNull(nodep->paramsp());
|
||||
|
|
|
|||
|
|
@ -273,7 +273,7 @@ class LinkParseVisitor final : public VNVisitor {
|
|||
<< nodep->verilogKwd() << "'");
|
||||
}
|
||||
|
||||
VL_RESTORER(m_portDups);
|
||||
VL_RESTORER_COPY(m_portDups);
|
||||
collectPorts(nodep->stmtsp());
|
||||
|
||||
iterateChildren(nodep);
|
||||
|
|
@ -763,12 +763,12 @@ class LinkParseVisitor final : public VNVisitor {
|
|||
VL_RESTORER(m_genblkAbove);
|
||||
VL_RESTORER(m_genblkNum);
|
||||
VL_RESTORER(m_beginDepth);
|
||||
VL_RESTORER(m_implTypedef);
|
||||
VL_RESTORER(m_lifetime);
|
||||
VL_RESTORER(m_lifetimeAllowed);
|
||||
VL_RESTORER(m_moduleWithGenericIface);
|
||||
VL_RESTORER(m_randSequenceNum);
|
||||
VL_RESTORER(m_valueModp);
|
||||
VL_RESTORER_CLEAR(m_implTypedef);
|
||||
|
||||
// Module: Create sim table for entire module and iterate
|
||||
cleanFileline(nodep);
|
||||
|
|
@ -780,7 +780,6 @@ class LinkParseVisitor final : public VNVisitor {
|
|||
m_genblkAbove = 0;
|
||||
m_genblkNum = 0;
|
||||
m_beginDepth = 0;
|
||||
m_implTypedef.clear();
|
||||
m_valueModp = nodep;
|
||||
m_lifetime = nodep->lifetime().makeImplicit();
|
||||
m_lifetimeAllowed = VN_IS(nodep, Class);
|
||||
|
|
@ -797,7 +796,7 @@ class LinkParseVisitor final : public VNVisitor {
|
|||
"Verilator top-level internals");
|
||||
}
|
||||
|
||||
VL_RESTORER(m_portDups);
|
||||
VL_RESTORER_COPY(m_portDups);
|
||||
collectPorts(nodep->stmtsp());
|
||||
|
||||
iterateChildren(nodep);
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class LinkWithVisitor final : public VNVisitor {
|
|||
|
||||
// STATE
|
||||
// Below state needs to be preserved between each module call.
|
||||
string m_randcIllegalWhy; // Why randc illegal
|
||||
const char* m_randcIllegalWhyp = nullptr; // Why randc illegal
|
||||
AstNode* m_randcIllegalp = nullptr; // Node causing randc illegal
|
||||
AstNodeExpr* m_currentRandomizeSelectp = nullptr; // fromp() of current `randomize()` call
|
||||
bool m_inRandomizeWith = false; // If in randomize() with (and no other with afterwards)
|
||||
|
|
@ -49,24 +49,24 @@ class LinkWithVisitor final : public VNVisitor {
|
|||
iterateChildren(nodep);
|
||||
}
|
||||
void visit(AstConstraintBefore* nodep) override {
|
||||
VL_RESTORER(m_randcIllegalWhy);
|
||||
VL_RESTORER(m_randcIllegalWhyp);
|
||||
VL_RESTORER(m_randcIllegalp);
|
||||
m_randcIllegalWhy = "'solve before' (IEEE 1800-2023 18.5.9)";
|
||||
m_randcIllegalWhyp = "'solve before' (IEEE 1800-2023 18.5.9)";
|
||||
m_randcIllegalp = nodep;
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
void visit(AstDist* nodep) override {
|
||||
VL_RESTORER(m_randcIllegalWhy);
|
||||
VL_RESTORER(m_randcIllegalWhyp);
|
||||
VL_RESTORER(m_randcIllegalp);
|
||||
m_randcIllegalWhy = "'constraint dist' (IEEE 1800-2023 18.5.3)";
|
||||
m_randcIllegalWhyp = "'constraint dist' (IEEE 1800-2023 18.5.3)";
|
||||
m_randcIllegalp = nodep;
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
void visit(AstConstraintExpr* nodep) override {
|
||||
VL_RESTORER(m_randcIllegalWhy);
|
||||
VL_RESTORER(m_randcIllegalWhyp);
|
||||
VL_RESTORER(m_randcIllegalp);
|
||||
if (nodep->isSoft()) {
|
||||
m_randcIllegalWhy = "'constraint soft' (IEEE 1800-2023 18.5.13.1)";
|
||||
m_randcIllegalWhyp = "'constraint soft' (IEEE 1800-2023 18.5.13.1)";
|
||||
m_randcIllegalp = nodep;
|
||||
}
|
||||
iterateChildrenConst(nodep);
|
||||
|
|
@ -76,7 +76,7 @@ class LinkWithVisitor final : public VNVisitor {
|
|||
if (nodep->varp()) { // Else due to dead code, might not have var pointer
|
||||
if (nodep->varp()->isRandC() && m_randcIllegalp) {
|
||||
nodep->v3error("Randc variables not allowed in "
|
||||
<< m_randcIllegalWhy << '\n'
|
||||
<< m_randcIllegalWhyp << '\n'
|
||||
<< nodep->warnContextPrimary() << '\n'
|
||||
<< m_randcIllegalp->warnOther()
|
||||
<< "... Location of restricting expression\n"
|
||||
|
|
|
|||
|
|
@ -2571,11 +2571,9 @@ class ParamVisitor final : public VNVisitor {
|
|||
// Iterate the body
|
||||
{
|
||||
VL_RESTORER(m_modp);
|
||||
VL_RESTORER(m_ifacePortNames);
|
||||
VL_RESTORER(m_ifaceInstCells);
|
||||
VL_RESTORER_CLEAR(m_ifacePortNames);
|
||||
VL_RESTORER_CLEAR(m_ifaceInstCells);
|
||||
m_modp = modp;
|
||||
m_ifacePortNames.clear();
|
||||
m_ifaceInstCells.clear();
|
||||
iterateChildren(modp);
|
||||
}
|
||||
}
|
||||
|
|
@ -3241,7 +3239,7 @@ class ParamVisitor final : public VNVisitor {
|
|||
// Note this clears nodep->genforp(), so begin is no longer special
|
||||
}
|
||||
} else {
|
||||
VL_RESTORER(m_generateHierName);
|
||||
VL_RESTORER_COPY(m_generateHierName);
|
||||
m_generateHierName += "." + nodep->prettyName();
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ class RandSequenceVisitor final : public VNVisitor {
|
|||
m_modp->addStmtsp(taskp);
|
||||
|
||||
// Create local (not output) break variable
|
||||
VL_RESTORER(m_localizeRemaps);
|
||||
VL_RESTORER_COPY(m_localizeRemaps);
|
||||
AstVar* breakVarp = newBreakVar(nodep->fileline(), false);
|
||||
taskp->addStmtsp(breakVarp);
|
||||
|
||||
|
|
@ -417,9 +417,9 @@ class RandSequenceVisitor final : public VNVisitor {
|
|||
m_rsp = nodep;
|
||||
VL_RESTORER(m_startProdp);
|
||||
|
||||
VL_RESTORER(m_localizes);
|
||||
VL_RESTORER(m_localizeNames);
|
||||
VL_RESTORER(m_localizeRemaps);
|
||||
VL_RESTORER_COPY(m_localizes);
|
||||
VL_RESTORER_COPY(m_localizeNames);
|
||||
VL_RESTORER_COPY(m_localizeRemaps);
|
||||
findLocalizes(nodep);
|
||||
|
||||
// Find first production
|
||||
|
|
@ -482,7 +482,7 @@ class RandSequenceVisitor final : public VNVisitor {
|
|||
// TODO we could do this only if break exists in the downstream production,
|
||||
// but as-is we'll optimize it away in most cases anyways
|
||||
VL_RESTORER(m_breakVarp);
|
||||
VL_RESTORER(m_localizeRemaps);
|
||||
VL_RESTORER_COPY(m_localizeRemaps);
|
||||
m_breakVarp = newBreakVar(nodep->fileline(), true);
|
||||
m_prodFuncp->addStmtsp(m_breakVarp);
|
||||
|
||||
|
|
|
|||
|
|
@ -306,10 +306,9 @@ private:
|
|||
}
|
||||
void visit(AstClass* nodep) override {
|
||||
// Move initial statements into the constructor
|
||||
VL_RESTORER(m_initialps);
|
||||
VL_RESTORER_CLEAR(m_initialps);
|
||||
VL_RESTORER(m_ctorp);
|
||||
VL_RESTORER(m_classp);
|
||||
m_initialps.clear();
|
||||
m_ctorp = nullptr;
|
||||
m_classp = nodep;
|
||||
{ // Find m_initialps, m_ctor
|
||||
|
|
|
|||
|
|
@ -485,7 +485,7 @@ class TraceDeclVisitor final : public VNVisitor {
|
|||
AstNodeDType* const skipTypep = nodep->skipRefp();
|
||||
// offset and direction args added in EmitCImp
|
||||
std::string callArgs{"tracep, \"" + VIdProtect::protect(m_traName) + "\""};
|
||||
VL_RESTORER(m_traName);
|
||||
VL_RESTORER_COPY(m_traName);
|
||||
FileLine* const flp = skipTypep->fileline();
|
||||
|
||||
const DtypeFuncKey dtypeKey{skipTypep, m_traVscp->varp()->varType()};
|
||||
|
|
@ -530,7 +530,7 @@ class TraceDeclVisitor final : public VNVisitor {
|
|||
void declUnpackedArray(AstUnpackArrayDType* const nodep, bool newFunc) {
|
||||
string prefixName(newFunc ? "name" : m_traName);
|
||||
|
||||
VL_RESTORER(m_traName);
|
||||
VL_RESTORER_COPY(m_traName);
|
||||
FileLine* const flp = nodep->fileline();
|
||||
|
||||
addToSubFunc(new AstTracePushPrefix{flp, prefixName, VTracePrefixType::ARRAY_UNPACKED,
|
||||
|
|
@ -568,7 +568,7 @@ class TraceDeclVisitor final : public VNVisitor {
|
|||
string prefixName(newFunc ? "name" : m_traName);
|
||||
AstNodeDType* const subtypep = nodep->subDTypep()->skipRefToEnump();
|
||||
|
||||
VL_RESTORER(m_traName);
|
||||
VL_RESTORER_COPY(m_traName);
|
||||
FileLine* const flp = nodep->fileline();
|
||||
|
||||
addToSubFunc(new AstTracePushPrefix{flp, prefixName, VTracePrefixType::ARRAY_PACKED,
|
||||
|
|
@ -918,7 +918,7 @@ class TraceDeclVisitor final : public VNVisitor {
|
|||
return;
|
||||
}
|
||||
|
||||
VL_RESTORER(m_traName);
|
||||
VL_RESTORER_COPY(m_traName);
|
||||
FileLine* const flp = nodep->fileline();
|
||||
|
||||
int nMembers = 0;
|
||||
|
|
|
|||
|
|
@ -2191,8 +2191,8 @@ class TristateVisitor final : public TristateBaseVisitor {
|
|||
VL_RESTORER(m_modp);
|
||||
VL_RESTORER(m_graphing);
|
||||
VL_RESTORER(m_unique);
|
||||
VL_RESTORER(m_lhsmap);
|
||||
VL_RESTORER(m_assigns);
|
||||
VL_RESTORER_CLEAR(m_lhsmap);
|
||||
VL_RESTORER_CLEAR(m_assigns);
|
||||
// Not preserved, needs pointer instead: TristateGraph origTgraph = m_tgraph;
|
||||
UASSERT_OBJ(m_tgraph.empty(), nodep, "Unsupported: NodeModule under NodeModule");
|
||||
|
||||
|
|
@ -2201,8 +2201,6 @@ class TristateVisitor final : public TristateBaseVisitor {
|
|||
m_tgraph.clearAndCheck();
|
||||
m_unique = 0;
|
||||
m_logicp = nullptr;
|
||||
m_lhsmap.clear();
|
||||
m_assigns.clear();
|
||||
m_modp = nodep;
|
||||
// Walk the graph, finding all variables and tristate constructs
|
||||
m_graphing = true;
|
||||
|
|
|
|||
|
|
@ -56,14 +56,12 @@ class UdpVisitor final : public VNVisitor {
|
|||
VL_RESTORER(m_primp);
|
||||
VL_RESTORER(m_outputInitVerfp);
|
||||
VL_RESTORER(m_isFirstOutput);
|
||||
VL_RESTORER(m_inputVars);
|
||||
VL_RESTORER(m_outputVars);
|
||||
VL_RESTORER_CLEAR(m_inputVars);
|
||||
VL_RESTORER_CLEAR(m_outputVars);
|
||||
m_outputInitVerfp = nullptr;
|
||||
m_primp = nodep;
|
||||
m_isFirstOutput = false;
|
||||
iterateChildren(nodep);
|
||||
m_inputVars.clear();
|
||||
m_outputVars.clear();
|
||||
}
|
||||
void visit(AstVar* nodep) override {
|
||||
// Push the input and output vars for primitive.
|
||||
|
|
|
|||
|
|
@ -7852,7 +7852,7 @@ class WidthVisitor final : public VNVisitor {
|
|||
}
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
assertAtStatement(nodep);
|
||||
VL_RESTORER(m_insideTempNames);
|
||||
VL_RESTORER_COPY(m_insideTempNames);
|
||||
if (AstClass* const classp = VN_CAST(nodep, Class)) {
|
||||
visitClass(classp);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ class WidthCommitVisitor final : public VNVisitor {
|
|||
// STATE
|
||||
AstNodeFTask* m_ftaskp = nullptr; // Current function/task
|
||||
AstNodeModule* m_modp = nullptr; // Current module
|
||||
std::string m_contNba; // In continuous- or non-blocking assignment
|
||||
const char* m_contNbap = nullptr; // In continuous- or non-blocking assignment
|
||||
bool m_contReads = false; // Check read continuous automatic variables
|
||||
bool m_dynsizedelem = false; // Writing dynamically-sized array element, not the array itself
|
||||
VMemberMap m_memberMap; // Member names cached for fast lookup
|
||||
|
|
@ -148,7 +148,7 @@ private:
|
|||
void varLifetimeCheck(AstNode* nodep, AstVar* varp) {
|
||||
// Skip if we are under a member select (lhs of a dot)
|
||||
// We don't care about lifetime of anything else than rhs of a dot
|
||||
if (!m_underSel && !m_contNba.empty()) {
|
||||
if (!m_underSel && m_contNbap) {
|
||||
std::string varType;
|
||||
const AstNodeDType* const varDtp = varp->dtypep()->skipRefp();
|
||||
if (varp->lifetime().isAutomatic() && !VN_IS(varDtp, IfaceRefDType)
|
||||
|
|
@ -162,7 +162,7 @@ private:
|
|||
if (!varType.empty()) {
|
||||
UINFO(1, " Related var dtype: " << varDtp);
|
||||
nodep->v3error(varType
|
||||
<< " variable not allowed in " << m_contNba
|
||||
<< " variable not allowed in " << m_contNbap
|
||||
<< " assignment (IEEE 1800-2023 6.21): " << varp->prettyNameQ());
|
||||
}
|
||||
}
|
||||
|
|
@ -419,9 +419,9 @@ private:
|
|||
void visit(AstAssignCont* nodep) override {
|
||||
iterateAndNextNull(nodep->timingControlp());
|
||||
{
|
||||
VL_RESTORER(m_contNba);
|
||||
VL_RESTORER(m_contNbap);
|
||||
VL_RESTORER(m_contReads);
|
||||
m_contNba = "continuous";
|
||||
m_contNbap = "continuous";
|
||||
m_contReads = true;
|
||||
iterateAndNextNull(nodep->lhsp());
|
||||
iterateAndNextNull(nodep->rhsp());
|
||||
|
|
@ -432,9 +432,9 @@ private:
|
|||
iterateAndNextNull(nodep->timingControlp());
|
||||
iterateAndNextNull(nodep->rhsp());
|
||||
{
|
||||
VL_RESTORER(m_contNba);
|
||||
VL_RESTORER(m_contNbap);
|
||||
VL_RESTORER(m_contReads);
|
||||
m_contNba = "nonblocking";
|
||||
m_contNbap = "nonblocking";
|
||||
m_contReads = false;
|
||||
iterateAndNextNull(nodep->lhsp());
|
||||
}
|
||||
|
|
@ -444,9 +444,9 @@ private:
|
|||
iterateAndNextNull(nodep->timingControlp());
|
||||
iterateAndNextNull(nodep->rhsp());
|
||||
{
|
||||
VL_RESTORER(m_contNba);
|
||||
VL_RESTORER(m_contNbap);
|
||||
VL_RESTORER(m_contReads);
|
||||
m_contNba = "continuous";
|
||||
m_contNbap = "continuous";
|
||||
m_contReads = false;
|
||||
iterateAndNextNull(nodep->lhsp());
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue