Compare commits

...

3 Commits

Author SHA1 Message Date
Icenowy Zheng 9deb30e674
Merge 001a63fba6 into 4b3c03dabc 2024-11-21 00:32:28 +00:00
github-actions[bot] 4b3c03dabc Bump version 2024-11-21 00:21:49 +00:00
Icenowy Zheng 001a63fba6 Fix global cache destruction in IdString class
When enabling LTO on GCC, the sequence of destructing static members in
IdString class is not promised, which can lead to the cache itself being
destructed but the destruct_guard not destructed.

Put all static members of IdString to a subclass similar to current
desturct_guard_t, to mmakes the guard a real guard.

This fixes SEGV when exiting a LTO-ed GCC-built yosys binary.

Signed-off-by: Icenowy Zheng <uwu@icenowy.me>
2023-08-28 16:40:53 +08:00
3 changed files with 167 additions and 174 deletions

View File

@ -155,7 +155,7 @@ ifeq ($(OS), Haiku)
CXXFLAGS += -D_DEFAULT_SOURCE
endif
YOSYS_VER := 0.47+86
YOSYS_VER := 0.47+116
# Note: We arrange for .gitcommit to contain the (short) commit hash in
# tarballs generated with git-archive(1) using .gitattributes. The git repo

View File

@ -32,18 +32,7 @@
YOSYS_NAMESPACE_BEGIN
bool RTLIL::IdString::destruct_guard_ok = false;
RTLIL::IdString::destruct_guard_t RTLIL::IdString::destruct_guard;
std::vector<char*> RTLIL::IdString::global_id_storage_;
dict<char*, int, hash_cstr_ops> RTLIL::IdString::global_id_index_;
#ifndef YOSYS_NO_IDS_REFCNT
std::vector<int> RTLIL::IdString::global_refcount_storage_;
std::vector<int> RTLIL::IdString::global_free_idx_list_;
#endif
#ifdef YOSYS_USE_STICKY_IDS
int RTLIL::IdString::last_created_idx_[8];
int RTLIL::IdString::last_created_idx_ptr_;
#endif
RTLIL::IdString::global_cache_t RTLIL::IdString::global_cache;
#define X(_id) IdString RTLIL::ID::_id;
#include "kernel/constids.inc"

View File

@ -88,25 +88,24 @@ namespace RTLIL
// the global id string cache
static bool destruct_guard_ok; // POD, will be initialized to zero
static struct destruct_guard_t {
destruct_guard_t() { destruct_guard_ok = true; }
~destruct_guard_t() { destruct_guard_ok = false; }
} destruct_guard;
static struct global_cache_t {
bool destruct_guard; // POD, will be initialized to zero
global_cache_t() { destruct_guard = true; }
~global_cache_t() { destruct_guard = false; }
static std::vector<char*> global_id_storage_;
static dict<char*, int, hash_cstr_ops> global_id_index_;
std::vector<char*> global_id_storage_;
dict<char*, int, hash_cstr_ops> global_id_index_;
#ifndef YOSYS_NO_IDS_REFCNT
static std::vector<int> global_refcount_storage_;
static std::vector<int> global_free_idx_list_;
std::vector<int> global_refcount_storage_;
std::vector<int> global_free_idx_list_;
#endif
#ifdef YOSYS_USE_STICKY_IDS
static int last_created_idx_ptr_;
static int last_created_idx_[8];
int last_created_idx_ptr_;
int last_created_idx_[8];
#endif
static inline void xtrace_db_dump()
inline void xtrace_db_dump()
{
#ifdef YOSYS_XTRACE_GET_PUT
for (int idx = 0; idx < GetSize(global_id_storage_); idx++)
@ -119,7 +118,7 @@ namespace RTLIL
#endif
}
static inline void checkpoint()
inline void checkpoint()
{
#ifdef YOSYS_USE_STICKY_IDS
last_created_idx_ptr_ = 0;
@ -134,7 +133,7 @@ namespace RTLIL
#endif
}
static inline int get_reference(int idx)
inline int get_reference(int idx)
{
if (idx) {
#ifndef YOSYS_NO_IDS_REFCNT
@ -148,9 +147,9 @@ namespace RTLIL
return idx;
}
static int get_reference(const char *p)
int get_reference(const char *p)
{
log_assert(destruct_guard_ok);
log_assert(destruct_guard);
if (!p[0])
return 0;
@ -224,11 +223,11 @@ namespace RTLIL
}
#ifndef YOSYS_NO_IDS_REFCNT
static inline void put_reference(int idx)
inline void put_reference(int idx)
{
// put_reference() may be called from destructors after the destructor of
// global_refcount_storage_ has been run. in this case we simply do nothing.
if (!destruct_guard_ok || !idx)
if (!destruct_guard || !idx)
return;
#ifdef YOSYS_XTRACE_GET_PUT
@ -245,7 +244,7 @@ namespace RTLIL
log_assert(refcount == 0);
free_reference(idx);
}
static inline void free_reference(int idx)
inline void free_reference(int idx)
{
if (yosys_xtrace) {
log("#X# Removed IdString '%s' with index %d.\n", global_id_storage_.at(idx), idx);
@ -258,23 +257,28 @@ namespace RTLIL
global_free_idx_list_.push_back(idx);
}
#else
static inline void put_reference(int) { }
inline void put_reference(int) { }
#endif
} global_cache;
static inline void xtrace_db_dump() { global_cache.xtrace_db_dump(); }
static inline void checkpoint() { global_cache.checkpoint(); }
// the actual IdString object is just is a single int
int index_;
inline IdString() : index_(0) { }
inline IdString(const char *str) : index_(get_reference(str)) { }
inline IdString(const IdString &str) : index_(get_reference(str.index_)) { }
inline IdString(const char *str) : index_(global_cache.get_reference(str)) { }
inline IdString(const IdString &str) : index_(global_cache.get_reference(str.index_)) { }
inline IdString(IdString &&str) : index_(str.index_) { str.index_ = 0; }
inline IdString(const std::string &str) : index_(get_reference(str.c_str())) { }
inline ~IdString() { put_reference(index_); }
inline IdString(const std::string &str) : index_(global_cache.get_reference(str.c_str())) { }
inline ~IdString() { global_cache.put_reference(index_); }
inline void operator=(const IdString &rhs) {
put_reference(index_);
index_ = get_reference(rhs.index_);
global_cache.put_reference(index_);
index_ = global_cache.get_reference(rhs.index_);
}
inline void operator=(const char *rhs) {
@ -288,11 +292,11 @@ namespace RTLIL
}
inline const char *c_str() const {
return global_id_storage_.at(index_);
return global_cache.global_id_storage_.at(index_);
}
inline std::string str() const {
return std::string(global_id_storage_.at(index_));
return std::string(global_cache.global_id_storage_.at(index_));
}
inline bool operator<(const IdString &rhs) const {