@@ -153,16 +153,18 @@ struct RTLIL::IdString
153153 static std::vector<char *> global_id_storage_;
154154 static std::unordered_map<std::string_view, int > global_id_index_;
155155#ifndef YOSYS_NO_IDS_REFCNT
156- // For prepopulated IdStrings, the refcount is meaningless since they
157- // are never freed even if the refcount is zero. For code efficiency
158- // we increment the refcount of prepopulated IdStrings like any other string,
159- // but we never decrement the refcount or check whether it's zero.
160- // So, make this unsigned because refcounts of preopulated IdStrings may overflow
161- // and overflow of signed integers is undefined behavior.
162- static std::vector<uint32_t > global_refcount_storage_;
156+ // All (index, refcount) pairs in this map have refcount > 0.
157+ static std::unordered_map<int , int > global_refcount_storage_;
163158 static std::vector<int > global_free_idx_list_;
164159#endif
165160
161+ static int refcount (int idx) {
162+ auto it = global_refcount_storage_.find (idx);
163+ if (it == global_refcount_storage_.end ())
164+ return 0 ;
165+ return it->second ;
166+ }
167+
166168 static inline void xtrace_db_dump ()
167169 {
168170 #ifdef YOSYS_XTRACE_GET_PUT
@@ -171,7 +173,7 @@ struct RTLIL::IdString
171173 if (global_id_storage_.at (idx) == nullptr )
172174 log (" #X# DB-DUMP index %d: FREE\n " , idx);
173175 else
174- log (" #X# DB-DUMP index %d: '%s' (ref %u)\n " , idx, global_id_storage_. at (idx), global_refcount_storage_. at (idx) );
176+ log (" #X# DB-DUMP index %d: '%s' (ref %u)\n " , idx, refcount (idx), refcount );
175177 }
176178 #endif
177179 }
@@ -191,7 +193,7 @@ struct RTLIL::IdString
191193 if (it != global_id_index_.end ()) {
192194 #ifdef YOSYS_XTRACE_GET_PUT
193195 if (yosys_xtrace)
194- log (" #X# GET-BY-NAME '%s' (index %d, refcount %u)\n " , global_id_storage_.at (it->second ), it->second , global_refcount_storage_. at (it->second ));
196+ log (" #X# GET-BY-NAME '%s' (index %d, refcount %u)\n " , global_id_storage_.at (it->second ), it->second , refcount (it->second ));
195197 #endif
196198 return it->second ;
197199 }
@@ -211,7 +213,6 @@ struct RTLIL::IdString
211213 log_assert (global_id_storage_.size () < 0x40000000 );
212214 global_free_idx_list_.push_back (global_id_storage_.size ());
213215 global_id_storage_.push_back (nullptr );
214- global_refcount_storage_.push_back (0 );
215216 }
216217
217218 int idx = global_free_idx_list_.back ();
@@ -234,7 +235,7 @@ struct RTLIL::IdString
234235
235236 #ifdef YOSYS_XTRACE_GET_PUT
236237 if (yosys_xtrace)
237- log (" #X# GET-BY-NAME '%s' (index %d, refcount %u)\n " , global_id_storage_.at (idx), idx, global_refcount_storage_. at (idx));
238+ log (" #X# GET-BY-NAME '%s' (index %d, refcount %u)\n " , global_id_storage_.at (idx), idx, refcount (idx));
238239 #endif
239240
240241 return idx;
@@ -436,11 +437,17 @@ struct RTLIL::OwningIdString : public RTLIL::IdString {
436437 static void get_reference (int idx)
437438 {
438439 #ifndef YOSYS_NO_IDS_REFCNT
439- global_refcount_storage_[idx]++;
440+ if (idx < static_cast <short >(StaticId::STATIC_ID_END))
441+ return ;
442+ auto it = global_refcount_storage_.find (idx);
443+ if (it == global_refcount_storage_.end ())
444+ global_refcount_storage_.insert (it, {idx, 1 });
445+ else
446+ ++it->second ;
440447 #endif
441448 #ifdef YOSYS_XTRACE_GET_PUT
442449 if (yosys_xtrace && idx >= static_cast <short >(StaticId::STATIC_ID_END))
443- log (" #X# GET-BY-INDEX '%s' (index %d, refcount %u)\n " , global_id_storage_.at (idx), idx, global_refcount_storage_. at (idx));
450+ log (" #X# GET-BY-INDEX '%s' (index %d, refcount %u)\n " , global_id_storage_.at (idx), idx, refcount (idx));
444451 #endif
445452 }
446453
@@ -452,11 +459,14 @@ struct RTLIL::OwningIdString : public RTLIL::IdString {
452459 if (index_ < static_cast <short >(StaticId::STATIC_ID_END) || !destruct_guard_ok)
453460 return ;
454461 #ifdef YOSYS_XTRACE_GET_PUT
455- if (yosys_xtrace) {
456- log (" #X# PUT '%s' (index %d, refcount %u)\n " , global_id_storage_.at (index_), index_, global_refcount_storage_.at (index_));
457- }
462+ if (yosys_xtrace)
463+ log (" #X# PUT '%s' (index %d, refcount %u)\n " , global_id_storage_.at (index_), index_, refcount (index_));
458464 #endif
459- --global_refcount_storage_[index_];
465+ auto it = global_refcount_storage_.find (index_);
466+ log_assert (it != global_refcount_storage_.end () && it->second >= 1 );
467+ if (--it->second == 0 ) {
468+ global_refcount_storage_.erase (it);
469+ }
460470 #endif
461471 }
462472};
0 commit comments