diff options
Diffstat (limited to '3rdparty/asmjit/src/asmjit/core.h')
-rw-r--r-- | 3rdparty/asmjit/src/asmjit/core.h | 1632 |
1 files changed, 782 insertions, 850 deletions
diff --git a/3rdparty/asmjit/src/asmjit/core.h b/3rdparty/asmjit/src/asmjit/core.h index d0fb214d0ce..66cbce642a3 100644 --- a/3rdparty/asmjit/src/asmjit/core.h +++ b/3rdparty/asmjit/src/asmjit/core.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 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. +// 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 @@ -27,62 +9,48 @@ //! Root namespace used by AsmJit. namespace asmjit { -// ============================================================================ -// [Documentation - mainpage] -// ============================================================================ - //! \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. +//! 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: +//! 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. +//! \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 should know about \ref +//! asmjit_assembler as it also uses operands, labels, and other concepts. Similarly \ref asmjit_compiler users +//! should 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: +//! 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 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. +//! - \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_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 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. +//! - \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 //! @@ -92,336 +60,403 @@ namespace asmjit { //! //! - 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(). +//! - Instruction validation in your debug builds can reveal problems too. AsmJit provides validation at instruction +//! level that can be enabled via \ref BaseEmitter::addDiagnosticOptions(). See \ref DiagnosticOptions for more +//! details. //! -//! See \ref BaseEmitter::ValidationOptions for more details. +//! - If you are a Compiler user, use diagnostic options and read carefully if anything suspicious pops out. +//! Diagnostic options can be enabled via \ref BaseEmitter::addDiagnosticOptions(). If unsure which ones to use, +//! enable annotations and all debug options: `DiagnosticOptions::kRAAnnotate | DiagnosticOptions::kRADebugAll`. //! -//! - 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. +//! - 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 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. +//! 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 identify and +//! 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 and can also save users from submitting issues. //! //! \section main_other Other Pages //! //! - <a href="annotated.html">Class List</a> - List of classes sorted alphabetically //! - <a href="namespaceasmjit.html">AsmJit Namespace</a> - List of symbols provided by `asmjit` namespace -// ============================================================================ -// [Documentation - asmjit_build] -// ============================================================================ //! \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. +//! 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. +//! - 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. +//! - **Clang** - Tested by GitHub Actions - Clang 10+ is officially supported and tested by CI, older Clang versions +//! having C++11 should work, but are not tested anymore due to upgraded CI images. //! -//! - **MINGW** - Tested by Travis-CI - Use the latest version, if possible. +//! - **GNU** - Tested by GitHub Actions - GCC 7+ is officially supported, older GCC versions from 4.8+ having C++11 +//! enabled should also work, but are not tested anymore due to upgraded CI images. //! -//! - **MSVC** - Tested by Travis-CI - VS2017+ is officially supported, VS2015 -//! is reported to work. +//! - **MINGW** - Reported to work, but not tested in our CI environment (help welcome). //! -//! - 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). +//! - **MSVC** - Tested by GitHub Actions - VS2019+ is officially supported, VS2015 and VS2017 is reported to work, +//! but not tested by CI anymore. //! //! ### Supported Operating Systems and Platforms //! //! - Tested: //! -//! - **Linux** - Tested by Travis-CI (any distribution is generally supported). +//! - **BSD** - FreeBSD, NetBSD, and OpenBSD tested by GitHub Actions (only recent images are tested by CI). BSD +//! runners only test BSD images with clang compiler. //! -//! - **OSX** - Tested by Travis-CI (any version is supported). +//! - **Linux** - Tested by GitHub Actions (only recent Ubuntu images are tested by CI, in general any distribution +//! should be supported as AsmJit has no dependencies). //! -//! - **Windows** - Tested by Travis-CI - (Windows 7+ is officially supported). +//! - **Mac OS** - Tested by GitHub Actions. //! -//! - **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. +//! - **Windows** - Tested by GitHub Actions - (Windows 7+ is officially supported). //! -//! - Untested: +//! - **Emscripten** - Works if compiled with \ref ASMJIT_NO_JIT. AsmJit cannot generate WASM code, but can be +//! used to generate X86/X64/AArch64 code within a browser, for example. //! -//! - **BSDs** - No maintainers, no CI environment to regularly test BSDs, -//! but they should work out of box. +//! - Untested: //! -//! - **Haiku** - Not regularly tested, but reported to work. +//! - **Haiku** - Reported to work, not tested by CI. //! -//! - **Other** operating systems would require some testing and support in -//! the following files: +//! - **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). +//! - **X86** and **X86_64** - Both 32-bit and 64-bit backends tested on CI. +//! - **AArch64** - AArch64 backend is currently only partially tested (there is no native AArch64 runner to test +//! AsmJit Builder/Compiler). //! //! ### 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. +//! 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. +//! \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. +//! 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. +//! - \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. +//! \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_BUILD_X86 - Always build X86 backend (X86 and X86_64). -//! - \ref ASMJIT_BUILD_ARM - Always build ARM backend (ARM and AArch64). -//! - \ref ASMJIT_BUILD_HOST - Always build the host backend, implied by default. +//! 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 auto-detected at compile-time, but this can be overridden. //! -//! ### Features Selection +//! - \ref ASMJIT_NO_X86 - Disables both X86 and X86_64 backends. +//! - \ref ASMJIT_NO_AARCH64 - Disables AArch64 backend. +//! - \ref ASMJIT_NO_FOREIGN - Disables the support for foreign architecture backends, only keeps a native backend. //! -//! 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. +//! ### AsmJit Compilation Options //! -//! - \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, +//! - \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_SHM_OPEN - Disables functionality that uses `shm_open()`. //! -//! - \ref ASMJIT_NO_COMPILER - Disables \ref asmjit_compiler functionality -//! completely. +//! - \ref ASMJIT_NO_ABI_NAMESPACE - Disables inline ABI namespace within `asmjit` namespace. This is only provided +//! for users that control all the dependencies (even transitive ones) and that make sure that no two AsmJit +//! versions are used at the same time. This option can be debugging a little simpler as there would not be ABI +//! tag after `asmjit::` namespace. Otherwise asmjit would look like `asmjit::_abi_1_13::`, for example. //! +//! ### 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_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_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 quiry instruction names, register names, etc... +//! - \ref ASMJIT_NO_LOGGING - Disables \ref Logger and \ref Formatter. //! //! - \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. +//! - \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. +//! +//! - \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. //! -//! \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. +//! \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. -// ============================================================================ -// [Documentation - asmjit_breaking_changes] -// ============================================================================ //! \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. +//! 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. +//! - Visit our [Public Gitter Chat](https://app.gitter.im/#/room/#asmjit:gitter.im) 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 2024-01-01 +//! +//! Core changes: +//! +//! - Renamed equality functions `eq()` to `equals()` - Only related to `String`, `ZoneVector`, and `CpuFeatures`. +//! Old function names were deprecated. +//! +//! - Removed `CallConvId::kNone` in favor of `CallConvId::kCDecl`, which is now the default calling convention. //! -//! - 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. +//! - Deprecated `CallConvId::kHost` in favor of `CallConvId::kCDecl` - host calling convention is now not part +//! of CallConvId, it can be calculated from CallConvId and Environment instead. +//! +//! ### Changes committed at 2023-12-27 +//! +//! Core changes: +//! +//! - Renamed `a64::Vec::ElementType` to `a64::VecElementType` and made it a typed enum. This enum was used mostly +//! internally, but there is a public API using it, so it's a breaking change. +//! +//! - Refactored `FuncSignature`, `FuncSignatureT`, and `FuncSignatureBuilder`. There is only `FuncSignature` now, +//! which acts as a function signature holder and builder. Replace `FuncSignatureBuilder` with `FuncSignature` +//! and use `FuncSignature::build<args>` instead of `FuncSignatureT<args>`. The old API has been deprecated. +//! +//! - The maximum number of function arguments was raised from 16 to 32. +//! +//! ### Changes committed at 2023-12-26 +//! +//! Core changes: +//! +//! - Reworked InstNode and InstExNode to be friendlier to static analysis and to not cause undefined behavior. +//! InstNode has no operands visually embedded within the struct so there is no _opArray (which was internal). +//! This means that sizeof(InstNode) changed, but since it's allocated by AsmJit this should be fine. Moreover, +//! there is no longer InstExNode as that was more a hack, instead there is now InstNodeWithOperands, which is +//! a template and specifies the number of operands embedded (InstNode accesses these). All nodes that inherited +//! InstExNode now just inherit InstNodeWithOperands<InstNode::kBaseOpCapacity>, which would provide the same +//! number of nodes as InstNode. +//! +//! - Moved GP and Vec registers from asmjit::arm namespace to asmjit::a64 namespace. At this time there was +//! no prior deprecation as having arm::Vec would collide with a64::Vec as arm namespace is used within a64 +//! namespace. Just change `arm::Gp` to `a64::Gp` and `arm::Vec` to `a64::Vec`. +//! +//! ### Changes committed at 2023-09-10 +//! +//! Core changes: +//! +//! - Changed allocation API to work with spans (JitAllocator). +//! +//! - This change is required to support more hardened platforms in the future that make it very difficult +//! to write JIT compilers. +//! - `JitAllocator::Span` now represents a memory that the user can access. It abstracts both regular and +//! dual mappings. +//! - The `Span` is mostly designed to make it possible to write into it, so in general the read+execute +//! pointer is what user is intended to keep. Use `span.rx()` to access RX pointer. `Span` is not needed +//! after the memory it references has been modified, only remember `span.rx()` pointer, which is then +//! used to deallocate or change the memory the span references. +//! - Use a new `JitAllocator::alloc()` to allocate a `Span`, then pass the populated Span to `JitAllocator` +//! write API such as `JitAllocator::write()` - note that JitAllocator can also establish a scope, so you +//! can use a lambda function that would perform the write, but since it's going through JitAllocator it's +//! able to ensure that the memory is actually writable. +//! - If you need to repopulate a `Span` from rx pointer, use `JitAllocator::query(<span-out>, rx)` to get it. +//! - Study what JitRuntime is doing to better understand how this new API works in detail. +//! - Users of JitRuntime do not have to do anything as JitRuntime properly abstracts the allocation. +//! +//! - Renamed some X86 CPU features to make them compatible with architecture manuals: +//! +//! - Changed `AVX512_CDI` to `AVX512_CD`. +//! - Changed `AVX512_ERI` to `AVX512_ER`. +//! - Changed `AVX512_PFI` to `AVX512_PF`. +//! +//! - Old names were deprecated. +//! +//! ### Changes committed at 2021-12-13 +//! +//! Core changes: +//! +//! - Removed old 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`. +//! - Setting function arguments through `Compiler::setArg()` was deprecated, use FuncNode::setArg() instead. +//! - 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 `DiagnosticOptions::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` and `DiagnosticOptions::k` (Compiler diagnostics flags). +//! - Moved `FormatOptions::kIndentation` to `FormatIndentationGroup::k`. +//! - Moved `FuncFrame::kAttr` to `FuncAttributes::k`. +//! - Moved `Globals::kReset` to `ResetPolicy::k`. +//! - Moved `InstDB::kAvx512Flag` to `InstDB::Avx512Flags::k`. +//! - Moved `InstDB::kFlag` to `InstDB::InstFlags::k`. +//! - Moved `InstDB::kMemFlag` to `InstDB::OpFlags::kMem`. +//! - Moved `InstDB::kMode` to `InstDB::Mode::k`. +//! - Moved `InstDB::kOpFlag` to `InstDB::OpFlags::k{OpType}...`. +//! - 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. +//! 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: //! -//! - \ref Imm operand has now only \ref Imm::value() and \ref Imm::valueAs() -//! functions that return its value content, and \ref Imm::setValue() function -//! that sets the content. Functions like `setI8()`, `setU8()` were deprecated. +//! - `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 \ref 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 \ref ArchRegs can be used to access such properties. +//! - `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 \ref 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 \ref Environment::isPlatformWindows(). +//! Some other functions were renamed, like `ArchInfo::isX86Family()` is now `Environment::isFamilyX86()`, etc. +//! The reason for changing the order was support for more properties 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`. +//! 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 \ref Environment. If you used -//! `CodeInfo` to set architecture and base address, this is now possible -//! with \ref Environment and setting base address explicitly by \ref -//! CodeHolder::init() - the first argument is \ref Environment, and the -//! second argument is base address, which defaults to \ref -//! Globals::kNoBaseAddress. +//! - `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. +//! CodeInfo class was deprecated, but the code using it should still compile with warnings. //! -//! - \ref CallConv has been updated to offer a more unified way of representing -//! calling conventions - many calling conventions were abstracted to follow -//! standard naming like \ref CallConv::kIdCDecl or \ref CallConv::kIdStdCall. +//! - `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 \ref FuncDetail::init() now -//! require both, calling convention and target \ref Environment. +//! This change means that other APIs like `FuncDetail::init()` now require both, calling convention and target +//! `Environment`. //! -//! - `Logging` namespace has been renamed to \ref Formatter, which now -//! provides general functionality for formatting in AsmJit. +//! - `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 please -//! make sure you don't use it. +//! 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 \ref BaseEmitter::embedDataArray(). +//! - `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: //! -//! - \ref 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. +//! - `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. //! -//! - \ref x86::Emitter (Assembler, Builder, Compiler) deprecates embed -//! utilities like `dint8()`, `duint8()`, `duint16()`, `dxmm()`, etc... -//! in favor of a new and more powerful \ref BaseEmitter::embedDataArray(). -//! This function also allows emitting repeated values and/or patterns, -//! which is used by helpers \ref BaseEmitter::embedUInt8(), and others... +//! - `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 \ref BaseEmitter::ValidationOptions, -//! which can be enabled/disabled through \ref BaseEmitter::addValidationOptions() -//! and \ref BaseEmitter::clearValidationOptions(), respectively. Validation -//! options now separate between encoding and Builder/Compiler so it's possible -//! to choose the granularity required. +//! - Validation is now available through `BaseEmitter::DiagnosticOptions`, which can be enabled/disabled through +//! `BaseEmitter::addDiagnosticOptions()` and `BaseEmitter::clearDiagnosticOptions()`, 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. +//! - 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 \ref InvokeNode. Additionally, function -//! calls should now use \ref 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()`. +//! - `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 \ref x86::Compiler::invoke() where the first -//! argument is `InvokeNode**`. The function now returns an error and would -//! call \ref 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. +//! - 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 \ref -//! ErrorHandler. +//! 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 <asmjit/x86.h> +//! //! using namespace asmjit; //! //! // The basic setup of JitRuntime and CodeHolder changed, use environment() @@ -434,59 +469,50 @@ namespace asmjit { //! // Calling a function (Compiler) changed - use invoke() instead of call(). //! void functionInvocation(x86::Compiler& cc) { //! InvokeNode* invokeNode; -//! cc.invoke(&invokeNode, targetOperand, FuncSignatureT<...>(...)); +//! cc.invoke(&invokeNode, targetOperand, FuncSignature::build<...>(...)); //! } //! ``` -// ============================================================================ -// [Documentation - asmjit_core] -// ============================================================================ //! \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: +//! 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 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. +//! - \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. +//! - \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 Type - 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 features described by \ref BaseFeatures. +//! - \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. +//! \note CodeHolder examples use \ref x86::Assembler as abstract interfaces cannot be used to generate code. //! //! ### CodeHolder & Emitters //! @@ -505,7 +531,8 @@ namespace asmjit { //! 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. +//! code.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! //! x86::Assembler a(&code); // Create and attach x86::Assembler to code. //! a.mov(x86::eax, 1); // Move one to eax register. @@ -529,8 +556,8 @@ namespace asmjit { //! } //! ``` //! -//! The example above used \ref x86::Assembler as an emitter. AsmJit provides the -//! following emitters that offer various levels of abstraction: +//! 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. @@ -538,30 +565,25 @@ namespace asmjit { //! //! ### 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. +//! 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 in 64-bit mode -//! the \ref Environment returned will use \ref Environment::kArchX64 architecture -//! in contrast to \ref Environment::kArchX86, which will be used in 32-bit mode on -//! any X86 platform. +//! 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 Environment::kArchX86. +//! 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 <asmjit/x86.h> @@ -574,7 +596,7 @@ namespace asmjit { //! //! // Create a custom environment initialized to 32-bit X86 architecture. //! Environment env; -//! env.setArch(Environment::kArchX86); +//! env.setArch(Arch::kX86); //! //! CodeHolder code; // Create a CodeHolder. //! code.init(env); // Initialize CodeHolder with custom environment. @@ -612,46 +634,37 @@ namespace asmjit { //! //! ### 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: +//! 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 <asmjit/x86.h> @@ -663,10 +676,11 @@ namespace asmjit { //! //! int main() { //! // Create a custom environment that matches the current host environment. -//! Environment env = hostEnvironment(); +//! Environment env = Environment::host(); +//! CpuFeatures cpuFeatures = CpuInfo::host().features(); //! //! CodeHolder code; // Create a CodeHolder. -//! code.init(env); // Initialize CodeHolder with environment. +//! code.init(env, cpuFeatures); // Initialize CodeHolder with environment. //! //! x86::Assembler a(&code); // Create and attach x86::Assembler to `code`. //! @@ -752,7 +766,7 @@ namespace asmjit { //! // memcpy((uint8_t*)p + section->offset(), //! // section->data(), //! // section->bufferSize()); -//! code.copyFlattenedData(p, codeSize, CodeHolder::kCopyPadSectionBuffer); +//! code.copyFlattenedData(p, codeSize, CopySectionFlags::kPadSectionBuffer); //! //! // Execute the generated function. //! int inA[4] = { 4, 3, 2, 1 }; @@ -774,37 +788,39 @@ namespace asmjit { //! } //! ``` //! -//! 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: +//! 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 <asmjit/x86.h> //! #include <stdio.h> //! +//! using namespace asmjit; +//! //! void initializeCodeHolder(CodeHolder& code) { -//! Environment env = hostEnvironment(); +//! Environment env = Environment::host(); +//! CpuFeatures cpuFeatures = CpuInfo::host().features(); //! uint64_t baseAddress = uint64_t(0x1234); //! //! // initialize CodeHolder with environment and custom base address. -//! code.init(env, baseAddress); +//! code.init(env, cpuFeatures, 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. +//! 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 <asmjit/core.h> //! #include <stdio.h> //! +//! using namespace asmjit; +//! //! void labelLinksExample(CodeHolder& code, const Label& label) { //! // Tests whether the `label` is bound. //! bool isBound = code.isLabelBound(label); @@ -819,16 +835,17 @@ namespace asmjit { //! } //! ``` //! -//! 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: +//! 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 relative to the start of the +//! section where it was bound: //! //! ``` //! #include <asmjit/core.h> //! #include <stdio.h> //! +//! 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 @@ -848,15 +865,16 @@ namespace asmjit { //! //! ### 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: +//! 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 <asmjit/x86.h> //! #include <stdio.h> //! +//! using namespace asmjit; +//! //! void sectionsExample(CodeHolder& code) { //! // Text section is always provided as the first section. //! Section* text = code.textSection(); // or code.sectionById(0); @@ -864,10 +882,11 @@ namespace asmjit { //! // 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). -//! 0, // Section flags, see Section::Flags. -//! 8); // Section alignment, must be power of 2. +//! ".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 @@ -892,17 +911,17 @@ namespace asmjit { //! } //! ``` //! -//! 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. +//! 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 <asmjit/x86.h> //! #include <stdio.h> //! +//! using namespace asmjit; +//! //! // ... (continuing the previous example) ... //! void sectionsExampleContinued(CodeHolder& code) { //! // Suppose we have some code that contains multiple sections and @@ -931,105 +950,86 @@ namespace asmjit { //! //! if (code.hasUnresolvedLinks()) { //! // This would mean either unbound label or some other issue. -//! printf("The code has %zu unbound labels\n", code.unresovedLinkCount()); +//! printf("The code has %zu unbound labels\n", code.unresolvedLinkCount()); //! exit(1); //! } //! } //! ``` -// ============================================================================ -// [Documentation - asmjit_assembler] -// ============================================================================ //! \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: +//! 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 x86::Assembler - Assembler implementation targeting X86 and X86_64 architectures. +//! - \ref a64::Assembler - Assembler implementation targeting AArch64 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 x86::Reg - Register operand specific to X86 and X86_64 architectures. +//! - \ref arm::Reg - Register operand specific to AArch64 architecture. //! - \ref BaseMem - Base class for a memory operand, inherited by: //! - \ref x86::Mem - Memory operand specific to X86 architecture. +//! - \ref arm::Mem - Memory operand specific to AArch64 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. +//! \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 +//! 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 - Unique id that describes each possible register provided -//! by the target architecture - for example X86 backend provides \ref -//! x86::Reg::RegType, which defines all variations of general purpose registers -//! (GPB-LO, GPB-HI, GPW, GPD, and GPQ) and all types of other registers like K, -//! MM, BND, XMM, YMM, and ZMM. -//! - Register Group - Groups multiple register types under a single group - for -//! example all general-purpose registers (of all sizes) on X86 are part of -//! \ref x86::Reg::kGroupGp and all SIMD registers (XMM, YMM, ZMM) are part -//! of \ref x86::Reg::kGroupVec. -//! - 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 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. +//! - 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. +//! 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. +//! 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 <asmjit/x86.h> @@ -1049,7 +1049,7 @@ namespace asmjit { //! // Constructs [src + idx] memory address - referencing [rax + r10]. //! x86::Mem m = x86::ptr(src, idx); //! -//! // Examine `m`: Returns `x86::Reg::kTypeGpq`. +//! // Examine `m`: Returns `RegType::kX86_Gpq`. //! m.indexType(); //! // Examine `m`: Returns 10 (`r10`). //! m.indexId(); @@ -1082,28 +1082,25 @@ namespace asmjit { //! //! // Type-unsafe, but possible. //! a.emit(x86::Inst::kIdMov, dst, m); -//! // Also possible, `emit()` is typeless and can be used with raw Operand. +//! // Also possible, `emit()` is type-less 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. +//! 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. +//! 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. +//! 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 <asmjit/x86.h> @@ -1128,7 +1125,7 @@ namespace asmjit { //! Mem g = ptr(rax, xmm1, 2); // g = [rax + xmm1 << 2] //! Mem h = ptr(rax, xmm1, 2, 15); // h = [rax + xmm1 << 2 + 15] //! -//! // Absolute adddress: +//! // Absolute address: //! uint64_t addr = (uint64_t)0x1234; //! Mem i = ptr(addr); // i = [0x1234] //! Mem j = ptr(addr, rbx); // j = [0x1234 + rbx] @@ -1146,9 +1143,8 @@ namespace asmjit { //! } //! ``` //! -//! 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: +//! 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 <asmjit/x86.h> @@ -1157,10 +1153,10 @@ namespace asmjit { //! //! void testX86Mem() { //! // The same as: dword ptr [rax + rbx]. -//! x86::Mem a = x86::dword_ptr(rax, rbx); +//! x86::Mem a = x86::dword_ptr(x86::rax, x86::rbx); //! //! // The same as: qword ptr [rdx + rsi << 0 + 1]. -//! x86::Mem b = x86::qword_ptr(rdx, rsi, 0, 1); +//! x86::Mem b = x86::qword_ptr(x86::rdx, x86::rsi, 0, 1); //! } //! ``` //! @@ -1173,18 +1169,18 @@ namespace asmjit { //! //! void testX86Mem() { //! // The same as: dword ptr [rax + 12]. -//! x86::Mem mem = x86::dword_ptr(rax, 12); +//! x86::Mem mem = x86::dword_ptr(x86::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.setSize(0); // Sets the size to 0 (makes it size-less). //! 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.setBase(x86::rcx); // Changes BASE to RCX. +//! mem.setIndex(x86::rax); // Changes INDEX to RAX. //! mem.hasIndex(); // true. //! } //! // ... @@ -1232,34 +1228,26 @@ namespace asmjit { //! //! - \ref x86::Assembler provides many X86/X64 examples. -// ============================================================================ -// [Documentation - asmjit_builder] -// ============================================================================ //! \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, +//! 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. +//! \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 : //! @@ -1272,199 +1260,165 @@ namespace asmjit { //! - 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 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. +//! - \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. +//! - \ref x86::Builder - Builder implementation targeting X86 and X86_64 architectures. +//! - \ref a64::Builder - Builder implementation targeting AArch64 architecture. -// ============================================================================ -// [Documentation - asmjit_compiler] -// ============================================================================ //! \defgroup asmjit_compiler Compiler //! \brief Compiler interface. //! //! ### Overview //! -//! \ref BaseCompiler is a high-level interface built on top of \ref BaseBuilder -//! interface, which provides register allocation and support for defining and -//! invoking functions. 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 that \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. +//! \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 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. +//! \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. +//! - \ref x86::Compiler - Compiler implementation targeting X86 and X86_64 architectures. +//! - \ref a64::Compiler - Compiler implementation targeting AArch64 architecture. //! //! ### Compiler Tips //! -//! Users of AsmJit have done mistakes in the past, this section should provide -//! some useful tips for beginners: +//! 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. +//! - 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 FormatOptions::Flags. Use \ref Logger::addFlags() to -//! turn on additional logging features when using Compiler. +//! - 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. -// ============================================================================ -// [Documentation - asmjit_function] -// ============================================================================ //! \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: +//! 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 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. +//! - 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 Type::Id - 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 Type::Id 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 Type::Id 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 Type::Id 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 +//! - \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. +//! 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. -// ============================================================================ -// [Documentation - asmjit_logging] -// ============================================================================ //! \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 as -//! a whole. Logging has always been an important part of AsmJit's infrastructure and -//! looking at logs can sometimes reveal code generation issues quickly. +//! 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. +//! +//! - \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 -//! inplementations are provided for simplicty: +//! +//! - Abstract class leaving the implementation on users. The following built-in implementations are provided for +//! simplicity: +//! //! - \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 FormatOptions::Flags -//! - \ref FormatOptions::IndentationType +//! 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: +//! 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 <asmjit/core.h> @@ -1477,7 +1431,8 @@ namespace asmjit { //! 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.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! code.setLogger(&logger); // Attach the `logger` to `code` holder. //! //! // ... code as usual, everything emitted will be logged to `stdout` ... @@ -1485,8 +1440,8 @@ namespace asmjit { //! } //! ``` //! -//! If output to FILE stream is not desired it's possible to use \ref StringLogger, -//! which concatenates everything into a multi-line string: +//! If output to FILE stream is not desired it's possible to use \ref StringLogger, which concatenates everything +//! into a multi-line string: //! //! ``` //! #include <asmjit/core.h> @@ -1500,7 +1455,8 @@ namespace asmjit { //! 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.init(rt.environment(), // Initialize code to match the JIT environment. +//! rt.cpuFeatures()); //! code.setLogger(&logger); // Attach the `logger` to `code` holder. //! //! // ... code as usual, logging will be concatenated to logger string ... @@ -1519,26 +1475,25 @@ namespace asmjit { //! //! ### 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. +//! 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 <asmjit/core.h> +//! #include <asmjit/x86.h> //! #include <stdio.h> //! //! using namespace asmjit; //! -//! void logOperand(uint32_t arch, const Operand_& op) { +//! 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. -//! uint32_t formatFlags = FormatOptions::kNoFlags; +//! FormatFlags formatFlags = FormatFlags::kNone; //! //! StringTmp<128> sb; //! Formatter::formatOperand(sb, formatFlags, emitter, arch, op); @@ -1551,34 +1506,34 @@ namespace asmjit { //! // 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. -//! uint32_t arch = Environment::kArchX64; +//! 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'. +//! logOperand(arch, rax); // Prints 'rax'. +//! logOperand(arch, ptr(rax, rbx, 2)); // Prints '[rax + rbx * 4]`. +//! logOperand(arch, dword_ptr(rax, rbx, 2)); // Prints 'dword [rax + rbx * 4]`. +//! logOperand(arch, imm(42)); // Prints '42'. //! } //! ``` //! //! Next example illustrates how to format whole instructions: //! //! ``` -//! #include <asmjit/core.h> +//! #include <asmjit/x86.h> //! #include <stdio.h> //! #include <utility> //! //! using namespace asmjit; //! //! template<typename... Args> -//! void logInstruction(uint32_t arch, const BaseInst& inst, Args&&... args) { +//! 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. -//! uint32_t formatFlags = FormatOptions::kNoFlags; +//! FormatFlags formatFlags = FormatFlags::kNone; //! //! // The formatter expects operands in an array. -//! Operand_ operands { std::forward<Args>(args)... }; +//! Operand_ operands[] { std::forward<Args>(args)... }; //! //! StringTmp<128> sb; //! Formatter::formatInstruction( @@ -1592,7 +1547,7 @@ namespace asmjit { //! // 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. -//! uint32_t arch = Environment::kArchX64; +//! Arch arch = Arch::kX64; //! //! // Prints 'mov rax, rcx'. //! logInstruction(arch, BaseInst(Inst::kIdMov), rax, rcx); @@ -1600,24 +1555,24 @@ namespace asmjit { //! // Prints 'vaddpd zmm0, zmm1, [rax] {1to8}'. //! logInstruction(arch, //! BaseInst(Inst::kIdVaddpd), -//! zmm0, zmm1, ptr(rax)._1toN()); +//! zmm0, zmm1, ptr(rax)._1to8()); //! //! // BaseInst abstracts instruction id, instruction options, and extraReg. //! // Prints 'lock add [rax], rcx'. //! logInstruction(arch, -//! BaseInst(Inst::kIdAdd, Inst::kOptionLock), -//! x86::ptr(rax), rcx); +//! BaseInst(Inst::kIdAdd, InstOptions::kX86_Lock), +//! 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, Inst::kOptionZMask, k2), +//! 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: +//! 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 <asmjit/core.h> @@ -1626,7 +1581,7 @@ namespace asmjit { //! using namespace asmjit; //! //! void formattingExample(BaseBuilder* builder) { -//! uint32_t formatFlags = FormatOptions::kNoFlags; +//! FormatOptions formatOptions {}; //! //! // This also shows how temporary strings can be used. //! StringTmp<512> sb; @@ -1635,7 +1590,7 @@ namespace asmjit { //! // 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); +//! Formatter::formatNodeList(sb, formatOptions, builder); //! //! // You can do whatever else with the string, it's always null terminated, //! // so it can be passed to C functions like printf(). @@ -1643,40 +1598,30 @@ namespace asmjit { //! } //! ``` -// ============================================================================ -// [Documentation - asmjit_error_handling] -// ============================================================================ //! \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`. +//! 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 +//! Errors should never be ignored, however, checking errors after each AsmJit API call would simply over-complicate +//! 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. +//! - 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 //! @@ -1702,7 +1647,7 @@ namespace asmjit { //! MyErrorHandler myErrorHandler; //! CodeHolder code; //! -//! code.init(rt.environment()); +//! code.init(rt.environment(), rt.cpuFeatures()); //! code.setErrorHandler(&myErrorHandler); //! //! x86::Assembler a(&code); @@ -1718,123 +1663,142 @@ namespace asmjit { //! - See \ref Error that lists error codes that AsmJit uses. //! - See \ref ErrorHandler for more details about error handling. -// ============================================================================ -// [Documentation - asmjit_instruction_db] -// ============================================================================ //! \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: +//! 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 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. -//! - \ref OpRWInfo - Read/write information of a single operand, part of -//! \ref InstRWInfo data structure. -//! - \ref BaseFeatures - CPU features required to execute the instruction. +//! - \ref InstRWInfo - Read/write information of instruction and its operands (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 +//! 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: +//! 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::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. +//! - \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. //! -//! - <a href="https://github.com/asmjit/asmjit/blob/master/test/asmjit_test_x86_instinfo.cpp">asmjit_test_x86_instinfo.cpp</a> +//! - <a href="https://github.com/asmjit/asmjit/blob/master/test/asmjit_test_instinfo.cpp">asmjit_test_instinfo.cpp</a> //! 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: +//! 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 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 BaseEmitter::ValidationOptions. +//! - \ref BaseEmitter::addDiagnosticOptions() - can be used to enable validation at emitter level, see \ref +//! DiagnosticOptions. -// ============================================================================ -// [Documentation - asmjit_virtual_memory] -// ============================================================================ - //! \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. +//! AsmJit's virtual memory management is divided into three main categories: +//! +//! - Low level interface that provides cross-platform abstractions for virtual memory allocation. Implemented in +//! \ref VirtMem namespace. This API is a thin wrapper around operating system specific calls such as +//! `VirtualAlloc()` and `mmap()` and it's intended to be used by AsmJit's higher level API. Low-level virtual +//! memory functions can be used to allocate virtual memory, change its permissions, and to release it. +//! Additionally, an API that allows to create dual mapping (to support hardened environments) is provided. +//! +//! - Middle level API that is provided by \ref JitAllocator, which uses \ref VirtMem internally and offers nicer +//! API that can be used by users to allocate executable memory conveniently. \ref JitAllocator tries to be smart, +//! for example automatically using dual mapping or `MAP_JIT` on hardened environments. +//! +//! - High level API that is provided by \ref JitRuntime, which implements \ref Target interface and uses \ref +//! JitAllocator under the hood. Since \ref JitRuntime inherits from \ref Target it makes it easy to use with +//! \ref CodeHolder. Many AsmJit examples use \ref JitRuntime for its simplicity and easy integration. +//! +//! The main difference between \ref VirtMem and \ref JitAllocator is that \ref VirtMem can only be used to allocate +//! whole pages, whereas \ref JitAllocator has `malloc()` like API that allows to allocate smaller quantities that +//! usually represent the size of an assembled function or a chunk of functions that can represent a module, for +//! example. \ref JitAllocator then tracks used space of each page it maintains. Internally, \ref JitAllocator uses +//! two bit arrays to track occupied regions in each allocated block of pages. +//! +//! ### Hardened Environments +//! +//! In the past, allocating virtual memory with Read+Write+Execute (RWX) access permissions was easy. However, modern +//! operating systems and runtime environments often use hardening, which typically prohibits mapping pages with both +//! Write and Execute permissions (known as the W^X policy). This presents a challenge for JIT compilers because +//! generated code for a single function is unlikely to fit in exactly N pages without leaving some space empty. To +//! accommodate this, the execution environment may need to temporarily change the permissions of existing pages to +//! read+write (RW) to insert new code into them, however, sometimes it's not possible to ensure that no thread is +//! executing code in such affected pages in a multithreaded environment, in which multiple threads may be executing +//! generated code. +//! +//! Such restrictions leave a lot of complexity on the application, so AsmJit implements a dual mapping technique to +//! make the life of AsmJit users easier. In this technique, a region of memory is mapped to two different virtual +//! addresses with different access permissions. One virtual address is mapped with read and write (RW) access, which +//! is used by the JIT compiler to write generated code. The other virtual address is mapped with read and execute (RX) +//! access, which is used by the application to execute the generated code. +//! +//! However, implementing dual mapping can be challenging because it typically requires obtaining an anonymous file +//! descriptor on most Unix-like operating systems. This file descriptor is then passed to mmap() twice to create +//! the two mappings. AsmJit handles this challenge by using system-specific techniques such as `memfd_create()` on +//! Linux, `shm_open(SHM_ANON)` on BSD, and `MAP_REMAPDUP` with `mremap()` on NetBSD. The latter approach does not +//! require a file descriptor. If none of these options are available, AsmJit uses a plain `open()` call followed by +//! `unlink()`. +//! +//! The most challenging part is actually obtaining a file descriptor that can be passed to `mmap()` with `PROT_EXEC`. +//! This is still something that may fail, for example the environment could be hardened in a way that this would +//! not be possible at all, and thus dual mapping would not work. +//! +//! Dual mapping is provided by both \ref VirtMem and \ref JitAllocator. -// ============================================================================ -// [Documentation - asmjit_zone_memory] -// ============================================================================ //! \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. +//! 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 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 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. +//! - \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 //! @@ -1848,11 +1812,10 @@ namespace asmjit { //! //! ### 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 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: //! @@ -1874,10 +1837,9 @@ namespace asmjit { //! } //! ``` //! -//! \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: +//! \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; @@ -1894,15 +1856,13 @@ namespace asmjit { //! //! ### 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 +//! 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. +//! 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 @@ -1926,10 +1886,9 @@ namespace asmjit { //! } //! ``` //! -//! 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. +//! 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 @@ -1947,48 +1906,46 @@ namespace asmjit { //! } //! ``` -// ============================================================================ -// [Documentation - asmjit_utilities] -// ============================================================================ //! \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: +//! 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 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. +//! - \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. +//! - \ref Support namespace provides many other utility functions and classes that are used by AsmJit, and made +//! public. -// ============================================================================ -// [Documentation - asmjit_<arch> backends] -// ============================================================================ //! \defgroup asmjit_x86 X86 Backend //! \brief X86/X64 backend. -// ============================================================================ -// [Documentation - asmjit_ra] -// ============================================================================ + +//! \defgroup asmjit_arm ARM Commons +//! \brief ARM commons shared between AArch32 and AArch64. + + +//! \defgroup asmjit_a64 AArch64 Backend +//! \brief AArch64 backend. + //! \cond INTERNAL //! \defgroup asmjit_ra RA @@ -1997,63 +1954,38 @@ namespace asmjit { } // {asmjit} -// ============================================================================ -// [Core Headers] -// ============================================================================ - -#include "./core/globals.h" - -#include "./core/arch.h" -#include "./core/assembler.h" -#include "./core/builder.h" -#include "./core/callconv.h" -#include "./core/codeholder.h" -#include "./core/compiler.h" -#include "./core/constpool.h" -#include "./core/cpuinfo.h" -#include "./core/datatypes.h" -#include "./core/emitter.h" -#include "./core/environment.h" -#include "./core/errorhandler.h" -#include "./core/features.h" -#include "./core/formatter.h" -#include "./core/func.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" - -// ============================================================================ -// [Deprecated] -// ============================================================================ - -#ifndef ASMJIT_NO_DEPRECATED -namespace asmjit { - -#ifndef ASMJIT_NO_COMPILER -ASMJIT_DEPRECATED("Use InvokeNode instead of FuncCallNode") -typedef InvokeNode FuncCallNode; -#endif // !ASMJIT_NO_COMPILER - -#ifndef ASMJIT_NO_LOGGING -namespace Logging { using namespace Formatter; } -#endif //! ASMJIT_NO_LOGGING - -} // {asmjit} -#endif // !ASMJIT_NO_DEPRECATED +#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 |