diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ae5b0f5..e589cf5 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -14,45 +14,31 @@ jobs:
matrix:
dotnet-version: ['6.0.x']
platform:
- - {arch: 'x86', dir: 'x32'}
- - {arch: 'x64', dir: 'x64'}
+ - {build: 'Win32', arch: 'x32'}
+ - {build: 'x64', arch: 'x64'}
env:
CONFIGURATION: Release
PLATFORM: ${{ matrix.platform.arch }}
steps:
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
- name: Add msbuild to PATH
- uses: microsoft/setup-msbuild@v1.0.2
- - name: Nuget dependencies
- run: |
- cd src
- msbuild Dotx64Dbg.sln -t:restore -p:RestorePackagesConfig=true -maxcpucount:2 /m
- IF %ERRORLEVEL% NEQ 0 (
- ECHO MSBuild for Debug x64 returned error code %ERRORLEVEL%
- EXIT /B %ERRORLEVEL%
- )
- cd ..
+ uses: microsoft/setup-msbuild@v1.3
- name: Build
run: |
- cd src
- msbuild Dotx64Dbg.sln /p:platform=${{ matrix.platform.arch }} /m
- IF %ERRORLEVEL% NEQ 0 (
- ECHO MSBuild for Debug x64 returned error code %ERRORLEVEL%
- EXIT /B %ERRORLEVEL%
- )
- cd ..
+ cmake . -B build -DCMAKE_BUILD_TYPE=Release -A ${{ matrix.platform.build }}
+ cmake --build build --config Release
- name: Tests
run: |
pushd .
- cd bin\${{ matrix.platform.dir }}\tests
- Tests.exe
+ cd bin\${{ matrix.platform.arch }}\tests
+ Dotx64DbgTests.exe
popd
- name: Upload artifacts (CI)
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v3
with:
name: dotx64Dbg-${{ runner.os }}-${{ matrix.platform.arch }}
- path: bin
+ path: bin/
if-no-files-found: error
package:
needs: build
@@ -60,7 +46,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Fetch artifacts
- uses: actions/download-artifact@v2
+ uses: actions/download-artifact@v3
with:
path: artifacts
- name: Display structure of downloaded files
@@ -70,22 +56,28 @@ jobs:
- name: Merge artifacts
shell: bash
run: |
- mkdir package
- cp -R -n ./artifacts/dotx64Dbg-Windows-x64/* ./package/
- cp -R -n ./artifacts/dotx64Dbg-Windows-x86/* ./package/
- rm -R ./package/x32/tests
- rm -R ./package/x64/tests
+ mkdir -p package/x64/plugins/Dotx64Dbg
+ mkdir -p package/x32/plugins/Dotx64Dbg
+ mkdir package/dotplugins
+ mkdir package/dotscripts
+ rm -R ./artifacts/dotx64Dbg-Windows-x32/x32/tests
+ rm -R ./artifacts/dotx64Dbg-Windows-x64/x64/tests
+ cp -R -n ./artifacts/dotx64Dbg-Windows-x64/x64/* ./package/x64/plugins/Dotx64Dbg
+ cp -R -n ./artifacts/dotx64Dbg-Windows-x32/x32/* ./package/x32/plugins/Dotx64Dbg
+ cp -R -n ./artifacts/dotx64Dbg-Windows-x32/dotplugins/* ./package/dotplugins/
+ cp -R -n ./artifacts/dotx64Dbg-Windows-x32/dotscripts/* ./package/dotscripts/
+ cp -R -n ./artifacts/dotx64Dbg-Windows-x32/dotx64dbg.json ./package/dotx64dbg.json
find ./package -type f -name '*.pdb' -delete
find ./package -type f -name '*.lib' -delete
find ./package -type f -name '*.exp' -delete
find ./package -type f -name '*.ilk' -delete
- name: Upload package (CI)
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v3
with:
name: dotx64dbg
path: package
if-no-files-found: error
- - name: Compress artifacts
+ - name: Compress package
uses: papeloto/action-zip@v1
if: ${{ startsWith(github.ref, 'refs/tags/') }}
with:
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..27133ae
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,598 @@
+# This file is automatically generated from cmake.toml - DO NOT EDIT
+# See https://github.com/build-cpp/cmkr for more information
+
+cmake_minimum_required(VERSION 3.15)
+
+if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
+ message(FATAL_ERROR "In-tree builds are not supported. Run CMake from a separate directory: cmake -B build")
+endif()
+
+# Regenerate CMakeLists.txt automatically in the root project
+set(CMKR_ROOT_PROJECT OFF)
+if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
+ set(CMKR_ROOT_PROJECT ON)
+
+ # Bootstrap cmkr
+ include(cmkr.cmake OPTIONAL RESULT_VARIABLE CMKR_INCLUDE_RESULT)
+ if(CMKR_INCLUDE_RESULT)
+ cmkr()
+ endif()
+
+ # Enable folder support
+ set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+endif()
+
+# Create a configure-time dependency on cmake.toml to improve IDE support
+if(CMKR_ROOT_PROJECT)
+ configure_file(cmake.toml cmake.toml COPYONLY)
+endif()
+
+project(Dotx64Dbg
+ LANGUAGES
+ CSharp
+ CXX
+)
+
+ # Only have Release and Debug, there are configuration errors with managed otherwise.
+ SET(CMAKE_CONFIGURATION_TYPES "Debug;Release")
+ SET(CMAKE_VS_NUGET_PACKAGE_RESTORE ON)
+
+ include(CSharpUtilities)
+
+ # Workaround for CLR projects, there is a pending fix for this:
+ # https://gitlab.kitware.com/cmake/cmake/-/merge_requests/7807 which corrects the exception option in use of CLR
+ string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS_INIT}")
+ string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG_INIT "${CMAKE_CXX_FLAGS_DEBUG_INIT}")
+ string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ set(BUILD_OUTPUT_DIR ${CMAKE_SOURCE_DIR}/bin/x64)
+elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
+ set(BUILD_OUTPUT_DIR ${CMAKE_SOURCE_DIR}/bin/x32)
+endif()
+
+# thirdparty
+set(CMKR_CMAKE_FOLDER ${CMAKE_FOLDER})
+if(CMAKE_FOLDER)
+ set(CMAKE_FOLDER "${CMAKE_FOLDER}/thirdparty")
+else()
+ set(CMAKE_FOLDER thirdparty)
+endif()
+add_subdirectory(thirdparty)
+set(CMAKE_FOLDER ${CMKR_CMAKE_FOLDER})
+
+# Target Dotx64DbgCommon
+set(CMKR_TARGET Dotx64DbgCommon)
+set(Dotx64DbgCommon_SOURCES "")
+
+set(CMKR_SOURCES ${Dotx64DbgCommon_SOURCES})
+add_library(Dotx64DbgCommon INTERFACE)
+
+if(Dotx64DbgCommon_SOURCES)
+ target_sources(Dotx64DbgCommon INTERFACE ${Dotx64DbgCommon_SOURCES})
+endif()
+
+add_library(dotx64dbg::common ALIAS Dotx64DbgCommon)
+target_compile_features(Dotx64DbgCommon INTERFACE
+ cxx_std_17
+)
+
+target_compile_options(Dotx64DbgCommon INTERFACE
+ "/MP"
+)
+
+target_link_options(Dotx64DbgCommon INTERFACE
+ "/DEBUG"
+)
+
+unset(CMKR_TARGET)
+unset(CMKR_SOURCES)
+
+# Target Dotx64DbgBindings
+set(CMKR_TARGET Dotx64DbgBindings)
+set(Dotx64DbgBindings_SOURCES "")
+
+list(APPEND Dotx64DbgBindings_SOURCES
+ "src/Bindings/Breakpoints.cpp"
+ "src/Bindings/Commands.cpp"
+ "src/Bindings/Debugger.cpp"
+ "src/Bindings/Expressions.cpp"
+ "src/Bindings/Instruction.cpp"
+ "src/Bindings/Instruction.Decoder.cpp"
+ "src/Bindings/Instruction.Encoder.cpp"
+ "src/Bindings/Instruction.Generator.cpp"
+ "src/Bindings/Logging.cpp"
+ "src/Bindings/Memory.cpp"
+ "src/Bindings/Module.cpp"
+ "src/Bindings/Platform.cpp"
+ "src/Bindings/Process.cpp"
+ "src/Bindings/Settings.cpp"
+ "src/Bindings/Symbols.cpp"
+ "src/Bindings/Thread.cpp"
+ "src/Bindings/UI.cpp"
+ "src/Bindings/AsmJitHelper.hpp"
+ "src/Bindings/Decoder.Converter.hpp"
+ "src/Bindings/Encoder.Converter.hpp"
+ "src/Bindings/Instruction.Decoder.hpp"
+ "src/Bindings/Instruction.EFlags.hpp"
+ "src/Bindings/Instruction.Encoder.hpp"
+ "src/Bindings/Instruction.Generator.hpp"
+ "src/Bindings/Instruction.Meta.hpp"
+ "src/Bindings/Instruction.Operand.hpp"
+ "src/Bindings/Instruction.Operands.hpp"
+ "src/Bindings/Instruction.hpp"
+ "src/Bindings/Marshal.hpp"
+ "src/Bindings/Mnemonic.hpp"
+ "src/Bindings/Register.hpp"
+)
+
+list(APPEND Dotx64DbgBindings_SOURCES
+ cmake.toml
+)
+
+set(CMKR_SOURCES ${Dotx64DbgBindings_SOURCES})
+add_library(Dotx64DbgBindings SHARED)
+
+if(Dotx64DbgBindings_SOURCES)
+ target_sources(Dotx64DbgBindings PRIVATE ${Dotx64DbgBindings_SOURCES})
+endif()
+
+source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${Dotx64DbgBindings_SOURCES})
+
+add_library(dotx64dbg::bindings ALIAS Dotx64DbgBindings)
+target_link_libraries(Dotx64DbgBindings PRIVATE
+ dotx64dbg::common
+ x64dbg::pluginsdk
+ asmjit::asmjit
+ Zydis
+)
+
+set_target_properties(Dotx64DbgBindings PROPERTIES
+ RUNTIME_OUTPUT_NAME
+ Dotx64DbgBindings
+ DOTNET_TARGET_FRAMEWORK
+ net6.0
+ DOTNET_TARGET_FRAMEWORK_VERSION
+ 6.0
+ COMMON_LANGUAGE_RUNTIME
+ netcore
+ VS_GLOBAL_ResolveNuGetPackages
+ false
+)
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 8) # x64
+ set_target_properties(Dotx64DbgBindings PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY_RELEASE
+ ${BUILD_OUTPUT_DIR}
+ RUNTIME_OUTPUT_DIRECTORY_DEBUG
+ ${BUILD_OUTPUT_DIR}
+ )
+endif()
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 4) # x32
+ set_target_properties(Dotx64DbgBindings PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY_RELEASE
+ ${BUILD_OUTPUT_DIR}
+ RUNTIME_OUTPUT_DIRECTORY_DEBUG
+ ${BUILD_OUTPUT_DIR}
+ )
+endif()
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ target_link_options(Dotx64DbgBindings PRIVATE "/DELAYLOAD:x64dbg.dll")
+ target_link_options(Dotx64DbgBindings PRIVATE "/DELAYLOAD:x64bridge.dll")
+elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
+ target_link_options(Dotx64DbgBindings PRIVATE "/DELAYLOAD:x32dbg.dll")
+ target_link_options(Dotx64DbgBindings PRIVATE "/DELAYLOAD:x32bridge.dll")
+endif()
+target_link_options(Dotx64DbgBindings PRIVATE "/DELAYLOAD:titanengine.dll")
+
+unset(CMKR_TARGET)
+unset(CMKR_SOURCES)
+
+# Target Dotx64DbgManaged
+set(CMKR_TARGET Dotx64DbgManaged)
+set(Dotx64DbgManaged_SOURCES "")
+
+list(APPEND Dotx64DbgManaged_SOURCES
+ "src/Dotx64Managed/API/Analysis/RegisterMask.cs"
+ "src/Dotx64Managed/API/Assembler.cs"
+ "src/Dotx64Managed/API/Assembler.Instructions.cs"
+ "src/Dotx64Managed/API/Breakpoints.cs"
+ "src/Dotx64Managed/API/Commands.cs"
+ "src/Dotx64Managed/API/Debugger.cs"
+ "src/Dotx64Managed/API/Expressions.cs"
+ "src/Dotx64Managed/API/Memory.cs"
+ "src/Dotx64Managed/API/Memory.Stream.cs"
+ "src/Dotx64Managed/API/Module.cs"
+ "src/Dotx64Managed/API/Module.Exports.cs"
+ "src/Dotx64Managed/API/Module.Imports.cs"
+ "src/Dotx64Managed/API/Module.Sections.cs"
+ "src/Dotx64Managed/API/Platform.cs"
+ "src/Dotx64Managed/API/Process.cs"
+ "src/Dotx64Managed/API/Thread.cs"
+ "src/Dotx64Managed/API/Thread.Register.cs"
+ "src/Dotx64Managed/API/UI/Disassembly.cs"
+ "src/Dotx64Managed/API/UI/Dump.cs"
+ "src/Dotx64Managed/API/UI/Log.cs"
+ "src/Dotx64Managed/API/UI/MemoryMap.cs"
+ "src/Dotx64Managed/API/UI/Menu.cs"
+ "src/Dotx64Managed/API/UI/Stack.cs"
+ "src/Dotx64Managed/API/UI/StatusBar.cs"
+ "src/Dotx64Managed/API/UI/Types.cs"
+ "src/Dotx64Managed/API/UI/UI.cs"
+ "src/Dotx64Managed/AssemblyLoader.cs"
+ "src/Dotx64Managed/Compiler.cs"
+ "src/Dotx64Managed/Hotload/Hotload.Adapter.Array.cs"
+ "src/Dotx64Managed/Hotload/Hotload.Adapter.Class.cs"
+ "src/Dotx64Managed/Hotload/Hotload.Adapter.cs"
+ "src/Dotx64Managed/Hotload/Hotload.Adapter.GenericDictionary.cs"
+ "src/Dotx64Managed/Hotload/Hotload.Adapter.GenericList.cs"
+ "src/Dotx64Managed/Hotload/Hotload.Adapter.Object.cs"
+ "src/Dotx64Managed/Hotload/Hotload.Adapter.Statics.cs"
+ "src/Dotx64Managed/Hotload/Hotload.Context.cs"
+ "src/Dotx64Managed/Hotload/Hotload.cs"
+ "src/Dotx64Managed/IPlugin.cs"
+ "src/Dotx64Managed/Logging.cs"
+ "src/Dotx64Managed/Manager.cs"
+ "src/Dotx64Managed/Manager.Events.cs"
+ "src/Dotx64Managed/Menus.cs"
+ "src/Dotx64Managed/Menus.Main.cs"
+ "src/Dotx64Managed/NodeList.cs"
+ "src/Dotx64Managed/Plugins.Builder.cs"
+ "src/Dotx64Managed/Plugins.cs"
+ "src/Dotx64Managed/Plugins.DependencyManager.cs"
+ "src/Dotx64Managed/Plugins.Hotload.cs"
+ "src/Dotx64Managed/Plugins.Watcher.cs"
+ "src/Dotx64Managed/ProjectGenerator.cs"
+ "src/Dotx64Managed/Resources.cs"
+ "src/Dotx64Managed/Scripting/Scripting.cs"
+ "src/Dotx64Managed/Scripting/Scripting.Register.cs"
+ "src/Dotx64Managed/ScriptLoader.cs"
+ "src/Dotx64Managed/Settings.cs"
+ "src/Dotx64Managed/Tests.cs"
+ "src/Dotx64Managed/Utils.cs"
+)
+
+list(APPEND Dotx64DbgManaged_SOURCES
+ cmake.toml
+)
+
+set(CMKR_SOURCES ${Dotx64DbgManaged_SOURCES})
+add_library(Dotx64DbgManaged SHARED)
+
+if(Dotx64DbgManaged_SOURCES)
+ target_sources(Dotx64DbgManaged PRIVATE ${Dotx64DbgManaged_SOURCES})
+endif()
+
+source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${Dotx64DbgManaged_SOURCES})
+
+add_library(dotx64dbg::managed ALIAS Dotx64DbgManaged)
+if(CMAKE_SIZEOF_VOID_P EQUAL 4) # x32
+ target_compile_definitions(Dotx64DbgManaged PRIVATE
+ _X86_
+ )
+endif()
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 8) # x64
+ target_compile_definitions(Dotx64DbgManaged PRIVATE
+ _X64_
+ )
+endif()
+
+target_link_libraries(Dotx64DbgManaged PRIVATE
+ dotx64dbg::bindings
+)
+
+set_target_properties(Dotx64DbgManaged PROPERTIES
+ RUNTIME_OUTPUT_NAME
+ Dotx64DbgManaged
+ DOTNET_SDK
+ Microsoft.NET.Sdk
+ DOTNET_TARGET_FRAMEWORK
+ net6.0
+ VS_GLOBAL_ResolveNuGetPackages
+ true
+ VS_GLOBAL_ROOTNAMESPACE
+ Dotx64Dbg
+ VS_GLOBAL_AppendTargetFrameworkToOutputPath
+ false
+ VS_GLOBAL_AppendRuntimeIdentifierToOutputPath
+ false
+ VS_GLOBAL_ProduceReferenceAssembly
+ false
+ VS_GLOBAL_ProduceReferenceAssemblyInOutDir
+ false
+ VS_GLOBAL_CopyLocalLockFileAssemblies
+ true
+ VS_GLOBAL_SatelliteResourceLanguages
+ neutral
+ VS_PACKAGE_REFERENCES
+ "Microsoft.CodeAnalysis.Compilers_3.10.0;NuGet.Configuration_5.11.0;NuGet.Frameworks_5.11.0;NuGet.Protocol_5.11.0;NuGet.Versioning_5.11.0"
+ VS_DOTNET_REFERENCES_COPY_LOCAL
+ false
+)
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 4) # x32
+ set_target_properties(Dotx64DbgManaged PROPERTIES
+ VS_GLOBAL_PlatformTarget
+ x86
+ RUNTIME_OUTPUT_DIRECTORY_RELEASE
+ ${BUILD_OUTPUT_DIR}
+ RUNTIME_OUTPUT_DIRECTORY_DEBUG
+ ${BUILD_OUTPUT_DIR}
+ )
+endif()
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 8) # x64
+ set_target_properties(Dotx64DbgManaged PROPERTIES
+ VS_GLOBAL_PlatformTarget
+ x64
+ RUNTIME_OUTPUT_DIRECTORY_RELEASE
+ ${BUILD_OUTPUT_DIR}
+ RUNTIME_OUTPUT_DIRECTORY_DEBUG
+ ${BUILD_OUTPUT_DIR}
+ )
+endif()
+
+unset(CMKR_TARGET)
+unset(CMKR_SOURCES)
+
+# Target Dotx64DbgTests
+set(CMKR_TARGET Dotx64DbgTests)
+set(Dotx64DbgTests_SOURCES "")
+
+list(APPEND Dotx64DbgTests_SOURCES
+ "src/Dotx64DbgTests/Testing.cs"
+ "src/Dotx64DbgTests/Runner.cs"
+ "src/Dotx64DbgTests/Tests/Tests.Assembler.cs"
+ "src/Dotx64DbgTests/Tests/Tests.Decoder.cs"
+ "src/Dotx64DbgTests/Tests/Tests.Generator.cs"
+ "src/Dotx64DbgTests/Tests/Tests.Operands.cs"
+ "src/Dotx64DbgTests/Tests/Tests.RegisterMaskGp.cs"
+ "src/Dotx64DbgTests/Tests/Tests.Registers.cs"
+)
+
+list(APPEND Dotx64DbgTests_SOURCES
+ cmake.toml
+)
+
+set(CMKR_SOURCES ${Dotx64DbgTests_SOURCES})
+add_executable(Dotx64DbgTests)
+
+if(Dotx64DbgTests_SOURCES)
+ target_sources(Dotx64DbgTests PRIVATE ${Dotx64DbgTests_SOURCES})
+endif()
+
+get_directory_property(CMKR_VS_STARTUP_PROJECT DIRECTORY ${PROJECT_SOURCE_DIR} DEFINITION VS_STARTUP_PROJECT)
+if(NOT CMKR_VS_STARTUP_PROJECT)
+ set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT Dotx64DbgTests)
+endif()
+
+source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${Dotx64DbgTests_SOURCES})
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 4) # x32
+ target_compile_definitions(Dotx64DbgTests PRIVATE
+ _X86_
+ )
+endif()
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 8) # x64
+ target_compile_definitions(Dotx64DbgTests PRIVATE
+ _X64_
+ )
+endif()
+
+target_link_libraries(Dotx64DbgTests PRIVATE
+ dotx64dbg::managed
+ dotx64dbg::bindings
+)
+
+set_target_properties(Dotx64DbgTests PROPERTIES
+ RUNTIME_OUTPUT_NAME
+ Dotx64DbgTests
+ DOTNET_SDK
+ Microsoft.NET.Sdk
+ DOTNET_TARGET_FRAMEWORK
+ net6.0
+ VS_GLOBAL_ROOTNAMESPACE
+ Dotx64Dbg
+ VS_GLOBAL_AppendTargetFrameworkToOutputPath
+ false
+ VS_GLOBAL_AppendRuntimeIdentifierToOutputPath
+ false
+ VS_GLOBAL_ProduceReferenceAssembly
+ false
+ VS_GLOBAL_ProduceReferenceAssemblyInOutDir
+ false
+ VS_GLOBAL_CopyLocalLockFileAssemblies
+ true
+ VS_GLOBAL_SatelliteResourceLanguages
+ neutral
+ VS_DOTNET_REFERENCES_COPY_LOCAL
+ true
+)
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 4) # x32
+ set_target_properties(Dotx64DbgTests PROPERTIES
+ VS_GLOBAL_PlatformTarget
+ x86
+ RUNTIME_OUTPUT_DIRECTORY_RELEASE
+ "${BUILD_OUTPUT_DIR}/tests"
+ RUNTIME_OUTPUT_DIRECTORY_DEBUG
+ "${BUILD_OUTPUT_DIR}/tests"
+ )
+endif()
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 8) # x64
+ set_target_properties(Dotx64DbgTests PROPERTIES
+ VS_GLOBAL_PlatformTarget
+ x64
+ RUNTIME_OUTPUT_DIRECTORY_RELEASE
+ "${BUILD_OUTPUT_DIR}/tests"
+ RUNTIME_OUTPUT_DIRECTORY_DEBUG
+ "${BUILD_OUTPUT_DIR}/tests"
+ )
+endif()
+
+unset(CMKR_TARGET)
+unset(CMKR_SOURCES)
+
+# Target Dotx64Dbg
+set(CMKR_TARGET Dotx64Dbg)
+set(Dotx64Dbg_SOURCES "")
+
+list(APPEND Dotx64Dbg_SOURCES
+ "src/Dotx64Dbg/Loader.cpp"
+ "src/Dotx64Dbg/Plugin.cpp"
+)
+
+list(APPEND Dotx64Dbg_SOURCES
+ cmake.toml
+)
+
+set(CMKR_SOURCES ${Dotx64Dbg_SOURCES})
+add_library(Dotx64Dbg SHARED)
+
+if(Dotx64Dbg_SOURCES)
+ target_sources(Dotx64Dbg PRIVATE ${Dotx64Dbg_SOURCES})
+endif()
+
+source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${Dotx64Dbg_SOURCES})
+
+add_library(dotx64dbg::dotx64dbg ALIAS Dotx64Dbg)
+target_link_libraries(Dotx64Dbg PRIVATE
+ dotx64dbg::common
+ x64dbg::pluginsdk
+ dotx64dbg::managed
+)
+
+set_target_properties(Dotx64Dbg PROPERTIES
+ DOTNET_TARGET_FRAMEWORK
+ net6.0
+ DOTNET_TARGET_FRAMEWORK_VERSION
+ 6.0
+ COMMON_LANGUAGE_RUNTIME
+ netcore
+ VS_GLOBAL_ResolveNuGetPackages
+ false
+ VS_GLOBAL_SatelliteResourceLanguages
+ neutral
+)
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 8) # x64
+ set_target_properties(Dotx64Dbg PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY_RELEASE
+ ${BUILD_OUTPUT_DIR}
+ RUNTIME_OUTPUT_DIRECTORY_DEBUG
+ ${BUILD_OUTPUT_DIR}
+ )
+endif()
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 4) # x32
+ set_target_properties(Dotx64Dbg PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY_RELEASE
+ ${BUILD_OUTPUT_DIR}
+ RUNTIME_OUTPUT_DIRECTORY_DEBUG
+ ${BUILD_OUTPUT_DIR}
+ )
+endif()
+
+unset(CMKR_TARGET)
+unset(CMKR_SOURCES)
+
+# Target Dotx64DbgLoader
+set(CMKR_TARGET Dotx64DbgLoader)
+set(Dotx64DbgLoader_SOURCES "")
+
+list(APPEND Dotx64DbgLoader_SOURCES
+ "src/Dotx64DbgLoader/Loader.cpp"
+)
+
+list(APPEND Dotx64DbgLoader_SOURCES
+ cmake.toml
+)
+
+set(CMKR_SOURCES ${Dotx64DbgLoader_SOURCES})
+add_library(Dotx64DbgLoader SHARED)
+
+if(Dotx64DbgLoader_SOURCES)
+ target_sources(Dotx64DbgLoader PRIVATE ${Dotx64DbgLoader_SOURCES})
+endif()
+
+source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${Dotx64DbgLoader_SOURCES})
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 4) # x32
+ target_compile_definitions(Dotx64DbgLoader PRIVATE
+ _X86_
+ )
+endif()
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 8) # x64
+ target_compile_definitions(Dotx64DbgLoader PRIVATE
+ _X64_
+ )
+endif()
+
+target_link_libraries(Dotx64DbgLoader PRIVATE
+ dotx64dbg::common
+ x64dbg::pluginsdk
+)
+
+set_target_properties(Dotx64DbgLoader PROPERTIES
+ VS_GLOBAL_ResolveNuGetPackages
+ false
+ RUNTIME_OUTPUT_NAME
+ Dotx64Dbg
+)
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 8) # x64
+ set_target_properties(Dotx64DbgLoader PROPERTIES
+ SUFFIX
+ .dp64
+ RUNTIME_OUTPUT_DIRECTORY_RELEASE
+ ${BUILD_OUTPUT_DIR}
+ RUNTIME_OUTPUT_DIRECTORY_DEBUG
+ ${BUILD_OUTPUT_DIR}
+ )
+endif()
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 4) # x32
+ set_target_properties(Dotx64DbgLoader PROPERTIES
+ SUFFIX
+ .dp32
+ RUNTIME_OUTPUT_DIRECTORY_RELEASE
+ ${BUILD_OUTPUT_DIR}
+ RUNTIME_OUTPUT_DIRECTORY_DEBUG
+ ${BUILD_OUTPUT_DIR}
+ )
+endif()
+
+unset(CMKR_TARGET)
+unset(CMKR_SOURCES)
+
+# Target Dotx64DbgResources
+set(CMKR_TARGET Dotx64DbgResources)
+set(Dotx64DbgResources_SOURCES "")
+
+list(APPEND Dotx64DbgResources_SOURCES
+ cmake.toml
+)
+
+set(CMKR_SOURCES ${Dotx64DbgResources_SOURCES})
+add_custom_target(Dotx64DbgResources SOURCES)
+
+if(Dotx64DbgResources_SOURCES)
+ target_sources(Dotx64DbgResources PRIVATE ${Dotx64DbgResources_SOURCES})
+endif()
+
+add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_directory
+ ${CMAKE_SOURCE_DIR}/src/Resources
+ ${BUILD_OUTPUT_DIR}/Resources
+)
+
+unset(CMKR_TARGET)
+unset(CMKR_SOURCES)
+
diff --git a/bin/dotplugins/example/ExamplePlugin.EvaluateExpression.cs b/bin/dotplugins/example/ExamplePlugin.EvaluateExpression.cs
index 44d21d9..db0d51e 100644
--- a/bin/dotplugins/example/ExamplePlugin.EvaluateExpression.cs
+++ b/bin/dotplugins/example/ExamplePlugin.EvaluateExpression.cs
@@ -8,7 +8,7 @@ void EvalExpr01(string[] args)
{
// Evaluate the expression "cip"
var result = Expressions.Evaluate("cip");
- System.Diagnostics.Debug.Assert(result == Dotx64Dbg.Thread.Active.Rip);
+ System.Diagnostics.Debug.Assert(result == Dotx64Dbg.Thread.Active.Nip);
Console.WriteLine($"cip = {result:X}");
}
@@ -30,7 +30,7 @@ void EvalExpr03(string[] args)
{
// Evaluate the value of eax+5
var result = Expressions.Evaluate("eax+5");
- System.Diagnostics.Debug.Assert(result == Thread.Active.Rax + 5);
+ System.Diagnostics.Debug.Assert(result == Thread.Active.Eax + 5);
Console.WriteLine($"eax+5 = {result:X}");
}
@@ -40,7 +40,7 @@ void EvalExpr04(string[] args)
{
// Use a sub expression like ReadPtr to read memory
var result = Expressions.Evaluate("ReadPtr(csp)");
- System.Diagnostics.Debug.Assert(result == Memory.ReadPtr(Thread.Active.Rsp));
+ System.Diagnostics.Debug.Assert(result == Memory.ReadPtr(Thread.Active.Nsp));
Console.WriteLine($"ReadPtr(csp) = {result:X}");
}
diff --git a/bin/x32/plugins/.empty b/bin/x32/plugins/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/bin/x64/plugins/.empty b/bin/x64/plugins/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/cmake.toml b/cmake.toml
new file mode 100644
index 0000000..0830a3c
--- /dev/null
+++ b/cmake.toml
@@ -0,0 +1,284 @@
+# Reference: https://build-cpp.github.io/cmkr/cmake-toml
+[project]
+name = "Dotx64Dbg"
+languages = ["CSharp", "CXX"]
+cmake-after = '''
+ # Only have Release and Debug, there are configuration errors with managed otherwise.
+ SET(CMAKE_CONFIGURATION_TYPES "Debug;Release")
+ SET(CMAKE_VS_NUGET_PACKAGE_RESTORE ON)
+
+ include(CSharpUtilities)
+
+ # Workaround for CLR projects, there is a pending fix for this:
+ # https://gitlab.kitware.com/cmake/cmake/-/merge_requests/7807 which corrects the exception option in use of CLR
+ string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS_INIT}")
+ string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG_INIT "${CMAKE_CXX_FLAGS_DEBUG_INIT}")
+ string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ set(BUILD_OUTPUT_DIR ${CMAKE_SOURCE_DIR}/bin/x64)
+elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
+ set(BUILD_OUTPUT_DIR ${CMAKE_SOURCE_DIR}/bin/x32)
+endif()
+'''
+
+[subdir.thirdparty]
+
+### Dotx64DbgCommon
+[target.Dotx64DbgCommon]
+type = "interface"
+alias = "dotx64dbg::common"
+compile-features = ["cxx_std_17"]
+compile-options = ["/MP"]
+link-options = ["/DEBUG"]
+
+### Dotx64DbgBindings
+[target.Dotx64DbgBindings]
+type = "shared"
+alias = "dotx64dbg::bindings"
+sources = [
+ "src/Bindings/Breakpoints.cpp",
+ "src/Bindings/Commands.cpp",
+ "src/Bindings/Debugger.cpp",
+ "src/Bindings/Expressions.cpp",
+ "src/Bindings/Instruction.cpp",
+ "src/Bindings/Instruction.Decoder.cpp",
+ "src/Bindings/Instruction.Encoder.cpp",
+ "src/Bindings/Instruction.Generator.cpp",
+ "src/Bindings/Logging.cpp",
+ "src/Bindings/Memory.cpp",
+ "src/Bindings/Module.cpp",
+ "src/Bindings/Platform.cpp",
+ "src/Bindings/Process.cpp",
+ "src/Bindings/Settings.cpp",
+ "src/Bindings/Symbols.cpp",
+ "src/Bindings/Thread.cpp",
+ "src/Bindings/UI.cpp",
+]
+headers = [
+ "src/Bindings/AsmJitHelper.hpp",
+ "src/Bindings/Decoder.Converter.hpp",
+ "src/Bindings/Encoder.Converter.hpp",
+ "src/Bindings/Instruction.Decoder.hpp",
+ "src/Bindings/Instruction.EFlags.hpp",
+ "src/Bindings/Instruction.Encoder.hpp",
+ "src/Bindings/Instruction.Generator.hpp",
+ "src/Bindings/Instruction.Meta.hpp",
+ "src/Bindings/Instruction.Operand.hpp",
+ "src/Bindings/Instruction.Operands.hpp",
+ "src/Bindings/Instruction.hpp",
+ "src/Bindings/Marshal.hpp",
+ "src/Bindings/Mnemonic.hpp",
+ "src/Bindings/Register.hpp",
+]
+private-link-libraries = [
+ "dotx64dbg::common",
+ "x64dbg::pluginsdk",
+ "asmjit::asmjit",
+ "Zydis",
+]
+cmake-after = '''
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ target_link_options(Dotx64DbgBindings PRIVATE "/DELAYLOAD:x64dbg.dll")
+ target_link_options(Dotx64DbgBindings PRIVATE "/DELAYLOAD:x64bridge.dll")
+elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
+ target_link_options(Dotx64DbgBindings PRIVATE "/DELAYLOAD:x32dbg.dll")
+ target_link_options(Dotx64DbgBindings PRIVATE "/DELAYLOAD:x32bridge.dll")
+endif()
+target_link_options(Dotx64DbgBindings PRIVATE "/DELAYLOAD:titanengine.dll")
+'''
+
+[target.Dotx64DbgBindings.properties]
+RUNTIME_OUTPUT_NAME = "Dotx64DbgBindings"
+DOTNET_TARGET_FRAMEWORK = "net6.0"
+DOTNET_TARGET_FRAMEWORK_VERSION = "6.0"
+COMMON_LANGUAGE_RUNTIME = "netcore"
+VS_GLOBAL_ResolveNuGetPackages = "false"
+x64.RUNTIME_OUTPUT_DIRECTORY_RELEASE = "${BUILD_OUTPUT_DIR}"
+x64.RUNTIME_OUTPUT_DIRECTORY_DEBUG = "${BUILD_OUTPUT_DIR}"
+x32.RUNTIME_OUTPUT_DIRECTORY_RELEASE = "${BUILD_OUTPUT_DIR}"
+x32.RUNTIME_OUTPUT_DIRECTORY_DEBUG = "${BUILD_OUTPUT_DIR}"
+
+### Dotx64DbgManaged
+[target.Dotx64DbgManaged]
+type = "shared"
+alias = "dotx64dbg::managed"
+sources = [
+ "src/Dotx64Managed/API/Analysis/RegisterMask.cs",
+ "src/Dotx64Managed/API/Assembler.cs",
+ "src/Dotx64Managed/API/Assembler.Instructions.cs",
+ "src/Dotx64Managed/API/Breakpoints.cs",
+ "src/Dotx64Managed/API/Commands.cs",
+ "src/Dotx64Managed/API/Debugger.cs",
+ "src/Dotx64Managed/API/Expressions.cs",
+ "src/Dotx64Managed/API/Memory.cs",
+ "src/Dotx64Managed/API/Memory.Stream.cs",
+ "src/Dotx64Managed/API/Module.cs",
+ "src/Dotx64Managed/API/Module.Exports.cs",
+ "src/Dotx64Managed/API/Module.Imports.cs",
+ "src/Dotx64Managed/API/Module.Sections.cs",
+ "src/Dotx64Managed/API/Platform.cs",
+ "src/Dotx64Managed/API/Process.cs",
+ "src/Dotx64Managed/API/Thread.cs",
+ "src/Dotx64Managed/API/Thread.Register.cs",
+ "src/Dotx64Managed/API/UI/Disassembly.cs",
+ "src/Dotx64Managed/API/UI/Dump.cs",
+ "src/Dotx64Managed/API/UI/Log.cs",
+ "src/Dotx64Managed/API/UI/MemoryMap.cs",
+ "src/Dotx64Managed/API/UI/Menu.cs",
+ "src/Dotx64Managed/API/UI/Stack.cs",
+ "src/Dotx64Managed/API/UI/StatusBar.cs",
+ "src/Dotx64Managed/API/UI/Types.cs",
+ "src/Dotx64Managed/API/UI/UI.cs",
+ "src/Dotx64Managed/AssemblyLoader.cs",
+ "src/Dotx64Managed/Compiler.cs",
+ "src/Dotx64Managed/Hotload/Hotload.Adapter.Array.cs",
+ "src/Dotx64Managed/Hotload/Hotload.Adapter.Class.cs",
+ "src/Dotx64Managed/Hotload/Hotload.Adapter.cs",
+ "src/Dotx64Managed/Hotload/Hotload.Adapter.GenericDictionary.cs",
+ "src/Dotx64Managed/Hotload/Hotload.Adapter.GenericList.cs",
+ "src/Dotx64Managed/Hotload/Hotload.Adapter.Object.cs",
+ "src/Dotx64Managed/Hotload/Hotload.Adapter.Statics.cs",
+ "src/Dotx64Managed/Hotload/Hotload.Context.cs",
+ "src/Dotx64Managed/Hotload/Hotload.cs",
+ "src/Dotx64Managed/IPlugin.cs",
+ "src/Dotx64Managed/Logging.cs",
+ "src/Dotx64Managed/Manager.cs",
+ "src/Dotx64Managed/Manager.Events.cs",
+ "src/Dotx64Managed/Menus.cs",
+ "src/Dotx64Managed/Menus.Main.cs",
+ "src/Dotx64Managed/NodeList.cs",
+ "src/Dotx64Managed/Plugins.Builder.cs",
+ "src/Dotx64Managed/Plugins.cs",
+ "src/Dotx64Managed/Plugins.DependencyManager.cs",
+ "src/Dotx64Managed/Plugins.Hotload.cs",
+ "src/Dotx64Managed/Plugins.Watcher.cs",
+ "src/Dotx64Managed/ProjectGenerator.cs",
+ "src/Dotx64Managed/Resources.cs",
+ "src/Dotx64Managed/Scripting/Scripting.cs",
+ "src/Dotx64Managed/Scripting/Scripting.Register.cs",
+ "src/Dotx64Managed/ScriptLoader.cs",
+ "src/Dotx64Managed/Settings.cs",
+ "src/Dotx64Managed/Tests.cs",
+ "src/Dotx64Managed/Utils.cs",
+]
+private-link-libraries = [
+ "dotx64dbg::bindings",
+]
+x32.private-compile-definitions = ["_X86_"]
+x64.private-compile-definitions = ["_X64_"]
+
+[target.Dotx64DbgManaged.properties]
+RUNTIME_OUTPUT_NAME = "Dotx64DbgManaged"
+x32.VS_GLOBAL_PlatformTarget = "x86"
+x64.VS_GLOBAL_PlatformTarget = "x64"
+DOTNET_SDK = "Microsoft.NET.Sdk"
+DOTNET_TARGET_FRAMEWORK = "net6.0"
+VS_GLOBAL_ResolveNuGetPackages = "true"
+VS_GLOBAL_ROOTNAMESPACE = "Dotx64Dbg"
+VS_GLOBAL_AppendTargetFrameworkToOutputPath = "false"
+VS_GLOBAL_AppendRuntimeIdentifierToOutputPath = "false"
+VS_GLOBAL_ProduceReferenceAssembly = "false"
+VS_GLOBAL_ProduceReferenceAssemblyInOutDir = "false"
+VS_GLOBAL_CopyLocalLockFileAssemblies = "true"
+VS_GLOBAL_SatelliteResourceLanguages = "neutral"
+VS_PACKAGE_REFERENCES = "Microsoft.CodeAnalysis.Compilers_3.10.0;NuGet.Configuration_5.11.0;NuGet.Frameworks_5.11.0;NuGet.Protocol_5.11.0;NuGet.Versioning_5.11.0"
+VS_DOTNET_REFERENCES_COPY_LOCAL = "false"
+x64.RUNTIME_OUTPUT_DIRECTORY_RELEASE = "${BUILD_OUTPUT_DIR}"
+x64.RUNTIME_OUTPUT_DIRECTORY_DEBUG = "${BUILD_OUTPUT_DIR}"
+x32.RUNTIME_OUTPUT_DIRECTORY_RELEASE = "${BUILD_OUTPUT_DIR}"
+x32.RUNTIME_OUTPUT_DIRECTORY_DEBUG = "${BUILD_OUTPUT_DIR}"
+
+[target.Dotx64DbgTests]
+type = "executable"
+sources = [
+ "src/Dotx64DbgTests/Testing.cs",
+ "src/Dotx64DbgTests/Runner.cs",
+ "src/Dotx64DbgTests/Tests/Tests.Assembler.cs",
+ "src/Dotx64DbgTests/Tests/Tests.Decoder.cs",
+ "src/Dotx64DbgTests/Tests/Tests.Generator.cs",
+ "src/Dotx64DbgTests/Tests/Tests.Operands.cs",
+ "src/Dotx64DbgTests/Tests/Tests.RegisterMaskGp.cs",
+ "src/Dotx64DbgTests/Tests/Tests.Registers.cs",
+]
+private-link-libraries = [
+ "dotx64dbg::managed",
+ "dotx64dbg::bindings",
+]
+x32.private-compile-definitions = ["_X86_"]
+x64.private-compile-definitions = ["_X64_"]
+
+[target.Dotx64DbgTests.properties]
+RUNTIME_OUTPUT_NAME = "Dotx64DbgTests"
+x32.VS_GLOBAL_PlatformTarget = "x86"
+x64.VS_GLOBAL_PlatformTarget = "x64"
+DOTNET_SDK = "Microsoft.NET.Sdk"
+DOTNET_TARGET_FRAMEWORK = "net6.0"
+VS_GLOBAL_ROOTNAMESPACE = "Dotx64Dbg"
+VS_GLOBAL_AppendTargetFrameworkToOutputPath = "false"
+VS_GLOBAL_AppendRuntimeIdentifierToOutputPath = "false"
+VS_GLOBAL_ProduceReferenceAssembly = "false"
+VS_GLOBAL_ProduceReferenceAssemblyInOutDir = "false"
+VS_GLOBAL_CopyLocalLockFileAssemblies = "true"
+VS_GLOBAL_SatelliteResourceLanguages = "neutral"
+VS_DOTNET_REFERENCES_COPY_LOCAL = "true"
+x64.RUNTIME_OUTPUT_DIRECTORY_RELEASE = "${BUILD_OUTPUT_DIR}/tests"
+x64.RUNTIME_OUTPUT_DIRECTORY_DEBUG = "${BUILD_OUTPUT_DIR}/tests"
+x32.RUNTIME_OUTPUT_DIRECTORY_RELEASE = "${BUILD_OUTPUT_DIR}/tests"
+x32.RUNTIME_OUTPUT_DIRECTORY_DEBUG = "${BUILD_OUTPUT_DIR}/tests"
+
+### Dotx64Dbg
+[target.Dotx64Dbg]
+type = "shared"
+alias = "dotx64dbg::dotx64dbg"
+sources = [
+ "src/Dotx64Dbg/Loader.cpp",
+ "src/Dotx64Dbg/Plugin.cpp",
+]
+headers = []
+private-link-libraries = [
+ "dotx64dbg::common",
+ "x64dbg::pluginsdk",
+ "dotx64dbg::managed",
+]
+[target.Dotx64Dbg.properties]
+DOTNET_TARGET_FRAMEWORK = "net6.0"
+DOTNET_TARGET_FRAMEWORK_VERSION = "6.0"
+COMMON_LANGUAGE_RUNTIME = "netcore"
+VS_GLOBAL_ResolveNuGetPackages = "false"
+VS_GLOBAL_SatelliteResourceLanguages = "neutral"
+x64.RUNTIME_OUTPUT_DIRECTORY_RELEASE = "${BUILD_OUTPUT_DIR}"
+x64.RUNTIME_OUTPUT_DIRECTORY_DEBUG = "${BUILD_OUTPUT_DIR}"
+x32.RUNTIME_OUTPUT_DIRECTORY_RELEASE = "${BUILD_OUTPUT_DIR}"
+x32.RUNTIME_OUTPUT_DIRECTORY_DEBUG = "${BUILD_OUTPUT_DIR}"
+
+### Dotx64DbgLoader
+[target.Dotx64DbgLoader]
+type = "shared"
+sources = ["src/Dotx64DbgLoader/Loader.cpp"]
+private-link-libraries = [
+ "dotx64dbg::common",
+ "x64dbg::pluginsdk",
+]
+x32.private-compile-definitions = ["_X86_"]
+x64.private-compile-definitions = ["_X64_"]
+[target.Dotx64DbgLoader.properties]
+VS_GLOBAL_ResolveNuGetPackages = "false"
+x64.SUFFIX = ".dp64"
+x32.SUFFIX = ".dp32"
+RUNTIME_OUTPUT_NAME = "Dotx64Dbg"
+x64.RUNTIME_OUTPUT_DIRECTORY_RELEASE = "${BUILD_OUTPUT_DIR}"
+x64.RUNTIME_OUTPUT_DIRECTORY_DEBUG = "${BUILD_OUTPUT_DIR}"
+x32.RUNTIME_OUTPUT_DIRECTORY_RELEASE = "${BUILD_OUTPUT_DIR}"
+x32.RUNTIME_OUTPUT_DIRECTORY_DEBUG = "${BUILD_OUTPUT_DIR}"
+
+[target.Dotx64DbgResources]
+type = "custom"
+cmake-after = '''
+add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_directory
+ ${CMAKE_SOURCE_DIR}/src/Resources
+ ${BUILD_OUTPUT_DIR}/Resources
+)
+'''
\ No newline at end of file
diff --git a/src/Bindings/Bindings.vcxproj b/src/Bindings/Bindings.vcxproj
deleted file mode 100644
index faf7412..0000000
--- a/src/Bindings/Bindings.vcxproj
+++ /dev/null
@@ -1,234 +0,0 @@
-
-
-
-
- Debug
- Win32
- true
-
-
- Release
- Win32
-
-
- Debug
- x64
-
-
- Release
- x64
-
-
-
- 16.0
- {A42ACB74-FD7C-4F6F-B3C4-205DFBFE827C}
- NetCoreCProj
- Bindings
- 10.0
- net6.0
-
-
-
- DynamicLibrary
- true
- v142
- NetCore
- Unicode
-
-
- DynamicLibrary
- false
- v142
- NetCore
- Unicode
-
-
- DynamicLibrary
- true
- v142
- NetCore
- Unicode
-
-
- DynamicLibrary
- false
- v142
- NetCore
- Unicode
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $(SolutionDir)..\bin\x64\plugins\
- Dotx64Dbg.Bindings
- false
-
-
- $(SolutionDir)..\bin\x64\plugins\
- Dotx64Dbg.Bindings
- false
-
-
- $(SolutionDir)..\bin\x32\plugins\
- Dotx64Dbg.Bindings
- $(Platform)\$(Configuration)\
- false
-
-
- $(SolutionDir)..\bin\x32\plugins\
- Dotx64Dbg.Bindings
- $(Platform)\$(Configuration)\
- false
-
-
- true
-
-
- true
-
-
- true
-
-
- true
-
-
- true
- false
-
-
-
- Level3
- _DEBUG;%(PreprocessorDefinitions)
- stdcpp17
- $(SolutionDir)include;$(SolutionDir)asmjit;$(SolutionDir)zycore\include;$(SolutionDir)zydis\include
- true
- true
-
-
-
- $(SolutionDir)include;%(AdditionalLibraryDirectories)
- x64dbg.dll;x64bridge.dll;TitanEngine.dll;%(DelayLoadDLLs)
-
-
-
-
- Level3
- WIN32;_DEBUG;%(PreprocessorDefinitions)
- stdcpp17
- $(SolutionDir)include;$(SolutionDir)asmjit;$(SolutionDir)zycore\include;$(SolutionDir)zydis\include
- true
- true
-
-
-
- $(SolutionDir)include;%(AdditionalLibraryDirectories)
- x32dbg.dll;x32bridge.dll;TitanEngine.dll;%(DelayLoadDLLs)
-
-
-
-
- Level3
- WIN32;NDEBUG;%(PreprocessorDefinitions)
- stdcpp17
- $(SolutionDir)include;$(SolutionDir)asmjit;$(SolutionDir)zycore\include;$(SolutionDir)zydis\include
- true
- true
-
-
-
- $(SolutionDir)include;%(AdditionalLibraryDirectories)
- x32dbg.dll;x32bridge.dll;TitanEngine.dll;%(DelayLoadDLLs)
- UseLinkTimeCodeGeneration
-
-
-
-
- Level3
- NDEBUG;%(PreprocessorDefinitions)
- stdcpp17
- $(SolutionDir)include;$(SolutionDir)asmjit;$(SolutionDir)zycore\include;$(SolutionDir)zydis\include
- true
- true
-
-
-
- $(SolutionDir)include;%(AdditionalLibraryDirectories)
- x64dbg.dll;x64bridge.dll;TitanEngine.dll;%(DelayLoadDLLs)
- true
- true
- UseLinkTimeCodeGeneration
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {401e7506-9879-4c5c-8638-6664852fbfff}
-
-
- {7d3a69f9-4055-47d3-8474-b62174e93de8}
-
-
- {333cf7b7-cd5b-4f09-b402-81c31d5e6e28}
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Bindings/Bindings.vcxproj.filters b/src/Bindings/Bindings.vcxproj.filters
deleted file mode 100644
index 4577b7e..0000000
--- a/src/Bindings/Bindings.vcxproj.filters
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Bindings/Instruction.Decoder.cpp b/src/Bindings/Instruction.Decoder.cpp
index 863e41d..4ebd743 100644
--- a/src/Bindings/Instruction.Decoder.cpp
+++ b/src/Bindings/Instruction.Decoder.cpp
@@ -79,16 +79,16 @@ namespace Dotx64Dbg
return Operand::None;
}
- static Instruction^ Convert(ZydisDecodedInstruction& instr, uint64_t addr)
+ static Instruction^ Convert(ZydisDecodedInstruction& instr, ZydisDecodedOperand* operands, uint64_t addr)
{
const auto id = convertZydisMnemonic(instr.mnemonic);
auto attribs = Instruction::Attributes::None;
auto addAttribute = [&](Instruction::Attributes a, Instruction::Attributes b)
- {
- return static_cast(static_cast(a) | static_cast(b));
- };
+ {
+ return static_cast(static_cast(a) | static_cast(b));
+ };
if (instr.attributes & ZYDIS_ATTRIB_HAS_LOCK)
{
@@ -118,13 +118,13 @@ namespace Dotx64Dbg
auto res = gcnew Instruction(attribs, id);
res->_Size = instr.length;
res->_Address = addr;
- res->_FlagsModified = (EFlags)instr.cpu_flags_written;
- res->_FlagsRead = (EFlags)instr.cpu_flags_read;
+ res->_FlagsModified = (EFlags)(instr.cpu_flags->modified | instr.cpu_flags->set_0 | instr.cpu_flags->set_1);
+ res->_FlagsRead = (EFlags)instr.cpu_flags->tested;
int opIndex = 0;
for (int i = 0; i < instr.operand_count; i++)
{
- auto& op = instr.operands[i];
+ auto& op = operands[i];
IOperand^ newOp = ConvertOperand(instr, op, addr);
OperandVisibility vis = OperandVisibility::Invalid;
@@ -162,12 +162,13 @@ namespace Dotx64Dbg
Instruction^ decodeInstruction(const ZydisDecoder* decoder, const uint8_t* buf, size_t len, uint64_t address)
{
ZydisDecodedInstruction instr{};
- if (auto status = ZydisDecoderDecodeBuffer(decoder, buf, len, &instr); status != ZYAN_STATUS_SUCCESS)
+ ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT];
+ if (auto status = ZydisDecoderDecodeFull(decoder, buf, len, &instr, operands); status != ZYAN_STATUS_SUCCESS)
{
return nullptr;
}
- return Convert(instr, address);
+ return Convert(instr, operands, address);
}
}
@@ -182,10 +183,10 @@ namespace Dotx64Dbg
_decoder = new ZydisDecoder();
#ifdef _M_AMD64
auto mode = ZYDIS_MACHINE_MODE_LONG_64;
- auto addrSize = ZYDIS_ADDRESS_WIDTH_64;
+ auto addrSize = ZYDIS_STACK_WIDTH_64;
#else
auto mode = ZYDIS_MACHINE_MODE_LEGACY_32;
- auto addrSize = ZYDIS_ADDRESS_WIDTH_32;
+ auto addrSize = ZYDIS_STACK_WIDTH_32;
#endif
if (auto status = ZydisDecoderInit(_decoder, mode, addrSize);
status != ZYAN_STATUS_SUCCESS)
diff --git a/src/Bindings/Instruction.Generator.cpp b/src/Bindings/Instruction.Generator.cpp
index 2ce4772..d1085e9 100644
--- a/src/Bindings/Instruction.Generator.cpp
+++ b/src/Bindings/Instruction.Generator.cpp
@@ -153,10 +153,10 @@ namespace Dotx64Dbg
ZydisDecoder decoder;
#ifdef _M_AMD64
auto mode = ZYDIS_MACHINE_MODE_LONG_64;
- auto addrSize = ZYDIS_ADDRESS_WIDTH_64;
+ auto addrSize = ZYDIS_STACK_WIDTH_64;
#else
auto mode = ZYDIS_MACHINE_MODE_LEGACY_32;
- auto addrSize = ZYDIS_ADDRESS_WIDTH_32;
+ auto addrSize = ZYDIS_STACK_WIDTH_32;
#endif
if (auto status = ZydisDecoderInit(&decoder, mode, addrSize);
status != ZYAN_STATUS_SUCCESS)
diff --git a/src/Bindings/Instruction.hpp b/src/Bindings/Instruction.hpp
index 68141f0..e64d5a0 100644
--- a/src/Bindings/Instruction.hpp
+++ b/src/Bindings/Instruction.hpp
@@ -4,7 +4,6 @@
#include
#include
-#include "Register.hpp"
#include "Mnemonic.hpp"
#include "Instruction.Operand.hpp"
#include "Instruction.EFlags.hpp"
diff --git a/src/Bindings/Marshal.hpp b/src/Bindings/Marshal.hpp
index 553a5c0..a59016b 100644
--- a/src/Bindings/Marshal.hpp
+++ b/src/Bindings/Marshal.hpp
@@ -41,6 +41,15 @@ namespace interop {
return buf;
}
+ inline std::wstring toUTF16(System::String^ str)
+ {
+ msclr::interop::marshal_context oMarshalContext;
+
+ const wchar_t* cstr = oMarshalContext.marshal_as(str);
+
+ return cstr;
+ }
+
inline System::String^ stringFromUTF8(const char* str)
{
return Marshal::PtrToStringUTF8(System::IntPtr((void*)str));
diff --git a/src/Bindings/Platform.cpp b/src/Bindings/Platform.cpp
new file mode 100644
index 0000000..f4ad97f
--- /dev/null
+++ b/src/Bindings/Platform.cpp
@@ -0,0 +1,137 @@
+#include
+#include
+
+#include "pluginsdk/bridgemain.h"
+#include "Marshal.hpp"
+
+#pragma comment(lib, "Shell32.lib")
+
+using namespace System;
+using namespace System::Runtime::InteropServices;
+
+namespace Dotx64Dbg::Native {
+
+ namespace Detail {
+
+ // Converts the browser filter to the format required by GetOpenFileNameW.
+ // Example
+ // Input: ".cs (*.cs)|*.cs|All files (*.*)|*.*"
+ // Output: "*.cs (*.cs)\0*.cs\0All files (*.*)\0*.*\0\0"
+ static std::wstring getBrowseFilter(const std::wstring& filter)
+ {
+ // Replace | with \0
+ std::wstring result = filter;
+ for (size_t i = 0; i < result.size(); i++)
+ {
+ if (result[i] == L'|')
+ result[i] = L'\0';
+ }
+ // Append terminator
+ result.push_back(L'\0');
+ return result;
+ }
+ }
+
+ public ref class Platform
+ {
+ public:
+
+ static System::String^ BrowseForFolder(System::String^ title)
+ {
+ const auto titleStr = interop::toUTF16(title);
+
+ BROWSEINFOW bi{};
+ bi.hwndOwner = GuiGetWindowHandle();
+ bi.lpszTitle = titleStr.c_str();
+ bi.lpfn = nullptr;
+ bi.lParam = 0;
+ bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI;
+
+ auto pidl = SHBrowseForFolderW(&bi);
+ if (!pidl)
+ return nullptr;
+
+ wchar_t path[MAX_PATH]{};
+ if (!SHGetPathFromIDListW(pidl, path))
+ return nullptr;
+
+ return gcnew System::String(path);
+ }
+
+ static System::String^ OpenFileBrowse(System::String^ title, System::String^ filter)
+ {
+ const auto titleStr = interop::toUTF16(title);
+ const auto filterStr = Detail::getBrowseFilter(interop::toUTF16(filter));
+ wchar_t path[1024]{};
+
+ OPENFILENAMEW ofn{};
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hInstance = GetModuleHandle(nullptr);
+ ofn.hwndOwner = GuiGetWindowHandle();
+ ofn.lpstrTitle = titleStr.c_str();
+ ofn.lpstrFilter = filterStr.c_str();
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFile = path;
+ ofn.nMaxFile = sizeof(path) / sizeof(wchar_t);
+ ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
+
+ if (!GetOpenFileNameW(&ofn))
+ return nullptr;
+
+ return gcnew System::String(path);
+ }
+
+ static System::String^ SaveFileBrowse(System::String^ title, System::String^ filter)
+ {
+ const auto titleStr = interop::toUTF16(title);
+ const auto filterStr = Detail::getBrowseFilter(interop::toUTF16(filter));
+ wchar_t path[1024]{};
+
+ OPENFILENAMEW ofn{};
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hInstance = GetModuleHandle(nullptr);
+ ofn.hwndOwner = GuiGetWindowHandle();
+ ofn.lpstrTitle = titleStr.c_str();
+ ofn.lpstrFilter = filterStr.c_str();
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFile = path;
+ ofn.nMaxFile = sizeof(path) / sizeof(wchar_t);
+ ofn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR;
+
+ if (!GetSaveFileNameW(&ofn))
+ return nullptr;
+
+ return gcnew System::String(path);
+ }
+
+ static void SetClipboardText(System::String^ text)
+ {
+ const auto textStr = interop::toUTF16(text);
+
+ const auto size = (textStr.size() + 1) * sizeof(wchar_t);
+ auto hMem = GlobalAlloc(GMEM_MOVEABLE, size);
+ if (!hMem)
+ return;
+
+ auto pMem = GlobalLock(hMem);
+ if (!pMem)
+ {
+ GlobalFree(hMem);
+ return;
+ }
+ memcpy(pMem, textStr.data(), size);
+ GlobalUnlock(hMem);
+
+ if (!OpenClipboard(GuiGetWindowHandle()))
+ {
+ GlobalFree(hMem);
+ return;
+ }
+
+ EmptyClipboard();
+ SetClipboardData(CF_UNICODETEXT, hMem);
+ CloseClipboard();
+ }
+ };
+
+}
diff --git a/src/Bindings/Plugin.cpp b/src/Bindings/Plugin.cpp
index 1d700b4..e69de29 100644
--- a/src/Bindings/Plugin.cpp
+++ b/src/Bindings/Plugin.cpp
@@ -1,17 +0,0 @@
-#ifdef _WIN64
-#pragma comment(lib, "pluginsdk/x64dbg.lib")
-#pragma comment(lib, "pluginsdk/x64bridge.lib")
-#pragma comment(lib, "pluginsdk/DeviceNameResolver/DeviceNameResolver_x64.lib")
-#pragma comment(lib, "pluginsdk/jansson/jansson_x64.lib")
-#pragma comment(lib, "pluginsdk/lz4/lz4_x64.lib")
-#pragma comment(lib, "pluginsdk/TitanEngine/TitanEngine_x64.lib")
-#pragma comment(lib, "pluginsdk/XEDParse/XEDParse_x64.lib")
-#else
-#pragma comment(lib, "pluginsdk/x32dbg.lib")
-#pragma comment(lib, "pluginsdk/x32bridge.lib")
-#pragma comment(lib, "pluginsdk/DeviceNameResolver/DeviceNameResolver_x86.lib")
-#pragma comment(lib, "pluginsdk/jansson/jansson_x86.lib")
-#pragma comment(lib, "pluginsdk/lz4/lz4_x86.lib")
-#pragma comment(lib, "pluginsdk/TitanEngine/TitanEngine_x86.lib")
-#pragma comment(lib, "pluginsdk/XEDParse/XEDParse_x86.lib")
-#endif //_WIN64
diff --git a/src/Bindings/Register.hpp b/src/Bindings/Register.hpp
index da3f0f7..4a44263 100644
--- a/src/Bindings/Register.hpp
+++ b/src/Bindings/Register.hpp
@@ -1,5 +1,7 @@
#pragma once
+#include
+
namespace Dotx64Dbg
{
public ref class Registers
diff --git a/src/Bindings/Symbols.cpp b/src/Bindings/Symbols.cpp
index 3de9a00..b49a0e4 100644
--- a/src/Bindings/Symbols.cpp
+++ b/src/Bindings/Symbols.cpp
@@ -1,13 +1,427 @@
-#include
+#include
#include
#include
#include "pluginsdk/bridgemain.h"
#include "pluginsdk/_plugins.h"
#include "pluginsdk/_scriptapi_label.h"
-#include "Symbols.hpp"
+#include "pluginsdk/_scriptapi_function.h"
+#include "pluginsdk/_scriptapi_comment.h"
+
+#include "Marshal.hpp"
+#include
namespace Dotx64Dbg {
+ namespace Detail
+ {
+ inline std::optional GetLabelInfo(System::UIntPtr addr)
+ {
+ auto va = reinterpret_cast(addr.ToPointer());
+
+ Script::Label::LabelInfo info;
+ if (Script::Label::GetInfo(va, &info))
+ {
+ return info;
+ }
+
+ return std::nullopt;
+ }
+
+
+ inline bool LabelIsTemporary(System::UIntPtr addr)
+ {
+ auto va = reinterpret_cast(addr.ToPointer());
+ return Script::Label::IsTemporary(va);
+ }
+
+ inline std::optional GetFuncInfo(System::UIntPtr addr)
+ {
+ auto va = reinterpret_cast(addr.ToPointer());
+
+ Script::Function::FunctionInfo info;
+ if (Script::Function::GetInfo(va, &info))
+ {
+ return info;
+ }
+
+ return std::nullopt;
+ }
+
+ inline std::optional GetCommentInfo(System::UIntPtr addr)
+ {
+ auto va = reinterpret_cast(addr.ToPointer());
+
+ Script::Comment::CommentInfo info;
+ if (Script::Comment::GetInfo(va, &info))
+ {
+ return info;
+ }
+
+ return std::nullopt;
+ }
+ }
+
+ public interface class Symbol
+ {
+ public:
+ enum class Type
+ {
+ None = 0,
+ Label,
+ Function,
+ Comment,
+ };
+
+ property Type SymbolType
+ {
+ virtual Type get();
+ }
+
+ property System::UIntPtr Address
+ {
+ virtual System::UIntPtr get();
+ }
+
+ property int Size
+ {
+ virtual int get();
+ }
+
+ property System::String^ Text
+ {
+ virtual System::String^ get();
+ }
+ };
+
+ public ref class Symbols
+ {
+ public:
+ /// Label
+ /////////////////////////////////////////////////////////////////////////////
+ ref class Label : public Symbol
+ {
+ System::UIntPtr _address;
+ uint32_t _rva;
+
+ public:
+ [System::Flags]
+ enum class Attribs
+ {
+ None = 0,
+ Manual = (1 << 0),
+ Temporary = (1 << 1),
+ };
+
+ internal:
+ Label(System::UIntPtr address, uint32_t rva)
+ {
+ _address = address;
+ _rva = rva;
+ }
+
+ public:
+ property Symbol::Type SymbolType
+ {
+ virtual Symbol::Type get()
+ {
+ return Symbol::Type::Label;
+ }
+ }
+
+ property System::UIntPtr Address
+ {
+ virtual System::UIntPtr get()
+ {
+ return _address;
+ }
+ }
+
+ property uint32_t RVA
+ {
+ virtual uint32_t get()
+ {
+ return _rva;
+ }
+ }
+
+ property int Size
+ {
+ virtual int get()
+ {
+ return 0;
+ }
+ }
+
+ property System::String^ Text
+ {
+ virtual System::String^ get()
+ {
+ if (auto info = Detail::GetLabelInfo(_address))
+ {
+ return interop::stringFromUTF8(info->text);
+ }
+ return nullptr;
+ }
+ }
+
+ property System::String^ Module
+ {
+ virtual System::String^ get()
+ {
+ if (auto info = Detail::GetLabelInfo(_address))
+ {
+ return interop::stringFromUTF8(info->mod);
+ }
+ return nullptr;
+ }
+ }
+
+ property Attribs Attributes
+ {
+ Attribs get()
+ {
+ Attribs res = Attribs::None;
+
+ if (auto info = Detail::GetLabelInfo(_address))
+ {
+ if (info->manual)
+ res = static_cast(static_cast(res) | static_cast(Attribs::Manual));
+
+ if (Detail::LabelIsTemporary(_address))
+ res = static_cast(static_cast(res) | static_cast(Attribs::Temporary));
+ }
+
+ return res;
+ }
+ }
+
+ static Symbols::Label^ Get(System::UIntPtr address)
+ {
+ auto va = reinterpret_cast(address.ToPointer());
+
+ Script::Label::LabelInfo info;
+ if (Script::Label::GetInfo(va, &info))
+ {
+ Label^ res = gcnew Label(address, static_cast(info.rva));
+ return res;
+ }
+
+ return nullptr;
+ }
+
+ static bool Set(System::UIntPtr address, System::String^ name, Symbols::Label::Attribs attribs)
+ {
+ auto va = reinterpret_cast(address.ToPointer());
+
+ auto nameStr = interop::toUTF8(name);
+ bool manual = (attribs & Symbols::Label::Attribs::Manual) != Symbols::Label::Attribs::None;
+
+ // NOTE: Temporary is not supported until the https://github.com/x64dbg/x64dbg/pull/2695 is merged.
+ bool temporary = (attribs & Label::Attribs::Manual) != Symbols::Label::Attribs::None;
+
+ return Script::Label::Set(va, nameStr.c_str(), manual, temporary);
+ }
+
+ static bool Remove(System::UIntPtr address)
+ {
+ auto va = reinterpret_cast(address.ToPointer());
+
+ return Script::Label::Delete(va);
+ }
+ };
+
+ public:
+ /// Function
+ /////////////////////////////////////////////////////////////////////////////
+ ref class Function : public Symbol
+ {
+ System::UIntPtr _address;
+ uint32_t _rva;
+
+ internal:
+ Function(System::UIntPtr address, uint32_t rva)
+ {
+ _address = address;
+ }
+
+ public:
+ property Symbol::Type SymbolType
+ {
+ virtual Symbol::Type get()
+ {
+ return Symbol::Type::Function;
+ }
+ }
+
+ property System::UIntPtr Address
+ {
+ virtual System::UIntPtr get()
+ {
+ return _address;
+ }
+ }
+
+ property uint32_t RVA
+ {
+ virtual uint32_t get()
+ {
+ return _rva;
+ }
+ }
+
+ property int Size
+ {
+ virtual int get()
+ {
+ if (auto info = Detail::GetFuncInfo(_address))
+ {
+ return static_cast(info->rvaEnd - info->rvaStart);
+ }
+ return 0;
+ }
+ }
+
+ property System::String^ Text
+ {
+ virtual System::String^ get()
+ {
+ return gcnew System::String("");
+ }
+ }
+
+ property System::String^ Module
+ {
+ virtual System::String^ get()
+ {
+ if (auto info = Detail::GetFuncInfo(_address))
+ {
+ return interop::stringFromUTF8(info->mod);
+ }
+ return nullptr;
+ }
+ }
+
+ static Symbols::Function^ Get(System::UIntPtr address)
+ {
+ if (auto info = Detail::GetFuncInfo(address))
+ {
+ Symbols::Function^ res = gcnew Symbols::Function(address, (uint32_t)info->rvaStart);
+ return res;
+ }
+ return nullptr;
+ }
+
+ static bool Set(System::UIntPtr startAddress, System::UIntPtr endAddress, bool manual)
+ {
+ auto startVA = reinterpret_cast(startAddress.ToPointer());
+ auto endVA = reinterpret_cast(startAddress.ToPointer());
+
+ return Script::Function::Add(startVA, endVA, manual, 0);
+ }
+
+ static bool Remove(System::UIntPtr address)
+ {
+ auto va = reinterpret_cast(address.ToPointer());
+ return Script::Function::Delete(va);
+ }
+ };
+
+ public:
+ /// Comment
+ /////////////////////////////////////////////////////////////////////////////
+ ref class Comment : public Symbol
+ {
+ System::UIntPtr _address;
+ uint32_t _rva;
+
+ internal:
+ Comment(System::UIntPtr address, uint32_t rva)
+ {
+ _address = address;
+ }
+
+ public:
+ property Symbol::Type SymbolType
+ {
+ virtual Symbol::Type get()
+ {
+ return Symbol::Type::Comment;
+ }
+ }
+
+ property System::UIntPtr Address
+ {
+ virtual System::UIntPtr get()
+ {
+ return _address;
+ }
+ }
+
+ property uint32_t RVA
+ {
+ virtual uint32_t get()
+ {
+ return _rva;
+ }
+ }
+
+ property int Size
+ {
+ virtual int get()
+ {
+ return 0;
+ }
+ }
+
+ property System::String^ Text
+ {
+ virtual System::String^ get()
+ {
+ if (auto cmtInfo = Detail::GetCommentInfo(_address))
+ {
+ return interop::stringFromUTF8(cmtInfo->text);
+ }
+ return nullptr;
+ }
+ }
+
+ property System::String^ Module
+ {
+ virtual System::String^ get()
+ {
+ if (auto info = Detail::GetCommentInfo(_address))
+ {
+ return interop::stringFromUTF8(info->mod);
+ }
+ return nullptr;
+ }
+ }
+
+ static Symbols::Comment^ Get(System::UIntPtr address)
+ {
+ if (auto info = Detail::GetCommentInfo(address))
+ {
+ Symbols::Comment^ res = gcnew Symbols::Comment(address, (uint32_t)info->rva);
+ return res;
+ }
+ return nullptr;
+ }
+
+ static bool Set(System::UIntPtr address, System::String^ text, bool manual)
+ {
+ auto va = reinterpret_cast(address.ToPointer());
+
+ auto textStr = interop::toUTF8(text);
+ return Script::Comment::Set(va, textStr.c_str(), manual);
+ }
+
+ static bool Remove(System::UIntPtr address)
+ {
+ auto va = reinterpret_cast(address.ToPointer());
+ return Script::Comment::Delete(va);
+ }
+ };
+ };
}
diff --git a/src/Bindings/Symbols.hpp b/src/Bindings/Symbols.hpp
deleted file mode 100644
index 7fc4079..0000000
--- a/src/Bindings/Symbols.hpp
+++ /dev/null
@@ -1,429 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-
-#include "pluginsdk/bridgemain.h"
-#include "pluginsdk/_plugins.h"
-#include "pluginsdk/_scriptapi_label.h"
-#include "pluginsdk/_scriptapi_function.h"
-#include "pluginsdk/_scriptapi_comment.h"
-
-#include "Marshal.hpp"
-#include
-
-namespace Dotx64Dbg {
-
- namespace Detail
- {
- inline std::optional GetLabelInfo(System::UIntPtr addr)
- {
- auto va = reinterpret_cast(addr.ToPointer());
-
- Script::Label::LabelInfo info;
- if (Script::Label::GetInfo(va, &info))
- {
- return info;
- }
-
- return std::nullopt;
- }
-
-
- inline bool LabelIsTemporary(System::UIntPtr addr)
- {
- auto va = reinterpret_cast(addr.ToPointer());
- return Script::Label::IsTemporary(va);
- }
-
- inline std::optional GetFuncInfo(System::UIntPtr addr)
- {
- auto va = reinterpret_cast(addr.ToPointer());
-
- Script::Function::FunctionInfo info;
- if (Script::Function::GetInfo(va, &info))
- {
- return info;
- }
-
- return std::nullopt;
- }
-
- inline std::optional GetCommentInfo(System::UIntPtr addr)
- {
- auto va = reinterpret_cast(addr.ToPointer());
-
- Script::Comment::CommentInfo info;
- if (Script::Comment::GetInfo(va, &info))
- {
- return info;
- }
-
- return std::nullopt;
- }
- }
-
- public interface class Symbol
- {
- public:
- enum class Type
- {
- None = 0,
- Label,
- Function,
- Comment,
- };
-
- property Type SymbolType
- {
- virtual Type get();
- }
-
- property System::UIntPtr Address
- {
- virtual System::UIntPtr get();
- }
-
- property int Size
- {
- virtual int get();
- }
-
- property System::String^ Text
- {
- virtual System::String^ get();
- }
- };
-
- public ref class Symbols
- {
- public:
- /// Label
- /////////////////////////////////////////////////////////////////////////////
- ref class Label : public Symbol
- {
- System::UIntPtr _address;
- uint32_t _rva;
-
- public:
- [System::Flags]
- enum class Attribs
- {
- None = 0,
- Manual = (1 << 0),
- Temporary = (1 << 1),
- };
-
- internal:
- Label(System::UIntPtr address, uint32_t rva)
- {
- _address = address;
- _rva = rva;
- }
-
- public:
- property Symbol::Type SymbolType
- {
- virtual Symbol::Type get()
- {
- return Symbol::Type::Label;
- }
- }
-
- property System::UIntPtr Address
- {
- virtual System::UIntPtr get()
- {
- return _address;
- }
- }
-
- property uint32_t RVA
- {
- virtual uint32_t get()
- {
- return _rva;
- }
- }
-
- property int Size
- {
- virtual int get()
- {
- return 0;
- }
- }
-
- property System::String^ Text
- {
- virtual System::String^ get()
- {
- if (auto info = Detail::GetLabelInfo(_address))
- {
- return interop::stringFromUTF8(info->text);
- }
- return nullptr;
- }
- }
-
- property System::String^ Module
- {
- virtual System::String^ get()
- {
- if (auto info = Detail::GetLabelInfo(_address))
- {
- return interop::stringFromUTF8(info->mod);
- }
- return nullptr;
- }
- }
-
- property Attribs Attributes
- {
- Attribs get()
- {
- Attribs res = Attribs::None;
-
- if (auto info = Detail::GetLabelInfo(_address))
- {
- if (info->manual)
- res = static_cast(static_cast(res) | static_cast(Attribs::Manual));
-
- if (Detail::LabelIsTemporary(_address))
- res = static_cast(static_cast(res) | static_cast(Attribs::Temporary));
- }
-
- return res;
- }
- }
-
- static Symbols::Label^ Get(System::UIntPtr address)
- {
- auto va = reinterpret_cast(address.ToPointer());
-
- Script::Label::LabelInfo info;
- if (Script::Label::GetInfo(va, &info))
- {
- Label^ res = gcnew Label(address, static_cast(info.rva));
- return res;
- }
-
- return nullptr;
- }
-
- static bool Set(System::UIntPtr address, System::String^ name, Symbols::Label::Attribs attribs)
- {
- auto va = reinterpret_cast(address.ToPointer());
-
- auto nameStr = interop::toUTF8(name);
- bool manual = (attribs & Symbols::Label::Attribs::Manual) != Symbols::Label::Attribs::None;
-
- // NOTE: Temporary is not supported until the https://github.com/x64dbg/x64dbg/pull/2695 is merged.
- bool temporary = (attribs & Label::Attribs::Manual) != Symbols::Label::Attribs::None;
-
- return Script::Label::Set(va, nameStr.c_str(), manual, temporary);
- }
-
- static bool Remove(System::UIntPtr address)
- {
- auto va = reinterpret_cast(address.ToPointer());
-
- return Script::Label::Delete(va);
- }
- };
-
- public:
- /// Function
- /////////////////////////////////////////////////////////////////////////////
- ref class Function : public Symbol
- {
- System::UIntPtr _address;
- uint32_t _rva;
-
- internal:
- Function(System::UIntPtr address, uint32_t rva)
- {
- _address = address;
- }
-
- public:
- property Symbol::Type SymbolType
- {
- virtual Symbol::Type get()
- {
- return Symbol::Type::Function;
- }
- }
-
- property System::UIntPtr Address
- {
- virtual System::UIntPtr get()
- {
- return _address;
- }
- }
-
- property uint32_t RVA
- {
- virtual uint32_t get()
- {
- return _rva;
- }
- }
-
- property int Size
- {
- virtual int get()
- {
- if (auto info = Detail::GetFuncInfo(_address))
- {
- return static_cast(info->rvaEnd - info->rvaStart);
- }
- return 0;
- }
- }
-
- property System::String^ Text
- {
- virtual System::String^ get()
- {
- return gcnew System::String("");
- }
- }
-
- property System::String^ Module
- {
- virtual System::String^ get()
- {
- if (auto info = Detail::GetFuncInfo(_address))
- {
- return interop::stringFromUTF8(info->mod);
- }
- return nullptr;
- }
- }
-
- static Symbols::Function^ Get(System::UIntPtr address)
- {
- if (auto info = Detail::GetFuncInfo(address))
- {
- Symbols::Function^ res = gcnew Symbols::Function(address, (uint32_t)info->rvaStart);
- return res;
- }
- return nullptr;
- }
-
- static bool Set(System::UIntPtr startAddress, System::UIntPtr endAddress, bool manual)
- {
- auto startVA = reinterpret_cast(startAddress.ToPointer());
- auto endVA = reinterpret_cast(startAddress.ToPointer());
-
- return Script::Function::Add(startVA, endVA, manual, 0);
- }
-
- static bool Remove(System::UIntPtr address)
- {
- auto va = reinterpret_cast(address.ToPointer());
- return Script::Function::Delete(va);
- }
- };
-
- public:
- /// Comment
- /////////////////////////////////////////////////////////////////////////////
- ref class Comment : public Symbol
- {
- System::UIntPtr _address;
- uint32_t _rva;
-
- internal:
- Comment(System::UIntPtr address, uint32_t rva)
- {
- _address = address;
- }
-
- public:
- property Symbol::Type SymbolType
- {
- virtual Symbol::Type get()
- {
- return Symbol::Type::Comment;
- }
- }
-
- property System::UIntPtr Address
- {
- virtual System::UIntPtr get()
- {
- return _address;
- }
- }
-
- property uint32_t RVA
- {
- virtual uint32_t get()
- {
- return _rva;
- }
- }
-
- property int Size
- {
- virtual int get()
- {
- return 0;
- }
- }
-
- property System::String^ Text
- {
- virtual System::String^ get()
- {
- if (auto cmtInfo = Detail::GetCommentInfo(_address))
- {
- return interop::stringFromUTF8(cmtInfo->text);
- }
- return nullptr;
- }
- }
-
- property System::String^ Module
- {
- virtual System::String^ get()
- {
- if (auto info = Detail::GetCommentInfo(_address))
- {
- return interop::stringFromUTF8(info->mod);
- }
- return nullptr;
- }
- }
-
- static Symbols::Comment^ Get(System::UIntPtr address)
- {
- if (auto info = Detail::GetCommentInfo(address))
- {
- Symbols::Comment^ res = gcnew Symbols::Comment(address, (uint32_t)info->rva);
- return res;
- }
- return nullptr;
- }
-
- static bool Set(System::UIntPtr address, System::String^ text, bool manual)
- {
- auto va = reinterpret_cast(address.ToPointer());
-
- auto textStr = interop::toUTF8(text);
- return Script::Comment::Set(va, textStr.c_str(), manual);
- }
-
- static bool Remove(System::UIntPtr address)
- {
- auto va = reinterpret_cast(address.ToPointer());
- return Script::Comment::Delete(va);
- }
- };
- };
-
-}
diff --git a/src/Bindings/UI.cpp b/src/Bindings/UI.cpp
index 521afad..179e3bd 100644
--- a/src/Bindings/UI.cpp
+++ b/src/Bindings/UI.cpp
@@ -17,7 +17,7 @@ namespace Dotx64Dbg::Native
///
/// Selection holds the start and end address of the selected elements in a window.
///
- ref class Selection
+ ref struct Selection
{
public:
///
@@ -158,6 +158,9 @@ namespace Dotx64Dbg::Native
static bool SetIcon(int hMenu, array^ image)
{
+ if (image == nullptr)
+ return false;
+
pin_ptr data = &image[0];
ICONDATA icon{ 0 };
@@ -221,5 +224,46 @@ namespace Dotx64Dbg::Native
return interop::stringFromUTF8(buf.get());
}
+
+ enum class MsgBoxType
+ {
+ Ok = MB_OK,
+ OkCancel = MB_OKCANCEL,
+ YesNo = MB_YESNO,
+ YesNoCancel = MB_YESNOCANCEL,
+ RetryCancel = MB_RETRYCANCEL,
+ AbortRetryIgnore = MB_ABORTRETRYIGNORE,
+ CancelTryContinue = MB_CANCELTRYCONTINUE,
+ };
+
+ enum class MsgBoxIcon
+ {
+ None = 0,
+ Error = MB_ICONERROR,
+ Question = MB_ICONQUESTION,
+ Warning = MB_ICONWARNING,
+ Information = MB_ICONINFORMATION,
+ };
+
+ enum class MsgBoxResult
+ {
+ Ok = IDOK,
+ Cancel = IDCANCEL,
+ Yes = IDYES,
+ No = IDNO,
+ Retry = IDRETRY,
+ Abort = IDABORT,
+ Ignore = IDIGNORE,
+ TryAgain = IDTRYAGAIN,
+ Continue = IDCONTINUE,
+ };
+
+ static MsgBoxResult MsgBox(System::String^ title, System::String^ message, MsgBoxType type, MsgBoxIcon icon)
+ {
+ const auto titleStr = interop::toUTF16(title);
+ const auto messageStr = interop::toUTF16(message);
+ const auto msgBoxType = (UINT)type | (UINT)icon;
+ return (MsgBoxResult)MessageBoxW(nullptr, messageStr.c_str(), titleStr.c_str(), msgBoxType);
+ }
};
}
diff --git a/src/Dotx64Dbg.sln b/src/Dotx64Dbg.sln
deleted file mode 100644
index 4041ffd..0000000
--- a/src/Dotx64Dbg.sln
+++ /dev/null
@@ -1,106 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30804.86
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Bindings", "Bindings\Bindings.vcxproj", "{A42ACB74-FD7C-4F6F-B3C4-205DFBFE827C}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dotx64Dbg.Managed", "Dotx64Managed\Dotx64Dbg.Managed.csproj", "{0BFC5B39-2F94-4552-BC95-43D20DCD9469}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Dotx64Dbg", "Dotx64Dbg\Dotx64Dbg.vcxproj", "{5153260B-62B5-41EE-B38C-C611091D4C6C}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D3FA5111-CDA5-41EB-9285-BF20005CE96A}"
- ProjectSection(SolutionItems) = preProject
- .editorconfig = .editorconfig
- EndProjectSection
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Dotx64DbgManagedTests\Tests.csproj", "{DA258F05-6D8A-4A10-B9AC-E01F8249B060}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "asmjit", "asmjit\asmjit.vcxproj", "{401E7506-9879-4C5C-8638-6664852FBFFF}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Dotx64Dbg.Loader", "Dotx64DbgLoader\Dotx64DbgLoader.vcxproj", "{D92BDD0D-DA10-4539-9BF1-2604EB392322}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zydis", "zydis\zydis.vcxproj", "{333CF7B7-CD5B-4F09-B402-81C31D5E6E28}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zycore", "zycore\zycore.vcxproj", "{7D3A69F9-4055-47D3-8474-B62174E93DE8}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|x64 = Debug|x64
- Debug|x86 = Debug|x86
- Release|x64 = Release|x64
- Release|x86 = Release|x86
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {A42ACB74-FD7C-4F6F-B3C4-205DFBFE827C}.Debug|x64.ActiveCfg = Debug|x64
- {A42ACB74-FD7C-4F6F-B3C4-205DFBFE827C}.Debug|x64.Build.0 = Debug|x64
- {A42ACB74-FD7C-4F6F-B3C4-205DFBFE827C}.Debug|x86.ActiveCfg = Debug|Win32
- {A42ACB74-FD7C-4F6F-B3C4-205DFBFE827C}.Debug|x86.Build.0 = Debug|Win32
- {A42ACB74-FD7C-4F6F-B3C4-205DFBFE827C}.Release|x64.ActiveCfg = Release|x64
- {A42ACB74-FD7C-4F6F-B3C4-205DFBFE827C}.Release|x64.Build.0 = Release|x64
- {A42ACB74-FD7C-4F6F-B3C4-205DFBFE827C}.Release|x86.ActiveCfg = Release|Win32
- {A42ACB74-FD7C-4F6F-B3C4-205DFBFE827C}.Release|x86.Build.0 = Release|Win32
- {0BFC5B39-2F94-4552-BC95-43D20DCD9469}.Debug|x64.ActiveCfg = Debug|x64
- {0BFC5B39-2F94-4552-BC95-43D20DCD9469}.Debug|x64.Build.0 = Debug|x64
- {0BFC5B39-2F94-4552-BC95-43D20DCD9469}.Debug|x86.ActiveCfg = Debug|x86
- {0BFC5B39-2F94-4552-BC95-43D20DCD9469}.Debug|x86.Build.0 = Debug|x86
- {0BFC5B39-2F94-4552-BC95-43D20DCD9469}.Release|x64.ActiveCfg = Release|x64
- {0BFC5B39-2F94-4552-BC95-43D20DCD9469}.Release|x64.Build.0 = Release|x64
- {0BFC5B39-2F94-4552-BC95-43D20DCD9469}.Release|x86.ActiveCfg = Release|x86
- {0BFC5B39-2F94-4552-BC95-43D20DCD9469}.Release|x86.Build.0 = Release|x86
- {5153260B-62B5-41EE-B38C-C611091D4C6C}.Debug|x64.ActiveCfg = Debug|x64
- {5153260B-62B5-41EE-B38C-C611091D4C6C}.Debug|x64.Build.0 = Debug|x64
- {5153260B-62B5-41EE-B38C-C611091D4C6C}.Debug|x86.ActiveCfg = Debug|Win32
- {5153260B-62B5-41EE-B38C-C611091D4C6C}.Debug|x86.Build.0 = Debug|Win32
- {5153260B-62B5-41EE-B38C-C611091D4C6C}.Release|x64.ActiveCfg = Release|x64
- {5153260B-62B5-41EE-B38C-C611091D4C6C}.Release|x64.Build.0 = Release|x64
- {5153260B-62B5-41EE-B38C-C611091D4C6C}.Release|x86.ActiveCfg = Release|Win32
- {5153260B-62B5-41EE-B38C-C611091D4C6C}.Release|x86.Build.0 = Release|Win32
- {DA258F05-6D8A-4A10-B9AC-E01F8249B060}.Debug|x64.ActiveCfg = Debug|x64
- {DA258F05-6D8A-4A10-B9AC-E01F8249B060}.Debug|x64.Build.0 = Debug|x64
- {DA258F05-6D8A-4A10-B9AC-E01F8249B060}.Debug|x86.ActiveCfg = Debug|x86
- {DA258F05-6D8A-4A10-B9AC-E01F8249B060}.Debug|x86.Build.0 = Debug|x86
- {DA258F05-6D8A-4A10-B9AC-E01F8249B060}.Release|x64.ActiveCfg = Release|x64
- {DA258F05-6D8A-4A10-B9AC-E01F8249B060}.Release|x64.Build.0 = Release|x64
- {DA258F05-6D8A-4A10-B9AC-E01F8249B060}.Release|x86.ActiveCfg = Release|x86
- {DA258F05-6D8A-4A10-B9AC-E01F8249B060}.Release|x86.Build.0 = Release|x86
- {401E7506-9879-4C5C-8638-6664852FBFFF}.Debug|x64.ActiveCfg = Debug|x64
- {401E7506-9879-4C5C-8638-6664852FBFFF}.Debug|x64.Build.0 = Debug|x64
- {401E7506-9879-4C5C-8638-6664852FBFFF}.Debug|x86.ActiveCfg = Debug|Win32
- {401E7506-9879-4C5C-8638-6664852FBFFF}.Debug|x86.Build.0 = Debug|Win32
- {401E7506-9879-4C5C-8638-6664852FBFFF}.Release|x64.ActiveCfg = Release|x64
- {401E7506-9879-4C5C-8638-6664852FBFFF}.Release|x64.Build.0 = Release|x64
- {401E7506-9879-4C5C-8638-6664852FBFFF}.Release|x86.ActiveCfg = Release|Win32
- {401E7506-9879-4C5C-8638-6664852FBFFF}.Release|x86.Build.0 = Release|Win32
- {D92BDD0D-DA10-4539-9BF1-2604EB392322}.Debug|x64.ActiveCfg = Debug|x64
- {D92BDD0D-DA10-4539-9BF1-2604EB392322}.Debug|x64.Build.0 = Debug|x64
- {D92BDD0D-DA10-4539-9BF1-2604EB392322}.Debug|x86.ActiveCfg = Debug|Win32
- {D92BDD0D-DA10-4539-9BF1-2604EB392322}.Debug|x86.Build.0 = Debug|Win32
- {D92BDD0D-DA10-4539-9BF1-2604EB392322}.Release|x64.ActiveCfg = Release|x64
- {D92BDD0D-DA10-4539-9BF1-2604EB392322}.Release|x64.Build.0 = Release|x64
- {D92BDD0D-DA10-4539-9BF1-2604EB392322}.Release|x86.ActiveCfg = Release|Win32
- {D92BDD0D-DA10-4539-9BF1-2604EB392322}.Release|x86.Build.0 = Release|Win32
- {333CF7B7-CD5B-4F09-B402-81C31D5E6E28}.Debug|x64.ActiveCfg = Debug|x64
- {333CF7B7-CD5B-4F09-B402-81C31D5E6E28}.Debug|x64.Build.0 = Debug|x64
- {333CF7B7-CD5B-4F09-B402-81C31D5E6E28}.Debug|x86.ActiveCfg = Debug|Win32
- {333CF7B7-CD5B-4F09-B402-81C31D5E6E28}.Debug|x86.Build.0 = Debug|Win32
- {333CF7B7-CD5B-4F09-B402-81C31D5E6E28}.Release|x64.ActiveCfg = Release|x64
- {333CF7B7-CD5B-4F09-B402-81C31D5E6E28}.Release|x64.Build.0 = Release|x64
- {333CF7B7-CD5B-4F09-B402-81C31D5E6E28}.Release|x86.ActiveCfg = Release|Win32
- {333CF7B7-CD5B-4F09-B402-81C31D5E6E28}.Release|x86.Build.0 = Release|Win32
- {7D3A69F9-4055-47D3-8474-B62174E93DE8}.Debug|x64.ActiveCfg = Debug|x64
- {7D3A69F9-4055-47D3-8474-B62174E93DE8}.Debug|x64.Build.0 = Debug|x64
- {7D3A69F9-4055-47D3-8474-B62174E93DE8}.Debug|x86.ActiveCfg = Debug|Win32
- {7D3A69F9-4055-47D3-8474-B62174E93DE8}.Debug|x86.Build.0 = Debug|Win32
- {7D3A69F9-4055-47D3-8474-B62174E93DE8}.Release|x64.ActiveCfg = Release|x64
- {7D3A69F9-4055-47D3-8474-B62174E93DE8}.Release|x64.Build.0 = Release|x64
- {7D3A69F9-4055-47D3-8474-B62174E93DE8}.Release|x86.ActiveCfg = Release|Win32
- {7D3A69F9-4055-47D3-8474-B62174E93DE8}.Release|x86.Build.0 = Release|Win32
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {7CBE0759-B87E-4C61-AC7C-E816435EE215}
- EndGlobalSection
-EndGlobal
diff --git a/src/Dotx64Dbg/Dotx64Dbg.vcxproj b/src/Dotx64Dbg/Dotx64Dbg.vcxproj
deleted file mode 100644
index dd5374d..0000000
--- a/src/Dotx64Dbg/Dotx64Dbg.vcxproj
+++ /dev/null
@@ -1,163 +0,0 @@
-
-
-
-
- Debug
- Win32
-
-
- Release
- Win32
-
-
- Debug
- x64
-
-
- Release
- x64
-
-
-
-
-
-
- 16.0
- {5153260B-62B5-41EE-B38C-C611091D4C6C}
- NetCoreCProj
- Loader
- 10.0
- net6.0
- Dotx64Dbg
-
-
-
- DynamicLibrary
- true
- v142
- NetCore
- Unicode
-
-
- DynamicLibrary
- false
- v142
- NetCore
- Unicode
-
-
- DynamicLibrary
- true
- v142
- NetCore
- Unicode
-
-
- DynamicLibrary
- false
- v142
- NetCore
- Unicode
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $(SolutionDir)..\bin\x64\plugins\
- .dll
- false
-
-
- .dll
- $(SolutionDir)..\bin\x32\plugins\
- false
-
-
- .dll
- $(SolutionDir)..\bin\x32\plugins\
- false
-
-
- .dll
- $(SolutionDir)..\bin\x64\plugins\
- false
-
-
- false
-
-
-
- Level3
- _DEBUG;%(PreprocessorDefinitions)
- $(SolutionDir)include;.;%(AdditionalIncludeDirectories)
- true
-
-
-
- $(SolutionDir)include;%(AdditionalLibraryDirectories)
-
-
-
-
- Level3
- WIN32;_DEBUG;%(PreprocessorDefinitions)
- $(SolutionDir)include;.;%(AdditionalIncludeDirectories)
- true
-
-
-
- $(SolutionDir)include;%(AdditionalLibraryDirectories)
-
-
-
-
- Level3
- WIN32;NDEBUG;%(PreprocessorDefinitions)
- $(SolutionDir)include;.;%(AdditionalIncludeDirectories)
- true
-
-
-
- $(SolutionDir)include;%(AdditionalLibraryDirectories)
-
-
-
-
- Level3
- NDEBUG;%(PreprocessorDefinitions)
- $(SolutionDir)include;.;%(AdditionalIncludeDirectories)
- true
-
-
-
- $(SolutionDir)include;%(AdditionalLibraryDirectories)
-
-
-
-
-
-
-
-
- {0bfc5b39-2f94-4552-bc95-43d20dcd9469}
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Dotx64Dbg/Dotx64Dbg.vcxproj.filters b/src/Dotx64Dbg/Dotx64Dbg.vcxproj.filters
deleted file mode 100644
index b6733b7..0000000
--- a/src/Dotx64Dbg/Dotx64Dbg.vcxproj.filters
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Dotx64Dbg/Plugin.cpp b/src/Dotx64Dbg/Plugin.cpp
index 518b0f6..e69de29 100644
--- a/src/Dotx64Dbg/Plugin.cpp
+++ b/src/Dotx64Dbg/Plugin.cpp
@@ -1,17 +0,0 @@
-#ifdef _WIN64
-#pragma comment(lib, "pluginsdk/x64dbg.lib")
-#pragma comment(lib, "pluginsdk/x64bridge.lib")
-#pragma comment(lib, "pluginsdk/DeviceNameResolver/DeviceNameResolver_x64.lib")
-#pragma comment(lib, "pluginsdk/jansson/jansson_x64.lib")
-#pragma comment(lib, "pluginsdk/lz4/lz4_x64.lib")
-#pragma comment(lib, "pluginsdk/TitanEngine/TitanEngine_x64.lib")
-#pragma comment(lib, "pluginsdk/XEDParse/XEDParse_x64.lib")
-#else
-#pragma comment(lib, "pluginsdk/x32dbg.lib")
-#pragma comment(lib, "pluginsdk/x32bridge.lib")
-#pragma comment(lib, "pluginsdk/DeviceNameResolver/DeviceNameResolver_x86.lib")
-#pragma comment(lib, "pluginsdk/jansson/jansson_x86.lib")
-#pragma comment(lib, "pluginsdk/lz4/lz4_x86.lib")
-#pragma comment(lib, "pluginsdk/TitanEngine/TitanEngine_x86.lib")
-#pragma comment(lib, "pluginsdk/XEDParse/XEDParse_x86.lib")
-#endif //_WIN64
diff --git a/src/Dotx64DbgLoader/Dotx64DbgLoader.vcxproj b/src/Dotx64DbgLoader/Dotx64DbgLoader.vcxproj
deleted file mode 100644
index 88bd8d2..0000000
--- a/src/Dotx64DbgLoader/Dotx64DbgLoader.vcxproj
+++ /dev/null
@@ -1,159 +0,0 @@
-
-
-
-
- Debug
- Win32
-
-
- Release
- Win32
-
-
- Debug
- x64
-
-
- Release
- x64
-
-
-
- 16.0
- {D92BDD0D-DA10-4539-9BF1-2604EB392322}
- NetCoreCProj
- Loader
- 10.0
- net6.0
- Dotx64Dbg.Loader
-
-
-
- DynamicLibrary
- true
- v142
- Unicode
-
-
- DynamicLibrary
- false
- v142
- Unicode
-
-
- DynamicLibrary
- true
- v142
- Unicode
-
-
- DynamicLibrary
- false
- v142
- Unicode
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $(SolutionDir)..\bin\x64\plugins\
- .dp64
- false
-
-
- .dp32
- $(SolutionDir)..\bin\x32\plugins\
- false
-
-
- .dp32
- $(SolutionDir)..\bin\x32\plugins\
-
-
- .dp64
- $(SolutionDir)..\bin\x64\plugins\
-
-
-
- Level3
- _DEBUG;%(PreprocessorDefinitions)
- $(SolutionDir)include;.;%(AdditionalIncludeDirectories)
- true
- false
- stdcpp17
- MultiThreadedDebug
- ProgramDatabase
-
-
-
- $(SolutionDir)include;%(AdditionalLibraryDirectories)
-
-
-
-
- Level3
- WIN32;_DEBUG;%(PreprocessorDefinitions)
- $(SolutionDir)include;.;%(AdditionalIncludeDirectories)
- true
- false
- stdcpp17
- MultiThreadedDebug
- ProgramDatabase
-
-
-
- $(SolutionDir)include;%(AdditionalLibraryDirectories)
-
-
-
-
- Level3
- WIN32;NDEBUG;%(PreprocessorDefinitions)
- $(SolutionDir)include;.;%(AdditionalIncludeDirectories)
- true
- false
- stdcpp17
- MultiThreaded
-
-
-
- $(SolutionDir)include;%(AdditionalLibraryDirectories)
-
-
-
-
- Level3
- NDEBUG;%(PreprocessorDefinitions)
- $(SolutionDir)include;.;%(AdditionalIncludeDirectories)
- true
- false
- stdcpp17
- MultiThreaded
-
-
-
- $(SolutionDir)include;%(AdditionalLibraryDirectories)
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Dotx64DbgLoader/Dotx64DbgLoader.vcxproj.filters b/src/Dotx64DbgLoader/Dotx64DbgLoader.vcxproj.filters
deleted file mode 100644
index 033ef10..0000000
--- a/src/Dotx64DbgLoader/Dotx64DbgLoader.vcxproj.filters
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Dotx64DbgLoader/Loader.cpp b/src/Dotx64DbgLoader/Loader.cpp
index db237ea..3b86675 100644
--- a/src/Dotx64DbgLoader/Loader.cpp
+++ b/src/Dotx64DbgLoader/Loader.cpp
@@ -3,14 +3,6 @@
#include "pluginsdk/_scriptapi_memory.h"
#include "pluginsdk/_scriptapi_register.h"
-#ifdef _WIN64
-#pragma comment(lib, "pluginsdk/x64dbg.lib")
-#pragma comment(lib, "pluginsdk/x64bridge.lib")
-#else
-#pragma comment(lib, "pluginsdk/x32dbg.lib")
-#pragma comment(lib, "pluginsdk/x32bridge.lib")
-#endif //_WIN64
-
static HMODULE _module{};
template
@@ -158,31 +150,94 @@ void CBSCRIPTAUTOCOMPLETE(const char* text, char** entries, int* entryCount)
return f(text, entries, entryCount);
}
-PLUG_EXPORT bool pluginit(PLUG_INITSTRUCT* initStruct)
+static HMODULE _thisModule = nullptr;
+
+int DllMain(HMODULE hmodule, DWORD reason, LPVOID reserved)
+{
+ if (reason == DLL_PROCESS_ATTACH)
+ {
+ _thisModule = hmodule;
+ }
+ return TRUE;
+}
+
+static int exceptionHandler(int code, PEXCEPTION_POINTERS ex)
{
-#ifdef _M_AMD64
- HMODULE curModule = GetModuleHandleA("Dotx64Dbg.Loader.dp64");
+ _plugin_logprintf("Exception while trying to load Dotx64Dbg (%08X)\n", code);
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+static bool checkLegacyInstall()
+{
+ // If Dotx64Dbg.Loader.dp32 exists in the main plugin folder refuse to load.
+ wchar_t curPath[1024]{};
+ GetModuleFileNameW(nullptr, curPath, sizeof(curPath) / sizeof(wchar_t));
+
+ if (auto* p = wcsrchr(curPath, L'\\'); p != nullptr)
+ {
+ *p = '\0';
+ }
+
+ wchar_t dllPath[1024]{};
+#if _X86_
+ swprintf_s(dllPath, L"%s\\plugins\\Dotx64Dbg.Loader.dp32", curPath);
#else
- HMODULE curModule = GetModuleHandleA("Dotx64Dbg.Loader.dp32");
+ swprintf_s(dllPath, L"%s\\plugins\\Dotx64Dbg.Loader.dp64", curPath);
#endif
- char curPath[1024]{};
- GetModuleFileNameA(curModule, curPath, sizeof(curPath));
+ if (GetFileAttributesW(dllPath) != INVALID_FILE_ATTRIBUTES)
+ {
+ _plugin_lograw_html("Dotx64Dbg.Loader.dp32 found in main plugin folder, please delete the old install.\n");
+ return true;
+ }
+
+ return false;
+}
+
+PLUG_EXPORT bool pluginit(PLUG_INITSTRUCT* initStruct)
+{
+ // Check for the legacy install.
+ if (checkLegacyInstall())
+ return false;
+
+ wchar_t curPath[1024]{};
+ GetModuleFileNameW(_thisModule, curPath, sizeof(curPath) / sizeof(wchar_t));
- if (auto* p = strrchr(curPath, '\\'); p != nullptr)
+ if (auto* p = wcsrchr(curPath, L'\\'); p != nullptr)
{
*p = '\0';
}
- char dllPath[1024]{};
- sprintf_s(dllPath, "%s\\Dotx64Dbg.dll", curPath);
+ wchar_t dllPath[1024]{};
+ swprintf_s(dllPath, L"%s\\Dotx64Dbg.dll", curPath);
- _module = LoadLibraryA(dllPath);
- if (_module == nullptr)
+ bool loadingError = false;
+
+ __try
{
- _plugin_logprintf("Unable to load Dotx64Dbg, make sure you have following installed:\n"
- "- .NET 6.0 Runtime (https://dotnet.microsoft.com/download/dotnet/6.0)\n"
- "- Visual Studio 2019 Runtime (https://support.microsoft.com/en-us/topic/the-latest-supported-visual-c-downloads-2647da03-1eea-4433-9aff-95f26a218cc0)\n"
+ _module = LoadLibraryW(dllPath);
+ if (_module == nullptr)
+ {
+ loadingError = true;
+ }
+ }
+ __except (exceptionHandler(GetExceptionCode(), GetExceptionInformation()))
+ {
+ loadingError = true;
+ }
+
+ if (loadingError)
+ {
+#if _X86_
+ static const wchar_t* arch = L"x86";
+#else
+ static const wchar_t* arch = L"x64";
+#endif
+ _plugin_logprintf("Unable to load Dotx64Dbg (%08X), make sure you have following installed:\n"
+ "- .NET 6.0 %s Runtime (https://dotnet.microsoft.com/download/dotnet/6.0)\n"
+ "- Visual Studio 2019 Runtime (https://support.microsoft.com/en-us/topic/the-latest-supported-visual-c-downloads-2647da03-1eea-4433-9aff-95f26a218cc0)\n",
+ GetLastError(),
+ arch
);
return false;
}
diff --git a/src/Dotx64DbgManagedTests/Tests.csproj b/src/Dotx64DbgManagedTests/Tests.csproj
deleted file mode 100644
index 887fe51..0000000
--- a/src/Dotx64DbgManagedTests/Tests.csproj
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
- net6.0-windows
- neutral
- x86;x64
- false
- false
- false
-
- Exe
-
- Dotx64Dbg.Managed.Tests
-
-
-
- x64
- ..\..\bin\x64\tests
- TRACE;_X64_
-
-
-
- x86
- ..\..\bin\x32\tests
- TRACE;_X86_
-
-
-
- ..\..\bin\x64\tests
- TRACE;_X64_
-
-
-
- ..\..\bin\x32\tests
- TRACE;_X86_
-
-
-
-
-
-
-
-
diff --git a/src/Dotx64DbgManagedTests/Tests/Tests.Decoder.cs b/src/Dotx64DbgManagedTests/Tests/Tests.Decoder.cs
deleted file mode 100644
index 8962fd9..0000000
--- a/src/Dotx64DbgManagedTests/Tests/Tests.Decoder.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Dotx64Dbg.Managed.Tests
-{
- using static Testing;
- using static Operands;
-
- class TestDecoder
- {
-
- }
-}
diff --git a/src/Dotx64DbgManagedTests/Runner.cs b/src/Dotx64DbgTests/Runner.cs
similarity index 96%
rename from src/Dotx64DbgManagedTests/Runner.cs
rename to src/Dotx64DbgTests/Runner.cs
index 4493cc3..7a5164f 100644
--- a/src/Dotx64DbgManagedTests/Runner.cs
+++ b/src/Dotx64DbgTests/Runner.cs
@@ -19,13 +19,6 @@ private static void Write(ConsoleColor color, string str)
Console.ForegroundColor = col;
}
- private static void WriteLine(ConsoleColor color, string str)
- {
- var col = Console.ForegroundColor;
- Console.ForegroundColor = color;
- Console.Write(str);
- Console.ForegroundColor = col;
- }
private static void WriteLine(string str)
{
Console.WriteLine(str);
@@ -219,4 +212,4 @@ public static void Main(string[] args)
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Dotx64DbgManagedTests/Testing.cs b/src/Dotx64DbgTests/Testing.cs
similarity index 100%
rename from src/Dotx64DbgManagedTests/Testing.cs
rename to src/Dotx64DbgTests/Testing.cs
diff --git a/src/Dotx64DbgManagedTests/Tests/Tests.Assembler.cs b/src/Dotx64DbgTests/Tests/Tests.Assembler.cs
similarity index 98%
rename from src/Dotx64DbgManagedTests/Tests/Tests.Assembler.cs
rename to src/Dotx64DbgTests/Tests/Tests.Assembler.cs
index f0a9817..f5979b3 100644
--- a/src/Dotx64DbgManagedTests/Tests/Tests.Assembler.cs
+++ b/src/Dotx64DbgTests/Tests/Tests.Assembler.cs
@@ -1,13 +1,7 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
namespace Dotx64Dbg.Managed.Tests
{
- using static Testing;
using static Operands;
+ using static Testing;
class TestAssembler
{
diff --git a/src/Dotx64DbgTests/Tests/Tests.Decoder.cs b/src/Dotx64DbgTests/Tests/Tests.Decoder.cs
new file mode 100644
index 0000000..a8d8c14
--- /dev/null
+++ b/src/Dotx64DbgTests/Tests/Tests.Decoder.cs
@@ -0,0 +1,7 @@
+namespace Dotx64Dbg.Managed.Tests
+{
+ class TestDecoder
+ {
+
+ }
+}
diff --git a/src/Dotx64DbgManagedTests/Tests/Tests.Generator.cs b/src/Dotx64DbgTests/Tests/Tests.Generator.cs
similarity index 96%
rename from src/Dotx64DbgManagedTests/Tests/Tests.Generator.cs
rename to src/Dotx64DbgTests/Tests/Tests.Generator.cs
index 08c6fd5..0142ce8 100644
--- a/src/Dotx64DbgManagedTests/Tests/Tests.Generator.cs
+++ b/src/Dotx64DbgTests/Tests/Tests.Generator.cs
@@ -1,14 +1,7 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Dotx64Dbg;
-
namespace Dotx64Dbg.Managed.Tests
{
- using static Testing;
using static Operands;
+ using static Testing;
class TestInstructionGenerator
{
diff --git a/src/Dotx64DbgManagedTests/Tests/Tests.Operands.cs b/src/Dotx64DbgTests/Tests/Tests.Operands.cs
similarity index 94%
rename from src/Dotx64DbgManagedTests/Tests/Tests.Operands.cs
rename to src/Dotx64DbgTests/Tests/Tests.Operands.cs
index 7bf7441..95a1eb7 100644
--- a/src/Dotx64DbgManagedTests/Tests/Tests.Operands.cs
+++ b/src/Dotx64DbgTests/Tests/Tests.Operands.cs
@@ -1,13 +1,6 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
namespace Dotx64Dbg.Managed.Tests
{
using static Testing;
- using static Operands;
class TestOperands
{
diff --git a/src/Dotx64DbgManagedTests/Tests/Tests.RegisterMaskGp.cs b/src/Dotx64DbgTests/Tests/Tests.RegisterMaskGp.cs
similarity index 98%
rename from src/Dotx64DbgManagedTests/Tests/Tests.RegisterMaskGp.cs
rename to src/Dotx64DbgTests/Tests/Tests.RegisterMaskGp.cs
index a2dbc37..d8e68c9 100644
--- a/src/Dotx64DbgManagedTests/Tests/Tests.RegisterMaskGp.cs
+++ b/src/Dotx64DbgTests/Tests/Tests.RegisterMaskGp.cs
@@ -1,8 +1,4 @@
-using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace Dotx64Dbg.Managed.Tests
{
diff --git a/src/Dotx64DbgManagedTests/Tests/Tests.Registers.cs b/src/Dotx64DbgTests/Tests/Tests.Registers.cs
similarity index 99%
rename from src/Dotx64DbgManagedTests/Tests/Tests.Registers.cs
rename to src/Dotx64DbgTests/Tests/Tests.Registers.cs
index f95c55a..80ac584 100644
--- a/src/Dotx64DbgManagedTests/Tests/Tests.Registers.cs
+++ b/src/Dotx64DbgTests/Tests/Tests.Registers.cs
@@ -1,10 +1,3 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Diagnostics;
-
namespace Dotx64Dbg.Managed.Tests
{
using static Testing;
diff --git a/src/Dotx64Managed/API/Platform.cs b/src/Dotx64Managed/API/Platform.cs
new file mode 100644
index 0000000..f0ec237
--- /dev/null
+++ b/src/Dotx64Managed/API/Platform.cs
@@ -0,0 +1,26 @@
+namespace Dotx64Dbg
+{
+ public static partial class Platform
+ {
+
+ public static string OpenFolderBrowse(string title)
+ {
+ return Native.Platform.BrowseForFolder(title);
+ }
+
+ public static string OpenFileBrowse(string title, string filter)
+ {
+ return Native.Platform.OpenFileBrowse(title, filter);
+ }
+
+ public static string SaveFileBrowse(string title, string filter)
+ {
+ return Native.Platform.SaveFileBrowse(title, filter);
+ }
+
+ public static void SetClipboardText(string text)
+ {
+ Native.Platform.SetClipboardText(text);
+ }
+ }
+}
diff --git a/src/Dotx64Managed/API/UI/UI.cs b/src/Dotx64Managed/API/UI/UI.cs
index b76da59..8e68357 100644
--- a/src/Dotx64Managed/API/UI/UI.cs
+++ b/src/Dotx64Managed/API/UI/UI.cs
@@ -1,9 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Dotx64Dbg;
namespace Dotx64Dbg
{
@@ -20,11 +15,42 @@ public enum WindowType
Types = Native.UI.WindowType.Types,
};
+ public enum MsgBoxType
+ {
+ Ok = Native.UI.MsgBoxType.Ok,
+ OkCancel = Native.UI.MsgBoxType.OkCancel,
+ YesNo = Native.UI.MsgBoxType.YesNo,
+ YesNoCancel = Native.UI.MsgBoxType.YesNoCancel,
+ };
+
+ public enum MsgBoxResult
+ {
+ Ok = Native.UI.MsgBoxResult.Ok,
+ Cancel = Native.UI.MsgBoxResult.Cancel,
+ Yes = Native.UI.MsgBoxResult.Yes,
+ No = Native.UI.MsgBoxResult.No,
+ };
+
+ public enum MsgBoxIcon
+ {
+ None = Native.UI.MsgBoxIcon.None,
+ Error = Native.UI.MsgBoxIcon.Error,
+ Warning = Native.UI.MsgBoxIcon.Warning,
+ Information = Native.UI.MsgBoxIcon.Information,
+ Question = Native.UI.MsgBoxIcon.Question,
+ };
+
public class Selection
{
- public Selection() { }
+ public Selection()
+ {
+ }
- public Selection(ulong start, ulong end) { Start = (nuint)start; End = (nuint)end; }
+ public Selection(ulong start, ulong end)
+ {
+ Start = (nuint)start;
+ End = (nuint)end;
+ }
internal Selection(Native.UI.Selection sel)
{
@@ -60,7 +86,10 @@ internal Native.UI.Selection ToNative()
//
// Summary:
// The size of the selection, End - Start.
- public nuint Size { get => End - Start; }
+ public nuint Size
+ {
+ get => End - Start;
+ }
}
///
@@ -91,17 +120,21 @@ public class UpdateSuppressor : IDisposable
public UpdateSuppressor()
{
wasEnabled = UpdatesEnabled;
- if(wasEnabled)
+ if (wasEnabled)
UpdatesEnabled = false;
}
public void Dispose()
{
- if(wasEnabled)
+ if (wasEnabled)
UpdatesEnabled = true;
}
}
- }
+ public static MsgBoxResult MsgBox(string title, string text, MsgBoxType type = MsgBoxType.Ok, MsgBoxIcon icon = MsgBoxIcon.None)
+ {
+ return (MsgBoxResult)Native.UI.MsgBox(title, text, (Native.UI.MsgBoxType)type, (Native.UI.MsgBoxIcon)icon);
+ }
+ }
}
diff --git a/src/Dotx64Managed/Compiler.cs b/src/Dotx64Managed/Compiler.cs
index 2d32f0b..3f62f92 100644
--- a/src/Dotx64Managed/Compiler.cs
+++ b/src/Dotx64Managed/Compiler.cs
@@ -1,4 +1,4 @@
-using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Emit;
@@ -21,7 +21,10 @@ class Compiler
public class Result
{
internal bool success = false;
- public bool Success { get => success; }
+ public bool Success
+ {
+ get => success;
+ }
public string OutputAssemblyPath;
public MemoryStream AssemblyStream;
public MemoryStream DebugStream;
@@ -67,7 +70,7 @@ public Result Compile(string[] files, bool forScripting = false)
success = false
};
}
- return Compile(parsed, forScripting);
+ return CompileInternal(parsed, forScripting);
}
catch (System.Exception ex)
{
@@ -82,7 +85,7 @@ public Result Compile(string code)
try
{
List parsed = new() { ParseCode(code, true) };
- return Compile(parsed, true);
+ return CompileInternal(parsed, true);
}
catch (System.Exception ex)
{
@@ -92,7 +95,7 @@ public Result Compile(string code)
return new Result();
}
- private Result Compile(List parsed, bool forScripting = false)
+ private Result CompileInternal(List parsed, bool forScripting = false)
{
var coreAssemblyPath = Path.GetDirectoryName(typeof(object).Assembly.Location);
@@ -104,9 +107,6 @@ private Result Compile(List parsed, bool forScripting = false)
assemblyRefs.Add(typeof(System.Runtime.AssemblyTargetedPatchBandAttribute).Assembly.Location);
assemblyRefs.Add(typeof(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo).Assembly.Location);
assemblyRefs.Add(typeof(Native.Logging).Assembly.Location);
- assemblyRefs.Add(typeof(System.Windows.Forms.Application).Assembly.Location);
- assemblyRefs.Add(typeof(System.Drawing.Bitmap).Assembly.Location);
- assemblyRefs.Add(typeof(System.Drawing.SizeF).Assembly.Location);
assemblyRefs.Add(typeof(System.ComponentModel.Component).Assembly.Location);
assemblyRefs.Add(typeof(System.Data.AcceptRejectRule).Assembly.Location);
@@ -141,9 +141,9 @@ private Result Compile(List parsed, bool forScripting = false)
.WithOptimizationLevel(OptimizationLevel.Debug)
.WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default)
#if _X86_
- .WithPlatform(Platform.X86)
+ .WithPlatform(Microsoft.CodeAnalysis.Platform.X86)
#else
- .WithPlatform(Platform.X64)
+ .WithPlatform(Microsoft.CodeAnalysis.Platform.X64)
#endif
.WithModuleName(Name + guid)
;
diff --git a/src/Dotx64Managed/Dotx64Dbg.Managed.csproj b/src/Dotx64Managed/Dotx64Dbg.Managed.csproj
deleted file mode 100644
index 054af18..0000000
--- a/src/Dotx64Managed/Dotx64Dbg.Managed.csproj
+++ /dev/null
@@ -1,91 +0,0 @@
-
-
-
- net6.0-windows
- Library
- true
- x64;x86
- neutral
- true
- false
-
-
-
- false
- false
- false
-
-
-
- x86
- DEBUG;TRACE;_X86_
- ..\..\bin\x32\plugins\Dotx64Dbg.Managed.xml
- ..\..\bin\x32\plugins
-
-
-
- true
- Dotx64Dbg
-
-
-
- x64
- DEBUG;TRACE;_X64_
- ..\..\bin\x64\plugins\Dotx64Dbg.Managed.xml
- ..\..\bin\x64\plugins
-
-
-
- TRACE;_X86_
- ..\..\bin\x32\plugins\Dotx64Dbg.Managed.xml
- ..\..\bin\x32\plugins
-
-
-
- TRACE;_X64_
- ..\..\bin\x64\plugins\Dotx64Dbg.Managed.xml
- ..\..\bin\x64\plugins
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- True
- True
- Resources.resx
-
-
-
-
-
- ResXFileCodeGenerator
- Resources.Designer.cs
-
-
-
-
diff --git a/src/Dotx64Managed/Menus.Main.cs b/src/Dotx64Managed/Menus.Main.cs
index 7404355..61dd152 100644
--- a/src/Dotx64Managed/Menus.Main.cs
+++ b/src/Dotx64Managed/Menus.Main.cs
@@ -1,6 +1,5 @@
using System.Diagnostics;
using System.IO;
-using System.Windows.Forms;
namespace Dotx64Dbg
{
@@ -8,15 +7,12 @@ internal static partial class Menus
{
internal static void RunScript()
{
- OpenFileDialog fdlg = new OpenFileDialog();
- fdlg.Title = "Open Dotx64Dbg Script";
- fdlg.Filter = ".cs (*.cs)|*.cs|All files (*.*)|*.*";
- fdlg.FilterIndex = 1;
- fdlg.RestoreDirectory = true;
- if (fdlg.ShowDialog() == DialogResult.OK)
- {
- ScriptLoader.ExecuteScriptFile(fdlg.FileName);
- }
+ var fileFilter = "C# File (*.cs)|*.cs|All files (*.*)|*.*";
+ var scriptPath = Platform.OpenFileBrowse("Open Dotx64Dbg Script", fileFilter);
+ if (scriptPath == null)
+ return;
+
+ ScriptLoader.ExecuteScriptFile(scriptPath);
}
internal static void OpenEditor(string projectPath)
@@ -40,7 +36,7 @@ internal static string PromptPluginName()
if (plugins.IsPluginNameTaken(pluginName))
{
- MessageBox.Show("A plugin with the specified name already exists.\n");
+ UI.MsgBox("Error", "A plugin with the specified name already exists.", UI.MsgBoxType.Ok);
continue;
}
@@ -59,7 +55,7 @@ internal static void CreateNewPlugin()
var pluginPath = plugins.CreatePluginTemplate(pluginName);
if (pluginPath == null)
{
- MessageBox.Show("Failed to create new plugin\n");
+ UI.MsgBox("Error", "Failed to create new plugin", UI.MsgBoxType.Ok);
return;
}
@@ -69,10 +65,10 @@ internal static void CreateNewPlugin()
internal static void InitializeMainMenu()
{
// Plugin icon
- Native.UI.Menu.SetIcon(MainMenu, ImageToBytes(Properties.Resources.Dotx64DbgIcon));
+ Native.UI.Menu.SetIcon(MainMenu, Resources.GetData("Dotx64DbgIcon"));
- AddMenu("Main/Run Script", Properties.Resources.RunIcon, RunScript);
- AddMenu("Main/Create Plugin", Properties.Resources.NewScriptIcon, CreateNewPlugin);
+ AddMenu("Main/Run Script", Resources.GetData("RunIcon"), RunScript);
+ AddMenu("Main/Create Plugin", Resources.GetData("NewScriptIcon"), CreateNewPlugin);
AddSeperator("Main");
}
@@ -119,11 +115,11 @@ internal static void AddPluginMenu(Plugin plugin)
return;
var info = plugin.Info;
- MessageBox.Show($"Name: {info.Name}\n" +
+ UI.MsgBox(info.Name,
$"Author: {info.Author}\n" +
$"Version: {info.Version}\n" +
$"Website: {info.Website}\n" +
- $"Description: {info.Description}", info.Name, MessageBoxButtons.OK, MessageBoxIcon.Information);
+ $"Description: {info.Description}", UI.MsgBoxType.Ok, UI.MsgBoxIcon.Information);
});
}
diff --git a/src/Dotx64Managed/Menus.cs b/src/Dotx64Managed/Menus.cs
index ae86b82..311add3 100644
--- a/src/Dotx64Managed/Menus.cs
+++ b/src/Dotx64Managed/Menus.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.IO;
using System.Linq;
namespace Dotx64Dbg
@@ -45,16 +44,9 @@ internal static void Initialize()
Handlers = new();
}
- internal static byte[] ImageToBytes(System.Drawing.Image image)
+ internal static byte[] ImageToBytes(Object image)
{
- if (image == null)
- return null;
-
- var ms = new MemoryStream();
-#pragma warning disable CA1416 // We only support Windows.
- image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
-#pragma warning restore CA1416
- return ms.ToArray();
+ return null;
}
internal static void InitializeMenus(MenuData data)
@@ -121,13 +113,13 @@ internal static void HandleCallback(int id)
internal static void AddMenu(string path, UI.Menu.MenuDelegate func) =>
AddMenu(path, null, func);
- internal static void AddMenu(string path, System.Drawing.Image image, UI.Menu.MenuDelegate func) =>
- AddMenu(null, path, image, func);
+ internal static void AddMenu(string path, byte[] imageData, UI.Menu.MenuDelegate func) =>
+ AddMenu(null, path, imageData, func);
internal static void AddMenu(Plugin plugin, string path, UI.Menu.MenuDelegate func) =>
AddMenu(plugin, path, null, func);
- internal static void AddMenu(Plugin plugin, string path, System.Drawing.Image image, UI.Menu.MenuDelegate func)
+ internal static void AddMenu(Plugin plugin, string path, byte[] imageData, UI.Menu.MenuDelegate func)
{
var pos = 0;
var prev = 0;
@@ -188,9 +180,8 @@ internal static void AddMenu(Plugin plugin, string path, System.Drawing.Image im
entryName = path.Substring(prev);
Native.UI.Menu.AddEntry(nextEntry.parent, nextEntry.id, entryName);
- if (image is not null)
+ if (imageData is not null)
{
- byte[] imageData = ImageToBytes(image);
Native.UI.Menu.SetEntryIcon(Manager.PluginHandle, nextEntry.id, imageData);
}
diff --git a/src/Dotx64Managed/Plugins.DependencyManager.cs b/src/Dotx64Managed/Plugins.DependencyManager.cs
index 43980d0..e80f04a 100644
--- a/src/Dotx64Managed/Plugins.DependencyManager.cs
+++ b/src/Dotx64Managed/Plugins.DependencyManager.cs
@@ -1,19 +1,18 @@
-using System;
-using System.IO;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading;
-using System.Reflection;
-
+using NuGet.Common;
using NuGet.Frameworks;
using NuGet.Packaging;
using NuGet.Packaging.Core;
using NuGet.Protocol;
using NuGet.Protocol.Core.Types;
using NuGet.Versioning;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading;
using System.Threading.Tasks;
-using NuGet.Common;
namespace Dotx64Dbg
{
@@ -21,7 +20,10 @@ internal partial class Plugins
{
internal class PluginDependencyConsumer
{
- public PluginInfo PluginInfo { get; }
+ public PluginInfo PluginInfo
+ {
+ get;
+ }
public bool HasNext => (_currentNode is null & _head.Next is not null) | _currentNode?.Next is not null;
@@ -43,7 +45,7 @@ public bool MoveNext()
{
if (!HasNext)
{
- if(_head.Next?.Resolved ?? false)
+ if (_head.Next?.Resolved ?? false)
_head.Next = null; // The last item was consumed
return false;
}
@@ -54,7 +56,7 @@ public bool MoveNext()
return true;
}
- if(_currentNode.Resolved) // Detach from list
+ if (_currentNode.Resolved) // Detach from list
{
_currentNode.Previous.Next = _currentNode.Next;
if (_currentNode.Next is not null)
@@ -116,8 +118,14 @@ class DependencyNode : IEquatable
{
public static DependencyNode Null => new();
- public DependencyNode Next { get; set; }
- public DependencyNode Previous { get; set; }
+ public DependencyNode Next
+ {
+ get; set;
+ }
+ public DependencyNode Previous
+ {
+ get; set;
+ }
public bool Resolved { get; set; } = false;
public int Id { get; } = 0;
@@ -129,7 +137,9 @@ public DependencyNode(string name)
Id = name.GetHashCode();
}
- private DependencyNode() { }
+ private DependencyNode()
+ {
+ }
public bool Equals(DependencyNode other) => Id == other.Id;
@@ -163,7 +173,7 @@ public string[] ResolvePluginDependencies(Plugin plugin, CancellationToken cance
if (!HasDependenciesChanged(plugin))
return pluginDepsCache[plugin.GetHashCode()].cachedResolvedDependencies;
- PluginDependencyConsumer dependencyConsumer = new (plugin.Info);
+ PluginDependencyConsumer dependencyConsumer = new(plugin.Info);
foreach (var resolver in resolvers)
{
@@ -173,7 +183,7 @@ public string[] ResolvePluginDependencies(Plugin plugin, CancellationToken cance
dependencyConsumer.ResetIterator();
}
- if(dependencyConsumer.HasAny)
+ if (dependencyConsumer.HasAny)
{
// TODO: Create a proper exception for this
throw new Exception("The current resolvers where not able to resolve all the dependencies");
@@ -225,7 +235,7 @@ private void AddPluginToCache(Plugin plugin, string[] resolvedDepencies)
internal class NuGetDependencyResolver : IDependencyResolver
{
static readonly string NugetSource = "https://api.nuget.org/v3/index.json";
- static string LocalNugetRepo => Path.Combine(Manager.PluginManager.PluginsPath, ".nuget");
+ static string LocalNugetRepo => Manager.PluginManager.PluginsPath;
private readonly NuGet.Common.ILogger Logger;
@@ -334,7 +344,7 @@ private static bool InitializePackageFolder(string pkgFullName, CancellationToke
// NuGet package original hash
string hashFilePath = Path.Combine(
- Path.GetDirectoryName(pkgFullName),
+ Path.GetDirectoryName(pkgFullName),
Path.GetFileNameWithoutExtension(pkgFullName) + PackagingCoreConstants.HashFileExtension);
using var hashFile = File.Create(hashFilePath);
@@ -352,7 +362,8 @@ private static bool InitializePackageFolder(string pkgFullName, CancellationToke
// Hash file
hashFile.Write(Encoding.UTF8.GetBytes(nupkgMetadataFile.ContentHash));
- } catch (IOException)
+ }
+ catch (IOException)
{
return false;
}
@@ -446,7 +457,7 @@ private LocalPackageInfo FindLocalOrDownloadPackage(string pkgId, string version
if (!DownloadPackage(pkgId, version, fs, token))
return null;
}
- if(!IsPackageInitialized(pkgFullName, token) && !InitializePackageFolder(pkgFullName, token))
+ if (!IsPackageInitialized(pkgFullName, token) && !InitializePackageFolder(pkgFullName, token))
{
Logger.LogError($"Package '{pkgId}' directory initialization failed!");
File.Delete(pkgFullName); // Maybe the nupkg is corrupted?
@@ -484,7 +495,7 @@ public class VersioningHelper
private static readonly string FrameworkNamePattern =
@"^(?[a-zA-Z.]+),Version=v(?(?[\d]+)\.(?[\d]+)(?:\.(?[\d]+))?)$";
- private readonly static System.Text.RegularExpressions.Regex Regex = new(FrameworkNamePattern);
+ private readonly static System.Text.RegularExpressions.Regex Regex = new(FrameworkNamePattern);
public static NuGet.Frameworks.NuGetFramework GetFrameworkFromAssembly(System.Reflection.Assembly assembly)
{
@@ -539,7 +550,7 @@ internal class LocalAssembliesResolver : IDependencyResolver
{
public void ResolveFullpathToDependency(PluginDependencyConsumer dependencyConsumer, CancellationToken token)
{
- while(dependencyConsumer.MoveNext())
+ while (dependencyConsumer.MoveNext())
{
token.ThrowIfCancellationRequested();
@@ -557,7 +568,7 @@ public static string[] ResolveDependencies(this Plugin plugin, Plugins.Dependenc
{
return resolver.ResolvePluginDependencies(plugin, token);
}
-
+
public static string[] ResolveDependencies(this Plugin plugin, Plugins.DependencyResolver resolver) =>
plugin.ResolveDependencies(resolver, CancellationToken.None);
}
diff --git a/src/Dotx64Managed/Plugins.cs b/src/Dotx64Managed/Plugins.cs
index 03f0c36..26c431f 100644
--- a/src/Dotx64Managed/Plugins.cs
+++ b/src/Dotx64Managed/Plugins.cs
@@ -413,7 +413,6 @@ internal bool IsPluginNameTaken(string pluginName)
return false;
}
-
public string CreatePluginTemplate(string pluginName)
{
var pluginPath = Path.Combine(Settings.PluginsPath, pluginName);
@@ -436,6 +435,8 @@ public string CreatePluginTemplate(string pluginName)
return null;
}
+ // TODO: Fixme.
+ /*
if (!Utils.WriteReplacedContents(Dotx64Dbg.Properties.Resources.plugin_json, replacements, pluginJsonPath))
{
// ERROR.
@@ -445,6 +446,7 @@ public string CreatePluginTemplate(string pluginName)
{
// ERROR.
}
+ */
return pluginPath;
}
diff --git a/src/Dotx64Managed/Properties/Resources.Designer.cs b/src/Dotx64Managed/Properties/Resources.Designer.cs
deleted file mode 100644
index 501fd1c..0000000
--- a/src/Dotx64Managed/Properties/Resources.Designer.cs
+++ /dev/null
@@ -1,139 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// This code was generated by a tool.
-// Runtime Version:4.0.30319.42000
-//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
-//
-//------------------------------------------------------------------------------
-
-namespace Dotx64Dbg.Properties {
- using System;
-
-
- ///
- /// A strongly-typed resource class, for looking up localized strings, etc.
- ///
- // This class was auto-generated by the StronglyTypedResourceBuilder
- // class via a tool like ResGen or Visual Studio.
- // To add or remove a member, edit your .ResX file then rerun ResGen
- // with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- internal class Resources {
-
- private static global::System.Resources.ResourceManager resourceMan;
-
- private static global::System.Globalization.CultureInfo resourceCulture;
-
- [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
- internal Resources() {
- }
-
- ///
- /// Returns the cached ResourceManager instance used by this class.
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Resources.ResourceManager ResourceManager {
- get {
- if (object.ReferenceEquals(resourceMan, null)) {
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Dotx64Dbg.Properties.Resources", typeof(Resources).Assembly);
- resourceMan = temp;
- }
- return resourceMan;
- }
- }
-
- ///
- /// Overrides the current thread's CurrentUICulture property for all
- /// resource lookups using this strongly typed resource class.
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Globalization.CultureInfo Culture {
- get {
- return resourceCulture;
- }
- set {
- resourceCulture = value;
- }
- }
-
- ///
- /// Looks up a localized resource of type System.Drawing.Bitmap.
- ///
- internal static System.Drawing.Bitmap Dotx64DbgIcon {
- get {
- object obj = ResourceManager.GetObject("Dotx64DbgIcon", resourceCulture);
- return ((System.Drawing.Bitmap)(obj));
- }
- }
-
- ///
- /// Looks up a localized resource of type System.Drawing.Bitmap.
- ///
- internal static System.Drawing.Bitmap NewScriptIcon {
- get {
- object obj = ResourceManager.GetObject("NewScriptIcon", resourceCulture);
- return ((System.Drawing.Bitmap)(obj));
- }
- }
-
- ///
- /// Looks up a localized string similar to using System;
- ///using Dotx64Dbg;
- ///
- ///public partial class MyPlugin : IPlugin, IHotload
- ///{
- /// /// <summary>
- /// /// Called as soon the plugin is first loaded, consequent hot-loads will not call this again.
- /// /// </summary>
- /// public MyPlugin()
- /// {
- /// Console.WriteLine("Hello World");
- /// }
- ///
- /// /// <summary>
- /// /// This is called after construction. This is also only called once.
- /// /// </summary>
- /// public void Startup()
- /// {
- /// }
- ///
- /// /// <summary>
- /// /// Classes that have [rest of string was truncated]";.
- ///
- internal static string plugin_cs {
- get {
- return ResourceManager.GetString("plugin_cs", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to {
- /// "Name": "%PLUGIN_NAME%",
- /// "Description": "",
- /// "Version": "0.0.0",
- /// "Author": "",
- /// "Website": ""
- ///}
- ///.
- ///
- internal static string plugin_json {
- get {
- return ResourceManager.GetString("plugin_json", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized resource of type System.Drawing.Bitmap.
- ///
- internal static System.Drawing.Bitmap RunIcon {
- get {
- object obj = ResourceManager.GetObject("RunIcon", resourceCulture);
- return ((System.Drawing.Bitmap)(obj));
- }
- }
- }
-}
diff --git a/src/Dotx64Managed/Properties/Resources.resx b/src/Dotx64Managed/Properties/Resources.resx
deleted file mode 100644
index 0962ad5..0000000
--- a/src/Dotx64Managed/Properties/Resources.resx
+++ /dev/null
@@ -1,136 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
-
- ..\Resources\Dotx64DbgIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\Resources\NewScript.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- ..\Template\plugin.cs;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
-
-
- ..\Template\plugin.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
-
-
- ..\Resources\Run.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
\ No newline at end of file
diff --git a/src/Dotx64Managed/Resources.cs b/src/Dotx64Managed/Resources.cs
new file mode 100644
index 0000000..814c60b
--- /dev/null
+++ b/src/Dotx64Managed/Resources.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace Dotx64Dbg
+{
+ class Resources
+ {
+ private static Dictionary _resources = new Dictionary();
+ private static string[] _resourceExtensions = new string[] { ".png", ".bmp", ".gif", ".jpg", ".jpeg", ".ico" };
+
+ static Resources()
+ {
+ var pluginPath = Utils.GetPluginPath();
+ var resourcesPath = Path.Combine(pluginPath, "Resources");
+
+ // Check if directory exists
+ if (!Directory.Exists(resourcesPath))
+ {
+ Console.Error.WriteLine($"Resources directory not found: {resourcesPath}");
+ return;
+ }
+
+ var files = Directory.EnumerateFiles(resourcesPath, "*.*", SearchOption.AllDirectories);
+ foreach (var file in files)
+ {
+ var ext = Path.GetExtension(file);
+ if (_resourceExtensions.Contains(ext))
+ {
+ // Load the contents and map filename to contents
+ var contents = File.ReadAllBytes(file);
+ var name = Path.GetFileNameWithoutExtension(file);
+ _resources[name] = contents;
+ }
+ }
+
+ Utils.DebugPrintLine($"Loaded {_resources.Count} resources");
+ }
+
+ public static byte[] GetData(string name)
+ {
+ if (_resources.TryGetValue(name, out var data))
+ return data;
+
+ Utils.DebugPrintLine($"Resource not found: {name}");
+ return null;
+ }
+ }
+}
diff --git a/src/Dotx64Managed/Utils.cs b/src/Dotx64Managed/Utils.cs
index 891891b..6a480a9 100644
--- a/src/Dotx64Managed/Utils.cs
+++ b/src/Dotx64Managed/Utils.cs
@@ -17,16 +17,15 @@ public static string GetRootPath()
return x64DbgPath;
}
- public static string GetPluginsPath()
+ // Returns the path to the folder of where this x64dbg plugin is located.
+ public static string GetPluginPath()
{
- var process = System.Diagnostics.Process.GetCurrentProcess();
- string fullPath = process.MainModule.FileName;
- string processPath = Path.GetDirectoryName(fullPath);
-
- return Path.GetFullPath(Path.Combine(processPath, "plugins"));
+ // Get the current assembly path
+ var fullPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
+ return Path.GetDirectoryName(fullPath);
}
- public static string DotX64DbgNugetDepsPath => Path.Combine(GetPluginsPath(), ".nuget");
+ public static string DotX64DbgNugetDepsPath => GetPluginPath();
public static void PrintFields(object obj)
{
diff --git a/src/Dotx64Managed/Resources/Dotx64DbgIcon.png b/src/Resources/Dotx64DbgIcon.png
similarity index 100%
rename from src/Dotx64Managed/Resources/Dotx64DbgIcon.png
rename to src/Resources/Dotx64DbgIcon.png
diff --git a/src/Dotx64Managed/Resources/NewScript.png b/src/Resources/NewScriptIcon.png
similarity index 100%
rename from src/Dotx64Managed/Resources/NewScript.png
rename to src/Resources/NewScriptIcon.png
diff --git a/src/Dotx64Managed/Resources/Run.png b/src/Resources/RunIcon.png
similarity index 100%
rename from src/Dotx64Managed/Resources/Run.png
rename to src/Resources/RunIcon.png
diff --git a/src/asmjit/asmjit.natvis b/src/asmjit/asmjit.natvis
deleted file mode 100644
index 68012e0..0000000
--- a/src/asmjit/asmjit.natvis
+++ /dev/null
@@ -1,245 +0,0 @@
-
-
-
-
-
-
-
- {_small.data, s8}
- {_large.data, s8}
-
-
- Small
- Large
- External
-
- - (int)_small.type, d
- - _large.size, d
- - asmjit::String::kSSOCapacity, d
- - _large.capacity, d
- - _small.data, s8
- - _large.data, s8
-
-
-
-
- {{ [size={_size, d} capacity={_capacity, d}] }}
-
- - _size, d
- - _capacity, d
-
- _size
- (($T1*)_data)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [None]
- [Reg] {{ type={regType()} group={regGroup()} size={opSize(), d} }}
- [Mem] {{ base={memBaseType()} index={memIndexType()} }}
- [Imm] {{ type={immType()} }}
- [Label]
- [Unknown]
-
-
- - _bits, X
- - opType()
- - regType()
- - regGroup()
- - opSize(), d
- - memBaseType()
- - memIndexType()
- - memRegHome()
- - opSize(), d
- - memX86Segment()
- - memX86AddrType()
- - memX86ShiftValue()
- - memX86Broadcast()
- - immType()
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [None]
- [Reg] {{ id={_baseId, d} group={regGroup(), d} type={regType(), d} size={opSize(), d} }}
- [Mem] {{ baseId={memBaseId(), d} indexId={memIndexId(), d} offset={(__int64)memOffset(), d} }}
- [Imm] {{ val={immValue(), d} hex={immValue(), X} }}
- [Label] {{ id={_baseId} }}
- [Unknown]
-
- - _signature._bits, X
- - opType()
- - opSize(), d
- - regType()
- - regGroup()
- - _baseId, d
- - memBaseType()
- - memBaseId()
- - memIndexType()
- - memIndexId()
- - memRegHome()
- - memOffset(), d
- - memX86Segment()
- - memX86AddrType()
- - memX86ShiftValue()
- - memX86Broadcast()
- - immType()
- - immValue(), X
- - _baseId, d
- - _baseId
- - _data[0]
- - _data[1]
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [RegValue {{ regType={regType()} indirect={isIndirect()} done={isDone()} }}]
- [StackValue {{ indirect={isIndirect()} done={isDone()} }}]
- [Unknown]
-
-
- - _data
- - (asmjit::TypeId)(typeId())
- - (asmjit::BaseReg::RegType)regType()
- - regId()
- - stackOffset()
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [InstNode]
- [SectionNode]
- [LabelNode]
- [AlignNode]
- [EmbedDataNode]
- [EmbedLabelNode]
- [EmbedLabelDeltaNode]
- [ConstPoolNode]
- [CommentNode]
- [SentinelNode]
- [JumpNode]
- [FuncNode]
- [FuncRetNode]
- [InvokeNode]
- [UnknownNode {nodeType(), d}]
-
-
- - _prev
- - _next
-
- - _any._nodeType
- - _any._nodeFlags
-
- - _position
- - _userDataU64
- - _userDataPtr
- - _passData
- - _inlineComment, s8
-
- - ((asmjit::InstNode*)this)->_baseInst
- - _inst._opCount
- - _inst._opCapacity
- - ((asmjit::InstNode*)this)->_opArray, [_inst._opCount]
-
- - ((asmjit::SectionNode*)this)->_id
- - ((asmjit::SectionNode*)this)->_nextSection
-
- - ((asmjit::LabelNode*)this)->_labelId
-
- - ((asmjit::AlignNode*)this)->_alignData._alignMode
- - ((asmjit::AlignNode*)this)->_alignment
-
- - _embed._typeId, d
- - _embed._typeSize, d
- - ((asmjit::EmbedDataNode*)this)->_itemCount
- - ((asmjit::EmbedDataNode*)this)->_repeatCount
- - ((asmjit::EmbedDataNode*)this)->_inlineData
- - ((asmjit::EmbedDataNode*)this)->_externalData
-
- - ((asmjit::EmbedLabelNode*)this)->_labelId
-
- - ((asmjit::EmbedLabelDeltaNode*)this)->_labelId
- - ((asmjit::EmbedLabelDeltaNode*)this)->_baseLabelId
- - ((asmjit::EmbedLabelDeltaNode*)this)->_dataSize
-
- - ((asmjit::ConstPoolNode*)this)->_constPool
-
- - _sentinel._sentinelType
-
- - ((asmjit::JumpNode*)this)->_annotation
-
- - ((asmjit::FuncNode*)this)->_funcDetail
- - ((asmjit::FuncNode*)this)->_frame
- - ((asmjit::FuncNode*)this)->_exitNode
- - ((asmjit::FuncNode*)this)->_end
- - ((asmjit::FuncNode*)this)->_args, [((asmjit::FuncNode*)this)->_funcDetail._argCount]
-
- - ((asmjit::InvokeNode*)this)->_funcDetail
- - ((asmjit::InvokeNode*)this)->_rets
- - ((asmjit::InvokeNode*)this)->_args, [((asmjit::InvokeNode*)this)->_funcDetail._argCount]
-
-
-
diff --git a/src/asmjit/asmjit.vcxproj b/src/asmjit/asmjit.vcxproj
deleted file mode 100644
index f4aea5f..0000000
--- a/src/asmjit/asmjit.vcxproj
+++ /dev/null
@@ -1,278 +0,0 @@
-
-
-
-
- Debug
- Win32
-
-
- Release
- Win32
-
-
- Debug
- x64
-
-
- Release
- x64
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 16.0
- Win32Proj
- {401e7506-9879-4c5c-8638-6664852fbfff}
- asmjit
- 10.0
-
-
-
- StaticLibrary
- true
- v142
- Unicode
-
-
- StaticLibrary
- false
- v142
- true
- Unicode
-
-
- StaticLibrary
- true
- v142
- Unicode
-
-
- StaticLibrary
- false
- v142
- true
- Unicode
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- true
- $(Platform)\$(Configuration)\
- $(SolutionDir)..\bin\x32\plugins\
-
-
- false
- $(SolutionDir)..\bin\x32\plugins\
- $(Platform)\$(Configuration)\
-
-
- true
- $(SolutionDir)..\bin\x64\plugins\
-
-
- false
- $(SolutionDir)..\bin\x64\plugins\
-
-
-
- Level3
- WIN32;_DEBUG;_CONSOLE;ASMJIT_STATIC;%(PreprocessorDefinitions)
- true
- stdcpplatest
- true
- false
- ProgramDatabase
-
-
- Console
- true
-
-
-
-
- Level3
- true
- WIN32;NDEBUG;_CONSOLE;ASMJIT_STATIC;%(PreprocessorDefinitions)
- true
- stdcpplatest
- true
- false
-
-
- Console
- true
- true
- true
-
-
-
-
- Level3
- _DEBUG;_CONSOLE;ASMJIT_STATIC;%(PreprocessorDefinitions)
- true
- true
- stdcpplatest
- false
- ProgramDatabase
-
-
- Console
- true
-
-
-
-
- Level3
- true
- NDEBUG;_CONSOLE;ASMJIT_STATIC;%(PreprocessorDefinitions)
- true
- true
- stdcpplatest
- false
- false
-
-
- Console
- true
- true
- true
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/asmjit/asmjit.vcxproj.filters b/src/asmjit/asmjit.vcxproj.filters
deleted file mode 100644
index afe7bba..0000000
--- a/src/asmjit/asmjit.vcxproj.filters
+++ /dev/null
@@ -1,350 +0,0 @@
-
-
-
-
- {9b7c64b5-e81a-47f1-a36a-8149c8960a4f}
-
-
- {d737f88b-1bbe-4954-bf5b-a4a066dfb0ee}
-
-
-
-
-
-
-
-
-
- x86
-
-
- x86
-
-
- x86
-
-
- x86
-
-
- x86
-
-
- x86
-
-
- x86
-
-
- x86
-
-
- x86
-
-
- x86
-
-
- x86
-
-
- x86
-
-
- x86
-
-
- x86
-
-
- x86
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
-
-
- x86
-
-
- x86
-
-
- x86
-
-
- x86
-
-
- x86
-
-
- x86
-
-
- x86
-
-
- x86
-
-
- x86
-
-
- x86
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
- core
-
-
-
\ No newline at end of file
diff --git a/src/asmjit/asmjit/asmjit-scope-begin.h b/src/asmjit/asmjit/asmjit-scope-begin.h
deleted file mode 100644
index 93397b5..0000000
--- a/src/asmjit/asmjit/asmjit-scope-begin.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// This file is part of AsmJit project
-//
-// See asmjit.h or LICENSE.md for license and copyright information
-// SPDX-License-Identifier: Zlib
-
-#ifdef _WIN32
- #pragma push_macro("min")
- #pragma push_macro("max")
-
- #ifdef min
- #undef min
- #endif
-
- #ifdef max
- #undef max
- #endif
-#endif
diff --git a/src/asmjit/asmjit/asmjit-scope-end.h b/src/asmjit/asmjit/asmjit-scope-end.h
deleted file mode 100644
index 702cef4..0000000
--- a/src/asmjit/asmjit/asmjit-scope-end.h
+++ /dev/null
@@ -1,9 +0,0 @@
-// This file is part of AsmJit project
-//
-// See asmjit.h or LICENSE.md for license and copyright information
-// SPDX-License-Identifier: Zlib
-
-#ifdef _WIN32
- #pragma pop_macro("min")
- #pragma pop_macro("max")
-#endif
diff --git a/src/asmjit/asmjit/asmjit.h b/src/asmjit/asmjit/asmjit.h
deleted file mode 100644
index 1cd0651..0000000
--- a/src/asmjit/asmjit/asmjit.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is part of AsmJit project
-//
-// SPDX-License-Identifier: Zlib
-// Official GitHub Repository: https://github.com/asmjit/asmjit
-//
-// Copyright (c) 2008-2021 The AsmJit Authors
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-// claim that you wrote the original software. If you use this software
-// in a product, an acknowledgment in the product documentation would be
-// appreciated but is not required.
-// 2. Altered source versions must be plainly marked as such, and must not be
-// misrepresented as being the original software.
-// 3. This notice may not be removed or altered from any source distribution.
-
-#ifndef ASMJIT_ASMJIT_H_INCLUDED
-#define ASMJIT_ASMJIT_H_INCLUDED
-
-#include "./core.h"
-
-#ifndef ASMJIT_NO_X86
- #include "./x86.h"
-#endif
-
-#endif // ASMJIT_ASMJIT_H_INCLUDED
diff --git a/src/asmjit/asmjit/core.h b/src/asmjit/asmjit/core.h
deleted file mode 100644
index 4f06a6f..0000000
--- a/src/asmjit/asmjit/core.h
+++ /dev/null
@@ -1,1843 +0,0 @@
-// This file is part of AsmJit project
-//
-// See asmjit.h or LICENSE.md for license and copyright information
-// SPDX-License-Identifier: Zlib
-
-#ifndef ASMJIT_CORE_H_INCLUDED
-#define ASMJIT_CORE_H_INCLUDED
-
-//! Root namespace used by AsmJit.
-namespace asmjit {
-
-//! \mainpage API Reference
-//!
-//! AsmJit C++ API reference documentation generated by Doxygen.
-//!
-//! AsmJit library uses one global namespace called \ref asmjit, which provides the whole functionality. Core
-//! functionality is within \ref asmjit namespace and architecture specific functionality is always in its own
-//! namespace. For example \ref asmjit::x86 provides both 32-bit and 64-bit X86 code generation.
-//!
-//! \section main_groups Documentation Groups
-//!
-//! AsmJit documentation is structured into groups. Groups can be followed in order to learn AsmJit, but knowledge
-//! from multiple groups is required to use AsmJit properly:
-//!
-//! $$DOCS_GROUP_OVERVIEW$$
-//!
-//! \note It's important to understand that in order to learn AsmJit all groups are important. Some groups can be
-//! omitted if a particular tool is out of interest - for example \ref asmjit_assembler users don't need to know
-//! about \ref asmjit_builder, but it's not the opposite. \ref asmjit_builder users must know about \ref
-//! asmjit_assembler as it also uses operands, labels, and other concepts. Similarly \ref asmjit_compiler users
-//! must know how both \ref asmjit_assembler and \ref asmjit_builder tools work.
-//!
-//! \section where_to_start Where To Start
-//!
-//! AsmJit \ref asmjit_core provides the following two classes that are essential from the code generation perspective:
-//!
-//! - \ref CodeHolder provides functionality to temporarily hold the generated code. It stores all the necessary
-//! information about the code - code buffers, sections, labels, symbols, and information about relocations.
-//!
-//! - \ref BaseEmitter provides interface used by emitter implementations. The interface provides basic building
-//! blocks that are then implemented by \ref BaseAssembler, \ref BaseBuilder, and \ref BaseCompiler.
-//!
-//! Code emitters:
-//!
-//! - \ref asmjit_assembler - provides direct machine code generation.
-//!
-//! - \ref asmjit_builder - provides intermediate code generation that can be processed before it's serialized to
-//! \ref BaseAssembler.
-//!
-//! - \ref asmjit_compiler - provides high-level code generation with built-in register allocation.
-//!
-//! - \ref FuncNode - provides insight into how function looks from the Compiler perspective and how it's stored in
-//! a node-list.
-//!
-//! \section main_recommendations Recommendations
-//!
-//! The following steps are recommended for all AsmJit users:
-//!
-//! - Make sure that you use \ref Logger, see \ref asmjit_logging.
-//!
-//! - Make sure that you use \ref ErrorHandler, see \ref asmjit_error_handling.
-//!
-//! - Instruction validation in your debug builds can reveal problems too. AsmJit provides validation at instruction
-//! level, that can be enabled by \ref BaseEmitter::addValidationOptions().
-//!
-//! See \ref ValidationOptions for more details.
-//!
-//! - Make sure you put a breakpoint into \ref DebugUtils::errored() function if you have a problem with AsmJit
-//! returning errors during instruction encoding or register allocation. Having an active breakpoint there can
-//! help to reveal the origin of the error, to inspect variables and other conditions that caused to it.
-//!
-//! The reason for using \ref Logger and \ref ErrorHandler is that they provide a very useful information about what's
-//! happening inside emitters. In many cases the information provided by these two is crucial to quickly fix issues
-//! that happen during development (for example wrong instruction, address, or register used). In addition, output from
-//! \ref Logger is always necessary when filling bug reports. In other words, using logging and proper error handling
-//! can save a lot of time during the development.
-//!
-//! \section main_other Other Pages
-//!
-//! - Class List - List of classes sorted alphabetically
-//! - AsmJit Namespace - List of symbols provided by `asmjit` namespace
-
-
-//! \defgroup asmjit_build Build Instructions
-//! \brief Build instructions, supported environments, and feature selection.
-//!
-//! ### Overview
-//!
-//! AsmJit is designed to be easy embeddable in any project. However, it depends on some compile-time definitions that
-//! can be used to enable or disable features to decrease the resulting binary size. A typical way of building AsmJit
-//! is to use [cmake](https://www.cmake.org), but it's also possible to just include AsmJit source code in your project
-//! and to just build it. The easiest way to include AsmJit in your project is to just include **src** directory in
-//! your project and to define \ref ASMJIT_STATIC. AsmJit can be just updated from time to time without any changes to
-//! this integration process. Do not embed AsmJit's `test` files in such case as these are used exclusively for testing.
-//!
-//! ### Supported C++ Compilers
-//!
-//! - Requirements:
-//!
-//! - AsmJit won't build without C++11 enabled. If you use older GCC or Clang you would have to enable at least
-//! C++11 standard through compiler flags.
-//!
-//! - Tested:
-//!
-//! - **Clang** - Tested by Travis-CI - Clang 3.9+ (with C++11 enabled) is officially supported (older Clang
-//! versions having C++11 support are probably fine, but are not regularly tested).
-//!
-//! - **GNU** - Tested by Travis-CI - GCC 4.8+ (with C++11 enabled) is officially supported.
-//!
-//! - **MINGW** - Tested by Travis-CI - Use the latest version, if possible.
-//!
-//! - **MSVC** - Tested by Travis-CI - VS2017+ is officially supported, VS2015 is reported to work.
-//!
-//! - Untested:
-//!
-//! - **Intel** - No maintainers and no CI environment to regularly test this compiler.
-//!
-//! - **Other** C++ compilers would require basic support in
-//! [core/api-config.h](https://github.com/asmjit/asmjit/tree/master/src/asmjit/core/api-config.h).
-//!
-//! ### Supported Operating Systems and Platforms
-//!
-//! - Tested:
-//!
-//! - **Linux** - Tested by Travis-CI (any distribution is generally supported).
-//!
-//! - **OSX** - Tested by Travis-CI (any version is supported).
-//!
-//! - **Windows** - Tested by Travis-CI - (Windows 7+ is officially supported).
-//!
-//! - **Emscripten** - Works if compiled with \ref ASMJIT_NO_JIT. AsmJit cannot generate WASM code, but can be
-//! used to generate X86/X64 code within a browser, for example.
-//!
-//! - Untested:
-//!
-//! - **BSDs** - No maintainers, no CI environment to regularly test BSDs, but they should work out of box.
-//!
-//! - **Haiku** - Not regularly tested, but reported to work.
-//!
-//! - **Other** operating systems would require some testing and support in the following files:
-//! - [core/api-config.h](https://github.com/asmjit/asmjit/tree/master/src/asmjit/core/api-config.h)
-//! - [core/osutils.cpp](https://github.com/asmjit/asmjit/tree/master/src/asmjit/core/osutils.cpp)
-//! - [core/virtmem.cpp](https://github.com/asmjit/asmjit/tree/master/src/asmjit/core/virtmem.cpp)
-//!
-//! ### Supported Backends / Architectures
-//!
-//! - **X86** - Both 32-bit and 64-bit backends tested by Travis-CI.
-//! - **ARM** - Work-in-progress (not public at the moment).
-//!
-//! ### Static Builds and Embedding
-//!
-//! These definitions can be used to enable static library build. Embed is used when AsmJit's source code is embedded
-//! directly in another project, implies static build as well.
-//!
-//! - \ref ASMJIT_EMBED - Asmjit is embedded, implies \ref ASMJIT_STATIC.
-//! - \ref ASMJIT_STATIC - Enable static-library build.
-//!
-//! \note Projects that use AsmJit statically must define \ref ASMJIT_STATIC in all compilation units that use AsmJit,
-//! otherwise AsmJit would use dynamic library imports in \ref ASMJIT_API decorator. The recommendation is to define
-//! this macro across the whole project that uses AsmJit this way.
-//!
-//! ### Build Configuration
-//!
-//! These definitions control whether asserts are active or not. By default AsmJit would autodetect build configuration
-//! from existing pre-processor definitions, but this behavior can be overridden, for example to enable debug asserts
-//! in release configuration.
-//!
-//! - \ref ASMJIT_BUILD_DEBUG - Overrides build configuration to debug, asserts will be enabled in this case.
-//! - \ref ASMJIT_BUILD_RELEASE - Overrides build configuration to release, asserts will be disabled in this case.
-//!
-//! \note There is usually no need to override the build configuration. AsmJit detects the build configuration by
-//! checking whether `NDEBUG` is defined and automatically defines \ref ASMJIT_BUILD_RELEASE if configuration overrides
-//! were not used. We only recommend using build configuration overrides in special situations, like using AsmJit in
-//! release configuration with asserts enabled for whatever reason.
-//!
-//! ### AsmJit Backends
-//!
-//! AsmJit currently supports only X86/X64 backend, but the plan is to add more backends in the future. By default
-//! AsmJit builds only the host backend, which is autodetected at compile-time, but this can be overridden.
-//!
-//! - \ref ASMJIT_NO_X86 - Disable X86/X64 backends.
-//! - \ref ASMJIT_NO_FOREIGN - Disables the support for foreign architectures.
-//!
-//! ### Features Selection
-//!
-//! AsmJit builds by defaults all supported features, which includes all emitters, logging, instruction validation and
-//! introspection, and JIT memory allocation. Features can be disabled at compile time by using `ASMJIT_NO_...`
-//! definitions.
-//!
-//! - \ref ASMJIT_NO_DEPRECATED - Disables deprecated API at compile time so it won't be available and the
-//! compilation will fail if there is attempt to use such API. This includes deprecated classes, namespaces,
-//! enumerations, and functions.
-//!
-//! - \ref ASMJIT_NO_BUILDER - Disables \ref asmjit_builder functionality completely. This implies \ref
-//! ASMJIT_NO_COMPILER as \ref asmjit_compiler cannot be used without \ref asmjit_builder.
-//!
-//! - \ref ASMJIT_NO_COMPILER - Disables \ref asmjit_compiler functionality completely.
-//!
-//! - \ref ASMJIT_NO_JIT - Disables JIT memory management and \ref JitRuntime.
-//!
-//! - \ref ASMJIT_NO_LOGGING - Disables \ref Logger and \ref Formatter.
-//!
-//! - \ref ASMJIT_NO_TEXT - Disables everything that contains string representation of AsmJit constants, should
-//! be used together with \ref ASMJIT_NO_LOGGING as logging doesn't make sense without the ability to query
-//! instruction names, register names, etc...
-//!
-//! - \ref ASMJIT_NO_VALIDATION - Disables validation API.
-//!
-//! - \ref ASMJIT_NO_INTROSPECTION - Disables instruction introspection API, must be used together with \ref
-//! ASMJIT_NO_COMPILER as \ref asmjit_compiler requires introspection for its liveness analysis and register
-//! allocation.
-//!
-//! \note It's not recommended to disable features if you plan to build AsmJit as a shared library that will be
-//! used by multiple projects that you don't control how AsmJit was built (for example AsmJit in a Linux distribution).
-//! The possibility to disable certain features exists mainly for customized AsmJit builds.
-
-
-//! \defgroup asmjit_breaking_changes Breaking Changes
-//! \brief Documentation of breaking changes
-//!
-//! ### Overview
-//!
-//! AsmJit is a live project that is being actively developed. Deprecating the existing API in favor of a new
-//! one is preferred, but it's not always possible if the changes are significant. AsmJit authors prefer to do
-//! accumulated breaking changes at once instead of breaking the API often. This page documents deprecated and
-//! removed APIs and should serve as a how-to guide for people that want to port existing code to work with the
-//! newest AsmJit.
-//!
-//! ### Tips
-//!
-//! Useful tips before you start:
-//!
-//! - Visit our [Public Gitter Channel](https://gitter.im/asmjit/asmjit) if you need a quick help.
-//!
-//! - Build AsmJit with `ASMJIT_NO_DEPRECATED` macro defined to make sure that you are not using deprecated
-//! functionality at all. Deprecated functions are decorated with `ASMJIT_DEPRECATED()` macro, but sometimes
-//! it's not possible to decorate everything like classes, which are used by deprecated functions as well,
-//! because some compilers would warn about that. If your project compiles fine with `ASMJIT_NO_DEPRECATED`
-//! it's not using anything, which was deprecated.
-//!
-//! ### Changes committed at XXXX-XX-XX
-//!
-//! Core changes:
-//!
-//! - Removed deprecated API.
-//!
-//! - Many enumerations were changed to enum class, and many public APIs were changed to use such enums instead
-//! of uint32_t. This change makes some APIs backward incompatible - there are no deprecations this time.
-//!
-//! - Extracted operand signature manipulation to `OperandSignature`.
-//! - Moved `{arch}::Features::k` to `CpuFeatures::{arch}::k`.
-//! - Moved `BaseEmitter::kEncodingOption` to `EncodingOptions::k`.
-//! - Moved `BaseEmitter::kFlag` to `EmitterFlags::k`.
-//! - Moved `BaseEmitter::kType` to `EmitterType::k`.
-//! - Moved `BaseEmitter::kValidationOption` to `ValidationOptions::kValidate`.
-//! - Moved `BaseFeatures` to `CpuFeatures`.
-//! - Moved `BaseInst::kControl` to `InstControlFlow::k`.
-//! - Moved `BaseInst::kOption` and `x86::Inst::kOption` to `InstOptions::k`.
-//! - Moved `BaseNode::kNode` to `NodeType::k`.
-//! - Moved `BaseReg::kGroup` and `x86::Reg::kGroup` to `RegGroup::k`.
-//! - Moved `BaseReg::kType` and `x86::Reg::kType` to `RegType::k`.
-//! - Moved `CallConv::kFlag` to `CallConvFlags::k`.
-//! - Moved `CallConv::kId` to `CallConvId::k`.
-//! - Moved `CallConv::kStrategy` to `CallConvStrategy::k`.
-//! - Moved `CodeBuffer::kFlag` to `CodeBufferFlags`.
-//! - Moved `ConstPool::kScope` to `ConstPoolScope::k`.
-//! - Moved `Environment::kArch` to `Arch::k`.
-//! - Moved `Environment::kSubArch` to `SubArch::k`.
-//! - Moved `Environment::kFormat` to `OjectFormat::k`.
-//! - Moved `Environment::kPlatform` to `Platform::k`.
-//! - Moved `Environment::kAbi` to `PlatformABI::k`.
-//! - Moved `Environment::kVendor` to `Vendor::k`.
-//! - Moved `FormatOptions::kFlag` to `FormatFlags::k`.
-//! - Moved `FormatOptions::kIndentation` to `FormatIndentationGroup::k`.
-//! - Moved `FuncFrame::kAttr` to `FuncAttributes::k`.
-//! - Moved `Globals::kReset` to `ResetPolicy::k`.
-//! - Moved `JitAllocator::kOption` to `JitAllocatorOptions::k`.
-//! - Moved `Label::kType` to `LabelType::k`.
-//! - Moved `Operand::kOpType` to `OperandType::k`.
-//! - Moved `OpRWInfo::kFlag` to `OpRWFlags::k`.
-//! - Moved `Type::kId` to `TypeId::k`.
-//! - Moved `VirtMem::k` to `VirtMem::MemoryFlags::k`.
-//!
-//! ### Changes committed at 2020-05-30
-//!
-//! AsmJit has been cleaned up significantly, many todo items have been fixed and many functions and classes have
-//! been redesigned, some in an incompatible way.
-//!
-//! Core changes:
-//!
-//! - `Imm` operand has now only `Imm::value()` and `Imm::valueAs()` functions that return its value content,
-//! and `Imm::setValue()` function that sets the content. Functions like `setI8()`, `setU8()` were deprecated.
-//!
-//! Old functions were deprecated, but code using them should still compile.
-//!
-//! - `ArchInfo` has been replaced with `Environment`. Environment provides more details about the architecture,
-//! but drops some properties that were used by arch info - `gpSize(`) and `gpCount()`. `gpSize()` can be replaced
-//! with `registerSize()` getter, which returns a native register size of the architecture the environment uses.
-//! However, `gpCount()` was removed - at the moment `ArchTraits` can be used to access such properties.
-//!
-//! Some other functions were renamed, like `ArchInfo::isX86Family()` is now `Environment::isFamilyX86()`, etc.
-//! The reason for changing the order was support for more propertries and all the accessors now start with the
-//! type of the property, like `Environment::isPlatformWindows()`.
-//!
-//! This function causes many other classes to provide `environment()` getter instead of `archInfo()` getter.
-//! In addition, AsmJit now uses `arch()` to get an architecture instead of `archId()`. `ArchInfo::kIdXXX` was
-//! renamed to `Environment::kArchXXX`.
-//!
-//! Some functions were deprecated, some removed...
-//!
-//! - `CodeInfo` has been removed in favor of `Environment`. If you used `CodeInfo` to set architecture and base
-//! address, this is now possible with `Environment` and setting base address explicitly by `CodeHolder::init()`
-//! - the first argument is `Environment`, and the second argument is base address, which defaults to
-//! `Globals::kNoBaseAddress`.
-//!
-//! CodeInfo class was deprecated, but the code using it should still compile with warnings.
-//!
-//! - `CallConv` has been updated to offer a more unified way of representing calling conventions - many calling
-//! conventions were abstracted to follow standard naming like `CallConvId::kCDecl` or `CallConvId::kStdCall`.
-//!
-//! This change means that other APIs like `FuncDetail::init()` now require both, calling convention and target
-//! `Environment`.
-//!
-//! - `Logging` namespace has been renamed to `Formatter`, which now provides general functionality for formatting
-//! in AsmJit.
-//!
-//! Logging namespace should still work, but its use is deprecated. Unfortunately this will be without deprecation
-//! warnings, so make sure you don't use it.
-//!
-//! - `Data64`, `Data128`, and `Data256` structs were deprecated and should no longer be used. There is no replacement,
-//! AsmJit users should simply create their own structures if they need them or use the new repeated embed API in
-//! emitters, see `BaseEmitter::embedDataArray()`.
-//!
-//! Emitter changes:
-//!
-//! - `BaseEmitter::emit()` function signature has been changed to accept 3 operands by reference and the rest 3
-//! operands as a continuous array. This change is purely cosmetic and shouldn't affect users as emit() has many
-//! overloads that dispatch to the right function.
-//!
-//! - `x86::Emitter` (Assembler, Builder, Compiler) deprecates embed utilities like `dint8()`, `duint8()`, `duint16()`,
-//! `dxmm()`, etc... in favor of a new and more powerful `BaseEmitter::embedDataArray()`. This function also allows
-//! emitting repeated values and/or patterns, which is used by helpers `BaseEmitter::embedUInt8()`, and others...
-//!
-//! - Validation is now available through `BaseEmitter::ValidationOptions`, which can be enabled/disabled through
-//! `BaseEmitter::addValidationOptions()` and `BaseEmitter::clearValidationOptions()`, respectively. Validation
-//! options now separate between encoding and Builder/Compiler so it's possible to choose the granularity required.
-//!
-//! Builder changes:
-//!
-//! - Internal functions for creating nodes were redesigned. They now accept a pointer to the node created as
-//! a first parameter. These changes should not affect AsmJit users as these functions were used internally.
-//!
-//! Compiler changes:
-//!
-//! - `FuncCallNode` has been renamed to `InvokeNode`. Additionally, function calls should now use
-//! `x86::Compiler::invoke()` instead of `call()`. The reason behind this is to remove the confusion between a
-//! `call` instruction and AsmJit's `call()` intrinsic, which is now `invoke()`.
-//!
-//! - Creating new nodes also changed. Now the preferred way of invoking a function is to call
-//! `x86::Compiler::invoke()` where the first argument is `InvokeNode**`. The function now returns an error and
-//! would call `ErrorHandler` in case of a failure. Error handling was unspecified in the past - the function was
-//! marked noexcept, but called error handler, which could throw.
-//!
-//! The reason behind this change is to make the API consistent with other changes and to also make it possible
-//! to inspect the possible error. In the previous API it returned a new node or `nullptr` in case of error,
-//! which the user couldn't inspect unless there was an attached `ErrorHandler`.
-//!
-//! Samples:
-//!
-//! ```
-//! #include
-//!
-//! using namespace asmjit;
-//!
-//! // The basic setup of JitRuntime and CodeHolder changed, use environment()
-//! // instead of codeInfo().
-//! void basicSetup() {
-//! JitRuntime rt;
-//! CodeHolder code(rt.environment());
-//! }
-//!
-//! // Calling a function (Compiler) changed - use invoke() instead of call().
-//! void functionInvocation(x86::Compiler& cc) {
-//! InvokeNode* invokeNode;
-//! cc.invoke(&invokeNode, targetOperand, FuncSignatureT<...>(...));
-//! }
-//! ```
-
-
-//! \defgroup asmjit_core Core
-//! \brief Globals, code storage, and emitter interface.
-//!
-//! ### Overview
-//!
-//! AsmJit library uses \ref CodeHolder to hold code during code generation and emitters inheriting from \ref
-//! BaseEmitter to emit code. CodeHolder uses containers to manage its data:
-//!
-//! - \ref Section - stores information about a code or data section.
-//! - \ref CodeBuffer - stores actual code or data, part of \ref Section.
-//! - \ref LabelEntry - stores information about a label - its name, offset, section where it belongs to, and
-//! other bits.
-//! - \ref LabelLink - stores information about yet unbound label, which was already used by the assembler.
-//! - \ref RelocEntry - stores information about a relocation.
-//! - \ref AddressTableEntry - stores information about an address, which was used in a jump or call. Such
-//! address may need relocation.
-//!
-//! To generate code you would need to instantiate at least the following classes:
-//!
-//! - \ref CodeHolder - to hold code during code generation.
-//! - \ref BaseEmitter - to emit code into \ref CodeHolder.
-//! - \ref Target (optional) - most likely \ref JitRuntime to keep the generated code in executable memory. \ref
-//! Target can be customized by inheriting from it.
-//!
-//! There are also other core classes that are important:
-//!
-//! - \ref Environment - describes where the code will run. Environment brings the concept of target triples or
-//! tuples into AsmJit, which means that users can specify target architecture, platform, and ABI.
-//! - \ref TypeId - encapsulates lightweight type functionality that can be used to describe primitive and vector
-//! types. Types are used by higher level utilities, for example by \ref asmjit_function and \ref asmjit_compiler.
-//! - \ref CpuInfo - encapsulates CPU information - stores both CPU information and CPU features described by \ref
-//! CpuFeatures.
-//!
-//! AsmJit also provides global constants:
-//!
-//! - \ref Globals - namespace that provides global constants.
-//! - \ref ByteOrder - byte-order constants and functionality.
-//!
-//! \note CodeHolder examples use \ref x86::Assembler as abstract interfaces cannot be used to generate code.
-//!
-//! ### CodeHolder & Emitters
-//!
-//! The example below shows how the mentioned classes interact to generate X86 code:
-//!
-//! ```
-//! #include
-//! #include
-//!
-//! using namespace asmjit;
-//!
-//! // Signature of the generated function.
-//! typedef int (*Func)(void);
-//!
-//! int main() {
-//! JitRuntime rt; // Runtime specialized for JIT code execution.
-//!
-//! CodeHolder code; // Holds code and relocation information.
-//! code.init(rt.environment()); // Initialize code to match the JIT environment.
-//!
-//! x86::Assembler a(&code); // Create and attach x86::Assembler to code.
-//! a.mov(x86::eax, 1); // Move one to eax register.
-//! a.ret(); // Return from function.
-//! // ===== x86::Assembler is no longer needed from here and can be destroyed =====
-//!
-//! Func fn; // Holds address to the generated function.
-//! Error err = rt.add(&fn, &code); // Add the generated code to the runtime.
-//! if (err) return 1; // Handle a possible error returned by AsmJit.
-//! // ===== CodeHolder is no longer needed from here and can be destroyed =====
-//!
-//! int result = fn(); // Execute the generated code.
-//! printf("%d\n", result); // Print the resulting "1".
-//!
-//! // All classes use RAII, all resources will be released before `main()` returns,
-//! // the generated function can be, however, released explicitly if you intend to
-//! // reuse or keep the runtime alive, which you should in a production-ready code.
-//! rt.release(fn);
-//!
-//! return 0;
-//! }
-//! ```
-//!
-//! The example above used \ref x86::Assembler as an emitter. AsmJit provides the following emitters that offer various
-//! levels of abstraction:
-//!
-//! - \ref asmjit_assembler - Low-level emitter that emits directly to \ref CodeBuffer.
-//! - \ref asmjit_builder - Low-level emitter that emits to a \ref BaseNode list.
-//! - \ref asmjit_compiler - High-level emitter that provides register allocation.
-//!
-//! ### Targets and JitRuntime
-//!
-//! AsmJit's \ref Target is an interface that provides basic target abstraction. At the moment AsmJit provides only
-//! one implementation called \ref JitRuntime, which as the name suggests provides JIT code target and execution
-//! runtime. \ref JitRuntime provides all the necessary stuff to implement a simple JIT compiler with basic memory
-//! management. It only provides \ref JitRuntime::add() and \ref JitRuntime::release() functions that are used to
-//! either add code to the runtime or release it. \ref JitRuntime doesn't do any decisions on when the code should be
-//! released, the decision is up to the developer.
-//!
-//! See more at \ref asmjit_virtual_memory group.
-//!
-//! ### More About Environment
-//!
-//! In the previous example the \ref Environment is retrieved from \ref JitRuntime. It's logical as \ref JitRuntime
-//! always returns an \ref Environment that is compatible with the host. For example if your application runs on X86_64
-//! CPU the \ref Environment returned will use \ref Arch::kX64 architecture in contrast to \ref Arch::kX86, which will
-//! be used in 32-bit mode on an X86 target.
-//!
-//! AsmJit allows to setup the \ref Environment manually and to select a different architecture and ABI when necessary.
-//! So let's do something else this time, let's always generate a 32-bit code and print its binary representation. To
-//! do that, we can create our own \ref Environment and initialize it to \ref Arch::kX86.
-//!
-//! ```
-//! #include
-//! #include
-//!
-//! using namespace asmjit;
-//!
-//! int main(int argc, char* argv[]) {
-//! using namespace asmjit::x86;
-//!
-//! // Create a custom environment initialized to 32-bit X86 architecture.
-//! Environment env;
-//! env.setArch(Arch::kX86);
-//!
-//! CodeHolder code; // Create a CodeHolder.
-//! code.init(env); // Initialize CodeHolder with custom environment.
-//!
-//! // Generate a 32-bit function that sums 4 floats and looks like:
-//! // void func(float* dst, const float* a, const float* b)
-//! x86::Assembler a(&code); // Create and attach x86::Assembler to `code`.
-//!
-//! a.mov(eax, dword_ptr(esp, 4)); // Load the destination pointer.
-//! a.mov(ecx, dword_ptr(esp, 8)); // Load the first source pointer.
-//! a.mov(edx, dword_ptr(esp, 12)); // Load the second source pointer.
-//!
-//! a.movups(xmm0, ptr(ecx)); // Load 4 floats from [ecx] to XMM0.
-//! a.movups(xmm1, ptr(edx)); // Load 4 floats from [edx] to XMM1.
-//! a.addps(xmm0, xmm1); // Add 4 floats in XMM1 to XMM0.
-//! a.movups(ptr(eax), xmm0); // Store the result to [eax].
-//! a.ret(); // Return from function.
-//!
-//! // We have no Runtime this time, it's on us what we do with the code.
-//! // CodeHolder stores code in Section, which provides some basic properties
-//! // and CodeBuffer structure. We are interested in section's CodeBuffer.
-//! //
-//! // NOTE: The first section is always '.text', it can be retrieved by
-//! // code.sectionById(0) or simply by code.textSection().
-//! CodeBuffer& buffer = code.textSection()->buffer();
-//!
-//! // Print the machine-code generated or do something else with it...
-//! // 8B4424048B4C24048B5424040F28010F58010F2900C3
-//! for (size_t i = 0; i < buffer.length; i++)
-//! printf("%02X", buffer.data[i]);
-//!
-//! return 0;
-//! }
-//! ```
-//!
-//! ### Explicit Code Relocation
-//!
-//! In addition to \ref Environment, \ref CodeHolder can be configured to specify a base-address (or a virtual base
-//! address in a linker terminology), which could be static (useful when you know the location where the target's
-//! machine code will be) or dynamic. AsmJit assumes dynamic base-address by default and relocates the code held by
-//! \ref CodeHolder to a user provided address on-demand. To be able to relocate to a user provided address it needs
-//! to store some information about relocations, which is represented by \ref RelocEntry. Relocation entries are only
-//! required if you call external functions from the generated code that cannot be encoded by using a 32-bit
-//! displacement (64-bit displacements are not provided by aby supported architecture).
-//!
-//! There is also a concept called \ref LabelLink - label link is a lightweight data structure that doesn't have any
-//! identifier and is stored in \ref LabelEntry as a single-linked list. Label link represents either unbound yet used
-//! label and cross-sections links (only relevant to code that uses multiple sections). Since crossing sections is
-//! something that cannot be resolved immediately these links persist until offsets of these sections are assigned and
-//! until \ref CodeHolder::resolveUnresolvedLinks() is called. It's an error if you end up with code that has
-//! unresolved label links after flattening. You can verify it by calling \ref CodeHolder::hasUnresolvedLinks(), which
-//! inspects the value returned by \ref CodeHolder::unresolvedLinkCount().
-//!
-//! AsmJit can flatten code that uses multiple sections by assigning each section an incrementing offset that respects
-//! its alignment. Use \ref CodeHolder::flatten() to do that. After the sections are flattened their offsets and
-//! virtual sizes are adjusted to respect each section's buffer size and alignment. The \ref
-//! CodeHolder::resolveUnresolvedLinks() function must be called before relocating the code held by \ref CodeHolder.
-//! You can also flatten your code manually by iterating over all sections and calculating their offsets (relative to
-//! base) by your own algorithm. In that case \ref CodeHolder::flatten() should not be called, however,
-//! \ref CodeHolder::resolveUnresolvedLinks() should be.
-//!
-//! The example below shows how to use a built-in virtual memory allocator \ref JitAllocator instead of using \ref
-//! JitRuntime (just in case you want to use your own memory management) and how to relocate the generated code
-//! into your own memory block - you can use your own virtual memory allocator if you prefer that, but that's OS
-//! specific and not covered by the documentation.
-//!
-//! The following code is similar to the previous one, but implements a function working in both 32-bit and 64-bit
-//! environments:
-//!
-//! ```
-//! #include
-//! #include
-//!
-//! using namespace asmjit;
-//!
-//! typedef void (*SumIntsFunc)(int* dst, const int* a, const int* b);
-//!
-//! int main() {
-//! // Create a custom environment that matches the current host environment.
-//! Environment env = Environment::host();
-//!
-//! CodeHolder code; // Create a CodeHolder.
-//! code.init(env); // Initialize CodeHolder with environment.
-//!
-//! x86::Assembler a(&code); // Create and attach x86::Assembler to `code`.
-//!
-//! // Signature: 'void func(int* dst, const int* a, const int* b)'.
-//! x86::Gp dst;
-//! x86::Gp src_a;
-//! x86::Gp src_b;
-//!
-//! // Handle the difference between 32-bit and 64-bit calling conventions
-//! // (arguments passed through stack vs. arguments passed by registers).
-//! if (env.is32Bit()) {
-//! dst = x86::eax;
-//! src_a = x86::ecx;
-//! src_b = x86::edx;
-//! a.mov(dst , x86::dword_ptr(x86::esp, 4));
-//! a.mov(src_a, x86::dword_ptr(x86::esp, 8));
-//! a.mov(src_b, x86::dword_ptr(x86::esp, 12));
-//! }
-//! else {
-//! if (env.isPlatformWindows()) {
-//! dst = x86::rcx; // First argument (destination pointer).
-//! src_a = x86::rdx; // Second argument (source 'a' pointer).
-//! src_b = x86::r8; // Third argument (source 'b' pointer).
-//! }
-//! else {
-//! dst = x86::rdi; // First argument (destination pointer).
-//! src_a = x86::rsi; // Second argument (source 'a' pointer).
-//! src_b = x86::rdx; // Third argument (source 'b' pointer).
-//! }
-//! }
-//!
-//! a.movdqu(x86::xmm0, x86::ptr(src_a)); // Load 4 ints from [src_a] to XMM0.
-//! a.movdqu(x86::xmm1, x86::ptr(src_b)); // Load 4 ints from [src_b] to XMM1.
-//! a.paddd(x86::xmm0, x86::xmm1); // Add 4 ints in XMM1 to XMM0.
-//! a.movdqu(x86::ptr(dst), x86::xmm0); // Store the result to [dst].
-//! a.ret(); // Return from function.
-//!
-//! // Even when we didn't use multiple sections AsmJit could insert one section
-//! // called '.addrtab' (address table section), which would be filled by data
-//! // required by relocations (absolute jumps and calls). You can omit this code
-//! // if you are 100% sure your code doesn't contain multiple sections and
-//! // such relocations. You can use `CodeHolder::hasAddressTable()` to verify
-//! // whether the address table section does exist.
-//! code.flatten();
-//! code.resolveUnresolvedLinks();
-//!
-//! // After the code was generated it can be relocated manually to any memory
-//! // location, however, we need to know it's size before we perform memory
-//! // allocation. `CodeHolder::codeSize()` returns the worst estimated code
-//! // size in case that relocations are not possible without trampolines (in
-//! // that case some extra code at the end of the current code buffer is
-//! // generated during relocation).
-//! size_t estimatedSize = code.codeSize();
-//!
-//! // Instead of rolling up our own memory allocator we can use the one AsmJit
-//! // provides. It's decoupled so you don't need to use `JitRuntime` for that.
-//! JitAllocator allocator;
-//!
-//! // Allocate an executable virtual memory and handle a possible failure.
-//! void* p = allocator.alloc(estimatedSize);
-//! if (!p)
-//! return 0;
-//!
-//! // Now relocate the code to the address provided by the memory allocator.
-//! // Please note that this DOESN'T COPY anything to `p`. This function will
-//! // store the address in CodeHolder and use relocation entries to patch the
-//! // existing code in all sections to respect the base address provided.
-//! code.relocateToBase((uint64_t)p);
-//!
-//! // This is purely optional. There are cases in which the relocation can omit
-//! // unneeded data, which would shrink the size of address table. If that
-//! // happened the codeSize returned after relocateToBase() would be smaller
-//! // than the originally `estimatedSize`.
-//! size_t codeSize = code.codeSize();
-//!
-//! // This will copy code from all sections to `p`. Iterating over all sections
-//! // and calling `memcpy()` would work as well, however, this function supports
-//! // additional options that can be used to also zero pad sections' virtual
-//! // size, etc.
-//! //
-//! // With some additional features, copyFlattenData() does roughly this:
-//! // for (Section* section : code.sections())
-//! // memcpy((uint8_t*)p + section->offset(),
-//! // section->data(),
-//! // section->bufferSize());
-//! code.copyFlattenedData(p, codeSize, CopySectionFlags::kPadSectionBuffer);
-//!
-//! // Execute the generated function.
-//! int inA[4] = { 4, 3, 2, 1 };
-//! int inB[4] = { 1, 5, 2, 8 };
-//! int out[4];
-//!
-//! // This code uses AsmJit's ptr_as_func<> to cast between void* and SumIntsFunc.
-//! ptr_as_func(p)(out, inA, inB);
-//!
-//! // Prints {5 8 4 9}
-//! printf("{%d %d %d %d}\n", out[0], out[1], out[2], out[3]);
-//!
-//! // Release 'p' is it's no longer needed. It will be destroyed with 'vm'
-//! // instance anyway, but it's a good practice to release it explicitly
-//! // when you know that the function will not be needed anymore.
-//! allocator.release(p);
-//!
-//! return 0;
-//! }
-//! ```
-//!
-//! If you know the base-address in advance (before the code generation) it can be passed as a second argument to
-//! \ref CodeHolder::init(). In that case the Assembler will know the absolute position of each instruction and
-//! would be able to use it during instruction encoding to prevent relocations where possible. The following example
-//! shows how to configure the base address:
-//!
-//! ```
-//! #include
-//! #include
-//!
-//! using namespace asmjit;
-//!
-//! void initializeCodeHolder(CodeHolder& code) {
-//! Environment env = Environment::host();
-//! uint64_t baseAddress = uint64_t(0x1234);
-//!
-//! // initialize CodeHolder with environment and custom base address.
-//! code.init(env, baseAddress);
-//! }
-//! ```
-//!
-//! ### Label Offsets and Links
-//!
-//! When a label that is not yet bound is used by the Assembler, it creates a \ref LabelLink, which is then added to
-//! a \ref LabelEntry. These links are also created if a label is used in a different section than in which it was
-//! bound. Let's examine some functions that can be used to check whether there are any unresolved links.
-//!
-//! ```
-//! #include
-//! #include
-//!
-//! using namespace asmjit;
-//!
-//! void labelLinksExample(CodeHolder& code, const Label& label) {
-//! // Tests whether the `label` is bound.
-//! bool isBound = code.isLabelBound(label);
-//! printf("Label %u is %s\n", label.id(), isBound ? "bound" : "not bound");
-//!
-//! // Returns true if the code contains either referenced, but unbound
-//! // labels, or cross-section label links that are not resolved yet.
-//! bool hasUnresolved = code.hasUnresolvedLinks(); // Boolean answer.
-//! size_t nUnresolved = code.unresolvedLinkCount(); // Count of unresolved links.
-//!
-//! printf("Number of unresolved links: %zu\n", nUnresolved);
-//! }
-//! ```
-//!
-//! There is no function that would return the number of unbound labels as this is completely unimportant from
-//! CodeHolder's perspective. If a label is not used then it doesn't matter whether it's bound or not, only actually
-//! used labels matter. After a Label is bound it's possible to query its offset offset relative to the start of the
-//! section where it was bound:
-//!
-//! ```
-//! #include
-//! #include
-//!
-//! using namespace asmjit;
-//!
-//! void labelOffsetExample(CodeHolder& code, const Label& label) {
-//! // Label offset is known after it's bound. The offset provided is relative
-//! // to the start of the section, see below for alternative. If the given
-//! // label is not bound the offset returned will be zero. It's recommended
-//! // to always check whether the label is bound before using its offset.
-//! uint64_t sectionOffset = code.labelOffset(label);
-//! printf("Label offset relative to section: %llu\n", (unsigned long long)sectionOffset);
-//!
-//! // If you use multiple sections and want the offset relative to the base.
-//! // NOTE: This function expects that the section has already an offset and
-//! // the label-link was resolved (if this is not true you will still get an
-//! // offset relative to the start of the section).
-//! uint64_t baseOffset = code.labelOffsetFromBase(label);
-//! printf("Label offset relative to base: %llu\n", (unsigned long long)baseOffset);
-//! }
-//! ```
-//!
-//! ### Sections
-//!
-//! AsmJit allows to create multiple sections within the same \ref CodeHolder. A test-case
-//! [asmjit_test_x86_sections.cpp](https://github.com/asmjit/asmjit/blob/master/test/asmjit_test_x86_sections.cpp)
-//! can be used as a reference point although the following example should also provide a useful insight:
-//!
-//! ```
-//! #include
-//! #include
-//!
-//! using namespace asmjit;
-//!
-//! void sectionsExample(CodeHolder& code) {
-//! // Text section is always provided as the first section.
-//! Section* text = code.textSection(); // or code.sectionById(0);
-//!
-//! // To create another section use CodeHolder::newSection().
-//! Section* data;
-//! Error err = code.newSection(&data,
-//! ".data", // Section name
-//! SIZE_MAX, // Name length if the name is not null terminated (or SIZE_MAX).
-//! SectionFlags::kNone, // Section flags, see SectionFlags.
-//! 8, // Section alignment, must be power of 2.
-//! 0); // Section order value (optional, default 0).
-//!
-//! // When you switch sections in Assembler, Builder, or Compiler the cursor
-//! // will always move to the end of that section. When you create an Assembler
-//! // the cursor would be placed at the end of the first (.text) section, which
-//! // is initially empty.
-//! x86::Assembler a(&code);
-//! Label L_Data = a.newLabel();
-//!
-//! a.mov(x86::eax, x86::ebx); // Emits in .text section.
-//!
-//! a.section(data); // Switches to the end of .data section.
-//! a.bind(L_Data); // Binds label in this .data section
-//! a.db(0x01); // Emits byte in .data section.
-//!
-//! a.section(text); // Switches to the end of .text section.
-//! a.add(x86::ebx, x86::eax); // Emits in .text section.
-//!
-//! // References a label in .text section, which was bound in .data section.
-//! // This would create a LabelLink even when the L_Data is already bound,
-//! // because the reference crosses sections. See below...
-//! a.lea(x86::rsi, x86::ptr(L_Data));
-//! }
-//! ```
-//!
-//! The last line in the example above shows that a LabelLink would be created even for bound labels that cross
-//! sections. In this case a referenced label was bound in another section, which means that the link couldn't be
-//! resolved at that moment. If your code uses sections, but you wish AsmJit to flatten these sections (you don't
-//! plan to flatten them manually) then there is an API for that.
-//!
-//! ```
-//! #include
-//! #include
-//!
-//! using namespace asmjit;
-//!
-//! // ... (continuing the previous example) ...
-//! void sectionsExampleContinued(CodeHolder& code) {
-//! // Suppose we have some code that contains multiple sections and
-//! // we would like to flatten it by using AsmJit's built-in API:
-//! Error err = code.flatten();
-//! if (err) {
-//! // There are many reasons it can fail, so always handle a possible error.
-//! printf("Failed to flatten the code: %s\n", DebugUtils::errorAsString(err));
-//! exit(1);
-//! }
-//!
-//! // After flattening all sections would contain assigned offsets
-//! // relative to base. Offsets are 64-bit unsigned integers so we
-//! // cast them to `size_t` for simplicity. On 32-bit targets it's
-//! // guaranteed that the offset cannot be greater than `2^32 - 1`.
-//! printf("Data section offset %zu", size_t(data->offset()));
-//!
-//! // The flattening doesn't resolve unresolved label links, this
-//! // has to be done manually as flattening can be done separately.
-//! err = code.resolveUnresolvedLinks();
-//! if (err) {
-//! // This is the kind of error that should always be handled...
-//! printf("Failed to resolve label links: %s\n", DebugUtils::errorAsString(err));
-//! exit(1);
-//! }
-//!
-//! if (code.hasUnresolvedLinks()) {
-//! // This would mean either unbound label or some other issue.
-//! printf("The code has %zu unbound labels\n", code.unresovedLinkCount());
-//! exit(1);
-//! }
-//! }
-//! ```
-
-
-//! \defgroup asmjit_assembler Assembler
-//! \brief Assembler interface and operands.
-//!
-//! ### Overview
-//!
-//! AsmJit's Assembler is used to emit machine code directly into a \ref CodeBuffer. In general, code generation
-//! with assembler requires the knowledge of the following:
-//!
-//! - \ref BaseAssembler and architecture-specific assemblers:
-//! - \ref x86::Assembler - Assembler specific to X86 architecture
-//! - \ref Operand and its variations:
-//! - \ref BaseReg - Base class for a register operand, inherited by:
-//! - \ref x86::Reg - Register operand specific to X86 architecture.
-//! - \ref BaseMem - Base class for a memory operand, inherited by:
-//! - \ref x86::Mem - Memory operand specific to X86 architecture.
-//! - \ref Imm - Immediate (value) operand.
-//! - \ref Label - Label operand.
-//!
-//! \note Assembler examples use \ref x86::Assembler as abstract interfaces cannot be used to generate code.
-//!
-//! ### Operand Basics
-//!
-//! Let's start with operands. \ref Operand is a data structure that defines a data layout of any operand. It can be
-//! inherited, but any class inheriting it cannot add any members to it, only the existing layout can be reused.
-//! AsmJit allows to construct operands dynamically, to store them, and to query a complete information about them
-//! at run-time. Operands are small (always 16 bytes per \ref Operand) and can be copied and passed by value. Please
-//! never allocate individual operands dynamically by using a `new` keyword - it would work, but then you would have
-//! to be responsible for deleting such operands. In AsmJit operands are always part of some other data structures
-//! like \ref InstNode, which is part of \ref asmjit_builder tool.
-//!
-//! Operands contain only identifiers, but not pointers to any code-generation data. For example \ref Label operand
-//! only provides label identifier, but not a pointer to \ref LabelEntry structure. In AsmJit such IDs are used to
-//! link stuff together without having to deal with pointers.
-//!
-//! AsmJit's operands all inherit from a base class called \ref Operand. Operands have the following properties that
-//! are commonly accessible by getters and setters:
-//!
-//! - \ref Operand - Base operand, which only provides accessors that are common to all operand types.
-//! - \ref BaseReg - Describes either physical or virtual register. Physical registers have id that matches the
-//! target's machine id directly whereas virtual registers must be allocated into physical registers by a register
-//! allocator pass. Register operand provides:
-//! - Register Type (\ref RegType) - Unique id that describes each possible register provided by the target
-//! architecture - for example X86 backend provides general purpose registers (GPB-LO, GPB-HI, GPW, GPD, and GPQ)
-//! and all types of other registers like K, MM, BND, XMM, YMM, ZMM, and TMM.
-//! - Register Group (\ref RegGroup) - Groups multiple register types under a single group - for example all
-//! general-purpose registers (of all sizes) on X86 are part of \ref RegGroup::kGp and all SIMD registers
-//! (XMM, YMM, ZMM) are part of \ref RegGroup::kVec.
-//! - Register Size - Contains the size of the register in bytes. If the size depends on the mode (32-bit vs
-//! 64-bit) then generally the higher size is used (for example RIP register has size 8 by default).
-//! - Register Id - Contains physical or virtual id of the register.
-//! - \ref BaseMem - Used to reference a memory location. Memory operand provides:
-//! - Base Register - A base register type and id (physical or virtual).
-//! - Index Register - An index register type and id (physical or virtual).
-//! - Offset - Displacement or absolute address to be referenced (32-bit if base register is used and 64-bit if
-//! base register is not used).
-//! - Flags that can describe various architecture dependent information (like scale and segment-override on X86).
-//! - \ref Imm - Immediate values are usually part of instructions (encoded within the instruction itself) or data.
-//! - \ref Label - used to reference a location in code or data. Labels must be created by the \ref BaseEmitter or
-//! by \ref CodeHolder. Each label has its unique id per \ref CodeHolder instance.
-//!
-//! ### Operand Manipulation
-//!
-//! AsmJit allows to construct operands dynamically, to store them, and to query a complete information about them at
-//! run-time. Operands are small (always 16 bytes per `Operand`) and should be always copied (by value) if you intend
-//! to store them (don't create operands by using `new` keyword, it's not recommended). Operands are safe to be passed
-//! to `memcpy()` and `memset()`, which becomes handy when working with arrays of operands. If you set all members of
-//! an \ref Operand to zero the operand would become NONE operand, which is the same as a default constructed Operand.
-//!
-//! The example below illustrates how operands can be used and modified even without using any other code generation
-//! classes. The example uses X86 architecture-specific operands.
-//!
-//! ```
-//! #include
-//!
-//! using namespace asmjit;
-//!
-//! // Registers can be copied, it's a common practice.
-//! x86::Gp dstRegByValue() { return x86::ecx; }
-//!
-//! void usingOperandsExample(x86::Assembler& a) {
-//! // Gets `ecx` register returned by a function.
-//! x86::Gp dst = dstRegByValue();
-//! // Gets `rax` register directly from the provided `x86` namespace.
-//! x86::Gp src = x86::rax;
-//! // Constructs `r10` dynamically.
-//! x86::Gp idx = x86::gpq(10);
-//! // Constructs [src + idx] memory address - referencing [rax + r10].
-//! x86::Mem m = x86::ptr(src, idx);
-//!
-//! // Examine `m`: Returns `RegType::kX86_Gpq`.
-//! m.indexType();
-//! // Examine `m`: Returns 10 (`r10`).
-//! m.indexId();
-//!
-//! // Reconstruct `idx` stored in mem:
-//! x86::Gp idx_2 = x86::Gp::fromTypeAndId(m.indexType(), m.indexId());
-//!
-//! // True, `idx` and idx_2` are identical.
-//! idx == idx_2;
-//!
-//! // Possible - op will still be the same as `m`.
-//! Operand op = m;
-//! // True (can be casted to BaseMem or architecture-specific Mem).
-//! op.isMem();
-//!
-//! // True, `op` is just a copy of `m`.
-//! m == op;
-//!
-//! // Static cast is fine and valid here.
-//! static_cast(op).addOffset(1);
-//! // However, using `as()` to cast to a derived type is preferred.
-//! op.as().addOffset(1);
-//! // False, `op` now points to [rax + r10 + 2], which is not [rax + r10].
-//! m == op;
-//!
-//! // Emitting 'mov' - type safe way.
-//! a.mov(dst, m);
-//! // Not possible, `mov` doesn't provide mov(x86::Gp, Operand) overload.
-//! a.mov(dst, op);
-//!
-//! // Type-unsafe, but possible.
-//! a.emit(x86::Inst::kIdMov, dst, m);
-//! // Also possible, `emit()` is typeless and can be used with raw Operand.
-//! a.emit(x86::Inst::kIdMov, dst, op);
-//! }
-//! ```
-//!
-//! Some operands have to be created explicitly by emitters. For example labels must be created by \ref
-//! BaseEmitter::newLabel(), which creates a label entry and returns a \ref Label operand with the id that refers
-//! to it. Such label then can be used by emitters.
-//!
-//! ### Memory Operands
-//!
-//! Some architectures like X86 provide a complex memory addressing model that allows to encode addresses having a
-//! BASE register, INDEX register with a possible scale (left shift), and displacement (called offset in AsmJit).
-//! Memory address on X86 can also specify memory segment (segment-override in X86 terminology) and some instructions
-//! (gather / scatter) require INDEX to be a \ref x86::Vec register instead of a general-purpose register.
-//!
-//! AsmJit allows to encode and work with all forms of addresses mentioned and implemented by X86. In addition, it
-//! also allows to construct absolute 64-bit memory address operands, which is only allowed in one form of 'mov'
-//! instruction.
-//!
-//! ```
-//! #include
-//!
-//! using namespace asmjit;
-//!
-//! void testX86Mem() {
-//! // Makes it easier to access x86 stuff...
-//! using namespace asmjit::x86;
-//!
-//! // BASE + OFFSET.
-//! Mem a = ptr(rax); // a = [rax]
-//! Mem b = ptr(rax, 15); // b = [rax + 15]
-//!
-//! // BASE + INDEX << SHIFT - Shift is in BITS as used by X86!
-//! Mem c = ptr(rax, rbx); // c = [rax + rbx]
-//! Mem d = ptr(rax, rbx, 2); // d = [rax + rbx << 2]
-//! Mem e = ptr(rax, rbx, 2, 15); // e = [rax + rbx << 2 + 15]
-//!
-//! // BASE + VM (Vector Index) (encoded as MOD+VSIB).
-//! Mem f = ptr(rax, xmm1); // f = [rax + xmm1]
-//! Mem g = ptr(rax, xmm1, 2); // g = [rax + xmm1 << 2]
-//! Mem h = ptr(rax, xmm1, 2, 15); // h = [rax + xmm1 << 2 + 15]
-//!
-//! // Absolute adddress:
-//! uint64_t addr = (uint64_t)0x1234;
-//! Mem i = ptr(addr); // i = [0x1234]
-//! Mem j = ptr(addr, rbx); // j = [0x1234 + rbx]
-//! Mem k = ptr(addr, rbx, 2); // k = [0x1234 + rbx << 2]
-//!
-//! // LABEL - Will be encoded as RIP (64-bit) or absolute address (32-bit).
-//! Label L = ...;
-//! Mem m = ptr(L); // m = [L]
-//! Mem n = ptr(L, rbx); // n = [L + rbx]
-//! Mem o = ptr(L, rbx, 2); // o = [L + rbx << 2]
-//! Mem p = ptr(L, rbx, 2, 15); // p = [L + rbx << 2 + 15]
-//!
-//! // RIP - 64-bit only (RIP can't use INDEX).
-//! Mem q = ptr(rip, 24); // q = [rip + 24]
-//! }
-//! ```
-//!
-//! Memory operands can optionally contain memory size. This is required by instructions where the memory size cannot
-//! be deduced from other operands, like `inc` and `dec` on X86:
-//!
-//! ```
-//! #include
-//!
-//! using namespace asmjit;
-//!
-//! void testX86Mem() {
-//! // The same as: dword ptr [rax + rbx].
-//! x86::Mem a = x86::dword_ptr(rax, rbx);
-//!
-//! // The same as: qword ptr [rdx + rsi << 0 + 1].
-//! x86::Mem b = x86::qword_ptr(rdx, rsi, 0, 1);
-//! }
-//! ```
-//!
-//! Memory operands provide API that can be used to access its properties:
-//!
-//! ```
-//! #include
-//!
-//! using namespace asmjit;
-//!
-//! void testX86Mem() {
-//! // The same as: dword ptr [rax + 12].
-//! x86::Mem mem = x86::dword_ptr(rax, 12);
-//!
-//! mem.hasBase(); // true.
-//! mem.hasIndex(); // false.
-//! mem.size(); // 4.
-//! mem.offset(); // 12.
-//!
-//! mem.setSize(0); // Sets the size to 0 (makes it sizeless).
-//! mem.addOffset(-1); // Adds -1 to the offset and makes it 11.
-//! mem.setOffset(0); // Sets the offset to 0.
-//! mem.setBase(rcx); // Changes BASE to RCX.
-//! mem.setIndex(rax); // Changes INDEX to RAX.
-//! mem.hasIndex(); // true.
-//! }
-//! // ...
-//! ```
-//!
-//! Making changes to memory operand is very comfortable when emitting loads
-//! and stores:
-//!
-//! ```
-//! #include
-//!
-//! using namespace asmjit;
-//!
-//! void testX86Mem(CodeHolder& code) {
-//! x86::Assembler a(code); // Your initialized x86::Assembler.
-//! x86::Mem mSrc = x86::ptr(eax); // Construct [eax] memory operand.
-//!
-//! // One way of emitting bunch of loads is to use `mem.adjusted()`, which
-//! // returns a new memory operand and keeps the source operand unchanged.
-//! a.movaps(x86::xmm0, mSrc); // No adjustment needed to load [eax].
-//! a.movaps(x86::xmm1, mSrc.adjusted(16)); // Loads from [eax + 16].
-//! a.movaps(x86::xmm2, mSrc.adjusted(32)); // Loads from [eax + 32].
-//! a.movaps(x86::xmm3, mSrc.adjusted(48)); // Loads from [eax + 48].
-//!
-//! // ... do something with xmm0-3 ...
-//!
-//! // Another way of adjusting memory is to change the operand in-place.
-//! // If you want to keep the original operand you can simply clone it.
-//! x86::Mem mDst = mSrc.clone(); // Clone mSrc.
-//!
-//! a.movaps(mDst, x86::xmm0); // Stores xmm0 to [eax].
-//! mDst.addOffset(16); // Adds 16 to `mDst`.
-//!
-//! a.movaps(mDst, x86::xmm1); // Stores to [eax + 16] .
-//! mDst.addOffset(16); // Adds 16 to `mDst`.
-//!
-//! a.movaps(mDst, x86::xmm2); // Stores to [eax + 32].
-//! mDst.addOffset(16); // Adds 16 to `mDst`.
-//!
-//! a.movaps(mDst, x86::xmm3); // Stores to [eax + 48].
-//! }
-//! ```
-//!
-//! ### Assembler Examples
-//!
-//! - \ref x86::Assembler provides many X86/X64 examples.
-
-
-//! \defgroup asmjit_builder Builder
-//! \brief Builder interface, nodes, and passes.
-//!
-//! ### Overview
-//!
-//! Both \ref BaseBuilder and \ref BaseCompiler interfaces describe emitters that emit into a representation that
-//! allows further processing. The code stored in such representation is completely safe to be patched, simplified,
-//! reordered, obfuscated, removed, injected, analyzed, or processed some other way. Each instruction, label,
-//! directive, or other building block is stored as \ref BaseNode (or derived class like \ref InstNode or \ref
-//! LabelNode) and contains all the information necessary to pass that node later to the assembler.
-//!
-//! \ref BaseBuilder is an emitter that inherits from \ref BaseEmitter interface. It was designed to provide a maximum
-//! compatibility with the existing \ref BaseAssembler emitter so users can move from assembler to builder when needed,
-//! for example to implement post-processing, which is not possible with Assembler.
-//!
-//! ### Builder Nodes
-//!
-//! \ref BaseBuilder doesn't generate machine code directly, it uses an intermediate representation based on nodes,
-//! however, it allows to serialize to \ref BaseAssembler when the code is ready to be encoded.
-//!
-//! There are multiple node types used by both \ref BaseBuilder and \ref BaseCompiler :
-//!
-//! - Basic nodes:
-//! - \ref BaseNode - Base class for all nodes.
-//! - \ref InstNode - Represents an instruction node.
-//! - \ref AlignNode - Represents an alignment directive (.align).
-//! - \ref LabelNode - Represents a location where to bound a \ref Label.
-//!
-//! - Data nodes:
-//! - \ref EmbedDataNode - Represents data.
-//! - \ref EmbedLabelNode - Represents \ref Label address embedded as data.
-//! - \ref EmbedLabelDeltaNode - Represents a difference of two labels embedded in data.
-//! - \ref ConstPoolNode - Represents a constant pool data embedded as data.
-//!
-//! - Informative nodes:
-//! - \ref CommentNode - Represents a comment string, doesn't affect code generation.
-//! - \ref SentinelNode - A marker that can be used to remember certain position in code or data, doesn't affect
-//! code generation. Used by \ref FuncNode to mark the end of a function.
-//!
-//! - Other nodes are provided by \ref asmjit_compiler infrastructure.
-//!
-//! ### Builder Examples
-//!
-//! - \ref x86::Builder provides many X86/X64 examples.
-
-
-//! \defgroup asmjit_compiler Compiler
-//! \brief Compiler interface.
-//!
-//! ### Overview
-//!
-//! \ref BaseCompiler is a high-level interface, which provides register allocation and support for defining and
-//! invoking functions, built on top of \ref BaseBuilder interface At the moment it's the easiest way of generating
-//! code in AsmJit as most architecture and OS specifics is properly abstracted and handled by AsmJit automatically.
-//! However, abstractions also mean restrictions, which means that \ref BaseCompiler has more limitations than \ref
-//! BaseAssembler or \ref BaseBuilder.
-//!
-//! Since \ref BaseCompiler provides register allocation it also establishes the concept of functions - a function
-//! in Compiler sense is a unit in which virtual registers are allocated into physical registers by the register
-//! allocator. In addition, it enables to use such virtual registers in function invocations.
-//!
-//! \ref BaseCompiler automatically handles function calling conventions. It's still architecture dependent, but
-//! makes the code generation much easies. Functions are essential; the first-step to generate some code is to define
-//! a signature of the function to be generated (before generating the function body itself). Function arguments and
-//! return value(s) are handled by assigning virtual registers to them. Similarly, function calls are handled the same
-//! way.
-//!
-//! ### Compiler Nodes
-//!
-//! \ref BaseCompiler adds some nodes that are required for function generation and invocation:
-//!
-//! - \ref FuncNode - Represents a function definition.
-//! - \ref FuncRetNode - Represents a function return.
-//! - \ref InvokeNode - Represents a function invocation.
-//!
-//! \ref BaseCompiler also makes the use of passes (\ref Pass) and automatically adds an architecture-dependent
-//! register allocator pass to the list of passes when attached to \ref CodeHolder.
-//!
-//! ### Compiler Examples
-//!
-//! - \ref x86::Compiler provides many X86/X64 examples.
-//!
-//! ### Compiler Tips
-//!
-//! Users of AsmJit have done mistakes in the past, this section should provide some useful tips for beginners:
-//!
-//! - Virtual registers in compiler are bound to a single function. At the moment the implementation doesn't
-//! care whether a single virtual register is used in multiple functions, but it sees it as two independent
-//! virtual registers in that case. This means that virtual registers cannot be used to implement global
-//! variables. Global variables are basically memory addresses which functions can read from and write to,
-//! and they have to be implemented in the same way.
-//!
-//! - Compiler provides a useful debugging functionality, which can be turned on through \ref FormatFlags. Use
-//! \ref Logger::addFlags() to turn on additional logging features when using Compiler.
-
-
-//! \defgroup asmjit_function Function
-//! \brief Function definitions.
-//!
-//! ### Overview
-//!
-//! AsmJit provides functionality that can be used to define function signatures and to calculate automatically
-//! optimal function frame that can be used directly by a prolog and epilog insertion. This feature was exclusive
-//! to AsmJit's Compiler for a very long time, but was abstracted out and is now available for all users regardless
-//! of the emitter they use. The following use cases are possible:
-//!
-//! - Calculate function frame before the function is generated - this is the only way available to \ref
-//! BaseAssembler users and it will be described in this section.
-//!
-//! - Calculate function frame after the function is generated - this way is generally used by \ref BaseBuilder
-//! and \ref BaseCompiler emitters and this way is generally described in \ref asmjit_compiler section.
-//!
-//! The following concepts are used to describe and create functions in AsmJit:
-//!
-//! - \ref TypeId - Type-id is an 8-bit value that describes a platform independent type as we know from C/C++.
-//! It provides abstractions for most common types like `int8_t`, `uint32_t`, `uintptr_t`, `float`, `double`,
-//! and all possible vector types to match ISAs up to AVX512. \ref TypeId was introduced originally for \ref
-//! asmjit_compiler, but it's now used by \ref FuncSignature as well.
-//!
-//! - \ref CallConv - Describes a calling convention - this class contains instructions to assign registers and
-//! stack addresses to function arguments and return value(s), but doesn't specify any function signature itself.
-//! Calling conventions are architecture and OS dependent.
-//!
-//! - \ref FuncSignature - Describes a function signature, for example `int func(int, int)`. FuncSignature contains
-//! a function calling convention id, return value type, and function arguments. The signature itself is platform
-//! independent and uses \ref TypeId to describe types of function arguments and function return value(s).
-//!
-//! - \ref FuncDetail - Architecture and ABI dependent information that describes \ref CallConv and expanded \ref
-//! FuncSignature. Each function argument and return value is represented as \ref FuncValue that contains the
-//! original \ref TypeId enriched with additional information that specifies whether the value is passed or
-//! returned by register (and which register) or by stack. Each value also contains some other metadata that
-//! provide additional information required to handle it properly (for example whether a vector is passed
-//! indirectly by a pointer as required by WIN64 calling convention).
-//!
-//! - \ref FuncFrame - Contains information about the function frame that can be used by prolog/epilog inserter
-//! (PEI). Holds call stack size size and alignment, local stack size and alignment, and various attributes that
-//! describe how prolog and epilog should be constructed. `FuncFrame` doesn't know anything about function's
-//! arguments or return values, it hold only information necessary to create a valid and ABI conforming function
-//! prologs and epilogs.
-//!
-//! - \ref FuncArgsAssignment - A helper class that can be used to reassign function arguments into user specified
-//! registers. It's architecture and ABI dependent mapping from function arguments described by \ref CallConv
-//! and \ref FuncDetail into registers specified by the user.
-//!
-//! It's a lot of concepts where each represents one step in a function frame calculation. It can be used to create
-//! function prologs, epilogs, and also to calculate information necessary to perform function calls.
-
-
-//! \defgroup asmjit_logging Logging
-//! \brief Logging and formatting.
-//!
-//! ### Overview
-//!
-//! The initial phase of a project that generates machine code is not always smooth. Failure cases are common not just
-//! at the beginning phase, but also during the development or refactoring. AsmJit provides logging functionality to
-//! address this issue. AsmJit does already a good job with function overloading to prevent from emitting unencodable
-//! instructions, but it can't prevent from emitting machine code that is correct at instruction level, but doesn't
-//! work when it's executed asa whole. Logging has always been an important part of AsmJit's infrastructure and looking
-//! at logs can sometimes reveal code generation issues quickly.
-//!
-//! AsmJit provides API for logging and formatting:
-//!
-//! - \ref Logger - A logger that you can pass to \ref CodeHolder and all emitters that inherit from \ref BaseEmitter.
-//!
-//! - \ref FormatOptions - Formatting options that can change how instructions and operands are formatted.
-//!
-//! - \ref Formatter - A namespace that provides functions that can format input data like \ref Operand, \ref BaseReg,
-//! \ref Label, and \ref BaseNode into \ref String.
-//!
-//! AsmJit's \ref Logger serves the following purposes:
-//!
-//! - Provides a basic foundation for logging.
-//!
-//! - Abstract class leaving the implementation on users. The following built-in implementations are provided for
-//! simplicty:
-//!
-//! - \ref FileLogger implements logging into a standard `FILE` stream.
-//! - \ref StringLogger serializes all logs into a \ref String instance.
-//!
-//! AsmJit's \ref FormatOptions provides the following to customize the formatting of instructions and operands through:
-//!
-//! - \ref FormatFlags
-//! - \ref FormatIndentationGroup
-//!
-//! ### Logging
-//!
-//! A \ref Logger is typically attached to a \ref CodeHolder, which propagates it to all attached emitters
-//! automatically. The example below illustrates how to use \ref FileLogger that outputs to standard output:
-//!
-//! ```
-//! #include
-//! #include
-//!
-//! using namespace asmjit;
-//!
-//! int main() {
-//! JitRuntime rt; // Runtime specialized for JIT code execution.
-//! FileLogger logger(stdout); // Logger should always survive CodeHolder.
-//!
-//! CodeHolder code; // Holds code and relocation information.
-//! code.init(rt.environment()); // Initialize to the same arch as JIT runtime.
-//! code.setLogger(&logger); // Attach the `logger` to `code` holder.
-//!
-//! // ... code as usual, everything emitted will be logged to `stdout` ...
-//! return 0;
-//! }
-//! ```
-//!
-//! If output to FILE stream is not desired it's possible to use \ref StringLogger, which concatenates everything
-//! into a multi-line string:
-//!
-//! ```
-//! #include
-//! #include
-//! #include
-//!
-//! using namespace asmjit;
-//!
-//! int main() {
-//! JitRuntime rt; // Runtime specialized for JIT code execution.
-//! StringLogger logger; // Logger should always survive CodeHolder.
-//!
-//! CodeHolder code; // Holds code and relocation information.
-//! code.init(rt.environment()); // Initialize to the same arch as JIT runtime.
-//! code.setLogger(&logger); // Attach the `logger` to `code` holder.
-//!
-//! // ... code as usual, logging will be concatenated to logger string ...
-//!
-//! // You can either use the string from StringLogger directly or you can
-//! // move it. Logger::data() returns its content as null terminated char[].
-//! printf("Logger content: %s\n", logger.data());
-//!
-//! // It can be moved into your own string like this:
-//! String content = std::move(logger.content());
-//! printf("The same content: %s\n", content.data());
-//!
-//! return 0;
-//! }
-//! ```
-//!
-//! ### Formatting
-//!
-//! AsmJit uses \ref Formatter to format inputs that are then passed to \ref Logger. Formatting is public and can be
-//! used by AsmJit users as well. The most important thing to know regarding formatting is that \ref Formatter always
-//! appends to the output string, so it can be used to build complex strings without having to concatenate
-//! intermediate strings.
-//!
-//! The first example illustrates how to format operands:
-//!
-//! ```
-//! #include
-//! #include
-//!
-//! using namespace asmjit;
-//!
-//! void logOperand(Arch arch, const Operand_& op) {
-//! // The emitter is optional (named labels and virtual registers need it).
-//! BaseEmitter* emitter = nullptr;
-//!
-//! // No flags by default.
-//! FormatFlags formatFlags = FormatFlags::kNone;
-//!
-//! StringTmp<128> sb;
-//! Formatter::formatOperand(sb, formatFlags, emitter, arch, op);
-//! printf("%s\n", sb.data());
-//! }
-//!
-//! void formattingExample() {
-//! using namespace x86;
-//!
-//! // Architecture is not part of operand, it must be passed explicitly.
-//! // Format flags. We pass it explicitly also to 'logOperand' to make
-//! // compatible with what AsmJit normally does.
-//! Arch arch = Arch::kX64;
-//!
-//! log(arch, rax); // Prints 'rax'.
-//! log(arch, ptr(rax, rbx, 2)); // Prints '[rax + rbx * 4]`.
-//! log(arch, dword_ptr(rax, rbx, 2)); // Prints 'dword [rax + rbx * 4]`.
-//! log(arch, imm(42)); // Prints '42'.
-//! }
-//! ```
-//!
-//! Next example illustrates how to format whole instructions:
-//!
-//! ```
-//! #include
-//! #include
-//! #include
-//!
-//! using namespace asmjit;
-//!
-//! template
-//! void logInstruction(Arch arch, const BaseInst& inst, Args&&... args) {
-//! // The emitter is optional (named labels and virtual registers need it).
-//! BaseEmitter* emitter = nullptr;
-//!
-//! // No flags by default.
-//! FormatFlags formatFlags = FormatFlags::kNone;
-//!
-//! // The formatter expects operands in an array.
-//! Operand_ operands { std::forward(args)... };
-//!
-//! StringTmp<128> sb;
-//! Formatter::formatInstruction(
-//! sb, formatFlags, emitter, arch, inst, operands, sizeof...(args));
-//! printf("%s\n", sb.data());
-//! }
-//!
-//! void formattingExample() {
-//! using namespace x86;
-//!
-//! // Architecture is not part of operand, it must be passed explicitly.
-//! // Format flags. We pass it explicitly also to 'logOperand' to make
-//! // compatible with what AsmJit normally does.
-//! Arch arch = Arch::kX64;
-//!
-//! // Prints 'mov rax, rcx'.
-//! logInstruction(arch, BaseInst(Inst::kIdMov), rax, rcx);
-//!
-//! // Prints 'vaddpd zmm0, zmm1, [rax] {1to8}'.
-//! logInstruction(arch,
-//! BaseInst(Inst::kIdVaddpd),
-//! zmm0, zmm1, ptr(rax)._1toN());
-//!
-//! // BaseInst abstracts instruction id, instruction options, and extraReg.
-//! // Prints 'lock add [rax], rcx'.
-//! logInstruction(arch,
-//! BaseInst(Inst::kIdAdd, InstOptions::kX86_Lock),
-//! x86::ptr(rax), rcx);
-//!
-//! // Similarly an extra register (like AVX-512 selector) can be used.
-//! // Prints 'vaddpd zmm0 {k2} {z}, zmm1, [rax]'.
-//! logInstruction(arch,
-//! BaseInst(Inst::kIdAdd, InstOptions::kX86_ZMask, k2),
-//! zmm0, zmm1, ptr(rax));
-//! }
-//! ```
-//!
-//! And finally, the example below illustrates how to use a built-in function to format the content of
-//! \ref BaseBuilder, which consists of nodes:
-//!
-//! ```
-//! #include
-//! #include
-//!
-//! using namespace asmjit;
-//!
-//! void formattingExample(BaseBuilder* builder) {
-//! FormatFlags formatFlags = FormatFlags::kNone;
-//!
-//! // This also shows how temporary strings can be used.
-//! StringTmp<512> sb;
-//!
-//! // FormatNodeList requires the String for output, formatting flags, which
-//! // were zero (no extra flags), and the builder instance, which we have
-//! // provided. An overloaded version also exists, which accepts begin and
-//! // and end nodes, which can be used to only format a range of nodes.
-//! Formatter::formatNodeList(sb, formatFlags, builder);
-//!
-//! // You can do whatever else with the string, it's always null terminated,
-//! // so it can be passed to C functions like printf().
-//! printf("%s\n", sb.data());
-//! }
-//! ```
-
-
-//! \defgroup asmjit_error_handling Error Handling
-//! \brief Error handling.
-//!
-//! ### Overview
-//!
-//! AsmJit uses error codes to represent and return errors. Every function that can fail returns an \ref Error code.
-//! Exceptions are never thrown by AsmJit itself even in extreme conditions like out-of-memory, but it's possible to
-//! override \ref ErrorHandler::handleError() to throw, in that case no error will be returned and exception will be
-//! thrown instead. All functions where this can happen are not marked `noexcept`.
-//!
-//! Errors should never be ignored, however, checking errors after each AsmJit API call would simply overcomplicate
-//! the whole code generation experience. \ref ErrorHandler exists to make the use of AsmJit API simpler as it allows
-//! to customize how errors can be handled:
-//!
-//! - Record the error and continue (the way how the error is user-implemented).
-//! - Throw an exception. AsmJit doesn't use exceptions and is completely exception-safe, but it's perfectly legal
-//! to throw an exception from the error handler.
-//! - Use plain old C's `setjmp()` and `longjmp()`. Asmjit always puts Assembler, Builder and Compiler to a
-//! consistent state before calling \ref ErrorHandler::handleError(), so `longjmp()` can be used without issues
-//! to cancel the code-generation if an error occurred. This method can be used if exception handling in your
-//! project is turned off and you still want some comfort. In most cases it should be safe as AsmJit uses \ref
-//! Zone memory and the ownership of memory it allocates always ends with the instance that allocated it. If
-//! using this approach please never jump outside the life-time of \ref CodeHolder and \ref BaseEmitter.
-//!
-//! ### Using ErrorHandler
-//!
-//! An example of attaching \ref ErrorHandler to \ref CodeHolder.
-//!
-//! ```
-//! #include
-//! #include
-//!
-//! using namespace asmjit;
-//!
-//! // A simple error handler implementation, extend according to your needs.
-//! class MyErrorHandler : public ErrorHandler {
-//! public:
-//! void handleError(Error err, const char* message, BaseEmitter* origin) override {
-//! printf("AsmJit error: %s\n", message);
-//! }
-//! };
-//!
-//! int main() {
-//! JitRuntime rt;
-//!
-//! MyErrorHandler myErrorHandler;
-//! CodeHolder code;
-//!
-//! code.init(rt.environment());
-//! code.setErrorHandler(&myErrorHandler);
-//!
-//! x86::Assembler a(&code);
-//! // ... code generation ...
-//!
-//! return 0;
-//! }
-//! ```
-//!
-//! Useful classes in error handling group:
-//!
-//! - See \ref DebugUtils that provides utilities useful for debugging.
-//! - See \ref Error that lists error codes that AsmJit uses.
-//! - See \ref ErrorHandler for more details about error handling.
-
-
-//! \defgroup asmjit_instruction_db Instruction DB
-//! \brief Instruction database (introspection, read/write, validation, ...).
-//!
-//! ### Overview
-//!
-//! AsmJit provides a public instruction database that can be used to query information about a complete instruction.
-//! The instruction database requires the knowledge of the following:
-//!
-//! - \ref BaseInst - Base instruction that contains instruction id, options, and a possible extra-register that
-//! represents either REP prefix counter or AVX-512 selector (mask).
-//!
-//! - \ref Operand - Represents operands of an instruction.
-//!
-//! Each instruction can be then queried for the following information:
-//!
-//! - \ref InstRWInfo - Read/write information of instruction and its oprands (includes \ref OpRWInfo).
-//!
-//! - \ref CpuFeatures - CPU features required to execute the instruction.
-//!
-//! In addition to query functionality AsmJit is also able to validate whether an instruction and its operands are
-//! valid. This is useful for making sure that what user tries to emit is correct and it can be also used by other
-//! projects that parse user input, like AsmTK project.
-//!
-//! ### Query API
-//!
-//! The instruction query API is provided by \ref InstAPI namespace. The following queries are possible:
-//!
-//! - \ref InstAPI::queryRWInfo() - queries read/write information of the given instruction and its operands.
-//! Includes also CPU flags read/written.
-//!
-//! - \ref InstAPI::queryFeatures() - queries CPU features that are required to execute the given instruction. A full
-//! instruction with operands must be given as some architectures like X86 may require different features for the
-//! same instruction based on its operands.
-//!
-//! - asmjit_test_instinfo.cpp
-//! can be also used as a reference about accessing instruction information.
-//!
-//! ### Validation API
-//!
-//! The instruction validation API is provided by \ref InstAPI namespace in the similar fashion like the Query API,
-//! however, validation can also be turned on at \ref BaseEmitter level. The following is possible:
-//!
-//! - \ref InstAPI::validate() - low-level instruction validation function that is used internally by emitters if
-//! strict validation is enabled.
-//!
-//! - \ref BaseEmitter::addValidationOptions() - can be used to enable validation at emitter level, see
-//! \ref ValidationOptions.
-
-
-//! \defgroup asmjit_virtual_memory Virtual Memory
-//! \brief Virtual memory management.
-//!
-//! ### Overview
-//!
-//! AsmJit's virtual memory management is divided into two main categories:
-//!
-//! - Low level API that provides cross-platform abstractions for virtual memory allocation. Implemented in
-//! \ref VirtMem namespace.
-//!
-//! - High level API that makes it very easy to store generated code for execution. See \ref JitRuntime, which is
-//! used by many examples for its simplicity and easy integration with \ref CodeHolder. There is also \ref
-//! JitAllocator, which lays somewhere between RAW memory allocation and \ref JitRuntime.
-
-
-//! \defgroup asmjit_zone Zone Memory
-//! \brief Zone memory allocator and containers.
-//!
-//! ### Overview
-//!
-//! AsmJit uses zone memory allocation (also known as Arena allocation) to allocate most of the data it uses. It's a
-//! fast allocator that allows AsmJit to allocate a lot of small data structures fast and without `malloc()` overhead.
-//! Since code generators and all related classes are usually short-lived this approach decreases memory usage and
-//! fragmentation as arena-based allocators always allocate larger blocks of memory, which are then split into smaller
-//! chunks.
-//!
-//! Another advantage of zone memory allocation is that since the whole library uses this strategy it's very easy to
-//! deallocate everything that a particular instance is holding by simply releasing the memory the allocator holds.
-//! This improves destruction time of such objects as there is no destruction at all. Long-lived objects just reset
-//! its data in destructor or in their reset() member function for a future reuse. For this purpose all containers in
-//! AsmJit are also zone allocated.
-//!
-//! ### Zone Allocation
-//!
-//! - \ref Zone - Incremental zone memory allocator with minimum features. It can only allocate memory without the
-//! possibility to return it back to the allocator.
-//!
-//! - \ref ZoneTmp - A temporary \ref Zone with some initial static storage. If the allocation requests fit the
-//! static storage allocated then there will be no dynamic memory allocation during the lifetime of \ref ZoneTmp,
-//! otherwise it would act as \ref Zone with one preallocated block on the stack.
-//!
-//! - \ref ZoneAllocator - A wrapper of \ref Zone that provides the capability of returning memory to the allocator.
-//! Such memory is stored in a pool for later reuse.
-//!
-//! ### Zone Allocated Containers
-//!
-//! - \ref ZoneString - Zone allocated string.
-//! - \ref ZoneHash - Zone allocated hash table.
-//! - \ref ZoneTree - Zone allocated red-black tree.
-//! - \ref ZoneList - Zone allocated double-linked list.
-//! - \ref ZoneStack - Zone allocated stack.
-//! - \ref ZoneVector - Zone allocated vector.
-//! - \ref ZoneBitVector - Zone allocated vector of bits.
-//!
-//! ### Using Zone Allocated Containers
-//!
-//! The most common data structure exposed by AsmJit is \ref ZoneVector. It's very similar to `std::vector`, but the
-//! implementation doesn't use exceptions and uses the mentioned \ref ZoneAllocator for performance reasons. You don't
-//! have to worry about allocations as you should not need to add items to AsmJit's data structures directly as there
-//! should be API for all required operations.
-//!
-//! The following APIs in \ref CodeHolder returns \ref ZoneVector reference:
-//!
-//! ```
-//! using namespace asmjit;
-//!
-//! void example(CodeHolder& code) {
-//! // Contains all emitters attached to CodeHolder.
-//! const ZoneVector& emitters = code.emitters();
-//!
-//! // Contains all section entries managed by CodeHolder.
-//! const ZoneVector& sections = code.sections();
-//!
-//! // Contains all label entries managed by CodeHolder.
-//! const ZoneVector& labelEntries = code.labelEntries();
-//!
-//! // Contains all relocation entries managed by CodeHolder.
-//! const ZoneVector& relocEntries = code.relocEntries();
-//! }
-//! ```
-//!
-//! \ref ZoneVector has overloaded array access operator to make it possible to access its elements through operator[].
-//! Some standard functions like \ref ZoneVector::empty(), \ref ZoneVector::size(), and \ref ZoneVector::data() are
-//! provided as well. Vectors are also iterable through a range-based for loop:
-//!
-//! ```
-//! using namespace asmjit;
-//!
-//! void example(CodeHolder& code) {
-//! for (LabelEntry* le : code.labelEntries()) {
-//! printf("Label #%u {Bound=%s Offset=%llu}",
-//! le->id(),
-//! le->isBound() ? "true" : "false",
-//! (unsigned long long)le->offset());
-//! }
-//! }
-//! ```
-//!
-//! ### Design Considerations
-//!
-//! Zone-allocated containers do not store the allocator within the container. This decision was made to reduce the
-//! footprint of such containers as AsmJit tooling, especially Compiler's register allocation, may use many instances
-//! of such containers to perform code analysis and register allocation.
-//!
-//! For example to append an item into a \ref ZoneVector it's required to pass the allocator as the first argument,
-//! so it can be used in case that the vector needs a reallocation. Such function also returns an error, which must
-//! be propagated to the caller.
-//!
-//! ```
-//! using namespace asmjit
-//!
-//! Error example(ZoneAllocator* allocator) {
-//! ZoneVector vector;
-//!
-//! // Unfortunately, allocator must be provided to all functions that mutate
-//! // the vector. However, AsmJit users should never need to do this as all
-//! // manipulation should be done through public API, which takes care of
-//! // that.
-//! for (int i = 0; i < 100; i++) {
-//! ASMJIT_PROPAGATE(vector.append(allocator, i));
-//! }
-//!
-//! // By default vector's destructor doesn't release anything as it knows
-//! // that its content is zone allocated. However, \ref ZoneVector::release
-//! // can be used to explicitly release the vector data to the allocator if
-//! // necessary
-//! vector.release(allocator);
-//! }
-//! ```
-//!
-//! Containers like \ref ZoneVector also provide a functionality to reserve a certain number of items before any items
-//! are added to it. This approach is used internally in most places as it allows to prepare space for data that will
-//! be added to some container before the data itself was created.
-//!
-//! ```
-//! using namespace asmjit
-//!
-//! Error example(ZoneAllocator* allocator) {
-//! ZoneVector vector;
-//!
-//! ASMJIT_PROPAGATE(vector.willGrow(100));
-//! for (int i = 0; i < 100; i++) {
-//! // Cannot fail.
-//! vector.appendUnsafe(allocator, i);
-//! }
-//!
-//! vector.release(allocator);
-//! }
-//! ```
-
-
-//! \defgroup asmjit_utilities Utilities
-//! \brief Utility classes and functions.
-//!
-//! ### Overview
-//!
-//! AsmJit uses and provides utility classes and functions, that can be used with AsmJit. The functionality can be
-//! divided into the following topics:
-//!
-//! ### String Functionality
-//!
-//! - \ref String - AsmJit's string container, which is used internally and which doesn't use exceptions and has
-//! a stable layout, which is not dependent on C++ standard library.
-//!
-//! - \ref StringTmp - String that can have base storage allocated on stack. The amount of storage on stack can
-//! be specified as a template parameter.
-//!
-//! - \ref FixedString - Fixed string container limited up to N characters.
-//!
-//! ### Code Generation Utilities
-//!
-//! - \ref ConstPool - Constant pool used by \ref BaseCompiler, but also available to users that may find use of it.
-//!
-//! ### Support Functionality Used by AsmJit
-//!
-//! - \ref Support namespace provides many other utility functions and classes that are used by AsmJit, and made
-//! public.
-
-
-//! \defgroup asmjit_x86 X86 Backend
-//! \brief X86/X64 backend.
-
-
-//! \cond INTERNAL
-//! \defgroup asmjit_ra RA
-//! \brief Register allocator internals.
-//! \endcond
-
-} // {asmjit}
-
-#include "asmjit-scope-begin.h"
-#include "core/archtraits.h"
-#include "core/assembler.h"
-#include "core/builder.h"
-#include "core/codeholder.h"
-#include "core/compiler.h"
-#include "core/constpool.h"
-#include "core/cpuinfo.h"
-#include "core/emitter.h"
-#include "core/environment.h"
-#include "core/errorhandler.h"
-#include "core/formatter.h"
-#include "core/func.h"
-#include "core/globals.h"
-#include "core/inst.h"
-#include "core/jitallocator.h"
-#include "core/jitruntime.h"
-#include "core/logger.h"
-#include "core/operand.h"
-#include "core/osutils.h"
-#include "core/string.h"
-#include "core/support.h"
-#include "core/target.h"
-#include "core/type.h"
-#include "core/virtmem.h"
-#include "core/zone.h"
-#include "core/zonehash.h"
-#include "core/zonelist.h"
-#include "core/zonetree.h"
-#include "core/zonestack.h"
-#include "core/zonestring.h"
-#include "core/zonevector.h"
-#include "asmjit-scope-end.h"
-
-#endif // ASMJIT_CORE_H_INCLUDED
diff --git a/src/asmjit/asmjit/core/api-build_p.h b/src/asmjit/asmjit/core/api-build_p.h
deleted file mode 100644
index 6eca971..0000000
--- a/src/asmjit/asmjit/core/api-build_p.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// This file is part of AsmJit project
-//
-// See asmjit.h or LICENSE.md for license and copyright information
-// SPDX-License-Identifier: Zlib
-
-#ifndef ASMJIT_CORE_API_BUILD_P_H_INCLUDED
-#define ASMJIT_CORE_API_BUILD_P_H_INCLUDED
-
-#define ASMJIT_EXPORTS
-
-// Only turn-off these warnings when building asmjit itself.
-#ifdef _MSC_VER
- #ifndef _CRT_SECURE_NO_DEPRECATE
- #define _CRT_SECURE_NO_DEPRECATE
- #endif
- #ifndef _CRT_SECURE_NO_WARNINGS
- #define _CRT_SECURE_NO_WARNINGS
- #endif
-#endif
-
-// Dependencies only required for asmjit build, but never exposed through public headers.
-#ifdef _WIN32
- #ifndef WIN32_LEAN_AND_MEAN
- #define WIN32_LEAN_AND_MEAN
- #endif
- #ifndef NOMINMAX
- #define NOMINMAX
- #endif
- #include
-#endif
-
-#include "./api-config.h"
-
-#if !defined(ASMJIT_BUILD_DEBUG) && defined(__GNUC__) && !defined(__clang__)
- #define ASMJIT_FAVOR_SIZE __attribute__((__optimize__("Os")))
- #define ASMJIT_FAVOR_SPEED __attribute__((__optimize__("O3")))
-#elif ASMJIT_CXX_HAS_ATTRIBUTE(__minsize__, 0)
- #define ASMJIT_FAVOR_SIZE __attribute__((__minsize__))
- #define ASMJIT_FAVOR_SPEED
-#else
- #define ASMJIT_FAVOR_SIZE
- #define ASMJIT_FAVOR_SPEED
-#endif
-
-// Make sure '#ifdef'ed unit tests are properly highlighted in IDE.
-#if !defined(ASMJIT_TEST) && defined(__INTELLISENSE__)
- #define ASMJIT_TEST
-#endif
-
-// Include a unit testing package if this is a `asmjit_test_unit` build.
-#if defined(ASMJIT_TEST)
- #include "../../../test/broken.h"
-#endif
-
-#endif // ASMJIT_CORE_API_BUILD_P_H_INCLUDED
diff --git a/src/asmjit/asmjit/core/api-config.h b/src/asmjit/asmjit/core/api-config.h
deleted file mode 100644
index 43ee2d9..0000000
--- a/src/asmjit/asmjit/core/api-config.h
+++ /dev/null
@@ -1,557 +0,0 @@
-// This file is part of AsmJit project
-//
-// See asmjit.h or LICENSE.md for license and copyright information
-// SPDX-License-Identifier: Zlib
-
-#ifndef ASMJIT_CORE_API_CONFIG_H_INCLUDED
-#define ASMJIT_CORE_API_CONFIG_H_INCLUDED
-
-// AsmJit Version
-// ==============
-
-//! \addtogroup asmjit_core
-//! \{
-
-//! AsmJit library version in `(Major << 16) | (Minor << 8) | (Patch)` format.
-#define ASMJIT_LIBRARY_VERSION 0x010600 /* 1.6.0 */
-
-//! \}
-
-// Global Dependencies
-// ===================
-
-#include
-#include
-#include // We really want std types as globals, not under 'std' namespace.
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-
-#if !defined(_WIN32) && !defined(__EMSCRIPTEN__)
- #include
-#endif
-
-// Build Options
-// =============
-
-// NOTE: Doxygen cannot document macros that are not defined, that's why we have to define them and then undefine
-// them immediately, so it won't use the macros with its own preprocessor.
-#ifdef _DOXYGEN
-namespace asmjit {
-
-//! \addtogroup asmjit_build
-//! \{
-
-//! Asmjit is embedded, implies \ref ASMJIT_STATIC.
-#define ASMJIT_EMBED
-
-//! Enables static-library build.
-#define ASMJIT_STATIC
-
-//! Defined when AsmJit's build configuration is 'Debug'.
-//!
-//! \note Can be defined explicitly to bypass autodetection.
-#define ASMJIT_BUILD_DEBUG
-
-//! Defined when AsmJit's build configuration is 'Release'.
-//!
-//! \note Can be defined explicitly to bypass autodetection.
-#define ASMJIT_BUILD_RELEASE
-
-//! Disables X86/X64 backends.
-#define ASMJIT_NO_X86
-
-//! Disables non-host backends entirely (useful for JIT compilers to minimize the library size).
-#define ASMJIT_NO_FOREIGN
-
-//! Disables deprecated API at compile time (deprecated API won't be available).
-#define ASMJIT_NO_DEPRECATED
-
-//! Disables \ref asmjit_builder functionality completely.
-#define ASMJIT_NO_BUILDER
-
-//! Disables \ref asmjit_compiler functionality completely.
-#define ASMJIT_NO_COMPILER
-
-//! Disables JIT memory management and \ref asmjit::JitRuntime.
-#define ASMJIT_NO_JIT
-
-//! Disables \ref asmjit::Logger and \ref asmjit::Formatter.
-#define ASMJIT_NO_LOGGING
-
-//! Disables everything that contains text.
-#define ASMJIT_NO_TEXT
-
-//! Disables instruction validation API.
-#define ASMJIT_NO_VALIDATION
-
-//! Disables instruction introspection API.
-#define ASMJIT_NO_INTROSPECTION
-
-// Avoid doxygen preprocessor using feature-selection definitions.
-#undef ASMJIT_BUILD_EMBNED
-#undef ASMJIT_BUILD_STATIC
-#undef ASMJIT_BUILD_DEBUG
-#undef ASMJIT_BUILD_RELEASE
-#undef ASMJIT_NO_X86
-#undef ASMJIT_NO_FOREIGN
-// (keep ASMJIT_NO_DEPRECATED defined, we don't document deprecated APIs).
-#undef ASMJIT_NO_BUILDER
-#undef ASMJIT_NO_COMPILER
-#undef ASMJIT_NO_JIT
-#undef ASMJIT_NO_LOGGING
-#undef ASMJIT_NO_TEXT
-#undef ASMJIT_NO_VALIDATION
-#undef ASMJIT_NO_INTROSPECTION
-
-//! \}
-
-} // {asmjit}
-#endif // _DOXYGEN
-
-// ASMJIT_NO_BUILDER implies ASMJIT_NO_COMPILER.
-#if defined(ASMJIT_NO_BUILDER) && !defined(ASMJIT_NO_COMPILER)
- #define ASMJIT_NO_COMPILER
-#endif
-
-// Prevent compile-time errors caused by misconfiguration.
-#if defined(ASMJIT_NO_TEXT) && !defined(ASMJIT_NO_LOGGING)
- #pragma message("'ASMJIT_NO_TEXT' can only be defined when 'ASMJIT_NO_LOGGING' is defined.")
- #undef ASMJIT_NO_TEXT
-#endif
-
-#if defined(ASMJIT_NO_INTROSPECTION) && !defined(ASMJIT_NO_COMPILER)
- #pragma message("'ASMJIT_NO_INTROSPECTION' can only be defined when 'ASMJIT_NO_COMPILER' is defined")
- #undef ASMJIT_NO_INTROSPECTION
-#endif
-
-// Build Mode
-// ==========
-
-// Detect ASMJIT_BUILD_DEBUG and ASMJIT_BUILD_RELEASE if not defined.
-#if !defined(ASMJIT_BUILD_DEBUG) && !defined(ASMJIT_BUILD_RELEASE)
- #if !defined(NDEBUG)
- #define ASMJIT_BUILD_DEBUG
- #else
- #define ASMJIT_BUILD_RELEASE
- #endif
-#endif
-
-// Target Architecture Detection
-// =============================
-
-#if defined(_M_X64) || defined(__x86_64__)
- #define ASMJIT_ARCH_X86 64
-#elif defined(_M_IX86) || defined(__X86__) || defined(__i386__)
- #define ASMJIT_ARCH_X86 32
-#else
- #define ASMJIT_ARCH_X86 0
-#endif
-
-#if defined(__arm64__) || defined(__aarch64__)
-# define ASMJIT_ARCH_ARM 64
-#elif defined(_M_ARM) || defined(_M_ARMT) || defined(__arm__) || defined(__thumb__) || defined(__thumb2__)
- #define ASMJIT_ARCH_ARM 32
-#else
- #define ASMJIT_ARCH_ARM 0
-#endif
-
-#if defined(_MIPS_ARCH_MIPS64) || defined(__mips64)
- #define ASMJIT_ARCH_MIPS 64
-#elif defined(_MIPS_ARCH_MIPS32) || defined(_M_MRX000) || defined(__mips__)
- #define ASMJIT_ARCH_MIPS 32
-#else
- #define ASMJIT_ARCH_MIPS 0
-#endif
-
-#define ASMJIT_ARCH_BITS (ASMJIT_ARCH_X86 | ASMJIT_ARCH_ARM | ASMJIT_ARCH_MIPS)
-#if ASMJIT_ARCH_BITS == 0
- #undef ASMJIT_ARCH_BITS
- #if defined (__LP64__) || defined(_LP64)
- #define ASMJIT_ARCH_BITS 64
- #else
- #define ASMJIT_ARCH_BITS 32
- #endif
-#endif
-
-#if (defined(__ARMEB__)) || \
- (defined(__MIPSEB__)) || \
- (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
- #define ASMJIT_ARCH_LE 0
- #define ASMJIT_ARCH_BE 1
-#else
- #define ASMJIT_ARCH_LE 1
- #define ASMJIT_ARCH_BE 0
-#endif
-
-#if defined(ASMJIT_NO_FOREIGN)
- #if !ASMJIT_ARCH_X86 && !defined(ASMJIT_NO_X86)
- #define ASMJIT_NO_X86
- #endif
-#endif
-
-
-// C++ Compiler and Features Detection
-// ===================================
-
-#define ASMJIT_CXX_GNU 0
-#define ASMJIT_CXX_MAKE_VER(MAJOR, MINOR) ((MAJOR) * 1000 + (MINOR))
-
-// Intel Compiler [pretends to be GNU or MSC, so it must be checked first]:
-// - https://software.intel.com/en-us/articles/c0x-features-supported-by-intel-c-compiler
-// - https://software.intel.com/en-us/articles/c14-features-supported-by-intel-c-compiler
-// - https://software.intel.com/en-us/articles/c17-features-supported-by-intel-c-compiler
-#if defined(__INTEL_COMPILER)
-
-// MSC Compiler:
-// - https://msdn.microsoft.com/en-us/library/hh567368.aspx
-//
-// Version List:
-// - 16.00.0 == VS2010
-// - 17.00.0 == VS2012
-// - 18.00.0 == VS2013
-// - 19.00.0 == VS2015
-// - 19.10.0 == VS2017
-#elif defined(_MSC_VER) && defined(_MSC_FULL_VER)
-
-// Clang Compiler [Pretends to be GNU, so it must be checked before]:
-// - https://clang.llvm.org/cxx_status.html
-#elif defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__)
-
-// GNU Compiler:
-// - https://gcc.gnu.org/projects/cxx-status.html
-#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
-
- #undef ASMJIT_CXX_GNU
- #define ASMJIT_CXX_GNU ASMJIT_CXX_MAKE_VER(__GNUC__, __GNUC_MINOR__)
-
-#endif
-
-// Compiler features detection macros.
-#if defined(__clang__) && defined(__has_attribute)
- #define ASMJIT_CXX_HAS_ATTRIBUTE(NAME, CHECK) (__has_attribute(NAME))
-#else
- #define ASMJIT_CXX_HAS_ATTRIBUTE(NAME, CHECK) (!(!(CHECK)))
-#endif
-
-// API Decorators & C++ Extensions
-// ===============================
-
-//! \def ASMJIT_API
-//!
-//! A decorator that is used to decorate API that AsmJit exports when built as a shared library.
-
-// API (Export / Import).
-#if !defined(ASMJIT_STATIC)
- #if defined(_WIN32) && (defined(_MSC_VER) || defined(__MINGW32__))
- #ifdef ASMJIT_EXPORTS
- #define ASMJIT_API __declspec(dllexport)
- #else
- #define ASMJIT_API __declspec(dllimport)
- #endif
- #elif defined(_WIN32) && defined(__GNUC__)
- #ifdef ASMJIT_EXPORTS
- #define ASMJIT_API __attribute__((__dllexport__))
- #else
- #define ASMJIT_API __attribute__((__dllimport__))
- #endif
- #elif defined(__GNUC__)
- #define ASMJIT_API __attribute__((__visibility__("default")))
- #endif
-#endif
-
-#if !defined(ASMJIT_API)
- #define ASMJIT_API
-#endif
-
-#if !defined(ASMJIT_VARAPI)
- #define ASMJIT_VARAPI extern ASMJIT_API
-#endif
-
-//! \def ASMJIT_VIRTAPI
-//!
-//! This is basically a workaround. When using MSVC and marking class as DLL export everything gets exported, which
-//! is unwanted in most projects. MSVC automatically exports typeinfo and vtable if at least one symbol of the class
-//! is exported. However, GCC has some strange behavior that even if one or more symbol is exported it doesn't export
-//! typeinfo unless the class itself is decorated with "visibility(default)" (i.e. ASMJIT_API).
-#if !defined(_WIN32) && defined(__GNUC__)
- #define ASMJIT_VIRTAPI ASMJIT_API
-#else
- #define ASMJIT_VIRTAPI
-#endif
-
-// Function attributes.
-#if !defined(ASMJIT_BUILD_DEBUG) && defined(__GNUC__)
- #define ASMJIT_FORCE_INLINE inline __attribute__((__always_inline__))
-#elif !defined(ASMJIT_BUILD_DEBUG) && defined(_MSC_VER)
- #define ASMJIT_FORCE_INLINE __forceinline
-#else
- #define ASMJIT_FORCE_INLINE inline
-#endif
-
-#if defined(__GNUC__)
- #define ASMJIT_NOINLINE __attribute__((__noinline__))
- #define ASMJIT_NORETURN __attribute__((__noreturn__))
-#elif defined(_MSC_VER)
- #define ASMJIT_NOINLINE __declspec(noinline)
- #define ASMJIT_NORETURN __declspec(noreturn)
-#else
- #define ASMJIT_NOINLINE
- #define ASMJIT_NORETURN
-#endif
-
-// Calling conventions.
-#if ASMJIT_ARCH_X86 == 32 && defined(__GNUC__)
- #define ASMJIT_CDECL __attribute__((__cdecl__))
- #define ASMJIT_STDCALL __attribute__((__stdcall__))
- #define ASMJIT_FASTCALL __attribute__((__fastcall__))
- #define ASMJIT_REGPARM(N) __attribute__((__regparm__(N)))
-#elif ASMJIT_ARCH_X86 == 32 && defined(_MSC_VER)
- #define ASMJIT_CDECL __cdecl
- #define ASMJIT_STDCALL __stdcall
- #define ASMJIT_FASTCALL __fastcall
- #define ASMJIT_REGPARM(N)
-#else
- #define ASMJIT_CDECL
- #define ASMJIT_STDCALL
- #define ASMJIT_FASTCALL
- #define ASMJIT_REGPARM(N)
-#endif
-
-#if ASMJIT_ARCH_X86 && defined(_WIN32) && defined(_MSC_VER)
- #define ASMJIT_VECTORCALL __vectorcall
-#elif ASMJIT_ARCH_X86 && defined(_WIN32)
- #define ASMJIT_VECTORCALL __attribute__((__vectorcall__))
-#else
- #define ASMJIT_VECTORCALL
-#endif
-
-
-// Type alignment (not allowed by C++11 'alignas' keyword).
-#if defined(__GNUC__)
- #define ASMJIT_ALIGN_TYPE(TYPE, N) __attribute__((__aligned__(N))) TYPE
-#elif defined(_MSC_VER)
- #define ASMJIT_ALIGN_TYPE(TYPE, N) __declspec(align(N)) TYPE
-#else
- #define ASMJIT_ALIGN_TYPE(TYPE, N) TYPE
-#endif
-
-//! \def ASMJIT_MAY_ALIAS
-//!
-//! Expands to `__attribute__((__may_alias__))` if supported.
-#if defined(__GNUC__)
- #define ASMJIT_MAY_ALIAS __attribute__((__may_alias__))
-#else
- #define ASMJIT_MAY_ALIAS
-#endif
-
-//! \def ASMJIT_MAYBE_UNUSED
-//!
-//! Expands to `[[maybe_unused]]` if supported or a compiler attribute instead.
-#if __cplusplus >= 201703L
- #define ASMJIT_MAYBE_UNUSED [[maybe_unused]]
-#elif defined(__GNUC__)
- #define ASMJIT_MAYBE_UNUSED __attribute__((unused))
-#else
- #define ASMJIT_MAYBE_UNUSED
-#endif
-
-//! \def ASMJIT_LIKELY(...)
-//!
-//! Condition is likely to be taken (mostly error handling and edge cases).
-
-//! \def ASMJIT_UNLIKELY(...)
-//!
-//! Condition is unlikely to be taken (mostly error handling and edge cases).
-#if defined(__GNUC__)
- #define ASMJIT_LIKELY(...) __builtin_expect(!!(__VA_ARGS__), 1)
- #define ASMJIT_UNLIKELY(...) __builtin_expect(!!(__VA_ARGS__), 0)
-#else
- #define ASMJIT_LIKELY(...) (__VA_ARGS__)
- #define ASMJIT_UNLIKELY(...) (__VA_ARGS__)
-#endif
-
-//! \def ASMJIT_FALLTHROUGH
-//!
-//! Portable [[fallthrough]] attribute.
-#if defined(__clang__) && __cplusplus >= 201103L
- #define ASMJIT_FALLTHROUGH [[clang::fallthrough]]
-#elif defined(__GNUC__) && __GNUC__ >= 7
- #define ASMJIT_FALLTHROUGH __attribute__((__fallthrough__))
-#else
- #define ASMJIT_FALLTHROUGH ((void)0) /* fallthrough */
-#endif
-
-//! \def ASMJIT_DEPRECATED
-//!
-//! Marks function, class, struct, enum, or anything else as deprecated.
-#if defined(__GNUC__)
- #define ASMJIT_DEPRECATED(MESSAGE) __attribute__((__deprecated__(MESSAGE)))
- #if defined(__clang__)
- #define ASMJIT_DEPRECATED_STRUCT(MESSAGE) __attribute__((__deprecated__(MESSAGE)))
- #else
- #define ASMJIT_DEPRECATED_STRUCT(MESSAGE) /* not usable if a deprecated function uses it */
- #endif
-#elif defined(_MSC_VER)
- #define ASMJIT_DEPRECATED(MESSAGE) __declspec(deprecated(MESSAGE))
- #define ASMJIT_DEPRECATED_STRUCT(MESSAGE) /* not usable if a deprecated function uses it */
-#else
- #define ASMJIT_DEPRECATED(MESSAGE)
- #define ASMJIT_DEPRECATED_STRUCT(MESSAGE)
-#endif
-
-// Utilities.
-#define ASMJIT_OFFSET_OF(STRUCT, MEMBER) ((int)(intptr_t)((const char*)&((const STRUCT*)0x100)->MEMBER) - 0x100)
-#define ASMJIT_ARRAY_SIZE(X) uint32_t(sizeof(X) / sizeof(X[0]))
-
-#if ASMJIT_CXX_HAS_ATTRIBUTE(no_sanitize, 0)
- #define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF __attribute__((__no_sanitize__("undefined")))
-#elif ASMJIT_CXX_GNU >= ASMJIT_CXX_MAKE_VER(4, 9)
- #define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF __attribute__((__no_sanitize_undefined__))
-#else
- #define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF
-#endif
-
-// Begin-Namespace & End-Namespace Macros
-// ======================================
-
-#if defined(__clang__)
- #define ASMJIT_BEGIN_NAMESPACE \
- namespace asmjit { \
- _Pragma("clang diagnostic push") \
- _Pragma("clang diagnostic ignored \"-Wconstant-logical-operand\"") \
- _Pragma("clang diagnostic ignored \"-Wunnamed-type-template-args\"")
- #define ASMJIT_END_NAMESPACE \
- _Pragma("clang diagnostic pop") \
- }
-#elif defined(__GNUC__) && __GNUC__ == 4
- #define ASMJIT_BEGIN_NAMESPACE \
- namespace asmjit { \
- _Pragma("GCC diagnostic push") \
- _Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"")
- #define ASMJIT_END_NAMESPACE \
- _Pragma("GCC diagnostic pop") \
- }
-#elif defined(__GNUC__) && __GNUC__ >= 8
- #define ASMJIT_BEGIN_NAMESPACE \
- namespace asmjit { \
- _Pragma("GCC diagnostic push") \
- _Pragma("GCC diagnostic ignored \"-Wclass-memaccess\"")
- #define ASMJIT_END_NAMESPACE \
- _Pragma("GCC diagnostic pop") \
- }
-#elif defined(_MSC_VER) && !defined(__INTEL_COMPILER)
- #define ASMJIT_BEGIN_NAMESPACE \
- namespace asmjit { \
- __pragma(warning(push)) \
- __pragma(warning(disable: 4127)) /* conditional expression is const */ \
- __pragma(warning(disable: 4201)) /* nameless struct/union */
- #define ASMJIT_END_NAMESPACE \
- __pragma(warning(pop)) \
- }
-#endif
-
-#if !defined(ASMJIT_BEGIN_NAMESPACE) && !defined(ASMJIT_END_NAMESPACE)
- #define ASMJIT_BEGIN_NAMESPACE namespace asmjit {
- #define ASMJIT_END_NAMESPACE }
-#endif
-
-#define ASMJIT_BEGIN_SUB_NAMESPACE(NAMESPACE) \
- ASMJIT_BEGIN_NAMESPACE \
- namespace NAMESPACE {
-
-#define ASMJIT_END_SUB_NAMESPACE \
- } \
- ASMJIT_END_NAMESPACE
-
-// C++ Utilities
-// =============
-
-#define ASMJIT_NONCOPYABLE(...) \
- private: \
- __VA_ARGS__(const __VA_ARGS__& other) = delete; \
- __VA_ARGS__& operator=(const __VA_ARGS__& other) = delete; \
- public:
-
-#define ASMJIT_NONCONSTRUCTIBLE(...) \
- private: \
- __VA_ARGS__() = delete; \
- __VA_ARGS__(const __VA_ARGS__& other) = delete; \
- __VA_ARGS__& operator=(const __VA_ARGS__& other) = delete; \
- public:
-
-//! \def ASMJIT_DEFINE_ENUM_FLAGS(T)
-//!
-//! Defines bit operations for enumeration flags.
-#ifdef _DOXYGEN
- #define ASMJIT_DEFINE_ENUM_FLAGS(T)
-#else
- #define ASMJIT_DEFINE_ENUM_FLAGS(T) \
- static ASMJIT_FORCE_INLINE constexpr T operator~(T a) noexcept { \
- return T(~(std::underlying_type::type)(a)); \
- } \
- \
- static ASMJIT_FORCE_INLINE constexpr T operator|(T a, T b) noexcept { \
- return T((std::underlying_type::type)(a) | \
- (std::underlying_type::type)(b)); \
- } \
- static ASMJIT_FORCE_INLINE constexpr T operator&(T a, T b) noexcept { \
- return T((std::underlying_type::type)(a) & \
- (std::underlying_type::type)(b)); \
- } \
- static ASMJIT_FORCE_INLINE constexpr T operator^(T a, T b) noexcept { \
- return T((std::underlying_type::type)(a) ^ \
- (std::underlying_type::type)(b)); \
- } \
- \
- static ASMJIT_FORCE_INLINE T& operator|=(T& a, T b) noexcept { \
- a = T((std::underlying_type::type)(a) | \
- (std::underlying_type::type)(b)); \
- return a; \
- } \
- static ASMJIT_FORCE_INLINE T& operator&=(T& a, T b) noexcept { \
- a = T((std::underlying_type::type)(a) & \
- (std::underlying_type::type)(b)); \
- return a; \
- } \
- static ASMJIT_FORCE_INLINE T& operator^=(T& a, T b) noexcept { \
- a = T((std::underlying_type::type)(a) ^ \
- (std::underlying_type::type)(b)); \
- return a; \
- }
-#endif
-
-//! \def ASMJIT_DEFINE_ENUM_COMPARE(T)
-//!
-//! Defines comparison operations for enumeration flags.
-#ifdef _DOXYGEN
- #define ASMJIT_DEFINE_ENUM_COMPARE(T)
-#else
- #define ASMJIT_DEFINE_ENUM_COMPARE(T) \
- static ASMJIT_FORCE_INLINE bool operator<(T a, T b) noexcept { \
- return (std::underlying_type::type)(a) < (std::underlying_type::type)(b); \
- } \
- static ASMJIT_FORCE_INLINE bool operator<=(T a, T b) noexcept { \
- return (std::underlying_type::type)(a) <= (std::underlying_type::type)(b); \
- } \
- static ASMJIT_FORCE_INLINE bool operator>(T a, T b) noexcept { \
- return (std::underlying_type::type)(a) > (std::underlying_type::type)(b); \
- } \
- static ASMJIT_FORCE_INLINE bool operator>=(T a, T b) noexcept { \
- return (std::underlying_type::type)(a) >= (std::underlying_type::type)(b); \
- }
-#endif
-
-// Cleanup Api-Config Specific Macros
-// ==================================
-
-#undef ASMJIT_CXX_GNU
-#undef ASMJIT_CXX_MAKE_VER
-
-#endif // ASMJIT_CORE_API_CONFIG_H_INCLUDED
diff --git a/src/asmjit/asmjit/core/archcommons.h b/src/asmjit/asmjit/core/archcommons.h
deleted file mode 100644
index 88b6069..0000000
--- a/src/asmjit/asmjit/core/archcommons.h
+++ /dev/null
@@ -1,140 +0,0 @@
-// This file is part of AsmJit project
-//
-// See asmjit.h or LICENSE.md for license and copyright information
-// SPDX-License-Identifier: Zlib
-
-#ifndef ASMJIT_CORE_ARCHCOMMONS_H_INCLUDED
-#define ASMJIT_CORE_ARCHCOMMONS_H_INCLUDED
-
-// This file provides architecture-specific classes that are required in the core library. For example Imm operand
-// allows to be created from arm::Shift in a const-expr way, so the arm::Shift must be provided. So this header file
-// provides everything architecture-specific that is used by the Core API.
-
-#include "../core/globals.h"
-
-ASMJIT_BEGIN_SUB_NAMESPACE(arm)
-
-//! \addtogroup asmjit_arm
-//! \{
-
-//! Shift operation predicate (ARM) describes either SHIFT or EXTEND operation.
-//!
-//! \note The constants are AsmJit specific. The first 5 values describe real constants on ARM32 and AArch64 hardware,
-//! however, the addition constants that describe extend modes are specific to AsmJit and would be translated to the
-//! AArch64 specific constants by the assembler.
-enum class ShiftOp {
- //! Shift left logical operation (default).
- //!
- //! Available to all ARM architectures.
- kLSL = 0x00u,
-
- //! Shift right logical operation.
- //!
- //! Available to all ARM architectures.
- kLSR = 0x01u,
-
- //! Shift right arithmetic operation.
- //!
- //! Available to all ARM architectures.
- kASR = 0x02u,
-
- //! Rotate right operation.
- //!
- //! \note Not available in AArch64 mode.
- kROR = 0x03u,
-
- //! Rotate right with carry operation (encoded as `kShiftROR` with zero).
- //!
- //! \note Not available in AArch64 mode.
- kRRX = 0x04u,
-
- //! Shift left by filling low order bits with ones.
- kMSL = 0x05u,
-
- //! UXTN extend register operation (AArch64 only).
- kUXTB = 0x06u,
- //! UXTH extend register operation (AArch64 only).
- kUXTH = 0x07u,
- //! UXTW extend register operation (AArch64 only).
- kUXTW = 0x08u,
- //! UXTX extend register operation (AArch64 only).
- kUXTX = 0x09u,
-
- //! SXTB extend register operation (AArch64 only).
- kSXTB = 0x0Au,
- //! SXTH extend register operation (AArch64 only).
- kSXTH = 0x0Bu,
- //! SXTW extend register operation (AArch64 only).
- kSXTW = 0x0Cu,
- //! SXTX extend register operation (AArch64 only).
- kSXTX = 0x0Du
-
- // NOTE: 0xE and 0xF are used by memory operand to specify POST|PRE offset mode.
-};
-
-//! Represents ARM immediate shift operation type and value.
-class Shift {
-public:
- //! Shift operation.
- ShiftOp _op;
- //! Shift Value.
- uint32_t _value;
-
- //! Default constructed Shift is not initialized.
- inline Shift() noexcept = default;
-
- //! Copy constructor (default)
- constexpr Shift(const Shift& other) noexcept = default;
-
- //! Constructs Shift from operation `op` and shift `value`.
- constexpr Shift(ShiftOp op, uint32_t value) noexcept
- : _op(op),
- _value(value) {}
-
- //! Returns the shift operation.
- constexpr ShiftOp op() const noexcept { return _op; }
- //! Sets shift operation to `op`.
- inline void setOp(ShiftOp op) noexcept { _op = op; }
-
- //! Returns the shift smount.
- constexpr uint32_t value() const noexcept { return _value; }
- //! Sets shift amount to `value`.
- inline void setValue(uint32_t value) noexcept { _value = value; }
-};
-
-//! Constructs a `LSL #value` shift (logical shift left).
-static constexpr Shift lsl(uint32_t value) noexcept { return Shift(ShiftOp::kLSL, value); }
-//! Constructs a `LSR #value` shift (logical shift right).
-static constexpr Shift lsr(uint32_t value) noexcept { return Shift(ShiftOp::kLSR, value); }
-//! Constructs a `ASR #value` shift (arithmetic shift right).
-static constexpr Shift asr(uint32_t value) noexcept { return Shift(ShiftOp::kASR, value); }
-//! Constructs a `ROR #value` shift (rotate right).
-static constexpr Shift ror(uint32_t value) noexcept { return Shift(ShiftOp::kROR, value); }
-//! Constructs a `RRX` shift (rotate with carry by 1).
-static constexpr Shift rrx() noexcept { return Shift(ShiftOp::kRRX, 0); }
-//! Constructs a `MSL #value` shift (logical shift left filling ones).
-static constexpr Shift msl(uint32_t value) noexcept { return Shift(ShiftOp::kMSL, value); }
-
-//! Constructs a `UXTB #value` extend and shift (unsigned byte extend).
-static constexpr Shift uxtb(uint32_t value) noexcept { return Shift(ShiftOp::kUXTB, value); }
-//! Constructs a `UXTH #value` extend and shift (unsigned hword extend).
-static constexpr Shift uxth(uint32_t value) noexcept { return Shift(ShiftOp::kUXTH, value); }
-//! Constructs a `UXTW #value` extend and shift (unsigned word extend).
-static constexpr Shift uxtw(uint32_t value) noexcept { return Shift(ShiftOp::kUXTW, value); }
-//! Constructs a `UXTX #value` extend and shift (unsigned dword extend).
-static constexpr Shift uxtx(uint32_t value) noexcept { return Shift(ShiftOp::kUXTX, value); }
-
-//! Constructs a `SXTB #value` extend and shift (signed byte extend).
-static constexpr Shift sxtb(uint32_t value) noexcept { return Shift(ShiftOp::kSXTB, value); }
-//! Constructs a `SXTH #value` extend and shift (signed hword extend).
-static constexpr Shift sxth(uint32_t value) noexcept { return Shift(ShiftOp::kSXTH, value); }
-//! Constructs a `SXTW #value` extend and shift (signed word extend).
-static constexpr Shift sxtw(uint32_t value) noexcept { return Shift(ShiftOp::kSXTW, value); }
-//! Constructs a `SXTX #value` extend and shift (signed dword extend).
-static constexpr Shift sxtx(uint32_t value) noexcept { return Shift(ShiftOp::kSXTX, value); }
-
-//! \}
-
-ASMJIT_END_SUB_NAMESPACE
-
-#endif // ASMJIT_CORE_ARCHCOMMONS_H_INCLUDED
diff --git a/src/asmjit/asmjit/core/archtraits.cpp b/src/asmjit/asmjit/core/archtraits.cpp
deleted file mode 100644
index 8b79ee2..0000000
--- a/src/asmjit/asmjit/core/archtraits.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
-// This file is part of AsmJit project
-//
-// See asmjit.h or LICENSE.md for license and copyright information
-// SPDX-License-Identifier: Zlib
-
-#include "../core/api-build_p.h"
-#include "../core/archtraits.h"
-#include "../core/misc_p.h"
-
-#if !defined(ASMJIT_NO_X86)
- #include "../x86/x86archtraits_p.h"
-#endif
-
-#ifdef ASMJIT_BUILD_ARM
- #include "../arm/armarchtraits_p.h"
-#endif
-
-ASMJIT_BEGIN_NAMESPACE
-
-static const constexpr ArchTraits noArchTraits = {
- // SP/FP/LR/PC.
- 0xFF, 0xFF, 0xFF, 0xFF,
-
- // Reserved,
- { 0, 0, 0 },
-
- // HW stack alignment.
- 0,
-
- // Min/Max stack offset.
- 0, 0,
-
- // ISA features [Gp, Vec, Other0, Other1].
- {{
- InstHints::kNoHints,
- InstHints::kNoHints,
- InstHints::kNoHints,
- InstHints::kNoHints
- }},
-
- // RegTypeToSignature.
- #define V(index) { OperandSignature(0) }
- {{ ASMJIT_LOOKUP_TABLE_32(V, 0) }},
- #undef V
-
- // RegTypeToTypeId.
- #define V(index) TypeId::kVoid
- {{ ASMJIT_LOOKUP_TABLE_32(V, 0) }},
- #undef V
-
- // TypeIdToRegType.
- #define V(index) RegType::kNone
- {{ ASMJIT_LOOKUP_TABLE_32(V, 0) }},
- #undef V
-
- // Word names of 8-bit, 16-bit, 32-bit, and 64-bit quantities.
- {
- ArchTypeNameId::kByte,
- ArchTypeNameId::kHalf,
- ArchTypeNameId::kWord,
- ArchTypeNameId::kQuad
- }
-};
-
-ASMJIT_VARAPI const ArchTraits _archTraits[uint32_t(Arch::kMaxValue) + 1] = {
- // No architecture.
- noArchTraits,
-
- // X86/X86 architectures.
-#if !defined(ASMJIT_NO_X86)
- x86::x86ArchTraits,
- x86::x64ArchTraits,
-#else
- noArchTraits,
- noArchTraits,
-#endif
-
- // RISCV32/RISCV64 architectures.
- noArchTraits,
- noArchTraits,
-
- // ARM architecture
- noArchTraits,
-
- // AArch64 architecture.
-#ifdef ASMJIT_BUILD_ARM
- arm::a64ArchTraits,
-#else
- noArchTraits,
-#endif
-
- // ARM/Thumb architecture.
- noArchTraits,
-
- // Reserved.
- noArchTraits,
-
- // MIPS32/MIPS64
- noArchTraits,
- noArchTraits
-};
-
-ASMJIT_FAVOR_SIZE Error ArchUtils::typeIdToRegSignature(Arch arch, TypeId typeId, TypeId* typeIdOut, OperandSignature* regSignatureOut) noexcept {
- const ArchTraits& archTraits = ArchTraits::byArch(arch);
-
- // TODO: Remove this, should never be used like this.
- // Passed RegType instead of TypeId?
- if (uint32_t(typeId) <= uint32_t(RegType::kMaxValue))
- typeId = archTraits.regTypeToTypeId(RegType(uint32_t(typeId)));
-
- if (ASMJIT_UNLIKELY(!TypeUtils::isValid(typeId)))
- return DebugUtils::errored(kErrorInvalidTypeId);
-
- // First normalize architecture dependent types.
- if (TypeUtils::isAbstract(typeId)) {
- bool is32Bit = Environment::is32Bit(arch);
- if (typeId == TypeId::kIntPtr)
- typeId = is32Bit ? TypeId::kInt32 : TypeId::kInt64;
- else
- typeId = is32Bit ? TypeId::kUInt32 : TypeId::kUInt64;
- }
-
- // Type size helps to construct all groups of registers.
- // TypeId is invalid if the size is zero.
- uint32_t size = TypeUtils::sizeOf(typeId);
- if (ASMJIT_UNLIKELY(!size))
- return DebugUtils::errored(kErrorInvalidTypeId);
-
- if (ASMJIT_UNLIKELY(typeId == TypeId::kFloat80))
- return DebugUtils::errored(kErrorInvalidUseOfF80);
-
- RegType regType = RegType::kNone;
- if (TypeUtils::isBetween(typeId, TypeId::_kBaseStart, TypeId::_kVec32Start)) {
- regType = archTraits._typeIdToRegType[uint32_t(typeId) - uint32_t(TypeId::_kBaseStart)];
- if (regType == RegType::kNone) {
- if (typeId == TypeId::kInt64 || typeId == TypeId::kUInt64)
- return DebugUtils::errored(kErrorInvalidUseOfGpq);
- else
- return DebugUtils::errored(kErrorInvalidTypeId);
- }
- }
- else {
- if (size <= 8 && archTraits._regSignature[RegType::kVec64].isValid())
- regType = RegType::kVec64;
- else if (size <= 16 && archTraits._regSignature[RegType::kVec128].isValid())
- regType = RegType::kVec128;
- else if (size == 32 && archTraits._regSignature[RegType::kVec256].isValid())
- regType = RegType::kVec256;
- else if (archTraits._regSignature[RegType::kVec512].isValid())
- regType = RegType::kVec512;
- else
- return DebugUtils::errored(kErrorInvalidTypeId);
- }
-
- *typeIdOut = typeId;
- *regSignatureOut = archTraits.regTypeToSignature(regType);
- return kErrorOk;
-}
-
-ASMJIT_END_NAMESPACE
diff --git a/src/asmjit/asmjit/core/archtraits.h b/src/asmjit/asmjit/core/archtraits.h
deleted file mode 100644
index 4d05c11..0000000
--- a/src/asmjit/asmjit/core/archtraits.h
+++ /dev/null
@@ -1,290 +0,0 @@
-// This file is part of AsmJit project
-//
-// See asmjit.h or LICENSE.md for license and copyright information
-// SPDX-License-Identifier: Zlib
-
-#ifndef ASMJIT_CORE_ARCHTRAITS_H_INCLUDED
-#define ASMJIT_CORE_ARCHTRAITS_H_INCLUDED
-
-#include "../core/operand.h"
-#include "../core/support.h"
-#include "../core/type.h"
-
-ASMJIT_BEGIN_NAMESPACE
-
-//! \addtogroup asmjit_core
-//! \{
-
-//! Instruction set architecture (ISA).
-enum class Arch : uint8_t {
- //! Unknown or uninitialized ISA.
- kUnknown = 0,
-
- //! 32-bit X86 ISA.
- kX86 = 1,
- //! 64-bit X86 ISA also known as X64, X86_64, and AMD64.
- kX64 = 2,
-
- //! 32-bit RISC-V ISA.
- kRISCV32 = 3,
- //! 64-bit RISC-V ISA.
- kRISCV64 = 4,
-
- //! 32-bit ARM ISA (little endian).
- kARM = 5,
- //! 64-bit ARM ISA in (little endian).
- kAArch64 = 6,
- //! 32-bit ARM ISA in Thumb mode (little endian).
- kThumb = 7,
-
- // 8 is not used at the moment, even numbers are 64-bit architectures.
-
- //! 32-bit MIPS ISA in (little endian).
- kMIPS32_LE = 9,
- //! 64-bit MIPS ISA in (little endian).
- kMIPS64_LE = 10,
-
- //! 32-bit ARM ISA (big endian).
- kARM_BE = 11,
- //! 64-bit ARM ISA in (big endian).
- kAArch64_BE = 12,
- //! 32-bit ARM ISA in Thumb mode (big endian).
- kThumb_BE = 13,
-
- // 14 is not used at the moment, even numbers are 64-bit architectures.
-
- //! 32-bit MIPS ISA in (big endian).
- kMIPS32_BE = 15,
- //! 64-bit MIPS ISA in (big endian).
- kMIPS64_BE = 16,
-
- //! Maximum value of `Arch`.
- kMaxValue = kMIPS64_BE,
-
- //! Mask used by 32-bit ISAs (odd are 32-bit, even are 64-bit).
- k32BitMask = 0x01,
- //! First big-endian architecture.
- kBigEndian = kARM_BE,
-
- //! ISA detected at compile-time (ISA of the host).
- kHost =
-#if defined(_DOXYGEN)
- DETECTED_AT_COMPILE_TIME
-#else
- ASMJIT_ARCH_X86 == 32 ? kX86 :
- ASMJIT_ARCH_X86 == 64 ? kX64 :
-
- ASMJIT_ARCH_ARM == 32 && ASMJIT_ARCH_LE ? kARM :
- ASMJIT_ARCH_ARM == 32 && ASMJIT_ARCH_BE ? kARM_BE :
- ASMJIT_ARCH_ARM == 64 && ASMJIT_ARCH_LE ? kAArch64 :
- ASMJIT_ARCH_ARM == 64 && ASMJIT_ARCH_BE ? kAArch64_BE :
-
- ASMJIT_ARCH_MIPS == 32 && ASMJIT_ARCH_LE ? kMIPS32_LE :
- ASMJIT_ARCH_MIPS == 32 && ASMJIT_ARCH_BE ? kMIPS32_BE :
- ASMJIT_ARCH_MIPS == 64 && ASMJIT_ARCH_LE ? kMIPS64_LE :
- ASMJIT_ARCH_MIPS == 64 && ASMJIT_ARCH_BE ? kMIPS64_BE :
-
- kUnknown
-#endif
-};
-
-//! Sub-architecture.
-enum class SubArch : uint8_t {
- //! Unknown or uninitialized architecture sub-type.
- kUnknown = 0,
-
- //! Maximum value of `SubArch`.
- kMaxValue = kUnknown,
-
- //! Sub-architecture detected at compile-time (sub-architecture of the host).
- kHost =
-#if defined(_DOXYGEN)
- DETECTED_AT_COMPILE_TIME
-#else
- kUnknown
-#endif
-};
-
-//! Identifier used to represent names of different data types across architectures.
-enum class ArchTypeNameId : uint8_t {
- //! Describes 'db' (X86/X86_64 convention, always 8-bit quantity).
- kDB = 0,
- //! Describes 'dw' (X86/X86_64 convention, always 16-bit word).
- kDW,
- //! Describes 'dd' (X86/X86_64 convention, always 32-bit word).
- kDD,
- //! Describes 'dq' (X86/X86_64 convention, always 64-bit word).
- kDQ,
- //! Describes 'byte' (always 8-bit quantity).
- kByte,
- //! Describes 'half' (most likely 16-bit word).
- kHalf,
- //! Describes 'word' (either 16-bit or 32-bit word).
- kWord,
- //! Describes 'hword' (most likely 16-bit word).
- kHWord,
- //! Describes 'dword' (either 32-bit or 64-bit word).
- kDWord,
- //! Describes 'qword' (64-bit word).
- kQWord,
- //! Describes 'xword' (64-bit word).
- kXWord,
- //! Describes 'short' (always 16-bit word).
- kShort,
- //! Describes 'long' (most likely 32-bit word).
- kLong,
- //! Describes 'quad' (64-bit word).
- kQuad,
-
- //! Maximum value of `ArchTypeNameId`.
- kMaxValue = kQuad
-};
-
-//! Instruction feature hints for each register group provided by \ref ArchTraits.
-//!
-//! Instruction feature hints describe miscellaneous instructions provided by the architecture that can be used by
-//! register allocator to make certain things simpler - like register swaps or emitting register push/pop sequences.
-//!
-//! \remarks Instruction feature hints are only defined for register groups that can be used with \ref
-//! asmjit_compiler infrastructure. Register groups that are not managed by Compiler are not provided by
-//! \ref ArchTraits and cannot be queried.
-enum class InstHints : uint8_t {
- //! No feature hints.
- kNoHints = 0,
-
- //! Architecture supports a register swap by using a single instructio.
- kRegSwap = 0x01u,
- //! Architecture provides push/pop instructions.
- kPushPop = 0x02u
-};
-ASMJIT_DEFINE_ENUM_FLAGS(InstHints)
-
-//! Architecture traits used by Function API and Compiler's register allocator.
-struct ArchTraits {
- //! \name Members
- //! \{
-
- //! Stack pointer register id.
- uint8_t _spRegId;
- //! Frame pointer register id.
- uint8_t _fpRegId;
- //! Link register id.
- uint8_t _linkRegId;
- //! Instruction pointer (or program counter) register id, if accessible.
- uint8_t _ipRegId;
-
- // Reserved.
- uint8_t _reserved[3];
- //! Hardware stack alignment requirement.
- uint8_t _hwStackAlignment;
-
- //! Minimum addressable offset on stack guaranteed for all instructions.
- uint32_t _minStackOffset;
- //! Maximum addressable offset on stack depending on specific instruction.
- uint32_t _maxStackOffset;
-
- //! Flags for each virtual register group.
- Support::Array _instHints;
-
- //! Maps register type into a signature, that provides group, size and can be used to construct register operands.
- Support::Array _regSignature;
- //! Maps a register to type-id, see \ref TypeId.
- Support::Array _regTypeToTypeId;
- //! Maps scalar TypeId values (from TypeId::_kIdBaseStart) to register types, see \ref TypeId.
- Support::Array _typeIdToRegType;
-
- //! Word name identifiers of 8-bit, 16-bit, 32-biit, and 64-bit quantities that appear in formatted text.
- ArchTypeNameId _typeNameIdTable[4];
-
- //! \}
-
- //! \name Accessors
- //! \{
-
- //! Returns stack pointer register id.
- inline uint32_t spRegId() const noexcept { return _spRegId; }
- //! Returns stack frame register id.
- inline uint32_t fpRegId() const noexcept { return _fpRegId; }
- //! Returns link register id, if the architecture provides it.
- inline uint32_t linkRegId() const noexcept { return _linkRegId; }
- //! Returns instruction pointer register id, if the architecture provides it.
- inline uint32_t ipRegId() const noexcept { return _ipRegId; }
-
- //! Returns a hardware stack alignment requirement.
- //!
- //! \note This is a hardware constraint. Architectures that don't constrain it would return the lowest alignment
- //! (1), however, some architectures may constrain the alignment, for example AArch64 requires 16-byte alignment.
- inline uint32_t hwStackAlignment() const noexcept { return _hwStackAlignment; }
-
- //! Tests whether the architecture provides link register, which is used across function calls. If the link
- //! register is not provided then a function call pushes the return address on stack (X86/X64).
- inline bool hasLinkReg() const noexcept { return _linkRegId != BaseReg::kIdBad; }
-
- //! Returns minimum addressable offset on stack guaranteed for all instructions.
- inline uint32_t minStackOffset() const noexcept { return _minStackOffset; }
- //! Returns maximum addressable offset on stack depending on specific instruction.
- inline uint32_t maxStackOffset() const noexcept { return _maxStackOffset; }
-
- //! Returns ISA flags of the given register `group`.
- inline InstHints instFeatureHints(RegGroup group) const noexcept { return _instHints[group]; }
- //! Tests whether the given register `group` has the given `flag` set.
- inline bool hasInstHint(RegGroup group, InstHints feature) const noexcept { return Support::test(_instHints[group], feature); }
- //! Tests whether the ISA provides register swap instruction for the given register `group`.
- inline bool hasInstRegSwap(RegGroup group) const noexcept { return hasInstHint(group, InstHints::kRegSwap); }
- //! Tests whether the ISA provides push/pop instructions for the given register `group`.
- inline bool hasInstPushPop(RegGroup group) const noexcept { return hasInstHint(group, InstHints::kPushPop); }
-
- inline bool hasRegType(RegType type) const noexcept {
- return type <= RegType::kMaxValue && _regSignature[type].isValid();
- }
-
- //! Returns an operand signature from the given register `type` of this architecture.
- inline OperandSignature regTypeToSignature(RegType type) const noexcept { return _regSignature[type]; }
- //! Returns a register from the given register `type` of this architecture.
- inline RegGroup regTypeToGroup(RegType type) const noexcept { return _regSignature[type].regGroup(); }
- //! Returns a register size the given register `type` of this architecture.
- inline uint32_t regTypeToSize(RegType type) const noexcept { return _regSignature[type].size(); }
- //! Returns a corresponding `TypeId` from the given register `type` of this architecture.
- inline TypeId regTypeToTypeId(RegType type) const noexcept { return _regTypeToTypeId[type]; }
-
- //! Returns a table of ISA word names that appear in formatted text. Word names are ISA dependent.
- //!
- //! The index of this table is log2 of the size:
- //! - [0] 8-bits
- //! - [1] 16-bits
- //! - [2] 32-bits
- //! - [3] 64-bits
- inline const ArchTypeNameId* typeNameIdTable() const noexcept { return _typeNameIdTable; }
-
- //! Returns an ISA word name identifier of the given `index`, see \ref typeNameIdTable() for more details.
- inline ArchTypeNameId typeNameIdByIndex(uint32_t index) const noexcept { return _typeNameIdTable[index]; }
-
- //! \}
-
- //! \name Statics
- //! \{
-
- //! Returns a const reference to `ArchTraits` for the given architecture `arch`.
- static inline const ArchTraits& byArch(Arch arch) noexcept;
-
- //! \}
-};
-
-ASMJIT_VARAPI const ArchTraits _archTraits[uint32_t(Arch::kMaxValue) + 1];
-
-//! \cond
-inline const ArchTraits& ArchTraits::byArch(Arch arch) noexcept { return _archTraits[uint32_t(arch)]; }
-//! \endcond
-
-//! Architecture utilities.
-namespace ArchUtils {
-
-ASMJIT_API Error typeIdToRegSignature(Arch arch, TypeId typeId, TypeId* typeIdOut, OperandSignature* regSignatureOut) noexcept;
-
-} // {ArchUtils}
-
-//! \}
-
-ASMJIT_END_NAMESPACE
-
-#endif // ASMJIT_CORE_ARCHTRAITS_H_INCLUDED
diff --git a/src/asmjit/asmjit/core/assembler.cpp b/src/asmjit/asmjit/core/assembler.cpp
deleted file mode 100644
index ea223a3..0000000
--- a/src/asmjit/asmjit/core/assembler.cpp
+++ /dev/null
@@ -1,406 +0,0 @@
-// This file is part of AsmJit project
-//
-// See asmjit.h or LICENSE.md for license and copyright information
-// SPDX-License-Identifier: Zlib
-
-#include "../core/api-build_p.h"
-#include "../core/assembler.h"
-#include "../core/codewriter_p.h"
-#include "../core/constpool.h"
-#include "../core/emitterutils_p.h"
-#include "../core/formatter.h"
-#include "../core/logger.h"
-#include "../core/support.h"
-
-ASMJIT_BEGIN_NAMESPACE
-
-// BaseAssembler - Construction & Destruction
-// ==========================================
-
-BaseAssembler::BaseAssembler() noexcept
- : BaseEmitter(EmitterType::kAssembler) {}
-
-BaseAssembler::~BaseAssembler() noexcept {}
-
-// BaseAssembler - Buffer Management
-// =================================
-
-Error BaseAssembler::setOffset(size_t offset) {
- if (ASMJIT_UNLIKELY(!_code))
- return reportError(DebugUtils::errored(kErrorNotInitialized));
-
- size_t size = Support::max(_section->bufferSize(), this->offset());
- if (ASMJIT_UNLIKELY(offset > size))
- return reportError(DebugUtils::errored(kErrorInvalidArgument));
-
- _bufferPtr = _bufferData + offset;
- return kErrorOk;
-}
-
-// BaseAssembler - Section Management
-// ==================================
-
-static void BaseAssembler_initSection(BaseAssembler* self, Section* section) noexcept {
- uint8_t* p = section->_buffer._data;
-
- self->_section = section;
- self->_bufferData = p;
- self->_bufferPtr = p + section->_buffer._size;
- self->_bufferEnd = p + section->_buffer._capacity;
-}
-
-Error BaseAssembler::section(Section* section) {
- if (ASMJIT_UNLIKELY(!_code))
- return reportError(DebugUtils::errored(kErrorNotInitialized));
-
- if (!_code->isSectionValid(section->id()) || _code->_sections[section->id()] != section)
- return reportError(DebugUtils::errored(kErrorInvalidSection));
-
-#ifndef ASMJIT_NO_LOGGING
- if (_logger)
- _logger->logf(".section %s {#%u}\n", section->name(), section->id());
-#endif
-
- BaseAssembler_initSection(this, section);
- return kErrorOk;
-}
-
-// BaseAssembler - Label Management
-// ================================
-
-Label BaseAssembler::newLabel() {
- uint32_t labelId = Globals::kInvalidId;
- if (ASMJIT_LIKELY(_code)) {
- LabelEntry* le;
- Error err = _code->newLabelEntry(&le);
- if (ASMJIT_UNLIKELY(err))
- reportError(err);
- else
- labelId = le->id();
- }
- return Label(labelId);
-}
-
-Label BaseAssembler::newNamedLabel(const char* name, size_t nameSize, LabelType type, uint32_t parentId) {
- uint32_t labelId = Globals::kInvalidId;
- if (ASMJIT_LIKELY(_code)) {
- LabelEntry* le;
- Error err = _code->newNamedLabelEntry(&le, name, nameSize, type, parentId);
- if (ASMJIT_UNLIKELY(err))
- reportError(err);
- else
- labelId = le->id();
- }
- return Label(labelId);
-}
-
-Error BaseAssembler::bind(const Label& label) {
- if (ASMJIT_UNLIKELY(!_code))
- return reportError(DebugUtils::errored(kErrorNotInitialized));
-
- Error err = _code->bindLabel(label, _section->id(), offset());
-
-#ifndef ASMJIT_NO_LOGGING
- if (_logger)
- EmitterUtils::logLabelBound(this, label);
-#endif
-
- resetInlineComment();
- if (err)
- return reportError(err);
-
- return kErrorOk;
-}
-
-// BaseAssembler - Embed
-// =====================
-
-Error BaseAssembler::embed(const void* data, size_t dataSize) {
- if (ASMJIT_UNLIKELY(!_code))
- return reportError(DebugUtils::errored(kErrorNotInitialized));
-
- if (dataSize == 0)
- return kErrorOk;
-
- CodeWriter writer(this);
- ASMJIT_PROPAGATE(writer.ensureSpace(this, dataSize));
-
- writer.emitData(data, dataSize);
- writer.done(this);
-
-#ifndef ASMJIT_NO_LOGGING
- if (_logger) {
- StringTmp<512> sb;
- Formatter::formatData(sb, _logger->flags(), arch(), TypeId::kUInt8, data, dataSize, 1);
- sb.append('\n');
- _logger->log(sb);
- }
-#endif
-
- return kErrorOk;
-}
-
-Error BaseAssembler::embedDataArray(TypeId typeId, const void* data, size_t itemCount, size_t repeatCount) {
- uint32_t deabstractDelta = TypeUtils::deabstractDeltaOfSize(registerSize());
- TypeId finalTypeId = TypeUtils::deabstract(typeId, deabstractDelta);
-
- if (ASMJIT_UNLIKELY(!TypeUtils::isValid(finalTypeId)))
- return reportError(DebugUtils::errored(kErrorInvalidArgument));
-
- if (itemCount == 0 || repeatCount == 0)
- return kErrorOk;
-
- uint32_t typeSize = TypeUtils::sizeOf(finalTypeId);
- Support::FastUInt8 of = 0;
-
- size_t dataSize = Support::mulOverflow(itemCount, size_t(typeSize), &of);
- size_t totalSize = Support::mulOverflow(dataSize, repeatCount, &of);
-
- if (ASMJIT_UNLIKELY(of))
- return reportError(DebugUtils::errored(kErrorOutOfMemory));
-
- CodeWriter writer(this);
- ASMJIT_PROPAGATE(writer.ensureSpace(this, totalSize));
-
- for (size_t i = 0; i < repeatCount; i++)
- writer.emitData(data, dataSize);
-
- writer.done(this);
-
-#ifndef ASMJIT_NO_LOGGING
- if (_logger) {
- StringTmp<512> sb;
- Formatter::formatData(sb, _logger->flags(), arch(), typeId, data, itemCount, repeatCount);
- sb.append('\n');
- _logger->log(sb);
- }
-#endif
-
- return kErrorOk;
-}
-
-#ifndef ASMJIT_NO_LOGGING
-static const TypeId dataTypeIdBySize[9] = {
- TypeId::kVoid, // [0] (invalid)
- TypeId::kUInt8, // [1] (uint8_t)
- TypeId::kUInt16, // [2] (uint16_t)
- TypeId::kVoid, // [3] (invalid)
- TypeId::kUInt32, // [4] (uint32_t)
- TypeId::kVoid, // [5] (invalid)
- TypeId::kVoid, // [6] (invalid)
- TypeId::kVoid, // [7] (invalid)
- TypeId::kUInt64 // [8] (uint64_t)
-};
-#endif
-
-Error BaseAssembler::embedConstPool(const Label& label, const ConstPool& pool) {
- if (ASMJIT_UNLIKELY(!_code))
- return reportError(DebugUtils::errored(kErrorNotInitialized));
-
- if (ASMJIT_UNLIKELY(!isLabelValid(label)))
- return reportError(DebugUtils::errored(kErrorInvalidLabel));
-
- ASMJIT_PROPAGATE(align(AlignMode::kData, uint32_t(pool.alignment())));
- ASMJIT_PROPAGATE(bind(label));
-
- size_t size = pool.size();
- if (!size)
- return kErrorOk;
-
- CodeWriter writer(this);
- ASMJIT_PROPAGATE(writer.ensureSpace(this, size));
-
-#ifndef ASMJIT_NO_LOGGING
- uint8_t* data = writer.cursor();
-#endif
-
- pool.fill(writer.cursor());
- writer.advance(size);
- writer.done(this);
-
-#ifndef ASMJIT_NO_LOGGING
- if (_logger) {
- uint32_t dataSizeLog2 = Support::min(Support::ctz(pool.minItemSize()), 3);
- uint32_t dataSize = 1 << dataSizeLog2;
-
- StringTmp<512> sb;
- Formatter::formatData(sb, _logger->flags(), arch(), dataTypeIdBySize[dataSize], data, size >> dataSizeLog2);
- sb.append('\n');
- _logger->log(sb);
- }
-#endif
-
- return kErrorOk;
-}
-
-Error BaseAssembler::embedLabel(const Label& label, size_t dataSize) {
- if (ASMJIT_UNLIKELY(!_code))
- return reportError(DebugUtils::errored(kErrorNotInitialized));
-
- ASMJIT_ASSERT(_code != nullptr);
- RelocEntry* re;
- LabelEntry* le = _code->labelEntry(label);
-
- if (ASMJIT_UNLIKELY(!le))
- return reportError(DebugUtils::errored(kErrorInvalidLabel));
-
- if (dataSize == 0)
- dataSize = registerSize();
-
- if (ASMJIT_UNLIKELY(!Support::isPowerOf2(dataSize) || dataSize > 8))
- return reportError(DebugUtils::errored(kErrorInvalidOperandSize));
-
- CodeWriter writer(this);
- ASMJIT_PROPAGATE(writer.ensureSpace(this, dataSize));
-
-#ifndef ASMJIT_NO_LOGGING
- if (_logger) {
- StringTmp<256> sb;
- sb.append('.');
- Formatter::formatDataType(sb, _logger->flags(), arch(), dataTypeIdBySize[dataSize]);
- sb.append(' ');
- Formatter::formatLabel(sb, FormatFlags::kNone, this, label.id());
- sb.append('\n');
- _logger->log(sb);
- }
-#endif
-
- Error err = _code->newRelocEntry(&re, RelocType::kRelToAbs);
- if (ASMJIT_UNLIKELY(err))
- return reportError(err);
-
- re->_sourceSectionId = _section->id();
- re->_sourceOffset = offset();
- re->_format.resetToDataValue(uint32_t(dataSize));
-
- if (le->isBound()) {
- re->_targetSectionId = le->section()->id();
- re->_payload = le->offset();
- }
- else {
- OffsetFormat of;
- of.resetToDataValue(uint32_t(dataSize));
-
- LabelLink* link = _code->newLabelLink(le, _section->id(), offset(), 0, of);
- if (ASMJIT_UNLIKELY(!link))
- return reportError(DebugUtils::errored(kErrorOutOfMemory));
-
- link->relocId = re->id();
- }
-
- // Emit dummy DWORD/QWORD depending on the data size.
- writer.emitZeros(dataSize);
- writer.done(this);
-
- return kErrorOk;
-}
-
-Error BaseAssembler::embedLabelDelta(const Label& label, const Label& base, size_t dataSize) {
- if (ASMJIT_UNLIKELY(!_code))
- return reportError(DebugUtils::errored(kErrorNotInitialized));
-
- LabelEntry* labelEntry = _code->labelEntry(label);
- LabelEntry* baseEntry = _code->labelEntry(base);
-
- if (ASMJIT_UNLIKELY(!labelEntry || !baseEntry))
- return reportError(DebugUtils::errored(kErrorInvalidLabel));
-
- if (dataSize == 0)
- dataSize = registerSize();
-
- if (ASMJIT_UNLIKELY(!Support::isPowerOf2(dataSize) || dataSize > 8))
- return reportError(DebugUtils::errored(kErrorInvalidOperandSize));
-
- CodeWriter writer(this);
- ASMJIT_PROPAGATE(writer.ensureSpace(this, dataSize));
-
-#ifndef ASMJIT_NO_LOGGING
- if (_logger) {
- StringTmp<256> sb;
- sb.append('.');
- Formatter::formatDataType(sb, _logger->flags(), arch(), dataTypeIdBySize[dataSize]);
- sb.append(" (");
- Formatter::formatLabel(sb, FormatFlags::kNone, this, label.id());
- sb.append(" - ");
- Formatter::formatLabel(sb, FormatFlags::kNone, this, base.id());
- sb.append(")\n");
- _logger->log(sb);
- }
-#endif
-
- // If both labels are bound within the same section it means the delta can be calculated now.
- if (labelEntry->isBound() && baseEntry->isBound() && labelEntry->section() == baseEntry->section()) {
- uint64_t delta = labelEntry->offset() - baseEntry->offset();
- writer.emitValueLE(delta, dataSize);
- }
- else {
- RelocEntry* re;
- Error err = _code->newRelocEntry(&re, RelocType::kExpression);
- if (ASMJIT_UNLIKELY(err))
- return reportError(err);
-
- Expression* exp = _code->_zone.newT();
- if (ASMJIT_UNLIKELY(!exp))
- return reportError(DebugUtils::errored(kErrorOutOfMemory));
-
- exp->reset();
- exp->opType = ExpressionOpType::kSub;
- exp->setValueAsLabel(0, labelEntry);
- exp->setValueAsLabel(1, baseEntry);
-
- re->_format.resetToDataValue(dataSize);
- re->_sourceSectionId = _section->id();
- re->_sourceOffset = offset();
- re->_payload = (uint64_t)(uintptr_t)exp;
-
- writer.emitZeros(dataSize);
- }
-
- writer.done(this);
- return kErrorOk;
-}
-
-// BaseAssembler - Comment
-// =======================
-
-Error BaseAssembler::comment(const char* data, size_t size) {
- if (!hasEmitterFlag(EmitterFlags::kLogComments)) {
- if (!hasEmitterFlag(EmitterFlags::kAttached))
- return reportError(DebugUtils::errored(kErrorNotInitialized));
- return kErrorOk;
- }
-
-#ifndef ASMJIT_NO_LOGGING
- // Logger cannot be NULL if `EmitterFlags::kLogComments` is set.
- ASMJIT_ASSERT(_logger != nullptr);
-
- _logger->log(data, size);
- _logger->log("\n", 1);
- return kErrorOk;
-#else
- DebugUtils::unused(data, size);
- return kErrorOk;
-#endif
-}
-
-// BaseAssembler - Events
-// ======================
-
-Error BaseAssembler::onAttach(CodeHolder* code) noexcept {
- ASMJIT_PROPAGATE(Base::onAttach(code));
-
- // Attach to the end of the .text section.
- BaseAssembler_initSection(this, code->_sections[0]);
-
- return kErrorOk;
-}
-
-Error BaseAssembler::onDetach(CodeHolder* code) noexcept {
- _section = nullptr;
- _bufferData = nullptr;
- _bufferEnd = nullptr;
- _bufferPtr = nullptr;
- return Base::onDetach(code);
-}
-
-ASMJIT_END_NAMESPACE
diff --git a/src/asmjit/asmjit/core/assembler.h b/src/asmjit/asmjit/core/assembler.h
deleted file mode 100644
index 7ea2505..0000000
--- a/src/asmjit/asmjit/core/assembler.h
+++ /dev/null
@@ -1,129 +0,0 @@
-// This file is part of AsmJit project
-//
-// See asmjit.h or LICENSE.md for license and copyright information
-// SPDX-License-Identifier: Zlib
-
-#ifndef ASMJIT_CORE_ASSEMBLER_H_INCLUDED
-#define ASMJIT_CORE_ASSEMBLER_H_INCLUDED
-
-#include "../core/codeholder.h"
-#include "../core/emitter.h"
-#include "../core/operand.h"
-
-ASMJIT_BEGIN_NAMESPACE
-
-//! \addtogroup asmjit_assembler
-//! \{
-
-//! Base assembler.
-//!
-//! This is a base class that provides interface used by architecture specific
-//! assembler implementations. Assembler doesn't hold any data, instead it's
-//! attached to \ref CodeHolder, which provides all the data that Assembler
-//! needs and which can be altered by it.
-//!
-//! Check out architecture specific assemblers for more details and examples:
-//!
-//! - \ref x86::Assembler - X86/X64 assembler implementation.
-class ASMJIT_VIRTAPI BaseAssembler : public BaseEmitter {
-public:
- ASMJIT_NONCOPYABLE(BaseAssembler)
- typedef BaseEmitter Base;
-
- //! Current section where the assembling happens.
- Section* _section = nullptr;
- //! Start of the CodeBuffer of the current section.
- uint8_t* _bufferData = nullptr;
- //! End (first invalid byte) of the current section.
- uint8_t* _bufferEnd = nullptr;
- //! Pointer in the CodeBuffer of the current section.
- uint8_t* _bufferPtr = nullptr;
-
- //! \name Construction & Destruction
- //! \{
-
- //! Creates a new `BaseAssembler` instance.
- ASMJIT_API BaseAssembler() noexcept;
- //! Destroys the `BaseAssembler` instance.
- ASMJIT_API virtual ~BaseAssembler() noexcept;
-
- //! \}
-
- //! \name Code-Buffer Management
- //! \{
-
- //! Returns the capacity of the current CodeBuffer.
- inline size_t bufferCapacity() const noexcept { return (size_t)(_bufferEnd - _bufferData); }
- //! Returns the number of remaining bytes in the current CodeBuffer.
- inline size_t remainingSpace() const noexcept { return (size_t)(_bufferEnd - _bufferPtr); }
-
- //! Returns the current position in the CodeBuffer.
- inline size_t offset() const noexcept { return (size_t)(_bufferPtr - _bufferData); }
-
- //! Sets the current position in the CodeBuffer to `offset`.
- //!
- //! \note The `offset` cannot be greater than buffer size even if it's
- //! within the buffer's capacity.
- ASMJIT_API Error setOffset(size_t offset);
-
- //! Returns the start of the CodeBuffer in the current section.
- inline uint8_t* bufferData() const noexcept { return _bufferData; }
- //! Returns the end (first invalid byte) in the current section.
- inline uint8_t* bufferEnd() const noexcept { return _bufferEnd; }
- //! Returns the current pointer in the CodeBuffer in the current section.
- inline uint8_t* bufferPtr() const noexcept { return _bufferPtr; }
-
- //! \}
-
- //! \name Section Management
- //! \{
-
- //! Returns the current section.
- inline Section* currentSection() const noexcept { return _section; }
-
- ASMJIT_API Error section(Section* section) override;
-
- //! \}
-
- //! \name Label Management
- //! \{
-
- ASMJIT_API Label newLabel() override;
- ASMJIT_API Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, LabelType type = LabelType::kGlobal, uint32_t parentId = Globals::kInvalidId) override;
- ASMJIT_API Error bind(const Label& label) override;
-
- //! \}
-
- //! \name Embed
- //! \{
-
- ASMJIT_API Error embed(const void* data, size_t dataSize) override;
- ASMJIT_API Error embedDataArray(TypeId typeId, const void* data, size_t itemCount, size_t repeatCount = 1) override;
- ASMJIT_API Error embedConstPool(const Label& label, const ConstPool& pool) override;
-
- ASMJIT_API Error embedLabel(const Label& label, size_t dataSize = 0) override;
- ASMJIT_API Error embedLabelDelta(const Label& label, const Label& base, size_t dataSize = 0) override;
-
- //! \}
-
- //! \name Comment
- //! \{
-
- ASMJIT_API Error comment(const char* data, size_t size = SIZE_MAX) override;
-
- //! \}
-
- //! \name Events
- //! \{
-
- ASMJIT_API Error onAttach(CodeHolder* code) noexcept override;
- ASMJIT_API Error onDetach(CodeHolder* code) noexcept override;
-
- //! \}
-};
-
-//! \}
-
-ASMJIT_END_NAMESPACE
-
-#endif // ASMJIT_CORE_ASSEMBLER_H_INCLUDED
diff --git a/src/asmjit/asmjit/core/builder.cpp b/src/asmjit/asmjit/core/builder.cpp
deleted file mode 100644
index b308791..0000000
--- a/src/asmjit/asmjit/core/builder.cpp
+++ /dev/null
@@ -1,886 +0,0 @@
-// This file is part of AsmJit project
-//
-// See asmjit.h or LICENSE.md for license and copyright information
-// SPDX-License-Identifier: Zlib
-
-#include "../core/api-build_p.h"
-#ifndef ASMJIT_NO_BUILDER
-
-#include "../core/builder.h"
-#include "../core/emitterutils_p.h"
-#include "../core/errorhandler.h"
-#include "../core/formatter.h"
-#include "../core/logger.h"
-#include "../core/support.h"
-
-ASMJIT_BEGIN_NAMESPACE
-
-// PostponedErrorHandler (Internal)
-// ================================
-
-//! Postponed error handler that never throws. Used as a temporal error handler
-//! to run passes. If error occurs, the caller is notified and will call the
-//! real error handler, that can throw.
-class PostponedErrorHandler : public ErrorHandler {
-public:
- void handleError(Error err, const char* message, BaseEmitter* origin) override {
- DebugUtils::unused(err, origin);
- _message.assign(message);
- }
-
- StringTmp<128> _message;
-};
-
-// BaseBuilder - Utilities
-// =======================
-
-static void BaseBuilder_deletePasses(BaseBuilder* self) noexcept {
- for (Pass* pass : self->_passes)
- pass->~Pass();
- self->_passes.reset();
-}
-
-// BaseBuilder - Construction & Destruction
-// ========================================
-
-BaseBuilder::BaseBuilder() noexcept
- : BaseEmitter(EmitterType::kBuilder),
- _codeZone(32768 - Zone::kBlockOverhead),
- _dataZone(16384 - Zone::kBlockOverhead),
- _passZone(65536 - Zone::kBlockOverhead),
- _allocator(&_codeZone) {}
-
-BaseBuilder::~BaseBuilder() noexcept {
- BaseBuilder_deletePasses(this);
-}
-
-// BaseBuilder - Node Management
-// =============================
-
-Error BaseBuilder::_newInstNode(InstNode** out, InstId instId, InstOptions instOptions, uint32_t opCount) {
- uint32_t opCapacity = InstNode::capacityOfOpCount(opCount);
- ASMJIT_ASSERT(opCapacity >= InstNode::kBaseOpCapacity);
-
- InstNode* node = _allocator.allocT(InstNode::nodeSizeOfOpCapacity(opCapacity));
- if (ASMJIT_UNLIKELY(!node))
- return reportError(DebugUtils::errored(kErrorOutOfMemory));
-
- *out = new(node) InstNode(this, instId, instOptions, opCount, opCapacity);
- return kErrorOk;
-}
-
-
-Error BaseBuilder::_newLabelNode(LabelNode** out) {
- *out = nullptr;
-
- ASMJIT_PROPAGATE(_newNodeT(out));
- return registerLabelNode(*out);
-}
-
-Error BaseBuilder::_newAlignNode(AlignNode** out, AlignMode alignMode, uint32_t alignment) {
- *out = nullptr;
- return _newNodeT(out, alignMode, alignment);
-}
-
-Error BaseBuilder::_newEmbedDataNode(EmbedDataNode** out, TypeId typeId, const void* data, size_t itemCount, size_t repeatCount) {
- *out = nullptr;
-
- uint32_t deabstractDelta = TypeUtils::deabstractDeltaOfSize(registerSize());
- TypeId finalTypeId = TypeUtils::deabstract(typeId, deabstractDelta);
-
- if (ASMJIT_UNLIKELY(!TypeUtils::isValid(finalTypeId)))
- return reportError(DebugUtils::errored(kErrorInvalidArgument));
-
- uint32_t typeSize = TypeUtils::sizeOf(finalTypeId);
- Support::FastUInt8 of = 0;
-
- size_t dataSize = Support::mulOverflow(itemCount, size_t(typeSize), &of);
- if (ASMJIT_UNLIKELY(of))
- return reportError(DebugUtils::errored(kErrorOutOfMemory));
-
- EmbedDataNode* node;
- ASMJIT_PROPAGATE(_newNodeT(&node));
-
- node->_embed._typeId = typeId;
- node->_embed._typeSize = uint8_t(typeSize);
- node->_itemCount = itemCount;
- node->_repeatCount = repeatCount;
-
- uint8_t* dstData = node->_inlineData;
- if (dataSize > EmbedDataNode::kInlineBufferSize) {
- dstData = static_cast(_dataZone.alloc(dataSize, 8));
- if (ASMJIT_UNLIKELY(!dstData))
- return reportError(DebugUtils::errored(kErrorOutOfMemory));
- node->_externalData = dstData;
- }
-
- if (data)
- memcpy(dstData, data, dataSize);
-
- *out = node;
- return kErrorOk;
-}
-
-Error BaseBuilder::_newConstPoolNode(ConstPoolNode** out) {
- *out = nullptr;
-
- ASMJIT_PROPAGATE(_newNodeT(out));
- return registerLabelNode(*out);
-}
-
-Error BaseBuilder::_newCommentNode(CommentNode** out, const char* data, size_t size) {
- *out = nullptr;
-
- if (data) {
- if (size == SIZE_MAX)
- size = strlen(data);
-
- if (size > 0) {
- data = static_cast(_dataZone.dup(data, size, true));
- if (ASMJIT_UNLIKELY(!data))
- return reportError(DebugUtils::errored(kErrorOutOfMemory));
- }
- }
-
- return _newNodeT(out, data);
-}
-
-BaseNode* BaseBuilder::addNode(BaseNode* node) noexcept {
- ASMJIT_ASSERT(node);
- ASMJIT_ASSERT(!node->_prev);
- ASMJIT_ASSERT(!node->_next);
- ASMJIT_ASSERT(!node->isActive());
-
- if (!_cursor) {
- if (!_firstNode) {
- _firstNode = node;
- _lastNode = node;
- }
- else {
- node->_next = _firstNode;
- _firstNode->_prev = node;
- _firstNode = node;
- }
- }
- else {
- BaseNode* prev = _cursor;
- BaseNode* next = _cursor->next();
-
- node->_prev = prev;
- node->_next = next;
-
- prev->_next = node;
- if (next)
- next->_prev = node;
- else
- _lastNode = node;
- }
-
- node->addFlags(NodeFlags::kIsActive);
- if (node->isSection())
- _dirtySectionLinks = true;
-
- _cursor = node;
- return node;
-}
-
-BaseNode* BaseBuilder::addAfter(BaseNode* node, BaseNode* ref) noexcept {
- ASMJIT_ASSERT(node);
- ASMJIT_ASSERT(ref);
-
- ASMJIT_ASSERT(!node->_prev);
- ASMJIT_ASSERT(!node->_next);
-
- BaseNode* prev = ref;
- BaseNode* next = ref->next();
-
- node->_prev = prev;
- node->_next = next;
-
- node->addFlags(NodeFlags::kIsActive);
- if (node->isSection())
- _dirtySectionLinks = true;
-
- prev->_next = node;
- if (next)
- next->_prev = node;
- else
- _lastNode = node;
-
- return node;
-}
-
-BaseNode* BaseBuilder::addBefore(BaseNode* node, BaseNode* ref) noexcept {
- ASMJIT_ASSERT(node != nullptr);
- ASMJIT_ASSERT(!node->_prev);
- ASMJIT_ASSERT(!node->_next);
- ASMJIT_ASSERT(!node->isActive());
- ASMJIT_ASSERT(ref != nullptr);
- ASMJIT_ASSERT(ref->isActive());
-
- BaseNode* prev = ref->prev();
- BaseNode* next = ref;
-
- node->_prev = prev;
- node->_next = next;
-
- node->addFlags(NodeFlags::kIsActive);
- if (node->isSection())
- _dirtySectionLinks = true;
-
- next->_prev = node;
- if (prev)
- prev->_next = node;
- else
- _firstNode = node;
-
- return node;
-}
-
-BaseNode* BaseBuilder::removeNode(BaseNode* node) noexcept {
- if (!node->isActive())
- return node;
-
- BaseNode* prev = node->prev();
- BaseNode* next = node->next();
-
- if (_firstNode == node)
- _firstNode = next;
- else
- prev->_next = next;
-
- if (_lastNode == node)
- _lastNode = prev;
- else
- next->_prev = prev;
-
- node->_prev = nullptr;
- node->_next = nullptr;
- node->clearFlags(NodeFlags::kIsActive);
- if (node->isSection())
- _dirtySectionLinks = true;
-
- if (_cursor == node)
- _cursor = prev;
-
- return node;
-}
-
-void BaseBuilder::removeNodes(BaseNode* first, BaseNode* last) noexcept {
- if (first == last) {
- removeNode(first);
- return;
- }
-
- if (!first->isActive())
- return;
-
- BaseNode* prev = first->prev();
- BaseNode* next = last->next();
-
- if (_firstNode == first)
- _firstNode = next;
- else
- prev->_next = next;
-
- if (_lastNode == last)
- _lastNode = prev;
- else
- next->_prev = prev;
-
- BaseNode* node = first;
- uint32_t didRemoveSection = false;
-
- for (;;) {
- next = node->next();
- ASMJIT_ASSERT(next != nullptr);
-
- node->_prev = nullptr;
- node->_next = nullptr;
- node->clearFlags(NodeFlags::kIsActive);
- didRemoveSection |= uint32_t(node->isSection());
-
- if (_cursor == node)
- _cursor = prev;
-
- if (node == last)
- break;
- node = next;
- }
-
- if (didRemoveSection)
- _dirtySectionLinks = true;
-}
-
-BaseNode* BaseBuilder::setCursor(BaseNode* node) noexcept {
- BaseNode* old = _cursor;
- _cursor = node;
- return old;
-}
-
-// BaseBuilder - Sections
-// ======================
-
-Error BaseBuilder::sectionNodeOf(SectionNode** out, uint32_t sectionId) {
- *out = nullptr;
-
- if (ASMJIT_UNLIKELY(!_code))
- return DebugUtils::errored(kErrorNotInitialized);
-
- if (ASMJIT_UNLIKELY(!_code->isSectionValid(sectionId)))
- return reportError(DebugUtils::errored(kErrorInvalidSection));
-
- if (sectionId >= _sectionNodes.size()) {
- Error err = _sectionNodes.reserve(&_allocator, sectionId + 1);
- if (ASMJIT_UNLIKELY(err != kErrorOk))
- return reportError(err);
- }
-
- SectionNode* node = nullptr;
- if (sectionId < _sectionNodes.size())
- node = _sectionNodes[sectionId];
-
- if (!node) {
- ASMJIT_PROPAGATE(_newNodeT(&node, sectionId));
-
- // We have already reserved enough space, this cannot fail now.
- if (sectionId >= _sectionNodes.size())
- _sectionNodes.resize(&_allocator, sectionId + 1);
-
- _sectionNodes[sectionId] = node;
- }
-
- *out = node;
- return kErrorOk;
-}
-
-Error BaseBuilder::section(Section* section) {
- SectionNode* node;
- ASMJIT_PROPAGATE(sectionNodeOf(&node, section->id()));
-
- if (!node->isActive()) {
- // Insert the section at the end if it was not part of the code.
- addAfter(node, lastNode());
- _cursor = node;
- }
- else {
- // This is a bit tricky. We cache section links to make sure that
- // switching sections doesn't involve traversal in linked-list unless
- // the position of the section has changed.
- if (hasDirtySectionLinks())
- updateSectionLinks();
-
- if (node->_nextSection)
- _cursor = node->_nextSection->_prev;
- else
- _cursor = _lastNode;
- }
-
- return kErrorOk;
-}
-
-void BaseBuilder::updateSectionLinks() noexcept {
- if (!_dirtySectionLinks)
- return;
-
- BaseNode* node_ = _firstNode;
- SectionNode* currentSection = nullptr;
-
- while (node_) {
- if (node_->isSection()) {
- if (currentSection)
- currentSection->_nextSection = node_->as();
- currentSection = node_->as();
- }
- node_ = node_->next();
- }
-
- if (currentSection)
- currentSection->_nextSection = nullptr;
-
- _dirtySectionLinks = false;
-}
-
-// BaseBuilder - Labels
-// ====================
-
-Error BaseBuilder::labelNodeOf(LabelNode** out, uint32_t labelId) {
- *out = nullptr;
-
- if (ASMJIT_UNLIKELY(!_code))
- return DebugUtils::errored(kErrorNotInitialized);
-
- uint32_t index = labelId;
- if (ASMJIT_UNLIKELY(index >= _code->labelCount()))
- return DebugUtils::errored(kErrorInvalidLabel);
-
- if (index >= _labelNodes.size())
- ASMJIT_PROPAGATE(_labelNodes.resize(&_allocator, index + 1));
-
- LabelNode* node = _labelNodes[index];
- if (!node) {
- ASMJIT_PROPAGATE(_newNodeT(&node, labelId));
- _labelNodes[index] = node;
- }
-
- *out = node;
- return kErrorOk;
-}
-
-Error BaseBuilder::registerLabelNode(LabelNode* node) {
- if (ASMJIT_UNLIKELY(!_code))
- return DebugUtils::errored(kErrorNotInitialized);
-
- LabelEntry* le;
- ASMJIT_PROPAGATE(_code->newLabelEntry(&le));
- uint32_t labelId = le->id();
-
- // We just added one label so it must be true.
- ASMJIT_ASSERT(_labelNodes.size() < labelId + 1);
- ASMJIT_PROPAGATE(_labelNodes.resize(&_allocator, labelId + 1));
-
- _labelNodes[labelId] = node;
- node->_labelId = labelId;
-
- return kErrorOk;
-}
-
-static Error BaseBuilder_newLabelInternal(BaseBuilder* self, uint32_t labelId) {
- ASMJIT_ASSERT(self->_labelNodes.size() < labelId + 1);
-
- uint32_t growBy = labelId - self->_labelNodes.size();
- Error err = self->_labelNodes.willGrow(&self->_allocator, growBy);
-
- if (ASMJIT_UNLIKELY(err))
- return self->reportError(err);
-
- LabelNode* node;
- ASMJIT_PROPAGATE(self->_newNodeT(&node, labelId));
-
- self->_labelNodes.resize(&self->_allocator, labelId + 1);
- self->_labelNodes[labelId] = node;
- node->_labelId = labelId;
- return kErrorOk;
-}
-
-Label BaseBuilder::newLabel() {
- uint32_t labelId = Globals::kInvalidId;
- LabelEntry* le;
-
- if (_code &&
- _code->newLabelEntry(&le) == kErrorOk &&
- BaseBuilder_newLabelInternal(this, le->id()) == kErrorOk) {
- labelId = le->id();
- }
-
- return Label(labelId);
-}
-
-Label BaseBuilder::newNamedLabel(const char* name, size_t nameSize, LabelType type, uint32_t parentId) {
- uint32_t labelId = Globals::kInvalidId;
- LabelEntry* le;
-
- if (_code &&
- _code->newNamedLabelEntry(&le, name, nameSize, type, parentId) == kErrorOk &&
- BaseBuilder_newLabelInternal(this, le->id()) == kErrorOk) {
- labelId = le->id();
- }
-
- return Label(labelId);
-}
-
-Error BaseBuilder::bind(const Label& label) {
- LabelNode* node;
- ASMJIT_PROPAGATE(labelNodeOf(&node, label));
-
- addNode(node);
- return kErrorOk;
-}
-
-// BaseBuilder - Passes
-// ====================
-
-ASMJIT_FAVOR_SIZE Pass* BaseBuilder::passByName(const char* name) const noexcept {
- for (Pass* pass : _passes)
- if (strcmp(pass->name(), name) == 0)
- return pass;
- return nullptr;
-}
-
-ASMJIT_FAVOR_SIZE Error BaseBuilder::addPass(Pass* pass) noexcept {
- if (ASMJIT_UNLIKELY(!_code))
- return DebugUtils::errored(kErrorNotInitialized);
-
- if (ASMJIT_UNLIKELY(pass == nullptr)) {
- // Since this is directly called by `addPassT()` we treat `null` argument
- // as out-of-memory condition. Otherwise it would be API misuse.
- return DebugUtils::errored(kErrorOutOfMemory);
- }
- else if (ASMJIT_UNLIKELY(pass->_cb)) {
- // Kinda weird, but okay...
- if (pass->_cb == this)
- return kErrorOk;
- return DebugUtils::errored(kErrorInvalidState);
- }
-
- ASMJIT_PROPAGATE(_passes.append(&_allocator, pass));
- pass->_cb = this;
- return kErrorOk;
-}
-
-ASMJIT_FAVOR_SIZE Error BaseBuilder::deletePass(Pass* pass) noexcept {
- if (ASMJIT_UNLIKELY(!_code))
- return DebugUtils::errored(kErrorNotInitialized);
-
- if (ASMJIT_UNLIKELY(pass == nullptr))
- return DebugUtils::errored(kErrorInvalidArgument);
-
- if (pass->_cb != nullptr) {
- if (pass->_cb != this)
- return DebugUtils::errored(kErrorInvalidState);
-
- uint32_t index = _passes.indexOf(pass);
- ASMJIT_ASSERT(index != Globals::kNotFound);
-
- pass->_cb = nullptr;
- _passes.removeAt(index);
- }
-
- pass->~Pass();
- return kErrorOk;
-}
-
-Error BaseBuilder::runPasses() {
- if (ASMJIT_UNLIKELY(!_code))
- return DebugUtils::errored(kErrorNotInitialized);
-
- if (_passes.empty())
- return kErrorOk;
-
- ErrorHandler* prev = errorHandler();
- PostponedErrorHandler postponed;
-
- Error err = kErrorOk;
- setErrorHandler(&postponed);
-
- for (Pass* pass : _passes) {
- _passZone.reset();
- err = pass->run(&_passZone, _logger);
- if (err)
- break;
- }
- _passZone.reset();
- setErrorHandler(prev);
-
- if (ASMJIT_UNLIKELY(err))
- return reportError(err, !postponed._message.empty() ? postponed._message.data() : nullptr);
-
- return kErrorOk;
-}
-
-// BaseBuilder - Emit
-// ==================
-
-Error BaseBuilder::_emit(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) {
- uint32_t opCount = EmitterUtils::opCountFromEmitArgs(o0, o1, o2, opExt);
- InstOptions options = instOptions() | forcedInstOptions();
-
- if (Support::test(options, InstOptions::kReserved)) {
- if (ASMJIT_UNLIKELY(!_code))
- return DebugUtils::errored(kErrorNotInitialized);
-
-#ifndef ASMJIT_NO_VALIDATION
- // Strict validation.
- if (hasValidationOption(ValidationOptions::kValidateIntermediate)) {
- Operand_ opArray[Globals::kMaxOpCount];
- EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt);
-
- Error err = InstAPI::validate(arch(), BaseInst(instId, options, _extraReg), opArray, opCount);
- if (ASMJIT_UNLIKELY(err)) {
- resetInstOptions();
- resetExtraReg();
- resetInlineComment();
- return reportError(err);
- }
- }
-#endif
-
- // Clear instruction options that should never be part of a regular instruction.
- options &= ~InstOptions::kReserved;
- }
-
- uint32_t opCapacity = InstNode::capacityOfOpCount(opCount);
- ASMJIT_ASSERT(opCapacity >= InstNode::kBaseOpCapacity);
-
- InstNode* node = _allocator.allocT(InstNode::nodeSizeOfOpCapacity(opCapacity));
- const char* comment = inlineComment();
-
- resetInstOptions();
- resetInlineComment();
-
- if (ASMJIT_UNLIKELY(!node)) {
- resetExtraReg();
- return reportError(DebugUtils::errored(kErrorOutOfMemory));
- }
-
- node = new(node) InstNode(this, instId, options, opCount, opCapacity);
- node->setExtraReg(extraReg());
- node->setOp(0, o0);
- node->setOp(1, o1);
- node->setOp(2, o2);
- for (uint32_t i = 3; i < opCount; i++)
- node->setOp(i, opExt[i - 3]);
- node->resetOpRange(opCount, opCapacity);
-
- if (comment)
- node->setInlineComment(static_cast(_dataZone.dup(comment, strlen(comment), true)));
-
- addNode(node);
- resetExtraReg();
- return kErrorOk;
-}
-
-// BaseBuilder - Align
-// ===================
-
-Error BaseBuilder::align(AlignMode alignMode, uint32_t alignment) {
- if (ASMJIT_UNLIKELY(!_code))
- return DebugUtils::errored(kErrorNotInitialized);
-
- AlignNode* node;
- ASMJIT_PROPAGATE(_newAlignNode(&node, alignMode, alignment));
-
- addNode(node);
- return kErrorOk;
-}
-
-// BaseBuilder - Embed
-// ===================
-
-Error BaseBuilder::embed(const void* data, size_t dataSize) {
- if (ASMJIT_UNLIKELY(!_code))
- return DebugUtils::errored(kErrorNotInitialized);
-
- EmbedDataNode* node;
- ASMJIT_PROPAGATE(_newEmbedDataNode(&node, TypeId::kUInt8, data, dataSize));
-
- addNode(node);
- return kErrorOk;
-}
-
-Error BaseBuilder::embedDataArray(TypeId typeId, const void* data, size_t itemCount, size_t itemRepeat) {
- if (ASMJIT_UNLIKELY(!_code))
- return DebugUtils::errored(kErrorNotInitialized);
-
- EmbedDataNode* node;
- ASMJIT_PROPAGATE(_newEmbedDataNode(&node, typeId, data, itemCount, itemRepeat));
-
- addNode(node);
- return kErrorOk;
-}
-
-Error BaseBuilder::embedConstPool(const Label& label, const ConstPool& pool) {
- if (ASMJIT_UNLIKELY(!_code))
- return DebugUtils::errored(kErrorNotInitialized);
-
- if (!isLabelValid(label))
- return reportError(DebugUtils::errored(kErrorInvalidLabel));
-
- ASMJIT_PROPAGATE(align(AlignMode::kData, uint32_t(pool.alignment())));
- ASMJIT_PROPAGATE(bind(label));
-
- EmbedDataNode* node;
- ASMJIT_PROPAGATE(_newEmbedDataNode(&node, TypeId::kUInt8, nullptr, pool.size()));
-
- pool.fill(node->data());
- addNode(node);
- return kErrorOk;
-}
-
-// BaseBuilder - EmbedLabel & EmbedLabelDelta
-// ==========================================
-//
-// If dataSize is zero it means that the size is the same as target register width, however,
-// if it's provided we really want to validate whether it's within the possible range.
-
-static inline bool BaseBuilder_checkDataSize(size_t dataSize) noexcept {
- return !dataSize || (Support::isPowerOf2(dataSize) && dataSize <= 8);
-}
-
-Error BaseBuilder::embedLabel(const Label& label, size_t dataSize) {
- if (ASMJIT_UNLIKELY(!_code))
- return DebugUtils::errored(kErrorNotInitialized);
-
- if (!BaseBuilder_checkDataSize(dataSize))
- return reportError(DebugUtils::errored(kErrorInvalidArgument));
-
- EmbedLabelNode* node;
- ASMJIT_PROPAGATE(_newNodeT(&node, label.id(), uint32_t(dataSize)));
-
- addNode(node);
- return kErrorOk;
-}
-
-Error BaseBuilder::embedLabelDelta(const Label& label, const Label& base, size_t dataSize) {
- if (ASMJIT_UNLIKELY(!_code))
- return DebugUtils::errored(kErrorNotInitialized);
-
- if (!BaseBuilder_checkDataSize(dataSize))
- return reportError(DebugUtils::errored(kErrorInvalidArgument));
-
- EmbedLabelDeltaNode* node;
- ASMJIT_PROPAGATE(_newNodeT(&node, label.id(), base.id(), uint32_t(dataSize)));
-
- addNode(node);
- return kErrorOk;
-}
-
-// BaseBuilder - Comment
-// =====================
-
-Error BaseBuilder::comment(const char* data, size_t size) {
- if (ASMJIT_UNLIKELY(!_code))
- return DebugUtils::errored(kErrorNotInitialized);
-
- CommentNode* node;
- ASMJIT_PROPAGATE(_newCommentNode(&node, data, size));
-
- addNode(node);
- return kErrorOk;
-}
-
-// BaseBuilder - SerializeTo
-// =========================
-
-Error BaseBuilder::serializeTo(BaseEmitter* dst) {
- Error err = kErrorOk;
- BaseNode* node_ = _firstNode;
-
- Operand_ opArray[Globals::kMaxOpCount];
-
- do {
- dst->setInlineComment(node_->inlineComment());
-
- if (node_->isInst()) {
- InstNode* node = node_->as();
-
- // NOTE: Inlined to remove one additional call per instruction.
- dst->setInstOptions(node->instOptions());
- dst->setExtraReg(node->extraReg());
-
- const Operand_* op = node->operands();
- const Operand_* opExt = EmitterUtils::noExt;
-
- uint32_t opCount = node->opCount();
- if (opCount > 3) {
- uint32_t i = 4;
- opArray[3] = op[3];
-
- while (i < opCount) {
- opArray[i].copyFrom(op[i]);
- i++;
- }
- while (i < Globals::kMaxOpCount) {
- opArray[i].reset();
- i++;
- }
- opExt = opArray + 3;
- }
-
- err = dst->_emit(node->id(), op[0], op[1], op[2], opExt);
- }
- else if (node_->isLabel()) {
- if (node_->isConstPool()) {
- ConstPoolNode* node = node_->as();
- err = dst->embedConstPool(node->label(), node->constPool());
- }
- else {
- LabelNode* node = node_->as();
- err = dst->bind(node->label());
- }
- }
- else if (node_->isAlign()) {
- AlignNode* node = node_->as();
- err = dst->align(node->alignMode(), node->alignment());
- }
- else if (node_->isEmbedData()) {
- EmbedDataNode* node = node_->as();
- err = dst->embedDataArray(node->typeId(), node->data(), node->itemCount(), node->repeatCount());
- }
- else if (node_->isEmbedLabel()) {
- EmbedLabelNode* node = node_->as();
- err = dst->embedLabel(node->label(), node->dataSize());
- }
- else if (node_->isEmbedLabelDelta()) {
- EmbedLabelDeltaNode* node = node_->as();
- err = dst->embedLabelDelta(node->label(), node->baseLabel(), node->dataSize());
- }
- else if (node_->isSection()) {
- SectionNode* node = node_->as();
- err = dst->section(_code->sectionById(node->id()));
- }
- else if (node_->isComment()) {
- CommentNode* node = node_->as();
- err = dst->comment(node->inlineComment());
- }
-
- if (err) break;
- node_ = node_->next();
- } while (node_);
-
- return err;
-}
-
-// BaseBuilder - Events
-// ====================
-
-Error BaseBuilder::onAttach(CodeHolder* code) noexcept {
- ASMJIT_PROPAGATE(Base::onAttach(code));
-
- SectionNode* initialSection;
- Error err = sectionNodeOf(&initialSection, 0);
-
- if (!err)
- err = _passes.willGrow(&_allocator, 8);
-
- if (ASMJIT_UNLIKELY(err)) {
- onDetach(code);
- return err;
- }
-
- _cursor = initialSection;
- _firstNode = initialSection;
- _lastNode = initialSection;
- initialSection->setFlags(NodeFlags::kIsActive);
-
- return kErrorOk;
-}
-
-Error BaseBuilder::onDetach(CodeHolder* code) noexcept {
- BaseBuilder_deletePasses(this);
- _sectionNodes.reset();
- _labelNodes.reset();
-
- _allocator.reset(&_codeZone);
- _codeZone.reset();
- _dataZone.reset();
- _passZone.reset();
-
- _nodeFlags = NodeFlags::kNone;
- _cursor = nullptr;
- _firstNode = nullptr;
- _lastNode = nullptr;
-
- return Base::onDetach(code);
-}
-
-// Pass - Construction & Destruction
-// =================================
-
-Pass::Pass(const char* name) noexcept
- : _name(name) {}
-Pass::~Pass() noexcept {}
-
-ASMJIT_END_NAMESPACE
-
-#endif // !ASMJIT_NO_BUILDER
diff --git a/src/asmjit/asmjit/core/builder.h b/src/asmjit/asmjit/core/builder.h
deleted file mode 100644
index 8c01943..0000000
--- a/src/asmjit/asmjit/core/builder.h
+++ /dev/null
@@ -1,1370 +0,0 @@
-// This file is part of AsmJit project
-//
-// See asmjit.h or LICENSE.md for license and copyright information
-// SPDX-License-Identifier: Zlib
-
-#ifndef ASMJIT_CORE_BUILDER_H_INCLUDED
-#define ASMJIT_CORE_BUILDER_H_INCLUDED
-
-#include "../core/api-config.h"
-#ifndef ASMJIT_NO_BUILDER
-
-#include "../core/assembler.h"
-#include "../core/codeholder.h"
-#include "../core/constpool.h"
-#include "../core/formatter.h"
-#include "../core/inst.h"
-#include "../core/operand.h"
-#include "../core/string.h"
-#include "../core/support.h"
-#include "../core/type.h"
-#include "../core/zone.h"
-#include "../core/zonevector.h"
-
-ASMJIT_BEGIN_NAMESPACE
-
-//! \addtogroup asmjit_builder
-//! \{
-
-class BaseBuilder;
-class Pass;
-
-class BaseNode;
-class InstNode;
-class SectionNode;
-class LabelNode;
-class AlignNode;
-class EmbedDataNode;
-class EmbedLabelNode;
-class ConstPoolNode;
-class CommentNode;
-class SentinelNode;
-class LabelDeltaNode;
-
-//! Type of node used by \ref BaseBuilder and \ref BaseCompiler.
-enum class NodeType : uint8_t {
- //! Invalid node (internal, don't use).
- kNone = 0,
-
- // [BaseBuilder]
-
- //! Node is \ref InstNode or \ref InstExNode.
- kInst = 1,
- //! Node is \ref SectionNode.
- kSection = 2,
- //! Node is \ref LabelNode.
- kLabel = 3,
- //! Node is \ref AlignNode.
- kAlign = 4,
- //! Node is \ref EmbedDataNode.
- kEmbedData = 5,
- //! Node is \ref EmbedLabelNode.
- kEmbedLabel = 6,
- //! Node is \ref EmbedLabelDeltaNode.
- kEmbedLabelDelta = 7,
- //! Node is \ref ConstPoolNode.
- kConstPool = 8,
- //! Node is \ref CommentNode.
- kComment = 9,
- //! Node is \ref SentinelNode.
- kSentinel = 10,
-
- // [BaseCompiler]
-
- //! Node is \ref JumpNode (acts as InstNode).
- kJump = 15,
- //! Node is \ref FuncNode (acts as LabelNode).
- kFunc = 16,
- //! Node is \ref FuncRetNode (acts as InstNode).
- kFuncRet = 17,
- //! Node is \ref InvokeNode (acts as InstNode).
- kInvoke = 18,
-
- // [UserDefined]
-
- //! First id of a user-defined node.
- kUser = 32
-};
-
-//! Node flags, specify what the node is and/or does.
-enum class NodeFlags : uint8_t {
- //! No flags.
- kNone = 0,
- //! Node is code that can be executed (instruction, label, align, etc...).
- kIsCode = 0x01u,
- //! Node is data that cannot be executed (data, const-pool, etc...).
- kIsData = 0x02u,
- //! Node is informative, can be removed and ignored.
- kIsInformative = 0x04u,
- //! Node can be safely removed if unreachable.
- kIsRemovable = 0x08u,
- //! Node does nothing when executed (label, align, explicit nop).
- kHasNoEffect = 0x10u,
- //! Node is an instruction or acts as it.
- kActsAsInst = 0x20u,
- //! Node is a label or acts as it.
- kActsAsLabel = 0x40u,
- //! Node is active (part of the code).
- kIsActive = 0x80u
-};
-ASMJIT_DEFINE_ENUM_FLAGS(NodeFlags)
-
-//! Type of the sentinel (purery informative purpose).
-enum class SentinelType : uint8_t {
- //! Type of the sentinel is not known.
- kUnknown = 0u,
- //! This is a sentinel used at the end of \ref FuncNode.
- kFuncEnd = 1u
-};
-
-//! Builder interface.
-//!
-//! `BaseBuilder` interface was designed to be used as a \ref BaseAssembler replacement in case pre-processing or
-//! post-processing of the generated code is required. The code can be modified during or after code generation.
-//! Pre processing or post processing can be done manually or through a \ref Pass object. \ref BaseBuilder stores
-//! the emitted code as a double-linked list of nodes, which allows O(1) insertion and removal during processing.
-//!
-//! Check out architecture specific builders for more details and examples:
-//!
-//! - \ref x86::Builder - X86/X64 builder implementation.
-class ASMJIT_VIRTAPI BaseBuilder : public BaseEmitter {
-public:
- ASMJIT_NONCOPYABLE(BaseBuilder)
- typedef BaseEmitter Base;
-
- //! \name Members
- //! \{
-
- //! Base zone used to allocate nodes and passes.
- Zone _codeZone;
- //! Data zone used to allocate data and names.
- Zone _dataZone;
- //! Pass zone, passed to `Pass::run()`.
- Zone _passZone;
- //! Allocator that uses `_codeZone`.
- ZoneAllocator _allocator;
-
- //! Array of `Pass` objects.
- ZoneVector _passes {};
- //! Maps section indexes to `LabelNode` nodes.
- ZoneVector _sectionNodes {};
- //! Maps label indexes to `LabelNode` nodes.
- ZoneVector _labelNodes {};
-
- //! Current node (cursor).
- BaseNode* _cursor = nullptr;
- //! First node of the current section.
- BaseNode* _firstNode = nullptr;
- //! Last node of the current section.
- BaseNode* _lastNode = nullptr;
-
- //! Flags assigned to each new node.
- NodeFlags _nodeFlags = NodeFlags::kNone;
- //! The sections links are dirty (used internally).
- bool _dirtySectionLinks = false;
-
- //! \}
-
- //! \name Construction & Destruction
- //! \{
-
- //! Creates a new `BaseBuilder` instance.
- ASMJIT_API BaseBuilder() noexcept;
- //! Destroys the `BaseBuilder` instance.
- ASMJIT_API virtual ~BaseBuilder() noexcept;
-
- //! \}
-
- //! \name Node Management
- //! \{
-
- //! Returns the first node.
- inline BaseNode* firstNode() const noexcept { return _firstNode; }
- //! Returns the last node.
- inline BaseNode* lastNode() const noexcept { return _lastNode; }
-
- //! Allocates and instantiates a new node of type `T` and returns its instance. If the allocation fails `nullptr`
- //! is returned.
- //!
- //! The template argument `T` must be a type that is extends \ref BaseNode.
- //!
- //! \remarks The pointer returned (if non-null) is owned by the Builder or Compiler. When the Builder/Compiler
- //! is destroyed it destroys all nodes it created so no manual memory management is required.
- template
- inline Error _newNodeT(T** out, Args&&... args) {
- *out = _allocator.newT(this, std::forward(args)...);
- if (ASMJIT_UNLIKELY(!*out))
- return reportError(DebugUtils::errored(kErrorOutOfMemory));
- return kErrorOk;
- }
-
- //! Creates a new \ref InstNode.
- ASMJIT_API Error _newInstNode(InstNode** out, InstId instId, InstOptions instOptions, uint32_t opCount);
- //! Creates a new \ref LabelNode.
- ASMJIT_API Error _newLabelNode(LabelNode** out);
- //! Creates a new \ref AlignNode.
- ASMJIT_API Error _newAlignNode(AlignNode** out, AlignMode alignMode, uint32_t alignment);
- //! Creates a new \ref EmbedDataNode.
- ASMJIT_API Error _newEmbedDataNode(EmbedDataNode** out, TypeId typeId, const void* data, size_t itemCount, size_t repeatCount = 1);
- //! Creates a new \ref ConstPoolNode.
- ASMJIT_API Error _newConstPoolNode(ConstPoolNode** out);
- //! Creates a new \ref CommentNode.
- ASMJIT_API Error _newCommentNode(CommentNode** out, const char* data, size_t size);
-
- //! Adds `node` after the current and sets the current node to the given `node`.
- ASMJIT_API BaseNode* addNode(BaseNode* node) noexcept;
- //! Inserts the given `node` after `ref`.
- ASMJIT_API BaseNode* addAfter(BaseNode* node, BaseNode* ref) noexcept;
- //! Inserts the given `node` before `ref`.
- ASMJIT_API BaseNode* addBefore(BaseNode* node, BaseNode* ref) noexcept;
- //! Removes the given `node`.
- ASMJIT_API BaseNode* removeNode(BaseNode* node) noexcept;
- //! Removes multiple nodes.
- ASMJIT_API void removeNodes(BaseNode* first, BaseNode* last) noexcept;
-
- //! Returns the cursor.
- //!
- //! When the Builder/Compiler is created it automatically creates a '.text' \ref SectionNode, which will be the
- //! initial one. When instructions are added they are always added after the cursor and the cursor is changed
- //! to be that newly added node. Use `setCursor()` to change where new nodes are inserted.
- inline BaseNode* cursor() const noexcept {
- return _cursor;
- }
-
- //! Sets the current node to `node` and return the previous one.
- ASMJIT_API BaseNode* setCursor(BaseNode* node) noexcept;
-
- //! Sets the current node without returning the previous node.
- //!
- //! Only use this function if you are concerned about performance and want this inlined (for example if you set
- //! the cursor in a loop, etc...).
- inline void _setCursor(BaseNode* node) noexcept {
- _cursor = node;
- }
-
- //! \}
-
- //! \name Section Management
- //! \{
-
- //! Returns a vector of SectionNode objects.
- //!
- //! \note If a section of some id is not associated with the Builder/Compiler it would be null, so always check
- //! for nulls if you iterate over the vector.
- inline const ZoneVector& sectionNodes() const noexcept {
- return _sectionNodes;
- }
-
- //! Tests whether the `SectionNode` of the given `sectionId` was registered.
- inline bool hasRegisteredSectionNode(uint32_t sectionId) const noexcept {
- return sectionId < _sectionNodes.size() && _sectionNodes[sectionId] != nullptr;
- }
-
- //! Returns or creates a `SectionNode` that matches the given `sectionId`.
- //!
- //! \remarks This function will either get the existing `SectionNode` or create it in case it wasn't created before.
- //! You can check whether a section has a registered `SectionNode` by using `BaseBuilder::hasRegisteredSectionNode()`.
- ASMJIT_API Error sectionNodeOf(SectionNode** out, uint32_t sectionId);
-
- ASMJIT_API Error section(Section* section) override;
-
- //! Returns whether the section links of active section nodes are dirty. You can update these links by calling
- //! `updateSectionLinks()` in such case.
- inline bool hasDirtySectionLinks() const noexcept { return _dirtySectionLinks; }
-
- //! Updates links of all active section nodes.
- ASMJIT_API void updateSectionLinks() noexcept;
-
- //! \}
-
- //! \name Label Management
- //! \{
-
- //! Returns a vector of \ref LabelNode nodes.
- //!
- //! \note If a label of some id is not associated with the Builder/Compiler it would be null, so always check for
- //! nulls if you iterate over the vector.
- inline const ZoneVector& labelNodes() const noexcept { return _labelNodes; }
-
- //! Tests whether the `LabelNode` of the given `labelId` was registered.
- inline bool hasRegisteredLabelNode(uint32_t labelId) const noexcept {
- return labelId < _labelNodes.size() && _labelNodes[labelId] != nullptr;
- }
-
- //! \overload
- inline bool hasRegisteredLabelNode(const Label& label) const noexcept {
- return hasRegisteredLabelNode(label.id());
- }
-
- //! Gets or creates a \ref LabelNode that matches the given `labelId`.
- //!
- //! \remarks This function will either get the existing `LabelNode` or create it in case it wasn't created before.
- //! You can check whether a label has a registered `LabelNode` by calling \ref BaseBuilder::hasRegisteredLabelNode().
- ASMJIT_API Error labelNodeOf(LabelNode** out, uint32_t labelId);
-
- //! \overload
- inline Error labelNodeOf(LabelNode** out, const Label& label) {
- return labelNodeOf(out, label.id());
- }
-
- //! Registers this \ref LabelNode (internal).
- //!
- //! This function is used internally to register a newly created `LabelNode` with this instance of Builder/Compiler.
- //! Use \ref labelNodeOf() functions to get back \ref LabelNode from a label or its identifier.
- ASMJIT_API Error registerLabelNode(LabelNode* node);
-
- ASMJIT_API Label newLabel() override;
- ASMJIT_API Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, LabelType type = LabelType::kGlobal, uint32_t parentId = Globals::kInvalidId) override;
- ASMJIT_API Error bind(const Label& label) override;
-
- //! \}
-
- //! \name Passes
- //! \{
-
- //! Returns a vector of `Pass` instances that will be executed by `runPasses()`.
- inline const ZoneVector& passes() const noexcept { return _passes; }
-
- //! Allocates and instantiates a new pass of type `T` and returns its instance. If the allocation fails `nullptr` is
- //! returned.
- //!
- //! The template argument `T` must be a type that is extends \ref Pass.
- //!
- //! \remarks The pointer returned (if non-null) is owned by the Builder or Compiler. When the Builder/Compiler is
- //! destroyed it destroys all passes it created so no manual memory management is required.
- template
- inline T* newPassT() noexcept { return _codeZone.newT(); }
-
- //! \overload
- template
- inline T* newPassT(Args&&... args) noexcept { return _codeZone.newT(std::forward(args)...); }
-
- template
- inline Error addPassT() { return addPass(newPassT()); }
-
- template
- inline Error addPassT(Args&&... args) { return addPass(newPassT(std::forward(args)...)); }
-
- //! Returns `Pass` by name.
- //!
- //! If the pass having the given `name` doesn't exist `nullptr` is returned.
- ASMJIT_API Pass* passByName(const char* name) const noexcept;
- //! Adds `pass` to the list of passes.
- ASMJIT_API Error addPass(Pass* pass) noexcept;
- //! Removes `pass` from the list of passes and delete it.
- ASMJIT_API Error deletePass(Pass* pass) noexcept;
-
- //! Runs all passes in order.
- ASMJIT_API Error runPasses();
-
- //! \}
-
- //! \name Emit
- //! \{
-
- ASMJIT_API Error _emit(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) override;
-
- //! \}
-
- //! \name Align
- //! \{
-
- ASMJIT_API Error align(AlignMode alignMode, uint32_t alignment) override;
-
- //! \}
-
- //! \name Embed
- //! \{
-
- ASMJIT_API Error embed(const void* data, size_t dataSize) override;
- ASMJIT_API Error embedDataArray(TypeId typeId, const void* data, size_t count, size_t repeat = 1) override;
- ASMJIT_API Error embedConstPool(const Label& label, const ConstPool& pool) override;
-
- ASMJIT_API Error embedLabel(const Label& label, size_t dataSize = 0) override;
- ASMJIT_API Error embedLabelDelta(const Label& label, const Label& base, size_t dataSize = 0) override;
-
- //! \}
-
- //! \name Comment
- //! \{
-
- ASMJIT_API Error comment(const char* data, size_t size = SIZE_MAX) override;
-
- //! \}
-
- //! \name Serialization
- //! \{
-
- //! Serializes everything the given emitter `dst`.
- //!
- //! Although not explicitly required the emitter will most probably be of Assembler type. The reason is that
- //! there is no known use of serializing nodes held by Builder/Compiler into another Builder-like emitter.
- ASMJIT_API Error serializeTo(BaseEmitter* dst);
-
- //! \}
-
- //! \name Events
- //! \{
-
- ASMJIT_API Error onAttach(CodeHolder* code) noexcept override;
- ASMJIT_API Error onDetach(CodeHolder* code) noexcept override;
-
- //! \}
-};
-
-//! Base node.
-//!
-//! Every node represents a building-block used by \ref BaseBuilder. It can be instruction, data, label, comment,
-//! directive, or any other high-level representation that can be transformed to the building blocks mentioned.
-//! Every class that inherits \ref BaseBuilder can define its own high-level nodes that can be later lowered to
-//! basic nodes like instructions.
-class BaseNode {
-public:
- ASMJIT_NONCOPYABLE(BaseNode)
-
- //! \name Members
- //! \{
-
- union {
- struct {
- //! Previous node.
- BaseNode* _prev;
- //! Next node.
- BaseNode* _next;
- };
- //! Links (an alternative view to previous and next nodes).
- BaseNode* _links[2];
- };
-
- //! Data shared between all types of nodes.
- struct AnyData {
- //! Node type.
- NodeType _nodeType;
- //! Node flags.
- NodeFlags _nodeFlags;
- //! Not used by BaseNode.
- uint8_t _reserved0;
- //! Not used by BaseNode.
- uint8_t _reserved1;
- };
-
- //! Data used by \ref AlignNode.
- struct AlignData {
- //! Node type.
- NodeType _nodeType;
- //! Node flags.
- NodeFlags _nodeFlags;
- //! Align mode.
- AlignMode _alignMode;
- //! Not used by AlignNode.
- uint8_t _reserved;
- };
-
- //! Data used by \ref InstNode.
- struct InstData {
- //! Node type.
- NodeType _nodeType;
- //! Node flags.
- NodeFlags _nodeFlags;
- //! Instruction operands count (used).
- uint8_t _opCount;
- //! Instruction operands capacity (allocated).
- uint8_t _opCapacity;
- };
-
- //! Data used by \ref EmbedDataNode.
- struct EmbedData {
- //! Node type.
- NodeType _nodeType;
- //! Node flags.
- NodeFlags _nodeFlags;
- //! Type id.
- TypeId _typeId;
- //! Size of `_typeId`.
- uint8_t _typeSize;
- };
-
- //! Data used by \ref SentinelNode.
- struct SentinelData {
- //! Node type.
- NodeType _nodeType;
- //! Node flags.
- NodeFlags _nodeFlags;
- //! Sentinel type.
- SentinelType _sentinelType;
- //! Not used by BaseNode.
- uint8_t _reserved1;
- };
-
- //! Data that can have different meaning dependning on \ref NodeType.
- union {
- //! Data useful by any node type.
- AnyData _any;
- //! Data specific to \ref AlignNode.
- AlignData _alignData;
- //! Data specific to \ref InstNode.
- InstData _inst;
- //! Data specific to \ref EmbedDataNode.
- EmbedData _embed;
- //! Data specific to \ref SentinelNode.
- SentinelData _sentinel;
- };
-
- //! Node position in code (should be unique).
- uint32_t _position;
-
- //! Value reserved for AsmJit users never touched by AsmJit itself.
- union {
- //! User data as 64-bit integer.
- uint64_t _userDataU64;
- //! User data as pointer.
- void* _userDataPtr;
- };
-
- //! Data used exclusively by the current `Pass`.
- void* _passData;
-
- //! Inline comment/annotation or nullptr if not used.
- const char* _inlineComment;
-
- //! \}
-
- //! \name Construction & Destruction
- //! \{
-
- //! Creates a new `BaseNode` - always use `BaseBuilder` to allocate nodes.
- inline BaseNode(BaseBuilder* cb, NodeType nodeType, NodeFlags nodeFlags = NodeFlags::kNone) noexcept {
- _prev = nullptr;
- _next = nullptr;
- _any._nodeType = nodeType;
- _any._nodeFlags = nodeFlags | cb->_nodeFlags;
- _any._reserved0 = 0;
- _any._reserved1 = 0;
- _position = 0;
- _userDataU64 = 0;
- _passData = nullptr;
- _inlineComment = nullptr;
- }
-
- //! \}
-
- //! \name Accessors
- //! \{
-
- //! Casts this node to `T*`.
- template
- inline T* as() noexcept { return static_cast(this); }
- //! Casts this node to `const T*`.
- template
- inline const T* as() const noexcept { return static_cast(this); }
-
- //! Returns previous node or `nullptr` if this node is either first or not
- //! part of Builder/Compiler node-list.
- inline BaseNode* prev() const noexcept { return _prev; }
- //! Returns next node or `nullptr` if this node is either last or not part
- //! of Builder/Compiler node-list.
- inline BaseNode* next() const noexcept { return _next; }
-
- //! Returns the type of the node, see `NodeType`.
- inline NodeType type() const noexcept { return _any._nodeType; }
-
- //! Sets the type of the node, see `NodeType` (internal).
- //!
- //! \remarks You should never set a type of a node to anything else than the initial value. This function is only
- //! provided for users that use custom nodes and need to change the type either during construction or later.
- inline void setType(NodeType type) noexcept { _any._nodeType = type; }
-
- //! Tests whether this node is either `InstNode` or extends it.
- inline bool isInst() const noexcept { return hasFlag(NodeFlags::kActsAsInst); }
- //! Tests whether this node is `SectionNode`.
- inline bool isSection() const noexcept { return type() == NodeType::kSection; }
- //! Tests whether this node is either `LabelNode` or extends it.
- inline bool isLabel() const noexcept { return hasFlag(NodeFlags::kActsAsLabel); }
- //! Tests whether this node is `AlignNode`.
- inline bool isAlign() const noexcept { return type() == NodeType::kAlign; }
- //! Tests whether this node is `EmbedDataNode`.
- inline bool isEmbedData() const noexcept { return type() == NodeType::kEmbedData; }
- //! Tests whether this node is `EmbedLabelNode`.
- inline bool isEmbedLabel() const noexcept { return type() == NodeType::kEmbedLabel; }
- //! Tests whether this node is `EmbedLabelDeltaNode`.
- inline bool isEmbedLabelDelta() const noexcept { return type() == NodeType::kEmbedLabelDelta; }
- //! Tests whether this node is `ConstPoolNode`.
- inline bool isConstPool() const noexcept { return type() == NodeType::kConstPool; }
- //! Tests whether this node is `CommentNode`.
- inline bool isComment() const noexcept { return type() == NodeType::kComment; }
- //! Tests whether this node is `SentinelNode`.
- inline bool isSentinel() const noexcept { return type() == NodeType::kSentinel; }
-
- //! Tests whether this node is `FuncNode`.
- inline bool isFunc() const noexcept { return type() == NodeType::kFunc; }
- //! Tests whether this node is `FuncRetNode`.
- inline bool isFuncRet() const noexcept { return type() == NodeType::kFuncRet; }
- //! Tests whether this node is `InvokeNode`.
- inline bool isInvoke() const noexcept { return type() == NodeType::kInvoke; }
-
- //! Returns the node flags.
- inline NodeFlags flags() const noexcept { return _any._nodeFlags; }
- //! Tests whether the node has the given `flag` set.
- inline bool hasFlag(NodeFlags flag) const noexcept { return Support::test(_any._nodeFlags, flag); }
- //! Replaces node flags with `flags`.
- inline void setFlags(NodeFlags flags) noexcept { _any._nodeFlags = flags; }
- //! Adds the given `flags` to node flags.
- inline void addFlags(NodeFlags flags) noexcept { _any._nodeFlags |= flags; }
- //! Clears the given `flags` from node flags.
- inline void clearFlags(NodeFlags flags) noexcept { _any._nodeFlags &= ~flags; }
-
- //! Tests whether the node is code that can be executed.
- inline bool isCode() const noexcept { return hasFlag(NodeFlags::kIsCode); }
- //! Tests whether the node is data that cannot be executed.
- inline bool isData() const noexcept { return hasFlag(NodeFlags::kIsData); }
- //! Tests whether the node is informative only (is never encoded like comment, etc...).
- inline bool isInformative() const noexcept { return hasFlag(NodeFlags::kIsInformative); }
- //! Tests whether the node is removable if it's in an unreachable code block.
- inline bool isRemovable() const noexcept { return hasFlag(NodeFlags::kIsRemovable); }
- //! Tests whether the node has no effect when executed (label, .align, nop, ...).
- inline bool hasNoEffect() const noexcept { return hasFlag(NodeFlags::kHasNoEffect); }
- //! Tests whether the node is part of the code.
- inline bool isActive() const noexcept { return hasFlag(NodeFlags::kIsActive); }
-
- //! Tests whether the node has a position assigned.
- //!
- //! \remarks Returns `true` if node position is non-zero.
- inline bool hasPosition() const noexcept { return _position != 0; }
- //! Returns node position.
- inline uint32_t position() const noexcept { return _position; }
- //! Sets node position.
- //!
- //! Node position is a 32-bit unsigned integer that is used by Compiler to track where the node is relatively to
- //! the start of the function. It doesn't describe a byte position in a binary, instead it's just a pseudo position
- //! used by liveness analysis and other tools around Compiler.
- //!
- //! If you don't use Compiler then you may use `position()` and `setPosition()` freely for your own purposes if
- //! the 32-bit value limit is okay for you.
- inline void setPosition(uint32_t position) noexcept { _position = position; }
-
- //! Returns user data casted to `T*`.
- //!
- //! User data is decicated to be used only by AsmJit users and not touched by the library. The data has a pointer
- //! size so you can either store a pointer or `intptr_t` value through `setUserDataAsIntPtr()`.
- template
- inline T* userDataAsPtr() const noexcept { return static_cast(_userDataPtr); }
- //! Returns user data casted to `int64_t`.
- inline int64_t userDataAsInt64() const noexcept { return int64_t(_userDataU64); }
- //! Returns user data casted to `uint64_t`.
- inline uint64_t userDataAsUInt64() const noexcept { return _userDataU64; }
-
- //! Sets user data to `data`.
- template
- inline void setUserDataAsPtr(T* data) noexcept { _userDataPtr = static_cast(data); }
- //! Sets used data to the given 64-bit signed `value`.
- inline void setUserDataAsInt64(int64_t value) noexcept { _userDataU64 = uint64_t(value); }
- //! Sets used data to the given 64-bit unsigned `value`.
- inline void setUserDataAsUInt64(uint64_t value) noexcept { _userDataU64 = value; }
-
- //! Resets user data to zero / nullptr.
- inline void resetUserData() noexcept { _userDataU64 = 0; }
-
- //! Tests whether the node has an associated pass data.
- inline bool hasPassData() const noexcept { return _passData != nullptr; }
- //! Returns the node pass data - data used during processing & transformations.
- template
- inline T* passData() const noexcept { return (T*)_passData; }
- //! Sets the node pass data to `data`.
- template
- inline void setPassData(T* data) noexcept { _passData = (void*)data; }
- //! Resets the node pass data to nullptr.
- inline void resetPassData() noexcept { _passData = nullptr; }
-
- //! Tests whether the node has an inline comment/annotation.
- inline bool hasInlineComment() const noexcept { return _inlineComment != nullptr; }
- //! Returns an inline comment/annotation string.
- inline const char* inlineComment() const noexcept { return _inlineComment; }
- //! Sets an inline comment/annotation string to `s`.
- inline void setInlineComment(const char* s) noexcept { _inlineComment = s; }
- //! Resets an inline comment/annotation string to nullptr.
- inline void resetInlineComment() noexcept { _inlineComment = nullptr; }
-
- //! \}
-};
-
-//! Instruction node.
-//!
-//! Wraps an instruction with its options and operands.
-class InstNode : public BaseNode {
-public:
- ASMJIT_NONCOPYABLE(InstNode)
-
- //! \name Constants
- //! \{
-
- //! Count of embedded operands per `InstNode` that are always allocated as a part of the instruction. Minimum
- //! embedded operands is 4, but in 32-bit more pointers are smaller and we can embed 5. The rest (up to 6 operands)
- //! is always stored in `InstExNode`.
- static constexpr uint32_t kBaseOpCapacity = uint32_t((128 - sizeof(BaseNode) - sizeof(BaseInst)) / sizeof(Operand_));
-
- //! \}
-
- //! \name Members
- //! \{
-
- //! Base instruction data.
- BaseInst _baseInst;
- //! First 4 or 5 operands (indexed from 0).
- Operand_ _opArray[kBaseOpCapacity];
-
- //! \}
-
- //! \name Construction & Destruction
- //! \{
-
- //! Creates a new `InstNode` instance.
- inline InstNode(BaseBuilder* cb, InstId instId, InstOptions options, uint32_t opCount, uint32_t opCapacity = kBaseOpCapacity) noexcept
- : BaseNode(cb, NodeType::kInst, NodeFlags::kIsCode | NodeFlags::kIsRemovable | NodeFlags::kActsAsInst),
- _baseInst(instId, options) {
- _inst._opCapacity = uint8_t(opCapacity);
- _inst._opCount = uint8_t(opCount);
- }
-
- //! \cond INTERNAL
- //! Reset all built-in operands, including `extraReg`.
- inline void _resetOps() noexcept {
- _baseInst.resetExtraReg();
- resetOpRange(0, opCapacity());
- }
- //! \endcond
-
- //! \}
-
- //! \name Accessors
- //! \{
-
- inline BaseInst& baseInst() noexcept { return _baseInst; }
- inline const BaseInst& baseInst() const noexcept { return _baseInst; }
-
- //! Returns the instruction id, see `BaseInst::Id`.
- inline InstId id() const noexcept { return _baseInst.id(); }
- //! Sets the instruction id to `id`, see `BaseInst::Id`.
- inline void setId(InstId id) noexcept { _baseInst.setId(id); }
-
- //! Returns instruction options.
- inline InstOptions instOptions() const noexcept { return _baseInst.options(); }
- //! Sets instruction options.
- inline void setInstOptions(InstOptions options) noexcept { _baseInst.setOptions(options); }
- //! Adds instruction options.
- inline void addInstOptions(InstOptions options) noexcept { _baseInst.addOptions(options); }
- //! Clears instruction options.
- inline void clearInstOptions(InstOptions options) noexcept { _baseInst.clearOptions(options); }
-
- //! Tests whether the node has an extra register operand.
- inline bool hasExtraReg() const noexcept { return _baseInst.hasExtraReg(); }
- //! Returns extra register operand.
- inline RegOnly& extraReg() noexcept { return _baseInst.extraReg(); }
- //! \overload
- inline const RegOnly& extraReg() const noexcept { return _baseInst.extraReg(); }
- //! Sets extra register operand to `reg`.
- inline void setExtraReg(const BaseReg& reg) noexcept { _baseInst.setExtraReg(reg); }
- //! Sets extra register operand to `reg`.
- inline void setExtraReg(const RegOnly& reg) noexcept { _baseInst.setExtraReg(reg); }
- //! Resets extra register operand.
- inline void resetExtraReg() noexcept { _baseInst.resetExtraReg(); }
-
- //! Returns operand count.
- inline uint32_t opCount() const noexcept { return _inst._opCount; }
- //! Returns operand capacity.
- inline uint32_t opCapacity() const noexcept { return _inst._opCapacity; }
-
- //! Sets operand count.
- inline void setOpCount(uint32_t opCount) noexcept { _inst._opCount = uint8_t(opCount); }
-
- //! Returns operands array.
- inline Operand* operands() noexcept { return (Operand*)_opArray; }
- //! Returns operands array (const).
- inline const Operand* operands() const noexcept { return (const Operand*)_opArray; }
-
- //! Returns operand at the given `index`.
- inline Operand& op(uint32_t index) noexcept {
- ASMJIT_ASSERT(index < opCapacity());
- return _opArray[index].as();
- }
-
- //! Returns operand at the given `index` (const).
- inline const Operand& op(uint32_t index) const noexcept {
- ASMJIT_ASSERT(index < opCapacity());
- return _opArray[index].as();
- }
-
- //! Sets operand at the given `index` to `op`.
- inline void setOp(uint32_t index, const Operand_& op) noexcept {
- ASMJIT_ASSERT(index < opCapacity());
- _opArray[index].copyFrom(op);
- }
-
- //! Resets operand at the given `index` to none.
- inline void resetOp(uint32_t index) noexcept {
- ASMJIT_ASSERT(index < opCapacity());
- _opArray[index].reset();
- }
-
- //! Resets operands at `[start, end)` range.
- inline void resetOpRange(uint32_t start, uint32_t end) noexcept {
- for (uint32_t i = start; i < end; i++)
- _opArray[i].reset();
- }
-
- //! \}
-
- //! \name Utilities
- //! \{
-
- inline bool hasOpType(OperandType opType) const noexcept {
- for (uint32_t i = 0, count = opCount(); i < count; i++)
- if (_opArray[i].opType() == opType)
- return true;
- return false;
- }
-
- inline bool hasRegOp() const noexcept { return hasOpType(OperandType::kReg); }
- inline bool hasMemOp() const noexcept { return hasOpType(OperandType::kMem); }
- inline bool hasImmOp() const noexcept { return hasOpType(OperandType::kImm); }
- inline bool hasLabelOp() const noexcept { return hasOpType(OperandType::kLabel); }
-
- inline uint32_t indexOfOpType(OperandType opType) const noexcept {
- uint32_t i = 0;
- uint32_t count = opCount();
-
- while (i < count) {
- if (_opArray[i].opType() == opType)
- break;
- i++;
- }
-
- return i;
- }
-
- inline uint32_t indexOfMemOp() const noexcept { return indexOfOpType(OperandType::kMem); }
- inline uint32_t indexOfImmOp() const noexcept { return indexOfOpType(OperandType::kImm); }
- inline uint32_t indexOfLabelOp() const noexcept { return indexOfOpType(OperandType::kLabel); }
-
- //! \}
-
- //! \name Rewriting
- //! \{
-
- //! \cond INTERNAL
- inline uint32_t* _getRewriteArray() noexcept { return &_baseInst._extraReg._id; }
- inline const uint32_t* _getRewriteArray() const noexcept { return &_baseInst._extraReg._id; }
-
- inline uint32_t getRewriteIndex(const uint32_t* id) const noexcept {
- const uint32_t* array = _getRewriteArray();
- ASMJIT_ASSERT(array <= id);
-
- size_t index = (size_t)(id - array);
- ASMJIT_ASSERT(index < 32);
-
- return uint32_t(index);
- }
-
- inline void rewriteIdAtIndex(uint32_t index, uint32_t id) noexcept {
- uint32_t* array = _getRewriteArray();
- array[index] = id;
- }
- //! \endcond
-
- //! \}
-
- //! \name Static Functions
- //! \{
-
- //! \cond INTERNAL
- static inline uint32_t capacityOfOpCount(uint32_t opCount) noexcept {
- return opCount <= kBaseOpCapacity ? kBaseOpCapacity : Globals::kMaxOpCount;
- }
-
- static inline size_t nodeSizeOfOpCapacity(uint32_t opCapacity) noexcept {
- size_t base = sizeof(InstNode) - kBaseOpCapacity * sizeof(Operand);
- return base + opCapacity * sizeof(Operand);
- }
- //! \endcond
-
- //! \}
-};
-
-//! Instruction node with maximum number of operands.
-//!
-//! This node is created automatically by Builder/Compiler in case that the required number of operands exceeds
-//! the default capacity of `InstNode`.
-class InstExNode : public InstNode {
-public:
- ASMJIT_NONCOPYABLE(InstExNode)
-
- //! \name Members
- //! \{
-
- //! Continued `_opArray[]` to hold up to `kMaxOpCount` operands.
- Operand_ _opArrayEx[Globals::kMaxOpCount - kBaseOpCapacity];
-
- //! \}
-
- //! \name Construction & Destruction
- //! \{
-
- //! Creates a new `InstExNode` instance.
- inline InstExNode(BaseBuilder* cb, InstId instId, InstOptions options, uint32_t opCapacity = Globals::kMaxOpCount) noexcept
- : InstNode(cb, instId, options, opCapacity) {}
-
- //! \}
-};
-
-//! Section node.
-class SectionNode : public BaseNode {
-public:
- ASMJIT_NONCOPYABLE(SectionNode)
-
- //! \name Members
- //! \{
-
- //! Section id.
- uint32_t _id;
-
- //! Next section node that follows this section.
- //!
- //! This link is only valid when the section is active (is part of the code) and when `Builder::hasDirtySectionLinks()`
- //! returns `false`. If you intend to use this field you should always call `Builder::updateSectionLinks()` before you
- //! do so.
- SectionNode* _nextSection;
-
- //! \}
-
- //! \name Construction & Destruction
- //! \{
-
- //! Creates a new `SectionNode` instance.
- inline SectionNode(BaseBuilder* cb, uint32_t secionId = 0) noexcept
- : BaseNode(cb, NodeType::kSection, NodeFlags::kHasNoEffect),
- _id(secionId),
- _nextSection(nullptr) {}
-
- //! \}
-
- //! \name Accessors
- //! \{
-
- //! Returns the section id.
- inline uint32_t id() const noexcept { return _id; }
-
- //! \}
-};
-
-//! Label node.
-class LabelNode : public BaseNode {
-public:
- ASMJIT_NONCOPYABLE(LabelNode)
-
- //! \name Members
- //! \{
-
- //! Label identifier.
- uint32_t _labelId;
-
- //! \}
-
- //! \name Construction & Destruction
- //! \{
-
- //! Creates a new `LabelNode` instance.
- inline LabelNode(BaseBuilder* cb, uint32_t labelId = 0) noexcept
- : BaseNode(cb, NodeType::kLabel, NodeFlags::kHasNoEffect | NodeFlags::kActsAsLabel),
- _labelId(labelId) {}
-
- //! \}
-
- //! \name Accessors
- //! \{
-
- //! Returns \ref Label representation of the \ref LabelNode.
- inline Label label() const noexcept { return Label(_labelId); }
- //! Returns the id of the label.
- inline uint32_t labelId() const noexcept { return _labelId; }
-
- //! \}
-};
-
-//! Align directive (BaseBuilder).
-//!
-//! Wraps `.align` directive.
-class AlignNode : public BaseNode {
-public:
- ASMJIT_NONCOPYABLE(AlignNode)
-
- //! \name Members
- //! \{
-
- //! Alignment (in bytes).
- uint32_t _alignment;
-
- //! \}
-
- //! \name Construction & Destruction
- //! \{
-
- //! Creates a new `AlignNode` instance.
- inline AlignNode(BaseBuilder* cb, AlignMode alignMode, uint32_t alignment) noexcept
- : BaseNode(cb, NodeType::kAlign, NodeFlags::kIsCode | NodeFlags::kHasNoEffect) {
-
- _alignData._alignMode = alignMode;
- _alignment = alignment;
- }
-
- //! \}
-
- //! \name Accessors
- //! \{
-
- //! Returns align mode.
- inline AlignMode alignMode() const noexcept { return _alignData._alignMode; }
- //! Sets align mode to `alignMode`.
- inline void setAlignMode(AlignMode alignMode) noexcept { _alignData._alignMode = alignMode; }
-
- //! Returns align offset in bytes.
- inline uint32_t alignment() const noexcept { return _alignment; }
- //! Sets align offset in bytes to `offset`.
- inline void setAlignment(uint32_t alignment) noexcept { _alignment = alignment; }
-
- //! \}
-};
-
-//! Embed data node.
-//!
-//! Wraps `.data` directive. The node contains data that will be placed at the node's position in the assembler
-//! stream. The data is considered to be RAW; no analysis nor byte-order conversion is performed on RAW data.
-class EmbedDataNode : public BaseNode {
-public:
- ASMJIT_NONCOPYABLE(EmbedDataNode)
-
- //! \cond INTERNAL
- static constexpr uint32_t kInlineBufferSize = 128 - (sizeof(BaseNode) + sizeof(size_t) * 2);
- //! \endcond
-
- //! \name Members
- //! \{
-
- size_t _itemCount;
- size_t _repeatCount;
-
- union {
- uint8_t* _externalData;
- uint8_t _inlineData[kInlineBufferSize];
- };
-
- //! \}
-
- //! \name Construction & Destruction
- //! \{
-
- //! Creates a new `EmbedDataNode` instance.
- inline EmbedDataNode(BaseBuilder* cb) noexcept
- : BaseNode(cb, NodeType::kEmbedData, NodeFlags::kIsData),
- _itemCount(0),
- _repeatCount(0) {
- _embed._typeId = TypeId::kUInt8;
- _embed._typeSize = uint8_t(1);
- memset(_inlineData, 0, kInlineBufferSize);
- }
-
- //! \}
-
- //! \name Accessors
- //! \{
-
- //! Returns data type as \ref TypeId.
- inline TypeId typeId() const noexcept { return _embed._typeId; }
- //! Returns the size of a single data element.
- inline uint32_t typeSize() const noexcept { return _embed._typeSize; }
-
- //! Returns a pointer to the data casted to `uint8_t`.
- inline uint8_t* data() const noexcept {
- return dataSize() <= kInlineBufferSize ? const_cast(_inlineData) : _externalData;
- }
-
- //! Returns a pointer to the data casted to `T`.
- template
- inline T* dataAs() const noexcept { return reinterpret_cast(data()); }
-
- //! Returns the number of (typed) items in the array.
- inline size_t itemCount() const noexcept { return _itemCount; }
-
- //! Returns how many times the data is repeated (default 1).
- //!
- //! Repeated data is useful when defining constants for SIMD, for example.
- inline size_t repeatCount() const noexcept { return _repeatCount; }
-
- //! Returns the size of the data, not considering the number of times it repeats.
- //!
- //! \note The returned value is the same as `typeSize() * itemCount()`.
- inline size_t dataSize() const noexcept { return typeSize() * _itemCount; }
-
- //! \}
-};
-
-//! Label data node.
-class EmbedLabelNode : public BaseNode {
-public:
- ASMJIT_NONCOPYABLE(EmbedLabelNode)
-
- //! \name Members
- //! \{
-
- uint32_t _labelId;
- uint32_t _dataSize;
-
- //! \}
-
- //! \name Construction & Destruction
- //! \{
-
- //! Creates a new `EmbedLabelNode` instance.
- inline EmbedLabelNode(BaseBuilder* cb, uint32_t labelId = 0, uint32_t dataSize = 0) noexcept
- : BaseNode(cb, NodeType::kEmbedLabel, NodeFlags::kIsData),
- _labelId(labelId),
- _dataSize(dataSize) {}
-
- //! \}
-
- //! \name Accessors
- //! \{
-
- //! Returns the label to embed as \ref Label operand.
- inline Label label() const noexcept { return Label(_labelId); }
- //! Returns the id of the label.
- inline uint32_t labelId() const noexcept { return _labelId; }
-
- //! Sets the label id from `label` operand.
- inline void setLabel(const Label& label) noexcept { setLabelId(label.id()); }
- //! Sets the label id (use with caution, improper use can break a lot of things).
- inline void setLabelId(uint32_t labelId) noexcept { _labelId = labelId; }
-
- //! Returns the data size.
- inline uint32_t dataSize() const noexcept { return _dataSize; }
- //! Sets the data size.
- inline void setDataSize(uint32_t dataSize) noexcept { _dataSize = dataSize; }
-
- //! \}
-};
-
-//! Label data node.
-class EmbedLabelDeltaNode : public BaseNode {
-public:
- ASMJIT_NONCOPYABLE(EmbedLabelDeltaNode)
-
- //! \name Members
- //! \{
-
- uint32_t _labelId;
- uint32_t _baseLabelId;
- uint32_t _dataSize;
-
- //! \}
-
- //! \name Construction & Destruction
- //! \{
-
- //! Creates a new `EmbedLabelDeltaNode` instance.
- inline EmbedLabelDeltaNode(BaseBuilder* cb, uint32_t labelId = 0, uint32_t baseLabelId = 0, uint32_t dataSize = 0) noexcept
- : BaseNode(cb, NodeType::kEmbedLabelDelta, NodeFlags::kIsData),
- _labelId(labelId),
- _baseLabelId(baseLabelId),
- _dataSize(dataSize) {}
-
- //! \}
-
- //! \name Accessors
- //! \{
-
- //! Returns the label as `Label` operand.
- inline Label label() const noexcept { return Label(_labelId); }
- //! Returns the id of the label.
- inline uint32_t labelId() const noexcept { return _labelId; }
-
- //! Sets the label id from `label` operand.
- inline void setLabel(const Label& label) noexcept { setLabelId(label.id()); }
- //! Sets the label id.
- inline void setLabelId(uint32_t labelId) noexcept { _labelId = labelId; }
-
- //! Returns the base label as `Label` operand.
- inline Label baseLabel() const noexcept { return Label(_baseLabelId); }
- //! Returns the id of the base label.
- inline uint32_t baseLabelId() const noexcept { return _baseLabelId; }
-
- //! Sets the base label id from `label` operand.
- inline void setBaseLabel(const Label& baseLabel) noexcept { setBaseLabelId(baseLabel.id()); }
- //! Sets the base label id.
- inline void setBaseLabelId(uint32_t baseLabelId) noexcept { _baseLabelId = baseLabelId; }
-
- //! Returns the size of the embedded label address.
- inline uint32_t dataSize() const noexcept { return _dataSize; }
- //! Sets the size of the embedded label address.
- inline void setDataSize(uint32_t dataSize) noexcept { _dataSize = dataSize; }
-
- //! \}
-};
-
-//! A node that wraps `ConstPool`.
-class ConstPoolNode : public LabelNode {
-public:
- ASMJIT_NONCOPYABLE(ConstPoolNode)
-
- //! \name Members
- //! \{
-
- ConstPool _constPool;
-
- //! \}
-
- //! \name Construction & Destruction
- //! \{
-
- //! Creates a new `ConstPoolNode` instance.
- inline ConstPoolNode(BaseBuilder* cb, uint32_t id = 0) noexcept
- : LabelNode(cb, id),
- _constPool(&cb->_codeZone) {
-
- setType(NodeType::kConstPool);
- addFlags(NodeFlags::kIsData);
- clearFlags(NodeFlags::kIsCode | NodeFlags::kHasNoEffect);
- }
-
- //! \}
-
- //! \name Accessors
- //! \{
-
- //! Tests whether the constant-pool is empty.
- inline bool empty() const noexcept { return _constPool.empty(); }
- //! Returns the size of the constant-pool in bytes.
- inline size_t size() const noexcept { return _constPool.size(); }
- //! Returns minimum alignment.
- inline size_t alignment() const noexcept { return _constPool.alignment(); }
-
- //! Returns the wrapped `ConstPool` instance.
- inline ConstPool& constPool() noexcept { return _constPool; }
- //! Returns the wrapped `ConstPool` instance (const).
- inline const ConstPool& constPool() const noexcept { return _constPool; }
-
- //! \}
-
- //! \name Utilities
- //! \{
-
- //! See `ConstPool::add()`.
- inline Error add(const void* data, size_t size, size_t& dstOffset) noexcept {
- return _constPool.add(data, size, dstOffset);
- }
-
- //! \}
-};
-
-//! Comment node.
-class CommentNode : public BaseNode {
-public:
- ASMJIT_NONCOPYABLE(CommentNode)
-
- //! \name Construction & Destruction
- //! \{
-
- //! Creates a new `CommentNode` instance.
- inline CommentNode(BaseBuilder* cb, const char* comment) noexcept
- : BaseNode(cb, NodeType::kComment, NodeFlags::kIsInformative | NodeFlags::kHasNoEffect | NodeFlags::kIsRemovable) {
- _inlineComment = comment;
- }
-
- //! \}
-};
-
-//! Sentinel node.
-//!
-//! Sentinel is a marker that is completely ignored by the code builder. It's used to remember a position in a code
-//! as it never gets removed by any pass.
-class SentinelNode : public BaseNode {
-public:
- ASMJIT_NONCOPYABLE(SentinelNode)
-
- //! \name Construction & Destruction
- //! \{
-
- //! Creates a new `SentinelNode` instance.
- inline SentinelNode(BaseBuilder* cb, SentinelType sentinelType = SentinelType::kUnknown) noexcept
- : BaseNode(cb, NodeType::kSentinel, NodeFlags::kIsInformative | NodeFlags::kHasNoEffect) {
-
- _sentinel._sentinelType = sentinelType;
- }
-
- //! \}
-
- //! \name Accessors
- //! \{
-
- //! Returns the type of the sentinel.
- inline SentinelType sentinelType() const noexcept {
- return _sentinel._sentinelType;
- }
-
- //! Sets the type of the sentinel.
- inline void setSentinelType(SentinelType type) noexcept {
- _sentinel._sentinelType = type;
- }
-
- //! \}
-};
-
-//! Pass can be used to implement code transformations, analysis, and lowering.
-class ASMJIT_VIRTAPI Pass {
-public:
- ASMJIT_BASE_CLASS(Pass)
- ASMJIT_NONCOPYABLE(Pass)
-
- //! \name Members
- //! \{
-
- //! BaseBuilder this pass is assigned to.
- BaseBuilder* _cb = nullptr;
- //! Name of the pass.
- const char* _name = nullptr;
-
- //! \}
-
- //! \name Construction & Destruction
- //! \{
-
- ASMJIT_API Pass(const char* name) noexcept;
- ASMJIT_API virtual ~Pass() noexcept;
-
- //! \}
-
- //! \name Accessors
- //! \{
-
- //! Returns \ref BaseBuilder associated with the pass.
- inline const BaseBuilder* cb() const noexcept { return _cb; }
- //! Returns the name of the pass.
- inline const char* name() const noexcept { return _name; }
-
- //! \}
-
- //! \name Pass Interface
- //! \{
-
- //! Processes the code stored in Builder or Compiler.
- //!
- //! This is the only function that is called by the `BaseBuilder` to process
- //! the code. It passes `zone`, which will be reset after the `run()` finishes.
- virtual Error run(Zone* zone, Logger* logger) = 0;
-
- //! \}
-};
-
-//! \}
-
-ASMJIT_END_NAMESPACE
-
-#endif // !ASMJIT_NO_BUILDER
-#endif // ASMJIT_CORE_BUILDER_H_INCLUDED
diff --git a/src/asmjit/asmjit/core/codebuffer.h b/src/asmjit/asmjit/core/codebuffer.h
deleted file mode 100644
index 4946e7a..0000000
--- a/src/asmjit/asmjit/core/codebuffer.h
+++ /dev/null
@@ -1,113 +0,0 @@
-// This file is part of AsmJit project
-//
-// See asmjit.h or LICENSE.md for license and copyright information
-// SPDX-License-Identifier: Zlib
-
-#ifndef ASMJIT_CORE_CODEBUFFER_H_INCLUDED
-#define ASMJIT_CORE_CODEBUFFER_H_INCLUDED
-
-#include "../core/globals.h"
-#include "../core/support.h"
-
-ASMJIT_BEGIN_NAMESPACE
-
-//! \addtogroup asmjit_core
-//! \{
-
-//! Flags used by \ref CodeBuffer.
-enum class CodeBufferFlags : uint32_t {
- //! No flags.
- kNone = 0,
- //! Buffer is external (not allocated by asmjit).
- kIsExternal = 0x00000001u,
- //! Buffer is fixed (cannot be reallocated).
- kIsFixed = 0x00000002u
-};
-ASMJIT_DEFINE_ENUM_FLAGS(CodeBufferFlags)
-
-//! Code or data buffer.
-struct CodeBuffer {
- //! \name Members
- //! \{
-
- //! The content of the buffer (data).
- uint8_t* _data;
- //! Number of bytes of `data` used.
- size_t _size;
- //! Buffer capacity (in bytes).
- size_t _capacity;
- //! Buffer flags.
- CodeBufferFlags _flags;
-
- //! \}
-
- //! \name Overloaded Operators
- //! \{
-
- //! Returns a referebce to the byte at the given `index`.
- inline uint8_t& operator[](size_t index) noexcept {
- ASMJIT_ASSERT(index < _size);
- return _data[index];
- }
- //! \overload
- inline const uint8_t& operator[](size_t index) const noexcept {
- ASMJIT_ASSERT(index < _size);
- return _data[index];
- }
-
- //! \}
-
- //! \name Accessors
- //! \{
-
- //! Returns code buffer flags.
- inline CodeBufferFlags flags() const noexcept { return _flags; }
- //! Tests whether the code buffer has the given `flag` set.
- inline bool hasFlag(CodeBufferFlags flag) const noexcept { return Support::test(_flags, flag); }
-
- //! Tests whether this code buffer has a fixed size.
- //!
- //! Fixed size means that the code buffer is fixed and cannot grow.
- inline bool isFixed() const noexcept { return hasFlag(CodeBufferFlags::kIsFixed); }
-
- //! Tests whether the data in this code buffer is external.
- //!
- //! External data can only be provided by users, it's never used by AsmJit.
- inline bool isExternal() const noexcept { return hasFlag(CodeBufferFlags::kIsExternal); }
-
- //! Tests whether the data in this code buffer is allocated (non-null).
- inline bool isAllocated() const noexcept { return _data != nullptr; }
-
- //! Tests whether the code buffer is empty.
- inline bool empty() const noexcept { return !_size; }
-
- //! Returns the size of the data.
- inline size_t size() const noexcept { return _size; }
- //! Returns the capacity of the data.
- inline size_t capacity() const noexcept { return _capacity; }
-
- //! Returns the pointer to the data the buffer references.
- inline uint8_t* data() noexcept { return _data; }
- //! \overload
- inline const uint8_t* data() const noexcept { return _data; }
-
- //! \}
-
- //! \name Iterators
- //! \{
-
- inline uint8_t* begin() noexcept { return _data; }
- inline const uint8_t* begin() const noexcept { return _data; }
-
- inline uint8_t* end() noexcept { return _data + _size; }
- inline const uint8_t* end() const noexcept { return _data + _size; }
-
- //! \}
-};
-
-//! \}
-
-ASMJIT_END_NAMESPACE
-
-#endif // ASMJIT_CORE_CODEBUFFER_H_INCLUDED
-
diff --git a/src/asmjit/asmjit/core/codeholder.cpp b/src/asmjit/asmjit/core/codeholder.cpp
deleted file mode 100644
index 2f34056..0000000
--- a/src/asmjit/asmjit/core/codeholder.cpp
+++ /dev/null
@@ -1,1155 +0,0 @@
-// This file is part of AsmJit project
-//
-// See asmjit.h or LICENSE.md for license and copyright information
-// SPDX-License-Identifier: Zlib
-
-#include "../core/api-build_p.h"
-#include "../core/assembler.h"
-#include "../core/codewriter_p.h"
-#include "../core/logger.h"
-#include "../core/support.h"
-
-#include
-#include
-
-ASMJIT_BEGIN_NAMESPACE
-
-// Globals
-// =======
-
-static const char CodeHolder_addrTabName[] = ".addrtab";
-
-//! Encode MOD byte.
-static inline uint32_t x86EncodeMod(uint32_t m, uint32_t o, uint32_t rm) noexcept {
- return (m << 6) | (o << 3) | rm;
-}
-
-// LabelLinkIterator
-// =================
-
-class LabelLinkIterator {
-public:
- inline LabelLinkIterator(LabelEntry* le) noexcept { reset(le); }
-
- inline explicit operator bool() const noexcept { return isValid(); }
- inline bool isValid() const noexcept { return _link != nullptr; }
-
- inline LabelLink* link() const noexcept { return _link; }
- inline LabelLink* operator->() const noexcept { return _link; }
-
- inline void reset(LabelEntry* le) noexcept {
- _pPrev = &le->_links;
- _link = *_pPrev;
- }
-
- inline void next() noexcept {
- _pPrev = &_link->next;
- _link = *_pPrev;
- }
-
- inline void resolveAndNext(CodeHolder* code) noexcept {
- LabelLink* linkToDelete = _link;
-
- _link = _link->next;
- *_pPrev = _link;
-
- code->_unresolvedLinkCount--;
- code->_allocator.release(linkToDelete, sizeof(LabelLink));
- }
-
- LabelLink** _pPrev;
- LabelLink* _link;
-};
-
-// CodeHolder - Utilities
-// ======================
-
-static void CodeHolder_resetInternal(CodeHolder* self, ResetPolicy resetPolicy) noexcept {
- uint32_t i;
- const ZoneVector& emitters = self->emitters();
-
- i = emitters.size();
- while (i)
- self->detach(emitters[--i]);
-
- // Reset everything into its construction state.
- self->_environment.reset();
- self->_baseAddress = Globals::kNoBaseAddress;
- self->_logger = nullptr;
- self->_errorHandler = nullptr;
-
- // Reset all sections.
- uint32_t numSections = self->_sections.size();
- for (i = 0; i < numSections; i++) {
- Section* section = self->_sections[i];
- if (section->_buffer.data() && !section->_buffer.isExternal())
- ::free(section->_buffer._data);
- section->_buffer._data = nullptr;
- section->_buffer._capacity = 0;
- }
-
- // Reset zone allocator and all containers using it.
- ZoneAllocator* allocator = self->allocator();
-
- self->_emitters.reset();
- self->_namedLabels.reset();
- self->_relocations.reset();
- self->_labelEntries.reset();
- self->_sections.reset();
- self->_sectionsByOrder.reset();
-
- self->_unresolvedLinkCount = 0;
- self->_addressTableSection = nullptr;
- self->_addressTableEntries.reset();
-
- allocator->reset(&self->_zone);
- self->_zone.reset(resetPolicy);
-}
-
-static void CodeHolder_onSettingsUpdated(CodeHolder* self) noexcept {
- // Notify all attached emitters about a settings update.
- for (BaseEmitter* emitter : self->emitters()) {
- emitter->onSettingsUpdated();
- }
-}
-
-// CodeHolder - Construction & Destruction
-// =======================================
-
-CodeHolder::CodeHolder() noexcept
- : _environment(),
- _baseAddress(Globals::kNoBaseAddress),
- _logger(nullptr),
- _errorHandler(nullptr),
- _zone(16384 - Zone::kBlockOverhead),
- _allocator(&_zone),
- _unresolvedLinkCount(0),
- _addressTableSection(nullptr) {}
-
-CodeHolder::~CodeHolder() noexcept {
- CodeHolder_resetInternal(this, ResetPolicy::kHard);
-}
-
-// CodeHolder - Init & Reset
-// =========================
-
-inline void CodeHolder_setSectionDefaultName(
- Section* section,
- char c0 = 0, char c1 = 0, char c2 = 0, char c3 = 0,
- char c4 = 0, char c5 = 0, char c6 = 0, char c7 = 0) noexcept {
-
- section->_name.u32[0] = Support::bytepack32_4x8(uint8_t(c0), uint8_t(c1), uint8_t(c2), uint8_t(c3));
- section->_name.u32[1] = Support::bytepack32_4x8(uint8_t(c4), uint8_t(c5), uint8_t(c6), uint8_t(c7));
-}
-
-Error CodeHolder::init(const Environment& environment, uint64_t baseAddress) noexcept {
- // Cannot reinitialize if it's locked or there is one or more emitter attached.
- if (isInitialized())
- return DebugUtils::errored(kErrorAlreadyInitialized);
-
- // If we are just initializing there should be no emitters attached.
- ASMJIT_ASSERT(_emitters.empty());
-
- // Create a default section and insert it to the `_sections` array.
- Error err = _sections.willGrow(&_allocator) |
- _sectionsByOrder.willGrow(&_allocator);
- if (err == kErrorOk) {
- Section* section = _allocator.allocZeroedT