Files
FEX-Emu--FEX/Source/Tests/IRLoader.cpp
T
Ryan Houdek 9fd3cd8884 Implements IR loader frontend application
This application loads an IR from an IR file.
It then proceeds to lex the file and translate it to binary IR.
Once the file is loaded it then the IR is passed off to the backend and
it attempts to run the IR.

This will be used when debugging RA and writing unit tests directly in
IR.
This is a necessary evil for ensuring correctness
2020-05-07 17:47:37 -07:00

165 lines
4.8 KiB
C++

#include "Common/ArgumentLoader.h"
#include "Common/EnvironmentLoader.h"
#include "CommonCore/VMFactory.h"
#include "Common/Config.h"
#include "HarnessHelpers.h"
#include "IRLoader/Loader.h"
#include "LogManager.h"
#include <FEXCore/Config/Config.h>
#include <FEXCore/Core/CodeLoader.h>
#include <FEXCore/Core/Context.h>
#include <FEXCore/Memory/SharedMem.h>
void MsgHandler(LogMan::DebugLevels Level, char const *Message) {
const char *CharLevel{nullptr};
switch (Level) {
case LogMan::NONE:
CharLevel = "NONE";
break;
case LogMan::ASSERT:
CharLevel = "ASSERT";
break;
case LogMan::ERROR:
CharLevel = "ERROR";
break;
case LogMan::DEBUG:
CharLevel = "DEBUG";
break;
case LogMan::INFO:
CharLevel = "Info";
break;
case LogMan::STDOUT:
CharLevel = "STDOUT";
break;
case LogMan::STDERR:
CharLevel = "STDERR";
break;
default:
CharLevel = "???";
break;
}
printf("[%s] %s\n", CharLevel, Message);
fflush(stdout);
}
void AssertHandler(char const *Message) {
printf("[ASSERT] %s\n", Message);
fflush(stdout);
}
class IRCodeLoader final : public FEXCore::CodeLoader {
public:
IRCodeLoader(FEX::IRLoader::Loader *Loader)
: IR {Loader} {
}
uint64_t StackSize() const override {
return STACK_SIZE;
}
void SetMemoryBase(uint64_t Base, bool Unified) override {
}
uint64_t SetupStack([[maybe_unused]] void *HostPtr, uint64_t GuestPtr) const override {
return GuestPtr + STACK_SIZE - 16;
}
uint64_t DefaultRIP() const override {
return IR->GetEntryRIP();
}
void MapMemoryRegion(std::function<void*(uint64_t, uint64_t, bool, bool)> Mapper) override {
}
void LoadMemory(MemoryWriter Writer) override {
}
uint64_t GetFinalRIP() override { return 0; }
virtual void AddIR(IRHandler Handler) override {
Handler(IR->GetEntryRIP(), IR->CreateIRCopy());
}
private:
FEX::IRLoader::Loader *IR;
constexpr static uint64_t STACK_SIZE = 8 * 1024 * 1024;
};
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);
FEX::Config::Value<uint8_t> CoreConfig{"Core", 0};
FEX::Config::Value<uint64_t> BlockSizeConfig{"MaxInst", 1};
FEX::Config::Value<bool> SingleStepConfig{"SingleStep", false};
FEX::Config::Value<bool> MultiblockConfig{"Multiblock", false};
FEX::Config::Value<bool> GdbServerConfig{"GdbServer", false};
FEX::Config::Value<bool> UnifiedMemory{"UnifiedMemory", false};
FEX::Config::Value<std::string> LDPath{"RootFS", ""};
auto Args = FEX::ArgLoader::Get();
auto ParsedArgs = FEX::ArgLoader::GetParsedArgs();
LogMan::Throw::A(!Args.empty(), "Not enough arguments");
FEXCore::Context::InitializeStaticTables();
auto SHM = FEXCore::SHM::AllocateSHMRegion(1ULL << 36);
auto CTX = FEXCore::Context::CreateNewContext();
FEXCore::Context::InitializeContext(CTX);
FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_DEFAULTCORE, CoreConfig() > 3 ? FEXCore::Config::CONFIG_CUSTOM : CoreConfig());
FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_MULTIBLOCK, MultiblockConfig());
FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_SINGLESTEP, SingleStepConfig());
FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_MAXBLOCKINST, BlockSizeConfig());
FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_GDBSERVER, GdbServerConfig());
FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_ROOTFSPATH, LDPath());
FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_UNIFIED_MEMORY, UnifiedMemory());
FEXCore::Context::SetCustomCPUBackendFactory(CTX, VMFactory::CPUCreationFactory);
FEXCore::Context::AddGuestMemoryRegion(CTX, SHM);
FEX::IRLoader::InitializeStaticTables();
FEX::IRLoader::Loader Loader(Args[0]);
int Return{};
if (Loader.IsValid()) {
IRCodeLoader CodeLoader{&Loader};
FEXCore::Context::InitCore(CTX, &CodeLoader);
FEXCore::Context::ExitReason ShutdownReason = FEXCore::Context::ExitReason::EXIT_SHUTDOWN;
// There might already be an exit handler, leave it installed
if(!FEXCore::Context::GetExitHandler(CTX)) {
FEXCore::Context::SetExitHandler(CTX, [&](uint64_t thread, FEXCore::Context::ExitReason reason) {
if (reason != FEXCore::Context::ExitReason::EXIT_DEBUG) {
ShutdownReason = reason;
FEXCore::Context::Stop(CTX);
}
});
}
FEXCore::Context::RunUntilExit(CTX);
LogMan::Msg::D("Reason we left VM: %d", ShutdownReason);
Return = 0;
}
else {
LogMan::Msg::E("Couldn't load IR");
Return = -1;
}
FEXCore::Context::DestroyContext(CTX);
FEXCore::SHM::DestroyRegion(SHM);
FEX::Config::Shutdown();
return Return;
}