diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index d3dd8c9e0..d859f126a 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -18,12 +18,16 @@ // //************************************************************************* // LinkDot TRANSFORMATIONS: -// Top-down traversal +// Top-down traversal in LinkDotFindVisitor // Cells: // Make graph of cell hierarchy // Var/Funcs's: // Collect all names into symtable under appropriate cell -// Top-down traversal +// Top-down traversal in LinkDotScopeVisitor +// Find VarScope versions of signals (well past original link) +// Top-down traversal in LinkDotParamVisitor +// Create implicit signals +// Top-down traversal in LinkDotResolveVisitor // VarXRef/Func's: // Find appropriate named cell and link to var they reference //************************************************************************* @@ -1014,21 +1018,29 @@ private: AstUser5InUse m_inuser5; // TYPES - enum DotPosition { DP_SCOPE, DP_VARETC, DP_MEMBER }; + enum DotPosition { DP_SCOPE, DP_VAR_ETC, DP_MEMBER }; // STATE LinkDotState* m_statep; // State, including dotted symbol table VSymEnt* m_curSymp; // SymEnt for current lookup point VSymEnt* m_modSymp; // SymEnt for current module - VSymEnt* m_dotSymp; // SymEnt for dotted AstParse lookup VSymEnt* m_pinSymp; // SymEnt for pin lookups AstCell* m_cellp; // Current cell AstNodeModule* m_modp; // Current module AstNodeFTask* m_ftaskp; // Current function/task - AstDot* m_dotp; // Current dot - DotPosition m_dotPos; // Scope part of dotted resolution - bool m_dotErr; // Error found in dotted resolution, ignore upwards - string m_dotText; // String of dotted names found in below parseref + + struct DotStates { + VSymEnt* m_dotSymp; // SymEnt for dotted AstParse lookup + AstDot* m_dotp; // Current dot + DotPosition m_dotPos; // Scope part of dotted resolution + bool m_dotErr; // Error found in dotted resolution, ignore upwards + string m_dotText; // String of dotted names found in below parseref + void init(VSymEnt* curSymp) { + m_dotSymp = curSymp; m_dotp = NULL; m_dotPos = DP_VAR_ETC; m_dotErr = false; m_dotText = ""; + } + DotStates() { init(NULL); } + ~DotStates() {} + } m_ds; // State to preserve across recursions int debug() { return LinkDotState::debug(); } @@ -1066,18 +1078,19 @@ private: virtual void visit(AstNodeModule* nodep, AstNUser*) { if (nodep->dead()) return; UINFO(8," "<getNodeSym(nodep); // Until overridden by a SCOPE + m_ds.init(m_curSymp); + m_ds.m_dotSymp = m_curSymp = m_modSymp = m_statep->getNodeSym(nodep); // Until overridden by a SCOPE m_cellp = NULL; m_modp = nodep; nodep->iterateChildren(*this); m_modp = NULL; - m_dotSymp = m_curSymp = m_modSymp = NULL; + m_ds.m_dotSymp = m_curSymp = m_modSymp = NULL; } virtual void visit(AstScope* nodep, AstNUser*) { UINFO(8," "<getScopeSym(nodep); + m_ds.m_dotSymp = m_curSymp = m_statep->getScopeSym(nodep); nodep->iterateChildren(*this); - m_dotSymp = m_curSymp = NULL; + m_ds.m_dotSymp = m_curSymp = NULL; } virtual void visit(AstCellInline* nodep, AstNUser*) { if (m_statep->forScopeCreation()) { @@ -1144,30 +1157,24 @@ private: virtual void visit(AstDot* nodep, AstNUser*) { if (nodep->user3SetOnce()) return; UINFO(8," "<start(); // Save, as nodep may go NULL { - m_dotp = nodep; // Always, not just at start if (start) { // Starting dot sequence if (debug()>=9) nodep->dumpTree("-dot-in: "); - m_dotText = ""; - m_dotErr = false; - m_dotSymp = m_curSymp; // Start from current point + m_ds.init(m_curSymp); // Start from current point } - // m_dotText communicates the cell prefix between stages - m_dotPos = DP_SCOPE; + m_ds.m_dotp = nodep; // Always, not just at start + m_ds.m_dotPos = DP_SCOPE; + // m_ds.m_dotText communicates the cell prefix between stages nodep->lhsp()->iterateAndNext(*this); - if (!m_dotErr) { // Once something wrong, give up - if (start && m_dotPos==DP_SCOPE) m_dotPos = DP_VARETC; // Top dot RHS is final RHS, else it's a DOT(DOT(x,*here*),real-rhs) which we consider a RHS + if (!m_ds.m_dotErr) { // Once something wrong, give up + if (start && m_ds.m_dotPos==DP_SCOPE) m_ds.m_dotPos = DP_VAR_ETC; // Top dot RHS is final RHS, else it's a DOT(DOT(x,*here*),real-rhs) which we consider a RHS nodep->rhsp()->iterateAndNext(*this); } if (start) { AstNode* newp; - if (m_dotErr) { + if (m_ds.m_dotErr) { newp = new AstConst(nodep->fileline(),AstConst::LogicFalse()); } else { // RHS is what we're left with @@ -1182,37 +1189,27 @@ private: pushDeletep(nodep); nodep=NULL; } } - m_dotp = lastDotp; if (start) { - m_dotText = lastText; - m_dotErr = lastErr; - m_dotPos = lastDotPos; - m_dotSymp = lastDotSymp; + m_ds = lastStates; + } else { + m_ds.m_dotp = lastStates.m_dotp; } } virtual void visit(AstParseRef* nodep, AstNUser*) { if (nodep->user3SetOnce()) return; - UINFO(9," linkPARSEREF se"<<(void*)m_dotSymp<<" pos="<v3fatalSrc("NULL lookup symbol table"); + // m_ds.m_dotSymp is symbol table relative to "."'s above now + if (!m_ds.m_dotSymp) nodep->v3fatalSrc("NULL lookup symbol table"); if (!m_statep->forPrimary()) nodep->v3fatalSrc("ParseRefs should no longer exist"); - AstDot* lastDotp = m_dotp; - string lastText = m_dotText; - bool lastErr = m_dotErr; - DotPosition lastDotPos = m_dotPos; - VSymEnt* lastDotSymp = m_dotSymp; + DotStates lastStates = m_ds; bool start = nodep->start(); // Save, as nodep may go NULL - if (nodep->start()) { - m_dotp = NULL; - m_dotText = ""; - m_dotErr = false; - m_dotPos = DP_VARETC; - m_dotSymp = m_curSymp; + if (start) { + m_ds.init(m_curSymp); } - if (m_dotPos == DP_MEMBER) { + if (m_ds.m_dotPos == DP_MEMBER) { // Found a Var, everything following is membership. {scope}.{var}.HERE {member} - AstNode* varEtcp = m_dotp->lhsp()->unlinkFrBack(); + AstNode* varEtcp = m_ds.m_dotp->lhsp()->unlinkFrBack(); AstNode* newp = new AstMemberSel(nodep->fileline(), varEtcp, VFlagChildDType(), nodep->name()); nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL; @@ -1225,7 +1222,7 @@ private: bool onlyVar = false; if (nodep->expect() == AstParseRefExp::PX_PREDOT) { // {a}.{b}, where {a} maybe a module name - // FUTURE: or variable, where dotting into structure member + // or variable, where dotting into structure member expectWhat = "scope/variable"; allowScope = true; allowVar = true; @@ -1243,9 +1240,9 @@ private: string baddot; VSymEnt* okSymp = NULL; if (allowScope) { - foundp = m_statep->findDotted(m_dotSymp, nodep->name(), baddot, okSymp); // Maybe NULL + foundp = m_statep->findDotted(m_ds.m_dotSymp, nodep->name(), baddot, okSymp); // Maybe NULL } else { - foundp = m_dotSymp->findIdFallback(nodep->name()); + foundp = m_ds.m_dotSymp->findIdFallback(nodep->name()); } if (foundp) UINFO(9," found=se"<<(void*)foundp<<" n="<nodep()<nodep()->castModule()) { // if top if (allowScope) { ok = true; - if (m_dotText!="") m_dotText += "."; - m_dotText += nodep->name(); - m_dotSymp = foundp; - m_dotPos = DP_SCOPE; + if (m_ds.m_dotText!="") m_ds.m_dotText += "."; + m_ds.m_dotText += nodep->name(); + m_ds.m_dotSymp = foundp; + m_ds.m_dotPos = DP_SCOPE; // Upper AstDot visitor will handle it from here } } else if (AstVar* varp = foundp->nodep()->castVar()) { if (allowVar) { AstNodeVarRef* newp; - if (m_dotText != "") { - newp = new AstVarXRef(nodep->fileline(), nodep->name(), m_dotText, false); // lvalue'ness computed later + if (m_ds.m_dotText != "") { + newp = new AstVarXRef(nodep->fileline(), nodep->name(), m_ds.m_dotText, false); // lvalue'ness computed later newp->varp(varp); - m_dotText = ""; + m_ds.m_dotText = ""; } else { newp = new AstVarRef(nodep->fileline(), nodep->name(), false); // lvalue'ness computed later newp->varp(varp); newp->packagep(foundp->packagep()); } nodep->replaceWith(newp); pushDeletep(nodep); nodep = NULL; - m_dotPos = DP_MEMBER; + m_ds.m_dotPos = DP_MEMBER; ok = true; } } @@ -1283,7 +1280,7 @@ private: AstNode* newp = new AstEnumItemRef(nodep->fileline(), valuep, foundp->packagep()); nodep->replaceWith(newp); pushDeletep(nodep); nodep = NULL; ok = true; - m_dotText = ""; + m_ds.m_dotText = ""; } } else if (AstNodeFTask* ftaskp = foundp->nodep()->castNodeFTask()) { @@ -1291,7 +1288,7 @@ private: AstNodeFTaskRef* refp = nodep->ftaskrefp()->castNodeFTaskRef(); if (!refp) nodep->v3fatalSrc("Parseref indicates FTASKref but none found"); refp->name(nodep->name()); - refp->dotted(m_dotText); // Maybe "" + refp->dotted(m_ds.m_dotText); // Maybe "" refp->taskp(ftaskp); refp->packagep(foundp->packagep()); // Generally set by parse, but might be an import taskFuncSwapCheck(refp); @@ -1302,24 +1299,24 @@ private: } // if (!ok) { - bool checkImplicit = (onlyVar && m_dotText==""); + bool checkImplicit = (onlyVar && m_ds.m_dotText==""); bool err = !(checkImplicit && m_statep->implicitOk(m_modp, nodep->name())); if (err) { m_statep->preErrorDump(); if (foundp) { - nodep->v3error("Found definition of '"<prettyName() + nodep->v3error("Found definition of '"<prettyName() <<"'"<<" as a "<nodep()->typeName() <<" but expected a "<v3error("Can't find definition of "<prettyName()); } else { nodep->v3error("Can't find definition of '"<<(baddot!=""?baddot:nodep->prettyName())<<"' in dotted " - <prettyName()); - okSymp->cellErrorScopes(nodep, AstNode::prettyName(m_dotText)); + <prettyName()); + okSymp->cellErrorScopes(nodep, AstNode::prettyName(m_ds.m_dotText)); } - m_dotErr = true; + m_ds.m_dotErr = true; } if (checkImplicit) { // Else if a scope is allowed, making a signal won't help error cascade // Create if implicit, and also if error (so only complain once) @@ -1331,11 +1328,7 @@ private: } } if (start) { - m_dotp = lastDotp; - m_dotText = lastText; - m_dotErr = lastErr; - m_dotPos = lastDotPos; - m_dotSymp = lastDotSymp; + m_ds = lastStates; } } virtual void visit(AstVarRef* nodep, AstNUser*) { @@ -1478,14 +1471,14 @@ private: virtual void visit(AstSelBit* nodep, AstNUser*) { if (nodep->user3SetOnce()) return; nodep->lhsp()->iterateAndNext(*this); - if (m_dotPos == DP_SCOPE) { // Already under dot, so this is {modulepart} DOT {modulepart} + if (m_ds.m_dotPos == DP_SCOPE) { // Already under dot, so this is {modulepart} DOT {modulepart} if (AstConst* constp = nodep->rhsp()->castConst()) { string index = AstNode::encodeNumber(constp->toSInt()); - m_dotText += "__BRA__"+index+"__KET__"; + m_ds.m_dotText += "__BRA__"+index+"__KET__"; } else { nodep->v3error("Unsupported: Non-constant inside []'s in the cell part of a dotted reference"); } - // And pass up m_dotText + // And pass up m_ds.m_dotText } nodep->fromp()->iterateAndNext(*this); nodep->bitp()->iterateAndNext(*this); @@ -1495,11 +1488,11 @@ private: UINFO(5," "<getNodeSym(nodep); + m_ds.m_dotSymp = m_curSymp = m_statep->getNodeSym(nodep); UINFO(5," cur=se"<<(void*)m_curSymp<iterateChildren(*this); } - m_dotSymp = m_curSymp = oldCurSymp; + m_ds.m_dotSymp = m_curSymp = oldCurSymp; UINFO(5," cur=se"<<(void*)m_curSymp<getNodeSym(nodep); + m_ds.m_dotSymp = m_curSymp = m_statep->getNodeSym(nodep); nodep->iterateChildren(*this); } - m_dotSymp = m_curSymp = oldCurSymp; + m_ds.m_dotSymp = m_curSymp = oldCurSymp; m_ftaskp = NULL; } virtual void visit(AstRefDType* nodep, AstNUser*) { @@ -1561,14 +1554,10 @@ public: m_statep = statep; m_modSymp = NULL; m_curSymp = NULL; - m_dotSymp = NULL; m_pinSymp = NULL; m_cellp = NULL; m_modp = NULL; m_ftaskp = NULL; - m_dotp = NULL; - m_dotPos = DP_VARETC; - m_dotErr = false; // rootp->accept(*this); }