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(); }