diff --git a/FEXCore/Source/CMakeLists.txt b/FEXCore/Source/CMakeLists.txt index d301f0a70..d5f902496 100644 --- a/FEXCore/Source/CMakeLists.txt +++ b/FEXCore/Source/CMakeLists.txt @@ -18,6 +18,7 @@ set (SRCS Common/JitSymbols.cpp Interface/Context/Context.cpp Interface/Core/LookupCache.cpp + Interface/Core/CodeCache.cpp Interface/Core/Core.cpp Interface/Core/CPUBackend.cpp Interface/Core/Addressing.cpp @@ -57,7 +58,6 @@ set (SRCS Interface/Core/X86Tables/VEXTables.cpp Interface/Core/X86Tables/X87Tables.cpp Interface/GDBJIT/GDBJIT.cpp - Interface/IR/AOTIR.cpp Interface/IR/IRDumper.cpp Interface/IR/IREmitter.cpp Interface/IR/PassManager.cpp diff --git a/FEXCore/Source/Interface/Context/Context.h b/FEXCore/Source/Interface/Context/Context.h index 88c1e4089..8f0ab1cde 100644 --- a/FEXCore/Source/Interface/Context/Context.h +++ b/FEXCore/Source/Interface/Context/Context.h @@ -6,7 +6,7 @@ #include "Interface/Core/CPUID.h" #include "Interface/Core/X86HelperGen.h" #include "Interface/Core/Dispatcher/Dispatcher.h" -#include "Interface/IR/AOTIR.h" +#include #include #include #include @@ -71,7 +71,23 @@ struct CustomIRResult { using BlockDelinkerFunc = void (*)(FEXCore::Core::CpuStateFrame* Frame, FEXCore::Context::ExitFunctionLinkData* Record); constexpr uint32_t TSC_SCALE_MAXIMUM = 1'000'000'000; ///< 1Ghz -class ContextImpl final : public FEXCore::Context::Context, CPU::CodeBufferManager { +class CodeCache : public AbstractCodeCache { +public: + CodeCache(ContextImpl&); + ~CodeCache(); + + ContextImpl& CTX; + bool IsGeneratingCache = false; + + void LoadData(Core::InternalThreadState&, std::byte* MappedCacheFile, const ExecutableFileSectionInfo&) override; + bool SaveData(Core::InternalThreadState&, int TargetFD, const ExecutableFileSectionInfo&, uint64_t SerializedBaseAddress) override; + + void InitiateCacheGeneration() override { + IsGeneratingCache = true; + } +}; + +class ContextImpl final : public FEXCore::Context::Context, public CPU::CodeBufferManager { public: // Context base class implementation. bool InitCore() override; @@ -141,10 +157,9 @@ public: FEXCore::CPUID::XCRResults RunXCRFunction(uint32_t Function) override; FEXCore::CPUID::FunctionResults RunCPUIDFunctionName(uint32_t Function, uint32_t Leaf, uint32_t CPU) override; - FEXCore::IR::AOTIRCacheEntry* LoadAOTIRCacheEntry(const fextl::string& Name) override; - void UnloadAOTIRCacheEntry(FEXCore::IR::AOTIRCacheEntry* Entry) override; - - void FinalizeAOTIRCache() override {} + CodeCache& GetCodeCache() override { + return CodeCache; + } void OnCodeBufferAllocated(CPU::CodeBuffer&) override; void ClearCodeCache(FEXCore::Core::InternalThreadState* Thread, bool NewCodeBuffer = true) override; @@ -224,6 +239,7 @@ public: FEXCore::HLE::SourcecodeResolver* SourcecodeResolver {}; FEXCore::ThunkHandler* ThunkHandler {}; fextl::unique_ptr Dispatcher; + CodeCache CodeCache; SignalDelegator* SignalDelegation {}; X86GeneratedCode X86CodeGen; @@ -330,8 +346,6 @@ private: */ void InitializeCompiler(FEXCore::Core::InternalThreadState* Thread); - IR::AOTIRCaptureCache IRCaptureCache; - bool SupportsHardwareTSO = false; bool AtomicTSOEmulationEnabled = true; bool VectorAtomicTSOEmulationEnabled = false; diff --git a/FEXCore/Source/Interface/Core/CPUBackend.h b/FEXCore/Source/Interface/Core/CPUBackend.h index ed5fc29d8..ab9f13b54 100644 --- a/FEXCore/Source/Interface/Core/CPUBackend.h +++ b/FEXCore/Source/Interface/Core/CPUBackend.h @@ -17,6 +17,10 @@ $end_info$ #include +namespace FEXCore::CPU { +union Relocation; +} + namespace FEXCore { namespace IR { @@ -157,18 +161,7 @@ namespace CPU { virtual CompiledCode CompileCode(uint64_t Entry, uint64_t Size, bool SingleInst, const FEXCore::IR::IRListView* IR, FEXCore::Core::DebugData* DebugData, bool CheckTF) = 0; - /** - * @brief Relocates a block of code from the JIT code object cache - * - * @param Entry - RIP of the entry - * @param SerializationData - Serialization data referring to the object cache for `Entry` - * - * @return An executable function pointer relocated from the cache object - */ - [[nodiscard]] - virtual void* RelocateJITObjectCode(uint64_t /* Entry */, const CodeSerialize::CodeObjectFileSection* /* SerializationData */) { - return nullptr; - } + virtual fextl::vector TakeRelocations() = 0; virtual void ClearCache() {} diff --git a/FEXCore/Source/Interface/Core/CodeCache.cpp b/FEXCore/Source/Interface/Core/CodeCache.cpp new file mode 100644 index 000000000..adac418a3 --- /dev/null +++ b/FEXCore/Source/Interface/Core/CodeCache.cpp @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +#include + +#include + +namespace FEXCore { + +ExecutableFileInfo::~ExecutableFileInfo() = default; + +} // namespace FEXCore + +namespace FEXCore::Context { + +CodeCache::CodeCache(ContextImpl& CTX_) + : CTX(CTX_) {} +CodeCache::~CodeCache() = default; + +void CodeCache::LoadData(Core::InternalThreadState& Thread, std::byte* MappedCacheFile, const ExecutableFileSectionInfo& GuestRIPLookup) { + // TODO +} + +bool CodeCache::SaveData(Core::InternalThreadState& Thread, int fd, const ExecutableFileSectionInfo& SourceBinary, uint64_t SerializedBaseAddress) { + // TODO + return true; +} + +} // namespace FEXCore::Context diff --git a/FEXCore/Source/Interface/Core/Core.cpp b/FEXCore/Source/Interface/Core/Core.cpp index 0d9912ee9..256a0b13f 100644 --- a/FEXCore/Source/Interface/Core/Core.cpp +++ b/FEXCore/Source/Interface/Core/Core.cpp @@ -18,6 +18,7 @@ $end_info$ #include "Interface/Core/JIT/JITClass.h" #include "Interface/Core/Dispatcher/Dispatcher.h" #include "Interface/Core/X86Tables/X86Tables.h" +#include #include "Interface/IR/IR.h" #include "Interface/IR/IREmitter.h" #include "Interface/IR/Passes/RegisterAllocationPass.h" @@ -77,7 +78,7 @@ namespace FEXCore::Context { ContextImpl::ContextImpl(const FEXCore::HostFeatures& Features) : HostFeatures {Features} , CPUID {this} - , IRCaptureCache {this} { + , CodeCache {*this} { if (!Config.Is64BitMode()) { // When operating in 32-bit mode, the virtual memory we care about is only the lower 32-bits. Config.VirtualMemSize = 1ULL << 32; @@ -708,9 +709,9 @@ ContextImpl::GenerateIR(FEXCore::Core::InternalThreadState* Thread, uint64_t Gue ContextImpl::CompileCodeResult ContextImpl::CompileCode(FEXCore::Core::InternalThreadState* Thread, uint64_t GuestRIP, uint64_t MaxInst) { if (SourcecodeResolver && Config.GDBSymbols()) { - auto AOTIRCacheEntry = SyscallHandler->LookupAOTIRCacheEntry(Thread, GuestRIP); - if (AOTIRCacheEntry.Entry) { - AOTIRCacheEntry.Entry->SourcecodeMap = SourcecodeResolver->GenerateMap(AOTIRCacheEntry.Entry->Filename, AOTIRCacheEntry.Entry->FileId); + auto MappedSection = SyscallHandler->LookupExecutableFileSection(*Thread, GuestRIP); + if (MappedSection) { + MappedSection->FileInfo.SourcecodeMap = SourcecodeResolver->GenerateMap(MappedSection->FileInfo.Filename, MappedSection->FileInfo.FileId); } } @@ -785,36 +786,44 @@ uintptr_t ContextImpl::CompileBlock(FEXCore::Core::CpuStateFrame* Frame, uint64_ if (Config.BlockJITNaming()) { auto FragmentBasePtr = CompiledCode.BlockBegin; - if (DebugData) { - auto GuestRIPLookup = SyscallHandler->LookupAOTIRCacheEntry(Thread, GuestRIP); + auto GuestRIPLookup = SyscallHandler->LookupExecutableFileSection(*Thread, GuestRIP); - if (DebugData->Subblocks.size()) { - for (auto& Subblock : DebugData->Subblocks) { - auto BlockBasePtr = FragmentBasePtr + Subblock.HostCodeOffset; - if (GuestRIPLookup.Entry) { - Symbols.Register(Thread->SymbolBuffer.get(), BlockBasePtr, CompiledCode.Size, GuestRIPLookup.Entry->Filename, - GuestRIP - GuestRIPLookup.VAFileStart); - } else { - Symbols.Register(Thread->SymbolBuffer.get(), BlockBasePtr, GuestRIP, Subblock.HostCodeSize); - } - } - } else { - if (GuestRIPLookup.Entry) { - Symbols.Register(Thread->SymbolBuffer.get(), FragmentBasePtr, CompiledCode.Size, GuestRIPLookup.Entry->Filename, - GuestRIP - GuestRIPLookup.VAFileStart); + if (DebugData->Subblocks.size()) { + for (auto& Subblock : DebugData->Subblocks) { + auto BlockBasePtr = FragmentBasePtr + Subblock.HostCodeOffset; + if (GuestRIPLookup) { + Symbols.Register(Thread->SymbolBuffer.get(), BlockBasePtr, CompiledCode.Size, GuestRIPLookup->FileInfo.Filename, + GuestRIP - GuestRIPLookup->FileStartVA); } else { - Symbols.Register(Thread->SymbolBuffer.get(), FragmentBasePtr, GuestRIP, CompiledCode.Size); + Symbols.Register(Thread->SymbolBuffer.get(), BlockBasePtr, GuestRIP, Subblock.HostCodeSize); } } + } else { + if (GuestRIPLookup) { + Symbols.Register(Thread->SymbolBuffer.get(), FragmentBasePtr, CompiledCode.Size, GuestRIPLookup->FileInfo.Filename, + GuestRIP - GuestRIPLookup->FileStartVA); + } else { + Symbols.Register(Thread->SymbolBuffer.get(), FragmentBasePtr, GuestRIP, CompiledCode.Size); + } + } + } + + if (Config.LibraryJITNaming() || Config.GDBSymbols()) { + auto MappedSection = SyscallHandler->LookupExecutableFileSection(*Thread, GuestRIP); + if (MappedSection) { + if (Config.LibraryJITNaming()) { + Symbols.RegisterNamedRegion(Thread->SymbolBuffer.get(), CodePtr, DebugData->HostCodeSize, MappedSection->FileInfo.Filename); + } + + if (Config.GDBSymbols()) { + GDBJITRegister(MappedSection->FileInfo, MappedSection->FileStartVA, GuestRIP, (uintptr_t)CodePtr, *DebugData); + } } } // Clear any relocations that might have been generated - Thread->CPUBackend->ClearRelocations(); - - if (IRCaptureCache.PostCompileCode(Thread, CompiledCode.BlockBegin, GuestRIP, StartAddr, Length, DebugData.get())) { - // Early exit - return (uintptr_t)CodePtr; + if (!CodeCache.IsGeneratingCache) { + Thread->CPUBackend->ClearRelocations(); } if (NeedsAddGuestCodeRanges) { @@ -1009,13 +1018,6 @@ void ContextImpl::MonoBackpatcherWrite(FEXCore::Core::CpuStateFrame* Frame, uint CTX->SyscallHandler->InvalidateGuestCodeRange(Thread, Address, Size); } -IR::AOTIRCacheEntry* ContextImpl::LoadAOTIRCacheEntry(const fextl::string& filename) { - auto rv = IRCaptureCache.LoadAOTIRCacheEntry(filename); - return rv; -} - -void ContextImpl::UnloadAOTIRCacheEntry(IR::AOTIRCacheEntry* Entry) {} - void ContextImpl::ConfigureAOTGen(FEXCore::Core::InternalThreadState* Thread, fextl::set* ExternalBranches, uint64_t SectionMaxAddress) { Thread->FrontendDecoder->SetExternalBranches(ExternalBranches); Thread->FrontendDecoder->SetSectionMaxAddress(SectionMaxAddress); diff --git a/FEXCore/Source/Interface/Core/JIT/Arm64Relocations.cpp b/FEXCore/Source/Interface/Core/JIT/Arm64Relocations.cpp index 68d3c585d..64c590014 100644 --- a/FEXCore/Source/Interface/Core/JIT/Arm64Relocations.cpp +++ b/FEXCore/Source/Interface/Core/JIT/Arm64Relocations.cpp @@ -81,35 +81,32 @@ void Arm64JITCore::InsertGuestRIPMove(ARMEmitter::Register Reg, uint64_t Constan Relocations.emplace_back(MoveABI); } -bool Arm64JITCore::ApplyRelocations(uint64_t GuestEntry, uint64_t CodeEntry, uint64_t CursorEntry, size_t NumRelocations, - const char* EntryRelocations) { - size_t DataIndex {}; - for (size_t j = 0; j < NumRelocations; ++j) { - const FEXCore::CPU::Relocation* Reloc = reinterpret_cast(&EntryRelocations[DataIndex]); - LOGMAN_THROW_A_FMT((DataIndex % alignof(Relocation)) == 0, "Alignment of relocation wasn't adhered to"); +bool Arm64JITCore::ApplyRelocations(uint64_t GuestEntry, std::span Code, std::span Relocations) { + const auto OrigBase = GetBufferBase(); + const auto OrigSize = GetBufferSize(); + const auto OrigOffset = GetCursorOffset(); - switch (Reloc->Header.Type) { + SetBuffer(reinterpret_cast(Code.data()), Code.size_bytes()); + for (auto& Reloc : Relocations) { + switch (Reloc.Header.Type) { case FEXCore::CPU::RelocationTypes::RELOC_NAMED_SYMBOL_LITERAL: { - uint64_t Pointer = GetNamedSymbolLiteral(Reloc->NamedSymbolLiteral.Symbol); + uint64_t Pointer = GetNamedSymbolLiteral(Reloc.NamedSymbolLiteral.Symbol); // Relocation occurs at the cursorEntry + offset relative to that cursor - SetCursorOffset(CursorEntry + Reloc->NamedSymbolLiteral.Offset); + SetCursorOffset(Reloc.NamedSymbolLiteral.Offset); // Generate a literal so we can place it dc64(Pointer); - - DataIndex += sizeof(Reloc->NamedSymbolLiteral); break; } case FEXCore::CPU::RelocationTypes::RELOC_NAMED_THUNK_MOVE: { - uint64_t Pointer = reinterpret_cast(EmitterCTX->ThunkHandler->LookupThunk(Reloc->NamedThunkMove.Symbol)); + uint64_t Pointer = reinterpret_cast(EmitterCTX->ThunkHandler->LookupThunk(Reloc.NamedThunkMove.Symbol)); if (Pointer == ~0ULL) { return false; } // Relocation occurs at the cursorEntry + offset relative to that cursor. - SetCursorOffset(CursorEntry + Reloc->NamedThunkMove.Offset); - LoadConstant(ARMEmitter::Size::i64Bit, ARMEmitter::Register(Reloc->NamedThunkMove.RegisterIndex), Pointer, true); - DataIndex += sizeof(Reloc->NamedThunkMove); + SetCursorOffset(Reloc.NamedThunkMove.Offset); + LoadConstant(ARMEmitter::Size::i64Bit, ARMEmitter::Register(Reloc.NamedThunkMove.RegisterIndex), Pointer, true); break; } case FEXCore::CPU::RelocationTypes::RELOC_GUEST_RIP_MOVE: { @@ -117,18 +114,27 @@ bool Arm64JITCore::ApplyRelocations(uint64_t GuestEntry, uint64_t CodeEntry, uin // XXX: Should spin the relocation list, create a list of guest RIP moves, and ask for them all once, reduces lock contention. uint64_t Pointer = ~0ULL; // EmitterCTX->JITObjectCache->FindRelocatedRIP(Reloc->GuestRIPMove.GuestRIP); if (Pointer == ~0ULL) { + SetBuffer(OrigBase, OrigSize); + SetCursorOffset(OrigOffset); return false; } // Relocation occurs at the cursorEntry + offset relative to that cursor. - SetCursorOffset(CursorEntry + Reloc->GuestRIPMove.Offset); - LoadConstant(ARMEmitter::Size::i64Bit, ARMEmitter::Register(Reloc->GuestRIPMove.RegisterIndex), Pointer, true); - DataIndex += sizeof(Reloc->GuestRIPMove); + SetCursorOffset(Reloc.GuestRIPMove.Offset); + LoadConstant(ARMEmitter::Size::i64Bit, ARMEmitter::Register(Reloc.GuestRIPMove.RegisterIndex), Pointer, true); break; } } } + SetBuffer(OrigBase, OrigSize); + SetCursorOffset(OrigOffset); + return true; } + +fextl::vector Arm64JITCore::TakeRelocations() { + return std::move(Relocations); +} + } // namespace FEXCore::CPU diff --git a/FEXCore/Source/Interface/Core/JIT/DebugData.h b/FEXCore/Source/Interface/Core/JIT/DebugData.h new file mode 100644 index 000000000..ffbd9f765 --- /dev/null +++ b/FEXCore/Source/Interface/Core/JIT/DebugData.h @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +#pragma once + +#include +#include + +#include + +namespace FEXCore::CPU { +union Relocation; +} // namespace FEXCore::CPU + +namespace FEXCore::Core { +struct DebugDataSubblock { + uint32_t HostCodeOffset; + uint32_t HostCodeSize; +}; + +struct DebugDataGuestOpcode { + uint64_t GuestEntryOffset; + ptrdiff_t HostEntryOffset; +}; + +/** + * @brief Contains debug data for a block of code for later debugger analysis + * + * Needs to remain around for as long as the code could be executed at least + */ +struct DebugData : public FEXCore::Allocator::FEXAllocOperators { + uint64_t HostCodeSize; ///< The size of the code generated in the host JIT + fextl::vector Subblocks; + fextl::vector GuestOpcodes; + fextl::vector* Relocations; +}; +} // namespace FEXCore::Core diff --git a/FEXCore/Source/Interface/Core/JIT/JITClass.h b/FEXCore/Source/Interface/Core/JIT/JITClass.h index 1753a9df9..28119a03e 100644 --- a/FEXCore/Source/Interface/Core/JIT/JITClass.h +++ b/FEXCore/Source/Interface/Core/JIT/JITClass.h @@ -381,7 +381,9 @@ private: fextl::vector Relocations; ///< Relocation code loading - bool ApplyRelocations(uint64_t GuestEntry, uint64_t CodeEntry, uint64_t CursorEntry, size_t NumRelocations, const char* EntryRelocations); + bool ApplyRelocations(uint64_t GuestEntry, std::span Code, std::span); + + fextl::vector TakeRelocations() override; /** @} */ diff --git a/FEXCore/Source/Interface/GDBJIT/GDBJIT.cpp b/FEXCore/Source/Interface/GDBJIT/GDBJIT.cpp index ede808ce1..b19deb686 100644 --- a/FEXCore/Source/Interface/GDBJIT/GDBJIT.cpp +++ b/FEXCore/Source/Interface/GDBJIT/GDBJIT.cpp @@ -42,19 +42,19 @@ void __attribute__((noinline)) __jit_debug_register_code() { namespace FEXCore { -void GDBJITRegister(FEXCore::IR::AOTIRCacheEntry* Entry, uintptr_t VAFileStart, uint64_t GuestRIP, uintptr_t HostEntry, - FEXCore::Core::DebugData* DebugData) { - auto map = Entry->SourcecodeMap.get(); +void GDBJITRegister(FEXCore::ExecutableFileInfo& Entry, uintptr_t VAFileStart, uint64_t GuestRIP, uintptr_t HostEntry, + FEXCore::Core::DebugData& DebugData) { + auto map = Entry.SourcecodeMap.get(); if (map) { auto FileOffset = GuestRIP - VAFileStart; auto Sym = map->FindSymbolMapping(FileOffset); - auto SymName = HLE::SourcecodeSymbolMapping::SymName(Sym, Entry->Filename, HostEntry, FileOffset); + auto SymName = HLE::SourcecodeSymbolMapping::SymName(Sym, Entry.Filename, HostEntry, FileOffset); fextl::vector Lines; - for (const auto& GuestOpcode : DebugData->GuestOpcodes) { + for (const auto& GuestOpcode : DebugData.GuestOpcodes) { auto Line = map->FindLineMapping(GuestRIP + GuestOpcode.GuestEntryOffset - VAFileStart); if (Line) { Lines.push_back({Line->LineNumber, HostEntry + GuestOpcode.HostEntryOffset}); @@ -80,7 +80,7 @@ void GDBJITRegister(FEXCore::IR::AOTIRCacheEntry* Entry, uintptr_t VAFileStart, for (int i = 0; i < info->nblocks; i++) { strncpy(blocks[i].name, SymName.c_str(), 511); blocks[i].start = HostEntry; - blocks[i].end = HostEntry + DebugData->HostCodeSize; + blocks[i].end = HostEntry + DebugData.HostCodeSize; } info->nlines = Lines.size(); @@ -113,7 +113,7 @@ void GDBJITRegister(FEXCore::IR::AOTIRCacheEntry* Entry, uintptr_t VAFileStart, } // namespace FEXCore #else namespace FEXCore { -void GDBJITRegister(FEXCore::IR::AOTIRCacheEntry*, uintptr_t, uint64_t, uintptr_t, FEXCore::Core::DebugData*) { +void GDBJITRegister(FEXCore::ExecutableFileInfo&, uintptr_t, uint64_t, uintptr_t, FEXCore::Core::DebugData&) { ERROR_AND_DIE_FMT("GDBSymbols support not compiled in"); } } // namespace FEXCore diff --git a/FEXCore/Source/Interface/GDBJIT/GDBJIT.h b/FEXCore/Source/Interface/GDBJIT/GDBJIT.h index 101224577..b169260b2 100644 --- a/FEXCore/Source/Interface/GDBJIT/GDBJIT.h +++ b/FEXCore/Source/Interface/GDBJIT/GDBJIT.h @@ -1,9 +1,8 @@ // SPDX-License-Identifier: MIT - -#include +#include +#include namespace FEXCore { -void GDBJITRegister(FEXCore::IR::AOTIRCacheEntry* Entry, uintptr_t VAFileStart, uint64_t GuestRIP, uintptr_t HostEntry, - FEXCore::Core::DebugData* DebugData); -} \ No newline at end of file +void GDBJITRegister(FEXCore::ExecutableFileInfo&, uintptr_t VAFileStart, uint64_t GuestRIP, uintptr_t HostEntry, FEXCore::Core::DebugData&); +} diff --git a/FEXCore/Source/Interface/IR/AOTIR.cpp b/FEXCore/Source/Interface/IR/AOTIR.cpp deleted file mode 100644 index 1426d186c..000000000 --- a/FEXCore/Source/Interface/IR/AOTIR.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: MIT -#include "FEXHeaderUtils/Filesystem.h" -#include "Interface/Context/Context.h" -#include "Interface/IR/AOTIR.h" - -#include -#include -#include - -#include -#include - -#include - -namespace FEXCore::IR { - -bool AOTIRCaptureCache::PostCompileCode(FEXCore::Core::InternalThreadState* Thread, void* CodePtr, uint64_t GuestRIP, uint64_t StartAddr, - uint64_t Length, FEXCore::Core::DebugData* DebugData) { - - // Both generated ir and LibraryJITName need a named region lookup - if (CTX->Config.LibraryJITNaming() || CTX->Config.GDBSymbols()) { - - auto AOTIRCacheEntry = CTX->SyscallHandler->LookupAOTIRCacheEntry(Thread, GuestRIP); - - if (AOTIRCacheEntry.Entry) { - if (DebugData && CTX->Config.LibraryJITNaming()) { - CTX->Symbols.RegisterNamedRegion(Thread->SymbolBuffer.get(), CodePtr, DebugData->HostCodeSize, AOTIRCacheEntry.Entry->Filename); - } - - if (CTX->Config.GDBSymbols()) { - GDBJITRegister(AOTIRCacheEntry.Entry, AOTIRCacheEntry.VAFileStart, GuestRIP, (uintptr_t)CodePtr, DebugData); - } - } - } - - return false; -} - -AOTIRCacheEntry* AOTIRCaptureCache::LoadAOTIRCacheEntry(const fextl::string& filename) { - fextl::string base_filename = FHU::Filesystem::GetFilename(filename); - - if (!base_filename.empty()) { - auto filename_hash = XXH3_64bits(filename.c_str(), filename.size()); - - auto fileid = fextl::fmt::format("{}-{}-{}{}{}", base_filename, filename_hash, - (CTX->Config.SMCChecks == FEXCore::Config::CONFIG_SMC_FULL) ? 'S' : 's', - CTX->Config.TSOEnabled ? 'T' : 't', CTX->Config.ABILocalFlags ? 'L' : 'l'); - - std::unique_lock lk(AOTIRCacheLock); - - auto Inserted = AOTIRCache.insert({fileid, AOTIRCacheEntry {.FileId = fileid, .Filename = filename}}); - auto Entry = &(Inserted.first->second); - - return Entry; - } - - return nullptr; -} - -} // namespace FEXCore::IR diff --git a/FEXCore/Source/Interface/IR/AOTIR.h b/FEXCore/Source/Interface/IR/AOTIR.h deleted file mode 100644 index 86f2aa51b..000000000 --- a/FEXCore/Source/Interface/IR/AOTIR.h +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: MIT -#pragma once - -#include -#include -#include -#include -#include - -#include -#include - -namespace FEXCore::CPU { -union Relocation; -} // namespace FEXCore::CPU - -namespace FEXCore::Core { -struct InternalThreadState; -struct DebugDataSubblock { - uint32_t HostCodeOffset; - uint32_t HostCodeSize; -}; - -struct DebugDataGuestOpcode { - uint64_t GuestEntryOffset; - ptrdiff_t HostEntryOffset; -}; - -/** - * @brief Contains debug data for a block of code for later debugger analysis - * - * Needs to remain around for as long as the code could be executed at least - */ -struct DebugData : public FEXCore::Allocator::FEXAllocOperators { - uint64_t HostCodeSize; ///< The size of the code generated in the host JIT - fextl::vector Subblocks; - fextl::vector GuestOpcodes; - fextl::vector* Relocations; -}; -} // namespace FEXCore::Core - -namespace FEXCore::Context { -class ContextImpl; -} - -namespace FEXCore::IR { - -struct AOTIRCacheEntry { - fextl::unique_ptr SourcecodeMap; - fextl::string FileId; - fextl::string Filename; -}; - -class AOTIRCaptureCache final { -public: - AOTIRCaptureCache(FEXCore::Context::ContextImpl* ctx) - : CTX {ctx} {} - - bool PostCompileCode(FEXCore::Core::InternalThreadState* Thread, void* CodePtr, uint64_t GuestRIP, uint64_t StartAddr, uint64_t Length, - FEXCore::Core::DebugData* DebugData); - - AOTIRCacheEntry* LoadAOTIRCacheEntry(const fextl::string& filename); - -private: - FEXCore::Context::ContextImpl* CTX; - - std::shared_mutex AOTIRCacheLock; - - fextl::unordered_map AOTIRCache; -}; - -} // namespace FEXCore::IR diff --git a/FEXCore/docs/IR.md b/FEXCore/docs/IR.md index 11d60c77e..986fd6949 100644 --- a/FEXCore/docs/IR.md +++ b/FEXCore/docs/IR.md @@ -78,14 +78,9 @@ When generating IR inside of the `OpDispatchBuilder` it is straight forward, jus This is an intrusive allocator that is used by the `OpDispatchBuilder` for storing IR data. It is a simple linear arena allocator without resizing capabilities. ### OpDispatchBuilder -OpDispatchBuilder provides two routines for handling the IR outside of the class -* `IRListView ViewIR();` - * Returns a wrapper container class the allows you to view the IR. This doesn't take ownership of the IR data. - * If the OpDispatcherBuilder changes its IR then changes are also visible to this class -* `IRListView *CreateIRCopy()` - * As the name says, it creates a new copy of the IR that is in the OpDispatchBuilder - * Copying the IR only copies the memory used and doesn't have any free space for optimizations after this copy operation - * Useful for tiered recompilers, AOT, and offline analysis +OpDispatchBuilder provides `IRListView ViewIR()` for handling the IR outside of the class: +* Returns a wrapper container class the allows you to view the IR. This doesn't take ownership of the IR data. +* If the OpDispatcherBuilder changes its IR then changes are also visible to this class This class uses two IntrusiveAllocator objects for tracking IR data. `ListData` and `Data` are the object names. * `ListData` is for tracking the doubly linked list of nodes diff --git a/FEXCore/include/FEXCore/Core/CodeCache.h b/FEXCore/include/FEXCore/Core/CodeCache.h new file mode 100644 index 000000000..3a16fbeaa --- /dev/null +++ b/FEXCore/include/FEXCore/Core/CodeCache.h @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MIT +#pragma once + +#include +#include + +#include + +namespace FEXCore { + +namespace Core { + struct InternalThreadState; +} // namespace Core + +namespace HLE { + struct SourcecodeMap; +} // namespace HLE + +// Generic information associated with an executable file. +struct ExecutableFileInfo { + ~ExecutableFileInfo(); + + fextl::unique_ptr SourcecodeMap; + fextl::string FileId; + fextl::string Filename; +}; + +// Information associated with a specific section of an executable file +struct ExecutableFileSectionInfo { + ExecutableFileInfo& FileInfo; + + // Start address that the file is mapped to. + uintptr_t FileStartVA; +}; + +class AbstractCodeCache { +public: + virtual ~AbstractCodeCache() = default; + + /** + * Loads a code cache from mapped memory and appends it to the current Core state. + * TODO: Optionally recompiles all contained code blocks at runtime for validation. + */ + virtual void LoadData(Core::InternalThreadState&, std::byte* MappedCacheFile, const ExecutableFileSectionInfo&) = 0; + + /** + * Bundles the current Core state (CodeBuffer, GuestToHostMapping, ...) to a code cache and writes it to the given file descriptor. + * Returns true on success. + */ + virtual bool SaveData(Core::InternalThreadState&, int TargetFD, const ExecutableFileSectionInfo&, uint64_t SerializedBaseAddress) = 0; + + /** + * Function to be called before compiling any code for caching purposes + */ + virtual void InitiateCacheGeneration() = 0; +}; + +} // namespace FEXCore diff --git a/FEXCore/include/FEXCore/Core/Context.h b/FEXCore/include/FEXCore/Core/Context.h index 007b14e1b..3f12d6017 100644 --- a/FEXCore/include/FEXCore/Core/Context.h +++ b/FEXCore/include/FEXCore/Core/Context.h @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -13,12 +14,7 @@ #include #include -#include -#include -#include - namespace FEXCore { -class CodeLoader; struct HostFeatures; class ForkableSharedMutex; class ThunkHandler; @@ -29,17 +25,11 @@ struct CPUState; struct InternalThreadState; } // namespace FEXCore::Core -namespace FEXCore::CPU { -class CPUBackend; -} - namespace FEXCore::HLE { -struct SyscallArguments; class SyscallHandler; } // namespace FEXCore::HLE namespace FEXCore::IR { -struct AOTIRCacheEntry; class IREmitter; } // namespace FEXCore::IR @@ -148,10 +138,7 @@ public: FEX_DEFAULT_VISIBILITY virtual FEXCore::CPUID::XCRResults RunXCRFunction(uint32_t Function) = 0; FEX_DEFAULT_VISIBILITY virtual FEXCore::CPUID::FunctionResults RunCPUIDFunctionName(uint32_t Function, uint32_t Leaf, uint32_t CPU) = 0; - FEX_DEFAULT_VISIBILITY virtual FEXCore::IR::AOTIRCacheEntry* LoadAOTIRCacheEntry(const fextl::string& Name) = 0; - FEX_DEFAULT_VISIBILITY virtual void UnloadAOTIRCacheEntry(FEXCore::IR::AOTIRCacheEntry* Entry) = 0; - - FEX_DEFAULT_VISIBILITY virtual void FinalizeAOTIRCache() = 0; + virtual AbstractCodeCache& GetCodeCache() = 0; FEX_DEFAULT_VISIBILITY virtual void ClearCodeCache(FEXCore::Core::InternalThreadState* Thread, bool NewCodeBuffer = true) = 0; FEX_DEFAULT_VISIBILITY virtual void InvalidateGuestCodeRange( diff --git a/FEXCore/include/FEXCore/HLE/SourcecodeResolver.h b/FEXCore/include/FEXCore/HLE/SourcecodeResolver.h index 86cc31410..a110924a1 100644 --- a/FEXCore/include/FEXCore/HLE/SourcecodeResolver.h +++ b/FEXCore/include/FEXCore/HLE/SourcecodeResolver.h @@ -9,10 +9,6 @@ #include #include -namespace FEXCore::IR { -struct AOTIRCacheEntry; -} - namespace FEXCore::HLE { struct SourcecodeLineMapping { diff --git a/FEXCore/include/FEXCore/HLE/SyscallHandler.h b/FEXCore/include/FEXCore/HLE/SyscallHandler.h index 9052e02e4..5677b5989 100644 --- a/FEXCore/include/FEXCore/HLE/SyscallHandler.h +++ b/FEXCore/include/FEXCore/HLE/SyscallHandler.h @@ -1,13 +1,11 @@ // SPDX-License-Identifier: MIT #pragma once #include -#include +#include +#include #include - -namespace FEXCore::IR { -struct AOTIRCacheEntry; -} +#include namespace FEXCore::Context { class Context; @@ -51,19 +49,6 @@ struct ExecutableRangeInfo { class SyscallHandler; class SourcecodeResolver; -struct AOTIRCacheEntryLookupResult { - AOTIRCacheEntryLookupResult(FEXCore::IR::AOTIRCacheEntry* Entry, uintptr_t VAFileStart) - : Entry(Entry) - , VAFileStart(VAFileStart) {} - - AOTIRCacheEntryLookupResult(AOTIRCacheEntryLookupResult&&) = default; - - FEXCore::IR::AOTIRCacheEntry* Entry; - uintptr_t VAFileStart; - - friend class SyscallHandler; -}; - class SyscallHandler { public: virtual ~SyscallHandler() = default; @@ -82,7 +67,7 @@ public: virtual void MarkOvercommitRange(uint64_t Start, uint64_t Length) {} virtual void UnmarkOvercommitRange(uint64_t Start, uint64_t Length) {} virtual ExecutableRangeInfo QueryGuestExecutableRange(FEXCore::Core::InternalThreadState* Thread, uint64_t Address) = 0; - virtual AOTIRCacheEntryLookupResult LookupAOTIRCacheEntry(FEXCore::Core::InternalThreadState* Thread, uint64_t GuestAddr) = 0; + virtual std::optional LookupExecutableFileSection(Core::InternalThreadState& Thread, uint64_t GuestAddr) = 0; virtual void PreCompile() {} diff --git a/FEXHeaderUtils/FEXHeaderUtils/Filesystem.h b/FEXHeaderUtils/FEXHeaderUtils/Filesystem.h index f92215726..44c784d24 100644 --- a/FEXHeaderUtils/FEXHeaderUtils/Filesystem.h +++ b/FEXHeaderUtils/FEXHeaderUtils/Filesystem.h @@ -8,7 +8,7 @@ #include #include #include -#include +#include #ifndef _WIN32 #include #include @@ -354,6 +354,11 @@ inline fextl::string GetFilename(const fextl::string& Path) { return PathToString(std::filesystem::path(Path).filename()); } +inline std::string_view GetFilename(std::string_view Path) { + auto Filename = PathToString(std::filesystem::path(Path).filename()); + return Path.substr(Path.size() - Filename.size()); +} + inline fextl::string ParentPath(const fextl::string& Path) { return PathToString(std::filesystem::path(Path).parent_path()); } diff --git a/Source/Tools/CodeSizeValidation/Main.cpp b/Source/Tools/CodeSizeValidation/Main.cpp index 746de65ef..173a8de71 100644 --- a/Source/Tools/CodeSizeValidation/Main.cpp +++ b/Source/Tools/CodeSizeValidation/Main.cpp @@ -460,8 +460,9 @@ public: } // These are no-ops implementations of the SyscallHandler API - FEXCore::HLE::AOTIRCacheEntryLookupResult LookupAOTIRCacheEntry(FEXCore::Core::InternalThreadState* Thread, uint64_t GuestAddr) override { - return {0, 0}; + std::optional + LookupExecutableFileSection(FEXCore::Core::InternalThreadState& Thread, uint64_t GuestAddr) override { + return std::nullopt; } FEXCore::HLE::ExecutableRangeInfo QueryGuestExecutableRange(FEXCore::Core::InternalThreadState* Thread, uint64_t Address) override { diff --git a/Source/Tools/CommonTools/DummyHandlers.h b/Source/Tools/CommonTools/DummyHandlers.h index 6bd8ace62..fea414779 100644 --- a/Source/Tools/CommonTools/DummyHandlers.h +++ b/Source/Tools/CommonTools/DummyHandlers.h @@ -22,8 +22,8 @@ public: } // These are no-ops implementations of the SyscallHandler API - FEXCore::HLE::AOTIRCacheEntryLookupResult LookupAOTIRCacheEntry(FEXCore::Core::InternalThreadState* Thread, uint64_t GuestAddr) override { - return {0, 0}; + std::optional LookupExecutableFileSection(FEXCore::Core::InternalThreadState&, uint64_t) override { + return std::nullopt; } FEXCore::HLE::ExecutableRangeInfo QueryGuestExecutableRange(FEXCore::Core::InternalThreadState* Thread, uint64_t Address) override { diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.h b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.h index 7f56cb37c..2578ce2f1 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.h +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.h @@ -290,8 +290,8 @@ public: static bool HandleSegfault(FEXCore::Core::InternalThreadState* Thread, int Signal, void* info, void* ucontext); void MarkGuestExecutableRange(FEXCore::Core::InternalThreadState* Thread, uint64_t Start, uint64_t Length) override; void InvalidateGuestCodeRange(FEXCore::Core::InternalThreadState* Thread, uint64_t Start, uint64_t Length) override; - // AOTIRCacheEntryLookupResult also includes a shared lock guard, so the pointed AOTIRCacheEntry return can be safely used - FEXCore::HLE::AOTIRCacheEntryLookupResult LookupAOTIRCacheEntry(FEXCore::Core::InternalThreadState* Thread, uint64_t GuestAddr) final override; + std::optional + LookupExecutableFileSection(FEXCore::Core::InternalThreadState& Thread, uint64_t GuestAddr) final override; FEXCore::HLE::ExecutableRangeInfo QueryGuestExecutableRange(FEXCore::Core::InternalThreadState* Thread, uint64_t Address) override; diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/SyscallsSMCTracking.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/SyscallsSMCTracking.cpp index a3bec6e71..1bebc4df8 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/SyscallsSMCTracking.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/SyscallsSMCTracking.cpp @@ -167,19 +167,19 @@ void SyscallHandler::InvalidateGuestCodeRange(FEXCore::Core::InternalThreadState FEX::HLE::_SyscallHandler->InvalidateCodeRangeIfNecessary(Thread, Start, Length); } -// Used for AOT -FEXCore::HLE::AOTIRCacheEntryLookupResult SyscallHandler::LookupAOTIRCacheEntry(FEXCore::Core::InternalThreadState* Thread, uint64_t GuestAddr) { - auto lk = FEXCore::GuardSignalDeferringSection(VMATracking.Mutex, Thread); +std::optional +SyscallHandler::LookupExecutableFileSection(FEXCore::Core::InternalThreadState& Thread, uint64_t GuestAddr) { + auto lk = FEXCore::GuardSignalDeferringSection(VMATracking.Mutex, &Thread); // Get the first mapping after GuestAddr, or end // GuestAddr is inclusive // If the write spans two pages, they will be flushed one at a time (generating two faults) auto Entry = VMATracking.FindVMAEntry(GuestAddr); - if (Entry == VMATracking.VMAs.end()) { - return {nullptr, 0}; + if (Entry == VMATracking.VMAs.end() || !Entry->second.Resource) { + return std::nullopt; } - return {Entry->second.Resource ? Entry->second.Resource->AOTIRCacheEntry : nullptr, Entry->second.Base - Entry->second.Offset}; + return FEXCore::ExecutableFileSectionInfo {*Entry->second.Resource->MappedFile, Entry->second.Base - Entry->second.Offset}; } FEXCore::HLE::ExecutableRangeInfo SyscallHandler::QueryGuestExecutableRange(FEXCore::Core::InternalThreadState* Thread, uint64_t Address) { @@ -374,19 +374,19 @@ void SyscallHandler::TrackMmap(FEXCore::Core::InternalThreadState* Thread, uint6 auto PathLength = FEX::get_fdpath(fd, Tmp); if (PathLength != -1) { - Tmp[PathLength] = '\0'; - auto [Iter, Inserted] = VMATracking.EmplaceMappedResource(mrid, VMATracking::MappedResource {nullptr, nullptr, 0}); + auto [Iter, Inserted] = VMATracking.InsertMappedResource(mrid, {nullptr, nullptr, 0}); Resource = &Iter->second; if (Inserted) { - Resource->AOTIRCacheEntry = CTX->LoadAOTIRCacheEntry(fextl::string(Tmp, PathLength)); + Resource->MappedFile = fextl::make_unique(); + Resource->MappedFile->Filename = fextl::string(Tmp, PathLength); Resource->Iterator = Iter; } } } else if (flags & MAP_SHARED) { VMATracking::MRID mrid {VMATracking::SpecialDev::Anon, AnonSharedId++}; - auto [Iter, Inserted] = VMATracking.EmplaceMappedResource(mrid, VMATracking::MappedResource {nullptr, nullptr, 0}); + auto [Iter, Inserted] = VMATracking.InsertMappedResource(mrid, {nullptr, nullptr, 0}); LOGMAN_THROW_A_FMT(Inserted == true, "VMA tracking error"); Resource = &Iter->second; Resource->Iterator = Iter; @@ -446,7 +446,7 @@ void SyscallHandler::TrackMremap(FEXCore::Core::InternalThreadState* Thread, uin void SyscallHandler::TrackShmat(FEXCore::Core::InternalThreadState* Thread, int shmid, uint64_t shmaddr, int shmflg, uint64_t Length) { VMATracking::MRID mrid {VMATracking::SpecialDev::SHM, static_cast(shmid)}; - auto [Iter, Inserted] = VMATracking.EmplaceMappedResource(mrid, VMATracking::MappedResource {nullptr, nullptr, Length}); + auto [Iter, Inserted] = VMATracking.InsertMappedResource(mrid, {nullptr, nullptr, Length}); auto Resource = &Iter->second; if (Inserted) { Resource->Iterator = Iter; diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/SyscallsVMATracking.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/SyscallsVMATracking.cpp index 74c383300..f12736fa3 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/SyscallsVMATracking.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/SyscallsVMATracking.cpp @@ -235,9 +235,6 @@ void VMATracking::DeleteVMARange(FEXCore::Context::Context* CTX, uintptr_t Base, // If linked to a Mapped Resource, remove from linked list and possibly delete the Mapped Resource if (Current->Resource) { if (ListRemove(Current) && Current->Resource != PreservedMappedResource) { - if (Current->Resource->AOTIRCacheEntry) { - CTX->UnloadAOTIRCacheEntry(Current->Resource->AOTIRCacheEntry); - } MappedResources.erase(Current->Resource->Iterator); } } @@ -540,9 +537,6 @@ uintptr_t VMATracking::DeleteSHMRegion(FEXCore::Context::Context* CTX, uintptr_t do { if (Entry->second.Resource == Resource) { if (ListRemove(&Entry->second)) { - if (Entry->second.Resource->AOTIRCacheEntry) { - CTX->UnloadAOTIRCacheEntry(Entry->second.Resource->AOTIRCacheEntry); - } MappedResources.erase(Entry->second.Resource->Iterator); } Entry = VMAs.erase(Entry); diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/SyscallsVMATracking.h b/Source/Tools/LinuxEmulation/LinuxSyscalls/SyscallsVMATracking.h index 5c0f0e693..1aa9ba2da 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/SyscallsVMATracking.h +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/SyscallsVMATracking.h @@ -5,12 +5,9 @@ #include #include +#include #include -namespace FEXCore::IR { -struct AOTIRCacheEntry; -} - namespace FEX::HLE::VMATracking { ///// VMA (Virtual Memory Area) tracking ///// @@ -37,7 +34,7 @@ struct VMAEntry; struct MappedResource { using ContainerType = fextl::map; - FEXCore::IR::AOTIRCacheEntry* AOTIRCacheEntry; + fextl::unique_ptr MappedFile; // Pointer to lowest memory range this file is mapped to VMAEntry* FirstVMA; uint64_t Length; // 0 if not fixed size @@ -87,7 +84,7 @@ struct VMATracking { using VMACIterator = decltype(VMAs)::const_iterator; // Find a VMA entry associated with the memory address. - // Used by `mremap`, and SIGSEGV handler to find previously mapped ranges, and `AOTIR` cache to find cache entries. + // Used by `mremap` and SIGSEGV handler to find previously mapped ranges, and CodeCache to find cache entries. // - Mutex must be at least shared_locked before calling VMACIterator FindVMAEntry(uint64_t GuestAddr) const; @@ -114,11 +111,9 @@ struct VMATracking { // Returns the Size of the Shm or 0 if not found uintptr_t DeleteSHMRegion(FEXCore::Context::Context* Ctx, uintptr_t Base); - // Emplaces a new `MappedResource` to track. - // Used for `mmap` and `shmat` resources; Anonymous, FD, and SHM depending on flags. - template - inline auto EmplaceMappedResource(Args&&... args) { - return MappedResources.emplace(args...); + // Adds a new `MappedResource` to track. + inline auto InsertMappedResource(const MRID& mrid, MappedResource Resource) { + return MappedResources.emplace(mrid, std::move(Resource)); } private: bool ListRemove(VMAEntry* Mapping); diff --git a/Source/Tools/LinuxEmulation/VDSO_Emulation.h b/Source/Tools/LinuxEmulation/VDSO_Emulation.h index e8f3f0347..3bcd810ec 100644 --- a/Source/Tools/LinuxEmulation/VDSO_Emulation.h +++ b/Source/Tools/LinuxEmulation/VDSO_Emulation.h @@ -11,6 +11,8 @@ namespace FEX::HLE { class SyscallHandler; } +#include + namespace FEX::VDSO { struct VDSOMapping { void* VDSOBase {}; diff --git a/Source/Windows/ARM64EC/Module.cpp b/Source/Windows/ARM64EC/Module.cpp index 73930de69..cd0ef311e 100644 --- a/Source/Windows/ARM64EC/Module.cpp +++ b/Source/Windows/ARM64EC/Module.cpp @@ -586,8 +586,8 @@ public: return {.NumArgs = 0, .HasReturn = false, .HostSyscallNumber = -1}; } - FEXCore::HLE::AOTIRCacheEntryLookupResult LookupAOTIRCacheEntry(FEXCore::Core::InternalThreadState* Thread, uint64_t GuestAddr) override { - return {0, 0}; + std::optional LookupExecutableFileSection(FEXCore::Core::InternalThreadState&, uint64_t) override { + return std::nullopt; } void MarkGuestExecutableRange(FEXCore::Core::InternalThreadState* Thread, uint64_t Start, uint64_t Length) override { diff --git a/Source/Windows/WOW64/Module.cpp b/Source/Windows/WOW64/Module.cpp index 278330eec..bdb2c55b8 100644 --- a/Source/Windows/WOW64/Module.cpp +++ b/Source/Windows/WOW64/Module.cpp @@ -478,8 +478,8 @@ public: return {.NumArgs = 0, .HasReturn = false, .HostSyscallNumber = -1}; } - FEXCore::HLE::AOTIRCacheEntryLookupResult LookupAOTIRCacheEntry(FEXCore::Core::InternalThreadState* Thread, uint64_t GuestAddr) override { - return {0, 0}; + std::optional LookupExecutableFileSection(FEXCore::Core::InternalThreadState&, uint64_t) override { + return std::nullopt; } void MarkGuestExecutableRange(FEXCore::Core::InternalThreadState* Thread, uint64_t Start, uint64_t Length) override {