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:
Geza Lore
2026-07-04 17:27:07 +01:00
committed by GitHub
parent 83eb54ec7e
commit 566f4e6efc
24 changed files with 180 additions and 148 deletions
+9 -9
View File
@@ -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());
}