diff --git a/src/asmjit/core.h b/src/asmjit/core.h
index 834d544..8d28815 100644
--- a/src/asmjit/core.h
+++ b/src/asmjit/core.h
@@ -17,7 +17,7 @@ namespace asmjit {
//! functionality is within \ref asmjit namespace and architecture specific functionality is always in its own
//! namespace. For example \ref asmjit::x86 provides both 32-bit and 64-bit X86 code generation.
//!
-//! \section main_groups Documentation Groups
+//! \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:
@@ -78,7 +78,7 @@ namespace asmjit {
//! output from \ref Logger is always necessary when filling bug reports. In other words, using logging and proper error
//! handling can save a lot of time during the development and can also save users from submitting issues.
//!
-//! \section main_other Other Pages
+//! \section other_pages Other Pages
//!
//! - Class List - List of classes sorted alphabetically
//! - AsmJit Namespace - List of symbols provided by `asmjit` namespace
@@ -96,6 +96,8 @@ namespace asmjit {
//! 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:
@@ -147,7 +149,7 @@ namespace asmjit {
//! - **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).
//!
-//! ### Static Builds and Embedding
+//! \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.
@@ -159,7 +161,31 @@ namespace asmjit {
//! otherwise AsmJit would use dynamic library imports in \ref ASMJIT_API decorator. The recommendation is to define
//! this macro across the whole project that uses AsmJit this way.
//!
-//! ### Build Configuration
+//! \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)
+//!
+//! project(asmjit_consumer C CXX) # Both C and CXX are required.
+//! set(CMAKE_CXX_STANDARD 17) # C++11 and never is supported.
+//!
+//! set(ASMJIT_DIR "3rdparty/asmjit") # Location of AsmJit.
+//! set(ASMJIT_STATIC TRUE) # Force static build.
+//!
+//! add_subdirectory("${ASMJIT_DIR}") # This adds AsmJit as a part of your project.
+//!
+//! add_executable(asmjit_consumer asmjit_consumer.cpp)
+//! target_link_libraries(
+//! asmjit_consumer asmjit::asmjit) # This adds AsmJit as a dependency to your target.
+//! ```
+//!
+//! \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
@@ -173,7 +199,7 @@ namespace asmjit {
//! were not used. We only recommend using build configuration overrides in special situations, like using AsmJit in
//! release configuration with asserts enabled for whatever reason.
//!
-//! ### AsmJit Backends
+//! \section build_backends AsmJit Backends
//!
//! AsmJit currently supports only X86/X64 backend, but the plan is to add more backends in the future. By default
//! AsmJit builds only the host backend, which is auto-detected at compile-time, but this can be overridden.
@@ -182,7 +208,7 @@ namespace asmjit {
//! - \ref ASMJIT_NO_AARCH64 - Disables AArch64 backend.
//! - \ref ASMJIT_NO_FOREIGN - Disables the support for foreign architecture backends, only keeps a native backend.
//!
-//! ### AsmJit Compilation Options
+//! \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,
@@ -195,9 +221,9 @@ namespace asmjit {
//! versions are used at the same time. This option can be debugging a little simpler as there would not be ABI
//! tag after `asmjit::` namespace. Otherwise asmjit would look like `asmjit::_abi_1_13::`, for example.
//!
-//! ### Features Selection
+//! \section build_features Build Features
//!
-//! AsmJit builds by defaults all supported features, which includes all emitters, logging, instruction validation and
+//! 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.
@@ -235,7 +261,7 @@ namespace asmjit {
//! removed APIs and should serve as a how-to guide for people that want to port existing code to work with the
//! newest AsmJit.
//!
-//! ### Tips
+//! \section tips Tips
//!
//! Useful tips before you start:
//!
@@ -247,6 +273,8 @@ namespace asmjit {
//! because some compilers would warn about that. If your project compiles fine with `ASMJIT_NO_DEPRECATED`
//! it's not using anything, which was deprecated.
//!
+//! \section api_changes API Changes
+//!
//! ### Changes committed at 2024-01-01
//!
//! Core changes:
@@ -513,7 +541,7 @@ namespace asmjit {
//!
//! \note CodeHolder examples use \ref x86::Assembler as abstract interfaces cannot be used to generate code.
//!
-//! ### CodeHolder & Emitters
+//! \section code_holder_and_emitters CodeHolder & Emitters
//!
//! The example below shows how the mentioned classes interact to generate X86 code:
//!
@@ -562,7 +590,7 @@ namespace asmjit {
//! - \ref asmjit_builder - Low-level emitter that emits to a \ref BaseNode list.
//! - \ref asmjit_compiler - High-level emitter that provides register allocation.
//!
-//! ### Targets and JitRuntime
+//! \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
@@ -631,7 +659,7 @@ namespace asmjit {
//! }
//! ```
//!
-//! ### Explicit Code Relocation
+//! \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
@@ -817,7 +845,7 @@ namespace asmjit {
//! }
//! ```
//!
-//! ### Label Offsets and Links
+//! \section labels Label Offsets and Links
//!
//! When a label that is not yet bound is used by the Assembler, it creates a \ref LabelLink, which is then added to
//! a \ref LabelEntry. These links are also created if a label is used in a different section than in which it was
@@ -871,7 +899,7 @@ namespace asmjit {
//! }
//! ```
//!
-//! ### Sections
+//! \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)
@@ -988,7 +1016,7 @@ namespace asmjit {
//!
//! \note Assembler examples use \ref x86::Assembler as abstract interfaces cannot be used to generate code.
//!
-//! ### Operand Basics
+//! \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.
@@ -1028,7 +1056,7 @@ namespace asmjit {
//! - \ref Label - used to reference a location in code or data. Labels must be created by the \ref BaseEmitter or
//! by \ref CodeHolder. Each label has its unique id per \ref CodeHolder instance.
//!
-//! ### Operand Manipulation
+//! \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
@@ -1099,7 +1127,7 @@ namespace asmjit {
//! BaseEmitter::newLabel(), which creates a label entry and returns a \ref Label operand with the id that refers
//! to it. Such label then can be used by emitters.
//!
-//! ### Memory Operands
+//! \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).
@@ -1232,7 +1260,7 @@ namespace asmjit {
//! }
//! ```
//!
-//! ### Assembler Examples
+//! \section examples Assembler Examples
//!
//! - \ref x86::Assembler provides many X86/X64 examples.
@@ -1252,7 +1280,7 @@ namespace asmjit {
//! compatibility with the existing \ref BaseAssembler emitter so users can move from assembler to builder when needed,
//! for example to implement post-processing, which is not possible with Assembler.
//!
-//! ### Builder Nodes
+//! \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.
@@ -1278,7 +1306,7 @@ namespace asmjit {
//!
//! - Other nodes are provided by \ref asmjit_compiler infrastructure.
//!
-//! ### Builder Examples
+//! \section builder_examples Examples
//!
//! - \ref x86::Builder - Builder implementation targeting X86 and X86_64 architectures.
//! - \ref a64::Builder - Builder implementation targeting AArch64 architecture.
@@ -1305,7 +1333,7 @@ namespace asmjit {
//! return value(s) are handled by assigning virtual registers to them. Similarly, function calls are handled the same
//! way.
//!
-//! ### Compiler Nodes
+//! \section compiler_nodes Compiler Nodes
//!
//! \ref BaseCompiler adds some nodes that are required for function generation and invocation:
//!
@@ -1316,12 +1344,12 @@ namespace asmjit {
//! \ref BaseCompiler also makes the use of passes (\ref Pass) and automatically adds an architecture-dependent
//! register allocator pass to the list of passes when attached to \ref CodeHolder.
//!
-//! ### Compiler Examples
+//! \section compiler_examples Compiler Examples
//!
//! - \ref x86::Compiler - Compiler implementation targeting X86 and X86_64 architectures.
//! - \ref a64::Compiler - Compiler implementation targeting AArch64 architecture.
//!
-//! ### Compiler Tips
+//! \section compiler_tips Compiler Tips
//!
//! Users of AsmJit have done mistakes in the past, this section should provide some useful tips for beginners:
//!
@@ -1423,7 +1451,7 @@ namespace asmjit {
//! - \ref FormatFlags
//! - \ref FormatIndentationGroup
//!
-//! ### Logging
+//! \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:
@@ -1481,7 +1509,7 @@ namespace asmjit {
//! }
//! ```
//!
-//! ### Formatting
+//! \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
@@ -1631,7 +1659,7 @@ namespace asmjit {
//! Zone memory and the ownership of memory it allocates always ends with the instance that allocated it. If
//! using this approach please never jump outside the life-time of \ref CodeHolder and \ref BaseEmitter.
//!
-//! ### Using ErrorHandler
+//! \section using_error_handler Using ErrorHandler
//!
//! An example of attaching \ref ErrorHandler to \ref CodeHolder.
//!
@@ -1695,7 +1723,7 @@ namespace asmjit {
//! valid. This is useful for making sure that what user tries to emit is correct and it can be also used by other
//! projects that parse user input, like AsmTK project.
//!
-//! ### Query API
+//! \section instruction_query Instruction Queries
//!
//! The instruction query API is provided by \ref InstAPI namespace. The following queries are possible:
//!
@@ -1709,7 +1737,7 @@ namespace asmjit {
//! - asmjit_test_instinfo.cpp
//! can be also used as a reference about accessing instruction information.
//!
-//! ### Validation API
+//! \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:
@@ -1748,7 +1776,7 @@ namespace asmjit {
//! example. \ref JitAllocator then tracks used space of each page it maintains. Internally, \ref JitAllocator uses
//! two bit arrays to track occupied regions in each allocated block of pages.
//!
-//! ### Hardened Environments
+//! \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
@@ -1796,7 +1824,7 @@ namespace asmjit {
//! its data in destructor or in their reset() member function for a future reuse. For this purpose all containers in
//! AsmJit are also zone allocated.
//!
-//! ### Zone Allocation
+//! \section zone_allocation Zone Allocation
//!
//! - \ref Zone - Incremental zone memory allocator with minimum features. It can only allocate memory without the
//! possibility to return it back to the allocator.
@@ -1808,7 +1836,7 @@ namespace asmjit {
//! - \ref ZoneAllocator - A wrapper of \ref Zone that provides the capability of returning memory to the allocator.
//! Such memory is stored in a pool for later reuse.
//!
-//! ### Zone Allocated Containers
+//! \section zone_containers Zone Allocated Containers
//!
//! - \ref ZoneString - Zone allocated string.
//! - \ref ZoneHash - Zone allocated hash table.
@@ -1818,7 +1846,7 @@ namespace asmjit {
//! - \ref ZoneVector - Zone allocated vector.
//! - \ref ZoneBitVector - Zone allocated vector of bits.
//!
-//! ### Using Zone Allocated Containers
+//! \section using_zone_containers Using Zone Allocated Containers
//!
//! The most common data structure exposed by AsmJit is \ref ZoneVector. It's very similar to `std::vector`, but the
//! implementation doesn't use exceptions and uses the mentioned \ref ZoneAllocator for performance reasons. You don't
@@ -1862,7 +1890,7 @@ namespace asmjit {
//! }
//! ```
//!
-//! ### Design Considerations
+//! \section design_considerations Design Considerations
//!
//! Zone-allocated containers do not store the allocator within the container. This decision was made to reduce the
//! footprint of such containers as AsmJit tooling, especially Compiler's register allocation, may use many instances
@@ -1923,7 +1951,7 @@ namespace asmjit {
//! AsmJit uses and provides utility classes and functions, that can be used with AsmJit. The functionality can be
//! divided into the following topics:
//!
-//! ### String Functionality
+//! \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.
@@ -1933,11 +1961,11 @@ namespace asmjit {
//!
//! - \ref FixedString - Fixed string container limited up to N characters.
//!
-//! ### Code Generation Utilities
+//! \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.
//!
-//! ### Support Functionality Used by AsmJit
+//! \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.
diff --git a/src/asmjit/core/archtraits.h b/src/asmjit/core/archtraits.h
index 9f08dea..a10a41e 100644
--- a/src/asmjit/core/archtraits.h
+++ b/src/asmjit/core/archtraits.h
@@ -196,7 +196,7 @@ struct ArchTraits {
//! Maps scalar TypeId values (from TypeId::_kIdBaseStart) to register types, see \ref TypeId.
Support::Array _typeIdToRegType;
- //! Word name identifiers of 8-bit, 16-bit, 32-biit, and 64-bit quantities that appear in formatted text.
+ //! Word name identifiers of 8-bit, 16-bit, 32-bit, and 64-bit quantities that appear in formatted text.
ArchTypeNameId _typeNameIdTable[4];
//! \}
diff --git a/src/asmjit/core/assembler.h b/src/asmjit/core/assembler.h
index d53d9e5..68f3d5a 100644
--- a/src/asmjit/core/assembler.h
+++ b/src/asmjit/core/assembler.h
@@ -17,10 +17,9 @@ ASMJIT_BEGIN_NAMESPACE
//! Base assembler.
//!
-//! This is a base class that provides interface used by architecture specific
-//! assembler implementations. Assembler doesn't hold any data, instead it's
-//! attached to \ref CodeHolder, which provides all the data that Assembler
-//! needs and which can be altered by it.
+//! This is a base class that provides interface used by architecture specific assembler implementations. Assembler
+//! doesn't hold any data, instead it's attached to \ref CodeHolder, which provides all the data that Assembler needs
+//! and which can be altered by it.
//!
//! Check out architecture specific assemblers for more details and examples:
//!
@@ -63,8 +62,7 @@ public:
//! Sets the current position in the CodeBuffer to `offset`.
//!
- //! \note The `offset` cannot be greater than buffer size even if it's
- //! within the buffer's capacity.
+ //! \note The `offset` cannot be greater than buffer size even if it's within the buffer's capacity.
ASMJIT_API Error setOffset(size_t offset);
//! Returns the start of the CodeBuffer in the current section.
diff --git a/src/asmjit/core/builder.h b/src/asmjit/core/builder.h
index 0de1923..6c10ecb 100644
--- a/src/asmjit/core/builder.h
+++ b/src/asmjit/core/builder.h
@@ -609,14 +609,12 @@ public:
template
ASMJIT_INLINE_NODEBUG const T* as() const noexcept { return static_cast(this); }
- //! Returns previous node or `nullptr` if this node is either first or not
- //! part of Builder/Compiler node-list.
+ //! Returns previous node or `nullptr` if this node is either first or not part of Builder/Compiler node-list.
ASMJIT_INLINE_NODEBUG BaseNode* prev() const noexcept { return _prev; }
- //! Returns next node or `nullptr` if this node is either last or not part
- //! of Builder/Compiler node-list.
+ //! Returns next node or `nullptr` if this node is either last or not part of Builder/Compiler node-list.
ASMJIT_INLINE_NODEBUG BaseNode* next() const noexcept { return _next; }
- //! Returns the type of the node, see `NodeType`.
+ //! Returns the type of the node, see \ref NodeType.
ASMJIT_INLINE_NODEBUG NodeType type() const noexcept { return _any._nodeType; }
//! Sets the type of the node, see `NodeType` (internal).
diff --git a/src/asmjit/core/compilerdefs.h b/src/asmjit/core/compilerdefs.h
index e2e74ce..4b2963c 100644
--- a/src/asmjit/core/compilerdefs.h
+++ b/src/asmjit/core/compilerdefs.h
@@ -18,7 +18,18 @@ class RAWorkReg;
//! \addtogroup asmjit_compiler
//! \{
-//! Virtual register data, managed by \ref BaseCompiler.
+//! Public virtual register interface, managed by \ref BaseCompiler.
+//!
+//! When a virtual register is created by \ref BaseCompiler a `VirtReg` is linked with the register operand id it
+//! returns. This `VirtReg` can be accessed via \ref BaseCompiler::virtRegByReg() function, which returns a pointer
+//! to `VirtReg`.
+//!
+//! In general, `VirtReg` should be only introspected as it contains important variables that are needed and managed
+//! by AsmJit, however, the `VirtReg` API can also be used to influence register allocation. For example there is
+//! a \ref VirtReg::setWeight() function, which could be used to increase a weight of a virtual register (thus make
+//! it hard to spill, for example). In addition, there is a \ref VirtReg::setHomeIdHint() function, which can be used
+//! to do an initial assignment of a physical register of a virtual register. However, AsmJit could still override
+//! the physical register assigned in some special cases.
class VirtReg {
public:
ASMJIT_NONCOPYABLE(VirtReg)
@@ -45,6 +56,8 @@ public:
//! True if this virtual register has assigned stack offset (can be only valid after register allocation pass).
uint8_t _hasStackSlot : 1;
uint8_t _reservedBits : 5;
+ //! Home register hint for the register allocator (initially unassigned).
+ uint8_t _homeIdHint = BaseReg::kIdBad;
//! Stack offset assigned by the register allocator relative to stack pointer (can be negative as well).
int32_t _stackOffset = 0;
@@ -145,6 +158,15 @@ public:
_stackOffset = stackOffset;
}
+ //! Tests whether this virtual register has assigned a physical register as a hint to the register allocator.
+ ASMJIT_INLINE_NODEBUG bool hasHomeIdHint() const noexcept { return _homeIdHint != BaseReg::kIdBad; }
+ //! Returns a physical register hint, which will be used by the register allocator.
+ ASMJIT_INLINE_NODEBUG uint32_t homeIdHint() const noexcept { return _homeIdHint; }
+ //! Assigns a physical register hint, which will be used by the register allocator.
+ ASMJIT_INLINE_NODEBUG void setHomeIdHint(uint32_t homeId) noexcept { _homeIdHint = uint8_t(homeId); }
+ //! Resets a physical register hint.
+ ASMJIT_INLINE_NODEBUG void resetHomeIdHint() noexcept { _homeIdHint = BaseReg::kIdBad; }
+
//! Returns a stack offset associated with a virtual register or explicit stack allocation.
//!
//! \note Always verify that the stack offset has been assigned by calling \ref hasStackSlot(). The return
diff --git a/src/asmjit/core/cpuinfo.cpp b/src/asmjit/core/cpuinfo.cpp
index b27588c..8ada345 100644
--- a/src/asmjit/core/cpuinfo.cpp
+++ b/src/asmjit/core/cpuinfo.cpp
@@ -488,7 +488,7 @@ static ASMJIT_FAVOR_SIZE void detectX86Cpu(CpuInfo& cpu) noexcept {
// The highest EAX that we understand.
constexpr uint32_t kHighestProcessedEAX = 0x8000001Fu;
- // Several CPUID calls are required to get the whole branc string. It's easier
+ // Several CPUID calls are required to get the whole brand string. It's easier
// to copy one DWORD at a time instead of copying the string a byte by byte.
uint32_t* brand = cpu._brand.u32;
do {
diff --git a/src/asmjit/core/cpuinfo.h b/src/asmjit/core/cpuinfo.h
index 2638146..fbb91e9 100644
--- a/src/asmjit/core/cpuinfo.h
+++ b/src/asmjit/core/cpuinfo.h
@@ -180,7 +180,7 @@ public:
#endif // !ASMJIT_NO_DEPRECATED
//! \}
- };
+ };
//! X86 specific features data.
struct X86 : public Data {
diff --git a/src/asmjit/core/radefs_p.h b/src/asmjit/core/radefs_p.h
index 5d6e87b..50e1eef 100644
--- a/src/asmjit/core/radefs_p.h
+++ b/src/asmjit/core/radefs_p.h
@@ -1120,7 +1120,8 @@ public:
: _workId(workId),
_virtId(vReg->id()),
_virtReg(vReg),
- _signature(vReg->signature()) {}
+ _signature(vReg->signature()),
+ _hintRegId(uint8_t(vReg->homeIdHint())) {}
//! \}