Files
FEX-Emu--FEX/Source/Common/ArgumentLoader.cpp
T
Ryan Houdek 20f11f25ca Fixes FEXInterpreter argument loading
If the guest application tried pushing arguments then optparse was still
capturing them as unknown and failing.

Just push the arguments directly in to our argument lists
2020-12-09 20:35:02 -08:00

302 lines
9.9 KiB
C++

#include "Common/ArgumentLoader.h"
#include "Common/Config.h"
#include "OptionParser.h"
namespace FEX::ArgLoader {
std::vector<std::string> RemainingArgs;
std::vector<std::string> ProgramArguments;
void FEX::ArgLoader::ArgLoader::Load() {
optparse::OptionParser Parser{};
optparse::OptionGroup CPUGroup(Parser, "CPU Core options");
optparse::OptionGroup EmulationGroup(Parser, "Emulation options");
optparse::OptionGroup TestGroup(Parser, "Test Harness options");
optparse::OptionGroup LoggingGroup(Parser, "Logging options");
{
CPUGroup.add_option("-c", "--core")
.dest("Core")
.help("Which CPU core to use")
#ifdef _M_X86_64
.choices({"irint", "irjit", "host"})
#else
.choices({"irint", "irjit"})
#endif
.set_default("irint");
std::string BreakString = "Break";
std::string MultiBlockString = "Multiblock";
Parser.set_defaults(BreakString, "0");
Parser.set_defaults(MultiBlockString, "0");
CPUGroup.add_option("-b", "--break")
.dest("Break")
.action("store_true")
.help("Break when op dispatcher doesn't understand instruction");
CPUGroup.add_option("--no-break")
.dest("Break")
.action("store_false")
.help("Break when op dispatcher doesn't understand instruction");
CPUGroup.add_option("-s", "--single-step")
.dest("SingleStep")
.action("store_true")
.help("Single Step config");
CPUGroup.add_option("-n", "--max-inst")
.dest("MaxInst")
.help("Maximum number of instructions to stick in a block")
.set_default(~0U);
CPUGroup.add_option("-m", "--multiblock")
.dest("Multiblock")
.action("store_true")
.help("Enable Multiblock code compilation");
CPUGroup.add_option("--no-multiblock")
.dest("Multiblock")
.action("store_false")
.help("Enable Multiblock code compilation");
CPUGroup.add_option("-G", "--gdb")
.dest("GdbServer")
.action("store_true")
.help("Enables the GDB server");
CPUGroup.add_option("-T", "--Threads")
.dest("Threads")
.help("Number of physical hardware threads to tell the process we have")
.set_default(1);
CPUGroup.add_option("--smc-full-checks")
.dest("SMCChecks")
.action("store_true")
.help("Checks code for modification before execution. Slow.")
.set_default(false);
CPUGroup.add_option("--unsafe-no-tso")
.dest("TSOEnabled")
.action("store_false")
.help("Disables TSO IR ops. Highly likely to break any threaded application")
.set_default(true);
CPUGroup.add_option("--unsafe-local-flags")
.dest("AbiLocalFlags")
.action("store_true")
.help("Assumes flags are not used across calls. Hand-written asm could violate this assumption")
.set_default(false);
CPUGroup.add_option("--unsafe-no-pf")
.dest("AbiNoPF")
.action("store_true")
.help("Does not calculate the parity flag on integer operations")
.set_default(false);
Parser.add_option_group(CPUGroup);
}
{
Parser.set_defaults("RootFS", "");
Parser.set_defaults("ThunkLibs", "");
EmulationGroup.add_option("-R", "--rootfs")
.dest("RootFS")
.help("Which Root filesystem prefix to use");
EmulationGroup.add_option("-t", "--thunklibs")
.dest("ThunkLibs")
.help("Folder to find the host-side thunking libs");
EmulationGroup.add_option("-U", "--unified-memory")
.dest("UnifiedMemory")
.action("store_true")
.help("Enable unified memory for the emulator");
EmulationGroup.add_option("-E", "--env")
.dest("Env")
.help("Adds an environment variable")
.action("append");
Parser.add_option_group(EmulationGroup);
}
{
TestGroup.add_option("-g", "--dump-gprs")
.dest("DumpGPRs")
.action("store_true")
.help("When Test Harness ends, print GPR state")
.set_default(false);
TestGroup.add_option("-C", "--ipc-client")
.dest("IPCClient")
.action("store_true")
.help("If the lockstep runner is a client or server")
.set_default(false);
TestGroup.add_option("-I", "--ID")
.dest("IPCID")
.help("Sets an ID that is prepended to IPC names. For multiple runners")
.set_default("0");
TestGroup.add_option("-e", "--elf")
.dest("ELFType")
.action("store_true")
.help("Lockstep runner should load argument as ELF")
.set_default(false);
Parser.add_option_group(TestGroup);
}
{
LoggingGroup.add_option("-s", "--silent")
.dest("SilentLog")
.help("Disable logging")
.action("store_true");
LoggingGroup.add_option("-o", "--output-log")
.dest("OutputLog")
.help("File to write FEX output to [stdout, stderr, <Filename>]")
.set_default("stderr");
LoggingGroup.add_option("--dump-ir")
.dest("DumpIR")
.help("Folder to dump the IR [no, stdout, stderr, <Folder>]")
.set_default("no");
Parser.add_option_group(LoggingGroup);
}
optparse::Values Options = Parser.parse_args(argc, argv);
{
if (Options.is_set_by_user("Core")) {
auto Core = Options["Core"];
if (Core == "irint")
Set(FEXCore::Config::ConfigOption::CONFIG_DEFAULTCORE, "0");
else if (Core == "irjit")
Set(FEXCore::Config::ConfigOption::CONFIG_DEFAULTCORE, "1");
#ifdef _M_X86_64
else if (Core == "host")
Set(FEXCore::Config::ConfigOption::CONFIG_DEFAULTCORE, "2");
#endif
}
if (Options.is_set_by_user("Break")) {
bool Break = Options.get("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");
Set(FEXCore::Config::ConfigOption::CONFIG_SINGLESTEP, std::to_string(SingleStep));
// Single stepping also enforces single instruction size blocks
Set(FEXCore::Config::ConfigOption::CONFIG_MAXBLOCKINST, std::to_string(1u));
}
else {
if (Options.is_set_by_user("MaxInst")) {
uint32_t MaxInst = Options.get("MaxInst");
Set(FEXCore::Config::ConfigOption::CONFIG_MAXBLOCKINST, std::to_string(MaxInst));
}
}
if (Options.is_set_by_user("Multiblock")) {
bool Multiblock = Options.get("Multiblock");
Set(FEXCore::Config::ConfigOption::CONFIG_MULTIBLOCK, std::to_string(Multiblock));
}
if (Options.is_set_by_user("GdbServer")) {
bool GdbServer = Options.get("GdbServer");
Set(FEXCore::Config::ConfigOption::CONFIG_GDBSERVER, std::to_string(GdbServer));
}
if (Options.is_set_by_user("Threads")) {
uint64_t Config = Options.get("Threads");
Set(FEXCore::Config::ConfigOption::CONFIG_EMULATED_CPU_CORES, std::to_string(Config));
}
if (Options.is_set_by_user("TSOEnabled")) {
bool TSOEnabled = Options.get("TSOEnabled");
Set(FEXCore::Config::ConfigOption::CONFIG_TSO_ENABLED, std::to_string(TSOEnabled));
}
if (Options.is_set_by_user("SMCChecks")) {
bool SMCChecks = Options.get("SMCChecks");
Set(FEXCore::Config::ConfigOption::CONFIG_SMC_CHECKS, std::to_string(SMCChecks));
}
if (Options.is_set_by_user("AbiLocalFlags")) {
bool AbiLocalFlags = Options.get("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");
Set(FEXCore::Config::ConfigOption::CONFIG_ABI_NO_PF, std::to_string(AbiNoPF));
}
}
{
if (Options.is_set_by_user("RootFS")) {
std::string Option = Options["RootFS"];
Set(FEXCore::Config::ConfigOption::CONFIG_ROOTFSPATH, Option);
}
if (Options.is_set_by_user("ThunkLibs")) {
std::string Option = Options["ThunkLibs"];
Set(FEXCore::Config::ConfigOption::CONFIG_THUNKLIBSPATH, Option);
}
if (Options.is_set_by_user("UnifiedMemory")) {
bool Option = Options.get("UnifiedMemory");
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) {
Set(FEXCore::Config::ConfigOption::CONFIG_ENVIRONMENT, *iter);
}
}
}
{
if (Options.is_set_by_user("DumpGPRs")) {
bool DumpGPRs = Options.get("DumpGPRs");
Set(FEXCore::Config::ConfigOption::CONFIG_DUMP_GPRS, std::to_string(DumpGPRs));
}
}
{
if (Options.is_set_by_user("SilentLog")) {
bool SilentLog = Options.get("SilentLog");
Set(FEXCore::Config::ConfigOption::CONFIG_SILENTLOGS, std::to_string(SilentLog));
}
if (Options.is_set_by_user("OutputLog")) {
std::string OutputLog = Options["OutputLog"];
Set(FEXCore::Config::ConfigOption::CONFIG_OUTPUTLOG, OutputLog);
}
if (Options.is_set_by_user("DumpIR")) {
std::string DumpIR = Options["DumpIR"];
Set(FEXCore::Config::ConfigOption::CONFIG_DUMPIR, DumpIR);
}
}
RemainingArgs = Parser.args();
ProgramArguments = Parser.parsed_args();
}
void LoadWithoutArguments(int _argc, char **_argv) {
// Skip argument 0, which will be the interpreter
for (int i = 1; i < _argc; ++i) {
RemainingArgs.emplace_back(_argv[i]);
}
// Put the interpreter in ProgramArguments
ProgramArguments.emplace_back(_argv[0]);
}
std::vector<std::string> Get() {
return RemainingArgs;
}
std::vector<std::string> GetParsedArgs() {
return ProgramArguments;
}
}