From cd370bf6d11ca3174c66e07d880351fcfc23818a Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 29 Aug 2025 05:56:19 +0000 Subject: [PATCH] Stop using `mutable` in `Const`. Now that we only call `bitvectorize()` in non-const methods, we can move the casting-away-const to only happen in `bitvectorize()`, which is deprecated so only some plugins (maybe) are using it. This means `const` `Const` methods don't change the underlying data, which means they'll be safe to use from multiple threads if/when we want to do that. --- kernel/rtlil.cc | 32 +++++++++++++++++++++----------- kernel/rtlil.h | 22 +++++++++++++--------- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 4175a008d..9863fc4e9 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -204,12 +204,22 @@ const pool &RTLIL::builtin_ff_cell_types() { #define check(condition) log_assert(condition && "malformed Const union") -Const::bitvectype& Const::get_bits() const { +const Const::bitvectype& Const::get_bits() const { check(is_bits()); return *get_if_bits(); } -std::string& Const::get_str() const { +const std::string& Const::get_str() const { + check(is_str()); + return *get_if_str(); +} + +Const::bitvectype& Const::get_bits() { + check(is_bits()); + return *get_if_bits(); +} + +std::string& Const::get_str() { check(is_str()); return *get_if_str(); } @@ -395,7 +405,7 @@ bool RTLIL::Const::as_bool() const return false; } - bitvectype& bv = get_bits(); + const bitvectype& bv = get_bits(); for (size_t i = 0; i < bv.size(); i++) if (bv[i] == State::S1) return true; @@ -542,7 +552,7 @@ std::string RTLIL::Const::decode_string() const if (auto str = get_if_str()) return *str; - bitvectype& bv = get_bits(); + const bitvectype& bv = get_bits(); const int n = GetSize(bv); const int n_over_8 = n / 8; std::string s; @@ -590,7 +600,7 @@ bool RTLIL::Const::empty() const { } } -void RTLIL::Const::bitvectorize_internal() const { +void RTLIL::Const::bitvectorize_internal() { if (tag == backing_tag::bits) return; @@ -641,7 +651,7 @@ bool RTLIL::Const::is_fully_zero() const return true; } - bitvectype& bv = get_bits(); + const bitvectype& bv = get_bits(); for (const auto &bit : bv) if (bit != RTLIL::State::S0) @@ -661,7 +671,7 @@ bool RTLIL::Const::is_fully_ones() const return true; } - bitvectype& bv = get_bits(); + const bitvectype& bv = get_bits(); for (const auto &bit : bv) if (bit != RTLIL::State::S1) return false; @@ -676,7 +686,7 @@ bool RTLIL::Const::is_fully_def() const if (is_str()) return true; - bitvectype& bv = get_bits(); + const bitvectype& bv = get_bits(); for (const auto &bit : bv) if (bit != RTLIL::State::S0 && bit != RTLIL::State::S1) return false; @@ -691,7 +701,7 @@ bool RTLIL::Const::is_fully_undef() const if (auto str = get_if_str()) return str->empty(); - bitvectype& bv = get_bits(); + const bitvectype& bv = get_bits(); for (const auto &bit : bv) if (bit != RTLIL::State::Sx && bit != RTLIL::State::Sz) return false; @@ -706,7 +716,7 @@ bool RTLIL::Const::is_fully_undef_x_only() const if (auto str = get_if_str()) return str->empty(); - bitvectype& bv = get_bits(); + const bitvectype& bv = get_bits(); for (const auto &bit : bv) if (bit != RTLIL::State::Sx) return false; @@ -742,7 +752,7 @@ Hasher RTLIL::Const::hash_into(Hasher h) const // If the bits are all 0/1, hash packed bits using the string hash. // Otherwise hash the leading packed bits with the rest of the bits individually. - bitvectype &bv = get_bits(); + const bitvectype &bv = get_bits(); int size = GetSize(bv); std::string packed; int packed_size = (size + 7) >> 3; diff --git a/kernel/rtlil.h b/kernel/rtlil.h index d2caf81f7..62a62021e 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -723,23 +723,27 @@ private: using bitvectype = std::vector; enum class backing_tag: bool { bits, string }; // Do not access the union or tag even in Const methods unless necessary - mutable backing_tag tag; + backing_tag tag; union { - mutable bitvectype bits_; - mutable std::string str_; + bitvectype bits_; + std::string str_; }; // Use these private utilities instead bool is_bits() const { return tag == backing_tag::bits; } bool is_str() const { return tag == backing_tag::string; } - bitvectype* get_if_bits() const { return is_bits() ? &bits_ : NULL; } - std::string* get_if_str() const { return is_str() ? &str_ : NULL; } + bitvectype* get_if_bits() { return is_bits() ? &bits_ : NULL; } + std::string* get_if_str() { return is_str() ? &str_ : NULL; } + const bitvectype* get_if_bits() const { return is_bits() ? &bits_ : NULL; } + const std::string* get_if_str() const { return is_str() ? &str_ : NULL; } - bitvectype& get_bits() const; - std::string& get_str() const; + bitvectype& get_bits(); + std::string& get_str(); + const bitvectype& get_bits() const; + const std::string& get_str() const; std::vector& bits_internal(); - void bitvectorize_internal() const; + void bitvectorize_internal(); public: Const() : flags(RTLIL::CONST_FLAG_NONE), tag(backing_tag::bits), bits_(std::vector()) {} @@ -772,7 +776,7 @@ public: [[deprecated("Don't use direct access to the internal std::vector, that's an implementation detail.")]] std::vector& bits() { return bits_internal(); } [[deprecated("Don't call bitvectorize() directly, it's an implementation detail.")]] - void bitvectorize() const { bitvectorize_internal(); } + void bitvectorize() const { const_cast(this)->bitvectorize_internal(); } bool as_bool() const;