From b59c7172454f118f935f5d0696662a0427d29673 Mon Sep 17 00:00:00 2001
From: dragonmux <git@dragonmux.network>
Date: Wed, 26 Jul 2023 20:46:56 +0100
Subject: [PATCH 1/2] 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.
---
 kernel/rtlil.cc |  1 +
 kernel/rtlil.h  | 10 +++++-----
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc
index 7f3508b2f..7011429ff 100644
--- a/kernel/rtlil.cc
+++ b/kernel/rtlil.cc
@@ -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_;
diff --git a/kernel/rtlil.h b/kernel/rtlil.h
index 7c7669caa..71ee7f989 100644
--- a/kernel/rtlil.h
+++ b/kernel/rtlil.h
@@ -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

From ef7e35857668a552c6ff783d5db29fa12708e1a2 Mon Sep 17 00:00:00 2001
From: dragonmux <git@dragonmux.network>
Date: Wed, 26 Jul 2023 20:50:55 +0100
Subject: [PATCH 2/2] kernel/rtlil: Trailing whitespace cleanup

---
 kernel/rtlil.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/kernel/rtlil.h b/kernel/rtlil.h
index 71ee7f989..a69ce480b 100644
--- a/kernel/rtlil.h
+++ b/kernel/rtlil.h
@@ -443,13 +443,13 @@ namespace RTLIL
 	static inline std::string encode_filename(const std::string &filename)
 	{
 		std::stringstream val;
-		if (!std::any_of(filename.begin(), filename.end(), [](char c) { 
-			return static_cast<unsigned char>(c) < 33 || static_cast<unsigned char>(c) > 126; 
+		if (!std::any_of(filename.begin(), filename.end(), [](char c) {
+			return static_cast<unsigned char>(c) < 33 || static_cast<unsigned char>(c) > 126;
 		})) return filename;
 		for (unsigned char const c : filename) {
 			if (c < 33 || c > 126)
 				val << stringf("$%02x", c);
-			else 
+			else
 				val << c;
 		}
 		return val.str();