diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index bb721a2ee..0e09698e0 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -735,9 +735,9 @@ AstNodeDType::CTypeRecursed AstNodeDType::cTypeRecurse(bool compound) const VL_M const CTypeRecursed sub = adtypep->subDTypep()->cTypeRecurse(true); info.m_type = "VlSampleQueue<" + sub.m_type + ">"; } else if (const auto* const adtypep = VN_CAST(dtypep, ClassRefDType)) { - info.m_type = "VlClassRef<" + EmitCBaseVisitor::prefixNameProtect(adtypep) + ">"; + info.m_type = "VlClassRef<" + EmitCBase::prefixNameProtect(adtypep) + ">"; } else if (const auto* const adtypep = VN_CAST(dtypep, IfaceRefDType)) { - info.m_type = EmitCBaseVisitor::prefixNameProtect(adtypep->ifaceViaCellp()) + "*"; + info.m_type = EmitCBase::prefixNameProtect(adtypep->ifaceViaCellp()) + "*"; } else if (const auto* const adtypep = VN_CAST(dtypep, UnpackArrayDType)) { if (adtypep->isCompound()) compound = true; const CTypeRecursed sub = adtypep->subDTypep()->cTypeRecurse(compound); @@ -746,7 +746,7 @@ AstNodeDType::CTypeRecursed AstNodeDType::cTypeRecurse(bool compound) const VL_M info.m_type += ">"; } else if (VN_IS(dtypep, NodeUOrStructDType) && !VN_AS(dtypep, NodeUOrStructDType)->packed()) { const auto* const sdtypep = VN_AS(dtypep, NodeUOrStructDType); - info.m_type = EmitCBaseVisitor::prefixNameProtect(sdtypep); + info.m_type = EmitCBase::prefixNameProtect(sdtypep); } else if (const AstBasicDType* const bdtypep = dtypep->basicp()) { // We don't print msb()/lsb() as multidim packed would require recursion, // and may confuse users as C++ data is stored always with bit 0 used diff --git a/src/V3CCtors.cpp b/src/V3CCtors.cpp index c70e11b2a..216f8141e 100644 --- a/src/V3CCtors.cpp +++ b/src/V3CCtors.cpp @@ -70,7 +70,7 @@ private: funcp->slow(!m_type.isClass()); // Only classes construct on fast path string preventUnusedStmt; if (m_type.isClass()) { - funcp->argTypes(EmitCBaseVisitor::symClassVar()); + funcp->argTypes(EmitCBase::symClassVar()); preventUnusedStmt = "if (false && vlSymsp) {} // Prevent unused\n"; } else if (m_type.isCoverage()) { funcp->argTypes("bool first"); diff --git a/src/V3Common.cpp b/src/V3Common.cpp index 72f900eb1..b5f5a4c8c 100644 --- a/src/V3Common.cpp +++ b/src/V3Common.cpp @@ -37,7 +37,7 @@ VL_DEFINE_DEBUG_FUNCTIONS; static void makeVlToString(AstClass* nodep) { AstCFunc* const funcp = new AstCFunc{nodep->fileline(), "VL_TO_STRING", nullptr, "std::string"}; - funcp->argTypes("const VlClassRef<" + EmitCBaseVisitor::prefixNameProtect(nodep) + ">& obj"); + funcp->argTypes("const VlClassRef<" + EmitCBase::prefixNameProtect(nodep) + ">& obj"); funcp->isMethod(false); funcp->isConst(false); funcp->isStatic(false); @@ -51,7 +51,7 @@ static void makeVlToString(AstClass* nodep) { static void makeVlToString(AstIface* nodep) { AstCFunc* const funcp = new AstCFunc{nodep->fileline(), "VL_TO_STRING", nullptr, "std::string"}; - funcp->argTypes("const " + EmitCBaseVisitor::prefixNameProtect(nodep) + "* obj"); + funcp->argTypes("const " + EmitCBase::prefixNameProtect(nodep) + "* obj"); funcp->isMethod(false); funcp->isConst(false); funcp->isStatic(false); @@ -65,7 +65,7 @@ static void makeVlToString(AstNodeUOrStructDType* nodep) { AstNodeModule* const modp = nodep->classOrPackagep(); AstCFunc* const funcp = new AstCFunc{nodep->fileline(), "VL_TO_STRING", nullptr, "std::string"}; - funcp->argTypes("const " + EmitCBaseVisitor::prefixNameProtect(nodep) + "& obj"); + funcp->argTypes("const " + EmitCBase::prefixNameProtect(nodep) + "& obj"); funcp->isMethod(false); funcp->isConst(false); funcp->isStatic(false); @@ -137,7 +137,7 @@ static void makeToStringMiddle(AstClass* nodep) { string stmt = "out += "; if (!comma.empty()) stmt += "\", \"+ "; // comma = ", "; // Nothing further so not needed - stmt += EmitCBaseVisitor::prefixNameProtect(nodep->extendsp()->dtypep()); + stmt += EmitCBase::prefixNameProtect(nodep->extendsp()->dtypep()); stmt += "::to_string_middle();\n"; nodep->user1(true); // So what we extend dumps this funcp->addStmtsp(new AstCStmt{nodep->fileline(), stmt}); diff --git a/src/V3DepthBlock.cpp b/src/V3DepthBlock.cpp index 3023f2457..889601de2 100644 --- a/src/V3DepthBlock.cpp +++ b/src/V3DepthBlock.cpp @@ -63,7 +63,7 @@ private: AstCCall* const callp = new AstCCall{nodep->fileline(), funcp}; callp->dtypeSetVoid(); if (VN_IS(m_modp, Class)) { - funcp->argTypes(EmitCBaseVisitor::symClassVar()); + funcp->argTypes(EmitCBase::symClassVar()); callp->argTypes("vlSymsp"); } UINFO(6, " New " << callp << endl); diff --git a/src/V3EmitCBase.h b/src/V3EmitCBase.h index a183b4e78..523072e18 100644 --- a/src/V3EmitCBase.h +++ b/src/V3EmitCBase.h @@ -48,7 +48,36 @@ public: //###################################################################### // Base Visitor class -- holds output file pointer -class EmitCBaseVisitor VL_NOT_FINAL : public VNVisitor { +class EmitCBase VL_NOT_FINAL { +public: + static string voidSelfAssign(const AstNodeModule* modp) { + const string className = prefixNameProtect(modp); + return className + "* const __restrict vlSelf VL_ATTR_UNUSED = static_cast<" + className + + "*>(voidSelf);\n"; + } + static string symClassName() { + return v3Global.opt.prefix() + "_" + VIdProtect::protect("_Syms"); + } + static string symClassVar() { return symClassName() + "* __restrict vlSymsp"; } + static string symClassAssign() { + return symClassName() + "* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;\n"; + } + static string prefixNameProtect(const AstNode* nodep) VL_MT_SAFE { // C++ name with prefix + return v3Global.opt.modPrefix() + "_" + VIdProtect::protect(nodep->name()); + } + static bool isAnonOk(const AstVar* varp) { + return v3Global.opt.compLimitMembers() != 0 // Enabled + && !varp->isStatic() // Not a static variable + && !varp->isSc() // Aggregates can't be anon + && !VN_IS(varp->dtypep()->skipRefp(), SampleQueueDType) // Aggregates can't be anon + && (varp->basicp() && !varp->basicp()->isOpaque()); // Aggregates can't be anon + } + static bool isConstPoolMod(const AstNode* modp) { + return modp == v3Global.rootp()->constPoolp()->modp(); + } +}; + +class EmitCBaseVisitor VL_NOT_FINAL : public VNVisitor, public EmitCBase { public: // STATE V3OutCFile* m_ofp = nullptr; @@ -63,9 +92,7 @@ public: void putsQuoted(const string& str) { ofp()->putsQuoted(str); } void ensureNewLine() { ofp()->ensureNewLine(); } bool optSystemC() { return v3Global.opt.systemC(); } - static string protect(const string& name) VL_MT_SAFE { - return VIdProtect::protectIf(name, true); - } + static string protect(const string& name) VL_MT_SAFE { return VIdProtect::protect(name); } static string protectIf(const string& name, bool doIt) { return VIdProtect::protectIf(name, doIt); } @@ -75,36 +102,10 @@ public: static string ifNoProtect(const string& in) VL_MT_SAFE { return v3Global.opt.protectIds() ? "" : in; } - static string voidSelfAssign(const AstNodeModule* modp) { - const string className = prefixNameProtect(modp); - return className + "* const __restrict vlSelf VL_ATTR_UNUSED = static_cast<" + className - + "*>(voidSelf);\n"; - } - static string symClassName() { return v3Global.opt.prefix() + "_" + protect("_Syms"); } - static string symClassVar() { return symClassName() + "* __restrict vlSymsp"; } - static string symClassAssign() { - return symClassName() + "* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;\n"; - } static string funcNameProtect(const AstCFunc* nodep, const AstNodeModule* modp = nullptr); - static string prefixNameProtect(const AstNode* nodep) VL_MT_SAFE { // C++ name with prefix - return v3Global.opt.modPrefix() + "_" + protect(nodep->name()); - } static string topClassName() VL_MT_SAFE { // Return name of top wrapper module return v3Global.opt.prefix(); } - - static bool isConstPoolMod(const AstNode* modp) { - return modp == v3Global.rootp()->constPoolp()->modp(); - } - - static bool isAnonOk(const AstVar* varp) { - return v3Global.opt.compLimitMembers() != 0 // Enabled - && !varp->isStatic() // Not a static variable - && !varp->isSc() // Aggregates can't be anon - && !VN_IS(varp->dtypep()->skipRefp(), SampleQueueDType) // Aggregates can't be anon - && (varp->basicp() && !varp->basicp()->isOpaque()); // Aggregates can't be anon - } - static AstCFile* newCFile(const string& filename, bool slow, bool source, bool add = true); string cFuncArgs(const AstCFunc* nodep); void emitCFuncHeader(const AstCFunc* funcp, const AstNodeModule* modp, bool withScope); diff --git a/src/V3EmitCFunc.h b/src/V3EmitCFunc.h index a2bb47892..7ea87dac3 100644 --- a/src/V3EmitCFunc.h +++ b/src/V3EmitCFunc.h @@ -83,7 +83,7 @@ class EmitCLazyDecls final : public VNVisitorConst { void visit(AstVarRef* nodep) override { AstVar* const varp = nodep->varp(); // Only constant pool symbols are lazy declared for now ... - if (EmitCBaseVisitor::isConstPoolMod(EmitCParentModule::get(varp))) { + if (EmitCBase::isConstPoolMod(EmitCParentModule::get(varp))) { lazyDeclareConstPoolVar(varp); } } diff --git a/src/V3EmitCHeaders.cpp b/src/V3EmitCHeaders.cpp index eadea126f..986ae5a08 100644 --- a/src/V3EmitCHeaders.cpp +++ b/src/V3EmitCHeaders.cpp @@ -224,7 +224,7 @@ class EmitCHeader final : public EmitCConstInit { } } puts(sdtypep->verilogKwd()); // "struct"/"union" - puts(" " + EmitCBaseVisitor::prefixNameProtect(sdtypep) + " {\n"); + puts(" " + EmitCBase::prefixNameProtect(sdtypep) + " {\n"); for (const AstMemberDType* itemp = sdtypep->membersp(); itemp; itemp = VN_AS(itemp->nextp(), MemberDType)) { puts(itemp->dtypep()->cType(itemp->nameProtect(), false, false)); diff --git a/src/V3EmitCImp.cpp b/src/V3EmitCImp.cpp index 4a96fa118..33a2d3a89 100644 --- a/src/V3EmitCImp.cpp +++ b/src/V3EmitCImp.cpp @@ -38,23 +38,22 @@ class EmitCGatherDependencies final : VNVisitorConst { std::set m_dependencies; // Header names to be included in output C++ file // METHODS - void addSymsDependency() { m_dependencies.insert(EmitCBaseVisitor::symClassName()); } + void addSymsDependency() { m_dependencies.insert(EmitCBase::symClassName()); } void addModDependency(const AstNodeModule* modp) { if (const AstClass* const classp = VN_CAST(modp, Class)) { - m_dependencies.insert(EmitCBaseVisitor::prefixNameProtect(classp->classOrPackagep())); + m_dependencies.insert(EmitCBase::prefixNameProtect(classp->classOrPackagep())); } else { - m_dependencies.insert(EmitCBaseVisitor::prefixNameProtect(modp)); + m_dependencies.insert(EmitCBase::prefixNameProtect(modp)); } } void addDTypeDependency(const AstNodeDType* nodep) { if (const AstClassRefDType* const dtypep = VN_CAST(nodep, ClassRefDType)) { m_dependencies.insert( - EmitCBaseVisitor::prefixNameProtect(dtypep->classp()->classOrPackagep())); + EmitCBase::prefixNameProtect(dtypep->classp()->classOrPackagep())); } else if (const AstNodeUOrStructDType* const dtypep = VN_CAST(nodep, NodeUOrStructDType)) { if (!dtypep->packed()) { - m_dependencies.insert( - EmitCBaseVisitor::prefixNameProtect(dtypep->classOrPackagep())); + m_dependencies.insert(EmitCBase::prefixNameProtect(dtypep->classOrPackagep())); } } } diff --git a/src/V3Partition.cpp b/src/V3Partition.cpp index 45976fe76..04d34e842 100644 --- a/src/V3Partition.cpp +++ b/src/V3Partition.cpp @@ -3129,8 +3129,8 @@ static const std::vector createThreadFunctions(const ThreadSchedule& funcp->argTypes("void* voidSelf, bool even_cycle"); // Setup vlSelf an vlSyms - funcp->addStmtsp(new AstCStmt{fl, EmitCBaseVisitor::voidSelfAssign(modp)}); - funcp->addStmtsp(new AstCStmt{fl, EmitCBaseVisitor::symClassAssign()}); + funcp->addStmtsp(new AstCStmt{fl, EmitCBase::voidSelfAssign(modp)}); + funcp->addStmtsp(new AstCStmt{fl, EmitCBase::symClassAssign()}); // Invoke each mtask scheduled to this thread from the thread function for (const ExecMTask* const mtaskp : thread) { diff --git a/src/V3Sched.cpp b/src/V3Sched.cpp index 601b82c7b..c1652e040 100644 --- a/src/V3Sched.cpp +++ b/src/V3Sched.cpp @@ -607,7 +607,7 @@ std::pair makeEvalLoop(AstNetlist* netlistp, const s AstTextBlock* const blockp = new AstTextBlock{flp}; failp->addThensp(blockp); FileLine* const locp = netlistp->topModulep()->fileline(); - const string& file = EmitCBaseVisitor::protect(locp->filename()); + const string& file = VIdProtect::protect(locp->filename()); const string& line = cvtToStr(locp->lineno()); const auto add = [&](const string& text) { blockp->addText(flp, text, true); }; add("#ifdef VL_DEBUG\n"); diff --git a/src/V3SchedTiming.cpp b/src/V3SchedTiming.cpp index 212163164..e772d1bcb 100644 --- a/src/V3SchedTiming.cpp +++ b/src/V3SchedTiming.cpp @@ -362,7 +362,7 @@ void transformForks(AstNetlist* const netlistp) { // If we're in a class, add a vlSymsp arg if (m_inClass) { newfuncp->addInitsp(new AstCStmt{nodep->fileline(), "VL_KEEP_THIS;\n"}); - newfuncp->argTypes(EmitCBaseVisitor::symClassVar()); + newfuncp->argTypes(EmitCBase::symClassVar()); callp->argTypes("vlSymsp"); } // Put the begin's statements in the function, delete the begin diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 64567e122..ea12eb5f3 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -802,7 +802,7 @@ private: // Convert input/inout DPI arguments to Internal types string args; - args += ("(" + EmitCBaseVisitor::symClassName() + args += ("(" + EmitCBase::symClassName() + "*)(__Vscopep->symsp())"); // Upcast w/o overhead AstNode* argnodesp = nullptr; for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) { @@ -1181,15 +1181,14 @@ private: cfuncp->isConstructor(true); AstClass* const classp = m_statep->getClassp(nodep); if (classp->extendsp()) { - cfuncp->baseCtors( - EmitCBaseVisitor::prefixNameProtect(classp->extendsp()->classp())); + cfuncp->baseCtors(EmitCBase::prefixNameProtect(classp->extendsp()->classp())); } } if (cfuncp->dpiExportImpl()) cfuncp->cname(nodep->cname()); if (!nodep->dpiImport() && !nodep->taskPublic()) { // Need symbol table - cfuncp->argTypes(EmitCBaseVisitor::symClassVar()); + cfuncp->argTypes(EmitCBase::symClassVar()); if (cfuncp->name() == "new") { const string stmt = VIdProtect::protect("_ctor_var_reset") + "(vlSymsp);\n"; cfuncp->addInitsp(new AstCStmt{nodep->fileline(), stmt}); diff --git a/src/V3Trace.cpp b/src/V3Trace.cpp index 32dbd8471..d7669f62d 100644 --- a/src/V3Trace.cpp +++ b/src/V3Trace.cpp @@ -154,7 +154,7 @@ public: //###################################################################### // Trace state, as a visitor of each AstNode -class TraceVisitor final : public EmitCBaseVisitor { +class TraceVisitor final : public VNVisitor { private: // NODE STATE // V3Hasher in V3DupFinder @@ -511,8 +511,8 @@ private: funcp->argTypes("void* voidSelf, " + v3Global.opt.traceClassBase() + "::" + (v3Global.opt.useTraceOffload() ? "OffloadBuffer" : "Buffer") + "* bufp"); - addInitStr(voidSelfAssign(m_topModp)); - addInitStr(symClassAssign()); + addInitStr(EmitCBase::voidSelfAssign(m_topModp)); + addInitStr(EmitCBase::symClassAssign()); // Add global activity check to change dump functions if (!full) { // addInitStr("if (VL_UNLIKELY(!vlSymsp->__Vm_activity)) return;\n"); @@ -709,8 +709,8 @@ private: cleanupFuncp->isStatic(true); cleanupFuncp->isLoose(true); m_topScopep->addBlocksp(cleanupFuncp); - cleanupFuncp->addInitsp(new AstCStmt{fl, voidSelfAssign(m_topModp)}); - cleanupFuncp->addInitsp(new AstCStmt{fl, symClassAssign()}); + cleanupFuncp->addInitsp(new AstCStmt{fl, EmitCBase::voidSelfAssign(m_topModp)}); + cleanupFuncp->addInitsp(new AstCStmt{fl, EmitCBase::symClassAssign()}); // Register it m_regFuncp->addStmtsp(new AstText{fl, "tracep->addCleanupCb(", true}); diff --git a/src/V3TraceDecl.cpp b/src/V3TraceDecl.cpp index bba3bc78b..704d1d4b4 100644 --- a/src/V3TraceDecl.cpp +++ b/src/V3TraceDecl.cpp @@ -93,7 +93,7 @@ public: //###################################################################### // TraceDecl state, as a visitor of each AstNode -class TraceDeclVisitor final : public EmitCBaseVisitor { +class TraceDeclVisitor final : public VNVisitor { private: // NODE STATE diff --git a/src/V3VariableOrder.cpp b/src/V3VariableOrder.cpp index bdff566ba..6f19fe113 100644 --- a/src/V3VariableOrder.cpp +++ b/src/V3VariableOrder.cpp @@ -169,7 +169,7 @@ class VariableOrder final { : (sigbytes == 1) ? 2 : 10; // Anonymous structure ok - attributes.anonOk = EmitCBaseVisitor::isAnonOk(varp); + attributes.anonOk = EmitCBase::isAnonOk(varp); } }