Remove Config::Edit::None default object

Config::Edit::apply no longer compares its this pointer against a global
object's address. The check it was performing has been moved to the
functions calling apply and turned into a check for a nullptr. This
avoids the need for a global constructor entirely.

Bug: b/175073772
Change-Id: I6395fadb821f1b53cded353ec378d517c43baa2c
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/56432
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Sean Risser <srisser@google.com>
Commit-Queue: Sean Risser <srisser@google.com>
diff --git a/src/Reactor/Coroutine.hpp b/src/Reactor/Coroutine.hpp
index a28f765..dd2fd92 100644
--- a/src/Reactor/Coroutine.hpp
+++ b/src/Reactor/Coroutine.hpp
@@ -139,7 +139,7 @@
 	// finalize() *must* be called explicitly on the same thread that
 	// instantiates the Coroutine instance if operator() is to be invoked on
 	// different threads.
-	inline void finalize(const char *name = "coroutine", const Config::Edit &cfg = Config::Edit::None);
+	inline void finalize(const char *name = "coroutine", const Config::Edit *cfg = nullptr);
 
 	// Starts execution of the coroutine and returns a unique_ptr to a
 	// Stream<> that exposes the await() function for obtaining yielded
@@ -169,7 +169,7 @@
 }
 
 template<typename Return, typename... Arguments>
-void Coroutine<Return(Arguments...)>::finalize(const char *name /*= "coroutine"*/, const Config::Edit &cfg /* = Config::Edit::None */)
+void Coroutine<Return(Arguments...)>::finalize(const char *name /*= "coroutine"*/, const Config::Edit *cfg /* = nullptr */)
 {
 	if(core != nullptr)
 	{
diff --git a/src/Reactor/LLVMReactor.cpp b/src/Reactor/LLVMReactor.cpp
index 72b45dd..ee13ffa 100644
--- a/src/Reactor/LLVMReactor.cpp
+++ b/src/Reactor/LLVMReactor.cpp
@@ -569,7 +569,7 @@
 	return ::defaultConfig();
 }
 
-std::shared_ptr<Routine> Nucleus::acquireRoutine(const char *name, const Config::Edit &cfgEdit /* = Config::Edit::None */)
+std::shared_ptr<Routine> Nucleus::acquireRoutine(const char *name, const Config::Edit *cfgEdit /* = nullptr */)
 {
 	if(jit->builder->GetInsertBlock()->empty() || !jit->builder->GetInsertBlock()->back().isTerminator())
 	{
@@ -591,7 +591,11 @@
 		// ::jit is thread-local, so when this is executed on a separate thread (see JIT_IN_SEPARATE_THREAD)
 		// it needs to only use the jit variable passed in as an argument.
 
-		auto cfg = cfgEdit.apply(jit->config);
+		Config cfg = jit->config;
+		if(cfgEdit)
+		{
+			cfg = cfgEdit->apply(jit->config);
+		}
 
 #ifdef ENABLE_RR_DEBUG_INFO
 		if(jit->debugInfo != nullptr)
@@ -4374,7 +4378,7 @@
 	jit->builder->SetInsertPoint(resumeBlock);
 }
 
-std::shared_ptr<Routine> Nucleus::acquireCoroutine(const char *name, const Config::Edit &cfgEdit /* = Config::Edit::None */)
+std::shared_ptr<Routine> Nucleus::acquireCoroutine(const char *name, const Config::Edit *cfgEdit /* = nullptr */)
 {
 	bool isCoroutine = jit->coroutine.id != nullptr;
 	if(isCoroutine)
@@ -4431,7 +4435,11 @@
 	}
 #endif  // defined(ENABLE_RR_LLVM_IR_VERIFICATION) || !defined(NDEBUG)
 
-	auto cfg = cfgEdit.apply(jit->config);
+	Config cfg = jit->config;
+	if(cfgEdit)
+	{
+		cfg = cfgEdit->apply(jit->config);
+	}
 	jit->optimize(cfg);
 
 	if(false)
diff --git a/src/Reactor/Nucleus.hpp b/src/Reactor/Nucleus.hpp
index d430845..73b23f6 100644
--- a/src/Reactor/Nucleus.hpp
+++ b/src/Reactor/Nucleus.hpp
@@ -99,8 +99,6 @@
 	class Edit
 	{
 	public:
-		static const Edit None;
-
 		Edit &set(Optimization::Level level)
 		{
 			optLevel = level;
@@ -166,7 +164,7 @@
 	static void adjustDefaultConfig(const Config::Edit &cfgEdit);
 	static Config getDefaultConfig();
 
-	std::shared_ptr<Routine> acquireRoutine(const char *name, const Config::Edit &cfgEdit = Config::Edit::None);
+	std::shared_ptr<Routine> acquireRoutine(const char *name, const Config::Edit *cfgEdit = nullptr);
 
 	static Value *allocateStackVariable(Type *type, int arraySize = 0);
 	static BasicBlock *createBasicBlock();
@@ -203,7 +201,7 @@
 	static void yield(Value *val);
 	// Called to finalize coroutine creation. After this call, Routine::getEntry can be called to retrieve the entry point to any
 	// of the three coroutine functions. Called by Coroutine::finalize.
-	std::shared_ptr<Routine> acquireCoroutine(const char *name, const Config::Edit &cfg = Config::Edit::None);
+	std::shared_ptr<Routine> acquireCoroutine(const char *name, const Config::Edit *cfg = nullptr);
 	// Called by Coroutine::operator() to execute CoroutineEntryBegin wrapped up in func. This is needed in case
 	// the call must be run on a separate thread of execution (e.g. on a fiber).
 	static CoroutineHandle invokeCoroutineBegin(Routine &routine, std::function<CoroutineHandle()> func);
diff --git a/src/Reactor/Reactor.cpp b/src/Reactor/Reactor.cpp
index e4b3ebe..98f030a 100644
--- a/src/Reactor/Reactor.cpp
+++ b/src/Reactor/Reactor.cpp
@@ -36,12 +36,8 @@
 
 namespace rr {
 
-const Config::Edit Config::Edit::None = {};
-
 Config Config::Edit::apply(const Config &cfg) const
 {
-	if(this == &None) { return cfg; }
-
 	auto level = optLevelChanged ? optLevel : cfg.optimization.getLevel();
 	auto passes = cfg.optimization.getPasses();
 	apply(optPassEdits, passes);
diff --git a/src/Reactor/Reactor.hpp b/src/Reactor/Reactor.hpp
index a916aba..0d5e4b3 100644
--- a/src/Reactor/Reactor.hpp
+++ b/src/Reactor/Reactor.hpp
@@ -3206,7 +3206,7 @@
 	vsnprintf(fullName, 1024, name, vararg);
 	va_end(vararg);
 
-	auto routine = core->acquireRoutine(fullName, Config::Edit::None);
+	auto routine = core->acquireRoutine(fullName, nullptr);
 	core.reset(nullptr);
 
 	return routine;
@@ -3222,7 +3222,7 @@
 	vsnprintf(fullName, 1024, name, vararg);
 	va_end(vararg);
 
-	auto routine = core->acquireRoutine(fullName, cfg);
+	auto routine = core->acquireRoutine(fullName, &cfg);
 	core.reset(nullptr);
 
 	return routine;
diff --git a/src/Reactor/SubzeroReactor.cpp b/src/Reactor/SubzeroReactor.cpp
index 458b357..db23dc5 100644
--- a/src/Reactor/SubzeroReactor.cpp
+++ b/src/Reactor/SubzeroReactor.cpp
@@ -986,7 +986,7 @@
 // This function lowers and produces executable binary code in memory for the input functions,
 // and returns a Routine with the entry points to these functions.
 template<size_t Count>
-static std::shared_ptr<Routine> acquireRoutine(Ice::Cfg *const (&functions)[Count], const char *const (&names)[Count], const Config::Edit &cfgEdit)
+static std::shared_ptr<Routine> acquireRoutine(Ice::Cfg *const (&functions)[Count], const char *const (&names)[Count], const Config::Edit *cfgEdit)
 {
 	// This logic is modeled after the IceCompiler, as well as GlobalContext::translateFunctions
 	// and GlobalContext::emitItems.
@@ -1089,7 +1089,7 @@
 	return std::shared_ptr<Routine>(handoffRoutine);
 }
 
-std::shared_ptr<Routine> Nucleus::acquireRoutine(const char *name, const Config::Edit &cfgEdit /* = Config::Edit::None */)
+std::shared_ptr<Routine> Nucleus::acquireRoutine(const char *name, const Config::Edit *cfgEdit /* = nullptr */)
 {
 	finalizeFunction();
 	return rr::acquireRoutine({ ::function }, { name }, cfgEdit);
@@ -4930,7 +4930,7 @@
 {
 }
 
-std::shared_ptr<Routine> Nucleus::acquireCoroutine(const char *name, const Config::Edit &cfgEdit /* = Config::Edit::None */)
+std::shared_ptr<Routine> Nucleus::acquireCoroutine(const char *name, const Config::Edit *cfgEdit /* = nullptr */)
 {
 	if(::coroGen)
 	{