diff --git a/src/V3Ast.h b/src/V3Ast.h index dc2a6b523..0e6508036 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -1183,30 +1183,34 @@ inline std::ostream& operator<<(std::ostream& os, const VNumRange& rhs) { class VUseType final { public: enum en : uint8_t { - IMP_INCLUDE, // Implementation (.cpp) needs an include - INT_INCLUDE, // Interface (.h) needs an include - IMP_FWD_CLASS, // Implementation (.cpp) needs a forward class declaration - INT_FWD_CLASS, // Interface (.h) needs a forward class declaration + // Enum values are compared with <, so order matters + INT_FWD_CLASS = 1 << 0, // Interface (.h) needs a forward class declaration + INT_INCLUDE = 1 << 1, // Interface (.h) needs an include }; enum en m_e; VUseType() - : m_e{IMP_FWD_CLASS} {} + : m_e{INT_FWD_CLASS} {} // cppcheck-suppress noExplicitConstructor constexpr VUseType(en _e) : m_e{_e} {} explicit VUseType(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - bool isInclude() const { return m_e == IMP_INCLUDE || m_e == INT_INCLUDE; } - bool isFwdClass() const { return m_e == IMP_FWD_CLASS || m_e == INT_FWD_CLASS; } constexpr operator en() const { return m_e; } + bool containsAny(VUseType other) { return m_e & other.m_e; } const char* ascii() const { - static const char* const names[] = {"IMP_INC", "INT_INC", "IMP_FWD", "INT_FWD"}; - return names[m_e]; + static const char* const names[] = {"INT_FWD", "INT_INC", "INT_FWD_INC"}; + return names[m_e - 1]; } }; constexpr bool operator==(const VUseType& lhs, const VUseType& rhs) { return lhs.m_e == rhs.m_e; } constexpr bool operator==(const VUseType& lhs, VUseType::en rhs) { return lhs.m_e == rhs; } constexpr bool operator==(VUseType::en lhs, const VUseType& rhs) { return lhs == rhs.m_e; } +constexpr VUseType::en operator|(VUseType::en lhs, VUseType::en rhs) { + return VUseType::en((uint8_t)lhs | (uint8_t)rhs); +} +constexpr VUseType::en operator&(VUseType::en lhs, VUseType::en rhs) { + return VUseType::en((uint8_t)lhs & (uint8_t)rhs); +} inline std::ostream& operator<<(std::ostream& os, const VUseType& rhs) { return os << rhs.ascii(); } diff --git a/src/V3CUse.cpp b/src/V3CUse.cpp index e53c8b3d1..1fae654db 100644 --- a/src/V3CUse.cpp +++ b/src/V3CUse.cpp @@ -28,9 +28,11 @@ #include "V3CUse.h" #include "V3Ast.h" +#include "V3FileLine.h" #include "V3Global.h" -#include +#include +#include VL_DEFINE_DEBUG_FUNCTIONS; @@ -46,54 +48,31 @@ class CUseVisitor final : public VNVisitor { // MEMBERS AstNodeModule* const m_modp; // Current module - std::set> m_didUse; // What we already used - bool m_dtypesImplOnly = false; + std::map> m_didUse; // What we already used // METHODS void addNewUse(AstNode* nodep, VUseType useType, const string& name) { - if (m_dtypesImplOnly - && (useType == VUseType::INT_INCLUDE || useType == VUseType::INT_FWD_CLASS)) - return; - - if (m_didUse.emplace(useType, name).second) { - AstCUse* const newp = new AstCUse{nodep->fileline(), useType, name}; - m_modp->addStmtsp(newp); - UINFO(8, "Insert " << newp << endl); + auto e = m_didUse.emplace(name, std::make_pair(nodep->fileline(), useType)); + if (e.second || ((e.first->second.second & useType) != useType)) { + e.first->second.second = e.first->second.second | useType; } } // VISITORS void visit(AstClassRefDType* nodep) override { - if (nodep->user1()) return; // Process once - if (!m_dtypesImplOnly) // We might need to revisit this type for interface - nodep->user1(true); addNewUse(nodep, VUseType::INT_FWD_CLASS, nodep->classp()->name()); } void visit(AstCFunc* nodep) override { - if (nodep->user1SetOnce()) return; // Process once + if (nodep->user1SetOnce()) return; iterateAndNextNull(nodep->argsp()); - - { - VL_RESTORER(m_dtypesImplOnly); - m_dtypesImplOnly = true; - - iterateAndNextNull(nodep->initsp()); - iterateAndNextNull(nodep->stmtsp()); - iterateAndNextNull(nodep->finalsp()); - } + iterateAndNextNull(nodep->stmtsp()); } + void visit(AstCCall* nodep) override { return; } void visit(AstCReturn* nodep) override { - if (nodep->user1SetOnce()) return; // Process once - if (m_dtypesImplOnly) { - for (AstNode* exprp = nodep->op1p(); exprp; exprp = exprp->nextp()) { - if (exprp->dtypep()) iterate(exprp->dtypep()); - } - } else { - iterateChildren(nodep); - } + UASSERT(!nodep->user1SetOnce(), "Visited same return twice."); + iterate(nodep->lhsp()->dtypep()); } void visit(AstNodeDType* nodep) override { - if (nodep->user1SetOnce()) return; // Process once if (nodep->virtRefDTypep()) iterate(nodep->virtRefDTypep()); if (nodep->virtRefDType2p()) iterate(nodep->virtRefDType2p()); @@ -108,7 +87,7 @@ class CUseVisitor final : public VNVisitor { } void visit(AstNode* nodep) override { if (nodep->user1SetOnce()) return; // Process once - if (nodep->dtypep() && !nodep->dtypep()->user1()) iterate(nodep->dtypep()); + if (nodep->dtypep()) iterate(nodep->dtypep()); iterateChildren(nodep); } void visit(AstCell* nodep) override { @@ -123,6 +102,12 @@ public: explicit CUseVisitor(AstNodeModule* modp) : m_modp(modp) { iterate(modp); + + for (auto& used : m_didUse) { + AstCUse* const newp = new AstCUse{used.second.first, used.second.second, used.first}; + m_modp->addStmtsp(newp); + UINFO(8, "Insert " << newp << endl); + } } ~CUseVisitor() override = default; VL_UNCOPYABLE(CUseVisitor); diff --git a/src/V3EmitCBase.h b/src/V3EmitCBase.h index 88fa6cae6..d3d797e3a 100644 --- a/src/V3EmitCBase.h +++ b/src/V3EmitCBase.h @@ -117,11 +117,12 @@ public: static void forModCUse(const AstNodeModule* modp, VUseType useType, F action) { for (AstNode* itemp = modp->stmtsp(); itemp; itemp = itemp->nextp()) { if (AstCUse* const usep = VN_CAST(itemp, CUse)) { - if (usep->useType() == useType) { - if (usep->useType().isInclude()) { + if (usep->useType().containsAny(useType)) { + if (usep->useType().containsAny(VUseType::INT_INCLUDE)) { action("#include \"" + prefixNameProtect(usep) + ".h\"\n"); + continue; // Forward declaration is not necessary } - if (usep->useType().isFwdClass()) { + if (usep->useType().containsAny(VUseType::INT_FWD_CLASS)) { action("class " + prefixNameProtect(usep) + ";\n"); } } diff --git a/src/V3EmitCHeaders.cpp b/src/V3EmitCHeaders.cpp index 04e38e172..4f63aa5b0 100644 --- a/src/V3EmitCHeaders.cpp +++ b/src/V3EmitCHeaders.cpp @@ -380,11 +380,10 @@ class EmitCHeader final : public EmitCConstInit { std::set cuse_set; auto add_to_cuse_set = [&](string s) { cuse_set.insert(s); }; - forModCUse(modp, VUseType::INT_INCLUDE, add_to_cuse_set); - forModCUse(modp, VUseType::INT_FWD_CLASS, add_to_cuse_set); + forModCUse(modp, VUseType::INT_FWD_CLASS | VUseType::INT_INCLUDE, add_to_cuse_set); if (const AstClassPackage* const packagep = VN_CAST(modp, ClassPackage)) { - forModCUse(packagep->classp(), VUseType::INT_INCLUDE, add_to_cuse_set); - forModCUse(packagep->classp(), VUseType::INT_FWD_CLASS, add_to_cuse_set); + forModCUse(packagep->classp(), VUseType::INT_INCLUDE | VUseType::INT_FWD_CLASS, + add_to_cuse_set); } for (const string& s : cuse_set) puts(s);