N64Recomp/CMakeLists.txt
Wiseguy 66062a06e9
Implement live recompiler (#114)
This commit implements the "live recompiler", which is another backend for the recompiler that generates platform-specific assembly at runtime. This is still static recompilation as opposed to dynamic recompilation, as it still requires information about the binary to recompile and leverages the same static analysis that the C recompiler uses. However, similarly to dynamic recompilation it's aimed at recompiling binaries at runtime, mainly for modding purposes.

The live recompiler leverages a library called sljit to generate platform-specific code. This library provides an API that's implemented on several platforms, including the main targets of this component: x86_64 and ARM64.

Performance is expected to be slower than the C recompiler, but should still be plenty fast enough for running large amounts of recompiled code without an issue. Considering these ROMs can often be run through an interpreter and still hit their full speed, performance should not be a concern for running native code even if it's less optimal than the C recompiler's codegen.

As mentioned earlier, the main use of the live recompiler will be for loading mods in the N64Recomp runtime. This makes it so that modders don't need to ship platform-specific binaries for their mods, and allows fixing bugs with recompilation down the line without requiring modders to update their binaries.

This PR also includes a utility for testing the live recompiler. It accepts binaries in a custom format which contain the instructions, input data, and target data. Documentation for the test format as well as most of the tests that were used to validate the live recompiler can be found here. The few remaining tests were hacked together binaries that I put together very hastily, so they need to be cleaned up and will probably be uploaded at a later date. The only test in that suite that doesn't currently succeed is the div test, due to unknown behavior when the two operands aren't properly sign extended to 64 bits. This has no bearing on practical usage, since the inputs will always be sign extended as expected.
2024-12-31 16:11:40 -05:00

195 lines
8 KiB
CMake

cmake_minimum_required(VERSION 3.20)
set(CMAKE_C_STANDARD 17)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# set(CMAKE_CXX_VISIBILITY_PRESET hidden)
# Rabbitizer
project(rabbitizer)
add_library(rabbitizer STATIC)
target_sources(rabbitizer PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/cplusplus/src/analysis/LoPairingInfo.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/cplusplus/src/analysis/RegistersTracker.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/cplusplus/src/instructions/InstrId.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/cplusplus/src/instructions/InstrIdType.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/cplusplus/src/instructions/InstructionBase.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/cplusplus/src/instructions/InstructionCpu.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/cplusplus/src/instructions/InstructionR3000GTE.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/cplusplus/src/instructions/InstructionR5900.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/cplusplus/src/instructions/InstructionRsp.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/analysis/RabbitizerLoPairingInfo.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/analysis/RabbitizerRegistersTracker.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/analysis/RabbitizerTrackedRegisterState.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/common/RabbitizerConfig.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/common/RabbitizerVersion.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/common/Utils.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/instructions/RabbitizerInstrCategory.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/instructions/RabbitizerInstrDescriptor.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/instructions/RabbitizerInstrId.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/instructions/RabbitizerInstrIdType.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/instructions/RabbitizerInstrSuffix.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/instructions/RabbitizerInstructionCpu/RabbitizerInstructionCpu_OperandType.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/instructions/RabbitizerInstructionR3000GTE/RabbitizerInstructionR3000GTE.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/instructions/RabbitizerInstructionR3000GTE/RabbitizerInstructionR3000GTE_OperandType.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/instructions/RabbitizerInstructionR3000GTE/RabbitizerInstructionR3000GTE_ProcessUniqueId.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/instructions/RabbitizerInstructionR5900/RabbitizerInstructionR5900.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/instructions/RabbitizerInstructionR5900/RabbitizerInstructionR5900_OperandType.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/instructions/RabbitizerInstructionR5900/RabbitizerInstructionR5900_ProcessUniqueId.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/instructions/RabbitizerInstructionRsp/RabbitizerInstructionRsp.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/instructions/RabbitizerInstructionRsp/RabbitizerInstructionRsp_OperandType.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/instructions/RabbitizerInstructionRsp/RabbitizerInstructionRsp_ProcessUniqueId.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/instructions/RabbitizerInstruction/RabbitizerInstruction.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/instructions/RabbitizerInstruction/RabbitizerInstruction_Disassemble.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/instructions/RabbitizerInstruction/RabbitizerInstruction_Examination.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/instructions/RabbitizerInstruction/RabbitizerInstruction_Operand.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/instructions/RabbitizerInstruction/RabbitizerInstruction_ProcessUniqueId.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/instructions/RabbitizerRegister.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/src/instructions/RabbitizerRegisterDescriptor.c")
target_include_directories(rabbitizer PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/include"
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/cplusplus/include")
target_include_directories(rabbitizer PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/lib/rabbitizer/tables")
# fmtlib
add_subdirectory(lib/fmt)
# tomlplusplus
set(TOML_ENABLE_FORMATTERS OFF)
add_subdirectory(lib/tomlplusplus)
# Hardcoded symbol lists (separate library to not force a dependency on N64Recomp)
project(SymbolLists)
add_library(SymbolLists)
target_sources(SymbolLists PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/symbol_lists.cpp
)
target_include_directories(SymbolLists PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/include"
)
# N64 recompiler core library
project(N64Recomp)
add_library(N64Recomp)
target_sources(N64Recomp PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/analysis.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/operations.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/cgenerator.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/recompilation.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/mod_symbols.cpp
)
target_include_directories(N64Recomp PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/include"
)
target_link_libraries(N64Recomp SymbolLists fmt rabbitizer tomlplusplus::tomlplusplus)
# N64 recompiler elf parsing
project(N64RecompElf)
add_library(N64RecompElf)
target_sources(N64RecompElf PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/elf.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/symbol_lists.cpp
)
target_include_directories(N64RecompElf PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/include"
)
target_include_directories(N64RecompElf PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/lib/ELFIO"
)
target_link_libraries(N64RecompElf fmt)
# N64 recompiler executable
project(N64RecompCLI)
add_executable(N64RecompCLI)
target_sources(N64RecompCLI PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/config.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp
)
target_include_directories(N64RecompCLI PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/include"
)
target_link_libraries(N64RecompCLI fmt rabbitizer tomlplusplus::tomlplusplus N64Recomp N64RecompElf)
set_target_properties(N64RecompCLI PROPERTIES OUTPUT_NAME N64Recomp)
# RSP recompiler
project(RSPRecomp)
add_executable(RSPRecomp)
target_include_directories(RSPRecomp PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_link_libraries(RSPRecomp fmt rabbitizer tomlplusplus::tomlplusplus)
target_sources(RSPRecomp PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/RSPRecomp/src/rsp_recomp.cpp)
# Mod tool
project(RecompModTool)
add_executable(RecompModTool)
target_sources(RecompModTool PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/config.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/mod_symbols.cpp
${CMAKE_CURRENT_SOURCE_DIR}/RecompModTool/main.cpp
)
target_include_directories(RecompModTool PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/lib/ELFIO
)
target_link_libraries(RecompModTool fmt tomlplusplus::tomlplusplus N64RecompElf)
# Offline mod recompiler
project(OfflineModRecomp)
add_executable(OfflineModRecomp)
target_sources(OfflineModRecomp PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/config.cpp
${CMAKE_CURRENT_SOURCE_DIR}/OfflineModRecomp/main.cpp
)
target_link_libraries(OfflineModRecomp fmt rabbitizer tomlplusplus::tomlplusplus N64Recomp)
# Live recompiler
project(LiveRecomp)
add_library(LiveRecomp)
target_sources(LiveRecomp PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/LiveRecomp/live_generator.cpp
${CMAKE_CURRENT_SOURCE_DIR}/lib/sljit/sljit_src/sljitLir.c
)
target_include_directories(LiveRecomp PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/lib/sljit/sljit_src
)
target_link_libraries(LiveRecomp N64Recomp)
# Live recompiler test
project(LiveRecompTest)
add_executable(LiveRecompTest)
target_sources(LiveRecompTest PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/LiveRecomp/live_recompiler_test.cpp
)
target_include_directories(LiveRecompTest PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/lib/sljit/sljit_src
)
target_link_libraries(LiveRecompTest LiveRecomp)