diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ce53def14..b32c7e437f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -425,7 +425,6 @@ endif() option(LLGL_ENABLE_CHECKED_CAST "Enable dynamic checked cast (only in Debug mode)" ON) option(LLGL_ENABLE_DEBUG_LAYER "Enable renderer debug layer (for both Debug and Release mode)" ON) -option(LLGL_ENABLE_JIT_COMPILER "Enable Just-in-Time (JIT) compilation for emulated deferred command buffers (experimental)" OFF) option(LLGL_ENABLE_EXCEPTIONS "Enable C++ exceptions" OFF) option(LLGL_PREFER_STL_CONTAINERS "Prefers C++ STL containers over custom containers, e.g. std::vector over SmallVector" OFF) @@ -476,10 +475,6 @@ if(LLGL_ENABLE_DEBUG_LAYER) ADD_DEFINE(LLGL_ENABLE_DEBUG_LAYER) endif() -if(LLGL_ENABLE_JIT_COMPILER) - ADD_DEFINE(LLGL_ENABLE_JIT_COMPILER) -endif() - if(LLGL_ENABLE_EXCEPTIONS) ADD_DEFINE(LLGL_ENABLE_EXCEPTIONS) endif() @@ -550,22 +545,6 @@ find_source_files(FilesCore CXX "${PROJECT_SOURCE_DI find_source_files(FilesPlatformBase CXX "${PROJECT_SOURCE_DIR}/sources/Platform") find_source_files(FilesRenderer CXX "${PROJECT_SOURCE_DIR}/sources/Renderer") -if(LLGL_ENABLE_JIT_COMPILER) - find_source_files(FilesJIT CXX "${PROJECT_SOURCE_DIR}/sources/JIT") - if(ARCH_IA32) - find_source_files(FilesJITArch CXX "${PROJECT_SOURCE_DIR}/sources/JIT/Arch/IA32") - elseif(ARCH_AMD64) - find_source_files(FilesJITArch CXX "${PROJECT_SOURCE_DIR}/sources/JIT/Arch/AMD64") - elseif(ARCH_ARM64) - find_source_files(FilesJITArch CXX "${PROJECT_SOURCE_DIR}/sources/JIT/Arch/ARM64") - endif() - if(WIN32) - find_source_files(FilesJITPlatform CXX "${PROJECT_SOURCE_DIR}/sources/JIT/Platform/Win32") - else() - find_source_files(FilesJITPlatform CXX "${PROJECT_SOURCE_DIR}/sources/JIT/Platform/POSIX") - endif() -endif() - if(LLGL_ENABLE_DEBUG_LAYER) find_source_files(FilesRendererDbg CXX "${PROJECT_SOURCE_DIR}/sources/Renderer/DebugLayer") find_source_files(FilesRendererDbgBuffer CXX "${PROJECT_SOURCE_DIR}/sources/Renderer/DebugLayer/Buffer") @@ -630,12 +609,6 @@ source_group("Sources\\Core" FILES ${FilesCore}) source_group("Sources\\Platform" FILES ${FilesPlatformBase} ${FilesPlatform}) source_group("Sources\\Renderer" FILES ${FilesRenderer}) -if(LLGL_ENABLE_JIT_COMPILER) - source_group("Sources\\JIT" FILES ${FilesJIT}) - source_group("Sources\\JIT\\Arch" FILES ${FilesJITArch}) - source_group("Sources\\JIT\\Platform" FILES ${FilesJITPlatform}) -endif() - if(LLGL_ENABLE_DEBUG_LAYER) source_group("Sources\\Renderer\\DebugLayer" FILES ${FilesRendererDbg}) source_group("Sources\\Renderer\\DebugLayer\\Buffer" FILES ${FilesRendererDbgBuffer}) @@ -680,15 +653,6 @@ if(MSVC) list(APPEND FilesLLGL ${FilesMsvcNatvis}) endif() -if(LLGL_ENABLE_JIT_COMPILER) - list( - APPEND FilesLLGL - ${FilesJIT} - ${FilesJITArch} - ${FilesJITPlatform} - ) -endif() - if(LLGL_ENABLE_DEBUG_LAYER) list( APPEND FilesLLGL diff --git a/sources/JIT/Arch/AMD64/AMD64Assembler.cpp b/sources/JIT/Arch/AMD64/AMD64Assembler.cpp deleted file mode 100644 index 132c50ab9e..0000000000 --- a/sources/JIT/Arch/AMD64/AMD64Assembler.cpp +++ /dev/null @@ -1,764 +0,0 @@ -/* - * AMD64Assembler.cpp - * - * Copyright (c) 2015 Lukas Hermanns. All rights reserved. - * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). - */ - -#include "AMD64Assembler.h" -#include "AMD64Opcode.h" -#include "../../../Core/Assertion.h" -#include - - -namespace LLGL -{ - -namespace JIT -{ - - -/* - * Internal members - */ - -/* -List of registers that are used for the first couple of arguments. -Note the difference between Microsoft and Unix x64 calling conventions. -see https://en.wikipedia.org/wiki/X86_calling_conventions#List_of_x86_calling_conventions -*/ -#ifdef _WIN32 - -/* -Microsoft x64 calling convention (Windows) -Preserved for caller: ??? -*/ -static const Reg g_amd64IntParams[] = { Reg::RCX, Reg::RDX, Reg::R8, Reg::R9 }; -static const Reg g_amd64FltParams[] = { Reg::XMM0, Reg::XMM1, Reg::XMM2, Reg::XMM3 }; -static const Reg g_amd64TempReg = Reg::RAX; - -#else - -/* -System V AMD64 ABI (Solaris, Linux, BSD, macOS) -Preserved for caller: RBP, RBX, R12-R15 -*/ -static const Reg g_amd64IntParams[] = { Reg::RDI, Reg::RSI, Reg::RDX, Reg::RCX, Reg::R8, Reg::R9 }; -static const Reg g_amd64FltParams[] = { Reg::XMM0, Reg::XMM1, Reg::XMM2, Reg::XMM3, Reg::XMM4, Reg::XMM5, Reg::XMM6, Reg::XMM7 }; -static const Reg g_amd64TempReg = Reg::RAX; - -#endif - -static constexpr std::size_t g_amd64IntParamsCount = sizeof(g_amd64IntParams)/sizeof(g_amd64IntParams[0]); -static constexpr std::size_t g_amd64FltParamsCount = sizeof(g_amd64FltParams)/sizeof(g_amd64FltParams[0]); - - -/* - * Internal functions - */ - -// Size of byte (1), word (2), dword (4), qword (8), ptr (8), stack-ptr (8), float (4), double (8) -static std::uint8_t GetArgSize(const ArgType t) -{ - switch (t) - { - case ArgType::Byte: return 1; - case ArgType::Word: return 2; - case ArgType::DWord: return 4; - case ArgType::QWord: return 8; - case ArgType::Ptr: return 8; - case ArgType::StackPtr: return 8; - case ArgType::Float: return 4; - case ArgType::Double: return 8; - } - LLGL_UNREACHABLE(); - return 0; -} - - -/* - * AMD64Assembler class - */ - -void AMD64Assembler::Begin() -{ - #if 0//TEST - _ForceExcep(); - XOrReg(Reg::EAX, Reg::EAX); - XOrReg(Reg::EAX, Reg::EBX); - XOrReg(Reg::RAX, Reg::RBX); - XOrReg(Reg::RDI, Reg::RSI); - #endif - - /* Reset data about local stack */ - localStackSize_ = 128;//0; - paramStackSize_ = 0; - - /* Write entry point prologue */ - WritePrologue(); - WriteStackFrame(GetEntryVarArgs(), GetStackAllocs()); -} - -void AMD64Assembler::End() -{ - /* Pop local stack */ - if (localStackSize_ > 0) - AddImm32(Reg::RSP, localStackSize_); - - /* Write entry point epilogue and append supplement at the end of program */ - WriteEpilogue(); - ApplySupplements(); -} - -void AMD64Assembler::WriteFuncCall(const void* addr, JITCallConv conv, bool farCall) -{ - const auto& args = GetArgs(); - - /* Move first couple of arguments into registers */ - std::size_t numIntRegs = 0, numFltRegs = 0; - std::size_t lastInt, lastFlt; - std::size_t num = args.size(); - - lastInt = lastFlt = std::numeric_limits::max(); - - for (std::size_t i = 0; i < num; ++i) - { - const JIT::Arg& arg = args[i]; - - /* Determine destination register for argument */ - Reg dstReg = g_amd64TempReg; - bool isFloat = IsFloat(arg.type); - - if (isFloat && numFltRegs < g_amd64FltParamsCount) - { - dstReg = g_amd64FltParams[numFltRegs++]; - lastFlt = i; - } - else if (!isFloat && numIntRegs < g_amd64IntParamsCount) - { - dstReg = g_amd64IntParams[numIntRegs++]; - lastInt = i; - } - else - break; - - if (arg.param < 0xF) - { - if (arg.param < varArgDisp_.size()) - { - /* Move parameter from local stack into destination register */ - if (IsFltReg(dstReg)) - MovDQURegMem(dstReg, Reg::RBP, varArgDisp_[arg.param]); - else - MovRegMem(dstReg, Reg::RBP, varArgDisp_[arg.param]); - } - } - else if (dstReg >= Reg::R8 && dstReg <= Reg::R15) - { - /* R8-R15 registers are only supported for 64-bit operand size */ - MovRegImm64(dstReg, arg.value.i64); - } - else - { - /* Move value into destination register */ - switch (arg.type) - { - case ArgType::Byte: - MovRegImm32(dstReg, arg.value.i8); - break; - case ArgType::Word: - MovRegImm32(dstReg, arg.value.i16); - break; - case ArgType::DWord: - MovRegImm32(dstReg, arg.value.i32); - break; - case ArgType::QWord: - MovRegImm64(dstReg, arg.value.i64); - break; - case ArgType::Ptr: - MovRegImm64(dstReg, arg.value.i64); - break; - case ArgType::StackPtr: - MovReg(dstReg, Reg::RBP); - SubImm32(dstReg, stackChunkOffsets_[arg.value.i8]); - break; - case ArgType::Float: - MovSSRegImm32(dstReg, arg.value.f32); - break; - case ArgType::Double: - MovSDRegImm64(dstReg, arg.value.f64); - break; - } - } - } - - /* Push remaining arguments onto stack */ - Displacement stackDisp; - - for (std::size_t i = 0; i < num; ++i) - { - std::size_t iRev = num - i - 1u; - const JIT::Arg& arg = args[iRev]; - - /* Check if argument has already been moved into a register */ - bool isFloat = IsFloat(arg.type); - - if ( ( isFloat && iRev == lastFlt ) || - ( !isFloat && iRev == lastInt ) ) - { - break; - } - - /* Push argument onto stack */ - switch (arg.type) - { - case ArgType::Byte: - case ArgType::Word: - case ArgType::DWord: - case ArgType::Float: - MovMemImm32(Reg::RSP, arg.value.i32, stackDisp); - stackDisp.disp8 += 8; - break; - case ArgType::QWord: - case ArgType::Ptr: - case ArgType::Double: - MovRegImm64(g_amd64TempReg, arg.value.i64); - MovMemReg(Reg::RSP, g_amd64TempReg, stackDisp); - stackDisp.disp8 += 8; - break; - case ArgType::StackPtr: - MovReg(g_amd64TempReg, Reg::RBP); - SubImm32(g_amd64TempReg, stackChunkOffsets_[arg.value.i8]); - MovMemReg(Reg::RSP, g_amd64TempReg, stackDisp); - stackDisp.disp8 += 8; - break; - } - } - - /* Write 'call' instruction */ - MovRegImm64(g_amd64TempReg, reinterpret_cast(addr)); - CallNear(g_amd64TempReg); -} - - -/* - * ======= Private: ======= - */ - -bool AMD64Assembler::IsLittleEndian() const -{ - return true; -} - -std::uint8_t AMD64Assembler::DispMod(const Displacement& disp) const -{ - if (disp.disp32 != 0) - { - if (disp.has32Bits) - return Operand_Mod10; // disp32 - else - return Operand_Mod01; // disp8 - } - return 0; -} - -std::uint8_t AMD64Assembler::ModRM(std::uint8_t mode, Reg r0, Reg r1) const -{ - std::uint8_t modRM = (mode | (RegByte(r0) << 3)); - - if (r1 == Reg::RSP) - modRM |= Operand_SIB; - else - modRM |= RegByte(r1); - - return modRM; -} - -void AMD64Assembler::WritePrologue() -{ - /* Store base stack pointer (RBP) */ - PushReg(Reg::RBP); - MovReg(Reg::RBP, Reg::RSP); - - #if 1 - /* Store general purpose registers */ - //TODO: determine which registers must be stored - PushReg(Reg::RBX); - #endif -} - -void AMD64Assembler::WriteEpilogue() -{ - #if 1 - /* Restore general purpose registers */ - //TODO: determine which registers must be restored - PopReg(Reg::RBX); - #endif - - /* Restore base stack pointer (RBP) */ - PopReg(Reg::RBP); - RetNear(paramStackSize_); -} - -void AMD64Assembler::WriteStackFrame( - const std::vector& varArgTypes, - const std::vector& stackChunks) -{ - /* Determine required stack size for variadic arguments */ - std::uint32_t varArgSize = 0; - for (JIT::ArgType type : varArgTypes) - varArgSize += (IsFloat(type) ? 16 : 8); - - /* Determine required stack size for allocations */ - std::uint32_t stackChunksSize = 0; - for (std::uint32_t chunk : stackChunks) - stackChunksSize += chunk; - - /* Allocate local stack */ - localStackSize_ += varArgSize; - - std::uint32_t chunkStackOffset = localStackSize_ + 8; - - localStackSize_ += stackChunksSize; - - if (localStackSize_ > 0) - SubImm32(Reg::RSP, localStackSize_); - - /* Store parameters in local stack */ - std::size_t numIntRegs = 0, numFltRegs = 0; - std::int8_t paramStackOffset = 16; // first parameter at [EBP+16] - std::int8_t localStackOffset = -16; // local variables after preserved EBX - - for (auto type : varArgTypes) - { - bool isFloat = IsFloat(type); - Reg srcReg = g_amd64TempReg; - - if (isFloat && numFltRegs < g_amd64FltParamsCount) - { - /* Get parameter from floating-point register */ - srcReg = g_amd64FltParams[numFltRegs++]; - } - else if (!isFloat && numIntRegs < g_amd64IntParamsCount) - { - /* Get parameter from integer register */ - srcReg = g_amd64IntParams[numIntRegs++]; - } - else - { - /* Load parameter from stack */ - MovRegMem(srcReg, Reg::RBP, Disp8{ paramStackOffset }); - paramStackOffset += 8; - paramStackSize_ += 8; - } - - /* Store parameter in local stack */ - if (IsFltReg(srcReg)) - { - localStackOffset -= 16; // SSE2 register size of 128 bits - MovDQUMemReg(Reg::RBP, srcReg, Disp8{ localStackOffset }); - } - else - { - localStackOffset -= 8; // x64 register size of 64 bits - MovMemReg(Reg::RBP, srcReg, Disp8{ localStackOffset }); - } - - /* Store parameter offset within stack frame */ - varArgDisp_.push_back(Disp8{ localStackOffset }); - } - - /* Determine stack base for arguments of subsequent calls */ - argStackBase_.disp8 = localStackOffset; - - /* Determine stack base for allocated stack chunks */ - stackChunkOffsets_.reserve(stackChunks.size()); - for (auto chunk : stackChunks) - { - chunkStackOffset += static_cast(chunk); - stackChunkOffsets_.push_back(chunkStackOffset); - } -} - -void AMD64Assembler::WriteOptREX(Reg reg, bool defaultsTo64Bit) -{ - std::uint8_t prefix = 0; - - if (Is64Reg(reg)) - { - if (!defaultsTo64Bit || reg >= Reg::R8) - { - prefix |= REX_W; - if (reg >= Reg::R8) - prefix |= REX_B; - } - } - - if (prefix != 0) - WriteByte(REX_Prefix | prefix); -} - -void AMD64Assembler::WriteOptDisp(const Displacement& disp) -{ - if (disp.disp32 != 0) - { - if (disp.has32Bits) - WriteDWord(static_cast(disp.disp32)); - else - WriteByte(static_cast(disp.disp8)); - } -} - -void AMD64Assembler::WriteOptSIB(Reg reg) -{ - if (reg == Reg::RSP) - WriteByte((RegByte(reg) << 3) | RegByte(reg)); -} - -void AMD64Assembler::BeginSupplement(const Arg& arg) -{ - Supplement supp; - { - supp.data.i64 = arg.value.i64; - supp.dataSize = GetArgSize(arg.type); - supp.rip = 0; - supp.dstOffset = GetAssembly().size(); - } - supplements_.push_back(supp); -} - -void AMD64Assembler::EndSupplement() -{ - /* Write RIP value for offset of next instruction */ - if (!supplements_.empty()) - supplements_.back().rip = GetAssembly().size(); -} - -void AMD64Assembler::ApplySupplements() -{ - auto& code = GetAssembly(); - - for (const Supplement& supp : supplements_) - { - /* Override displacement dummy */ - std::uint32_t disp32 = static_cast(code.size() - supp.rip); - ::memcpy(&(code[supp.dstOffset]), &disp32, sizeof(disp32)); - - /* Write supplement data */ - Write(supp.data.i8, supp.dataSize); - } -} - -void AMD64Assembler::ErrInvalidUseOfRSP() -{ - #ifdef LLGL_DEBUG - //Error("invalid use of %RSP register in MOV instruction"); - #endif -} - -/* ----- PUSH ----- */ - -void AMD64Assembler::PushReg(Reg srcReg) -{ - WriteOptREX(srcReg, true); - WriteByte(Opcode_PushReg | RegByte(srcReg)); -} - -void AMD64Assembler::PushImm8(std::uint8_t byte) -{ - WriteByte(Opcode_PushImm8); - WriteByte(byte); -} - -void AMD64Assembler::PushImm16(std::uint16_t word) -{ - PushImm32(word); -} - -void AMD64Assembler::PushImm32(std::uint32_t dword) -{ - WriteByte(Opcode_PushImm); - WriteDWord(dword); -} - -void AMD64Assembler::Push(Reg srcReg) -{ - if (IsFltReg(srcReg)) - { - SubImm32(Reg::RSP, 16); - MovDQUMemReg(Reg::RSP, srcReg, {}); - } - else - PushReg(srcReg); -} - -/* ----- POP ----- */ - -void AMD64Assembler::PopReg(Reg dstReg) -{ - WriteOptREX(dstReg, true); - WriteByte(Opcode_PopReg | RegByte(dstReg)); -} - -void AMD64Assembler::Pop(Reg dstReg) -{ - if (IsFltReg(dstReg)) - { - MovDQURegMem(dstReg, Reg::RSP, {}); - AddImm32(Reg::RSP, 16); - } - else - PopReg(dstReg); -} - -/* ----- MOV ----- */ - -// Opcode: 89 /r -void AMD64Assembler::MovReg(Reg dstReg, Reg srcReg) -{ - WriteOptREX(dstReg); - WriteByte(Opcode_MovMemReg); - WriteByte(Operand_Mod11 | RegByte(srcReg) << 3 | RegByte(dstReg)); -} - -void AMD64Assembler::MovRegImm32(Reg dstReg, std::uint32_t dword) -{ - if (dword != 0) - { - WriteByte(Opcode_MovRegImm | RegByte(dstReg)); - WriteDWord(dword); - } - else - XOrReg(dstReg, dstReg); -} - -void AMD64Assembler::MovRegImm64(Reg dstReg, std::uint64_t qword) -{ - if (qword != 0) - { - WriteOptREX(dstReg); - WriteByte(Opcode_MovRegImm | RegByte(dstReg)); - WriteQWord(qword); - } - else - XOrReg(dstReg, dstReg); -} - -void AMD64Assembler::MovMemImm32(Reg dstMemReg, std::uint32_t dword, const Displacement& disp) -{ - WriteOptREX(dstMemReg); // prefix - WriteByte(Opcode_MovMemImm); - WriteByte(DispMod(disp) | RegByte(dstMemReg)); - WriteOptSIB(dstMemReg); - WriteOptDisp(disp); // displacement - WriteDWord(dword); // immediate -} - -void AMD64Assembler::MovMemReg(Reg dstMemReg, Reg srcReg, const Displacement& disp) -{ - WriteOptREX(srcReg); // prefix - WriteByte(Opcode_MovMemReg); - WriteByte(ModRM(DispMod(disp), srcReg, dstMemReg)); - WriteOptSIB(dstMemReg); - WriteOptDisp(disp); // displacement -} - -void AMD64Assembler::MovRegMem(Reg dstReg, Reg srcMemReg, const Displacement& disp) -{ - WriteOptREX(dstReg); - WriteByte(Opcode_MovRegMem); - WriteByte(ModRM(DispMod(disp), dstReg, srcMemReg)); - WriteOptSIB(srcMemReg); - WriteOptDisp(disp); -} - -#if 0 // UNUSED -// dstReg: XMM0-XMM7, srcMemReg: RAX-RDI -void AMD64Assembler::MovSSRegMem(Reg dstReg, Reg srcMemReg, const Displacement& disp) -{ - Write(OpcodeSSE2_MovSSRegMem, 3); - WriteByte(DispMod(disp) | (RegByte(dstReg) << 3) | RegByte(srcMemReg)); - WriteOptDisp(disp); // displacement -} - -// dstReg: XMM0-XMM7, srcMemReg: RAX-RDI -void AMD64Assembler::MovSDRegMem(Reg dstReg, Reg srcMemReg, const Displacement& disp) -{ - Write(OpcodeSSE2_MovSDRegMem, 3); - WriteByte(DispMod(disp) | (RegByte(dstReg) << 3) | RegByte(srcMemReg)); - WriteOptDisp(disp); // displacement -} -#endif // /UNUSED - -void AMD64Assembler::MovSSRegImm32(Reg dstReg, float f32) -{ - Write(OpcodeSSE2_MovSSRegMem, 3); - WriteByte((RegByte(dstReg) << 3) | Operand_RIP); - - Arg arg; - arg.type = ArgType::Float; - arg.value.f32 = f32; - BeginSupplement(arg); - - WriteDWord(0); // displacement (dummy) - - EndSupplement(); -} - -void AMD64Assembler::MovSDRegImm64(Reg dstReg, double f64) -{ - Write(OpcodeSSE2_MovSDRegMem, 3); - WriteByte((RegByte(dstReg) << 3) | Operand_RIP); - - Arg arg; - arg.type = ArgType::Double; - arg.value.f64 = f64; - BeginSupplement(arg); - - WriteDWord(0); // displacement (dummy) - - EndSupplement(); -} - -// dstReg: XMM0-XMM7, srcMemReg: RAX-RDI -void AMD64Assembler::MovDQURegMem(Reg dstReg, Reg srcMemReg, const Displacement& disp) -{ - Write(OpcodeSSE2_MovDQURegMem, 3); - WriteByte(ModRM(DispMod(disp), dstReg, srcMemReg)); - WriteOptSIB(srcMemReg); - WriteOptDisp(disp); -} - -// dstMemReg: RAX-RDI, srcReg: XMM0-XMM7 -void AMD64Assembler::MovDQUMemReg(Reg dstMemReg, Reg srcReg, const Displacement& disp) -{ - Write(OpcodeSSE2_MovDQUMemReg, 3); - WriteByte(ModRM(DispMod(disp), srcReg, dstMemReg)); - WriteOptSIB(dstMemReg); - WriteOptDisp(disp); -} - -/* ----- ADD ----- */ - -void AMD64Assembler::AddImm32(Reg dst, std::uint32_t dword) -{ - WriteOptREX(dst); - WriteByte(Opcode_AddImm); - WriteByte(Operand_Mod11 | RegByte(dst)); - WriteDWord(dword); -} - -/* ----- SUB ----- */ - -// Opcode: 81 /5 id -void AMD64Assembler::SubImm32(Reg dstReg, std::uint32_t dword) -{ - WriteOptREX(dstReg); - WriteByte(Opcode_SubImm); - WriteByte(Operand_Mod11 | (5u << 3) | RegByte(dstReg)); - WriteDWord(dword); -} - -/* ----- DIV ----- */ - -// Opcode: F7 /6 -// Divide RDX:RAX -> Quotient: RAX, Remainder: RDX -void AMD64Assembler::DivReg(Reg srcReg) -{ - WriteOptREX(srcReg); - WriteByte(Opcode_DivReg); - WriteByte(Operand_Mod11 | (6u << 3) | RegByte(srcReg)); -} - -/* ----- XOR ----- */ - -// Opcode: 31 /r -void AMD64Assembler::XOrReg(Reg dstReg, Reg srcReg) -{ - WriteOptREX(dstReg); - WriteByte(Opcode_XOrMemReg); - WriteByte(Operand_Mod11 | RegByte(srcReg) << 3 | RegByte(dstReg)); -} - -/* ----- CALL ----- */ - -void AMD64Assembler::CallNear(Reg reg) -{ - WriteOptREX(reg, true); - WriteByte(0xFF); - WriteByte(Opcode_CallNear | Operand_Mod11 | RegByte(reg)); -} - -/* ----- RET ----- */ - -void AMD64Assembler::RetNear(std::uint16_t word) -{ - if (word > 0) - { - WriteByte(Opcode_RetNearImm16); - WriteWord(word); - } - else - WriteByte(Opcode_RetNear); -} - -void AMD64Assembler::RetFar(std::uint16_t word) -{ - if (word > 0) - { - WriteByte(Opcode_RetFarImm16); - WriteWord(word); - } - else - WriteByte(Opcode_RetFar); -} - -/* ----- INT ----- */ - -void AMD64Assembler::Int(std::uint8_t byte) -{ - WriteByte(Opcode_Int); - WriteByte(byte); -} - -#if 1//TESTING -void AMD64Assembler::_ForceExcep() -{ - //TEST: generate division by zero instruction to force exception - MovRegImm32(Reg::RAX, 0); - MovRegImm32(Reg::RDX, 0); - DivReg(Reg::RAX); -} -#endif - - -/* - * Displacement structure - */ - -AMD64Assembler::Displacement::Displacement() : - has32Bits { false }, - disp32 { 0 } -{ -} - -AMD64Assembler::Disp8::Disp8(std::int8_t disp) -{ - has32Bits = false; - disp8 = disp; -} - -AMD64Assembler::Disp32::Disp32(std::int32_t disp) -{ - has32Bits = true; - disp32 = disp; -} - - -} // /namespace JIT - -} // /namespace LLGL - - - -// ================================================================================ diff --git a/sources/JIT/Arch/AMD64/AMD64Assembler.h b/sources/JIT/Arch/AMD64/AMD64Assembler.h deleted file mode 100644 index 4f44bf0f0d..0000000000 --- a/sources/JIT/Arch/AMD64/AMD64Assembler.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * AMD64Assembler.h - * - * Copyright (c) 2015 Lukas Hermanns. All rights reserved. - * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). - */ - -#ifndef LLGL_AMD64_ASSEMBLER_H -#define LLGL_AMD64_ASSEMBLER_H - - -#include "AMD64Register.h" -#include "../../JITCompiler.h" -#include -#include - - -namespace LLGL -{ - -namespace JIT -{ - - -// AMD64 (a.k.a. x86_64) assembly code generator. -class AMD64Assembler final : public JITCompiler -{ - - public: - - void Begin() override; - void End() override; - - private: - - bool IsLittleEndian() const override; - void WriteFuncCall(const void* addr, JITCallConv conv, bool farCall) override; - - private: - - struct Displacement; - - std::uint8_t DispMod(const Displacement& disp) const; - std::uint8_t ModRM(std::uint8_t mode, Reg r0, Reg r1) const; - - void WritePrologue(); - void WriteEpilogue(); - - void WriteStackFrame( - const std::vector& varArgTypes, - const std::vector& stackChunks - ); - - void WriteOptREX(Reg reg, bool defaultsTo64Bit = false); - void WriteOptDisp(const Displacement& disp); - void WriteOptSIB(Reg reg); - - void BeginSupplement(const Arg& arg); - void EndSupplement(); - void ApplySupplements(); - - void ErrInvalidUseOfRSP(); - - private: - - void PushReg(Reg srcReg); - void PushImm8(std::uint8_t byte); - void PushImm16(std::uint16_t word); - void PushImm32(std::uint32_t dword); - void Push(Reg srcReg); - - void PopReg(Reg dstReg); - void Pop(Reg dstReg); - - void MovReg(Reg dstReg, Reg srcReg); - void MovRegImm32(Reg dstReg, std::uint32_t dword); - void MovRegImm64(Reg dstReg, std::uint64_t qword); - void MovMemImm32(Reg dstMemReg, std::uint32_t dword, const Displacement& disp); - void MovMemReg(Reg dstMemReg, Reg srcReg, const Displacement& disp); - void MovRegMem(Reg dstReg, Reg srcMemReg, const Displacement& disp); - - #if 0 // UNUSED - void MovSSRegMem(Reg dstReg, Reg srcMemReg, const Displacement& disp); - void MovSDRegMem(Reg dstReg, Reg srcMemReg, const Displacement& disp); - #endif // /UNUSED - - void MovSSRegImm32(Reg dstReg, float f32); - void MovSDRegImm64(Reg dstReg, double f64); - - void MovDQURegMem(Reg dstReg, Reg srcMemReg, const Displacement& disp); - void MovDQUMemReg(Reg dstMemReg, Reg srcReg, const Displacement& disp); - - void AddImm32(Reg dstReg, std::uint32_t dword); - void SubImm32(Reg dstReg, std::uint32_t dword); - void DivReg(Reg srcReg); - void XOrReg(Reg dstReg, Reg srcReg); - - void CallNear(Reg reg); - - void RetNear(std::uint16_t word = 0); - void RetFar(std::uint16_t word = 0); - - void Int(std::uint8_t byte); - - #if 1//TESTING - void _ForceExcep(); - #endif - - private: - - struct Supplement - { - QWord data; // Supplement data to be written at the end of the program (e.g. float literals) - std::uint8_t dataSize; // Data size (in bytes) - std::uint64_t rip; // Program counter (RIP register) - std::size_t dstOffset; // Destination byte offset where the instruction must be updated - }; - - struct Displacement - { - Displacement(); - Displacement(const Displacement&) = default; - Displacement& operator = (const Displacement&) = default; - - bool has32Bits; - union - { - std::int8_t disp8; - std::int32_t disp32; - }; - }; - - struct Disp8 : public Displacement - { - Disp8(std::int8_t disp); - }; - - struct Disp32 : public Displacement - { - Disp32(std::int32_t disp); - }; - - private: - - std::uint32_t localStackSize_ = 0; - std::uint16_t paramStackSize_ = 0; - Displacement argStackBase_; - - // Supplement data that must be updated after encoding - std::vector supplements_; - - // Displacements of parameters within stack frame - std::vector varArgDisp_; - - // Base pointer offsets of stack allocations - std::vector stackChunkOffsets_; - -}; - - -} // /namespace JIT - -} // /namespace LLGL - - -#endif - - - -// ================================================================================ diff --git a/sources/JIT/Arch/AMD64/AMD64Opcode.h b/sources/JIT/Arch/AMD64/AMD64Opcode.h deleted file mode 100644 index 9398bdda37..0000000000 --- a/sources/JIT/Arch/AMD64/AMD64Opcode.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * AMD64Opcode.h - * - * Copyright (c) 2015 Lukas Hermanns. All rights reserved. - * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). - */ - -#ifndef LLGL_AMD64_OPCODE_H -#define LLGL_AMD64_OPCODE_H - - -#include -#include -#include - - -namespace LLGL -{ - -namespace JIT -{ - -/* -ModR/M => Mode Register/Memory -SIB => Scale-Index-Base -mod = b11 => addressing via register -REX.W: 0 = default operand size, 1 = 64-bit operand size -REX.R: permitting access to 16 registers in ModR/M field -REX.X: permitting access to 16 registers in SIB field -REX.B: permitting access to 16 registers in ModR/M field -------------------------------------------------------------------------------------- -| Field: |  REX | Opcode | ModR/M |  SIB | Displacement | Immediate | -|--------|----------|----------------|--------|----------|--------------|-----------| -| Size: | 0-1 |  1-3 | 0-1 |  0-1 |  0,1,2,4 |  0,1,2,4 | -|--------|----------|----------------|--------|----------|--------------|-----------| -| Bits: | 0100WRXB | | mod: 2 | scale: 2 |  |  | -|  |  | 0x0F | reg: 3 | index: 3 |  |  | -|  |  | 0x0F 0x38 | r/m: 3 | base: 3 |  |  | -|  |  | 0x0F 0x3A | | |  |  | -------------------------------------------------------------------------------------- -*/ - -enum REXBits : std::uint8_t -{ - REX_Prefix = 0x40, - REX_W = 0x08, - REX_R = 0x04, - REX_B = 0x01, -}; - -enum ModRMBits : std::uint8_t -{ - Operand_Mod01 = 0x40, // disp8 - Operand_Mod10 = 0x80, // disp32 - Operand_Mod11 = 0xC0, // direct addressing - Operand_RIP = 0x05, // 00 000 101 - Operand_SIB = 0x04, // 00 000 100 -}; - -enum OpcodePrefix : std::uint8_t -{ - OpcodePrefix_2 = 0x0F, - OpcodePrefix_3a = 0x38, - OpcodePrefix_3b = 0x3A, -}; - -enum Opcode : std::uint8_t -{ - Opcode_PushImm = 0x68, // 68 id - Opcode_PushImm8 = 0x6A, // 6A ib - Opcode_PushReg = 0x50, - Opcode_PopReg = 0x58, // 58 +rq - Opcode_AddImm = 0x81, // 81 /0 id - Opcode_SubImm = 0x81, // 81 /5 id - Opcode_DivReg = 0xF7, // F7 /6 - Opcode_XOrMemReg = 0x31, // 31 /r - Opcode_XOrRegMem = 0x33, // 33 /r - Opcode_MovRegImm8 = 0xB0, // B0 +rb ib - Opcode_MovRegImm = 0xB8, // [REX.W] B8 +rd id - Opcode_MovMemImm = 0xC7, // C7 /0 id - Opcode_MovMemReg = 0x89, // 89 /r - Opcode_MovRegMem = 0x8B, // 8B /r - Opcode_RetNear = 0xC3, // C3 - Opcode_RetFar = 0xCB, // CB - Opcode_RetNearImm16 = 0xC2, // C2 iw - Opcode_RetFarImm16 = 0xCA, // CA iw - Opcode_CallNear = 0x10, // /2 => 00 010 000 => 0x10 - Opcode_Int = 0xCD, // CD ib -}; - -static const std::uint8_t OpcodeSSE2_MovSSRegMem[3] = { 0xF3, 0x0F, 0x10 }; -static const std::uint8_t OpcodeSSE2_MovSSMemReg[3] = { 0xF3, 0x0F, 0x11 }; - -static const std::uint8_t OpcodeSSE2_MovSDRegMem[3] = { 0xF2, 0x0F, 0x10 }; -static const std::uint8_t OpcodeSSE2_MovSDMemReg[3] = { 0xF2, 0x0F, 0x11 }; - -static const std::uint8_t OpcodeSSE2_MovDQURegMem[3] = { 0xF3, 0x0F, 0x6F }; -static const std::uint8_t OpcodeSSE2_MovDQUMemReg[3] = { 0xF3, 0x0F, 0x7F }; - - -} // /namespace JIT - -} // /namespace LLGL - - -#endif - - - -// ================================================================================ diff --git a/sources/JIT/Arch/AMD64/AMD64Register.cpp b/sources/JIT/Arch/AMD64/AMD64Register.cpp deleted file mode 100644 index 5b1b91ff18..0000000000 --- a/sources/JIT/Arch/AMD64/AMD64Register.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * AMD64Register.cpp - * - * Copyright (c) 2015 Lukas Hermanns. All rights reserved. - * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). - */ - -#include "AMD64Register.h" -#include "AMD64Opcode.h" - - -namespace LLGL -{ - -namespace JIT -{ - - -std::uint8_t RegByte(const Reg reg) -{ - switch (reg) - { - case Reg::EAX: return 0x00; // 000 - case Reg::ECX: return 0x01; // 001 - case Reg::EDX: return 0x02; // 010 - case Reg::EBX: return 0x03; // 011 - case Reg::ESP: return 0x04; // 100 - case Reg::EBP: return 0x05; // 101 - case Reg::ESI: return 0x06; // 110 - case Reg::EDI: return 0x07; // 111 - - case Reg::RAX: return 0x00; // 000 - case Reg::RCX: return 0x01; // 001 - case Reg::RDX: return 0x02; // 010 - case Reg::RBX: return 0x03; // 011 - case Reg::RSP: return 0x04; // 100 - case Reg::RBP: return 0x05; // 101 - case Reg::RSI: return 0x06; // 110 - case Reg::RDI: return 0x07; // 111 - - case Reg::R8: return 0x00; // 000 - case Reg::R9: return 0x01; // 001 - case Reg::R10: return 0x02; // 010 - case Reg::R11: return 0x03; // 011 - case Reg::R12: return 0x04; // 100 - case Reg::R13: return 0x05; // 101 - case Reg::R14: return 0x06; // 110 - case Reg::R15: return 0x07; // 111 - - case Reg::XMM0: return 0x00; // 000 - case Reg::XMM1: return 0x01; // 001 - case Reg::XMM2: return 0x02; // 010 - case Reg::XMM3: return 0x03; // 011 - case Reg::XMM4: return 0x04; // 100 - case Reg::XMM5: return 0x05; // 101 - case Reg::XMM6: return 0x06; // 110 - case Reg::XMM7: return 0x07; // 111 - - case Reg::XMM8: return 0x00; // 000 - case Reg::XMM9: return 0x01; // 001 - case Reg::XMM10: return 0x02; // 010 - case Reg::XMM11: return 0x03; // 011 - case Reg::XMM12: return 0x04; // 100 - case Reg::XMM13: return 0x05; // 101 - case Reg::XMM14: return 0x06; // 110 - case Reg::XMM15: return 0x07; // 111 - } - return 0xFF; -} - -bool Is64Reg(const Reg reg) -{ - return (reg >= Reg::RAX && reg <= Reg::R15); -} - -bool IsFltReg(const Reg reg) -{ - return (reg >= Reg::XMM0 && reg <= Reg::XMM15); -} - - -} // /namespace JIT - -} // /namespace LLGL - - - -// ================================================================================ diff --git a/sources/JIT/Arch/AMD64/AMD64Register.h b/sources/JIT/Arch/AMD64/AMD64Register.h deleted file mode 100644 index a48a6de47c..0000000000 --- a/sources/JIT/Arch/AMD64/AMD64Register.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * AMD64Register.h - * - * Copyright (c) 2015 Lukas Hermanns. All rights reserved. - * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). - */ - -#ifndef LLGL_AMD64_REGISTER_H -#define LLGL_AMD64_REGISTER_H - - -#include - - -namespace LLGL -{ - -namespace JIT -{ - - -// AMD64 register enumeration. -enum class Reg -{ - EAX, - ECX, - EDX, - EBX, - ESP, - EBP, - ESI, - EDI, - - RAX, - RCX, - RDX, - RBX, - RSP, - RBP, - RSI, - RDI, - - R8, - R9, - R10, - R11, - R12, - R13, - R14, - R15, - - XMM0, - XMM1, - XMM2, - XMM3, - XMM4, - XMM5, - XMM6, - XMM7, - - XMM8, - XMM9, - XMM10, - XMM11, - XMM12, - XMM13, - XMM14, - XMM15, -}; - -// Returns the specified register part of an AMD64 opcode. -std::uint8_t RegByte(const Reg reg); - -// Returns true, if 'reg' is a 64-bit register (i.e. RAX-RSP and R8-R15). -bool Is64Reg(const Reg reg); - -// Returns true, if 'reg' denotes a floating-point register (i.e. XMM0-XMM15). -bool IsFltReg(const Reg reg); - - -} // /namespace JIT - -} // /namespace LLGL - - -#endif - - - -// ================================================================================ diff --git a/sources/JIT/Arch/IA32/IA32Assembler.cpp b/sources/JIT/Arch/IA32/IA32Assembler.cpp deleted file mode 100644 index 472be259ce..0000000000 --- a/sources/JIT/Arch/IA32/IA32Assembler.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - * IA32Assembler.cpp - * - * Copyright (c) 2015 Lukas Hermanns. All rights reserved. - * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). - */ - -#include "IA32Assembler.h" -#include "IA32Opcode.h" - - -namespace LLGL -{ - -namespace JIT -{ - - -void IA32Assembler::Begin() -{ - //TODO -} - -void IA32Assembler::End() -{ - //TODO -} - -void IA32Assembler::WriteFuncCall(const void* addr, JITCallConv conv, bool farCall) -{ - #if 0 - /* Write arguments */ - for () - { - - } - - /* Write 'this' pointer */ - if (conv == JITCallConv::ThisCall) - { - if (auto ptr = GetThisPtr()) - MovRegImm32(Reg::ECX, reinterpret_cast(ptr)); - else - throw std::runtime_error("missing 'this' pointer for '__thiscall' IA-32/x86 instruction"); - } - - /* Write 'call' instruction */ - if (farCall) - CallFar(Reg::EAX); - else - CallNear(Reg::EAX); - #endif -} - - -/* - * ======= Private: ======= - */ - -bool IA32Assembler::IsLittleEndian() const -{ - return true; -} - -void IA32Assembler::PushReg(const Reg reg) -{ - WriteByte(Opcode_PushReg | RegByte(reg)); -} - -void IA32Assembler::PushImm32(std::uint32_t dword) -{ - WriteByte(Opcode_PushImm32); - WriteDWord(dword); -} - -void IA32Assembler::PopReg(const Reg reg) -{ - WriteByte(Opcode_PopReg | RegByte(reg)); -} - -void IA32Assembler::MovRegImm32(const Reg reg, std::uint32_t dword) -{ - WriteByte(0x48); //??? - WriteByte(Opcode_MovRegImm32 | RegByte(reg)); - WriteDWord(dword); -} - -void IA32Assembler::CallNear(const Reg reg) -{ - WriteByte(0xFF); - WriteByte(Opcode_CallNear | RegByte(reg)); -} - -void IA32Assembler::CallFar(const Reg reg) -{ - //TODO -} - -void IA32Assembler::RetNear(std::uint16_t word) -{ - if (word > 0) - { - WriteByte(Opcode_RetNearImm16); - WriteWord(word); - } - else - WriteByte(Opcode_RetNear); -} - -void IA32Assembler::RetFar(std::uint16_t word) -{ - if (word > 0) - { - WriteByte(Opcode_RetFarImm16); - WriteWord(word); - } - else - WriteByte(Opcode_RetFar); -} - - -} // /namespace JIT - -} // /namespace LLGL - - - -// ================================================================================ diff --git a/sources/JIT/Arch/IA32/IA32Assembler.h b/sources/JIT/Arch/IA32/IA32Assembler.h deleted file mode 100644 index e991fae34e..0000000000 --- a/sources/JIT/Arch/IA32/IA32Assembler.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * IA32Assembler.h - * - * Copyright (c) 2015 Lukas Hermanns. All rights reserved. - * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). - */ - -#ifndef LLGL_IA32_ASSEMBLER_H -#define LLGL_IA32_ASSEMBLER_H - - -#include "IA32Register.h" -#include "../../JITCompiler.h" -#include -#include - - -namespace LLGL -{ - -namespace JIT -{ - - -// IA-32 (a.k.a. x86) assembly code generator. -class IA32Assembler final : public JITCompiler -{ - - public: - - void Begin() override; - void End() override; - - private: - - bool IsLittleEndian() const override; - void WriteFuncCall(const void* addr, JITCallConv conv, bool farCall) override; - - private: - - void PushReg(const Reg reg); - void PushImm32(std::uint32_t dword); - - void PopReg(const Reg reg); - - void MovRegImm32(const Reg reg, std::uint32_t dword); - - void CallNear(const Reg reg); - void CallFar(const Reg reg); - - void RetNear(std::uint16_t word = 0); - void RetFar(std::uint16_t word = 0); - -}; - - -} // /namespace JIT - -} // /namespace LLGL - - -#endif - - - -// ================================================================================ diff --git a/sources/JIT/Arch/IA32/IA32Opcode.h b/sources/JIT/Arch/IA32/IA32Opcode.h deleted file mode 100644 index da2277f1d3..0000000000 --- a/sources/JIT/Arch/IA32/IA32Opcode.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * IA32Opcode.h - * - * Copyright (c) 2015 Lukas Hermanns. All rights reserved. - * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). - */ - -#ifndef LLGL_IA32_OPCODE_H -#define LLGL_IA32_OPCODE_H - - -#include -#include -#include - - -namespace LLGL -{ - -namespace JIT -{ - - -enum Opcode : std::uint8_t -{ - Opcode_PushReg = 0x50, - Opcode_PopReg = 0x58, - Opcode_PushImm32 = 0x68, - Opcode_MovRegImm32 = 0xB8, // B8+ rd id - Opcode_RetNear = 0xC3, // C3 - Opcode_RetFar = 0xCB, // CB - Opcode_RetNearImm16 = 0xC2, // C2 iw - Opcode_RetFarImm16 = 0xCA, // CA iw - Opcode_CallNear = 0xD0, - //OpCode_CallFar = 0xE0, -}; - - -} // /namespace JIT - -} // /namespace LLGL - - -#endif - - - -// ================================================================================ diff --git a/sources/JIT/Arch/IA32/IA32Register.cpp b/sources/JIT/Arch/IA32/IA32Register.cpp deleted file mode 100644 index b339aaba0d..0000000000 --- a/sources/JIT/Arch/IA32/IA32Register.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * IA32Register.cpp - * - * Copyright (c) 2015 Lukas Hermanns. All rights reserved. - * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). - */ - -#include "IA32Register.h" -#include "IA32Opcode.h" - - -namespace LLGL -{ - -namespace JIT -{ - - -std::uint8_t RegByte(const Reg reg) -{ - switch (reg) - { - case Reg::EAX: return 0x00; // 000 - case Reg::ECX: return 0x01; // 001 - case Reg::EDX: return 0x02; // 010 - case Reg::EBX: return 0x03; // 011 - case Reg::ESP: return 0x04; // 100 - case Reg::EBP: return 0x05; // 101 - case Reg::ESI: return 0x06; // 110 - case Reg::EDI: return 0x07; // 111 - } - return 0xFF; -} - - -} // /namespace JIT - -} // /namespace LLGL - - - -// ================================================================================ diff --git a/sources/JIT/Arch/IA32/IA32Register.h b/sources/JIT/Arch/IA32/IA32Register.h deleted file mode 100644 index 0e700d2b3b..0000000000 --- a/sources/JIT/Arch/IA32/IA32Register.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * IA32Register.h - * - * Copyright (c) 2015 Lukas Hermanns. All rights reserved. - * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). - */ - -#ifndef LLGL_IA32_REGISTER_H -#define LLGL_IA32_REGISTER_H - - -#include - - -namespace LLGL -{ - -namespace JIT -{ - - -// IA-32 register enumeration. -enum class Reg -{ - EAX, - ECX, - EDX, - EBX, - ESP, - EBP, - ESI, - EDI, -}; - -// Returns the specified register part of an IA-32 opcode. -std::uint8_t RegByte(const Reg reg); - - -} // /namespace JIT - -} // /namespace LLGL - - -#endif - - - -// ================================================================================ diff --git a/sources/JIT/AssemblyTypes.h b/sources/JIT/AssemblyTypes.h deleted file mode 100644 index 170921e74b..0000000000 --- a/sources/JIT/AssemblyTypes.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * AssemblyTypes.h - * - * Copyright (c) 2015 Lukas Hermanns. All rights reserved. - * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). - */ - -#ifndef LLGL_ASSEMBLY_TYPES_H -#define LLGL_ASSEMBLY_TYPES_H - - -#include - - -namespace LLGL -{ - -namespace JIT -{ - - -// Argument type enumeration. -enum class ArgType -{ - Byte, - Word, - DWord, - QWord, - Ptr, - StackPtr, - Float, - Double, -}; - -// Word (16 bit). -union Word -{ - std::uint16_t i16; - std::uint8_t i8[2]; -}; - -// Double word (32 bit). -union DWord -{ - std::uint32_t i32; - std::uint8_t i8[4]; -}; - -// Quad word (64 bit). -union QWord -{ - std::uint64_t i64; - std::uint8_t i8[8]; -}; - -// Function argument with type and value. -struct Arg -{ - ArgType type : 4; - std::uint8_t param : 4; // Parameter index (0xF if unused) - union - { - std::uint8_t i8; - std::uint16_t i16; - std::uint32_t i32; - std::uint64_t i64; - const void* ptr; - float f32; - double f64; - } - value; -}; - -// Returns true if the specified argument type denotes a floating-point type. -inline bool IsFloat(const ArgType t) -{ - return (t >= ArgType::Float); -} - -// Converts the specified 16-bit value from little-endian to big-endian and vice-versa. -inline std::uint16_t SwapEndian16(std::uint16_t value) -{ - return (value >> 8) | (value << 8); -} - -// Converts the specified 32-bit value from little-endian to big-endian and vice-versa. -inline std::uint32_t SwapEndian32(std::uint32_t value) -{ - return - ( - ((value >> 0x18) & 0x000000ff) | // Move byte 3 to byte 0 - ((value >> 0x08) & 0x0000ff00) | // Move byte 2 to byte 1 - ((value << 0x08) & 0x00ff0000) | // Move byte 1 to byte 2 - ((value << 0x18) & 0xff000000) // Move byte 0 to byte 3 - ); -} - - -} // /namespace JIT - -} // /namespace LLGL - - -#endif - - - -// ================================================================================ diff --git a/sources/JIT/JITCompiler.cpp b/sources/JIT/JITCompiler.cpp deleted file mode 100644 index 6212750f98..0000000000 --- a/sources/JIT/JITCompiler.cpp +++ /dev/null @@ -1,365 +0,0 @@ -/* - * JITCompiler.cpp - * - * Copyright (c) 2015 Lukas Hermanns. All rights reserved. - * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). - */ - -#include "JITCompiler.h" -#include "AssemblyTypes.h" -#include "../Core/CoreUtils.h" -#include "../Core/PrintfUtils.h" -#include -#include -#include - -#include -#if defined LLGL_OS_WIN32 -# include "Platform/Win32/Win32JITProgram.h" -#else -# include "Platform/POSIX/POSIXJITProgram.h" -#endif - -#if defined LLGL_ARCH_ARM -//# include "Arch/ARM/ARMAssembler.h" -#elif defined LLGL_ARCH_AMD64 -# include "Arch/AMD64/AMD64Assembler.h" -#elif defined LLGL_ARCH_IA32 -# include "Arch/IA32/IA32Assembler.h" -#endif - - -namespace LLGL -{ - - -using namespace JIT; - -std::unique_ptr JITCompiler::Create() -{ - std::unique_ptr compiler; - - /* Create JIT compiler for current CPU architecture */ - #if defined LLGL_ARCH_ARM - //TODO - #elif defined LLGL_ARCH_AMD64 - compiler = MakeUnique(); - #elif defined LLGL_ARCH_IA32 - compiler = MakeUnique(); - #endif - - /* Store meta data */ - if (compiler) - compiler->littleEndian_ = compiler->IsLittleEndian(); - - return compiler; -} - -UTF8String JITCompiler::DumpAssembly(std::size_t bytesPerLine) const -{ - Report output; - - const auto& bytes = GetAssembly(); - for_range(i, bytes.size()) - { - /* Write current hex value and separator */ - output.Printf("0x%02X", static_cast(bytes[i])); - if (i + 1 < for_range_end(i)) - output.Printf(bytesPerLine > 0 && (i + 1) % bytesPerLine == 0 ? "\n" : " "); - } - - return UTF8String{ output.GetText() }; -} - -std::unique_ptr JITCompiler::FlushProgram() -{ - if (!assembly_.empty()) - { - auto program = JITProgram::Create(assembly_.data(), assembly_.size()); - assembly_.clear(); - return program; - } - return nullptr; -} - -void JITCompiler::EntryPointVarArgs(const std::initializer_list& varArgTypes) -{ - entryVarArgs_.reserve(varArgTypes.size()); - for (JIT::ArgType type : varArgTypes) - entryVarArgs_.push_back(type); -} - -std::uint8_t JITCompiler::StackAlloc(std::uint32_t size) -{ - auto idx = static_cast(stackAllocs_.size()); - stackAllocs_.push_back(size); - return idx; -} - -void JITCompiler::PushVarArg(std::uint8_t idx) -{ - if (idx < entryVarArgs_.size() && idx < 0xF) - { - Arg arg; - { - arg.type = entryVarArgs_[idx]; - arg.param = idx; - arg.value.i64 = 0; - } - args_.push_back(arg); - } -} - -void JITCompiler::PushStackPtr(std::uint8_t idx) -{ - if (idx < stackAllocs_.size()) - { - Arg arg; - { - arg.type = ArgType::StackPtr; - arg.param = 0xF; - arg.value.i8 = idx; - } - args_.push_back(arg); - } -} - -void JITCompiler::PushPtr(const void* value) -{ - Arg arg; - { - arg.type = ArgType::Ptr; - arg.param = 0xF; - arg.value.ptr = value; - } - args_.push_back(arg); -} - -void JITCompiler::PushByte(std::uint8_t value) -{ - Arg arg; - { - arg.type = ArgType::Byte; - arg.param = 0xF; - arg.value.i64 = 0; - arg.value.i8 = value; - } - args_.push_back(arg); -} - -void JITCompiler::PushWord(std::uint16_t value) -{ - Arg arg; - { - arg.type = ArgType::Word; - arg.param = 0xF; - arg.value.i64 = 0; - arg.value.i16 = value; - } - args_.push_back(arg); -} - -void JITCompiler::PushDWord(std::uint32_t value) -{ - Arg arg; - { - arg.type = ArgType::DWord; - arg.param = 0xF; - arg.value.i64 = 0; - arg.value.i32 = value; - } - args_.push_back(arg); -} - -void JITCompiler::PushQWord(std::uint64_t value) -{ - Arg arg; - { - arg.type = ArgType::QWord; - arg.param = 0xF; - arg.value.i64 = value; - } - args_.push_back(arg); -} - -void JITCompiler::PushFloat(float value) -{ - Arg arg; - { - arg.type = ArgType::Float; - arg.param = 0xF; - arg.value.i64 = 0; - arg.value.f32 = value; - } - args_.push_back(arg); -} - -void JITCompiler::PushDouble(double value) -{ - Arg arg; - { - arg.type = ArgType::Double; - arg.param = 0xF; - arg.value.f64 = value; - } - args_.push_back(arg); -} - -void JITCompiler::FuncCall(const void* addr, JITCallConv conv, bool farCall) -{ - WriteFuncCall(addr, conv, farCall); - args_.clear(); -} - -void JITCompiler::PushSizeT(std::uint64_t value) -{ - #ifdef LLGL_ARCH_IA32 - PushDWord(static_cast(value)); - #else - PushQWord(value); - #endif -} - -void JITCompiler::PushSSizeT(std::int64_t value) -{ - PushSizeT(static_cast(value)); -} - - -/* - * ======= Protected: ======= - */ - -void JITCompiler::Write(const void* data, std::size_t size) -{ - assembly_.reserve(assembly_.size() + size); - auto* byteAlignedData = reinterpret_cast(data); - #if 0 - if (littleEndian_) - { - /* Encode for little endian */ - for_range(i, size) - assembly_.push_back(byteAlignedData[size - i - 1u]); - } - else - #endif - { - /* Encode for big endian */ - for_range(i, size) - assembly_.push_back(byteAlignedData[i]); - } -} - -void JITCompiler::WriteByte(std::uint8_t data) -{ - Write(&data, sizeof(data)); -} - -void JITCompiler::WriteWord(std::uint16_t data) -{ - Write(&data, sizeof(data)); -} - -void JITCompiler::WriteDWord(std::uint32_t data) -{ - Write(&data, sizeof(data)); -} - -void JITCompiler::WriteQWord(std::uint64_t data) -{ - Write(&data, sizeof(data)); -} - -void JITCompiler::WritePtr(const void* data) -{ - Write(&data, sizeof(data)); -} - - -#ifdef LLGL_DEBUG - -void Test1(int x, int8_t b, uint16_t h, uint64_t q, int i5, int i6, int i7, int8_t i8, uint64_t i9) -{ - Log::Printf( - "%s: x = %d, b = %d, h = 0x%04X, q = %" PRIu64 ", i = { %d, %d, %d, %d, %" PRIu64 " }\n", - __FUNCTION__, x, (int)b, (int)h, q, i5, i6, i7, (int)i8, i9 - ); -} - -void Test2(float f, double d) -{ - Log::Printf( - "%s: f = %f, d = %f\n", - __FUNCTION__, (double)f, d - ); -} - -void Call_Test1() -{ - Test1(1, 2, 3, 4, 5, 6, 7, 8, 9); -} - -LLGL_EXPORT void TestJIT1() -{ - #if 0//TEST - //Test2(1.23f, 4.56); - Call_Test1(); - #endif - - auto comp = JITCompiler::Create(); - - comp->EntryPointVarArgs({ JIT::ArgType::DWord, JIT::ArgType::Float, JIT::ArgType::Double }); - - comp->Begin(); - - #if 1 - # if 0 - comp->PushDWord(42); - # else - comp->PushVarArg(0); - # endif - comp->PushByte(-3); - comp->PushWord(0x40); - comp->PushQWord(999999ull); - comp->PushDWord(1); - comp->PushDWord(2); - comp->PushDWord(3); - comp->PushByte(4); - comp->PushQWord(888888ull); - comp->FuncCall(reinterpret_cast(Test1)); - - int a[] = { 1, 2, 3 }; - int b[] = { 4, 5, 6 }; - - comp->PushPtr(b); - comp->PushPtr(a); - comp->PushQWord(sizeof(a)); - comp->FuncCall(reinterpret_cast(::memcpy)); - #endif - - #if 1 - # if 0 - comp->PushFloat(-1.2345f); - comp->PushDouble(3.14); - # else - comp->PushVarArg(1); - comp->PushVarArg(2); - # endif - comp->FuncCall(reinterpret_cast(Test2)); - #endif - - comp->End(); - - auto prog = comp->FlushProgram(); - - prog->GetEntryPoint()(28, 2.3f, 4.5); -} - -#endif // /LLGL_DEBUG - - -} // /namespace LLGL - - - -// ================================================================================ diff --git a/sources/JIT/JITCompiler.h b/sources/JIT/JITCompiler.h deleted file mode 100644 index ea8ec73f47..0000000000 --- a/sources/JIT/JITCompiler.h +++ /dev/null @@ -1,332 +0,0 @@ -/* - * JITCompiler.h - * - * Copyright (c) 2015 Lukas Hermanns. All rights reserved. - * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). - */ - -#ifndef LLGL_JIT_COMPILER_H -#define LLGL_JIT_COMPILER_H - - -#include "JITProgram.h" -#include "AssemblyTypes.h" -#include -#include -#include -#include -#include -#include -#include - - -namespace LLGL -{ - - -// Enumeration for calling conventions. -enum class JITCallConv -{ - CDecl, // '__cdecl' to internal function - StdCall, // '__stdcall' to internal function - ThisCall, // '__thiscall' to internal function -}; - -// Structure to pass a variadic argument via 'JITCompiler::Call' template function. -struct JITVarArg -{ - std::uint8_t index; -}; - -// Structure to pass a stack pointer via to the 'JITCompiler::Call' template function. -struct JITStackPtr -{ - std::uint8_t index; -}; - -// Returns the raw function pointer of the specified member function, e.g. GetMemberFuncPtr(&Foo::Bar). -template -inline const void* GetMemberFuncPtr(T pfn) -{ - union - { - T func; - const void* addr; - } - ptr; - ptr.func = pfn; - return ptr.addr; -} - -// IA-32 (a.k.a. x86) assembly code generator. -class LLGL_EXPORT JITCompiler : public NonCopyable -{ - - public: - - /* - Instantiates a new JIT compiler for the current hardware architecture (i.e. x86, x64, ARM), - or null if the architecture is not supported. - */ - static std::unique_ptr Create(); - - // Dumps the current assembly code to the output stream. - UTF8String DumpAssembly(std::size_t bytesPerLine = 8) const; - - // Flushes the currently build program, or null if no program was build. - std::unique_ptr FlushProgram(); - - public: - - // Stores the parameter list of the secified types for the program entry points (must be called before 'Begin'). - void EntryPointVarArgs(const std::initializer_list& varArgTypes); - - // Stores teh stack allocation for the specified amount of bytes, and returns the ID of this allocation (must be called before 'Begin'). - std::uint8_t StackAlloc(std::uint32_t size); - - // Begins with generating assembly code - virtual void Begin() = 0; - virtual void End() = 0; - - // Pushes the entry point parameter, specified by the zero-based index 'idx', to the argument list. - void PushVarArg(std::uint8_t idx); - - // Pushes the ID of the specified stack allocation, specified by the zero-based index 'idx', to the argument list. - void PushStackPtr(std::uint8_t idx); - - // Pushes the specified value to the argument list for the next function call. - void PushPtr(const void* value); - void PushByte(std::uint8_t value); - void PushWord(std::uint16_t value); - void PushDWord(std::uint32_t value); - void PushQWord(std::uint64_t value); - void PushFloat(float value); - void PushDouble(double value); - void PushSizeT(std::uint64_t value); - void PushSSizeT(std::int64_t value); - - /* - Encodes a function call. - \param[in] addr Specifies the pointer to the native function that is to be called. - \param[in] conv Specifies the calling convention. This is only used for x86 assembly and ignored otherwise. - \param[in] farCall Specifies whether an intersegment function (far call) is to be used. - */ - void FuncCall( - const void* addr, - JITCallConv conv = JITCallConv::CDecl, - bool farCall = false - ); - - /* - Encodes a function call with the specified variadic arguments. - \param[in] func Specifies the function object. This must be a global non-overloaded function. - \param[in] args Specifies the argument list. Only pointers, integrals and floating-point types are allowed (no references). - */ - template - void Call(Func&& func, Args&&... args) - { - PushArgs(std::forward(args)...); - FuncCall(reinterpret_cast(func)); - } - - /* - Encodes a member function call with the specified variadic arguments. - \param[in] func Specifies the function object. This must be a global non-overloaded function. - \param[in] inst Specifies the class instance on which the member function is to be called. - \param[in] args Specifies the argument list. Only pointers, integrals and floating-point types are allowed (no references). - */ - template - void CallMember(Func&& func, Inst&& inst, Args&&... args) - { - PushVariant(std::forward(inst));//TODO: PushThisPtr(inst); - PushArgs(std::forward(args)...); - FuncCall(GetMemberFuncPtr(func)); - } - - protected: - - JITCompiler() = default; - - virtual bool IsLittleEndian() const = 0; - virtual void WriteFuncCall(const void* addr, JITCallConv conv, bool farCall) = 0; - - protected: - - void Write(const void* data, std::size_t size); - void WriteByte(std::uint8_t data); - void WriteWord(std::uint16_t data); - void WriteDWord(std::uint32_t data); - void WriteQWord(std::uint64_t data); - void WritePtr(const void* data); - - protected: - - // Returns the assembly code (constant). - inline const std::vector& GetAssembly() const - { - return assembly_; - } - - // Returns the assembly code. - inline std::vector& GetAssembly() - { - return assembly_; - } - - // Returns the list of function arguments. - inline const std::vector& GetArgs() const - { - return args_; - } - - // Returns the list of entry point variadic arguments. - inline const std::vector& GetEntryVarArgs() const - { - return entryVarArgs_; - } - - // Returns the list of stack allocations. - inline const std::vector& GetStackAllocs() const - { - return stackAllocs_; - } - - private: - - template - inline void PushVariant(T arg); - - template - inline void PushVariant(T* arg); - - template - inline void PushVariant(const T* arg); - - inline void PushVariant(std::nullptr_t); - - template - inline void PushArgsPrimary(Arg0&& arg0); - - template - inline void PushArgsPrimary(Arg0&& arg0, ArgsN&&... argsN); - - template - inline void PushArgs(Args&&... args); - - private: - - bool littleEndian_ = false; - std::vector assembly_; - - std::vector args_; - std::vector entryVarArgs_; - std::vector stackAllocs_; - -}; - - -/* ----- Template implementations ----- */ - -template -inline void JITCompiler::PushVariant(T arg) -{ - switch (sizeof(T)) - { - case 1: - PushByte(static_cast(arg)); - break; - case 2: - PushWord(static_cast(arg)); - break; - case 4: - PushDWord(static_cast(arg)); - break; - case 8: - PushQWord(static_cast(arg)); - break; - } -} - -template -inline void JITCompiler::PushVariant(T* arg) -{ - PushPtr(reinterpret_cast(arg)); -} - -template -inline void JITCompiler::PushVariant(const T* arg) -{ - PushPtr(reinterpret_cast(arg)); -} - -inline void JITCompiler::PushVariant(std::nullptr_t) -{ - PushPtr(nullptr); -} - -// Template specialization -template <> -inline void JITCompiler::PushVariant(float arg) -{ - PushFloat(arg); -} - -// Template specialization -template <> -inline void JITCompiler::PushVariant(double arg) -{ - PushDouble(arg); -} - -// Template specialization -template <> -inline void JITCompiler::PushVariant(JITVarArg arg) -{ - PushVarArg(arg.index); -} - -// Template specialization -template <> -inline void JITCompiler::PushVariant(JITStackPtr arg) -{ - PushStackPtr(arg.index); -} - -template -inline void JITCompiler::PushArgsPrimary(Arg0&& arg0) -{ - PushVariant(arg0); -} - -template -inline void JITCompiler::PushArgsPrimary(Arg0&& arg0, ArgsN&&... argsN) -{ - PushVariant(arg0); - PushArgsPrimary(std::forward(argsN)...); -} - -template -inline void JITCompiler::PushArgs(Args&&... args) -{ - PushArgsPrimary(std::forward(args)...); -} - -template <> -inline void JITCompiler::PushArgs<>() -{ - // do nothing -} - -#ifdef LLGL_DEBUG -LLGL_EXPORT void TestJIT1(); -#endif // /LLGL_DEBUG - - -} // /namespace LLGL - - -#endif - - - -// ================================================================================ diff --git a/sources/JIT/JITProgram.h b/sources/JIT/JITProgram.h deleted file mode 100644 index 970c4bed3b..0000000000 --- a/sources/JIT/JITProgram.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * JITProgram.h - * - * Copyright (c) 2015 Lukas Hermanns. All rights reserved. - * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). - */ - -#ifndef LLGL_JIT_PROGRAM_H -#define LLGL_JIT_PROGRAM_H - - -#include -#include -#include - - -namespace LLGL -{ - - -// Wrapper class for platform dependent native code. -class LLGL_EXPORT JITProgram : public NonCopyable -{ - - public: - - // Function pointer type of the main entry point. - typedef void (*EntryPointPtr)(...); - - public: - - // Creates a new JIT program with the specified code. - static std::unique_ptr Create(const void* code, std::size_t size); - - // Returns the main entry point of the native JIT program. - inline EntryPointPtr GetEntryPoint() const - { - return entryPoint_; - } - - protected: - - JITProgram() = default; - - // Sets the address for the function pointer that can be executed. - inline void SetEntryPoint(void* addr) - { - entryPoint_ = reinterpret_cast(addr); - } - - private: - - EntryPointPtr entryPoint_ = nullptr; - -}; - - -} // /namespace LLGL - - -#endif - - - -// ================================================================================ diff --git a/sources/JIT/Platform/POSIX/POSIXJITProgram.cpp b/sources/JIT/Platform/POSIX/POSIXJITProgram.cpp deleted file mode 100644 index cf34186a65..0000000000 --- a/sources/JIT/Platform/POSIX/POSIXJITProgram.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * POSIXJITProgram.cpp - * - * Copyright (c) 2015 Lukas Hermanns. All rights reserved. - * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). - */ - -#include "POSIXJITProgram.h" -#include "../../../Core/CoreUtils.h" -#include -#include -#include // sysconf -#include // mmap - - -namespace LLGL -{ - - -std::unique_ptr JITProgram::Create(const void* code, std::size_t size) -{ - return MakeUnique(code, size); -} - -POSIXJITProgram::POSIXJITProgram(const void* code, std::size_t size) : - size_ { GetAlignedSize(size, std::size_t(sysconf(_SC_PAGE_SIZE))) } -{ - /* Map executable memory space */ - addr_ = ::mmap( - nullptr, - size_, - (PROT_READ | PROT_WRITE | PROT_EXEC), - (MAP_PRIVATE | MAP_ANONYMOUS), - -1, // must be -1 if MAP_ANONYMOUS is used - 0 - ); - - if (addr_ == MAP_FAILED) - throw std::runtime_error("failed to map executable virtual memory with read/write protection mode"); - - /* Copy code into executable memory space */ - ::memcpy(addr_, code, size); - - /* Set function pointer to executable memory address */ - SetEntryPoint(addr_); -} - -POSIXJITProgram::POSIXJITProgram() -{ - munmap(addr_, size_); -} - - -} // /namespace LLGL - - - -// ================================================================================ diff --git a/sources/JIT/Platform/POSIX/POSIXJITProgram.h b/sources/JIT/Platform/POSIX/POSIXJITProgram.h deleted file mode 100644 index 1c87e54615..0000000000 --- a/sources/JIT/Platform/POSIX/POSIXJITProgram.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * POSIXJITProgram.h - * - * Copyright (c) 2015 Lukas Hermanns. All rights reserved. - * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). - */ - -#ifndef LLGL_POSIX_JIT_PROGRAM_H -#define LLGL_POSIX_JIT_PROGRAM_H - - -#include "../../JITProgram.h" -#include - - -namespace LLGL -{ - - -class LLGL_EXPORT POSIXJITProgram : public JITProgram -{ - - public: - - POSIXJITProgram(const void* code, std::size_t size); - POSIXJITProgram(); - - private: - - void* addr_ = nullptr; - std::size_t size_ = 0; - -}; - - -} // /namespace LLGL - - -#endif - - - -// ================================================================================ diff --git a/sources/JIT/Platform/Win32/Win32JITProgram.cpp b/sources/JIT/Platform/Win32/Win32JITProgram.cpp deleted file mode 100644 index 317d9e13ca..0000000000 --- a/sources/JIT/Platform/Win32/Win32JITProgram.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Win32JITProgram.cpp - * - * Copyright (c) 2015 Lukas Hermanns. All rights reserved. - * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). - */ - -#include "Win32JITProgram.h" -#include "../../../Core/CoreUtils.h" -#include -#include -#include - -#define WIN32_LEAN_AND_MEAN -#include - - -namespace LLGL -{ - - -std::unique_ptr JITProgram::Create(const void* code, std::size_t size) -{ - return MakeUnique(code, size); -} - -Win32JITProgram::Win32JITProgram(const void* code, std::size_t size) : - size_ { size } -{ - /* Allocate chunk of executable memory */ - addr_ = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - if (addr_ == 0) - throw std::runtime_error("failed to allocate " + std::to_string(size) + " byte(s) of executable memory"); - - /* Copy assembly code to executable memory space */ - ::memcpy(addr_, code, size); - - /* Make assembly buffer executable */ - DWORD oldProtect = 0; - if (VirtualProtect(addr_, size, PAGE_EXECUTE_READ, &oldProtect) == 0) - throw std::runtime_error("failed to change virtual memory protection"); - - /* Set function pointer to executable memory address */ - SetEntryPoint(addr_); -} - -Win32JITProgram::~Win32JITProgram() -{ - VirtualFree(addr_, 0, MEM_RELEASE); -} - - -} // /namespace LLGL - - - -// ================================================================================ diff --git a/sources/JIT/Platform/Win32/Win32JITProgram.h b/sources/JIT/Platform/Win32/Win32JITProgram.h deleted file mode 100644 index e9f09aa3f9..0000000000 --- a/sources/JIT/Platform/Win32/Win32JITProgram.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Win32JITProgram.h - * - * Copyright (c) 2015 Lukas Hermanns. All rights reserved. - * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). - */ - -#ifndef LLGL_WIN32_JIT_PROGRAM_H -#define LLGL_WIN32_JIT_PROGRAM_H - - -#include "../../JITProgram.h" -#include -#include - - -namespace LLGL -{ - - -// Wrapper class for platform dependent native code. -class LLGL_EXPORT Win32JITProgram : public JITProgram -{ - - public: - - Win32JITProgram(const void* code, std::size_t size); - ~Win32JITProgram(); - - private: - - void* addr_ = nullptr; - std::size_t size_ = 0; - -}; - - -} // /namespace LLGL - - -#endif - - - -// ================================================================================ diff --git a/sources/Renderer/OpenGL/Command/GLCommandAssembler.cpp b/sources/Renderer/OpenGL/Command/GLCommandAssembler.cpp deleted file mode 100644 index 17026e5a6b..0000000000 --- a/sources/Renderer/OpenGL/Command/GLCommandAssembler.cpp +++ /dev/null @@ -1,527 +0,0 @@ -/* - * GLCommandAssembler.cpp - * - * Copyright (c) 2015 Lukas Hermanns. All rights reserved. - * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). - */ - -#ifdef LLGL_ENABLE_JIT_COMPILER - -#include "GLCommandAssembler.h" -#include "GLCommandExecutor.h" -#include "GLCommand.h" -#include "GLDeferredCommandBuffer.h" -#include "../../../JIT/JITCompiler.h" - -#include "../GLSwapChain.h" -#include "../GLTypes.h" -#include "../GLCore.h" -#include "../Ext/GLExtensions.h" -#include "../Ext/GLExtensionRegistry.h" -#include "../../CheckedCast.h" -#include "../../../Core/Assertion.h" - -#include "../Shader/GLShaderProgram.h" -#include "../Shader/GLShaderUniform.h" - -#include "../Texture/GLTexture.h" -#include "../Texture/GLRenderTarget.h" -#include "../Texture/GLMipGenerator.h" -#include "../Texture/GLFramebufferCapture.h" -#ifdef LLGL_GL_ENABLE_OPENGL2X -# include "../Texture/GL2XSampler.h" -#endif - -#include "../Buffer/GLBufferWithVAO.h" -#include "../Buffer/GLBufferArrayWithVAO.h" - -#include "../RenderState/GLStateManager.h" -#include "../RenderState/GLGraphicsPSO.h" -#include "../RenderState/GLResourceHeap.h" -#include "../RenderState/GLRenderPass.h" -#include "../RenderState/GLQueryHeap.h" - -#include - - -namespace LLGL -{ - - -static std::size_t AssembleGLCommand(const GLOpcode opcode, const void* pc, JITCompiler& compiler) -{ - /* Declare index of variadic argument of entry point */ - static const JITVarArg g_stateMngrArg{ 0 }; - - /* Generate native CPU opcodes for emulated GLOpcode */ - switch (opcode) - { - case GLOpcodeBufferSubData: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLBuffer::BufferSubData, cmd->buffer, cmd->offset, cmd->size, (cmd + 1)); - return (sizeof(*cmd) + cmd->size); - } - case GLOpcodeCopyBufferSubData: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLBuffer::CopyBufferSubData, cmd->writeBuffer, cmd->readBuffer, cmd->readOffset, cmd->writeOffset, cmd->size); - return sizeof(*cmd); - } - case GLOpcodeClearBufferData: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLBuffer::ClearBufferData, cmd->buffer, cmd->data); - return sizeof(*cmd); - } - case GLOpcodeClearBufferSubData: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLBuffer::ClearBufferSubData, cmd->buffer, cmd->offset, cmd->size, cmd->data); - return sizeof(*cmd); - } - case GLOpcodeCopyImageSubData: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLTexture::CopyImageSubData, cmd->dstTexture, cmd->dstLevel, &(cmd->dstOffset), cmd->srcTexture, cmd->srcLevel, &(cmd->srcOffset), &(cmd->extent)); - return sizeof(*cmd); - } - case GLOpcodeCopyImageToBuffer: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLTexture::CopyImageToBuffer, cmd->texture, &(cmd->region), cmd->bufferID, cmd->offset, cmd->size, cmd->rowLength, cmd->imageHeight); - return sizeof(*cmd); - } - case GLOpcodeCopyImageFromBuffer: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLTexture::CopyImageFromBuffer, cmd->texture, &(cmd->region), cmd->bufferID, cmd->offset, cmd->size, cmd->rowLength, cmd->imageHeight); - return sizeof(*cmd); - } - case GLOpcodeCopyFramebufferSubData: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLFramebufferCapture::CaptureFramebuffer, &(GLFramebufferCapture::Get()), g_stateMngrArg, cmd->dstTexture, cmd->dstLevel, &(cmd->dstOffset), &(cmd->srcOffset), &(cmd->extent)); - return sizeof(*cmd); - } - case GLOpcodeGenerateMipmap: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLMipGenerator::GenerateMipsForTexture, &(GLMipGenerator::Get()), g_stateMngrArg, cmd->texture); - return sizeof(*cmd); - } - case GLOpcodeGenerateMipmapSubresource: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLMipGenerator::GenerateMipsRangeForTexture, &(GLMipGenerator::Get()), g_stateMngrArg, cmd->texture, cmd->baseMipLevel, cmd->numMipLevels, cmd->baseArrayLayer, cmd->numArrayLayers); - return sizeof(*cmd); - } - case GLOpcodeExecute: - { - auto cmd = reinterpret_cast(pc); - compiler.Call(ExecuteGLDeferredCommandBuffer, cmd->commandBuffer, g_stateMngrArg); - return sizeof(*cmd); - } - case GLOpcodeViewport: - { - auto cmd = reinterpret_cast(pc); - { - compiler.CallMember(&GLStateManager::SetViewport, g_stateMngrArg, &(cmd->viewport)); - compiler.CallMember(&GLStateManager::SetDepthRange, g_stateMngrArg, &(cmd->depthRange)); - } - return sizeof(*cmd); - } - case GLOpcodeViewportArray: - { - auto cmd = reinterpret_cast(pc); - auto cmdData = reinterpret_cast(cmd + 1); - { - compiler.CallMember(&GLStateManager::SetViewportArray, g_stateMngrArg, cmd->first, cmd->count, cmdData); - compiler.CallMember(&GLStateManager::SetDepthRangeArray, g_stateMngrArg, cmd->first, cmd->count, (cmdData + sizeof(GLViewport)*cmd->count)); - } - return (sizeof(*cmd) + sizeof(GLViewport)*cmd->count + sizeof(GLDepthRange)*cmd->count); - } - case GLOpcodeScissor: - { - auto cmd = reinterpret_cast(pc); - { - compiler.CallMember(&GLStateManager::SetScissor, g_stateMngrArg, &(cmd->scissor)); - } - return sizeof(*cmd); - } - case GLOpcodeScissorArray: - { - auto cmd = reinterpret_cast(pc); - auto cmdData = reinterpret_cast(cmd + 1); - { - compiler.CallMember(&GLStateManager::SetScissorArray, g_stateMngrArg, cmd->first, cmd->count, cmdData); - } - return (sizeof(*cmd) + sizeof(GLScissor)*cmd->count); - } - case GLOpcodeClearColor: - { - auto cmd = reinterpret_cast(pc); - compiler.Call(glClearColor, cmd->color[0], cmd->color[1], cmd->color[2], cmd->color[3]); - return sizeof(*cmd); - } - case GLOpcodeClearDepth: - { - auto cmd = reinterpret_cast(pc); - compiler.Call(GLProfile::ClearDepth, cmd->depth); - return sizeof(*cmd); - } - case GLOpcodeClearStencil: - { - auto cmd = reinterpret_cast(pc); - compiler.Call(glClearStencil, cmd->stencil); - return sizeof(*cmd); - } - case GLOpcodeClear: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLStateManager::Clear, g_stateMngrArg, cmd->flags); - return sizeof(*cmd); - } - case GLOpcodeClearAttachmentsWithRenderPass: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLStateManager::ClearAttachmentsWithRenderPass, g_stateMngrArg, cmd->renderPass, cmd->numClearValues, (cmd + 1)); - return (sizeof(*cmd) + sizeof(ClearValue)*cmd->numClearValues); - } - case GLOpcodeClearBuffers: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLStateManager::ClearBuffers, g_stateMngrArg, cmd->numAttachments, (cmd + 1)); - return sizeof(*cmd); - } - case GLOpcodeResolveRenderTarget: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLRenderTarget::ResolveMultisampled, cmd->renderTarget, g_stateMngrArg); - return sizeof(*cmd); - } - case GLOpcodeBindVertexArray: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLSharedContextVertexArray::Bind, cmd->vertexArray, g_stateMngrArg); - return sizeof(*cmd); - } - case GLOpcodeBindElementArrayBufferToVAO: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLStateManager::BindElementArrayBufferToVAO, g_stateMngrArg, cmd->id, cmd->indexType16Bits); - return sizeof(*cmd); - } - case GLOpcodeBindBufferBase: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLStateManager::BindBufferBase, g_stateMngrArg, cmd->target, cmd->index, cmd->id); - return sizeof(*cmd); - } - case GLOpcodeBindBuffersBase: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLStateManager::BindBuffersBase, g_stateMngrArg, cmd->target, cmd->first, cmd->count, (cmd + 1)); - return (sizeof(*cmd) + sizeof(GLuint)*cmd->count); - } - case GLOpcodeBeginTransformFeedback: - { - auto cmd = reinterpret_cast(pc); - compiler.Call(glBeginTransformFeedback, cmd->primitiveMove); - return sizeof(*cmd); - } - #ifdef GL_NV_transform_feedback - case GLOpcodeBeginTransformFeedbackNV: - { - auto cmd = reinterpret_cast(pc); - compiler.Call(glBeginTransformFeedbackNV, cmd->primitiveMove); - return sizeof(*cmd); - } - #endif // /GL_NV_transform_feedback - case GLOpcodeEndTransformFeedback: - { - compiler.Call(glEndTransformFeedback); - return 0; - } - #ifdef GL_NV_transform_feedback - case GLOpcodeEndTransformFeedbackNV: - { - compiler.Call(glEndTransformFeedbackNV); - return 0; - } - #endif // /GL_NV_transform_feedback - case GLOpcodeBindResourceHeap: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLResourceHeap::Bind, cmd->resourceHeap, g_stateMngrArg, cmd->descriptorSet); - return sizeof(*cmd); - } - case GLOpcodeBindRenderTarget: - { - //TODO: update reference to GLStateManager; find better way to update g_stateMngrArg (2nd parameter) - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLStateManager::BindRenderTarget, g_stateMngrArg, cmd->renderTarget, nullptr); - return sizeof(*cmd); - } - case GLOpcodeBindPipelineState: - { - auto cmd = reinterpret_cast(pc); - if (cmd->pipelineState->IsGraphicsPSO()) - compiler.CallMember(&GLGraphicsPSO::Bind, cmd->pipelineState, g_stateMngrArg); - else - compiler.CallMember(&GLPipelineState::Bind, cmd->pipelineState, g_stateMngrArg); - return sizeof(*cmd); - } - case GLOpcodeSetBlendColor: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLStateManager::SetBlendColor, g_stateMngrArg, cmd->color); - return sizeof(*cmd); - } - case GLOpcodeSetStencilRef: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLStateManager::SetStencilRef, g_stateMngrArg, cmd->ref, cmd->face); - return sizeof(*cmd); - } - case GLOpcodeSetUniform: - { - auto cmd = reinterpret_cast(pc); - compiler.Call(GLSetUniform, cmd->type, cmd->location, cmd->count, (cmd + 1)); - return (sizeof(*cmd) + cmd->size); - } - case GLOpcodeBeginQuery: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLQueryHeap::Begin, cmd->queryHeap, cmd->query); - return sizeof(*cmd); - } - case GLOpcodeEndQuery: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLQueryHeap::End, cmd->queryHeap); - return sizeof(*cmd); - } - case GLOpcodeBeginConditionalRender: - { - auto cmd = reinterpret_cast(pc); - compiler.Call(glBeginConditionalRender, cmd->id, cmd->mode); - return sizeof(*cmd); - } - case GLOpcodeEndConditionalRender: - { - compiler.Call(glEndConditionalRender); - return 0; - } - case GLOpcodeDrawArrays: - { - auto cmd = reinterpret_cast(pc); - compiler.Call(glDrawArrays, cmd->mode, cmd->first, cmd->count); - return sizeof(*cmd); - } - case GLOpcodeDrawArraysInstanced: - { - auto cmd = reinterpret_cast(pc); - compiler.Call(glDrawArraysInstanced, cmd->mode, cmd->first, cmd->count, cmd->instancecount); - return sizeof(*cmd); - } - #ifdef GL_ARB_base_instance - case GLOpcodeDrawArraysInstancedBaseInstance: - { - auto cmd = reinterpret_cast(pc); - compiler.Call(glDrawArraysInstancedBaseInstance, cmd->mode, cmd->first, cmd->count, cmd->instancecount, cmd->baseinstance); - return sizeof(*cmd); - } - #endif // /GL_ARB_base_instance - case GLOpcodeDrawArraysIndirect: - { - //TODO: generate loop in ASM - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLStateManager::BindBuffer, g_stateMngrArg, GLBufferTarget::DrawIndirectBuffer, cmd->id); - GLintptr offset = cmd->indirect; - for (std::uint32_t i = 0; i < cmd->numCommands; ++i) - { - compiler.Call(glDrawArraysIndirect, cmd->mode, reinterpret_cast(offset)); - offset += cmd->stride; - } - return sizeof(*cmd); - } - case GLOpcodeDrawElements: - { - auto cmd = reinterpret_cast(pc); - compiler.Call(glDrawElements, cmd->mode, cmd->count, cmd->type, cmd->indices); - return sizeof(*cmd); - } - case GLOpcodeDrawElementsBaseVertex: - { - auto cmd = reinterpret_cast(pc); - compiler.Call(glDrawElementsBaseVertex, cmd->mode, cmd->count, cmd->type, cmd->indices, cmd->basevertex); - return sizeof(*cmd); - } - case GLOpcodeDrawElementsInstanced: - { - auto cmd = reinterpret_cast(pc); - compiler.Call(glDrawElementsInstanced, cmd->mode, cmd->count, cmd->type, cmd->indices, cmd->instancecount); - return sizeof(*cmd); - } - case GLOpcodeDrawElementsInstancedBaseVertex: - { - auto cmd = reinterpret_cast(pc); - compiler.Call(glDrawElementsInstancedBaseVertex, cmd->mode, cmd->count, cmd->type, cmd->indices, cmd->instancecount, cmd->basevertex); - return sizeof(*cmd); - } - #ifdef GL_ARB_base_instance - case GLOpcodeDrawElementsInstancedBaseVertexBaseInstance: - { - auto cmd = reinterpret_cast(pc); - compiler.Call(glDrawElementsInstancedBaseVertexBaseInstance, cmd->mode, cmd->count, cmd->type, cmd->indices, cmd->instancecount, cmd->basevertex, cmd->baseinstance); - return sizeof(*cmd); - } - #endif // /GL_ARB_base_instance - case GLOpcodeDrawElementsIndirect: - { - auto cmd = reinterpret_cast(pc); - { - //TODO: generate loop in ASM - compiler.CallMember(&GLStateManager::BindBuffer, g_stateMngrArg, GLBufferTarget::DrawIndirectBuffer, cmd->id); - GLintptr offset = cmd->indirect; - for (std::uint32_t i = 0; i < cmd->numCommands; ++i) - { - compiler.Call(glDrawElementsIndirect, cmd->mode, cmd->type, reinterpret_cast(offset)); - offset += cmd->stride; - } - } - return sizeof(*cmd); - } - #ifdef GL_ARB_multi_draw_indirect - case GLOpcodeMultiDrawArraysIndirect: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLStateManager::BindBuffer, g_stateMngrArg, GLBufferTarget::DrawIndirectBuffer, cmd->id); - compiler.Call(glMultiDrawArraysIndirect, cmd->mode, cmd->indirect, cmd->drawcount, cmd->stride); - return sizeof(*cmd); - } - case GLOpcodeMultiDrawElementsIndirect: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLStateManager::BindBuffer, g_stateMngrArg, GLBufferTarget::DrawIndirectBuffer, cmd->id); - compiler.Call(glMultiDrawElementsIndirect, cmd->mode, cmd->type, cmd->indirect, cmd->drawcount, cmd->stride); - return sizeof(*cmd); - } - #endif // /GL_ARB_multi_draw_indirect - #ifdef GL_ARB_compute_shader - case GLOpcodeDispatchCompute: - { - auto cmd = reinterpret_cast(pc); - compiler.Call(glDispatchCompute, cmd->numgroups[0], cmd->numgroups[1], cmd->numgroups[2]); - return sizeof(*cmd); - } - case GLOpcodeDispatchComputeIndirect: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLStateManager::BindBuffer, g_stateMngrArg, GLBufferTarget::DispatchIndirectBuffer, cmd->id); - compiler.Call(glDispatchComputeIndirect, cmd->indirect); - return sizeof(*cmd); - } - #endif // /GL_ARB_compute_shader - case GLOpcodeBindTexture: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLStateManager::ActiveTexture, g_stateMngrArg, cmd->slot); - compiler.CallMember(&GLStateManager::BindGLTexture, g_stateMngrArg, cmd->texture); - return sizeof(*cmd); - } - case GLOpcodeBindImageTexture: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLStateManager::BindImageTexture, g_stateMngrArg, cmd->unit, cmd->level, cmd->format, cmd->texture); - return sizeof(*cmd); - } - case GLOpcodeBindSampler: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLStateManager::BindSampler, g_stateMngrArg, cmd->layer, cmd->sampler); - return sizeof(*cmd); - } - #ifdef LLGL_GL_ENABLE_OPENGL2X - case GLOpcodeBindGL2XSampler: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLStateManager::BindGL2XSampler, g_stateMngrArg, cmd->layer, cmd->samplerGL2X); - return sizeof(*cmd); - } - #endif - #ifdef LLGL_GLEXT_MEMORY_BARRIERS - case GLOpcodeMemoryBarrier: - { - auto cmd = reinterpret_cast(pc); - compiler.Call(glMemoryBarrier, cmd->barriers); - return sizeof(*cmd); - } - #endif - #if LLGL_GLEXT_DEBUG - case GLOpcodePushDebugGroup: - { - auto cmd = reinterpret_cast(pc); - compiler.Call(glPushDebugGroup, cmd->source, cmd->id, cmd->length, reinterpret_cast(cmd + 1)); - return (sizeof(*cmd) + cmd->length + 1); - } - case GLOpcodePopDebugGroup: - { - compiler.Call(glPopDebugGroup); - return 0; - } - #endif // /LLGL_GLEXT_DEBUG - default: - return 0; - } -} - -// Determines the maximum requried stack size to execute the specified command buffer natively -static std::size_t RequiredLocalStackSize(const GLDeferredCommandBuffer& cmdBuffer) -{ - std::size_t maxSize = 0; - - maxSize = cmdBuffer.GetMaxNumViewports() * sizeof(GLViewport); - maxSize = std::max(maxSize, cmdBuffer.GetMaxNumViewports() * sizeof(GLDepthRange)); - maxSize = std::max(maxSize, cmdBuffer.GetMaxNumScissors() * sizeof(GLScissor)); - - return maxSize; -} - -std::unique_ptr AssembleGLDeferredCommandBuffer(const GLDeferredCommandBuffer& cmdBuffer) -{ - /* Try to create a JIT-compiler for the active architecture (if supported) */ - if (std::unique_ptr compiler = JITCompiler::Create()) - { - /* Declare variadic arguments for entry point of JIT program */ - compiler->EntryPointVarArgs({ JIT::ArgType::Ptr }); - - /* Declare stack allocation for temporary storage (viewports and scissors) */ - auto stackSize = static_cast(RequiredLocalStackSize(cmdBuffer)); - if (stackSize > 0) - compiler->StackAlloc(stackSize); - - /* Assemble GL commands into JIT program */ - compiler->Begin(); - { - const GLVirtualCommandBuffer& virtualCmdBuffer = cmdBuffer.GetVirtualCommandBuffer(); - virtualCmdBuffer.Run(AssembleGLCommand, *compiler); - } - compiler->End(); - - /* Build final program */ - return compiler->FlushProgram(); - } - return nullptr; -} - - -} // /namespace LLGL - - -#endif // /LLGL_ENABLE_JIT_COMPILER - - - -// ================================================================================ diff --git a/sources/Renderer/OpenGL/Command/GLCommandAssembler.h b/sources/Renderer/OpenGL/Command/GLCommandAssembler.h deleted file mode 100644 index a1deeeae5d..0000000000 --- a/sources/Renderer/OpenGL/Command/GLCommandAssembler.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * GLCommandAssembler.h - * - * Copyright (c) 2015 Lukas Hermanns. All rights reserved. - * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). - */ - -#ifndef LLGL_GL_COMMAND_ASSEMBLER_H -#define LLGL_GL_COMMAND_ASSEMBLER_H - -#ifdef LLGL_ENABLE_JIT_COMPILER - - -#include - - -namespace LLGL -{ - - -class JITProgram; -class GLDeferredCommandBuffer; - -std::unique_ptr AssembleGLDeferredCommandBuffer(const GLDeferredCommandBuffer& cmdbuffer); - - -} // /namespace LLGL - - -#endif // /LLGL_ENABLE_JIT_COMPILER - -#endif - - - -// ================================================================================ diff --git a/sources/Renderer/OpenGL/Command/GLCommandExecutor.cpp b/sources/Renderer/OpenGL/Command/GLCommandExecutor.cpp index 30069434ca..2de42ce880 100644 --- a/sources/Renderer/OpenGL/Command/GLCommandExecutor.cpp +++ b/sources/Renderer/OpenGL/Command/GLCommandExecutor.cpp @@ -38,10 +38,6 @@ #include #include -#ifdef LLGL_ENABLE_JIT_COMPILER -# include "../../../JIT/JITProgram.h" -#endif - #include @@ -492,30 +488,10 @@ static void ExecuteGLCommandsEmulated(const GLVirtualCommandBuffer& virtualCmdBu virtualCmdBuffer.Run(ExecuteGLCommand, stateMngr); } -#ifdef LLGL_ENABLE_JIT_COMPILER - -static void ExecuteGLCommandsNatively(const JITProgram& exec, GLStateManager& stateMngr) -{ - /* Execute native program and pass pointer to state manager */ - exec.GetEntryPoint()(&stateMngr); -} - -#endif // /LLGL_ENABLE_JIT_COMPILER - void ExecuteGLDeferredCommandBuffer(const GLDeferredCommandBuffer& cmdBuffer, GLStateManager& stateMngr) { - #ifdef LLGL_ENABLE_JIT_COMPILER - if (auto exec = cmdBuffer.GetExecutable().get()) - { - /* Execute GL commands with native executable */ - ExecuteGLCommandsNatively(*exec, stateMngr); - } - else - #endif // /LLGL_ENABLE_JIT_COMPILER - { - /* Emulate execution of GL commands */ - ExecuteGLCommandsEmulated(cmdBuffer.GetVirtualCommandBuffer(), &stateMngr); - } + /* Emulate execution of GL commands */ + ExecuteGLCommandsEmulated(cmdBuffer.GetVirtualCommandBuffer(), &stateMngr); } void ExecuteGLCommandBuffer(const GLCommandBuffer& cmdBuffer, GLStateManager& stateMngr) diff --git a/sources/Renderer/OpenGL/Command/GLDeferredCommandBuffer.cpp b/sources/Renderer/OpenGL/Command/GLDeferredCommandBuffer.cpp index 33c99b2742..bf4222cd7f 100644 --- a/sources/Renderer/OpenGL/Command/GLDeferredCommandBuffer.cpp +++ b/sources/Renderer/OpenGL/Command/GLDeferredCommandBuffer.cpp @@ -41,10 +41,6 @@ #include #include // std::strlen -#ifdef LLGL_ENABLE_JIT_COMPILER -# include "GLCommandAssembler.h" -#endif // /LLGL_ENABLE_JIT_COMPILER - namespace LLGL { @@ -63,32 +59,13 @@ void GLDeferredCommandBuffer::Begin() /* Reset internal command buffer */ buffer_.Clear(); ResetRenderState(); - - #ifdef LLGL_ENABLE_JIT_COMPILER - - /* Reset states relevant to the GL command assembler */ - executable_.reset(); - maxNumViewports_ = 0; - maxNumScissors_ = 0; - - #endif // /LLGL_ENABLE_JIT_COMPILER } void GLDeferredCommandBuffer::End() { - #ifdef LLGL_ENABLE_JIT_COMPILER - - /* Generate native assembly only if command buffer will be submitted multiple times */ - if ((GetFlags() & CommandBufferFlags::MultiSubmit) != 0) - executable_ = AssembleGLDeferredCommandBuffer(*this); - - #else - /* Pack virtual command buffer if it has to be traversed multiple times */ if ((GetFlags() & CommandBufferFlags::MultiSubmit) != 0) buffer_.Pack(); - - #endif // /LLGL_ENABLE_JIT_COMPILER } void GLDeferredCommandBuffer::Execute(CommandBuffer& secondaryCommandBuffer) @@ -274,10 +251,6 @@ void GLDeferredCommandBuffer::GenerateMips(Texture& texture, const TextureSubres void GLDeferredCommandBuffer::SetViewport(const Viewport& viewport) { - #ifdef LLGL_ENABLE_JIT_COMPILER - maxNumViewports_ = std::max(maxNumViewports_, 1u); - #endif // /LLGL_ENABLE_JIT_COMPILER - auto cmd = AllocCommand(GLOpcodeViewport); { cmd->viewport = GLViewport{ viewport.x, viewport.y, viewport.width, viewport.height }; @@ -290,10 +263,6 @@ void GLDeferredCommandBuffer::SetViewports(std::uint32_t numViewports, const Vie /* Clamp number of viewports to limit */ numViewports = std::min(numViewports, LLGL_MAX_NUM_VIEWPORTS_AND_SCISSORS); - #ifdef LLGL_ENABLE_JIT_COMPILER - maxNumViewports_ = std::max(maxNumViewports_, numViewports); - #endif // /LLGL_ENABLE_JIT_COMPILER - /* Encode GL command */ auto cmd = AllocCommand(GLOpcodeViewportArray, (sizeof(GLViewport) + sizeof(GLDepthRange))*numViewports); { @@ -320,10 +289,6 @@ void GLDeferredCommandBuffer::SetViewports(std::uint32_t numViewports, const Vie void GLDeferredCommandBuffer::SetScissor(const Scissor& scissor) { - #ifdef LLGL_ENABLE_JIT_COMPILER - maxNumScissors_ = std::max(maxNumScissors_, 1u); - #endif // /LLGL_ENABLE_JIT_COMPILER - auto cmd = AllocCommand(GLOpcodeScissor); cmd->scissor = GLScissor{ scissor.x, scissor.y, scissor.width, scissor.height }; } @@ -333,10 +298,6 @@ void GLDeferredCommandBuffer::SetScissors(std::uint32_t numScissors, const Sciss /* Clamp number of scissors to limit */ numScissors = std::min(numScissors, LLGL_MAX_NUM_VIEWPORTS_AND_SCISSORS); - #ifdef LLGL_ENABLE_JIT_COMPILER - maxNumScissors_ = std::max(maxNumScissors_, numScissors); - #endif // /LLGL_ENABLE_JIT_COMPILER - /* Encode GL command */ auto cmd = AllocCommand(GLOpcodeScissorArray, sizeof(GLScissor)*numScissors); { diff --git a/sources/Renderer/OpenGL/Command/GLDeferredCommandBuffer.h b/sources/Renderer/OpenGL/Command/GLDeferredCommandBuffer.h index a9ef02e300..08de0261aa 100644 --- a/sources/Renderer/OpenGL/Command/GLDeferredCommandBuffer.h +++ b/sources/Renderer/OpenGL/Command/GLDeferredCommandBuffer.h @@ -15,10 +15,6 @@ #include #include -#ifdef LLGL_ENABLE_JIT_COMPILER -# include "../../../JIT/JITProgram.h" -#endif - namespace LLGL { @@ -70,28 +66,6 @@ class GLDeferredCommandBuffer final : public GLCommandBuffer return flags_; } - #ifdef LLGL_ENABLE_JIT_COMPILER - - // Returns the just-in-time compiled command buffer that can be executed natively, or null if not available. - inline const std::unique_ptr& GetExecutable() const - { - return executable_; - } - - // Returns the maximum number of viewports that are set in this command buffer. - inline std::uint32_t GetMaxNumViewports() const - { - return maxNumViewports_; - } - - // Returns the maximum number of scissors that are set in this command buffer. - inline std::uint32_t GetMaxNumScissors() const - { - return maxNumScissors_; - } - - #endif // /LLGL_ENABLE_JIT_COMPILER - private: void BindBufferBase(const GLBufferTarget bufferTarget, const GLBuffer& bufferGL, std::uint32_t slot); @@ -114,15 +88,9 @@ class GLDeferredCommandBuffer final : public GLCommandBuffer private: - long flags_ = 0; - GLVirtualCommandBuffer buffer_; - GLRenderTarget* renderTargetToResolve_ = nullptr; - - #ifdef LLGL_ENABLE_JIT_COMPILER - std::unique_ptr executable_; - std::uint32_t maxNumViewports_ = 0; - std::uint32_t maxNumScissors_ = 0; - #endif // /LLGL_ENABLE_JIT_COMPILER + long flags_ = 0; + GLVirtualCommandBuffer buffer_; + GLRenderTarget* renderTargetToResolve_ = nullptr; }; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ae10cbe3ec..f8bb1079da 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -18,7 +18,6 @@ find_project_source_files( FilesTest_Compute "${TEST_PROJECTS_DIR}/Te find_project_source_files( FilesTest_D3D12 "${TEST_PROJECTS_DIR}/Test_D3D12.cpp" ) find_project_source_files( FilesTest_Display "${TEST_PROJECTS_DIR}/Test_Display.cpp" ) find_project_source_files( FilesTest_Image "${TEST_PROJECTS_DIR}/Test_Image.cpp" ) -find_project_source_files( FilesTest_JIT "${TEST_PROJECTS_DIR}/Test_JIT.cpp" ) find_project_source_files( FilesTest_Metal "${TEST_PROJECTS_DIR}/Test_Metal.cpp" ) find_project_source_files( FilesTest_OpenGL "${TEST_PROJECTS_DIR}/Test_OpenGL.cpp" ) find_project_source_files( FilesTest_Performance "${TEST_PROJECTS_DIR}/Test_Performance.cpp" ) @@ -60,7 +59,6 @@ if(LLGL_BUILD_TESTS) add_llgl_example_project(Test_Compute CXX "${FilesTest_Compute}" "${LLGL_MODULE_LIBS}") add_llgl_example_project(Test_Display CXX "${FilesTest_Display}" "${LLGL_MODULE_LIBS}") add_llgl_example_project(Test_Image CXX "${FilesTest_Image}" "${LLGL_MODULE_LIBS}") - add_llgl_example_project(Test_JIT CXX "${FilesTest_JIT}" "${LLGL_MODULE_LIBS}") add_llgl_example_project(Test_Performance CXX "${FilesTest_Performance}" "${LLGL_MODULE_LIBS}") add_llgl_example_project(Test_SeparateShaders CXX "${FilesTest_SeparateShaders}" "${LLGL_MODULE_LIBS}") add_llgl_example_project(Test_ShaderReflect CXX "${FilesTest_ShaderReflect}" "${LLGL_MODULE_LIBS}") diff --git a/tests/Test_JIT.cpp b/tests/Test_JIT.cpp deleted file mode 100644 index f539246b16..0000000000 --- a/tests/Test_JIT.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Test_JIT.cpp - * - * Copyright (c) 2015 Lukas Hermanns. All rights reserved. - * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). - */ - -#include -#include - - -#if defined LLGL_ENABLE_JIT_COMPILER && defined LLGL_DEBUG - -namespace LLGL -{ -LLGL_EXPORT void TestJIT1(); -} - - -int main() -{ - try - { - LLGL::TestJIT1(); - } - catch (const std::exception& e) - { - ::fprintf(stderr, "%s\n", e.what()); - } - - return 0; -} - -#else // LLGL_ENABLE_JIT_COMPILER - -int main() -{ - ::fprintf(stderr, "LLGL was not compiled with LLGL_ENABLE_JIT_COMPILER\n"); - return 0; -} - -#endif // /LLGL_ENABLE_JIT_COMPILER