diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 7ecebfb89..bcdbbd452 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -3127,7 +3127,11 @@ void RTLIL::Module::cloneInto(RTLIL::Module *new_mod, bool src_id_verbatim) cons // were inherited via the wholesale copy and already account for // these new AttrObjects, so no retain on src. if (this->meta_ && new_mod->design) { - new_mod->meta_ = new_mod->design->alloc_obj_meta(); + // The Module::name masquerade write in clone() may have + // pre-allocated this slot; reuse it so the name-write + // before cloneInto isn't leaked. + if (!new_mod->meta_) + new_mod->meta_ = new_mod->design->alloc_obj_meta(); *new_mod->meta_ = *this->meta_; } } else { diff --git a/kernel/rtlil.h b/kernel/rtlil.h index ebb4959a4..479abe541 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -129,6 +129,7 @@ namespace RTLIL struct SigNormIndex; struct SrcAttr; struct ObjMeta; + struct ModuleNameMasq; typedef std::pair SigSig; struct PortBit; @@ -2800,12 +2801,50 @@ public: RTLIL::SigBit Oai4Gate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_b, const RTLIL::SigBit &sig_c, const RTLIL::SigBit &sig_d, const RTLIL::SrcAttr &src = RTLIL::SrcAttr()); }; +// Zero-size masquerade for Module::name. Reads/writes route through +// module->design->obj_name(this) / obj_set_name. Shadows NamedObject::name +// at the Module-instance scope; static_cast(module)->name +// still hits the (now-unused) inline base field. Writing requires +// module->design to be set first. +struct RTLIL::ModuleNameMasq { + operator RTLIL::IdString() const; + ModuleNameMasq& operator=(RTLIL::IdString id); + // Without this, `new_mod->name = src_mod->name` invokes the implicit + // copy-assign (no-op) instead of operator=(IdString), so the meta + // never gets written. + ModuleNameMasq& operator=(const ModuleNameMasq& other) { return *this = RTLIL::IdString(other); } + bool empty() const { return RTLIL::IdString(*this).empty(); } + std::string str() const { return RTLIL::IdString(*this).str(); } + const char* c_str() const { return RTLIL::IdString(*this).c_str(); } + bool isPublic() const { return RTLIL::IdString(*this).isPublic(); } + std::string unescape() const { return RTLIL::IdString(*this).unescape(); } + bool begins_with(const char* s) const { return RTLIL::IdString(*this).begins_with(s); } + bool ends_with(const char* s) const { return RTLIL::IdString(*this).ends_with(s); } + template bool in(Ts&&... args) const { + return RTLIL::IdString(*this).in(std::forward(args)...); + } + std::string substr(size_t pos = 0, size_t len = std::string::npos) const { + return RTLIL::IdString(*this).substr(pos, len); + } + size_t size() const { return RTLIL::IdString(*this).size(); } + bool contains(const char *p) const { return RTLIL::IdString(*this).contains(p); } + bool operator==(RTLIL::IdString rhs) const { return RTLIL::IdString(*this) == rhs; } + bool operator!=(RTLIL::IdString rhs) const { return RTLIL::IdString(*this) != rhs; } + bool operator< (RTLIL::IdString rhs) const { return RTLIL::IdString(*this) < rhs; } + bool operator==(const std::string &rhs) const { return RTLIL::IdString(*this) == rhs; } + bool operator!=(const std::string &rhs) const { return RTLIL::IdString(*this) != rhs; } + bool operator==(const ModuleNameMasq &rhs) const { return RTLIL::IdString(*this) == RTLIL::IdString(rhs); } + bool operator!=(const ModuleNameMasq &rhs) const { return RTLIL::IdString(*this) != RTLIL::IdString(rhs); } +}; + struct RTLIL::Module : public RTLIL::NamedObject, public CellAdderMixin { friend struct RTLIL::SigNormIndex; friend struct RTLIL::Cell; friend struct RTLIL::Design; + [[no_unique_address]] RTLIL::ModuleNameMasq name; + Hasher::hash_t hashidx_; [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } @@ -3135,6 +3174,20 @@ void RTLIL::Process::rewrite_sigspecs2(T &functor) it->rewrite_sigspecs2(functor); } +inline RTLIL::ModuleNameMasq::operator RTLIL::IdString() const { + const RTLIL::Module *m = reinterpret_cast( + reinterpret_cast(this) - offsetof(RTLIL::Module, name)); + return m->design ? m->design->obj_name(m) : RTLIL::IdString{}; +} + +inline RTLIL::ModuleNameMasq& RTLIL::ModuleNameMasq::operator=(RTLIL::IdString id) { + RTLIL::Module *m = reinterpret_cast( + reinterpret_cast(this) - offsetof(RTLIL::Module, name)); + log_assert(m->design && "assignment to Module::name requires the module to be attached to a design"); + m->design->obj_set_name(m, id); + return *this; +} + YOSYS_NAMESPACE_END #endif diff --git a/passes/cmds/chtype.cc b/passes/cmds/chtype.cc index eb194f3e3..d68050519 100644 --- a/passes/cmds/chtype.cc +++ b/passes/cmds/chtype.cc @@ -34,7 +34,9 @@ static void publish_design(RTLIL::Design* design) { auto saved_modules = design->modules_; design->modules_.clear(); for (auto& [name, mod] : saved_modules) { - publish(mod->name); + RTLIL::IdString new_name = mod->name; + publish(new_name); + mod->name = new_name; design->modules_[mod->name] = mod; for (auto* cell : mod->cells()) { publish(cell->type);