// This file is part of AsmJit project <https://asmjit.com>
//
// SPDX-License-Identifier: Zlib
// Official GitHub Repository: https://github.com/asmjit/asmjit
//
// Copyright (c) 2008-2025 The AsmJit Authors
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
//    claim that you wrote the original software. If you use this software
//    in a product, an acknowledgment in the product documentation would be
//    appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
//    misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.

#ifndef ASMJIT_CORE_H_INCLUDED
#define ASMJIT_CORE_H_INCLUDED

//! Root namespace used by AsmJit.
namespace asmjit {

//! \mainpage API Reference
//!
//! AsmJit C++ API reference documentation generated by Doxygen.
//!
//! AsmJit library uses one global namespace called \ref asmjit, which provides the whole functionality. Core
//! functionality is within \ref asmjit namespace and architecture specific functionality is always in its own
//! namespace. For example \ref asmjit::x86 provides both 32-bit and 64-bit X86 code generation.
//!
//! \section doc_groups Documentation Groups
//!
//! AsmJit documentation is structured into groups. Groups can be followed in order to learn AsmJit, but knowledge
//! from multiple groups is required to use AsmJit properly:
//!
//! $$DOCS_GROUP_OVERVIEW$$
//!
//! \note It's important to understand that in order to learn AsmJit all groups are important. Some groups can be
//! omitted if a particular tool is out of interest - for example \ref asmjit_assembler users don't need to know
//! about \ref asmjit_builder, but it's not the opposite. \ref asmjit_builder users 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:
//!
//!   - \ref CodeHolder provides functionality to temporarily hold the generated code. It stores all the necessary
//!     information about the code - code buffers, sections, labels, symbols, and information about relocations.
//!
//!   - \ref BaseEmitter provides interface used by emitter implementations. The interface provides basic building
//!     blocks that are then implemented by \ref BaseAssembler, \ref BaseBuilder, and \ref BaseCompiler.
//!
//! Code emitters:
//!
//!  - \ref asmjit_assembler - provides direct machine code generation.
//!
//!  - \ref asmjit_builder - provides intermediate code generation that can be processed before it's serialized to
//!    \ref BaseAssembler.
//!
//!  - \ref asmjit_compiler - provides high-level code generation with built-in register allocation.
//!
//!  - \ref FuncNode - provides insight into how function looks from the Compiler perspective and how it's stored in
//!     a node-list.
//!
//! \section main_recommendations Recommendations
//!
//! The following steps are recommended for all AsmJit users:
//!
//!   - Make sure that you use \ref Logger, see \ref asmjit_logging.
//!
//!   - Make sure that you use \ref ErrorHandler, see \ref asmjit_error_handling.
//!
//!   - Instruction validation in your debug builds can reveal problems too. AsmJit provides validation at instruction
//!     level that can be enabled via \ref BaseEmitter::add_diagnostic_options(). See \ref DiagnosticOptions 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::add_diagnostic_options(). If unsure which ones to use,
//!     enable annotations and all debug options: `DiagnosticOptions::kRAAnnotate | DiagnosticOptions::kRADebugAll`.
//!
//!   - Make sure you put a breakpoint into \ref make_error() 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 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 other_pages 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


//! \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.
//!
//! \section supported_environment Supported Operating Systems, Compilers, and Build Tools
//!
//! ### Supported C++ Compilers
//!
//!   - Requirements:
//!
//!     - AsmJit won't build without C++17 enabled. If you use older GCC or Clang you would have to enable at least
//!       C++17 standard through compiler flags.
//!
//!   - Tested:
//!
//!     - **Clang** - Tested by GitHub Actions - Clang 14+ is officially supported and tested by CI, older Clang versions
//!       having C++17 should work, but these versions are not tested anymore due to upgraded CI images.
//!
//!     - **GNU** - Tested by GitHub Actions - GCC 9+ is officially supported and tested by CI, older GCC versions such
//!       as GCC 7 should work, but these versions are not tested anymore due to upgraded CI images.
//!
//!     - **MINGW** - Reported to work, but not tested in our CI environment (help welcome!).
//!
//!     - **MSVC** - Tested by GitHub Actions - VS2022 and onwards are officially supported and tested by CI, VS2015,
//!       VS2017, and VS2019 are not tested anymore due to upgraded CI images. VS2019 should work well.
//!
//! ### Supported Operating Systems and Platforms
//!
//!   - Tested:
//!
//!     - **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. Both X86_64 and AArch64 host builds are tested.
//!
//!     - **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). Linux tests X86, X86_64, and AArch64 host builds.
//!
//!     - **Mac OS** - Tested by GitHub Actions.
//!
//!     - **Windows** - Tested by GitHub Actions - (Windows 7+ is officially supported).
//!
//!     - **Emscripten** - Works if compiled with \ref ASMJIT_NO_JIT. AsmJit cannot generate WASM code, but can be
//!       used to generate X86/X64/AArch64 code within a browser, for example.
//!
//!   - Untested:
//!
//!     - **Haiku** - Reported to work, not tested by CI.
//!
//!     - **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** and **X86_64** - Both 32-bit and 64-bit backends tested on CI.
//!   - **AArch64** - Tested on CI (Native Apple runners and Linux emulated via QEMU).
//!
//! \section build_mode Static Builds and Embedding
//!
//! These definitions can be used to enable static library build. Embed is used when AsmJit's source code is embedded
//! directly in another project, implies static build as well.
//!
//!   - \ref ASMJIT_EMBED - Asmjit is embedded, implies \ref ASMJIT_STATIC.
//!   - \ref ASMJIT_STATIC - Enable static-library build.
//!
//! \note Projects that use AsmJit statically must define \ref ASMJIT_STATIC in all compilation units that use AsmJit,
//! otherwise AsmJit would use dynamic library imports in \ref ASMJIT_API decorator. The recommendation is to define
//! this macro across the whole project that uses AsmJit this way.
//!
//! \section cmake_integration CMake Integration
//!
//! AsmJit has a first-class CMake support. When consuming AsmJit as a cmake dependency, just use `asmjit::asmjit`
//! as a link dependency, which would instrument cmake to setup everything else, including include paths, and build
//! flags (either defining `ASMJIT_STATIC` or not, and possibly defining other AsmJit feature macros). For example
//! considering that AsmJit was fetched to `3rdparty/asmjit` directory in your project as an external dependency,
//! you can just use the following CMake snippet that integrates AsmJit with your own CMake project:
//!
//! ```cmake
//! cmake_minimum_required(VERSION 3.30 FATAL_ERROR)
//! project(app C CXX)
//!
//! set(ASMJIT_DIR "3rdparty/asmjit")              # Location of AsmJit.
//! set(ASMJIT_STATIC TRUE)                        # Force static build.
//! add_subdirectory("${ASMJIT_DIR}")              # Adds AsmJit sub-project to your project.
//!
//! add_executable(app asmjit_consumer.cpp)        # Adds executable that uses AsmJit.
//! target_link_libraries(app asmjit::asmjit)      # Adds AsmJit as a dependency to app.
//! target_compile_features(app PUBLIC cxx_std_17) # Makes C++17 as a requirement.
//! ```
//!
//! \section build_type Build Type Configuration
//!
//! These definitions control whether asserts are active or not. By default AsmJit would autodetect build configuration
//! from existing pre-processor definitions, but this behavior can be overridden, for example to enable debug asserts
//! in release configuration.
//!
//!   - \ref ASMJIT_BUILD_DEBUG - Overrides build configuration to debug, asserts will be enabled in this case.
//!   - \ref ASMJIT_BUILD_RELEASE - Overrides build configuration to release, asserts will be disabled in this case.
//!
//! \note There is usually no need to override the build configuration. AsmJit detects the build configuration by
//! checking whether `NDEBUG` is defined and automatically defines \ref ASMJIT_BUILD_RELEASE if configuration overrides
//! were not used. We only recommend using build configuration overrides in special situations, like using AsmJit in
//! release configuration with asserts enabled for whatever reason.
//!
//! \section build_backends AsmJit Backends
//!
//! All backends AsmJit supports are included by default. To exclude a backend use the following build-type macros:
//!
//!   - \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.
//!     For example if your target is X86, `ASMJIT_NO_FOREIGN` would disable every backend but X86.
//!
//! \section build_options Build 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,
//!     enumerations, and functions.
//!
//!   - \ref ASMJIT_NO_SHM_OPEN - Disables functionality that uses `shm_open()`.
//!
//!   - \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.
//!
//! \section build_features Build Features
//!
//! AsmJit builds by default 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_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_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_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.


//! \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.
//!
//! \section api_changes API Changes
//!
//! ### Changes committed at 2025-09-06
//!
//! Core changes:
//!
//!   - Refactored AsmJit to use snake_case_function_names() instead of camelCasedFunctionNames().
//!
//!   - Renamed Compiler's `newIntPtr()` and `newUIntPtr()` to `new_gp_ptr()`, or you should use just `new_gpz()`.
//!
//!   - Renamed Zone to Arena (including containers) and merged Arena and ArenaAllocator into a single class.
//!
//!   - Removed `Support::Temporary` in favor of `Span<uint8_t>`. `CodeHolder` and `Arena` now accept
//!     `Span<uint8_t>` instead of `Support::Temporary`.
//!
//! ### Changes committed at 2025-06-15
//!
//! Core changes:
//!
//!   - No more architecture specific \ref RegTraits - removed `BaseRegTraits` and kept just RegTraits:
//!
//!     - `BaseRegTraits` -> `RegTraits`
//!     - `arm::RegTraits` -> `RegTraits`
//!     - `x86::RegTraits` -> `RegTraits`
//!
//!   - Removed register signature and helper functions from ArchTraits. This functionality is now available
//!     via asmjit::RegTraits and asmjit::RegUtils and doesn't require a valid architecture traits instance.
//!
//!   - No more architecture specific Gp/Vec/Mask register types in RegType and RegGroup:
//!
//!     - `RegGroup::kX86_Rip`  -> `RegGroup::kPC`
//!     - `RegGroup::kX86_KReg` -> `RegGroup::kMask`
//!     - `RegType::kX86_GpbLo` -> `RegType::kGp8Lo`
//!     - `RegType::kX86_GpbLo` -> `RegType::kGp8Lo`
//!     - `RegType::kX86_GpbHi` -> `RegType::kGp8Hi`
//!     - `RegType::kX86_Gpw`   -> `RegType::kGp16`
//!     - `RegType::kX86_Gpd`   -> `RegType::kGp32`
//!     - `RegType::kX86_Gpq`   -> `RegType::kGp64`
//!     - `RegType::kX86_Xmm`   -> `RegType::kVec128`
//!     - `RegType::kX86_Ymm`   -> `RegType::kVec256`
//!     - `RegType::kX86_Zmm`   -> `RegType::kVec512`
//!     - `RegType::kX86_KReg`  -> `RegType::kMask`
//!     - `RegType::kARM_PC`    -> `RegType::kPC`
//!     - `RegType::kARM_GpW`   -> `RegType::kGp32`
//!     - `RegType::kARM_GpX`   -> `RegType::kGp64`
//!     - `RegType::kARM_VecB`  -> `RegType::kVec8`
//!     - `RegType::kARM_VecH`  -> `RegType::kVec16`
//!     - `RegType::kARM_VecS`  -> `RegType::kVec32`
//!     - `RegType::kARM_VecD`  -> `RegType::kVec64`
//!     - `RegType::kARM_VecQ`  -> `RegType::kVec128`
//!     - `RegType::kARM_VecV`  -> `RegType::kVec128`
//!
//!   - Renamed `asmjit::BaseReg` to asmjit::Reg, added `asmjit::UniGp` and `asmjit::UniVec` which are now base
//!     classes for platform specific `[x86|a64]::Gp` and `[x86|a64]::Vec`
//!
//!   - Gp and Vec register API is now more platform independent - use `isGp32()` instead of `isGpd()`, similarly,
//!     use `isGp64` instead of `isGpq()` (X86_64) or `isGpX()` (AArch64), etc... The same applies to vectors -
//!     use `isVec128()` instead of `isXmm()` (X86) or `isVecQ()` (AArch64), `isVec256()` instead of `isYmm()`,
//!     etc...
//!
//!   - Renamed some member functions in Operand and Reg:
//!
//!     - `isType(regId)` -> `isReg(regId)`
//!     - `isGroup(regGroup)` -> `isReg(regGroup)`
//!     - `regOp.type()` -> `regOp.regType()`
//!     - `regOp.group()` -> `regOp.regGroup()`
//!
//!   - Removed some static functions from \ref Operand, \ref Reg, etc... in favor of member functions. Most
//!     of the operand functionality is now provided by \ref Operand_ class:
//!
//!     - `Operand::isGp(op)` -> op.isGp();
//!     - `x86::Reg::isGp(op, id)` -> op.isGp(id);
//!
//!   - Removed sub-registers `x86::Gpb`, `x86::GpbLo`, `x86::GpbHi`, `x86::Gpw`, `x86::Gpd`, `x86::Gpq`, `x86::Xmm`,
//!     `x86::Ymm`, `x86::Zmm` - use just `x86::Gp` and `x86::Vec`, which represent all removed X86 sub-registers.
//!     From now, use `x86::Gp` to work with x86 general purpose registers and `x86::Vec` to work with XMM, YMM,
//!     and ZMM registers.
//!
//!   - Removed sub-registers `a64::GpW` and `a64::GpX`, `a64::VecB`, `a64::VecH`, `a64::VecS`, `a64::VecD`,
//!     `a64::VecV`, which represent all removed AArch64 sub-registers. From now, use `a64::Gp` to work with
//!     general purpose registers and `a64::Vec` to work with NEON registers of any size, element type, and
//!     element index.
//!
//!   - Since sub-register types are gone it's no longer possible to write `gpb(id)` to get AL register, etc...
//!     However, all register operands that can hold multiple register types now offer `Reg::make_xxx(id)` API,
//!     which can be used as a convenience or just use platform specific API like `x86::gpd(id)` or `x86::gp32(id)`,
//!     similarly for AArch64 use `a64::x(id)` or `a64::gp64(id)`, etc...
//!
//!   - Renamed some id getters - `Section::id()` -> `Section::sectionId()`, etc...
//!
//! Builder changes:
//!
//!   - Removed BaseBuilder::deletePass() - this function was most likely never used by user code and it was also
//!     never used by AsmJit. Passes should be only added and not removed, which simplifies some planned future
//!     changes.
//!
//! ### Changes committed at 2025-05-24
//!
//! Core changes:
//!
//!   - AsmJit now requires C++17 to compile.
//!
//!   - Deprecated asmjit/asmjit.h header. Use asmjit/core.h to include everything except backend specific stuff,
//!     and asmjit/x86.h or asmjit/a64.h to include tools of a specific architecture. At this time the asmjit.h
//!     header is just deprecated, so it will still work as it used to for some time.
//!
//! ### Changes committed at 2025-05-10
//!
//! Core changes:
//!
//!   - Removed AVX512 functionality that was never used on x86 hardware as Xeon Phi was never supported by AsmJit:
//!
//!     - AVX512_ER
//!     - AVX512_PF
//!     - AVX512_4FMAPS
//!     - AVX512_4VNNIW
//!
//!   - Instruction 'vcvtneps2bf16' no longer accepts memory operand without explicit size (to minimize ambiguity)
//!
//! ### 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.
//!
//!   - 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.
//!
//! Core changes:
//!
//!   - `Imm` operand has now only `Imm::value()` and `Imm::valueAs()` functions that return its value content,
//!     and `Imm::setValue()` function that sets the content. Functions like `setI8()`, `setU8()` were deprecated.
//!
//!     Old functions were deprecated, but code using them should still compile.
//!
//!   - `ArchInfo` has been replaced with `Environment`. Environment provides more details about the architecture,
//!     but drops some properties that were used by arch info - `gpSize(`) and `gpCount()`. `gpSize()` can be replaced
//!     with `registerSize()` getter, which returns a native register size of the architecture the environment uses.
//!     However, `gpCount()` was removed - at the moment `ArchTraits` can be used to access such properties.
//!
//!     Some other functions were renamed, like `ArchInfo::isX86Family()` is now `Environment::isFamilyX86()`, etc.
//!     The reason for changing the order was support for more 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`.
//!
//!     Some functions were deprecated, some removed...
//!
//!   - `CodeInfo` has been removed in favor of `Environment`. If you used `CodeInfo` to set architecture and base
//!     address, this is now possible with `Environment` and setting base address explicitly by `CodeHolder::init()`
//!     - the first argument is `Environment`, and the second argument is base address, which defaults to
//!     `Globals::kNoBaseAddress`.
//!
//!     CodeInfo class was deprecated, but the code using it should still compile with warnings.
//!
//!   - `CallConv` has been updated to offer a more unified way of representing calling conventions - many calling
//!     conventions were abstracted to follow standard naming like `CallConvId::kCDecl` or `CallConvId::kStdCall`.
//!
//!     This change means that other APIs like `FuncDetail::init()` now require both, calling convention and target
//!     `Environment`.
//!
//!   - `Logging` namespace has been renamed to `Formatter`, which now provides general functionality for formatting
//!     in AsmJit.
//!
//!     Logging namespace should still work, but its use is deprecated. Unfortunately this will be without deprecation
//!     warnings, so make sure you don't use it.
//!
//!   - `Data64`, `Data128`, and `Data256` structs were deprecated and should no longer be used. There is no replacement,
//!     AsmJit users should simply create their own structures if they need them or use the new repeated embed API in
//!     emitters, see `BaseEmitter::embedDataArray()`.
//!
//! Emitter changes:
//!
//!   - `BaseEmitter::emit()` function signature has been changed to accept 3 operands by reference and the rest 3
//!     operands as a continuous array. This change is purely cosmetic and shouldn't affect users as emit() has many
//!     overloads that dispatch to the right function.
//!
//!   - `x86::Emitter` (Assembler, Builder, Compiler) deprecates embed utilities like `dint8()`, `duint8()`, `duint16()`,
//!     `dxmm()`, etc... in favor of a new and more powerful `BaseEmitter::embedDataArray()`. This function also allows
//!     emitting repeated values and/or patterns, which is used by helpers `BaseEmitter::embedUInt8()`, and others...
//!
//!   - Validation is now available through `BaseEmitter::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.
//!
//! Compiler changes:
//!
//!   - `FuncCallNode` has been renamed to `InvokeNode`. Additionally, function calls should now use
//!     `x86::Compiler::invoke()` instead of `call()`. The reason behind this is to remove the confusion between a
//!     `call` instruction and AsmJit's `call()` intrinsic, which is now `invoke()`.
//!
//!   - Creating new nodes also changed. Now the preferred way of invoking a function is to call
//!     `x86::Compiler::invoke()` where the first argument is `InvokeNode**`. The function now returns an error and
//!     would call `ErrorHandler` in case of a failure. Error handling was unspecified in the past - the function was
//!     marked noexcept, but called error handler, which could throw.
//!
//!     The reason behind this change is to make the API consistent with other changes and to also make it possible
//!     to inspect the possible error. In  the previous API it returned a new node or `nullptr` in case of error,
//!     which the user couldn't inspect unless there was an attached `ErrorHandler`.
//!
//! Samples:
//!
//! ```
//! #include <asmjit/x86.h>
//!
//! using namespace asmjit;
//!
//! // The basic setup of JitRuntime and CodeHolder changed, use environment()
//! // instead of codeInfo().
//! void basicSetup() {
//!   JitRuntime rt;
//!   CodeHolder code(rt.environment());
//! }
//!
//! // Calling a function (Compiler) changed - use invoke() instead of call().
//! void functionInvocation(x86::Compiler& cc) {
//!   InvokeNode* invokeNode;
//!   cc.invoke(&invokeNode, targetOperand, FuncSignature::build<...>(...));
//! }
//! ```


//! \defgroup asmjit_core Core
//! \brief Globals, code storage, and emitter interface.
//!
//! ### Overview
//!
//! AsmJit library uses \ref CodeHolder to hold code during code generation and emitters inheriting from \ref
//! BaseEmitter to emit code. CodeHolder uses containers to manage its data:
//!
//!   - \ref Section - stores information about a code or data section.
//!   - \ref CodeBuffer - stores actual code or data, part of \ref Section.
//!   - \ref LabelEntry - stores information about a \ref Label - its name, offset, section where it belongs to,
//!     and other bits.
//!   - \ref Fixup - stores information about positions in code that needs to be fixed up later, for example
//!     when referencing a \ref Label, which was not bound to a position in code yet.
//!   - \ref RelocEntry - stores information about a relocation.
//!   - \ref AddressTableEntry - stores information about an absolute address, which was used in a jump or call.
//!     Code referencing an absolute address may need relocation or a record in address table.
//!
//! To generate code you would need to instantiate at least the following classes:
//!
//!   - \ref CodeHolder - to hold code during code generation.
//!   - \ref BaseEmitter - to emit code into \ref CodeHolder.
//!   - \ref Target (optional) - most likely \ref JitRuntime to keep the generated code in executable memory. \ref
//!     Target can be customized by inheriting from it.
//!
//! There are also other core classes that are important:
//!
//!   - \ref Environment - describes where the code will run. Environment brings the concept of target triples or
//!     tuples into AsmJit, which means that users can specify target architecture, platform, and ABI.
//!   - \ref TypeId - encapsulates lightweight type functionality that can be used to describe primitive and vector
//!     types. Types are used by higher level utilities, for example by \ref asmjit_function and \ref asmjit_compiler.
//!   - \ref CpuInfo - encapsulates CPU information - stores both CPU information and CPU features described by \ref
//!     CpuFeatures.
//!
//! AsmJit also provides global constants:
//!
//!   - \ref Globals - namespace that provides global constants.
//!
//! \note CodeHolder examples use \ref x86::Assembler as abstract interfaces cannot be used to generate code.
//!
//! \section code_holder_and_emitters CodeHolder & Emitters
//!
//! The example below shows how the mentioned classes interact to generate X86 code:
//!
//! ```
//! #include <asmjit/x86.h>
//! #include <stdio.h>
//!
//! using namespace asmjit;
//!
//! // Signature of the generated function.
//! using Func = int (*)(void);
//!
//! int main() {
//!   JitRuntime rt;                    // Runtime specialized for JIT code execution.
//!
//!   CodeHolder code;                  // Holds code and relocation information.
//!   code.init(rt.environment(),       // Initialize code to match the JIT environment.
//!             rt.cpu_features());
//!
//!   x86::Assembler a(&code);          // Create and attach x86::Assembler to code.
//!   a.mov(x86::eax, 1);               // Move one to eax register.
//!   a.ret();                          // Return from function.
//!   // ===== x86::Assembler is no longer needed from here and can be destroyed =====
//!
//!   Func fn;                          // Holds address to the generated function.
//!   Error err = rt.add(&fn, &code);   // Add the generated code to the runtime.
//!
//!   if (err != Error::kOk) {
//!     return 1;                       // Handle a possible error returned by AsmJit.
//!   }
//!   // ===== CodeHolder is no longer needed from here and can be destroyed =====
//!
//!   int result = fn();                // Execute the generated code.
//!   printf("%d\n", result);           // Print the resulting "1".
//!
//!   // All classes use RAII, all resources will be released before `main()` returns,
//!   // the generated function can be, however, released explicitly if you intend to
//!   // reuse or keep the runtime alive, which you should in a production-ready code.
//!   rt.release(fn);
//!
//!   return 0;
//! }
//! ```
//!
//! The example above used \ref x86::Assembler as an emitter. AsmJit provides the following emitters that offer various
//! levels of abstraction:
//!
//!   - \ref asmjit_assembler - Low-level emitter that emits directly to \ref CodeBuffer.
//!   - \ref asmjit_builder - Low-level emitter that emits to a \ref BaseNode list.
//!   - \ref asmjit_compiler - High-level emitter that provides register allocation.
//!
//! \section targets_and_jit_runtime Targets and JitRuntime
//!
//! AsmJit's \ref Target is an interface that provides basic target abstraction. At the moment AsmJit provides only
//! one implementation called \ref JitRuntime, which as the name suggests provides JIT code target and execution
//! runtime. \ref JitRuntime provides all the necessary stuff to implement a simple JIT compiler with basic memory
//! management. It only provides \ref JitRuntime::add() and \ref JitRuntime::release() functions that are used to
//! either add code to the runtime or release it. \ref JitRuntime doesn't do any decisions on when the code should be
//! released, the decision is up to the developer.
//!
//! See more at \ref asmjit_virtual_memory group.
//!
//! ### More About Environment
//!
//! In the previous example the \ref Environment is retrieved from \ref JitRuntime. It's logical as \ref JitRuntime
//! always returns an \ref Environment that is compatible with the host. For example if your application runs on X86_64
//! CPU the \ref Environment returned will use \ref Arch::kX64 architecture in contrast to \ref Arch::kX86, which will
//! be used in 32-bit mode on an X86 target.
//!
//! AsmJit allows to setup the \ref Environment manually and to select a different architecture and ABI when necessary.
//! So let's do something else this time, let's always generate a 32-bit code and print its binary representation. To
//! do that, we can create our own \ref Environment and initialize it to \ref Arch::kX86.
//!
//! ```
//! #include <asmjit/x86.h>
//! #include <stdio.h>
//!
//! using namespace asmjit;
//!
//! int main(int argc, char* argv[]) {
//!   using namespace asmjit::x86;
//!
//!   // Create a custom environment initialized to 32-bit X86 architecture.
//!   Environment env;
//!   env.set_arch(Arch::kX86);
//!
//!   CodeHolder code;                  // Create a CodeHolder.
//!   code.init(env);                   // Initialize CodeHolder with custom environment.
//!
//!   // Generate a 32-bit function that sums 4 floats and looks like:
//!   //   void func(float* dst, const float* a, const float* b)
//!   x86::Assembler a(&code);          // Create and attach x86::Assembler to `code`.
//!
//!   a.mov(eax, dword_ptr(esp, 4));    // Load the destination pointer.
//!   a.mov(ecx, dword_ptr(esp, 8));    // Load the first source pointer.
//!   a.mov(edx, dword_ptr(esp, 12));   // Load the second source pointer.
//!
//!   a.movups(xmm0, ptr(ecx));         // Load 4 floats from [ecx] to XMM0.
//!   a.movups(xmm1, ptr(edx));         // Load 4 floats from [edx] to XMM1.
//!   a.addps(xmm0, xmm1);              // Add 4 floats in XMM1 to XMM0.
//!   a.movups(ptr(eax), xmm0);         // Store the result to [eax].
//!   a.ret();                          // Return from function.
//!
//!   // We have no Runtime this time, it's on us what we do with the code.
//!   // CodeHolder stores code in Section, which provides some basic properties
//!   // and CodeBuffer structure. We are interested in section's CodeBuffer.
//!   //
//!   // NOTE: The first section is always '.text', it can be retrieved by
//!   // code.section_by_id(0) or simply by code.text_section().
//!   CodeBuffer& buffer = code.text_section()->buffer();
//!
//!   // Print the machine-code generated or do something else with it...
//!   //   8B4424048B4C24048B5424040F28010F58010F2900C3
//!   for (size_t i = 0; i < buffer.length; i++)
//!     printf("%02X", buffer.data[i]);
//!
//!   return 0;
//! }
//! ```
//!
//! \section explicit_code_relocation 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 Fixup - it's a lightweight data structure that doesn't have any identifier and
//! is stored in \ref LabelEntry and \ref CodeHolder as a single-linked list. Fixup represents either a reference to an
//! unbound label and cross-sections references (only relevant to code that uses multiple sections). Since crossing
//! sections is something that cannot be resolved immediately these fixups persist until offsets of these sections are
//! assigned and until \ref CodeHolder::resolve_cross_section_fixups() is called. It's an error if you end up with code that
//! still has fixups after flattening. You can verify it by calling \ref CodeHolder::has_unresolved_fixups(), which inspects
//! the value returned by \ref CodeHolder::unresolved_fixup_count().
//!
//! 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::resolve_cross_section_fixups() 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::resolve_cross_section_fixups() 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>
//! #include <stdio.h>
//!
//! using namespace asmjit;
//!
//! using SumIntsFunc = void (*)(int* dst, const int* a, const int* b);
//!
//! int main() {
//!   // Create a custom environment that matches the current host environment.
//!   Environment env = Environment::host();
//!   CpuFeatures cpu_features = CpuInfo::host().features();
//!
//!   CodeHolder code;                  // Create a CodeHolder.
//!   code.init(env, cpu_features);     // Initialize CodeHolder with environment.
//!
//!   x86::Assembler a(&code);          // Create and attach x86::Assembler to `code`.
//!
//!   // Signature: 'void func(int* dst, const int* a, const int* b)'.
//!   x86::Gp dst;
//!   x86::Gp src_a;
//!   x86::Gp src_b;
//!
//!   // Handle the difference between 32-bit and 64-bit calling conventions
//!   // (arguments passed through stack vs. arguments passed by registers).
//!   if (env.is_32bit()) {
//!     dst   = x86::eax;
//!     src_a = x86::ecx;
//!     src_b = x86::edx;
//!     a.mov(dst  , x86::dword_ptr(x86::esp, 4));
//!     a.mov(src_a, x86::dword_ptr(x86::esp, 8));
//!     a.mov(src_b, x86::dword_ptr(x86::esp, 12));
//!   }
//!   else {
//!     if (env.is_platform_windows()) {
//!       dst   = x86::rcx;             // First argument  (destination pointer).
//!       src_a = x86::rdx;             // Second argument (source 'a' pointer).
//!       src_b = x86::r8;              // Third argument  (source 'b' pointer).
//!     }
//!     else {
//!       dst   = x86::rdi;             // First argument  (destination pointer).
//!       src_a = x86::rsi;             // Second argument (source 'a' pointer).
//!       src_b = x86::rdx;             // Third argument  (source 'b' pointer).
//!     }
//!   }
//!
//!   a.movdqu(x86::xmm0, x86::ptr(src_a)); // Load 4 ints from [src_a] to XMM0.
//!   a.movdqu(x86::xmm1, x86::ptr(src_b)); // Load 4 ints from [src_b] to XMM1.
//!   a.paddd(x86::xmm0, x86::xmm1);        // Add 4 ints in XMM1 to XMM0.
//!   a.movdqu(x86::ptr(dst), x86::xmm0);   // Store the result to [dst].
//!   a.ret();                              // Return from function.
//!
//!   // Even when we didn't use multiple sections AsmJit could insert one section
//!   // called '.addrtab' (address table section), which would be filled by data
//!   // required by relocations (absolute jumps and calls). You can omit this code
//!   // if you are 100% sure your code doesn't contain multiple sections and
//!   // such relocations. You can use `CodeHolder::has_address_table_section()` to
//!   // verify whether the address table section does exist.
//!   code.flatten();
//!   code.resolve_cross_section_fixups();
//!
//!   // After the code was generated it can be relocated manually to any memory
//!   // location, however, we need to know it's size before we perform memory
//!   // allocation. `CodeHolder::code_size()` returns the worst estimated code
//!   // size in case that relocations are not possible without trampolines (in
//!   // that case some extra code at the end of the current code buffer is
//!   // generated during relocation).
//!   size_t estimated_size = code.code_size();
//!
//!   // Instead of rolling up our own memory allocator we can use the one AsmJit
//!   // provides. It's decoupled so you don't need to use `JitRuntime` for that.
//!   JitAllocator allocator;
//!
//!   // Allocate an executable virtual memory and handle a possible failure.
//!   JitAllocator::Span span;
//!   Error err = allocator.alloc(span, estimated_size);
//!
//!   if (err != Error::kOk) { // <- NOTE: This must be checked, always!
//!     return 0;
//!   }
//!
//!   // Now relocate the code to the address provided by the memory allocator.
//!   // Please note that this DOESN'T COPY anything to it. This function will
//!   // store the address in CodeHolder and use relocation entries to patch
//!   // the existing code in all sections to respect the base address provided.
//!   code.relocate_to_base((uint64_t)span.rx());
//!
//!   // This is purely optional. There are cases in which the relocation can omit
//!   // unneeded data, which would shrink the size of address table. If that
//!   // happened the code_size returned after relocate_to_base() would be smaller
//!   // than the originally `estimated_size`.
//!   size_t code_size = code.code_size();
//!
//!   // This will copy code from all sections to `p`. Iterating over all sections
//!   // and calling `memcpy()` would work as well, however, this function supports
//!   // additional options that can be used to also zero pad sections' virtual
//!   // size, etc.
//!   //
//!   // With some additional features, copyFlattenData() does roughly the following:
//!   //
//!   // allocator.write([&](JitAllocator::Span& span) noexcept -> Error {
//!   //   for (Section* section : code.sections()) {
//!   //     uint8_t* p = (uint8_t*)span.rw() + section->offset();
//!   //     memcpy(p, section->data(), section->buffer_size());
//!   //   }
//!   //   return Error::kOk;
//!   // }
//!   allocator.write([&](JitAllocator::Span& span) noexcept -> Error {
//!     code.copy_flattened_data(span.rw(), code_size, CopySectionFlags::kPadSectionBuffer);
//!     return Error::kOk;
//!   });
//!
//!   // Execute the generated function.
//!   int in_a[4] = { 4, 3, 2, 1 };
//!   int in_b[4] = { 1, 5, 2, 8 };
//!   int out[4];
//!
//!   // This code uses AsmJit's ptr_as_func<> to cast between void* and SumIntsFunc.
//!   SumIntsFunc fn = ptr_as_func<SumIntsFunc>(span.rx());
//!   fn(out, in_a, in_b);
//!
//!   // Prints {5 8 4 9}
//!   printf("{%d %d %d %d}\n", out[0], out[1], out[2], out[3]);
//!
//!   // Release `fn` is it's no longer needed. It will be destroyed with 'vm'
//!   // instance anyway, but it's a good practice to release it explicitly
//!   // when you know that the function will not be needed anymore.
//!   allocator.release(fn);
//!
//!   return 0;
//! }
//! ```
//!
//! If you know the base-address in advance (before the code generation) it can be passed as a second argument to
//! \ref CodeHolder::init(). In that case the Assembler will know the absolute position of each instruction and
//! would be able to use it during instruction encoding to prevent relocations where possible. The following example
//! shows how to configure the base address:
//!
//! ```
//! #include <asmjit/x86.h>
//! #include <stdio.h>
//!
//! using namespace asmjit;
//!
//! void initialize_code_holder_example(CodeHolder& code) {
//!   Environment env = Environment::host();
//!   CpuFeatures cpu_features = CpuInfo::host().features();
//!   uint64_t base_address = uint64_t(0x1234);
//!
//!   // initialize CodeHolder with environment and custom base address.
//!   code.init(env, cpu_features, base_address);
//! }
//! ```
//!
//! \section labels Label Offsets and Links
//!
//! When a label that is not yet bound is used by the Assembler, it creates a \ref Fixup, which is then referenced
//! by \ref LabelEntry. Fixups are also created if a label is referenced 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 fixups.
//!
//! ```
//! #include <asmjit/core.h>
//! #include <stdio.h>
//!
//! using namespace asmjit;
//!
//! void label_links_example(CodeHolder& code, const Label& label) {
//!   // Tests whether the `label` is bound.
//!   bool is_bound = code.is_label_bound(label);
//!   printf("Label %u is %s\n", label.id(), is_bound ? "bound" : "not bound");
//!
//!   // Returns true if the code contains either referenced, but unbound
//!   // labels, or cross-section fixups that are not resolved yet.
//!   bool has_unresolved = code.has_unresolved_fixups();  // Boolean answer.
//!   size_t n_unresolved = code.unresolved_fixup_count(); // Count of unresolved fixups.
//!
//!   printf("Number of unresolved fixups: %zu\n", n_unresolved);
//! }
//! ```
//!
//! 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
//!   // label is not bound the offset returned will be zero. It's recommended
//!   // to always check whether the label is bound before using its offset.
//!   uint64_t section_offset = code.label_offset(label);
//!   printf("Label offset relative to section: %llu\n", (unsigned long long)section_offset);
//!
//!   // If you use multiple sections and want the offset relative to the base.
//!   // NOTE: This function expects that the section has already an offset and
//!   // the label-link was resolved (if this is not true you will still get an
//!   // offset relative to the start of the section).
//!   uint64_t base_offset = code.label_offset_from_base(label);
//!   printf("Label offset relative to base: %llu\n", (unsigned long long)base_offset);
//! }
//! ```
//!
//! \section code_sections Code & Data Sections
//!
//! AsmJit allows to create multiple sections within the same \ref CodeHolder. A test-case
//! [asmjit_test_x86_sections.cpp](https://github.com/asmjit/asmjit/blob/master/test/asmjit_test_x86_sections.cpp)
//! can be used as a reference point although the following example should also provide a useful insight:
//!
//! ```
//! #include <asmjit/x86.h>
//! #include <stdio.h>
//!
//! using namespace asmjit;
//!
//! void sections_example(CodeHolder& code) {
//!   // Text section is always provided as the first section.
//!   Section* text = code.text_section(); // or code.section_by_id(0);
//!
//!   // To create another section use CodeHolder::new_section().
//!   Section* data;
//!   Error err = code.new_section(Out(data),
//!     ".data",                // Section name
//!     SIZE_MAX,               // Name length if the name is not null terminated (or SIZE_MAX).
//!     SectionFlags::kNone,    // Section flags, see SectionFlags.
//!     8,                      // Section alignment, must be power of 2.
//!     0);                     // Section order value (optional, default 0).
//!
//!   // When you switch sections in Assembler, Builder, or Compiler the cursor
//!   // will always move to the end of that section. When you create an Assembler
//!   // the cursor would be placed at the end of the first (.text) section, which
//!   // is initially empty.
//!   x86::Assembler a(&code);
//!   Label L_Data = a.new_label();
//!
//!   a.mov(x86::eax, x86::ebx); // Emits in .text section.
//!
//!   a.section(data);           // Switches to the end of .data section.
//!   a.bind(L_Data);            // Binds label in this .data section
//!   a.db(0x01);                // Emits byte in .data section.
//!
//!   a.section(text);           // Switches to the end of .text section.
//!   a.add(x86::ebx, x86::eax); // Emits in .text section.
//!
//!   // References a label in .text section, which was bound in .data section. This would create a
//!   // fixup even when the L_Data is already bound, because the reference crosses sections. See below...
//!   a.lea(x86::rsi, x86::ptr(L_Data));
//! }
//! ```
//!
//! The last line in the example above shows that a \ref Fixup 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 reference 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 a ready API for that.
//!
//! ```
//! #include <asmjit/x86.h>
//! #include <stdio.h>
//!
//! using namespace asmjit;
//!
//! // ... (continuing the previous example) ...
//! void sections_example_continued(CodeHolder& code) {
//!   // Suppose we have some code that contains multiple sections and
//!   // we would like to flatten it by using AsmJit's built-in API:
//!   Error err = code.flatten();
//!   if (err != Error::kOk) {
//!     // There are many reasons it can fail, so always handle a possible error.
//!     printf("Failed to flatten the code: %s\n", DebugUtils::error_as_string(err));
//!     exit(1);
//!   }
//!
//!   // After flattening all sections would contain assigned offsets relative to base.
//!   // Offsets are 64-bit unsigned integers so we cast them to `size_t` for simplicity.
//!   // On 32-bit targets it's guaranteed that the offset cannot be greater than `2^32 - 1`.
//!   printf("Data section offset %zu", size_t(data->offset()));
//!
//!   // The flattening doesn't resolve unresolved fixups, this
//!   // has to be done manually as flattening can be done separately.
//!   err = code.resolve_cross_section_fixups();
//!   if (err != Error::kOk) {
//!     // This is the kind of error that should always be handled...
//!     printf("Failed to resolve fixups: %s\n", DebugUtils::error_as_string(err));
//!     exit(1);
//!   }
//!
//!   if (code.has_unresolved_fixups()) {
//!     // This would mean either unbound label or some other issue.
//!     printf("The code has %zu unbound labels\n", code.unresolved_fixup_count());
//!     exit(1);
//!   }
//! }
//! ```


//! \defgroup asmjit_assembler Assembler
//! \brief Assembler interface and operands.
//!
//! ### Overview
//!
//! AsmJit's Assembler is used to emit machine code directly into a \ref CodeBuffer. In general, code generation
//! with assembler requires the knowledge of the following:
//!
//!   - \ref BaseAssembler and architecture-specific assemblers:
//!     - \ref x86::Assembler - Assembler implementation targeting X86 and X86_64 architectures.
//!     - \ref a64::Assembler - Assembler implementation targeting AArch64 architecture.
//!   - \ref Operand and its variations:
//!     - \ref Reg - Base class for a register operand, inherited by:
//!        - \ref UniGp - Universal abstraction of a general purpose register, inherited by:
//!          - \ref x86::Gp - GP register operand specific to X86 and X86_64 architectures.
//!          - \ref a64::Gp - GP Register operand specific to AArch64 architecture.
//!        - \ref UniVec - Universal abstraction of a vector register, inherited by:
//!          - \ref x86::Vec - Vector register operand specific to X86 and X86_64 architectures.
//!          - \ref a64::Vec - Vector register operand specific to AArch64 architecture.
//!        - \ref x86::Mm, \ref x86::KReg, \ref x86::Tmm, and other architecture specific register operands.
//!     - \ref BaseMem - Base class for a memory operand, inherited by:
//!        - \ref x86::Mem - Memory operand specific to X86 and X86_64 architectures.
//!        - \ref a64::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.
//!
//! \section operand_basics 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 Reg - Describes either physical or virtual register. Physical registers have ids that match the target's
//!     machine id directly whereas virtual registers must be allocated into physical registers by a register allocator
//!     pass. Register operand provides:
//!     - Register Type (\ref RegType) - Unique id that describes each possible register provided by the target
//!       architecture - for example X86 backend provides general purpose registers (GPB-LO, GPB-HI, GPW, GPD, and GPQ)
//!       and various 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.
//!     - Unified interface of general purpose registers is provided by \ref UniGp, which acts as a base of
//!       all architecture specific GP registers such as \ref x86::Gp and \ref a64::Gp.
//!     - Unified interface of vector registers is provided by \ref UniVec, which acts as a base of all architecture
//!       specific vector registers such as \ref x86::Vec and \ref a64::Vec. Please note that X86 MMX registers are
//!       not part of \ref x86::Vec, instead they are modeled as \ref x86::Mm.
//!   - \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.
//!
//! \section operand_manipulation Operand Manipulation
//!
//! AsmJit allows to construct operands dynamically, to store them, and to query a complete information about them at
//! run-time. Operands are small (always 16 bytes per `Operand`) and should be always copied (by value) if you intend
//! to store them (don't create operands by using `new` keyword, it's not recommended). Operands are safe to be passed
//! to `memcpy()` and `memset()`, which becomes handy when working with arrays of operands. If you set all members of
//! an \ref Operand to zero the operand would become NONE operand, which is the same as a default constructed Operand.
//!
//! The example below illustrates how operands can be used and modified even without using any other code generation
//! classes. The example uses X86 architecture-specific operands.
//!
//! ```
//! #include <asmjit/x86.h>
//!
//! using namespace asmjit;
//!
//! // Registers can be copied, it's a common practice.
//! x86::Gp dstRegByValue() { return x86::ecx; }
//!
//! void usingOperandsExample(x86::Assembler& a) {
//!   // Gets `ecx` register returned by a function.
//!   x86::Gp dst = dstRegByValue();
//!   // Gets `rax` register directly from the provided `x86` namespace.
//!   x86::Gp src = x86::rax;
//!   // Constructs `r10` dynamically.
//!   x86::Gp idx = x86::gpq(10);
//!   // Constructs [src + idx] memory address - referencing [rax + r10].
//!   x86::Mem m = x86::ptr(src, idx);
//!
//!   // Examine `m`: Returns `RegType::kGp64`.
//!   m.index_type();
//!   // Examine `m`: Returns 10 (`r10`).
//!   m.index_id();
//!
//!   // Reconstruct `idx` stored in mem:
//!   x86::Gp idx_2 = x86::Gp::from_type_and_id(m.index_type(), m.index_id());
//!
//!   // True, `idx` and `idx_2` are identical.
//!   idx == idx_2;
//!
//!   // Possible - op will still be the same as `m`.
//!   Operand op = m;
//!   // True (can be casted to BaseMem or architecture-specific Mem).
//!   op.is_mem();
//!
//!   // True, `op` is just a copy of `m`.
//!   m == op;
//!
//!   // Static cast is fine and valid here.
//!   static_cast<BaseMem&>(op).add_offset(1);
//!   // However, using `as<T>()` to cast to a derived type is preferred.
//!   op.as<BaseMem>().add_offset(1);
//!   // False, `op` now points to [rax + r10 + 2], which is not [rax + r10].
//!   m == op;
//!
//!   // Emitting 'mov' - type safe way.
//!   a.mov(dst, m);
//!   // Not possible, `mov` doesn't provide mov(x86::Gp, Operand) overload.
//!   a.mov(dst, op);
//!
//!   // Type-unsafe, but possible.
//!   a.emit(x86::Inst::kIdMov, dst, m);
//!   // Also possible, `emit()` is 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::new_label(), 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.
//!
//! \section memory_operands Memory Operands
//!
//! Some architectures like X86 provide a complex memory addressing model that allows to encode addresses having a
//! BASE register, INDEX register with a possible scale (left shift), and displacement (called offset in AsmJit).
//! Memory address on X86 can also specify memory segment (segment-override in X86 terminology) and some instructions
//! (gather / scatter) require INDEX to be a \ref x86::Vec register instead of a general-purpose register.
//!
//! AsmJit allows to encode and work with all forms of addresses mentioned and implemented by X86. In addition, it
//! also allows to construct absolute 64-bit memory address operands, which is only allowed in one form of 'mov'
//! instruction.
//!
//! ```
//! #include <asmjit/x86.h>
//!
//! using namespace asmjit;
//!
//! void testX86Mem() {
//!   // Makes it easier to access x86 stuff...
//!   using namespace asmjit::x86;
//!
//!   // BASE + OFFSET.
//!   Mem a = ptr(rax);                 // a = [rax]
//!   Mem b = ptr(rax, 15);             // b = [rax + 15]
//!
//!   // BASE + INDEX << SHIFT - Shift is in BITS as used by X86!
//!   Mem c = ptr(rax, rbx);            // c = [rax + rbx]
//!   Mem d = ptr(rax, rbx, 2);         // d = [rax + rbx << 2]
//!   Mem e = ptr(rax, rbx, 2, 15);     // e = [rax + rbx << 2 + 15]
//!
//!   // BASE + VM (Vector Index) (encoded as MOD+VSIB).
//!   Mem f = ptr(rax, xmm1);           // f = [rax + xmm1]
//!   Mem g = ptr(rax, xmm1, 2);        // g = [rax + xmm1 << 2]
//!   Mem h = ptr(rax, xmm1, 2, 15);    // h = [rax + xmm1 << 2 + 15]
//!
//!   // Absolute address:
//!   uint64_t addr = (uint64_t)0x1234;
//!   Mem i = ptr(addr);                // i = [0x1234]
//!   Mem j = ptr(addr, rbx);           // j = [0x1234 + rbx]
//!   Mem k = ptr(addr, rbx, 2);        // k = [0x1234 + rbx << 2]
//!
//!   // LABEL - Will be encoded as RIP (64-bit) or absolute address (32-bit).
//!   Label L = ...;
//!   Mem m = ptr(L);                   // m = [L]
//!   Mem n = ptr(L, rbx);              // n = [L + rbx]
//!   Mem o = ptr(L, rbx, 2);           // o = [L + rbx << 2]
//!   Mem p = ptr(L, rbx, 2, 15);       // p = [L + rbx << 2 + 15]
//!
//!   // RIP - 64-bit only (RIP can't use INDEX).
//!   Mem q = ptr(rip, 24);             // q = [rip + 24]
//! }
//! ```
//!
//! Memory operands can optionally contain memory size. This is required by instructions where the memory size cannot
//! be deduced from other operands, like `inc` and `dec` on X86:
//!
//! ```
//! #include <asmjit/x86.h>
//!
//! using namespace asmjit;
//!
//! void testX86Mem() {
//!   // The same as: 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(x86::rdx, x86::rsi, 0, 1);
//! }
//! ```
//!
//! Memory operands provide API that can be used to access its properties:
//!
//! ```
//! #include <asmjit/x86.h>
//!
//! using namespace asmjit;
//!
//! void testX86Mem() {
//!   // The same as: dword ptr [rax + 12].
//!   x86::Mem mem = x86::dword_ptr(x86::rax, 12);
//!
//!   mem.has_base();                    // true.
//!   mem.has_index();                   // false.
//!   mem.size();                        // 4.
//!   mem.offset();                      // 12.
//!
//!   mem.set_size(0);                   // Sets the size to 0 (makes it size-less).
//!   mem.add_offset(-1);                // Adds -1 to the offset and makes it 11.
//!   mem.set_offset(0);                 // Sets the offset to 0.
//!   mem.set_base(x86::rcx);            // Changes BASE to RCX.
//!   mem.set_index(x86::rax);           // Changes INDEX to RAX.
//!   mem.has_index();                   // true.
//! }
//! ```
//!
//! Making changes to memory operand is very comfortable when emitting loads
//! and stores:
//!
//! ```
//! #include <asmjit/x86.h>
//!
//! using namespace asmjit;
//!
//! void testX86Mem(CodeHolder& code) {
//!   x86::Assembler a(code);            // Your initialized x86::Assembler.
//!   x86::Mem mSrc = x86::ptr(eax);     // Construct [eax] memory operand.
//!
//!   // One way of emitting bunch of loads is to use `mem.adjusted()`, which
//!   // returns a new memory operand and keeps the source operand unchanged.
//!   a.movaps(x86::xmm0, mSrc);              // No adjustment needed to load [eax].
//!   a.movaps(x86::xmm1, mSrc.adjusted(16)); // Loads from [eax + 16].
//!   a.movaps(x86::xmm2, mSrc.adjusted(32)); // Loads from [eax + 32].
//!   a.movaps(x86::xmm3, mSrc.adjusted(48)); // Loads from [eax + 48].
//!
//!   // ... do something with xmm0-3 ...
//!
//!   // Another way of adjusting memory is to change the operand in-place.
//!   // If you want to keep the original operand you can simply clone it.
//!   x86::Mem mDst = mSrc.clone();      // Clone mSrc.
//!
//!   a.movaps(mDst, x86::xmm0);         // Stores xmm0 to [eax].
//!   mDst.add_offset(16);               // Adds 16 to `mDst`.
//!
//!   a.movaps(mDst, x86::xmm1);         // Stores to [eax + 16] .
//!   mDst.add_offset(16);               // Adds 16 to `mDst`.
//!
//!   a.movaps(mDst, x86::xmm2);         // Stores to [eax + 32].
//!   mDst.add_offset(16);               // Adds 16 to `mDst`.
//!
//!   a.movaps(mDst, x86::xmm3);         // Stores to [eax + 48].
//! }
//! ```
//!
//! \section examples Assembler Examples
//!
//!   - \ref x86::Assembler provides many X86/X64 examples.


//! \defgroup asmjit_builder Builder
//! \brief Builder interface, nodes, and passes.
//!
//! ### Overview
//!
//! Both \ref BaseBuilder and \ref BaseCompiler interfaces describe emitters that emit into a representation that
//! allows further processing. The code stored in such representation is completely safe to be patched, simplified,
//! reordered, obfuscated, removed, injected, analyzed, or processed some other way. Each instruction, label,
//! directive, or other building block is stored as \ref BaseNode (or derived class like \ref InstNode or \ref
//! LabelNode) and contains all the information necessary to pass that node later to the assembler.
//!
//! \ref BaseBuilder is an emitter that inherits from \ref BaseEmitter interface. It was designed to provide a maximum
//! compatibility with the existing \ref BaseAssembler emitter so users can move from assembler to builder when needed,
//! for example to implement post-processing, which is not possible with Assembler.
//!
//! \section builder_nodes Builder Nodes
//!
//! \ref BaseBuilder doesn't generate machine code directly, it uses an intermediate representation based on nodes,
//! however, it allows to serialize to \ref BaseAssembler when the code is ready to be encoded.
//!
//! There are multiple node types used by both \ref BaseBuilder and \ref BaseCompiler :
//!
//!   - Basic nodes:
//!     - \ref BaseNode - Base class for all nodes.
//!     - \ref InstNode - Represents an instruction node.
//!     - \ref AlignNode - Represents an alignment directive (.align).
//!     - \ref LabelNode - Represents a location where to bound a \ref Label.
//!
//!   - Data nodes:
//!     - \ref EmbedDataNode - Represents data.
//!     - \ref EmbedLabelNode - Represents \ref Label address embedded as data.
//!     - \ref EmbedLabelDeltaNode - Represents a difference of two labels embedded in data.
//!     - \ref ConstPoolNode - Represents a constant pool data embedded as data.
//!
//!   - Informative nodes:
//!     - \ref CommentNode - Represents a comment string, doesn't affect code generation.
//!     - \ref SentinelNode - A marker that can be used to remember certain position in code or data, doesn't affect
//!       code generation. Used by \ref FuncNode to mark the end of a function.
//!
//!   - Other nodes are provided by \ref asmjit_compiler infrastructure.
//!
//! \section builder_examples Examples
//!
//!   - \ref x86::Builder - Builder implementation targeting X86 and X86_64 architectures.
//!   - \ref a64::Builder - Builder implementation targeting AArch64 architecture.


//! \defgroup asmjit_compiler Compiler
//! \brief Compiler interface.
//!
//! ### Overview
//!
//! \ref BaseCompiler is a high-level interface, which provides register allocation and support for defining and
//! invoking functions, built on top of \ref BaseBuilder interface At the moment it's the easiest way of generating
//! code in AsmJit as most architecture and OS specifics is properly abstracted and handled by AsmJit automatically.
//! However, abstractions also mean restrictions, which means that \ref BaseCompiler has more limitations than \ref
//! BaseAssembler or \ref BaseBuilder.
//!
//! Since \ref BaseCompiler provides register allocation it also establishes the concept of functions - a function
//! in Compiler sense is a unit in which virtual registers are allocated into physical registers by the register
//! allocator. In addition, it enables to use such virtual registers in function invocations.
//!
//! \ref BaseCompiler automatically handles function calling conventions. It's still architecture dependent, but
//! makes the code generation much easies. Functions are essential; the first-step to generate some code is to define
//! a signature of the function to be generated (before generating the function body itself). Function arguments and
//! return value(s) are handled by assigning virtual registers to them. Similarly, function calls are handled the same
//! way.
//!
//! \section compiler_nodes Compiler Nodes
//!
//! \ref BaseCompiler adds some nodes that are required for function generation and invocation:
//!
//!   - \ref FuncNode - Represents a function definition.
//!   - \ref FuncRetNode - Represents a function return.
//!   - \ref InvokeNode - Represents a function invocation.
//!
//! \ref BaseCompiler also makes the use of passes (\ref Pass) and automatically adds an architecture-dependent
//! register allocator pass to the list of passes when attached to \ref CodeHolder.
//!
//! \section compiler_examples Compiler Examples
//!
//!   - \ref x86::Compiler - Compiler implementation targeting X86 and X86_64 architectures.
//!   - \ref a64::Compiler - Compiler implementation targeting AArch64 architecture.
//!
//! \section compiler_tips Compiler Tips
//!
//! Users of AsmJit have done mistakes in the past, this section should provide some useful tips for beginners:
//!
//!   - Virtual registers in compiler are bound to a single function. At the moment the implementation doesn't
//!     care whether a single virtual register is used in multiple functions, but it sees it as two independent
//!     virtual registers in that case. This means that virtual registers cannot be used to implement global
//!     variables. Global variables are basically memory addresses which functions can read from and write to,
//!     and they have to be implemented in the same way.
//!
//!   - Compiler provides a useful debugging functionality, which can be turned on through \ref FormatFlags. Use
//!     \ref Logger::add_flags() to turn on additional logging features when using Compiler.


//! \defgroup asmjit_function Function
//! \brief Function definitions.
//!
//! ### Overview
//!
//! AsmJit provides functionality that can be used to define function signatures and to calculate automatically
//! optimal function frame that can be used directly by a prolog and epilog insertion. This feature was exclusive
//! to AsmJit's Compiler for a very long time, but was abstracted out and is now available for all users regardless
//! of the emitter they use. The following use cases are possible:
//!
//!   - Calculate function frame before the function is generated - this is the only way available to \ref
//!     BaseAssembler users and it will be described in this section.
//!
//!   - Calculate function frame after the function is generated - this way is generally used by \ref BaseBuilder
//!     and \ref BaseCompiler emitters and this way is generally described in \ref asmjit_compiler section.
//!
//! The following concepts are used to describe and create functions in AsmJit:
//!
//!   - \ref TypeId - Type-id is an 8-bit value that describes a platform independent type as we know from C/C++.
//!     It provides abstractions for most common types like `int8_t`, `uint32_t`, `uintptr_t`, `float`, `double`,
//!     and all possible vector types to match ISAs up to AVX512. \ref TypeId was introduced originally for \ref
//!     asmjit_compiler, but it's now used by \ref FuncSignature as well.
//!
//!   - \ref CallConv - Describes a calling convention - this class contains instructions to assign registers and
//!     stack addresses to function arguments and return value(s), but doesn't specify any function signature itself.
//!     Calling conventions are architecture and OS dependent.
//!
//!   - \ref FuncSignature - Describes a function signature, for example `int func(int, int)`. FuncSignature contains
//!     a function calling convention id, return value type, and function arguments. The signature itself is platform
//!     independent and uses \ref TypeId to describe types of function arguments and function return value(s).
//!
//!   - \ref FuncDetail - Architecture and ABI dependent information that describes \ref CallConv and expanded \ref
//!     FuncSignature. Each function argument and return value is represented as \ref FuncValue that contains the
//!     original \ref TypeId enriched with additional information that specifies whether the value is passed or
//!     returned by register (and which register) or by stack. Each value also contains some other metadata that
//!     provide additional information required to handle it properly (for example whether a vector is passed
//!     indirectly by a pointer as required by WIN64 calling convention).
//!
//!   - \ref FuncFrame - Contains information about the function frame that can be used by prolog/epilog inserter
//!     (PEI). Holds call stack size size and alignment, local stack size and alignment, and various attributes that
//!     describe how prolog and epilog should be constructed. `FuncFrame` doesn't know anything about function's
//!     arguments or return values, it hold only information necessary to create a valid and ABI conforming function
//!     prologs and epilogs.
//!
//!   - \ref FuncArgsAssignment - A helper class that can be used to reassign function arguments into user specified
//!     registers. It's architecture and ABI dependent mapping from function arguments described by \ref CallConv
//!     and \ref FuncDetail into registers specified by the user.
//!
//! It's a lot of concepts where each represents one step in a function frame calculation. It can be used to create
//! function prologs, epilogs, and also to calculate information necessary to perform function calls.


//! \defgroup asmjit_logging Logging
//! \brief Logging and formatting.
//!
//! ### Overview
//!
//! The initial phase of a project that generates machine code is not always smooth. Failure cases are common not just
//! at the beginning phase, but also during the development or refactoring. AsmJit provides logging functionality to
//! address this issue. AsmJit does already a good job with function overloading to prevent from emitting unencodable
//! instructions, but it can't prevent from emitting machine code that is correct at instruction level, but doesn't
//! work when it's executed asa whole. Logging has always been an important part of AsmJit's infrastructure and looking
//! at logs can sometimes reveal code generation issues quickly.
//!
//! AsmJit provides API for logging and formatting:
//!
//!   - \ref Logger - A logger that you can pass to \ref CodeHolder and all emitters that inherit from \ref BaseEmitter.
//!
//!   - \ref FormatOptions - Formatting options that can change how instructions and operands are formatted.
//!
//!   - \ref Formatter - A namespace that provides functions that can format input data like \ref Operand, \ref Reg,
//!     \ref Label, and \ref BaseNode into \ref String.
//!
//! AsmJit's \ref Logger serves the following purposes:
//!
//!   - Provides a basic foundation for logging.
//!
//!   - Abstract class leaving the implementation on users. The following built-in implementations are provided for
//!     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 FormatFlags
//!   - \ref FormatIndentationGroup
//!
//! \section logging Logging
//!
//! A \ref Logger is typically attached to a \ref CodeHolder, which propagates it to all attached emitters
//! automatically. The example below illustrates how to use \ref FileLogger that outputs to standard output:
//!
//! ```
//! #include <asmjit/core.h>
//! #include <stdio.h>
//!
//! using namespace asmjit;
//!
//! int main() {
//!   JitRuntime rt;               // Runtime specialized for JIT code execution.
//!   FileLogger logger(stdout);   // Logger should always survive CodeHolder.
//!
//!   CodeHolder code;             // Holds code and relocation information.
//!   code.init(rt.environment(),  // Initialize code to match the JIT environment.
//!             rt.cpu_features());
//!   code.set_logger(&logger);    // Attach the `logger` to `code` holder.
//!
//!   // ... code as usual, everything emitted will be logged to `stdout` ...
//!   return 0;
//! }
//! ```
//!
//! If output to FILE stream is not desired it's possible to use \ref StringLogger, which concatenates everything
//! into a multi-line string:
//!
//! ```
//! #include <asmjit/core.h>
//! #include <stdio.h>
//! #include <utility>
//!
//! using namespace asmjit;
//!
//! int main() {
//!   JitRuntime rt;               // Runtime specialized for JIT code execution.
//!   StringLogger logger;         // Logger should always survive CodeHolder.
//!
//!   CodeHolder code;             // Holds code and relocation information.
//!   code.init(rt.environment(),  // Initialize code to match the JIT environment.
//!             rt.cpu_features());
//!   code.set_logger(&logger);    // Attach the `logger` to `code` holder.
//!
//!   // ... code as usual, logging will be concatenated to logger string  ...
//!
//!   // You can either use the string from StringLogger directly or you can
//!   // move it. Logger::data() returns its content as null terminated char[].
//!   printf("Logger content: %s\n", logger.data());
//!
//!   // It can be moved into your own string like this:
//!   String content = std::move(logger.content());
//!   printf("The same content: %s\n", content.data());
//!
//!   return 0;
//! }
//! ```
//!
//! \section formatting Formatting
//!
//! AsmJit uses \ref Formatter to format inputs that are then passed to \ref Logger. Formatting is public and can be
//! used by AsmJit users as well. The most important thing to know regarding formatting is that \ref Formatter always
//! appends to the output string, so it can be used to build complex strings without having to concatenate
//! intermediate strings.
//!
//! The first example illustrates how to format operands:
//!
//! ```
//! #include <asmjit/x86.h>
//! #include <stdio.h>
//!
//! using namespace asmjit;
//!
//! void logOperand(Arch arch, const Operand_& op) {
//!   // The emitter is optional (named labels and virtual registers need it).
//!   BaseEmitter* emitter = nullptr;
//!
//!   // No flags by default.
//!   FormatFlags format_flags = FormatFlags::kNone;
//!
//!   StringTmp<128> sb;
//!   Formatter::format_operand(sb, format_flags, emitter, arch, op);
//!   printf("%s\n", sb.data());
//! }
//!
//! void formattingExample() {
//!   using namespace x86;
//!
//!   // Architecture is not part of operand, it must be passed explicitly.
//!   // Format flags. We pass it explicitly also to 'logOperand' to make
//!   // compatible with what AsmJit normally does.
//!   Arch arch = Arch::kX64;
//!
//!   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/x86.h>
//! #include <stdio.h>
//! #include <utility>
//!
//! using namespace asmjit;
//!
//! template<typename... 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.
//!   FormatFlags format_flags = FormatFlags::kNone;
//!
//!   // The formatter expects operands in an array.
//!   Operand_ operands[] { std::forward<Args>(args)... };
//!
//!   StringTmp<128> sb;
//!   Formatter::format_instruction(
//!     sb, format_flags, emitter, arch, inst, operands, sizeof...(args));
//!   printf("%s\n", sb.data());
//! }
//!
//! void formattingExample() {
//!   using namespace x86;
//!
//!   // Architecture is not part of operand, it must be passed explicitly.
//!   // Format flags. We pass it explicitly also to 'logOperand' to make
//!   // compatible with what AsmJit normally does.
//!   Arch arch = Arch::kX64;
//!
//!   // Prints 'mov rax, rcx'.
//!   logInstruction(arch, BaseInst(Inst::kIdMov), rax, rcx);
//!
//!   // Prints 'vaddpd zmm0, zmm1, [rax] {1to8}'.
//!   logInstruction(arch,
//!                  BaseInst(Inst::kIdVaddpd),
//!                  zmm0, zmm1, ptr(rax)._1to8());
//!
//!   // BaseInst abstracts instruction id, instruction options, and extra_reg.
//!   // Prints 'lock add [rax], rcx'.
//!   logInstruction(arch,
//!                  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, InstOptions::kX86_ZMask, k2),
//!                  zmm0, zmm1, ptr(rax));
//! }
//! ```
//!
//! And finally, the example below illustrates how to use a built-in function to format the content of
//! \ref BaseBuilder, which consists of nodes:
//!
//! ```
//! #include <asmjit/core.h>
//! #include <stdio.h>
//!
//! using namespace asmjit;
//!
//! void formattingExample(BaseBuilder* builder) {
//!   FormatOptions format_options {};
//!
//!   // This also shows how temporary strings can be used.
//!   StringTmp<512> sb;
//!
//!   // FormatNodeList requires the String for output, formatting flags, which
//!   // were zero (no extra flags), and the builder instance, which we have
//!   // provided. An overloaded version also exists, which accepts begin and
//!   // and end nodes, which can be used to only format a range of nodes.
//!   Formatter::format_node_list(sb, format_options, builder);
//!
//!   // You can do whatever else with the string, it's always null terminated,
//!   // so it can be passed to C functions like printf().
//!   printf("%s\n", sb.data());
//! }
//! ```


//! \defgroup asmjit_error_handling Error Handling
//! \brief Error handling.
//!
//! ### Overview
//!
//! AsmJit uses error codes to represent and return errors. Every function that can fail returns an \ref Error code.
//! Exceptions are never thrown by AsmJit itself even in extreme conditions like out-of-memory, but it's possible to
//! override \ref ErrorHandler::handle_error() 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 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::handle_error(), 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
//!     Arena allocated 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.
//!
//! \section using_error_handler Using ErrorHandler
//!
//! An example of attaching \ref ErrorHandler to \ref CodeHolder.
//!
//! ```
//! #include <asmjit/x86.h>
//! #include <stdio.h>
//!
//! using namespace asmjit;
//!
//! // A simple error handler implementation, extend according to your needs.
//! class MyErrorHandler : public ErrorHandler {
//! public:
//!   void handle_error(Error err, const char* message, BaseEmitter* origin) override {
//!     printf("AsmJit error: %s\n", message);
//!   }
//! };
//!
//! int main() {
//!   JitRuntime rt;
//!
//!   MyErrorHandler myErrorHandler;
//!   CodeHolder code;
//!
//!   code.init(rt.environment(), rt.cpu_features());
//!   code.set_error_handler(&myErrorHandler);
//!
//!   x86::Assembler a(&code);
//!   // ... code generation ...
//!
//!   return 0;
//! }
//! ```
//!
//! Useful classes in error handling group:
//!
//!   - See \ref DebugUtils that provides utilities useful for debugging.
//!   - See \ref Error that lists error codes that AsmJit uses.
//!   - See \ref ErrorHandler for more details about error handling.


//! \defgroup asmjit_instruction_db Instruction DB
//! \brief Instruction database (introspection, read/write, validation, ...).
//!
//! ### Overview
//!
//! AsmJit provides a public instruction database that can be used to query information about a complete instruction.
//! The instruction database requires the knowledge of the following:
//!
//!   - \ref BaseInst - Base instruction that contains instruction id, options, and a possible extra-register that
//!     represents either REP prefix counter or AVX-512 selector (mask).
//!
//!   - \ref Operand - Represents operands of an instruction.
//!
//! Each instruction can be then queried for the following information:
//!
//!   - \ref InstRWInfo - Read/write information of instruction and its 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
//! projects that parse user input, like AsmTK project.
//!
//! \section instruction_query Instruction Queries
//!
//! The instruction query API is provided by \ref InstAPI namespace. The following queries are possible:
//!
//!   - \ref InstAPI::query_rw_info() - queries read/write information of the given instruction and its operands.
//!     Includes also CPU flags read/written.
//!
//!   - \ref InstAPI::query_features() - 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_instinfo.cpp">asmjit_test_instinfo.cpp</a>
//!     can be also used as a reference about accessing instruction information.
//!
//! \section instruction_validation Instruction Validation
//!
//! The instruction validation API is provided by \ref InstAPI namespace in the similar fashion like the Query API,
//! however, validation can also be turned on at \ref BaseEmitter level. The following is possible:
//!
//!   - \ref InstAPI::validate() - low-level instruction validation function that is used internally by emitters
//!     if strict validation is enabled.
//!
//!   - \ref BaseEmitter::add_diagnostic_options() - can be used to enable validation at emitter level, see \ref
//!     DiagnosticOptions.


//! \defgroup asmjit_virtual_memory Virtual Memory
//! \brief Virtual memory management.
//!
//! ### Overview
//!
//! AsmJit's virtual memory management is divided into three main categories:
//!
//!   - \ref VirtMem namespace provides low level interface that can be used for cross-platform  virtual memory
//!     allocation. 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.
//!
//!   - \ref JitAllocator provides middle level API, which is built on top of \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.
//!
//!   - \ref JitRuntime provides high level API, 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.
//!
//! \section hardened_environments 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.


//! \defgroup asmjit_support Support
//! \brief Provides utility functions, arena allocator, and arena-backed containers.
//!
//! ### Overview
//!
//! This functionality is primarily intended for AsmJit's internal use, but is exposed to users since it may be used
//! in public headers as well. \ref Arena and arena-backed containers are used by many AsmJit classes, which are public,
//! and AsmJit doesn't try to hide the use.
//!
//! The arena allocator is used for most allocations within AsmJit. It is optimized for fast allocation of small objects,
//! avoiding the overhead of `malloc()`. Memory is managed in large blocks that are split into smaller chunks, reducing
//! fragmentation and improving performance.
//!
//! Releasing an arena allocator invalidates memory it holds, allowing efficient cleanup without per-object destruction.
//! Long-lived objects typically reset their data in the destructor or via `reset()` for allocation reuse. All AsmJit
//! containers use \ref Arena allocator.
//!
//! \section arena_allocators Arena Allocators
//!
//!   - \ref Arena - Arena memory allocator that quickly allocates the requested memory from larger chunks and then
//!     frees everything at once. AsmJit uses Arena allocators almost everywhere as almost everything is short-lived.
//!
//!   - \ref ArenaTmp - A temporary \ref Arena 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 ArenaTmp,
//!     otherwise it would act as \ref Arena with one preallocated block at the beginning.
//!
//! \section arena_containers Arena-Allocated Containers
//!
//!   - \ref ArenaString - Arena allocated string.
//!   - \ref ArenaHash   - Arena allocated hash table.
//!   - \ref ArenaTree   - Arena allocated red-black tree.
//!   - \ref ArenaList   - Arena allocated double-linked list.
//!   - \ref ArenaVector - Arena allocated vector.
//!
//! \section using_arena_containers Using Arena-Allocated Containers
//!
//! The most common data structure exposed by AsmJit is \ref ArenaVector. It's very similar to `std::vector`, but the
//! implementation doesn't use exceptions and uses the mentioned \ref Arena allocator for increased performance and
//! decreased memory footprint. 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.
//!
//! Most of the time, AsmJit returns a non-owning Span instead of a reference to the allocator when it returns an array
//! of something. For example, the following APIs in \ref CodeHolder return a non-owning \ref Span instance:
//!
//! ```
//! using namespace asmjit;
//!
//! void example(CodeHolder& code) {
//!   // Contains all section entries managed by CodeHolder.
//!   Span<Section*> sections = code.sections();
//!
//!   // Contains all label entries managed by CodeHolder.
//!   Span<LabelEntry> label_entries = code.label_entries();
//!
//!   // Contains all relocation entries managed by CodeHolder.
//!   Span<RelocEntry*> reloc_entries = code.reloc_entries();
//! }
//! ```
//!
//! \ref Span has overloaded array access operator to make it possible to access its elements through operator[].
//! Some standard functions like \ref ArenaVector::is_empty(), \ref ArenaVector::size(), and \ref ArenaVector::data() are
//! provided as well. Vectors are also iterable through a range-based for loop:
//!
//! ```
//! using namespace asmjit;
//!
//! void example(CodeHolder& code) {
//!   Span<LabelEntry> label_entries = code.label_entries();
//!   for (size_t label_id = 0; label_id < label_entries.size(); label_id++) {
//!     const LabelEntry& le = label_entries[label_id];
//!     if (le.is_bound()) {
//!       printf("Bound Label #%u at offset=%llu\n", uint32_t(label_id), (unsigned long long)le.offset());
//!     }
//!   }
//! }
//! ```
//!
//! \section design_considerations Design Considerations
//!
//! Arena-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 an \ref ArenaVector it's required to pass the allocator as the first argument,
//! so it can be used in case that the vector needs to grow. Such function also returns an error, which must be
//! propagated to the caller.
//!
//! ```
//! using namespace asmjit;
//!
//! Error example(Arena& arena) {
//!   ArenaVector<int> vector;
//!
//!   // Unfortunately, arena must be provided to all functions that mutate
//!   // the vector. However, AsmJit users should never need to do this as all
//!   // manipulation should be done through public API, which takes care of
//!   // this.
//!   for (int i = 0; i < 100; i++) {
//!     ASMJIT_PROPAGATE(vector.append(arena, i));
//!   }
//!
//!   // By default vector's destructor doesn't release anything as it knows
//!   // that its content is allocated by Arena. However, \ref ArenaVector::release
//!   // can be used to explicitly release the vector data back to the allocator if
//!   // necessary
//!   vector.release(arena);
//! }
//! ```
//!
//! Containers like \ref ArenaVector also provide a functionality to reserve a certain number of items before any items
//! are added to it. This approach is used internally in most places as it allows to prepare space for data that will
//! be added to some container before the data itself was created.
//!
//! ```
//! using namespace asmjit;
//!
//! Error example(Arena& arena) {
//!   ArenaVector<int> vector;
//!
//!   ASMJIT_PROPAGATE(vector.reserve_additional(arena, 100));
//!   for (int i = 0; i < 100; i++) {
//!     // Cannot fail.
//!     vector.append_unchecked(arena, i);
//!   }
//!
//!   vector.release(arena);
//! }
//! ```


//! \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:
//!
//! \section string_utilities String Utilities
//!
//!   - \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.
//!
//! \section codegen_utilities Code Generation Utilities
//!
//!   - \ref ConstPool - Constant pool used by \ref BaseCompiler, but also available to users that may find use of it.
//!
//! \section support_utilities Support Functionality Used by AsmJit
//!
//!   - \ref Support namespace provides many other utility functions and classes that are used by AsmJit, and made
//!     public.


//! \defgroup asmjit_x86 X86 Backend
//! \brief X86/X64 backend.


//! \defgroup asmjit_arm ARM Commons
//! \brief ARM commons shared between AArch32 and AArch64.


//! \defgroup asmjit_a64 AArch64 Backend
//! \brief AArch64 backend.

//! \defgroup asmjit_ujit Universal JIT
//! \brief Universal JIT abstracts X86, X86_64, and AArch64 code generation.
//!
//! ### Overview
//!
//! Universal JIT (UJIT) is an abstraction that uses AsmJit's Compiler, but provides target independent API that
//! users can use to target multiple target architectures at a time. The goal of Universal JIT is not to provide
//! its own IR. Instead, it translates user calls into target-dependent instructions (or instruction sequences)
//! and allows users to switch to target-specific assembly only where required for extra performance.
//!
//! \warning UJIT is still in an experimental phase, expect minor API breaks in the future especially towards API
//! stabilization.
//!
//! API Overview
//!
//! Compiler:
//!
//!  - \ref ujit::UniCompiler - UniCompiler that wraps an existing \ref ujit::BackendCompiler.
//!  - \ref ujit::BackendCompiler - alias of a platform-dependent Compiler (\ref x86::Compiler or \ref a64::Compiler).
//!
//! Operands:
//!
//!  - \ref ujit::Gp - alias of a platform-dependent general-purpose register (\ref x86::Gp, \ref a64::Gp).
//!  - \ref ujit::Vec - alias of a platform-dependent vector register (\ref x86::Vec, \ref a64::Vec).
//!  - \ref ujit::Mem - alias of a platform-dependent memory operand (\ref x86::Mem, \ref a64::Mem).
//!
//! Conditions:
//!
//!  - \ref ujit::CondCode - alias of a platform-dependent condition code (\ref x86::CondCode, a64::CondCode).
//!  - \ref ujit::UniCondition - platform-independent condition representation that can be used with some ujit
//!    instructions.
//!
//! Instructions:
//!
//!  - \ref ujit::UniOpCond - instruction that can be used by \ref ujit::UniCondition.
//!  - \ref ujit::UniOpM - instruction with a single `[mem]` operand.
//!  - \ref ujit::UniOpRM - instruction with `[reg, mem]` operands.
//!  - \ref ujit::UniOpMR - instruction with `[mem, reg]` operands.
//!  - \ref ujit::UniOpRR - instruction with `[reg, reg]` operands.
//!  - \ref ujit::UniOpRRR - instruction with `[reg, reg, reg]` operands.
//!  - \ref ujit::UniOpVR - instruction with `[vec, reg]` operands.
//!  - \ref ujit::UniOpVM - instruction with `[vec, mem]` operands.
//!  - \ref ujit::UniOpMV - instruction with `[mem, vec]` operands.
//!  - \ref ujit::UniOpVV - instruction with `[vec, vec]` operands.
//!  - \ref ujit::UniOpVVI - instruction with `[vec, vec, imm]` operands.
//!  - \ref ujit::UniOpVVV - instruction with `[vec, vec, vec]` operands.
//!  - \ref ujit::UniOpVVVI - instruction with `[vec, vec, vec, imm]` operands.
//!  - \ref ujit::UniOpVVVV - instruction with `[vec, vec, vec, vec]` operands.
//!
//! ### UniCompiler Example
//!
//! Using UniCompiler is like using a regular platform-dependent AsmJit's Compiler - UniCompiler wraps its API
//! and delegates most of non-emit calls to Compiler, however, it abstracts how instructions are emitted so it
//! could offer universal API for both general-purpose and SIMD instructions. The following example demonstrates
//! how to use it:
//!
//! ```
//! #include <asmjit/ujit.h>
//! #include <stdio.h>
//!
//! using namespace asmjit;
//!
//! int main() {
//!   // Signature of the generated function.
//!   using Func = void (*)(uint32_t* dst, const uint32_t* src1, const uint32_t* src2);
//!
//!   JitRuntime rt;                           // Creates a JIT runtime that holds executable code.
//!   FileLogger logger(stdout);               // Creates a logger that prints to stdout.
//!   CodeHolder code;                         // Creates a CodeHolder - holds code and other information.
//!
//!   code.init(rt.environment(),              // Initializes CodeHolder to match the JIT environment.
//!             rt.cpu_features());
//!   code.set_logger(&logger);                // Initializes CodeHolder's logger.
//!
//!   ujit::BackendCompiler backend_cc(&code); // Creates a regular backend compiler instance.
//!   ujit::UniCompiler uc(&backend_cc,        // Creates UniCompiler with attached backend compiler.
//!                        rt.cpu_features(),  // CPU features must be passed explicitly.
//!                        rt.cpu_hints());    // CPU hints must be passed explicitly.
//!
//!   // Begin a function of the required signature (this exactly matches the Compiler use).
//!   FuncNode* func = uc.add_func(FuncSignature::build<void, uint32_t*, const uint32_t*, const uint32_t*>());
//!
//!   ujit::Gp d_ptr = uc.new_gp_ptr();        // Creates a destination pointer.
//!   ujit::Gp a_ptr = uc.new_gp_ptr();        // Creates a first source pointer.
//!   ujit::Gp b_ptr = uc.new_gp_ptr();        // Creates a second source pointer.
//!
//!   func->set_arg(0, d_ptr);                 // Assigns 1st argument.
//!   func->set_arg(1, a_ptr);                 // Assigns 2nd argument.
//!   func->set_arg(2, b_ptr);                 // Assigns 3rd argument.
//!
//!   ujit::Vec v0 = uc.new_vec128();          // Creates a 128-bit vector register.
//!   ujit::Vec v1 = uc.new_vec128();          // Creates a 128-bit vector register.
//!
//!   uc.v_loadu128(v0, ujit::mem_ptr(a_ptr)); // Unaligned load of 128 bits from [a_ptr] into v0.
//!   uc.v_loadu128(v1, ujit::mem_ptr(b_ptr)); // Unaligned load of 128 bits from [b_ptr] into v1.
//!   uc.v_add_i32(v0, v0, v1);                // Vector addition of 4 32-bit integers.
//!   uc.v_storeu128(ujit::mem_ptr(d_ptr), v0);// Unaligned store of 128 bits from v0 to [d_ptr].
//!
//!   uc.end_func();                           // End of the function body.
//!   Error err1 = uc.finalize();              // Translates and assembles the whole 'backend_cc' content.
//!
//!   if (err1 != Error::kOk) {
//!     // Handle a possible error returned by AsmJit as finalize can fail. One reason could be wrong operands
//!     // to some instruction or other platform constraints. Usually UniCompiler handles most of platform
//!     // constraints by itself, but this error code must be checked regardless.
//!     return 1;
//!   }
//!   // ----> Both BackendCompiler and UniCompiler are no longer needed from here and can be destroyed <----
//!
//!   Func fn;
//!   Error err2 = rt.add(&fn, &code);         // Add the generated code to JIT runtime (executable memory).
//!
//!   if (err2 != Error::kOk) {
//!     // Handle a possible error returned by AsmJit. This would be either out of executable memory or failure
//!     // to allocate it (for example excessive user-space hardening or making the allocation of executable
//!     // memory forbidden).
//!     return 1;
//!   }
//!   // ----> CodeHolder is no longer needed from here and can be destroyed <----
//!
//!   // Input data.
//!   static constexpr uint32_t a_data[4] = {1u,2u,4u,8u};
//!   static constexpr uint32_t b_data[4] = {6u,4u,3u,1u};
//!
//!   // Output data.
//!   uint32_t d_data[4] {};
//!
//!   // Calls the generated function.
//!   fn(d_data, a_data, b_data);
//!
//!   // Prints both inputs and the output.
//!   printf("a_data={%u,%u,%u,%u}\n", a_data[0], a_data[1], a_data[2], a_data[3]);
//!   printf("b_data={%u,%u,%u,%u}\n", b_data[0], b_data[1], b_data[2], b_data[3]);
//!   printf("d_data={%u,%u,%u,%u}\n", d_data[0], d_data[1], d_data[2], d_data[3]);
//!
//!   // Explicitly removes the function from JIT runtime.
//!   rt.release(fn);
//!
//!   return 0;
//! }
//! ```
//!
//! ### Emitting Backend-Specific Code
//!
//! In cases, in which backend-specific code is required for performance reasons, it's possible to use the
//! underlying backend-specific Compiler, which is provided as a `cc` member of `UniCompiler`. The next example
//! demonstrates how to use AArch64-specific code path during code generation:
//!
//! ```
//! #include <asmjit/ujit.h>
//!
//! using namespace asmjit;
//!
//! void emit_backend_specific_code(UniCompiler& uc, const ujit::Gp& a, const ujit::Gp& b, const ujit::Gp& c) {
//! #if defined(ASMJIT_UJIT_AARCH64)
//!   // Emit aarch64 specific code via `uc.cc`:
//!   uc.cc->orn(a, b, c);
//! #else
//!   // Generic code.
//!   ujit::Gp tmp = uc.new_similar_reg(a);
//!   uc.not_(tmp, c);
//!   uc.or_(a, b, tmp);
//! #endif
//! ```
//!

//! \cond INTERNAL
//! \defgroup asmjit_ra RA
//! \brief Register allocator internals.
//! \endcond

} // {asmjit}

#include "asmjit-scope-begin.h"
#include "core/api-config.h"
#include "core/archcommons.h"
#include "core/archtraits.h"
#include "core/arena.h"
#include "core/arenahash.h"
#include "core/arenalist.h"
#include "core/arenapool.h"
#include "core/arenastring.h"
#include "core/arenatree.h"
#include "core/arenavector.h"
#include "core/assembler.h"
#include "core/builder.h"
#include "core/codebuffer.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/fixup.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/span.h"
#include "core/string.h"
#include "core/support.h"
#include "core/target.h"
#include "core/type.h"
#include "core/virtmem.h"
#include "asmjit-scope-end.h"

#endif // ASMJIT_CORE_H_INCLUDED
