// AsmJit - Machine code generation for C++ // // * Official AsmJit Home Page: https://asmjit.com // * Official Github Repository: https://github.com/asmjit/asmjit // // Copyright (c) 2008-2020 The AsmJit Authors // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages // arising from the use of this software. // // Permission is granted to anyone to use this software for any purpose, // including commercial applications, and to alter it and redistribute it // freely, subject to the following restrictions: // // 1. The origin of this software must not be misrepresented; you must not // claim that you wrote the original software. If you use this software // in a product, an acknowledgment in the product documentation would be // appreciated but is not required. // 2. Altered source versions must be plainly marked as such, and must not be // misrepresented as being the original software. // 3. This notice may not be removed or altered from any source distribution. #ifndef ASMJIT_CORE_H_INCLUDED #define ASMJIT_CORE_H_INCLUDED //! Root namespace used by AsmJit. namespace asmjit { // ============================================================================ // [Documentation - mainpage] // ============================================================================ //! \mainpage API Reference //! //! AsmJit C++ API reference documentation generated by Doxygen. //! //! AsmJit library uses one global namespace called \ref asmjit, which provides //! the whole functionality. Core functionality is within \ref asmjit namespace //! and architecture specific functionality is always in its own namespace. For //! example \ref asmjit::x86 provides both 32-bit and 64-bit X86 code generation. //! //! \section main_groups Documentation Groups //! //! AsmJit documentation is structured into groups. Groups can be followed in //! order to learn AsmJit, but knowledge from multiple groups is required to //! use AsmJit properly: //! //! $$DOCS_GROUP_OVERVIEW$$ //! //! \note It's important to understand that in order to learn AsmJit all groups //! are important. Some groups can be omitted if a particular tool is out of //! interest - for example \ref asmjit_assembler users don't need to know about //! \ref asmjit_builder, but it's not the opposite. \ref asmjit_builder users //! must know about \ref asmjit_assembler as it also uses operands, labels, and //! other concepts. Similarly \ref asmjit_compiler users must know how both \ref //! asmjit_assembler and \ref asmjit_builder tools work. //! //! \section where_to_start Where To Start //! //! AsmJit \ref asmjit_core provides the following two classes that are essential //! from the code generation perspective: //! //! - \ref CodeHolder provides functionality //! to temporarily hold the generated code. It stores all the necessary //! information about the code - code buffers, sections, labels, symbols, //! and information about relocations. //! //! - \ref BaseEmitter provides interface used //! by emitter implementations. The interface provides basic building blocks //! that are then implemented by \ref BaseAssembler, \ref BaseBuilder, and //! \ref BaseCompiler. //! //! Code emitters: //! //! - \ref asmjit_assembler - provides direct machine code generation. //! //! - \ref asmjit_builder - provides intermediate code generation that can //! be processed before it's serialized to \ref BaseAssembler. //! //! - \ref asmjit_compiler - provides high-level code generation with built-in //! register allocation. //! //! - \ref FuncNode - provides insight into how function looks from the Compiler //! perspective and how it's stored in a node-list. //! //! \section main_recommendations Recommendations //! //! The following steps are recommended for all AsmJit users: //! //! - Make sure that you use \ref Logger, see \ref asmjit_logging. //! //! - Make sure that you use \ref ErrorHandler, see \ref asmjit_error_handling. //! //! - Instruction validation in your debug builds can reveal problems too. //! AsmJit provides validation at instruction level, that can be enabled //! by \ref BaseEmitter::addValidationOptions(). //! //! See \ref BaseEmitter::ValidationOptions for more details. //! //! - Make sure you put a breakpoint into \ref DebugUtils::errored() function //! if you have a problem with AsmJit returning errors during instruction //! encoding or register allocation. Having an active breakpoint there can //! help to reveal the origin of the error, to inspect variables and other //! conditions that caused to it. //! //! The reason for using \ref Logger and \ref ErrorHandler is that they provide //! a very useful information about what's happening inside emitters. In many //! cases the information provided by these two is crucial to quickly fix issues //! that happen during development (for example wrong instruction, address, or //! register used). In addition, output from \ref Logger is always necessary //! when filling bug reports. In other words, using logging and proper error //! handling can save a lot of time during the development. //! //! \section main_other Other Pages //! //! - Class List - List of classes sorted alphabetically //! - AsmJit Namespace - List of symbols provided by `asmjit` namespace // ============================================================================ // [Documentation - asmjit_build] // ============================================================================ //! \defgroup asmjit_build Build Instructions //! \brief Build instructions, supported environments, and feature selection. //! //! ### Overview //! //! AsmJit is designed to be easy embeddable in any project. However, it depends //! on some compile-time definitions that can be used to enable or disable //! features to decrease the resulting binary size. A typical way of building //! AsmJit is to use [cmake](https://www.cmake.org), but it's also possible to //! just include AsmJit source code in your project and to just build it. The //! easiest way to include AsmJit in your project is to just include **src** //! directory in your project and to define \ref ASMJIT_STATIC. AsmJit can be //! just updated from time to time without any changes to this integration //! process. Do not embed AsmJit's `test` files in such case as these are used //! exclusively for testing. //! //! ### Supported C++ Compilers //! //! - Requirements: //! //! - AsmJit won't build without C++11 enabled. If you use older GCC or Clang //! you would have to enable at least C++11 standard through compiler flags. //! //! - Tested: //! //! - **Clang** - Tested by Travis-CI - Clang 3.9+ (with C++11 enabled) is //! officially supported (older Clang versions having C++11 support are //! probably fine, but are not regularly tested). //! //! - **GNU** - Tested by Travis-CI - GCC 4.8+ (with C++11 enabled) is //! officially supported. //! //! - **MINGW** - Tested by Travis-CI - Use the latest version, if possible. //! //! - **MSVC** - Tested by Travis-CI - VS2017+ is officially supported, VS2015 //! is reported to work. //! //! - Untested: //! //! - **Intel** - No maintainers and no CI environment to regularly test //! this compiler. //! //! - **Other** C++ compilers would require basic support in //! [core/api-config.h](https://github.com/asmjit/asmjit/tree/master/src/asmjit/core/api-config.h). //! //! ### Supported Operating Systems and Platforms //! //! - Tested: //! //! - **Linux** - Tested by Travis-CI (any distribution is generally supported). //! //! - **OSX** - Tested by Travis-CI (any version is supported). //! //! - **Windows** - Tested by Travis-CI - (Windows 7+ is officially supported). //! //! - **Emscripten** - Works if compiled with \ref ASMJIT_NO_JIT. AsmJit //! cannot generate WASM code, but can be used to generate X86/X64 code //! within a browser, for example. //! //! - Untested: //! //! - **BSDs** - No maintainers, no CI environment to regularly test BSDs, //! but they should work out of box. //! //! - **Haiku** - Not regularly tested, but reported to work. //! //! - **Other** operating systems would require some testing and support in //! the following files: //! - [core/api-config.h](https://github.com/asmjit/asmjit/tree/master/src/asmjit/core/api-config.h) //! - [core/osutils.cpp](https://github.com/asmjit/asmjit/tree/master/src/asmjit/core/osutils.cpp) //! - [core/virtmem.cpp](https://github.com/asmjit/asmjit/tree/master/src/asmjit/core/virtmem.cpp) //! //! ### Supported Backends / Architectures //! //! - **X86** - Both 32-bit and 64-bit backends tested by Travis-CI. //! - **ARM** - Work-in-progress (not public at the moment). //! //! ### Static Builds and Embedding //! //! These definitions can be used to enable static library build. Embed is used //! when AsmJit's source code is embedded directly in another project, implies //! static build as well. //! //! - \ref ASMJIT_EMBED - Asmjit is embedded, implies \ref ASMJIT_STATIC. //! - \ref ASMJIT_STATIC - Enable static-library build. //! //! \note Projects that use AsmJit statically must define \ref ASMJIT_STATIC in //! all compilation units that use AsmJit, otherwise AsmJit would use dynamic //! library imports in \ref ASMJIT_API decorator. The recommendation is to //! define this macro across the whole project that uses AsmJit this way. //! //! ### Build Configuration //! //! These definitions control whether asserts are active or not. By default //! AsmJit would autodetect build configuration from existing pre-processor //! definitions, but this behavior can be overridden, for example to enable //! debug asserts in release configuration. //! //! - \ref ASMJIT_BUILD_DEBUG - Overrides build configuration to debug, //! asserts will be enabled in this case. //! - \ref ASMJIT_BUILD_RELEASE - Overrides build configuration to release, //! asserts will be disabled in this case. //! //! \note There is usually no need to override the build configuration. AsmJit //! detects the build configuration by checking whether `NDEBUG` is defined and //! automatically defines \ref ASMJIT_BUILD_RELEASE if configuration overrides //! were not used. We only recommend using build configuration overrides in //! special situations, like using AsmJit in release configuration with asserts //! enabled for whatever reason. //! //! ### AsmJit Backends //! //! AsmJit currently supports only X86/X64 backend, but the plan is to add more //! backends in the future. By default AsmJit builds only the host backend, which //! is autodetected at compile-time, but this can be overridden. //! //! - \ref ASMJIT_BUILD_X86 - Always build X86 backend (X86 and X86_64). //! - \ref ASMJIT_BUILD_ARM - Always build ARM backend (ARM and AArch64). //! - \ref ASMJIT_BUILD_HOST - Always build the host backend. //! //! ### Features Selection //! //! AsmJit builds by defaults all supported features, which includes all emitters, //! logging, instruction validation and introspection, and JIT memory allocation. //! Features can be disabled at compile time by using `ASMJIT_NO_...` definitions. //! //! - \ref ASMJIT_NO_DEPRECATED - Disables deprecated API at compile time //! so it won't be available and the compilation will fail if there is //! attempt to use such API. This includes deprecated classes, namespaces, //! enumerations, and functions. //! //! - \ref ASMJIT_NO_FOREIGN - Disables the support for foreign architectures. //! If defined, it would internally set \ref ASMJIT_BUILD_HOST to true. //! //! - \ref ASMJIT_NO_BUILDER - Disables \ref asmjit_builder functionality //! completely. This implies \ref ASMJIT_NO_COMPILER as \ref asmjit_compiler //! cannot be used without \ref asmjit_builder. //! //! - \ref ASMJIT_NO_COMPILER - Disables \ref asmjit_compiler functionality //! completely. //! //! - \ref ASMJIT_NO_JIT - Disables JIT memory management and \ref JitRuntime. //! //! - \ref ASMJIT_NO_LOGGING - Disables \ref Logger and \ref Formatter. //! //! - \ref ASMJIT_NO_TEXT - Disables everything that contains string //! representation of AsmJit constants, should be used together with //! \ref ASMJIT_NO_LOGGING as logging doesn't make sense without the //! ability to quiry instruction names, register names, etc... //! //! - \ref ASMJIT_NO_VALIDATION - Disables validation API. //! //! - \ref ASMJIT_NO_INTROSPECTION - Disables instruction introspection API, //! must be used together with \ref ASMJIT_NO_COMPILER as \ref asmjit_compiler //! requires introspection for its liveness analysis and register allocation. //! //! \note It's not recommended to disable features if you plan to build AsmJit //! as a shared library that will be used by multiple projects that you don't //! control how AsmJit was built (for example AsmJit in a Linux distribution). //! The possibility to disable certain features exists mainly for customized //! AsmJit builds. // ============================================================================ // [Documentation - asmjit_breaking_changes] // ============================================================================ //! \defgroup asmjit_breaking_changes Breaking Changes //! \brief Documentation of breaking changes //! //! ### Overview //! //! AsmJit is a live project that is being actively developed. Deprecating the //! existing API in favor of a new one is preferred, but it's not always //! possible if the changes are significant. AsmJit authors prefer to do //! accumulated breaking changes at once instead of breaking the API often. //! This page documents deprecated and removed APIs and should serve as a how-to //! guide for people that want to port existing code to work with the newest AsmJit. //! //! ### Tips //! //! Useful tips before you start: //! //! - Visit our [Public Gitter Channel](https://gitter.im/asmjit/asmjit) if //! you need a quick help. //! //! - Build AsmJit with `ASMJIT_NO_DEPRECATED` macro defined to make sure that //! you are not using deprecated functionality at all. Deprecated functions //! are decorated with `ASMJIT_DEPRECATED()` macro, but sometimes it's not //! possible to decorate everything like classes, which are used by deprecated //! functions as well, because some compilers would warn about that. If your //! project compiles fine with `ASMJIT_NO_DEPRECATED` it's not using anything, //! which was deprecated. //! //! ### Changes committed at 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: //! //! - \ref Imm operand has now only \ref Imm::value() and \ref Imm::valueAs() //! functions that return its value content, and \ref Imm::setValue() function //! that sets the content. Functions like `setI8()`, `setU8()` were deprecated. //! //! Old functions were deprecated, but code using them should still compile. //! //! - `ArchInfo` has been replaced with \ref Environment. Environment provides //! more details about the architecture, but drops some properties that //! were used by arch info - `gpSize(`) and `gpCount()`. `gpSize()` can //! be replaced with `registerSize()` getter, which returns a native register //! size of the architecture the environment uses. However, `gpCount()` was //! removed - at the moment \ref ArchRegs can be used to access such properties. //! //! Some other functions were renamed, like `ArchInfo::isX86Family()` is //! now \ref Environment::isFamilyX86(), etc. The reason for changing the //! order was support for more propertries and all the accessors now //! start with the type of the property, like \ref Environment::isPlatformWindows(). //! //! This function causes many other classes to provide `environment()` getter //! instead of `archInfo()` getter. In addition, AsmJit now uses `arch()` to //! get an architecture instead of `archId()`. `ArchInfo::kIdXXX` was renamed //! to `Environment::kArchXXX`. //! //! Some functions were deprecated, some removed... //! //! - `CodeInfo` has been removed in favor of \ref Environment. If you used //! `CodeInfo` to set architecture and base address, this is now possible //! with \ref Environment and setting base address explicitly by \ref //! CodeHolder::init() - the first argument is \ref Environment, and the //! second argument is base address, which defaults to \ref //! Globals::kNoBaseAddress. //! //! CodeInfo class was deprecated, but the code using it should still //! compile with warnings. //! //! - \ref CallConv has been updated to offer a more unified way of representing //! calling conventions - many calling conventions were abstracted to follow //! standard naming like \ref CallConv::kIdCDecl or \ref CallConv::kIdStdCall. //! //! This change means that other APIs like \ref FuncDetail::init() now //! require both, calling convention and target \ref Environment. //! //! - `Logging` namespace has been renamed to \ref Formatter, which now //! provides general functionality for formatting in AsmJit. //! //! Logging namespace should still work, but its use is deprecated. //! Unfortunately this will be without deprecation warnings, so please //! make sure you don't use it. //! //! - `Data64`, `Data128`, and `Data256` structs were deprecated and should //! no longer be used. There is no replacement, AsmJit users should simply //! create their own structures if they need them or use the new repeated //! embed API in emitters, see \ref BaseEmitter::embedDataArray(). //! //! Emitter changes: //! //! - \ref BaseEmitter::emit() function signature has been changed to accept //! 3 operands by reference and the rest 3 operands as a continuous array. //! This change is purely cosmetic and shouldn't affect users as emit() //! has many overloads that dispatch to the right function. //! //! - \ref x86::Emitter (Assembler, Builder, Compiler) deprecates embed //! utilities like `dint8()`, `duint8()`, `duint16()`, `dxmm()`, etc... //! in favor of a new and more powerful \ref BaseEmitter::embedDataArray(). //! This function also allows emitting repeated values and/or patterns, //! which is used by helpers \ref BaseEmitter::embedUInt8(), and others... //! //! - Validation is now available through \ref BaseEmitter::ValidationOptions, //! which can be enabled/disabled through \ref BaseEmitter::addValidationOptions() //! and \ref BaseEmitter::clearValidationOptions(), respectively. Validation //! options now separate between encoding and Builder/Compiler so it's possible //! to choose the granularity required. //! //! 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 \ref InvokeNode. Additionally, function //! calls should now use \ref x86::Compiler::invoke() instead of `call()`. //! The reason behind this is to remove the confusion between a `call` //! instruction and AsmJit's `call()` intrinsic, which is now `invoke()`. //! //! - Creating new nodes also changed. Now the preferred way of invoking a //! function is to call \ref x86::Compiler::invoke() where the first //! argument is `InvokeNode**`. The function now returns an error and would //! call \ref ErrorHandler in case of a failure. Error handling was //! unspecified in the past - the function was marked noexcept, but called //! error handler, which could throw. //! //! The reason behind this change is to make the API consistent with other //! changes and to also make it possible to inspect the possible error. In //! the previous API it returned a new node or `nullptr` in case of error, //! which the user couldn't inspect unless there was an attached \ref //! ErrorHandler. //! //! Samples: //! //! ``` //! #include //! using namespace asmjit; //! //! // The basic setup of JitRuntime and CodeHolder changed, use environment() //! // instead of codeInfo(). //! void basicSetup() { //! JitRuntime rt; //! CodeHolder code(rt.environment()); //! } //! //! // Calling a function (Compiler) changed - use invoke() instead of call(). //! void functionInvocation(x86::Compiler& cc) { //! InvokeNode* invokeNode; //! cc.invoke(&invokeNode, targetOperand, FuncSignatureT<...>(...)); //! } //! ``` // ============================================================================ // [Documentation - asmjit_core] // ============================================================================ //! \defgroup asmjit_core Core //! \brief Globals, code storage, and emitter interface. //! //! ### Overview //! //! AsmJit library uses \ref CodeHolder to hold code during code generation and //! emitters inheriting from \ref BaseEmitter to emit code. CodeHolder uses //! containers to manage its data: //! //! - \ref Section - stores information about a code or data section. //! - \ref CodeBuffer - stores actual code or data, part of \ref Section. //! - \ref LabelEntry - stores information about a label - its name, offset, //! section where it belongs to, and other bits. //! - \ref LabelLink - stores information about yet unbound label, which was //! already used by the assembler. //! - \ref RelocEntry - stores information about a relocation. //! - \ref AddressTableEntry - stores information about an address, which was //! used in a jump or call. Such address may need relocation. //! //! To generate code you would need to instantiate at least the following classes: //! //! - \ref CodeHolder - to hold code during code generation. //! - \ref BaseEmitter - to emit code into \ref CodeHolder. //! - \ref Target (optional) - most likely \ref JitRuntime to keep the generated //! code in executable memory. \ref Target can be customized by inheriting from //! it. //! //! There are also other core classes that are important: //! //! - \ref Environment - describes where the code will run. Environment brings //! the concept of target triples or tuples into AsmJit, which means that users //! can specify target architecture, platform, and ABI. //! - \ref Type - encapsulates lightweight type functionality that can be used //! to describe primitive and vector types. Types are used by higher level //! utilities, for example by \ref asmjit_function and \ref asmjit_compiler. //! - \ref CpuInfo - encapsulates CPU information - stores both CPU information //! and features described by \ref BaseFeatures. //! //! AsmJit also provides global constants: //! //! - \ref Globals - namespace that provides global constants. //! - \ref ByteOrder - byte-order constants and functionality. //! //! \note CodeHolder examples use \ref x86::Assembler as abstract interfaces cannot //! be used to generate code. //! //! ### CodeHolder & Emitters //! //! The example below shows how the mentioned classes interact to generate X86 code: //! //! ``` //! #include //! #include //! //! using namespace asmjit; //! //! // Signature of the generated function. //! typedef int (*Func)(void); //! //! int main() { //! JitRuntime rt; // Runtime specialized for JIT code execution. //! //! CodeHolder code; // Holds code and relocation information. //! code.init(rt.environment()); // Initialize code to match the JIT environment. //! //! x86::Assembler a(&code); // Create and attach x86::Assembler to code. //! a.mov(x86::eax, 1); // Move one to eax register. //! a.ret(); // Return from function. //! // ===== x86::Assembler is no longer needed from here and can be destroyed ===== //! //! Func fn; // Holds address to the generated function. //! Error err = rt.add(&fn, &code); // Add the generated code to the runtime. //! if (err) return 1; // Handle a possible error returned by AsmJit. //! // ===== CodeHolder is no longer needed from here and can be destroyed ===== //! //! int result = fn(); // Execute the generated code. //! printf("%d\n", result); // Print the resulting "1". //! //! // All classes use RAII, all resources will be released before `main()` returns, //! // the generated function can be, however, released explicitly if you intend to //! // reuse or keep the runtime alive, which you should in a production-ready code. //! rt.release(fn); //! //! return 0; //! } //! ``` //! //! The example above used \ref x86::Assembler as an emitter. AsmJit provides the //! following emitters that offer various levels of abstraction: //! //! - \ref asmjit_assembler - Low-level emitter that emits directly to \ref CodeBuffer. //! - \ref asmjit_builder - Low-level emitter that emits to a \ref BaseNode list. //! - \ref asmjit_compiler - High-level emitter that provides register allocation. //! //! ### Targets and JitRuntime //! //! AsmJit's \ref Target is an interface that provides basic target abstraction. //! At the moment AsmJit provides only one implementation called \ref JitRuntime, //! which as the name suggests provides JIT code target and execution runtime. //! \ref JitRuntime provides all the necessary stuff to implement a simple JIT //! compiler with basic memory management. It only provides \ref JitRuntime::add() //! and \ref JitRuntime::release() functions that are used to either add code //! to the runtime or release it. \ref JitRuntime doesn't do any decisions on //! when the code should be released, the decision is up to the developer. //! //! See more at \ref asmjit_virtual_memory group. //! //! ### More About Environment //! //! In the previous example the \ref Environment is retrieved from \ref JitRuntime. //! It's logical as \ref JitRuntime always returns an \ref Environment that is //! compatible with the host. For example if your application runs in 64-bit mode //! the \ref Environment returned will use \ref Environment::kArchX64 architecture //! in contrast to \ref Environment::kArchX86, which will be used in 32-bit mode on //! any X86 platform. //! //! AsmJit allows to setup the \ref Environment manually and to select a different //! architecture and ABI when necessary. So let's do something else this time, let's //! always generate a 32-bit code and print its binary representation. To do that, we //! can create our own \ref Environment and initialize it to \ref Environment::kArchX86. //! //! ``` //! #include //! #include //! //! using namespace asmjit; //! //! int main(int argc, char* argv[]) { //! using namespace asmjit::x86; //! //! // Create a custom environment initialized to 32-bit X86 architecture. //! Environment env; //! env.setArch(Environment::kArchX86); //! //! CodeHolder code; // Create a CodeHolder. //! code.init(env); // Initialize CodeHolder with custom environment. //! //! // Generate a 32-bit function that sums 4 floats and looks like: //! // void func(float* dst, const float* a, const float* b) //! x86::Assembler a(&code); // Create and attach x86::Assembler to `code`. //! //! a.mov(eax, dword_ptr(esp, 4)); // Load the destination pointer. //! a.mov(ecx, dword_ptr(esp, 8)); // Load the first source pointer. //! a.mov(edx, dword_ptr(esp, 12)); // Load the second source pointer. //! //! a.movups(xmm0, ptr(ecx)); // Load 4 floats from [ecx] to XMM0. //! a.movups(xmm1, ptr(edx)); // Load 4 floats from [edx] to XMM1. //! a.addps(xmm0, xmm1); // Add 4 floats in XMM1 to XMM0. //! a.movups(ptr(eax), xmm0); // Store the result to [eax]. //! a.ret(); // Return from function. //! //! // We have no Runtime this time, it's on us what we do with the code. //! // CodeHolder stores code in Section, which provides some basic properties //! // and CodeBuffer structure. We are interested in section's CodeBuffer. //! // //! // NOTE: The first section is always '.text', it can be retrieved by //! // code.sectionById(0) or simply by code.textSection(). //! CodeBuffer& buffer = code.textSection()->buffer(); //! //! // Print the machine-code generated or do something else with it... //! // 8B4424048B4C24048B5424040F28010F58010F2900C3 //! for (size_t i = 0; i < buffer.length; i++) //! printf("%02X", buffer.data[i]); //! //! return 0; //! } //! ``` //! //! ### Explicit Code Relocation //! //! In addition to \ref Environment, \ref CodeHolder can be configured to //! specify a base-address (or a virtual base-address in a linker terminology), //! which could be static (useful when you know the location where the target's //! machine code will be) or dynamic. AsmJit assumes dynamic base-address by //! default and relocates the code held by \ref CodeHolder to a user provided //! address on-demand. To be able to relocate to a user provided address it needs //! to store some information about relocations, which is represented by \ref //! RelocEntry. Relocation entries are only required if you call external functions //! from the generated code that cannot be encoded by using a 32-bit displacement //! (64-bit displacements are not provided by aby supported architecture). //! //! There is also a concept called \ref LabelLink - label link is a lightweight //! data structure that doesn't have any identifier and is stored in \ref LabelEntry //! as a single-linked list. Label link represents either unbound yet used label //! and cross-sections links (only relevant to code that uses multiple sections). //! Since crossing sections is something that cannot be resolved immediately these //! links persist until offsets of these sections are assigned and until //! \ref CodeHolder::resolveUnresolvedLinks() is called. It's an error if you end //! up with code that has unresolved label links after flattening. You can verify //! it by calling \ref CodeHolder::hasUnresolvedLinks(), which inspects the value //! returned by \ref CodeHolder::unresolvedLinkCount(). //! //! AsmJit can flatten code that uses multiple sections by assigning each section //! an incrementing offset that respects its alignment. Use \ref CodeHolder::flatten() //! to do that. After the sections are flattened their offsets and virtual-sizes //! are adjusted to respect each section's buffer size and alignment. The \ref //! CodeHolder::resolveUnresolvedLinks() function must be called before relocating //! the code held by \ref CodeHolder. You can also flatten your code manually by //! iterating over all sections and calculating their offsets (relative to base) //! by your own algorithm. In that case \ref CodeHolder::flatten() should not be //! called, however, \ref CodeHolder::resolveUnresolvedLinks() should be. //! //! The example below shows how to use a built-in virtual memory allocator //! \ref JitAllocator instead of using \ref JitRuntime (just in case you want //! to use your own memory management) and how to relocate the generated code //! into your own memory block - you can use your own virtual memory allocator //! if you prefer that, but that's OS specific and not covered by the documentation. //! //! The following code is similar to the previous one, but implements a function //! working in both 32-bit and 64-bit environments: //! //! ``` //! #include //! #include //! //! using namespace asmjit; //! //! typedef void (*SumIntsFunc)(int* dst, const int* a, const int* b); //! //! int main() { //! // Create a custom environment that matches the current host environment. //! Environment env = hostEnvironment(); //! //! CodeHolder code; // Create a CodeHolder. //! code.init(env); // Initialize CodeHolder with environment. //! //! x86::Assembler a(&code); // Create and attach x86::Assembler to `code`. //! //! // Signature: 'void func(int* dst, const int* a, const int* b)'. //! x86::Gp dst; //! x86::Gp src_a; //! x86::Gp src_b; //! //! // Handle the difference between 32-bit and 64-bit calling conventions //! // (arguments passed through stack vs. arguments passed by registers). //! if (env.is32Bit()) { //! dst = x86::eax; //! src_a = x86::ecx; //! src_b = x86::edx; //! a.mov(dst , x86::dword_ptr(x86::esp, 4)); //! a.mov(src_a, x86::dword_ptr(x86::esp, 8)); //! a.mov(src_b, x86::dword_ptr(x86::esp, 12)); //! } //! else { //! if (env.isPlatformWindows()) { //! dst = x86::rcx; // First argument (destination pointer). //! src_a = x86::rdx; // Second argument (source 'a' pointer). //! src_b = x86::r8; // Third argument (source 'b' pointer). //! } //! else { //! dst = x86::rdi; // First argument (destination pointer). //! src_a = x86::rsi; // Second argument (source 'a' pointer). //! src_b = x86::rdx; // Third argument (source 'b' pointer). //! } //! } //! //! a.movdqu(x86::xmm0, x86::ptr(src_a)); // Load 4 ints from [src_a] to XMM0. //! a.movdqu(x86::xmm1, x86::ptr(src_b)); // Load 4 ints from [src_b] to XMM1. //! a.paddd(x86::xmm0, x86::xmm1); // Add 4 ints in XMM1 to XMM0. //! a.movdqu(x86::ptr(dst), x86::xmm0); // Store the result to [dst]. //! a.ret(); // Return from function. //! //! // Even when we didn't use multiple sections AsmJit could insert one section //! // called '.addrtab' (address table section), which would be filled by data //! // required by relocations (absolute jumps and calls). You can omit this code //! // if you are 100% sure your code doesn't contain multiple sections and //! // such relocations. You can use `CodeHolder::hasAddressTable()` to verify //! // whether the address table section does exist. //! code.flatten(); //! code.resolveUnresolvedLinks(); //! //! // After the code was generated it can be relocated manually to any memory //! // location, however, we need to know it's size before we perform memory //! // allocation. `CodeHolder::codeSize()` returns the worst estimated code //! // size in case that relocations are not possible without trampolines (in //! // that case some extra code at the end of the current code buffer is //! // generated during relocation). //! size_t estimatedSize = code.codeSize(); //! //! // Instead of rolling up our own memory allocator we can use the one AsmJit //! // provides. It's decoupled so you don't need to use `JitRuntime` for that. //! JitAllocator allocator; //! //! // Allocate an executable virtual memory and handle a possible failure. //! void* p = allocator.alloc(estimatedSize); //! if (!p) //! return 0; //! //! // Now relocate the code to the address provided by the memory allocator. //! // Please note that this DOESN'T COPY anything to `p`. This function will //! // store the address in CodeHolder and use relocation entries to patch the //! // existing code in all sections to respect the base address provided. //! code.relocateToBase((uint64_t)p); //! //! // This is purely optional. There are cases in which the relocation can omit //! // unneeded data, which would shrink the size of address table. If that //! // happened the codeSize returned after relocateToBase() would be smaller //! // than the originally `estimatedSize`. //! size_t codeSize = code.codeSize(); //! //! // This will copy code from all sections to `p`. Iterating over all sections //! // and calling `memcpy()` would work as well, however, this function supports //! // additional options that can be used to also zero pad sections' virtual //! // size, etc. //! // //! // With some additional features, copyFlattenData() does roughly this: //! // for (Section* section : code.sections()) //! // memcpy((uint8_t*)p + section->offset(), //! // section->data(), //! // section->bufferSize()); //! code.copyFlattenedData(p, codeSize, CodeHolder::kCopyPadSectionBuffer); //! //! // Execute the generated function. //! int inA[4] = { 4, 3, 2, 1 }; //! int inB[4] = { 1, 5, 2, 8 }; //! int out[4]; //! //! // This code uses AsmJit's ptr_as_func<> to cast between void* and SumIntsFunc. //! ptr_as_func(p)(out, inA, inB); //! //! // Prints {5 8 4 9} //! printf("{%d %d %d %d}\n", out[0], out[1], out[2], out[3]); //! //! // Release 'p' is it's no longer needed. It will be destroyed with 'vm' //! // instance anyway, but it's a good practice to release it explicitly //! // when you know that the function will not be needed anymore. //! allocator.release(p); //! //! return 0; //! } //! ``` //! //! If you know the base-address in advance (before the code generation) it can //! be passed as a second argument to \ref CodeHolder::init(). In that case the //! Assembler will know the absolute position of each instruction and would be //! able to use it during instruction encoding to prevent relocations where //! possible. The following example shows how to configure the base address: //! //! ``` //! #include //! #include //! //! void initializeCodeHolder(CodeHolder& code) { //! Environment env = hostEnvironment(); //! uint64_t baseAddress = uint64_t(0x1234); //! //! // initialize CodeHolder with environment and custom base address. //! code.init(env, baseAddress); //! } //! ``` //! //! ### Label Offsets and Links //! //! When a label that is not yet bound is used by the Assembler, it creates a //! \ref LabelLink, which is then added to a \ref LabelEntry. These links are //! also created if a label is used in a different section than in which it //! was bound. Let's examine some functions that can be used to check whether //! there are any unresolved links. //! //! ``` //! #include //! #include //! //! void labelLinksExample(CodeHolder& code, const Label& label) { //! // Tests whether the `label` is bound. //! bool isBound = code.isLabelBound(label); //! printf("Label %u is %s\n", label.id(), isBound ? "bound" : "not bound"); //! //! // Returns true if the code contains either referenced, but unbound //! // labels, or cross-section label links that are not resolved yet. //! bool hasUnresolved = code.hasUnresolvedLinks(); // Boolean answer. //! size_t nUnresolved = code.unresolvedLinkCount(); // Count of unresolved links. //! //! printf("Number of unresolved links: %zu\n", nUnresolved); //! } //! ``` //! //! There is no function that would return the number of unbound labels as this //! is completely unimportant from CodeHolder's perspective. If a label is not //! used then it doesn't matter whether it's bound or not, only actually used //! labels matter. After a Label is bound it's possible to query its offset //! offset relative to the start of the section where it was bound: //! //! ``` //! #include //! #include //! //! void labelOffsetExample(CodeHolder& code, const Label& label) { //! // Label offset is known after it's bound. The offset provided is relative //! // to the start of the section, see below for alternative. If the given //! // label is not bound the offset returned will be zero. It's recommended //! // to always check whether the label is bound before using its offset. //! uint64_t sectionOffset = code.labelOffset(label); //! printf("Label offset relative to section: %llu\n", (unsigned long long)sectionOffset); //! //! // If you use multiple sections and want the offset relative to the base. //! // NOTE: This function expects that the section has already an offset and //! // the label-link was resolved (if this is not true you will still get an //! // offset relative to the start of the section). //! uint64_t baseOffset = code.labelOffsetFromBase(label); //! printf("Label offset relative to base: %llu\n", (unsigned long long)baseOffset); //! } //! ``` //! //! ### Sections //! //! AsmJit allows to create multiple sections within the same \ref CodeHolder. //! A test-case [asmjit_test_x86_sections.cpp](https://github.com/asmjit/asmjit/blob/master/test/asmjit_test_x86_sections.cpp) //! can be used as a reference point although the following example should //! also provide a useful insight: //! //! ``` //! #include //! #include //! //! void sectionsExample(CodeHolder& code) { //! // Text section is always provided as the first section. //! Section* text = code.textSection(); // or code.sectionById(0); //! //! // To create another section use CodeHolder::newSection(). //! Section* data; //! Error err = code.newSection(&data, //! ".data", // Section name //! SIZE_MAX, // Name length if the name is not null terminated (or SIZE_MAX). //! 0, // Section flags, see Section::Flags. //! 8, // Section alignment, must be power of 2. //! 0); // Section order value (optional, default 0). //! //! // When you switch sections in Assembler, Builder, or Compiler the cursor //! // will always move to the end of that section. When you create an Assembler //! // the cursor would be placed at the end of the first (.text) section, which //! // is initially empty. //! x86::Assembler a(&code); //! Label L_Data = a.newLabel(); //! //! a.mov(x86::eax, x86::ebx); // Emits in .text section. //! //! a.section(data); // Switches to the end of .data section. //! a.bind(L_Data); // Binds label in this .data section //! a.db(0x01); // Emits byte in .data section. //! //! a.section(text); // Switches to the end of .text section. //! a.add(x86::ebx, x86::eax); // Emits in .text section. //! //! // References a label in .text section, which was bound in .data section. //! // This would create a LabelLink even when the L_Data is already bound, //! // because the reference crosses sections. See below... //! a.lea(x86::rsi, x86::ptr(L_Data)); //! } //! ``` //! //! The last line in the example above shows that a LabelLink would be created //! even for bound labels that cross sections. In this case a referenced label //! was bound in another section, which means that the link couldn't be resolved //! at that moment. If your code uses sections, but you wish AsmJit to flatten //! these sections (you don't plan to flatten them manually) then there is an //! API for that. //! //! ``` //! #include //! #include //! //! // ... (continuing the previous example) ... //! void sectionsExampleContinued(CodeHolder& code) { //! // Suppose we have some code that contains multiple sections and //! // we would like to flatten it by using AsmJit's built-in API: //! Error err = code.flatten(); //! if (err) { //! // There are many reasons it can fail, so always handle a possible error. //! printf("Failed to flatten the code: %s\n", DebugUtils::errorAsString(err)); //! exit(1); //! } //! //! // After flattening all sections would contain assigned offsets //! // relative to base. Offsets are 64-bit unsigned integers so we //! // cast them to `size_t` for simplicity. On 32-bit targets it's //! // guaranteed that the offset cannot be greater than `2^32 - 1`. //! printf("Data section offset %zu", size_t(data->offset())); //! //! // The flattening doesn't resolve unresolved label links, this //! // has to be done manually as flattening can be done separately. //! err = code.resolveUnresolvedLinks(); //! if (err) { //! // This is the kind of error that should always be handled... //! printf("Failed to resolve label links: %s\n", DebugUtils::errorAsString(err)); //! exit(1); //! } //! //! if (code.hasUnresolvedLinks()) { //! // This would mean either unbound label or some other issue. //! printf("The code has %zu unbound labels\n", code.unresovedLinkCount()); //! exit(1); //! } //! } //! ``` // ============================================================================ // [Documentation - asmjit_assembler] // ============================================================================ //! \defgroup asmjit_assembler Assembler //! \brief Assembler interface and operands. //! //! ### Overview //! //! AsmJit's Assembler is used to emit machine code directly into a \ref //! CodeBuffer. In general, code generation with assembler requires the knowledge //! of the following: //! //! - \ref BaseAssembler and architecture-specific assemblers: //! - \ref x86::Assembler - Assembler specific to X86 architecture //! - \ref Operand and its variations: //! - \ref BaseReg - Base class for a register operand, inherited by: //! - \ref x86::Reg - Register operand specific to X86 architecture. //! - \ref BaseMem - Base class for a memory operand, inherited by: //! - \ref x86::Mem - Memory operand specific to X86 architecture. //! - \ref Imm - Immediate (value) operand. //! - \ref Label - Label operand. //! //! \note Assembler examples use \ref x86::Assembler as abstract interfaces cannot //! be used to generate code. //! //! ### Operand Basics //! //! Let's start with operands. \ref Operand is a data structure that defines a //! data layout of any operand. It can be inherited, but any class inheriting //! it cannot add any members to it, only the existing layout can be reused. //! AsmJit allows to construct operands dynamically, to store them, and to query //! a complete information about them at run-time. Operands are small (always 16 //! bytes per \ref Operand) and can be copied and passed by value. Please never //! allocate individual operands dynamically by using a `new` keyword - it would //! work, but then you would have to be responsible for deleting such operands. //! In AsmJit operands are always part of some other data structures like \ref //! InstNode, which is part of \ref asmjit_builder tool. //! //! Operands contain only identifiers, but not pointers to any code-generation data. //! For example \ref Label operand only provides label identifier, but not a pointer //! to \ref LabelEntry structure. In AsmJit such IDs are used to link stuff together //! without having to deal with pointers. //! //! AsmJit's operands all inherit from a base class called \ref Operand. Operands //! have the following properties that are commonly accessible by getters and setters: //! //! - \ref Operand - Base operand, which only provides accessors that are common //! to all operand types. //! - \ref BaseReg - Describes either physical or virtual register. Physical //! registers have id that matches the target's machine id directly whereas //! virtual registers must be allocated into physical registers by a register //! allocator pass. Register operand provides: //! - Register Type - Unique id that describes each possible register provided //! by the target architecture - for example X86 backend provides \ref //! x86::Reg::RegType, which defines all variations of general purpose registers //! (GPB-LO, GPB-HI, GPW, GPD, and GPQ) and all types of other registers like K, //! MM, BND, XMM, YMM, and ZMM. //! - Register Group - Groups multiple register types under a single group - for //! example all general-purpose registers (of all sizes) on X86 are part of //! \ref x86::Reg::kGroupGp and all SIMD registers (XMM, YMM, ZMM) are part //! of \ref x86::Reg::kGroupVec. //! - Register Size - Contains the size of the register in bytes. If the size //! depends on the mode (32-bit vs 64-bit) then generally the higher size is //! used (for example RIP register has size 8 by default). //! - Register Id - Contains physical or virtual id of the register. //! - \ref BaseMem - Used to reference a memory location. Memory operand provides: //! - Base Register - A base register type and id (physical or virtual). //! - Index Register - An index register type and id (physical or virtual). //! - Offset - Displacement or absolute address to be referenced (32-bit if base //! register is used and 64-bit if base register is not used). //! - Flags that can describe various architecture dependent information (like //! scale and segment-override on X86). //! - \ref Imm - Immediate values are usually part of instructions (encoded within //! the instruction itself) or data. //! - \ref Label - used to reference a location in code or data. Labels must be //! created by the \ref BaseEmitter or by \ref CodeHolder. Each label has its //! unique id per \ref CodeHolder instance. //! //! ### Operand Manipulation //! //! AsmJit allows to construct operands dynamically, to store them, and to query //! a complete information about them at run-time. Operands are small (always 16 //! bytes per `Operand`) and should be always copied (by value) if you intend to //! store them (don't create operands by using `new` keyword, it's not recommended). //! Operands are safe to be passed to `memcpy()` and `memset()`, which becomes //! handy when working with arrays of operands. If you set all members of an \ref //! Operand to zero the operand would become NONE operand, which is the same as a //! default constructed Operand. //! //! The example below illustrates how operands can be used and modified even //! without using any other code generation classes. The example uses X86 //! architecture-specific operands. //! //! ``` //! #include //! //! using namespace asmjit; //! //! // Registers can be copied, it's a common practice. //! x86::Gp dstRegByValue() { return x86::ecx; } //! //! void usingOperandsExample(x86::Assembler& a) { //! // Gets `ecx` register returned by a function. //! x86::Gp dst = dstRegByValue(); //! // Gets `rax` register directly from the provided `x86` namespace. //! x86::Gp src = x86::rax; //! // Constructs `r10` dynamically. //! x86::Gp idx = x86::gpq(10); //! // Constructs [src + idx] memory address - referencing [rax + r10]. //! x86::Mem m = x86::ptr(src, idx); //! //! // Examine `m`: Returns `x86::Reg::kTypeGpq`. //! m.indexType(); //! // Examine `m`: Returns 10 (`r10`). //! m.indexId(); //! //! // Reconstruct `idx` stored in mem: //! x86::Gp idx_2 = x86::Gp::fromTypeAndId(m.indexType(), m.indexId()); //! //! // True, `idx` and idx_2` are identical. //! idx == idx_2; //! //! // Possible - op will still be the same as `m`. //! Operand op = m; //! // True (can be casted to BaseMem or architecture-specific Mem). //! op.isMem(); //! //! // True, `op` is just a copy of `m`. //! m == op; //! //! // Static cast is fine and valid here. //! static_cast(op).addOffset(1); //! // However, using `as()` to cast to a derived type is preferred. //! op.as().addOffset(1); //! // False, `op` now points to [rax + r10 + 2], which is not [rax + r10]. //! m == op; //! //! // Emitting 'mov' - type safe way. //! a.mov(dst, m); //! // Not possible, `mov` doesn't provide mov(x86::Gp, Operand) overload. //! a.mov(dst, op); //! //! // Type-unsafe, but possible. //! a.emit(x86::Inst::kIdMov, dst, m); //! // Also possible, `emit()` is typeless and can be used with raw Operand. //! a.emit(x86::Inst::kIdMov, dst, op); //! } //! ``` //! //! Some operands have to be created explicitly by emitters. For example labels //! must be created by \ref BaseEmitter::newLabel(), which creates a label entry //! and returns a \ref Label operand with the id that refers to it. Such label //! then can be used by emitters. //! //! ### Memory Operands //! //! Some architectures like X86 provide a complex memory addressing model that //! allows to encode addresses having a BASE register, INDEX register with a //! possible scale (left shift), and displacement (called offset in AsmJit). //! Memory address on X86 can also specify memory segment (segment-override in //! X86 terminology) and some instructions (gather / scatter) require INDEX to //! be a \ref x86::Vec register instead of a general-purpose register. //! //! AsmJit allows to encode and work with all forms of addresses mentioned and //! implemented by X86. In addition, it also allows to construct absolute 64-bit //! memory address operands, which is only allowed in one form of 'mov' instruction. //! //! ``` //! #include //! //! using namespace asmjit; //! //! void testX86Mem() { //! // Makes it easier to access x86 stuff... //! using namespace asmjit::x86; //! //! // BASE + OFFSET. //! Mem a = ptr(rax); // a = [rax] //! Mem b = ptr(rax, 15); // b = [rax + 15] //! //! // BASE + INDEX << SHIFT - Shift is in BITS as used by X86! //! Mem c = ptr(rax, rbx); // c = [rax + rbx] //! Mem d = ptr(rax, rbx, 2); // d = [rax + rbx << 2] //! Mem e = ptr(rax, rbx, 2, 15); // e = [rax + rbx << 2 + 15] //! //! // BASE + VM (Vector Index) (encoded as MOD+VSIB). //! Mem f = ptr(rax, xmm1); // f = [rax + xmm1] //! Mem g = ptr(rax, xmm1, 2); // g = [rax + xmm1 << 2] //! Mem h = ptr(rax, xmm1, 2, 15); // h = [rax + xmm1 << 2 + 15] //! //! // Absolute adddress: //! uint64_t addr = (uint64_t)0x1234; //! Mem i = ptr(addr); // i = [0x1234] //! Mem j = ptr(addr, rbx); // j = [0x1234 + rbx] //! Mem k = ptr(addr, rbx, 2); // k = [0x1234 + rbx << 2] //! //! // LABEL - Will be encoded as RIP (64-bit) or absolute address (32-bit). //! Label L = ...; //! Mem m = ptr(L); // m = [L] //! Mem n = ptr(L, rbx); // n = [L + rbx] //! Mem o = ptr(L, rbx, 2); // o = [L + rbx << 2] //! Mem p = ptr(L, rbx, 2, 15); // p = [L + rbx << 2 + 15] //! //! // RIP - 64-bit only (RIP can't use INDEX). //! Mem q = ptr(rip, 24); // q = [rip + 24] //! } //! ``` //! //! Memory operands can optionally contain memory size. This is required by //! instructions where the memory size cannot be deduced from other operands, //! like `inc` and `dec` on X86: //! //! ``` //! #include //! //! using namespace asmjit; //! //! void testX86Mem() { //! // The same as: dword ptr [rax + rbx]. //! x86::Mem a = x86::dword_ptr(rax, rbx); //! //! // The same as: qword ptr [rdx + rsi << 0 + 1]. //! x86::Mem b = x86::qword_ptr(rdx, rsi, 0, 1); //! } //! ``` //! //! Memory operands provide API that can be used to access its properties: //! //! ``` //! #include //! //! using namespace asmjit; //! //! void testX86Mem() { //! // The same as: dword ptr [rax + 12]. //! x86::Mem mem = x86::dword_ptr(rax, 12); //! //! mem.hasBase(); // true. //! mem.hasIndex(); // false. //! mem.size(); // 4. //! mem.offset(); // 12. //! //! mem.setSize(0); // Sets the size to 0 (makes it sizeless). //! mem.addOffset(-1); // Adds -1 to the offset and makes it 11. //! mem.setOffset(0); // Sets the offset to 0. //! mem.setBase(rcx); // Changes BASE to RCX. //! mem.setIndex(rax); // Changes INDEX to RAX. //! mem.hasIndex(); // true. //! } //! // ... //! ``` //! //! Making changes to memory operand is very comfortable when emitting loads //! and stores: //! //! ``` //! #include //! //! using namespace asmjit; //! //! void testX86Mem(CodeHolder& code) { //! x86::Assembler a(code); // Your initialized x86::Assembler. //! x86::Mem mSrc = x86::ptr(eax); // Construct [eax] memory operand. //! //! // One way of emitting bunch of loads is to use `mem.adjusted()`, which //! // returns a new memory operand and keeps the source operand unchanged. //! a.movaps(x86::xmm0, mSrc); // No adjustment needed to load [eax]. //! a.movaps(x86::xmm1, mSrc.adjusted(16)); // Loads from [eax + 16]. //! a.movaps(x86::xmm2, mSrc.adjusted(32)); // Loads from [eax + 32]. //! a.movaps(x86::xmm3, mSrc.adjusted(48)); // Loads from [eax + 48]. //! //! // ... do something with xmm0-3 ... //! //! // Another way of adjusting memory is to change the operand in-place. //! // If you want to keep the original operand you can simply clone it. //! x86::Mem mDst = mSrc.clone(); // Clone mSrc. //! //! a.movaps(mDst, x86::xmm0); // Stores xmm0 to [eax]. //! mDst.addOffset(16); // Adds 16 to `mDst`. //! //! a.movaps(mDst, x86::xmm1); // Stores to [eax + 16] . //! mDst.addOffset(16); // Adds 16 to `mDst`. //! //! a.movaps(mDst, x86::xmm2); // Stores to [eax + 32]. //! mDst.addOffset(16); // Adds 16 to `mDst`. //! //! a.movaps(mDst, x86::xmm3); // Stores to [eax + 48]. //! } //! ``` //! //! ### Assembler Examples //! //! - \ref x86::Assembler provides many X86/X64 examples. // ============================================================================ // [Documentation - asmjit_builder] // ============================================================================ //! \defgroup asmjit_builder Builder //! \brief Builder interface, nodes, and passes. //! //! ### Overview //! //! Both \ref BaseBuilder and \ref BaseCompiler interfaces describe emitters //! that emit into a representation that allows further processing. The code //! stored in such representation is completely safe to be patched, simplified, //! reordered, obfuscated, removed, injected, analyzed, or processed some other //! way. Each instruction, label, directive, or other building block is stored //! as \ref BaseNode (or derived class like \ref InstNode or \ref LabelNode) //! and contains all the information necessary to pass that node later to the //! assembler. //! //! \ref BaseBuilder is an emitter that inherits from \ref BaseEmitter interface. //! It was designed to provide a maximum compatibility with the existing \ref //! BaseAssembler emitter so users can move from assembler to builder when needed, //! for example to implement post-processing, which is not possible with Assembler. //! //! ### Builder Nodes //! //! \ref BaseBuilder doesn't generate machine code directly, it uses an intermediate //! representation based on nodes, however, it allows to serialize to \ref BaseAssembler //! when the code is ready to be encoded. //! //! There are multiple node types used by both \ref BaseBuilder and \ref BaseCompiler : //! //! - Basic nodes: //! - \ref BaseNode - Base class for all nodes. //! - \ref InstNode - Represents an instruction node. //! - \ref AlignNode - Represents an alignment directive (.align). //! - \ref LabelNode - Represents a location where to bound a \ref Label. //! //! - Data nodes: //! - \ref EmbedDataNode - Represents data. //! - \ref EmbedLabelNode - Represents \ref Label address embedded as data. //! - \ref EmbedLabelDeltaNode - Represents a difference of two labels //! embedded in data. //! - \ref ConstPoolNode - Represents a constant pool data embedded as data. //! //! - Informative nodes: //! - \ref CommentNode - Represents a comment string, doesn't affect code //! generation. //! - \ref SentinelNode - A marker that can be used to remember certain //! position in code or data, doesn't affect code generation. Used by //! \ref FuncNode to mark the end of a function. //! //! - Other nodes are provided by \ref asmjit_compiler infrastructure. //! //! ### Builder Examples //! //! - \ref x86::Builder provides many X86/X64 examples. // ============================================================================ // [Documentation - asmjit_compiler] // ============================================================================ //! \defgroup asmjit_compiler Compiler //! \brief Compiler interface. //! //! ### Overview //! //! \ref BaseCompiler is a high-level interface built on top of \ref BaseBuilder //! interface, which provides register allocation and support for defining and //! invoking functions. At the moment it's the easiest way of generating code //! in AsmJit as most architecture and OS specifics is properly abstracted and //! handled by AsmJit automatically. However, abstractions also mean restrictions, //! which means that \ref BaseCompiler has more limitations than \ref BaseAssembler //! or \ref BaseBuilder. //! //! Since \ref BaseCompiler provides register allocation it also establishes the //! concept of functions - a function in Compiler sense is a unit in which virtual //! registers are allocated into physical registers by the register allocator. //! In addition, it enables to use such virtual registers in function invocations. //! //! \ref BaseCompiler automatically handles function calling conventions. It's //! still architecture dependent, but makes the code generation much easies. //! Functions are essential; the first-step to generate some code is to define a //! signature of the function to be generated (before generating the function body //! itself). Function arguments and return value(s) are handled by assigning //! virtual registers to them. Similarly, function calls are handled the same way. //! //! ### Compiler Nodes //! //! \ref BaseCompiler adds some nodes that are required for function generation //! and invocation: //! //! - \ref FuncNode - Represents a function definition. //! - \ref FuncRetNode - Represents a function return. //! - \ref InvokeNode - Represents a function invocation. //! //! \ref BaseCompiler also makes the use of passes (\ref Pass) and automatically //! adds an architecture-dependent register allocator pass to the list of passes //! when attached to \ref CodeHolder. //! //! ### Compiler Examples //! //! - \ref x86::Compiler provides many X86/X64 examples. //! //! ### Compiler Tips //! //! Users of AsmJit have done mistakes in the past, this section should provide //! some useful tips for beginners: //! //! - Virtual registers in compiler are bound to a single function. At the //! moment the implementation doesn't care whether a single virtual register //! is used in multiple functions, but it sees it as two independent virtual //! registers in that case. This means that virtual registers cannot be used //! to implement global variables. Global variables are basically memory //! addresses which functions can read from and write to, and they have to //! be implemented in the same way. //! //! - Compiler provides a useful debugging functionality, which can be turned //! on through \ref FormatOptions::Flags. Use \ref Logger::addFlags() to //! turn on additional logging features when using Compiler. // ============================================================================ // [Documentation - asmjit_function] // ============================================================================ //! \defgroup asmjit_function Function //! \brief Function definitions. //! //! ### Overview //! //! AsmJit provides functionality that can be used to define function signatures //! and to calculate automatically optimal function frame that can be used directly //! by a prolog and epilog insertion. This feature was exclusive to AsmJit's Compiler //! for a very long time, but was abstracted out and is now available for all users //! regardless of the emitter they use. The following use cases are possible: //! //! - 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 Type::Id - Type-id is an 8-bit value that describes a platform //! independent type as we know from C/C++. It provides abstractions for //! most common types like `int8_t`, `uint32_t`, `uintptr_t`, `float`, //! `double`, and all possible vector types to match ISAs up to AVX512. //! \ref Type::Id was introduced originally for \ref asmjit_compiler, but //! it's now used by \ref FuncSignature as well. //! //! - \ref CallConv - Describes a calling convention - this class contains //! instructions to assign registers and stack addresses to function //! arguments and return value(s), but doesn't specify any function //! signature itself. Calling conventions are architecture and OS dependent. //! //! - \ref FuncSignature - Describes a function signature, for example //! `int func(int, int)`. FuncSignature contains a function calling convention //! id, return value type, and function arguments. The signature itself is //! platform independent and uses \ref Type::Id to describe types of function //! arguments and function return value(s). //! //! - \ref FuncDetail - Architecture and ABI dependent information that describes //! \ref CallConv and expanded \ref FuncSignature. Each function argument and //! return value is represented as \ref FuncValue that contains the original //! \ref Type::Id enriched with additional information that specifies whether //! the value is passed or returned by register (and which register) or by //! stack. Each value also contains some other metadata that provide additional //! information required to handle it properly (for example whether a vector is //! passed indirectly by a pointer as required by WIN64 calling convention). //! //! - \ref FuncFrame - Contains information about the function frame that can //! be used by prolog/epilog inserter (PEI). Holds call stack size size and //! alignment, local stack size and alignment, and various attributes that //! describe how prolog and epilog should be constructed. `FuncFrame` doesn't //! know anything about function's arguments or return values, it hold only //! information necessary to create a valid and ABI conforming function prologs //! and epilogs. //! //! - \ref FuncArgsAssignment - A helper class that can be used to reassign //! function arguments into user specified registers. It's architecture and //! ABI dependent mapping from function arguments described by \ref CallConv //! 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. // ============================================================================ // [Documentation - asmjit_logging] // ============================================================================ //! \defgroup asmjit_logging Logging //! \brief Logging and formatting. //! //! ### Overview //! //! The initial phase of a project that generates machine code is not always smooth. //! Failure cases are common not just at the beginning phase, but also during the //! development or refactoring. AsmJit provides logging functionality to address //! this issue. AsmJit does already a good job with function overloading to prevent //! from emitting unencodable instructions, but it can't prevent from emitting machine //! code that is correct at instruction level, but doesn't work when it's executed as //! a whole. Logging has always been an important part of AsmJit's infrastructure and //! looking at logs can sometimes reveal code generation issues quickly. //! //! AsmJit provides API for logging and formatting: //! - \ref Logger - A logger that you can pass to \ref CodeHolder and all emitters //! that inherit from \ref BaseEmitter. //! - \ref FormatOptions - Formatting options that can change how instructions and //! operands are formatted. //! - \ref Formatter - A namespace that provides functions that can format input //! data like \ref Operand, \ref BaseReg, \ref Label, and \ref BaseNode into //! \ref String. //! //! AsmJit's \ref Logger serves the following purposes: //! - Provides a basic foundation for logging. //! - Abstract class leaving the implementation on users. The following built-in //! inplementations are provided for simplicty: //! - \ref FileLogger implements logging into a standard `FILE` stream. //! - \ref StringLogger serializes all logs into a \ref String instance. //! //! AsmJit's \ref FormatOptions provides the following to customize the formatting of //! instructions and operands through: //! - \ref FormatOptions::Flags //! - \ref FormatOptions::IndentationType //! //! ### Logging //! //! A \ref Logger is typically attached to a \ref CodeHolder, which propagates it //! to all attached emitters automatically. The example below illustrates how to //! use \ref FileLogger that outputs to standard output: //! //! ``` //! #include //! #include //! //! using namespace asmjit; //! //! int main() { //! JitRuntime rt; // Runtime specialized for JIT code execution. //! FileLogger logger(stdout); // Logger should always survive CodeHolder. //! //! CodeHolder code; // Holds code and relocation information. //! code.init(rt.environment()); // Initialize to the same arch as JIT runtime. //! code.setLogger(&logger); // Attach the `logger` to `code` holder. //! //! // ... code as usual, everything emitted will be logged to `stdout` ... //! return 0; //! } //! ``` //! //! If output to FILE stream is not desired it's possible to use \ref StringLogger, //! which concatenates everything into a multi-line string: //! //! ``` //! #include //! #include //! #include //! //! using namespace asmjit; //! //! int main() { //! JitRuntime rt; // Runtime specialized for JIT code execution. //! StringLogger logger; // Logger should always survive CodeHolder. //! //! CodeHolder code; // Holds code and relocation information. //! code.init(rt.environment()); // Initialize to the same arch as JIT runtime. //! code.setLogger(&logger); // Attach the `logger` to `code` holder. //! //! // ... code as usual, logging will be concatenated to logger string ... //! //! // You can either use the string from StringLogger directly or you can //! // move it. Logger::data() returns its content as null terminated char[]. //! printf("Logger content: %s\n", logger.data()); //! //! // It can be moved into your own string like this: //! String content = std::move(logger.content()); //! printf("The same content: %s\n", content.data()); //! //! return 0; //! } //! ``` //! //! ### Formatting //! //! AsmJit uses \ref Formatter to format inputs that are then passed to \ref //! Logger. Formatting is public and can be used by AsmJit users as well. The //! most important thing to know regarding formatting is that \ref Formatter //! always appends to the output string, so it can be used to build complex //! strings without having to concatenate intermediate strings. //! //! The first example illustrates how to format operands: //! //! ``` //! #include //! #include //! //! using namespace asmjit; //! //! void logOperand(uint32_t arch, const Operand_& op) { //! // The emitter is optional (named labels and virtual registers need it). //! BaseEmitter* emitter = nullptr; //! //! // No flags by default. //! uint32_t formatFlags = FormatOptions::kNoFlags; //! //! StringTmp<128> sb; //! Formatter::formatOperand(sb, formatFlags, emitter, arch, op); //! printf("%s\n", sb.data()); //! } //! //! void formattingExample() { //! using namespace x86; //! //! // Architecture is not part of operand, it must be passed explicitly. //! // Format flags. We pass it explicitly also to 'logOperand' to make //! // compatible with what AsmJit normally does. //! uint32_t arch = Environment::kArchX64; //! //! log(arch, rax); // Prints 'rax'. //! log(arch, ptr(rax, rbx, 2)); // Prints '[rax + rbx * 4]`. //! log(arch, dword_ptr(rax, rbx, 2)); // Prints 'dword [rax + rbx * 4]`. //! log(arch, imm(42)); // Prints '42'. //! } //! ``` //! //! Next example illustrates how to format whole instructions: //! //! ``` //! #include //! #include //! #include //! //! using namespace asmjit; //! //! template //! void logInstruction(uint32_t arch, const BaseInst& inst, Args&&... args) { //! // The emitter is optional (named labels and virtual registers need it). //! BaseEmitter* emitter = nullptr; //! //! // No flags by default. //! uint32_t formatFlags = FormatOptions::kNoFlags; //! //! // The formatter expects operands in an array. //! Operand_ operands { std::forward(args)... }; //! //! StringTmp<128> sb; //! Formatter::formatInstruction( //! sb, formatFlags, emitter, arch, inst, operands, sizeof...(args)); //! printf("%s\n", sb.data()); //! } //! //! void formattingExample() { //! using namespace x86; //! //! // Architecture is not part of operand, it must be passed explicitly. //! // Format flags. We pass it explicitly also to 'logOperand' to make //! // compatible with what AsmJit normally does. //! uint32_t arch = Environment::kArchX64; //! //! // Prints 'mov rax, rcx'. //! logInstruction(arch, BaseInst(Inst::kIdMov), rax, rcx); //! //! // Prints 'vaddpd zmm0, zmm1, [rax] {1to8}'. //! logInstruction(arch, //! BaseInst(Inst::kIdVaddpd), //! zmm0, zmm1, ptr(rax)._1toN()); //! //! // BaseInst abstracts instruction id, instruction options, and extraReg. //! // Prints 'lock add [rax], rcx'. //! logInstruction(arch, //! BaseInst(Inst::kIdAdd, Inst::kOptionLock), //! x86::ptr(rax), rcx); //! //! // Similarly an extra register (like AVX-512 selector) can be used. //! // Prints 'vaddpd zmm0 {k2} {z}, zmm1, [rax]'. //! logInstruction(arch, //! BaseInst(Inst::kIdAdd, Inst::kOptionZMask, k2), //! zmm0, zmm1, ptr(rax)); //! } //! ``` //! //! And finally, the example below illustrates how to use a built-in function //! to format the content of \ref BaseBuilder, which consists of nodes: //! //! ``` //! #include //! #include //! //! using namespace asmjit; //! //! void formattingExample(BaseBuilder* builder) { //! uint32_t formatFlags = FormatOptions::kNoFlags; //! //! // This also shows how temporary strings can be used. //! StringTmp<512> sb; //! //! // FormatNodeList requires the String for output, formatting flags, which //! // were zero (no extra flags), and the builder instance, which we have //! // provided. An overloaded version also exists, which accepts begin and //! // and end nodes, which can be used to only format a range of nodes. //! Formatter::formatNodeList(sb, formatFlags, builder); //! //! // You can do whatever else with the string, it's always null terminated, //! // so it can be passed to C functions like printf(). //! printf("%s\n", sb.data()); //! } //! ``` // ============================================================================ // [Documentation - asmjit_error_handling] // ============================================================================ //! \defgroup asmjit_error_handling Error Handling //! \brief Error handling. //! //! ### Overview //! //! AsmJit uses error codes to represent and return errors. Every function that //! can fail returns an \ref Error code. Exceptions are never thrown by AsmJit //! itself even in extreme conditions like out-of-memory, but it's possible to //! override \ref ErrorHandler::handleError() to throw, in that case no error //! will be returned and exception will be thrown instead. All functions where //! this can happen are not marked `noexcept`. //! //! Errors should never be ignored, however, checking errors after each AsmJit //! API call would simply overcomplicate the whole code generation experience. //! \ref ErrorHandler exists to make the use of AsmJit API simpler as it allows //! to customize how errors can be handled: //! //! - Record the error and continue (the way how the error is user-implemented). //! - Throw an exception. AsmJit doesn't use exceptions and is completely //! exception-safe, but it's perfectly legal to throw an exception from //! the error handler. //! - Use plain old C's `setjmp()` and `longjmp()`. Asmjit always puts Assembler, //! Builder and Compiler to a consistent state before calling \ref //! ErrorHandler::handleError(), so `longjmp()` can be used without issues to //! cancel the code-generation if an error occurred. This method can be used if //! exception handling in your project is turned off and you still want some //! comfort. In most cases it should be safe as AsmJit uses \ref Zone memory //! and the ownership of memory it allocates always ends with the instance that //! allocated it. If using this approach please never jump outside the life-time //! of \ref CodeHolder and \ref BaseEmitter. //! //! ### Using ErrorHandler //! //! An example of attaching \ref ErrorHandler to \ref CodeHolder. //! //! ``` //! #include //! #include //! //! using namespace asmjit; //! //! // A simple error handler implementation, extend according to your needs. //! class MyErrorHandler : public ErrorHandler { //! public: //! void handleError(Error err, const char* message, BaseEmitter* origin) override { //! printf("AsmJit error: %s\n", message); //! } //! }; //! //! int main() { //! JitRuntime rt; //! //! MyErrorHandler myErrorHandler; //! CodeHolder code; //! //! code.init(rt.environment()); //! code.setErrorHandler(&myErrorHandler); //! //! x86::Assembler a(&code); //! // ... code generation ... //! //! return 0; //! } //! ``` //! //! Useful classes in error handling group: //! //! - See \ref DebugUtils that provides utilities useful for debugging. //! - See \ref Error that lists error codes that AsmJit uses. //! - See \ref ErrorHandler for more details about error handling. // ============================================================================ // [Documentation - asmjit_instruction_db] // ============================================================================ //! \defgroup asmjit_instruction_db Instruction DB //! \brief Instruction database (introspection, read/write, validation, ...). //! //! ### Overview //! //! AsmJit provides a public instruction database that can be used to query //! information about a complete instruction. The instruction database requires //! the knowledge of the following: //! //! - \ref BaseInst - Base instruction that contains instruction id, options, //! and a possible extra-register that represents either REP prefix counter //! or AVX-512 selector (mask). //! - \ref Operand - Represents operands of an instruction. //! //! Each instruction can be then queried for the following information: //! //! - \ref InstRWInfo - Read/write information of instruction and its oprands. //! - \ref OpRWInfo - Read/write information of a single operand, part of //! \ref InstRWInfo data structure. //! - \ref BaseFeatures - CPU features required to execute the instruction. //! //! In addition to query functionality AsmJit is also able to validate whether //! an instruction and its operands are valid. This is useful for making sure //! that what user tries to emit is correct and it can be also used by other //! projects that parse user input, like AsmTK project. //! //! ### Query API //! //! The instruction query API is provided by \ref InstAPI namespace. The //! following queries are possible: //! //! - \ref InstAPI::queryRWInfo() - queries read/write information of the //! given instruction and its operands. Includes also CPU flags read/written. //! //! - \ref InstAPI::queryFeatures() - queries CPU features that are required //! to execute the given instruction. A full instruction with operands must //! be given as some architectures like X86 may require different features //! for the same instruction based on its operands. //! //! - asmjit_test_x86_instinfo.cpp //! can be also used as a reference about accessing instruction information. //! //! ### Validation API //! //! The instruction validation API is provided by \ref InstAPI namespace in the //! similar fashion like the Query API, however, validation can also be turned //! on at \ref BaseEmitter level. The following is possible: //! //! - \ref InstAPI::validate() - low-level instruction validation function //! that is used internally by emitters if strict validation is enabled. //! //! - \ref BaseEmitter::addValidationOptions() - can be used to enable //! validation at emitter level, see \ref BaseEmitter::ValidationOptions. // ============================================================================ // [Documentation - asmjit_virtual_memory] // ============================================================================ //! \defgroup asmjit_virtual_memory Virtual Memory //! \brief Virtual memory management. //! //! ### Overview //! //! AsmJit's virtual memory management is divided into two main categories: //! //! - Low level API that provides cross-platform abstractions for virtual //! memory allocation. Implemented in \ref VirtMem namespace. //! - High level API that makes it very easy to store generated code for //! execution. See \ref JitRuntime, which is used by many examples for its //! simplicity and easy integration with \ref CodeHolder. There is also //! \ref JitAllocator, which lays somewhere between RAW memory allocation //! and \ref JitRuntime. // ============================================================================ // [Documentation - asmjit_zone_memory] // ============================================================================ //! \defgroup asmjit_zone Zone Memory //! \brief Zone memory allocator and containers. //! //! ### Overview //! //! AsmJit uses zone memory allocation (also known as Arena allocation) to allocate //! most of the data it uses. It's a fast allocator that allows AsmJit to allocate //! a lot of small data structures fast and without `malloc()` overhead. Since //! code generators and all related classes are usually short-lived this approach //! decreases memory usage and fragmentation as arena-based allocators always //! allocate larger blocks of memory, which are then split into smaller chunks. //! //! Another advantage of zone memory allocation is that since the whole library //! uses this strategy it's very easy to deallocate everything that a particular //! instance is holding by simply releasing the memory the allocator holds. This //! improves destruction time of such objects as there is no destruction at all. //! Long-lived objects just reset its data in destructor or in their reset() //! member function for a future reuse. For this purpose all containers in AsmJit //! are also zone allocated. //! //! ### Zone Allocation //! //! - \ref Zone - Incremental zone memory allocator with minimum features. It //! can only allocate memory without the possibility to return it back to //! the allocator. //! //! - \ref ZoneTmp - A temporary \ref Zone with some initial static storage. //! If the allocation requests fit the static storage allocated then there //! will be no dynamic memory allocation during the lifetime of \ref ZoneTmp, //! otherwise it would act as \ref Zone with one preallocated block on the //! stack. //! //! - \ref ZoneAllocator - A wrapper of \ref Zone that provides the capability //! of returning memory to the allocator. Such memory is stored in a pool for //! later reuse. //! //! ### Zone Allocated Containers //! //! - \ref ZoneString - Zone allocated string. //! - \ref ZoneHash - Zone allocated hash table. //! - \ref ZoneTree - Zone allocated red-black tree. //! - \ref ZoneList - Zone allocated double-linked list. //! - \ref ZoneStack - Zone allocated stack. //! - \ref ZoneVector - Zone allocated vector. //! - \ref ZoneBitVector - Zone allocated vector of bits. //! //! ### Using Zone Allocated Containers //! //! The most common data structure exposed by AsmJit is \ref ZoneVector. It's very //! similar to `std::vector`, but the implementation doesn't use exceptions and //! uses the mentioned \ref ZoneAllocator for performance reasons. You don't have //! to worry about allocations as you should not need to add items to AsmJit's //! data structures directly as there should be API for all required operations. //! //! The following APIs in \ref CodeHolder returns \ref ZoneVector reference: //! //! ``` //! using namespace asmjit; //! //! void example(CodeHolder& code) { //! // Contains all emitters attached to CodeHolder. //! const ZoneVector& emitters = code.emitters(); //! //! // Contains all section entries managed by CodeHolder. //! const ZoneVector& sections = code.sections(); //! //! // Contains all label entries managed by CodeHolder. //! const ZoneVector& labelEntries = code.labelEntries(); //! //! // Contains all relocation entries managed by CodeHolder. //! const ZoneVector& relocEntries = code.relocEntries(); //! } //! ``` //! //! \ref ZoneVector has overloaded array access operator to make it possible //! to access its elements through operator[]. Some standard functions like //! \ref ZoneVector::empty(), \ref ZoneVector::size(), and \ref ZoneVector::data() //! are provided as well. Vectors are also iterable through a range-based for loop: //! //! ``` //! using namespace asmjit; //! //! void example(CodeHolder& code) { //! for (LabelEntry* le : code.labelEntries()) { //! printf("Label #%u {Bound=%s Offset=%llu}", //! le->id(), //! le->isBound() ? "true" : "false", //! (unsigned long long)le->offset()); //! } //! } //! ``` //! //! ### Design Considerations //! //! Zone-allocated containers do not store the allocator within the container. //! This decision was made to reduce the footprint of such containers as AsmJit //! tooling, especially Compiler's register allocation, may use many instances //! of such containers to perform code analysis and register allocation. //! //! For example to append an item into a \ref ZoneVector it's required to pass //! the allocator as the first argument, so it can be used in case that the //! vector needs a reallocation. Such function also returns an error, which //! must be propagated to the caller. //! //! ``` //! using namespace asmjit //! //! Error example(ZoneAllocator* allocator) { //! ZoneVector vector; //! //! // Unfortunately, allocator must be provided to all functions that mutate //! // the vector. However, AsmJit users should never need to do this as all //! // manipulation should be done through public API, which takes care of //! // that. //! for (int i = 0; i < 100; i++) { //! ASMJIT_PROPAGATE(vector.append(allocator, i)); //! } //! //! // By default vector's destructor doesn't release anything as it knows //! // that its content is zone allocated. However, \ref ZoneVector::release //! // can be used to explicitly release the vector data to the allocator if //! // necessary //! vector.release(allocator); //! } //! ``` //! //! Containers like \ref ZoneVector also provide a functionality to reserve a //! certain number of items before any items are added to it. This approach is //! used internally in most places as it allows to prepare space for data that //! will be added to some container before the data itself was created. //! //! ``` //! using namespace asmjit //! //! Error example(ZoneAllocator* allocator) { //! ZoneVector vector; //! //! ASMJIT_PROPAGATE(vector.willGrow(100)); //! for (int i = 0; i < 100; i++) { //! // Cannot fail. //! vector.appendUnsafe(allocator, i); //! } //! //! vector.release(allocator); //! } //! ``` // ============================================================================ // [Documentation - asmjit_utilities] // ============================================================================ //! \defgroup asmjit_utilities Utilities //! \brief Utility classes and functions. //! //! ### Overview //! //! AsmJit uses and provides utility classes and functions, that can be used //! with AsmJit. The functionality can be divided into the following topics: //! //! ### String Functionality //! //! - \ref String - AsmJit's string container, which is used internally //! and which doesn't use exceptions and has a stable layout, which is //! not dependent on C++ standard library. //! - \ref StringTmp - String that can have base storage allocated on //! stack. The amount of storage on stack can be specified as a template //! parameter. //! - \ref FixedString - Fixed string container limited up to N characters. //! //! ### Code Generation Utilities //! //! - \ref ConstPool - Constant pool used by \ref BaseCompiler, but also //! available to users that may find use of it. //! //! ### Support Functionality Used by AsmJit //! //! - \ref Support namespace provides many other utility functions and //! classes that are used by AsmJit, and made public. // ============================================================================ // [Documentation - asmjit_ backends] // ============================================================================ //! \defgroup asmjit_x86 X86 Backend //! \brief X86/X64 backend. // ============================================================================ // [Documentation - asmjit_ra] // ============================================================================ //! \cond INTERNAL //! \defgroup asmjit_ra RA //! \brief Register allocator internals. //! \endcond } // {asmjit} // ============================================================================ // [Core Headers] // ============================================================================ #include "asmjit-scope-begin.h" #include "core/archtraits.h" #include "core/assembler.h" #include "core/builder.h" #include "core/codeholder.h" #include "core/compiler.h" #include "core/constpool.h" #include "core/cpuinfo.h" #include "core/datatypes.h" #include "core/emitter.h" #include "core/environment.h" #include "core/errorhandler.h" #include "core/features.h" #include "core/formatter.h" #include "core/func.h" #include "core/globals.h" #include "core/inst.h" #include "core/jitallocator.h" #include "core/jitruntime.h" #include "core/logger.h" #include "core/operand.h" #include "core/osutils.h" #include "core/string.h" #include "core/support.h" #include "core/target.h" #include "core/type.h" #include "core/virtmem.h" #include "core/zone.h" #include "core/zonehash.h" #include "core/zonelist.h" #include "core/zonetree.h" #include "core/zonestack.h" #include "core/zonestring.h" #include "core/zonevector.h" #include "asmjit-scope-end.h" // ============================================================================ // [Deprecated] // ============================================================================ #ifndef ASMJIT_NO_DEPRECATED namespace asmjit { #ifndef ASMJIT_NO_COMPILER ASMJIT_DEPRECATED("Use InvokeNode instead of FuncCallNode") typedef InvokeNode FuncCallNode; #endif // !ASMJIT_NO_COMPILER #ifndef ASMJIT_NO_LOGGING namespace Logging { using namespace Formatter; } #endif //! ASMJIT_NO_LOGGING } // {asmjit} #endif // !ASMJIT_NO_DEPRECATED #endif // ASMJIT_CORE_H_INCLUDED