From f14cd547915cb3b86256aaff73d5cd9f4e101843 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sat, 5 Dec 2020 21:08:00 -0800 Subject: [PATCH] Switches over to having a correctly layered configuration system Instead of having the configuration being loaded and stored in to a frontend system. First moves the backing store of the configuration in to FEXCore. Each layer that is constructed then loads its particular configuration. After the layers are loaded, then a meta layer is constructed that merges the layers flat. This means we will no longer hit the problem where a configuration is stored in the "main" configuration file, then environment and arguments passed manage to overwrite it. The order of the layers going from inner most layer to outer most, with outermost overwriting previous layer configurations is as follows: Main < Global application < Local application < Arguments < Environment One step that needs to be changed in the future is that FEXCore can then just load its configuration from the layers directly since the data is in FEXCore now. This will be reserved for a future change so we are less disruptive. --- External/FEXCore/Source/Common/Paths.cpp | 2 +- .../FEXCore/Source}/Common/StringConv.h | 3 +- .../Source/Interface/Config/Config.cpp | 154 ++++++++ .../FEXCore/include/FEXCore/Config/Config.h | 113 ++++++ Source/Common/ArgumentLoader.cpp | 64 ++-- Source/Common/ArgumentLoader.h | 16 +- Source/Common/Config.cpp | 348 +++++++++++------- Source/Common/Config.h | 104 +++--- Source/Common/EnvironmentLoader.cpp | 120 ------ Source/Core/CPU/HostCore/HostCore.cpp | 2 +- Source/Tests/ELFLoader.cpp | 69 ++-- Source/Tests/HarnessHelpers.h | 4 +- Source/Tests/IRLoader.cpp | 23 +- Source/Tests/TestHarness.cpp | 5 +- Source/Tests/TestHarnessRunner.cpp | 32 +- Source/Tests/TestSingleStepHardware.cpp | 11 +- Source/Tests/UnitTestGenerator.cpp | 8 +- Source/Tools/Debugger/IMGui_I.cpp | 12 +- Source/Tools/Debugger/Main.cpp | 8 +- Source/Tools/Opt.cpp | 9 +- 20 files changed, 672 insertions(+), 435 deletions(-) rename {Source => External/FEXCore/Source}/Common/StringConv.h (97%) diff --git a/External/FEXCore/Source/Common/Paths.cpp b/External/FEXCore/Source/Common/Paths.cpp index a1247e547..da716ce47 100644 --- a/External/FEXCore/Source/Common/Paths.cpp +++ b/External/FEXCore/Source/Common/Paths.cpp @@ -17,7 +17,7 @@ namespace FEXCore::Paths { } if (!HomeDir) { - HomeDir = ""; + HomeDir = "."; } char *XDGDataDir = getenv("XDG_DATA_DIR"); diff --git a/Source/Common/StringConv.h b/External/FEXCore/Source/Common/StringConv.h similarity index 97% rename from Source/Common/StringConv.h rename to External/FEXCore/Source/Common/StringConv.h index e060b0fd3..bcec5b51a 100644 --- a/Source/Common/StringConv.h +++ b/External/FEXCore/Source/Common/StringConv.h @@ -4,7 +4,7 @@ #include #include -namespace FEX::StrConv { +namespace FEXCore::StrConv { [[maybe_unused]] static bool Conv(std::string_view Value, bool *Result) { *Result = std::stoi(std::string(Value), nullptr, 0); return true; @@ -38,5 +38,4 @@ namespace FEX::StrConv { *Result = Value; return true; } - } diff --git a/External/FEXCore/Source/Interface/Config/Config.cpp b/External/FEXCore/Source/Interface/Config/Config.cpp index a2afb03b4..2e850a613 100644 --- a/External/FEXCore/Source/Interface/Config/Config.cpp +++ b/External/FEXCore/Source/Interface/Config/Config.cpp @@ -1,3 +1,5 @@ +#include "Common/StringConv.h" + #include #include "Interface/Context/Context.h" @@ -109,5 +111,157 @@ namespace FEXCore::Config { return 0; } + + static std::map> ConfigLayers; + static FEXCore::Config::Layer *Meta{}; + + constexpr std::array LoadOrder = { + FEXCore::Config::LayerType::LAYER_MAIN, + FEXCore::Config::LayerType::LAYER_GLOBAL_APP, + FEXCore::Config::LayerType::LAYER_LOCAL_APP, + FEXCore::Config::LayerType::LAYER_ARGUMENTS, + FEXCore::Config::LayerType::LAYER_ENVIRONMENT, + FEXCore::Config::LayerType::LAYER_TOP + }; + + Layer::Layer(const LayerType _Type) + : Type {_Type} { + } + + Layer::~Layer() { + } + + class MetaLayer final : public FEXCore::Config::Layer { + public: + MetaLayer(const LayerType _Type) + : FEXCore::Config::Layer (_Type) { + } + ~MetaLayer() { + } + void Load(); + + private: + void MergeConfigMap(const LayerOptions &Options); + }; + + void MetaLayer::Load() { + OptionMap.clear(); + + for (auto CurrentLayer = LoadOrder.begin(); CurrentLayer != LoadOrder.end(); ++CurrentLayer) { + auto it = ConfigLayers.find(*CurrentLayer); + if (it != ConfigLayers.end() && *CurrentLayer != Type) { + // Merge this layer's options to this layer + MergeConfigMap(it->second->GetOptionMap()); + } + } + } + + void MetaLayer::MergeConfigMap(const LayerOptions &Options) { + // Insert this layer's options, overlaying previous options that exist here + for (auto &it : Options) { + OptionMap.insert_or_assign(it.first, it.second); + } + } + + void Initialize() { + AddLayer(std::make_unique(FEXCore::Config::LayerType::LAYER_TOP)); + Meta = ConfigLayers.begin()->second.get(); + } + + void Shutdown() { + ConfigLayers.clear(); + Meta = nullptr; + } + + void Load() { + for (auto CurrentLayer = LoadOrder.begin(); CurrentLayer != LoadOrder.end(); ++CurrentLayer) { + auto it = ConfigLayers.find(*CurrentLayer); + if (it != ConfigLayers.end()) { + it->second->Load(); + } + } + } + + void ReloadMetaLayer() { + Meta->Load(); + } + + void AddLayer(std::unique_ptr _Layer) { + ConfigLayers.emplace(_Layer->GetLayerType(), std::move(_Layer)); + } + + bool Exists(ConfigOption Option) { + return Meta->OptionExists(Option); + } + + std::optional All(ConfigOption Option) { + return Meta->All(Option); + } + + std::optional Get(ConfigOption Option) { + return Meta->Get(Option); + } + + void Set(ConfigOption Option, std::string Data) { + Meta->Set(Option, Data); + } + + void EraseSet(ConfigOption Option, std::string Data) { + Meta->EraseSet(Option, Data); + } + + template + T Value::Get(FEXCore::Config::ConfigOption Option) { + T Result; + auto Value = FEXCore::Config::Get(Option); + + if (!FEXCore::StrConv::Conv(**Value, &Result)) { + assert(0 && "Attempted to convert invalid value"); + } + return Result; + } + + template + T Value::GetIfExists(FEXCore::Config::ConfigOption Option, T Default) { + T Result; + auto Value = FEXCore::Config::Get(Option); + + if (Value && FEXCore::StrConv::Conv(**Value, &Result)) { + return Result; + } + else { + return Default; + } + } + + template<> + std::string Value::GetIfExists(FEXCore::Config::ConfigOption Option, std::string Default) { + auto Value = FEXCore::Config::Get(Option); + if (Value) { + return **Value; + } + else { + return Default; + } + } + + template bool Value::GetIfExists(FEXCore::Config::ConfigOption Option, bool Default); + template uint8_t Value::GetIfExists(FEXCore::Config::ConfigOption Option, uint8_t Default); + template uint64_t Value::GetIfExists(FEXCore::Config::ConfigOption Option, uint64_t Default); + + // Constructor + template Value::Value(FEXCore::Config::ConfigOption _Option, std::string Default); + template Value::Value(FEXCore::Config::ConfigOption _Option, bool Default); + template Value::Value(FEXCore::Config::ConfigOption _Option, uint8_t Default); + template Value::Value(FEXCore::Config::ConfigOption _Option, uint64_t Default); + + template + void Value::GetListIfExists(FEXCore::Config::ConfigOption Option, std::list *List) { + auto Value = FEXCore::Config::All(Option); + List->clear(); + if (Value) { + *List = **Value; + } + } } diff --git a/External/FEXCore/include/FEXCore/Config/Config.h b/External/FEXCore/include/FEXCore/Config/Config.h index ed7cc1937..68b24f42d 100644 --- a/External/FEXCore/include/FEXCore/Config/Config.h +++ b/External/FEXCore/include/FEXCore/Config/Config.h @@ -1,6 +1,8 @@ #pragma once #include +#include +#include #include namespace FEXCore::Config { @@ -21,6 +23,11 @@ namespace FEXCore::Config { CONFIG_ABI_LOCAL_FLAGS, CONFIG_ABI_NO_PF, CONFIG_DUMPIR, + CONFIG_SILENTLOGS, + CONFIG_ENVIRONMENT, + CONFIG_OUTPUTLOG, + CONFIG_BREAK_ON_FRONTEND, + CONFIG_DUMP_GPRS, }; enum ConfigCore { @@ -32,4 +39,110 @@ namespace FEXCore::Config { void SetConfig(FEXCore::Context::Context *CTX, ConfigOption Option, uint64_t Config); void SetConfig(FEXCore::Context::Context *CTX, ConfigOption Option, std::string const &Config); uint64_t GetConfig(FEXCore::Context::Context *CTX, ConfigOption Option); + + enum class LayerType { + LAYER_MAIN, + LAYER_ARGUMENTS, + LAYER_GLOBAL_APP, + LAYER_LOCAL_APP, + LAYER_ENVIRONMENT, + LAYER_TOP, + }; + + using LayerValue = std::list; + using LayerOptions = std::unordered_map; + + class Layer { + public: + explicit Layer(const LayerType _Type); + virtual ~Layer(); + + virtual void Load() = 0; + + bool OptionExists(ConfigOption Option) const { + return OptionMap.find(Option) != OptionMap.end(); + } + + std::optional + All(ConfigOption Option) { + const auto it = OptionMap.find(Option); + if (it == OptionMap.end()) { + return std::nullopt; + } + + return &it->second; + } + + std::optional + Get(ConfigOption Option) { + const auto it = OptionMap.find(Option); + if (it == OptionMap.end()) { + return std::nullopt; + } + + return &it->second.front(); + } + + void Set(ConfigOption Option, std::string Data) { + OptionMap[Option].emplace_back(Data); + } + + void EraseSet(ConfigOption Option, std::string Data) { + OptionMap.erase(Option); + OptionMap[Option].emplace_back(Data); + } + + const LayerType GetLayerType() const { return Type; } + const LayerOptions &GetOptionMap() { return OptionMap; } + + protected: + const LayerType Type; + LayerOptions OptionMap; + }; + + void Initialize(); + void Shutdown(); + + void Load(); + void ReloadMetaLayer(); + + void AddLayer(std::unique_ptr _Layer); + + bool Exists(ConfigOption Option); + std::optional All(ConfigOption Option); + std::optional Get(ConfigOption Option); + + void Set(ConfigOption Option, std::string Data); + void EraseSet(ConfigOption Option, std::string Data); + + template + class Value { + public: + template ::value, int>::type = 0> + Value(FEXCore::Config::ConfigOption _Option, T Default) + : Option {_Option} { + ValueData = FEXCore::Config::Value::GetIfExists(Option, Default); + } + + template ::value, int>::type = 0> + Value(FEXCore::Config::ConfigOption _Option, T Default) + : Option {_Option} { + ValueData = FEXCore::Config::Value::GetIfExists(Option, Default); + GetListIfExists(Option, &AppendList); + } + + T operator()() { return ValueData; } + std::list &All() { return AppendList; } + + private: + FEXCore::Config::ConfigOption Option; + T ValueData; + std::list AppendList; + + static T Get(FEXCore::Config::ConfigOption Option); + static T GetIfExists(FEXCore::Config::ConfigOption Option, T Default); + static void GetListIfExists(FEXCore::Config::ConfigOption Option, std::list *List); + }; } diff --git a/Source/Common/ArgumentLoader.cpp b/Source/Common/ArgumentLoader.cpp index 6550ff436..22be3e89a 100644 --- a/Source/Common/ArgumentLoader.cpp +++ b/Source/Common/ArgumentLoader.cpp @@ -1,3 +1,4 @@ +#include "Common/ArgumentLoader.h" #include "Common/Config.h" #include "OptionParser.h" @@ -6,8 +7,7 @@ namespace FEX::ArgLoader { std::vector RemainingArgs; std::vector ProgramArguments; - void Load(int argc, char **argv) { - + void FEX::ArgLoader::ArgLoader::Load() { optparse::OptionParser Parser{}; optparse::OptionGroup CPUGroup(Parser, "CPU Core options"); optparse::OptionGroup EmulationGroup(Parser, "Emulation options"); @@ -168,87 +168,87 @@ namespace FEX::ArgLoader { if (Options.is_set_by_user("Core")) { auto Core = Options["Core"]; if (Core == "irint") - Config::Add("Core", "0"); + Set(FEXCore::Config::ConfigOption::CONFIG_DEFAULTCORE, "0"); else if (Core == "irjit") - Config::Add("Core", "1"); + Set(FEXCore::Config::ConfigOption::CONFIG_DEFAULTCORE, "1"); #ifdef _M_X86_64 else if (Core == "host") - Config::Add("Core", "2"); + Set(FEXCore::Config::ConfigOption::CONFIG_DEFAULTCORE, "2"); #endif } if (Options.is_set_by_user("Break")) { bool Break = Options.get("Break"); - Config::Add("Break", std::to_string(Break)); + Set(FEXCore::Config::ConfigOption::CONFIG_BREAK_ON_FRONTEND, std::to_string(Break)); } if (Options.is_set_by_user("SingleStep")) { bool SingleStep = Options.get("SingleStep"); - Config::Add("SingleStep", std::to_string(SingleStep)); + Set(FEXCore::Config::ConfigOption::CONFIG_SINGLESTEP, std::to_string(SingleStep)); // Single stepping also enforces single instruction size blocks - Config::Add("MaxInst", std::to_string(1u)); + Set(FEXCore::Config::ConfigOption::CONFIG_MAXBLOCKINST, std::to_string(1u)); } else { if (Options.is_set_by_user("MaxInst")) { uint32_t MaxInst = Options.get("MaxInst"); - Config::Add("MaxInst", std::to_string(MaxInst)); + Set(FEXCore::Config::ConfigOption::CONFIG_MAXBLOCKINST, std::to_string(MaxInst)); } } if (Options.is_set_by_user("Multiblock")) { bool Multiblock = Options.get("Multiblock"); - Config::Add("Multiblock", std::to_string(Multiblock)); + Set(FEXCore::Config::ConfigOption::CONFIG_MULTIBLOCK, std::to_string(Multiblock)); } if (Options.is_set_by_user("GdbServer")) { bool GdbServer = Options.get("GdbServer"); - Config::Add("GdbServer", std::to_string(GdbServer)); + Set(FEXCore::Config::ConfigOption::CONFIG_GDBSERVER, std::to_string(GdbServer)); } if (Options.is_set_by_user("Threads")) { uint64_t Config = Options.get("Threads"); - Config::Add("Threads", std::to_string(Config)); + Set(FEXCore::Config::ConfigOption::CONFIG_EMULATED_CPU_CORES, std::to_string(Config)); } if (Options.is_set_by_user("TSOEnabled")) { bool TSOEnabled = Options.get("TSOEnabled"); - Config::Add("TSOEnabled", std::to_string(TSOEnabled)); + Set(FEXCore::Config::ConfigOption::CONFIG_TSO_ENABLED, std::to_string(TSOEnabled)); } - + if (Options.is_set_by_user("SMCChecks")) { bool SMCChecks = Options.get("SMCChecks"); - Config::Add("SMCChecks", std::to_string(SMCChecks)); + Set(FEXCore::Config::ConfigOption::CONFIG_SMC_CHECKS, std::to_string(SMCChecks)); } if (Options.is_set_by_user("AbiLocalFlags")) { bool AbiLocalFlags = Options.get("AbiLocalFlags"); - Config::Add("AbiLocalFlags", std::to_string(AbiLocalFlags)); + Set(FEXCore::Config::ConfigOption::CONFIG_ABI_LOCAL_FLAGS, std::to_string(AbiLocalFlags)); } if (Options.is_set_by_user("AbiNoPF")) { bool AbiNoPF = Options.get("AbiNoPF"); - Config::Add("AbiNoPF", std::to_string(AbiNoPF)); + Set(FEXCore::Config::ConfigOption::CONFIG_ABI_NO_PF, std::to_string(AbiNoPF)); } } { if (Options.is_set_by_user("RootFS")) { std::string Option = Options["RootFS"]; - Config::Add("RootFS", Option); + Set(FEXCore::Config::ConfigOption::CONFIG_ROOTFSPATH, Option); } if (Options.is_set_by_user("ThunkLibs")) { std::string Option = Options["ThunkLibs"]; - Config::Add("ThunkLibs", Option); + Set(FEXCore::Config::ConfigOption::CONFIG_THUNKLIBSPATH, Option); } if (Options.is_set_by_user("UnifiedMemory")) { bool Option = Options.get("UnifiedMemory"); - Config::Add("UnifiedMemory", std::to_string(Option)); + Set(FEXCore::Config::ConfigOption::CONFIG_UNIFIED_MEMORY, std::to_string(Option)); } if (Options.is_set_by_user("Env")) { for (auto iter = Options.all("Env").begin(); iter != Options.all("Env").end(); ++iter) { - Config::Append("Env", *iter); + Set(FEXCore::Config::ConfigOption::CONFIG_ENVIRONMENT, *iter); } } } @@ -256,38 +256,24 @@ namespace FEX::ArgLoader { { if (Options.is_set_by_user("DumpGPRs")) { bool DumpGPRs = Options.get("DumpGPRs"); - Config::Add("DumpGPRs", std::to_string(DumpGPRs)); - } - - if (Options.is_set_by_user("IPCClient")) { - bool IPCClient = Options.get("IPCClient"); - Config::Add("IPCClient", std::to_string(IPCClient)); - } - - if (Options.is_set_by_user("ELFType")) { - bool ELFType = Options.get("ELFType"); - Config::Add("ELFType", std::to_string(ELFType)); - } - if (Options.is_set_by_user("IPCID")) { - const char* Value = Options.get("IPCID"); - Config::Add("IPCID", Value); + Set(FEXCore::Config::ConfigOption::CONFIG_DUMP_GPRS, std::to_string(DumpGPRs)); } } { if (Options.is_set_by_user("SilentLog")) { bool SilentLog = Options.get("SilentLog"); - Config::Add("SilentLog", std::to_string(SilentLog)); + Set(FEXCore::Config::ConfigOption::CONFIG_SILENTLOGS, std::to_string(SilentLog)); } if (Options.is_set_by_user("OutputLog")) { std::string OutputLog = Options["OutputLog"]; - Config::Add("OutputLog", OutputLog); + Set(FEXCore::Config::ConfigOption::CONFIG_OUTPUTLOG, OutputLog); } if (Options.is_set_by_user("DumpIR")) { std::string DumpIR = Options["DumpIR"]; - Config::Add("DumpIR", DumpIR); + Set(FEXCore::Config::ConfigOption::CONFIG_DUMPIR, DumpIR); } } diff --git a/Source/Common/ArgumentLoader.h b/Source/Common/ArgumentLoader.h index 2d51ed15a..6770e9361 100644 --- a/Source/Common/ArgumentLoader.h +++ b/Source/Common/ArgumentLoader.h @@ -1,10 +1,24 @@ #pragma once +#include + #include #include namespace FEX::ArgLoader { - void Load(int argc, char **argv); + class ArgLoader final : public FEXCore::Config::Layer { + public: + explicit ArgLoader(int _argc, char **_argv) + : FEXCore::Config::Layer(FEXCore::Config::LayerType::LAYER_ARGUMENTS) + , argc {_argc} + , argv {_argv} {} + + void Load(); + + private: + int argc{}; + char **argv; + }; std::vector Get(); std::vector GetParsedArgs(); diff --git a/Source/Common/Config.cpp b/Source/Common/Config.cpp index 221078c60..870fa2092 100644 --- a/Source/Common/Config.cpp +++ b/Source/Common/Config.cpp @@ -1,12 +1,15 @@ #include "Common/Config.h" + #include #include #include #include #include +#include #include #include +#include #include #include #include @@ -14,56 +17,60 @@ #include namespace FEX::Config { - std::unordered_map> ConfigMap; + std::string GetConfigFolder(bool Global) { + std::string ConfigDir; + if (Global) { + ConfigDir = GLOBAL_DATA_DIRECTORY; + } + else { + char const *HomeDir = getenv("HOME"); - struct JsonAllocator { - jsonPool_t PoolObject; - std::unique_ptr> json_objects; - }; + if (!HomeDir) { + HomeDir = getenv("PWD"); + } + + if (!HomeDir) { + HomeDir = "."; + } + + char const *ConfigXDG = getenv("XDG_CONFIG_HOME"); + ConfigDir = ConfigXDG ? ConfigXDG : HomeDir; + ConfigDir += "/.fex-emu/"; + + // Ensure the folder structure is created for our configuration + if (!std::filesystem::exists(ConfigDir) && + !std::filesystem::create_directories(ConfigDir)) { + LogMan::Msg::D("Couldn't create config directory: '%s'", ConfigDir.c_str()); + // Let's go local in this case + return "./"; + } + } + + return ConfigDir; + } std::string GetConfigFileLocation() { - char const *HomeDir = getenv("HOME"); - - if (!HomeDir) { - HomeDir = getenv("PWD"); - } - - if (!HomeDir) { - HomeDir = ""; - } - - char const *ConfigXDG = getenv("XDG_CONFIG_HOME"); - std::string ConfigDir = ConfigXDG ? ConfigXDG : HomeDir; - ConfigDir += "/.fex-emu/"; - - // Ensure the folder structure is created for our configuration - if (!std::filesystem::exists(ConfigDir) && - !std::filesystem::create_directories(ConfigDir)) { - LogMan::Msg::D("Couldn't create config directory: '%s'", ConfigDir.c_str()); - // Let's go local in this case - return "Config.json"; - } - - std::string ConfigFile = ConfigDir; - ConfigFile += "Config.json"; - + std::string ConfigFile = GetConfigFolder(false) + "Config.json"; return ConfigFile; } - json_t* PoolInit(jsonPool_t* Pool) { - JsonAllocator* alloc = json_containerOf(Pool, JsonAllocator, PoolObject); - alloc->json_objects = std::make_unique>(); - return &*alloc->json_objects->emplace(alloc->json_objects->end()); + std::string GetApplicationConfig(std::string &Filename, bool Global) { + std::string ConfigFile = GetConfigFolder(Global); + if (!Global && + !std::filesystem::exists(ConfigFile) && + !std::filesystem::create_directories(ConfigFile)) { + LogMan::Msg::D("Couldn't create config directory: '%s'", ConfigFile.c_str()); + // Let's go local in this case + return "./"; + } + + ConfigFile += "AppConfig/" + Filename + ".json"; + return ConfigFile; } - json_t* PoolAlloc(jsonPool_t* Pool) { - JsonAllocator* alloc = json_containerOf(Pool, JsonAllocator, PoolObject); - return &*alloc->json_objects->emplace(alloc->json_objects->end()); - } - - bool LoadConfigFile(std::vector &Data) { + bool LoadConfigFile(std::vector &Data, std::string Config) { std::fstream ConfigFile; - ConfigFile.open(GetConfigFileLocation(), std::fstream::in); + ConfigFile.open(Config, std::ios::in); if (!ConfigFile.is_open()) { return false; @@ -73,7 +80,8 @@ namespace FEX::Config { LogMan::Msg::D("Couldn't load configuration file: Seek end"); return false; } - size_t FileSize = ConfigFile.tellg(); + + auto FileSize = ConfigFile.tellg(); if (ConfigFile.fail()) { LogMan::Msg::D("Couldn't load configuration file: tellg"); return false; @@ -86,7 +94,7 @@ namespace FEX::Config { if (FileSize > 0) { Data.resize(FileSize); - if (ConfigFile.read(&Data.at(0), FileSize)) { + if (!ConfigFile.read(&Data.at(0), FileSize)) { // Probably means permissions aren't set. Just early exit return false; } @@ -99,9 +107,25 @@ namespace FEX::Config { return true; } - void Init() { + struct JsonAllocator { + jsonPool_t PoolObject; + std::unique_ptr> json_objects; + }; + + json_t* PoolInit(jsonPool_t* Pool) { + JsonAllocator* alloc = json_containerOf(Pool, JsonAllocator, PoolObject); + alloc->json_objects = std::make_unique>(); + return &*alloc->json_objects->emplace(alloc->json_objects->end()); + } + + json_t* PoolAlloc(jsonPool_t* Pool) { + JsonAllocator* alloc = json_containerOf(Pool, JsonAllocator, PoolObject); + return &*alloc->json_objects->emplace(alloc->json_objects->end()); + } + + void LoadJSonConfig(std::string &Config, std::function Func) { std::vector Data; - if (!LoadConfigFile(Data)) { + if (!LoadConfigFile(Data, Config)) { return; } @@ -141,118 +165,172 @@ namespace FEX::Config { return; } - FEX::Config::Add(ConfigName, ConfigString); + Func(ConfigName, ConfigString); } } - void Shutdown() { + static const std::map ConfigToNameLookup = {{ + {FEXCore::Config::ConfigOption::CONFIG_DEFAULTCORE, "Core"}, + {FEXCore::Config::ConfigOption::CONFIG_MAXBLOCKINST, "MaxInst"}, + {FEXCore::Config::ConfigOption::CONFIG_SINGLESTEP, "SingleStep"}, + {FEXCore::Config::ConfigOption::CONFIG_MULTIBLOCK, "Multiblock"}, + {FEXCore::Config::ConfigOption::CONFIG_GDBSERVER, "GdbServer"}, + {FEXCore::Config::ConfigOption::CONFIG_EMULATED_CPU_CORES, "Threads"}, + {FEXCore::Config::ConfigOption::CONFIG_ROOTFSPATH, "RootFS"}, + {FEXCore::Config::ConfigOption::CONFIG_THUNKLIBSPATH, "ThunkLibs"}, + {FEXCore::Config::ConfigOption::CONFIG_SILENTLOGS, "SilentLog"}, + {FEXCore::Config::ConfigOption::CONFIG_ENVIRONMENT, "Env"}, + {FEXCore::Config::ConfigOption::CONFIG_OUTPUTLOG, "OutputLog"}, + {FEXCore::Config::ConfigOption::CONFIG_DUMPIR, "DumpIR"}, + {FEXCore::Config::ConfigOption::CONFIG_TSO_ENABLED, "TSOEnabled"}, + {FEXCore::Config::ConfigOption::CONFIG_SMC_CHECKS, "SMCChecks"}, + {FEXCore::Config::ConfigOption::CONFIG_ABI_LOCAL_FLAGS, "ABILocalFlags"}, + {FEXCore::Config::ConfigOption::CONFIG_ABI_NO_PF, "ABINoPF"}, + }}; + + + void SaveLayerToJSON(std::string Filename, FEXCore::Config::Layer *const Layer) { char Buffer[4096]; - char *Dest; + char *Dest{}; Dest = json_objOpen(Buffer, nullptr); Dest = json_objOpen(Dest, "Config"); - for (auto &it : ConfigMap) { - if (!it.second().empty()) { - Dest = json_str(Dest, it.first.data(), it.second().c_str()); - } + for (auto &it : Layer->GetOptionMap()) { + auto &Name = ConfigToNameLookup.find(it.first)->second; + for (auto &var : it.second) { + Dest = json_str(Dest, Name.c_str(), var.c_str()); + } } Dest = json_objClose(Dest); Dest = json_objClose(Dest); json_end(Dest); - // Write the config to a temporary file first then move it to the correct location - // This is to solve threading issues when multiple applications are loading and storing the configuration - std::string Config = GetConfigFileLocation(); - std::string ConfigTmp{Config}; - ConfigTmp.resize(Config.size() + 6); - - auto it = ConfigTmp.rbegin(); - for (int i = 6; i > 0; --i) { - *it = 'X'; - ++it; - } - - int tmp = mkstemp(&ConfigTmp.at(0)); - write(tmp, Buffer, strlen(Buffer)); - close(tmp); - // Rename only works if ther files are in the same filesystem - rename(ConfigTmp.c_str(), GetConfigFileLocation().c_str()); - - ConfigMap.clear(); + std::ofstream Output (Filename, std::ios::out | std::ios::binary); + if (Output.is_open()) { + Output.write(Buffer, strlen(Buffer)); + Output.close(); + } } - void Add(std::string const &Key, std::string_view const Value) { - FEX::Config::Value Val{Key, Value, true}; - ConfigMap.try_emplace(Key, Val); + OptionMapper::OptionMapper(FEXCore::Config::LayerType Layer) + : FEXCore::Config::Layer(Layer) { } - void Append(std::string const &Key, std::string_view const Value) { - auto Iter = ConfigMap.find(Key); - if (Iter == ConfigMap.end()) { - FEX::Config::Value Val{Key, "", true}; - Iter = ConfigMap.try_emplace(Key, Val).first; - } - Iter->second.Append(std::string(Value)); - } + static const std::map ConfigLookup = {{ + {"Core", FEXCore::Config::ConfigOption::CONFIG_DEFAULTCORE}, + {"MaxInst", FEXCore::Config::ConfigOption::CONFIG_MAXBLOCKINST}, + {"SingleStep", FEXCore::Config::ConfigOption::CONFIG_SINGLESTEP}, + {"Multiblock", FEXCore::Config::ConfigOption::CONFIG_MULTIBLOCK}, + {"GdbServer", FEXCore::Config::ConfigOption::CONFIG_GDBSERVER}, + {"Threads", FEXCore::Config::ConfigOption::CONFIG_EMULATED_CPU_CORES}, + {"RootFS", FEXCore::Config::ConfigOption::CONFIG_ROOTFSPATH}, + {"ThunkLibs", FEXCore::Config::ConfigOption::CONFIG_THUNKLIBSPATH}, + {"SilentLog", FEXCore::Config::ConfigOption::CONFIG_SILENTLOGS}, + {"Env", FEXCore::Config::ConfigOption::CONFIG_ENVIRONMENT}, + {"OutputLog", FEXCore::Config::ConfigOption::CONFIG_OUTPUTLOG}, + {"DumpIR", FEXCore::Config::ConfigOption::CONFIG_DUMPIR}, + {"TSOEnabled", FEXCore::Config::ConfigOption::CONFIG_TSO_ENABLED}, + {"SMCChecks", FEXCore::Config::ConfigOption::CONFIG_SMC_CHECKS}, + {"ABILocalFlags", FEXCore::Config::ConfigOption::CONFIG_ABI_LOCAL_FLAGS}, + {"AbiNoPF", FEXCore::Config::ConfigOption::CONFIG_ABI_NO_PF}, + }}; - bool Exists(std::string const &Key) { - return ConfigMap.find(Key) != ConfigMap.end(); - } - - Value &Get(std::string const &Key) { - auto Value = ConfigMap.find(Key); - if (Value == ConfigMap.end()) - assert(0 && "Not a real config value"); - return Value->second; - } - - Value *GetIfExists(std::string const &Key) { - auto Value = ConfigMap.find(Key); - if (Value == ConfigMap.end()) - return nullptr; - - return &Value->second; - } - - template - T Get(std::string const &Key) { - T Value; - if (!FEX::StrConv::Conv(Get(Key)(), &Value)) { - assert(0 && "Attempted to convert invalid value"); - } - return Value; - } - - template - T GetIfExists(std::string const &Key, T Default) { - T Value; - if (Exists(Key) && FEX::StrConv::Conv(FEX::Config::Get(Key)(), &Value)) { - return Value; - } - else { - return Default; + void OptionMapper::MapNameToOption(const char *ConfigName, const char *ConfigString) { + auto it = ConfigLookup.find(ConfigName); + if (it != ConfigLookup.end()) { + Set(it->second, ConfigString); } } - template<> - std::string GetIfExists(std::string const &Key, std::string Default) { - auto Res = GetIfExists(Key); - if (Res) { - return (*Res)(); - } - else { - return Default; - } + MainLoader::MainLoader() + : FEX::Config::OptionMapper(FEXCore::Config::LayerType::LAYER_MAIN) { + Config = GetConfigFileLocation(); } - template bool GetIfExists(std::string const &Key, bool Default); - template uint8_t GetIfExists(std::string const &Key, uint8_t Default); - template uint64_t GetIfExists(std::string const &Key, uint64_t Default); + MainLoader::MainLoader(std::string ConfigFile) + : FEX::Config::OptionMapper(FEXCore::Config::LayerType::LAYER_MAIN) { + Config = ConfigFile; + } - void GetListIfExists(std::string const &Key, std::list *List) { - List->clear(); - auto Res = GetIfExists(Key); - if (Res) { - *List = Res->All(); + void MainLoader::Load() { + LoadJSonConfig(Config, [this](const char *Name, const char *ConfigString) { + MapNameToOption(Name, ConfigString); + }); + } + + AppLoader::AppLoader(std::string Filename, bool Global) + : FEX::Config::OptionMapper(Global ? FEXCore::Config::LayerType::LAYER_GLOBAL_APP : FEXCore::Config::LayerType::LAYER_LOCAL_APP) { + Config = GetApplicationConfig(Filename, Global); + + // Immediately load so we can reload the meta layer + Load(); + } + + void AppLoader::Load() { + LoadJSonConfig(Config, [this](const char *Name, const char *ConfigString) { + MapNameToOption(Name, ConfigString); + }); + } + + EnvLoader::EnvLoader(char *const _envp[]) + : FEXCore::Config::Layer(FEXCore::Config::LayerType::LAYER_ENVIRONMENT) + , envp {_envp} { + } + + void EnvLoader::Load() { + std::unordered_map EnvMap; + + for(const char *const *pvar=envp; pvar && *pvar; pvar++) { + std::string_view Var(*pvar); + size_t pos = Var.rfind('='); + if (std::string::npos == pos) + continue; + + std::string_view Ident = Var.substr(0,pos); + std::string_view Value = Var.substr(pos+1); + EnvMap[Ident]=Value; + } + + std::function GetVar = [=](const std::string_view id) -> std::optional { + if (EnvMap.find(id) != EnvMap.end()) + return EnvMap.at(id); + + // If envp[] was empty, search using std::getenv() + const char* vs = std::getenv(id.data()); + if (vs) { + return vs; + } + else { + return std::nullopt; + } + }; + + static const std::array, 18> ConfigLookup = {{ + {"FEX_CORE", FEXCore::Config::ConfigOption::CONFIG_DEFAULTCORE}, + {"FEX_MAXINST", FEXCore::Config::ConfigOption::CONFIG_MAXBLOCKINST}, + {"FEX_SINGLESTEP", FEXCore::Config::ConfigOption::CONFIG_SINGLESTEP}, + {"FEX_MULTIBLOCK", FEXCore::Config::ConfigOption::CONFIG_MULTIBLOCK}, + {"FEX_GDBSERVER", FEXCore::Config::ConfigOption::CONFIG_GDBSERVER}, + {"FEX_THREADS", FEXCore::Config::ConfigOption::CONFIG_EMULATED_CPU_CORES}, + {"FEX_ROOTFS", FEXCore::Config::ConfigOption::CONFIG_ROOTFSPATH}, + {"FEX_THUNKLIBS", FEXCore::Config::ConfigOption::CONFIG_THUNKLIBSPATH}, + {"FEX_SILENTLOG", FEXCore::Config::ConfigOption::CONFIG_SILENTLOGS}, + {"FEX_ENV", FEXCore::Config::ConfigOption::CONFIG_ENVIRONMENT}, + {"FEX_OUTPUTLOG", FEXCore::Config::ConfigOption::CONFIG_OUTPUTLOG}, + {"FEX_DUMPIR", FEXCore::Config::ConfigOption::CONFIG_DUMPIR}, + {"FEX_TSOENABLED", FEXCore::Config::ConfigOption::CONFIG_TSO_ENABLED}, + {"FEX_SMCCHECKS", FEXCore::Config::ConfigOption::CONFIG_SMC_CHECKS}, + {"FEX_ABILOCALFLAGS", FEXCore::Config::ConfigOption::CONFIG_ABI_LOCAL_FLAGS}, + {"FEX_ABINOPF", FEXCore::Config::ConfigOption::CONFIG_ABI_NO_PF}, + {"FEX_BREAK", FEXCore::Config::ConfigOption::CONFIG_BREAK_ON_FRONTEND}, + {"FEX_DUMP_GPRS", FEXCore::Config::ConfigOption::CONFIG_DUMP_GPRS}, + }}; + + std::optional Value; + + for (auto &it : ConfigLookup) { + if ((Value = GetVar(it.first)).has_value()) { + Set(it.second, std::string(*Value)); + } } } } diff --git a/Source/Common/Config.h b/Source/Common/Config.h index 52b780135..a56ed5a26 100644 --- a/Source/Common/Config.h +++ b/Source/Common/Config.h @@ -1,6 +1,5 @@ #pragma once - -#include "Common/StringConv.h" +#include #include #include @@ -11,66 +10,55 @@ * @brief This is a singleton for storing global configuration state */ namespace FEX::Config { - template - class Value; - - void Init(); - void Shutdown(); - - void Add(std::string const &Key, std::string_view const Value); - void Append(std::string const &Key, std::string_view const Value); - bool Exists(std::string const &Key); - Value &Get(std::string const &Key); - Value *GetIfExists(std::string const &Key); - - template - T Get(std::string const &Key); - - template - T GetIfExists(std::string const &Key, T Default); - - void GetListIfExists(std::string const &Key, std::list *List); - - template - class Value { + class EmptyMapper : public FEXCore::Config::Layer { public: - Value(std::string const &key, std::string_view const Value, bool ConfigBacking) - : Key {key} { - ValueData = Value; + explicit EmptyMapper() + : FEXCore::Config::Layer(FEXCore::Config::LayerType::LAYER_MAIN) { } + void Load() override {} - template ::value, int>::type = 0> - Value(std::string const &key, T Default) - : Key {key} { - ValueData = FEX::Config::GetIfExists(Key, Default); - } - - template ::value, int>::type = 0> - Value(std::string const &key, T Default) - : Key {key} { - ValueData = FEX::Config::GetIfExists(Key, Default); - FEX::Config::GetListIfExists(Key, &AppendList); - } - - void Set(T NewValue) { - ValueData = NewValue; - FEX::Config::Add(Key, std::to_string(NewValue)); - } - - void Append(T NewValue) { - AppendList.emplace_back(NewValue); - } - - T operator()() { return ValueData; } - std::list &All() { return AppendList; } - - private: - std::string const Key; - T ValueData; - std::list AppendList; + protected: }; + class OptionMapper : public FEXCore::Config::Layer { + public: + explicit OptionMapper(FEXCore::Config::LayerType Layer); + protected: + void MapNameToOption(const char *ConfigName, const char *ConfigString); + }; + + class MainLoader final : public FEX::Config::OptionMapper { + public: + explicit MainLoader(); + explicit MainLoader(std::string ConfigFile); + void Load() override; + + private: + std::string Config; + }; + + class AppLoader final : public FEX::Config::OptionMapper { + public: + explicit AppLoader(std::string Filename, bool Global); + void Load(); + + private: + std::string Config; + }; + + class EnvLoader final : public FEXCore::Config::Layer { + public: + explicit EnvLoader(char *const _envp[]); + void Load() override; + + private: + char *const *envp; + }; + + std::string GetConfigFolder(bool Global); + std::string GetConfigFileLocation(); + std::string GetApplicationConfig(std::string &Filename, bool Global); + + void SaveLayerToJSON(std::string Filename, FEXCore::Config::Layer *const Layer); } diff --git a/Source/Common/EnvironmentLoader.cpp b/Source/Common/EnvironmentLoader.cpp index 3c428fc1d..6c11c158f 100644 --- a/Source/Common/EnvironmentLoader.cpp +++ b/Source/Common/EnvironmentLoader.cpp @@ -12,126 +12,6 @@ namespace FEX::EnvLoader { void Load(char *const envp[]) { - std::unordered_map EnvMap; - - for(const char *const *pvar=envp; pvar && *pvar; pvar++) { - string_view Var(*pvar); - size_t pos = Var.rfind('='); - if (string::npos==pos) - continue; - - string_view Ident = Var.substr(0,pos); - string_view Value = Var.substr(pos+1); - EnvMap[Ident]=Value; - } - - std::function GetVar = [=](const string_view id) -> const string_view { - if (EnvMap.find(id) != EnvMap.end()) - return EnvMap.at(id); - - // If envp[] was empty, search using std::getenv() - const char* vs = std::getenv(id.data()); - string_view sv(vs?vs:""); - return sv; - }; - - string_view Value; - { - if ((Value = GetVar("FEX_CORE")).size()) { - // Accept Numeric or name // - if (isdigit(Value[0])) Config::Add("Core", Value); - else { - uint32_t CoreVal = 0; - if (Value == string_view("irint")) CoreVal = 0; // default - else if (Value == string_view("irjit")) CoreVal = 1; -#ifdef _M_X86_64 - else if (Value == string_view("host")) CoreVal = 2; -#endif - else { LogMan::Msg::D("FEX_CORE has invalid identifier"); } - Config::Add("Core", std::to_string(CoreVal)); - } - } - - if ((Value = GetVar("FEX_BREAK")).size()) { - if (isdigit(Value[0])) Config::Add("Break", Value); - } - - if ((Value = GetVar("FEX_SINGLE_STEP")).size()) { - if (isdigit(Value[0])) { - Config::Add("SingleStep", Value); - Config::Add("MaxInst", std::to_string(1u)); - } - } - else if ((Value = GetVar("FEX_MAX_INST")).size()) { - if (isdigit(Value[0])) Config::Add("MaxInst", Value); - } - - if ((Value = GetVar("FEX_MULTIBLOCK")).size()) { - if (isdigit(Value[0])) Config::Add("Multiblock", Value); - } - - if ((Value = GetVar("FEX_GDB_SERVER")).size()) { - if (isdigit(Value[0])) Config::Add("GdbServer", Value); - } - - if ((Value = GetVar("FEX_THREADS")).size()) { - if (isdigit(Value[0])) Config::Add("Threads", Value); - } - - if ((Value = GetVar("FEX_TSO_ENABLED")).size()) { - if (isdigit(Value[0])) Config::Add("TSOEnabled", Value); - } - - if ((Value = GetVar("FEX_SMC_CHECKS")).size()) { - if (isdigit(Value[0])) Config::Add("SMCChecks", Value); - } - } - - { - if ((Value = GetVar("FEX_ROOTFS")).size()) { - Config::Add("RootFS", Value); - if (!std::filesystem::exists(Value)) { - LogMan::Msg::D("FEX_ROOTFS '%s' doesn't exist", Value.data()); - Config::Add("RootFS", ""); - } - } - - if ((Value = GetVar("FEX_UNIFIED_MEM")).size()) { - if (isdigit(Value[0])) Config::Add("UnifiedMemory", Value); - } - } - - { - if ((Value = GetVar("FEX_DUMP_GPRS")).size()) { - if (isdigit(Value[0])) Config::Add("DumpGPRs", Value); - } - - if ((Value = GetVar("FEX_IPC_CLIENT")).size()) { - if (isdigit(Value[0])) Config::Add("IPCClient", Value); - } - - if ((Value = GetVar("FEX_ELF_TYPE")).size()) { - if (isdigit(Value[0])) Config::Add("ELFType", Value); - } - - if ((Value = GetVar("FEX_IPCID")).size()) { - Config::Add("IPCID", Value); - } - } - - { - if ((Value = GetVar("FEX_SILENTLOG")).size()) { - Config::Add("SilentLog", Value); - } - - if ((Value = GetVar("FEX_OUTPUTLOG")).size()) { - Config::Add("OutputLog", Value); - } - - if ((Value = GetVar("FEX_DUMPIR")).size()) { - Config::Add("DumpIR", Value); - } - } } } diff --git a/Source/Core/CPU/HostCore/HostCore.cpp b/Source/Core/CPU/HostCore/HostCore.cpp index 31bf53141..8c5169e2f 100644 --- a/Source/Core/CPU/HostCore/HostCore.cpp +++ b/Source/Core/CPU/HostCore/HostCore.cpp @@ -48,7 +48,7 @@ private: void InstallSignalHandler(); FEX::ThreadState *ThreadState; - FEX::Config::Value ConfigMultiblock{"Multiblock", false}; + FEXCore::Config::Value ConfigMultiblock{"Multiblock", false}; std::thread ExecutionThread; Memmap LocalMemoryMapper{}; pid_t ChildPid; diff --git a/Source/Tests/ELFLoader.cpp b/Source/Tests/ELFLoader.cpp index 60a86079e..021f7be7c 100644 --- a/Source/Tests/ELFLoader.cpp +++ b/Source/Tests/ELFLoader.cpp @@ -143,26 +143,45 @@ int main(int argc, char **argv, char **const envp) { return -1; } - FEX::Config::Init(); - FEX::EnvLoader::Load(envp); - FEX::ArgLoader::Load(argc, argv); + FEXCore::Config::Initialize(); + FEXCore::Config::AddLayer(std::make_unique()); + FEXCore::Config::AddLayer(std::make_unique(argc, argv)); + FEXCore::Config::AddLayer(std::make_unique(envp)); + FEXCore::Config::Load(); - FEX::Config::Value CoreConfig{"Core", 0}; - FEX::Config::Value BlockSizeConfig{"MaxInst", 1}; - FEX::Config::Value SingleStepConfig{"SingleStep", false}; - FEX::Config::Value MultiblockConfig{"Multiblock", false}; - FEX::Config::Value GdbServerConfig{"GdbServer", false}; - FEX::Config::Value ThreadsConfig{"Threads", 1}; - FEX::Config::Value LDPath{"RootFS", ""}; - FEX::Config::Value ThunkLibsPath{"ThunkLibs", ""}; - FEX::Config::Value SilentLog{"SilentLog", false}; - FEX::Config::Value Environment{"Env", ""}; - FEX::Config::Value OutputLog{"OutputLog", "stderr"}; - FEX::Config::Value DumpIR{"DumpIR", "no"}; - FEX::Config::Value TSOEnabledConfig{"TSOEnabled", true}; - FEX::Config::Value SMCChecksConfig{"SMCChecks", false}; - FEX::Config::Value ABILocalFlags{"ABILocalFlags", false}; - FEX::Config::Value AbiNoPF{"AbiNoPF", false}; + auto Args = FEX::ArgLoader::Get(); + auto ParsedArgs = FEX::ArgLoader::GetParsedArgs(); + + if (Args.empty()) { + // Early exit if we weren't passed an argument + return 0; + } + + std::string Program = Args[0]; + + // These layers load on initialization + FEXCore::Config::AddLayer(std::make_unique(std::filesystem::path(Program).filename(), true)); + FEXCore::Config::AddLayer(std::make_unique(std::filesystem::path(Program).filename(), false)); + + // Reload the meta layer + FEXCore::Config::ReloadMetaLayer(); + + FEXCore::Config::Value CoreConfig{FEXCore::Config::CONFIG_DEFAULTCORE, 0}; + FEXCore::Config::Value BlockSizeConfig{FEXCore::Config::CONFIG_MAXBLOCKINST, 1}; + FEXCore::Config::Value SingleStepConfig{FEXCore::Config::CONFIG_SINGLESTEP, false}; + FEXCore::Config::Value MultiblockConfig{FEXCore::Config::CONFIG_MULTIBLOCK, false}; + FEXCore::Config::Value GdbServerConfig{FEXCore::Config::CONFIG_GDBSERVER, false}; + FEXCore::Config::Value ThreadsConfig{FEXCore::Config::CONFIG_EMULATED_CPU_CORES, 1}; + FEXCore::Config::Value LDPath{FEXCore::Config::CONFIG_ROOTFSPATH, ""}; + FEXCore::Config::Value ThunkLibsPath{FEXCore::Config::CONFIG_THUNKLIBSPATH, ""}; + FEXCore::Config::Value SilentLog{FEXCore::Config::CONFIG_SILENTLOGS, false}; + FEXCore::Config::Value Environment{FEXCore::Config::CONFIG_ENVIRONMENT, ""}; + FEXCore::Config::Value OutputLog{FEXCore::Config::CONFIG_OUTPUTLOG, "stderr"}; + FEXCore::Config::Value DumpIR{FEXCore::Config::CONFIG_DUMPIR, "no"}; + FEXCore::Config::Value TSOEnabledConfig{FEXCore::Config::CONFIG_TSO_ENABLED, true}; + FEXCore::Config::Value SMCChecksConfig{FEXCore::Config::CONFIG_SMC_CHECKS, false}; + FEXCore::Config::Value ABILocalFlags{FEXCore::Config::CONFIG_ABI_LOCAL_FLAGS, false}; + FEXCore::Config::Value AbiNoPF{FEXCore::Config::CONFIG_ABI_NO_PF, false}; ::SilentLog = SilentLog(); @@ -179,16 +198,6 @@ int main(int argc, char **argv, char **const envp) { } } - auto Args = FEX::ArgLoader::Get(); - auto ParsedArgs = FEX::ArgLoader::GetParsedArgs(); - - if (Args.empty()) { - // Early exit if we weren't passed an argument - return 0; - } - - std::string Program = Args[0]; - InterpreterHandler(&Program, LDPath(), &Args); if (!std::filesystem::exists(Program)) { @@ -249,7 +258,7 @@ int main(int argc, char **argv, char **const envp) { FEXCore::Context::DestroyContext(CTX); FEXCore::SHM::DestroyRegion(SHM); - FEX::Config::Shutdown(); + FEXCore::Config::Shutdown(); if (OutputFD != stderr && OutputFD != stdout && diff --git a/Source/Tests/HarnessHelpers.h b/Source/Tests/HarnessHelpers.h index ff4369ddd..400516860 100644 --- a/Source/Tests/HarnessHelpers.h +++ b/Source/Tests/HarnessHelpers.h @@ -290,7 +290,7 @@ namespace FEX::HarnessHelper { bool Is64BitMode() const { return BaseConfig.OptionMode == 1; } private: - FEX::Config::Value ConfigDumpGPRs{"DumpGPRs", false}; + FEXCore::Config::Value ConfigDumpGPRs{FEXCore::Config::CONFIG_DUMP_GPRS, false}; struct ConfigStructBase { uint64_t OptionMatch; @@ -434,7 +434,7 @@ private: }; public: - ELFCodeLoader(std::string const &Filename, std::string const &RootFS, [[maybe_unused]] std::vector const &args, std::vector const &ParsedArgs, char **const envp = nullptr, FEX::Config::Value *AdditionalEnvp = nullptr) + ELFCodeLoader(std::string const &Filename, std::string const &RootFS, [[maybe_unused]] std::vector const &args, std::vector const &ParsedArgs, char **const envp = nullptr, FEXCore::Config::Value *AdditionalEnvp = nullptr) : File {Filename, RootFS, false} , DB {&File} , Args {args} { diff --git a/Source/Tests/IRLoader.cpp b/Source/Tests/IRLoader.cpp index 9a3e8d19b..b75d42b55 100644 --- a/Source/Tests/IRLoader.cpp +++ b/Source/Tests/IRLoader.cpp @@ -97,17 +97,19 @@ int main(int argc, char **argv, char **const envp) { LogMan::Throw::InstallHandler(AssertHandler); LogMan::Msg::InstallHandler(MsgHandler); - FEX::Config::Init(); - FEX::EnvLoader::Load(envp); - FEX::ArgLoader::Load(argc, argv); + FEXCore::Config::Initialize(); + FEXCore::Config::AddLayer(std::make_unique()); + FEXCore::Config::AddLayer(std::make_unique(argc, argv)); + FEXCore::Config::AddLayer(std::make_unique(envp)); + FEXCore::Config::Load(); - FEX::Config::Value CoreConfig{"Core", 0}; - FEX::Config::Value BlockSizeConfig{"MaxInst", 1}; - FEX::Config::Value SingleStepConfig{"SingleStep", false}; - FEX::Config::Value MultiblockConfig{"Multiblock", false}; - FEX::Config::Value GdbServerConfig{"GdbServer", false}; - FEX::Config::Value UnifiedMemory{"UnifiedMemory", false}; - FEX::Config::Value LDPath{"RootFS", ""}; + FEXCore::Config::Value CoreConfig{FEXCore::Config::CONFIG_DEFAULTCORE, 0}; + FEXCore::Config::Value BlockSizeConfig{FEXCore::Config::CONFIG_MAXBLOCKINST, 1}; + FEXCore::Config::Value SingleStepConfig{FEXCore::Config::CONFIG_SINGLESTEP, false}; + FEXCore::Config::Value MultiblockConfig{FEXCore::Config::CONFIG_MULTIBLOCK, false}; + FEXCore::Config::Value GdbServerConfig{FEXCore::Config::CONFIG_GDBSERVER, false}; + FEXCore::Config::Value LDPath{FEXCore::Config::CONFIG_ROOTFSPATH, ""}; + FEXCore::Config::Value UnifiedMemory{FEXCore::Config::CONFIG_UNIFIED_MEMORY, false}; auto Args = FEX::ArgLoader::Get(); auto ParsedArgs = FEX::ArgLoader::GetParsedArgs(); @@ -169,7 +171,6 @@ int main(int argc, char **argv, char **const envp) { FEXCore::Context::DestroyContext(CTX); FEXCore::SHM::DestroyRegion(SHM); - FEX::Config::Shutdown(); return Return; } diff --git a/Source/Tests/TestHarness.cpp b/Source/Tests/TestHarness.cpp index edf014c15..3c4110214 100644 --- a/Source/Tests/TestHarness.cpp +++ b/Source/Tests/TestHarness.cpp @@ -51,7 +51,10 @@ int main(int argc, char **argv) { LogMan::Throw::InstallHandler(AssertHandler); LogMan::Msg::InstallHandler(MsgHandler); - FEX::ArgLoader::Load(argc, argv); + FEXCore::Config::Initialize(); + FEXCore::Config::AddLayer(std::make_unique()); + FEXCore::Config::AddLayer(std::make_unique(argc, argv)); + FEXCore::Config::Load(); auto Args = FEX::ArgLoader::Get(); diff --git a/Source/Tests/TestHarnessRunner.cpp b/Source/Tests/TestHarnessRunner.cpp index b5eef5d46..80e7daedd 100644 --- a/Source/Tests/TestHarnessRunner.cpp +++ b/Source/Tests/TestHarnessRunner.cpp @@ -52,18 +52,28 @@ void AssertHandler(char const *Message) { int main(int argc, char **argv, char **const envp) { LogMan::Throw::InstallHandler(AssertHandler); LogMan::Msg::InstallHandler(MsgHandler); - FEX::Config::Init(); - FEX::EnvLoader::Load(envp); - FEX::ArgLoader::Load(argc, argv); + FEXCore::Config::Initialize(); + FEXCore::Config::AddLayer(std::make_unique()); + FEXCore::Config::AddLayer(std::make_unique(argc, argv)); + FEXCore::Config::AddLayer(std::make_unique(envp)); + FEXCore::Config::Load(); - FEX::Config::Value CoreConfig{"Core", 0}; - FEX::Config::Value BlockSizeConfig{"MaxInst", 1}; - FEX::Config::Value SingleStepConfig{"SingleStep", false}; - FEX::Config::Value MultiblockConfig{"Multiblock", false}; - FEX::Config::Value TSOEnabledConfig{"TSOEnabled", true}; - FEX::Config::Value SMCChecksConfig{"SMCChecks", false}; - FEX::Config::Value ABILocalFlags{"ABILocalFlags", false}; - FEX::Config::Value AbiNoPF{"AbiNoPF", false}; + FEXCore::Config::Value CoreConfig{FEXCore::Config::CONFIG_DEFAULTCORE, 0}; + FEXCore::Config::Value BlockSizeConfig{FEXCore::Config::CONFIG_MAXBLOCKINST, 1}; + FEXCore::Config::Value SingleStepConfig{FEXCore::Config::CONFIG_SINGLESTEP, false}; + FEXCore::Config::Value MultiblockConfig{FEXCore::Config::CONFIG_MULTIBLOCK, false}; + FEXCore::Config::Value GdbServerConfig{FEXCore::Config::CONFIG_GDBSERVER, false}; + FEXCore::Config::Value ThreadsConfig{FEXCore::Config::CONFIG_EMULATED_CPU_CORES, 1}; + FEXCore::Config::Value LDPath{FEXCore::Config::CONFIG_ROOTFSPATH, ""}; + FEXCore::Config::Value ThunkLibsPath{FEXCore::Config::CONFIG_THUNKLIBSPATH, ""}; + FEXCore::Config::Value SilentLog{FEXCore::Config::CONFIG_SILENTLOGS, false}; + FEXCore::Config::Value Environment{FEXCore::Config::CONFIG_ENVIRONMENT, ""}; + FEXCore::Config::Value OutputLog{FEXCore::Config::CONFIG_OUTPUTLOG, "stderr"}; + FEXCore::Config::Value DumpIR{FEXCore::Config::CONFIG_DUMPIR, "no"}; + FEXCore::Config::Value TSOEnabledConfig{FEXCore::Config::CONFIG_TSO_ENABLED, true}; + FEXCore::Config::Value SMCChecksConfig{FEXCore::Config::CONFIG_SMC_CHECKS, false}; + FEXCore::Config::Value ABILocalFlags{FEXCore::Config::CONFIG_ABI_LOCAL_FLAGS, false}; + FEXCore::Config::Value AbiNoPF{FEXCore::Config::CONFIG_ABI_NO_PF, false}; auto Args = FEX::ArgLoader::Get(); diff --git a/Source/Tests/TestSingleStepHardware.cpp b/Source/Tests/TestSingleStepHardware.cpp index d0bbc29f1..46d9b4583 100644 --- a/Source/Tests/TestSingleStepHardware.cpp +++ b/Source/Tests/TestSingleStepHardware.cpp @@ -88,11 +88,13 @@ void AssertHandler(char const *Message) { int main(int argc, char **argv, char **const envp) { LogMan::Throw::InstallHandler(AssertHandler); LogMan::Msg::InstallHandler(MsgHandler); - FEX::Config::Init(); - FEX::EnvLoader::Load(envp); - FEX::ArgLoader::Load(argc, argv); + FEXCore::Config::Initialize(); + FEXCore::Config::AddLayer(std::make_unique()); + FEXCore::Config::AddLayer(std::make_unique(argc, argv)); + FEXCore::Config::AddLayer(std::make_unique(envp)); + FEXCore::Config::Load(); - FEX::Config::Value CoreConfig{"Core", 0}; + FEXCore::Config::Value CoreConfig{FEXCore::Config::CONFIG_DEFAULTCORE, 0}; auto Args = FEX::ArgLoader::Get(); // FEX::Core localCore {static_cast(CoreConfig())}; @@ -103,6 +105,5 @@ int main(int argc, char **argv, char **const envp) { // localCore.RunLoop(true); // printf("Managed to load? %s\n", Result ? "Yes" : "No"); - FEX::Config::Shutdown(); return 0; } diff --git a/Source/Tests/UnitTestGenerator.cpp b/Source/Tests/UnitTestGenerator.cpp index 3468fcf72..3e82cf4d6 100644 --- a/Source/Tests/UnitTestGenerator.cpp +++ b/Source/Tests/UnitTestGenerator.cpp @@ -2390,9 +2390,11 @@ int main(int argc, char **argv, char **const envp) { LogMan::Throw::InstallHandler(AssertHandler); LogMan::Msg::InstallHandler(MsgHandler); - FEX::Config::Init(); - FEX::EnvLoader::Load(envp); - FEX::ArgLoader::Load(argc, argv); + FEXCore::Config::Initialize(); + FEXCore::Config::AddLayer(std::make_unique()); + FEXCore::Config::AddLayer(std::make_unique(argc, argv)); + FEXCore::Config::AddLayer(std::make_unique(envp)); + FEXCore::Config::Load(); auto Args = FEX::ArgLoader::Get(); diff --git a/Source/Tools/Debugger/IMGui_I.cpp b/Source/Tools/Debugger/IMGui_I.cpp index dc6c9d22c..71666771a 100644 --- a/Source/Tools/Debugger/IMGui_I.cpp +++ b/Source/Tools/Debugger/IMGui_I.cpp @@ -800,10 +800,10 @@ namespace History { namespace Config { bool ShowConfig = true; struct Configs { - FEX::Config::Value ConfigMaxInst{"MaxInst", 255}; - FEX::Config::Value ConfigCore{"Core", 0}; - FEX::Config::Value ConfigRunningMode{"RunningMode", 0}; - FEX::Config::Value ConfigMultiblock{"Multiblock", false}; + FEXCore::Config::Value ConfigMaxInst{FEXCore::Config::CONFIG_MAXBLOCKINST, 255}; + FEXCore::Config::Value ConfigCore{FEXCore::Config::CONFIG_DEFAULTCORE, 0}; + FEXCore::Config::Value ConfigRunningMode{FEXCore::Config::CONFIG_SINGLESTEP, 0}; + FEXCore::Config::Value ConfigMultiblock{FEXCore::Config::CONFIG_MULTIBLOCK, false}; }; std::unique_ptr Config; @@ -813,11 +813,9 @@ namespace Config { void Window() { if (ImGui::Begin("#Config", &ShowConfig)) { if (ImGui::SliderInt("Max Inst", &NewInstMax, -1, 255)) { - Config->ConfigMaxInst.Set(NewInstMax); } if (ImGui::Checkbox("Multiblock", &Multiblock)) { - Config->ConfigMultiblock.Set(Multiblock); } } ImGui::End(); @@ -832,8 +830,6 @@ namespace Config { } void Shutdown() { - Config::Config->ConfigCore.Set(FEX::DebuggerState::GetCoreType()); - Config::Config->ConfigRunningMode.Set(FEX::DebuggerState::GetRunningMode()); } } diff --git a/Source/Tools/Debugger/Main.cpp b/Source/Tools/Debugger/Main.cpp index 3ef1c8d57..f7e73af4e 100644 --- a/Source/Tools/Debugger/Main.cpp +++ b/Source/Tools/Debugger/Main.cpp @@ -128,9 +128,12 @@ void GetIRCallback(std::stringstream *out, uint64_t PC) { } int main(int argc, char **argv, char **const envp) { - FEX::Config::Init(); FEX::EnvLoader::Load(envp); - FEX::ArgLoader::Load(argc, argv); + FEXCore::Config::Initialize(); + FEXCore::Config::AddLayer(std::make_unique()); + FEXCore::Config::AddLayer(std::make_unique(argc, argv)); + FEXCore::Config::AddLayer(std::make_unique(envp)); + FEXCore::Config::Load(); FEXCore::Context::InitializeStaticTables(); @@ -190,7 +193,6 @@ int main(int argc, char **argv, char **const envp) { ImGui::DestroyContext(); Context->Shutdown(); - FEX::Config::Shutdown(); return 0; } diff --git a/Source/Tools/Opt.cpp b/Source/Tools/Opt.cpp index 169fd9c1f..92928d2a7 100644 --- a/Source/Tools/Opt.cpp +++ b/Source/Tools/Opt.cpp @@ -5,9 +5,10 @@ #include int main(int argc, char **argv, char **const envp) { - FEX::Config::Init(); - FEX::EnvLoader::Load(envp); - FEX::ArgLoader::Load(argc, argv); + FEXCore::Config::Initialize(); + FEXCore::Config::AddLayer(std::make_unique()); + FEXCore::Config::AddLayer(std::make_unique(argc, argv)); + FEXCore::Config::AddLayer(std::make_unique(envp)); + FEXCore::Config::Load(); - FEX::Config::Shutdown(); }