kernel/rtlil: Fixed the destruction guard for IdString

The guard is optimised out on some compilers under certain conditions (eg: LTO on GCC) as constant under C++ lifetime rules.
This is because the guard type's member is invalid to access (UB) after the type has been destroyed, resulting in
`destruct_guard.ok` being unable to be `false` according to the optimiser, based on the lifetime rules.

This patch still invokes UB (all accesses to the destroyed IdString instance are), but at least the optimiser
can't reason that destruct_guard_ok cannot be false and therefore it's safe to optimise out from its guard role.
This commit is contained in:
dragonmux 2023-07-26 20:46:56 +01:00
parent b04d0e09e8
commit b59c717245
No known key found for this signature in database
GPG Key ID: 64861EA89B35507A
2 changed files with 6 additions and 5 deletions

View File

@ -30,6 +30,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_;

View File

@ -85,10 +85,10 @@ namespace RTLIL
// the global id string cache
static bool destruct_guard_ok; // POD, will be initialized to zero
static struct destruct_guard_t {
bool ok; // POD, will be initialized to zero
destruct_guard_t() { ok = true; }
~destruct_guard_t() { ok = false; }
destruct_guard_t() { destruct_guard_ok = true; }
~destruct_guard_t() { destruct_guard_ok = false; }
} destruct_guard;
static std::vector<char*> global_id_storage_;
@ -147,7 +147,7 @@ namespace RTLIL
static int get_reference(const char *p)
{
log_assert(destruct_guard.ok);
log_assert(destruct_guard_ok);
if (!p[0])
return 0;
@ -225,7 +225,7 @@ namespace RTLIL
{
// 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_ok || !idx)
return;
#ifdef YOSYS_XTRACE_GET_PUT