Commit 2e8eef42 authored by Jason Swails's avatar Jason Swails
Browse files

Merge branch 'master' of github.com:/pandegroup/openmm into feature/cuda-docker

parents 4ec26e2f df52ff73
...@@ -157,7 +157,7 @@ ENDIF (NOT CMAKE_CXX_FLAGS_RELEASE) ...@@ -157,7 +157,7 @@ ENDIF (NOT CMAKE_CXX_FLAGS_RELEASE)
SET(OPENMM_LIBRARY_NAME OpenMM) SET(OPENMM_LIBRARY_NAME OpenMM)
SET(OPENMM_MAJOR_VERSION 7) SET(OPENMM_MAJOR_VERSION 7)
SET(OPENMM_MINOR_VERSION 3) SET(OPENMM_MINOR_VERSION 4)
SET(OPENMM_BUILD_VERSION 0) SET(OPENMM_BUILD_VERSION 0)
ADD_DEFINITIONS(-DOPENMM_LIBRARY_NAME=${OPENMM_LIBRARY_NAME} ADD_DEFINITIONS(-DOPENMM_LIBRARY_NAME=${OPENMM_LIBRARY_NAME}
......
...@@ -851,7 +851,7 @@ by the user. That is, the interaction energy of each angle is given by ...@@ -851,7 +851,7 @@ by the user. That is, the interaction energy of each angle is given by
where :math:`f(\theta)` is a user defined mathematical expression. The angle where :math:`f(\theta)` is a user defined mathematical expression. The angle
:math:`\theta` is guaranteed to be in the range [-π, π]. Like PeriodicTorsionForce, it :math:`\theta` is guaranteed to be in the range :math:`[-\pi, +\pi]`\ . Like PeriodicTorsionForce, it
is defined to be zero when the first and last particles are on the same side of is defined to be zero when the first and last particles are on the same side of
the bond formed by the middle two particles (the *cis* configuration). the bond formed by the middle two particles (the *cis* configuration).
...@@ -973,7 +973,7 @@ of four particles. That is, the interaction energy of each bond is given by ...@@ -973,7 +973,7 @@ of four particles. That is, the interaction energy of each bond is given by
where *f*\ (\ *...*\ ) is a user defined mathematical expression. It may where *f*\ (\ *...*\ ) is a user defined mathematical expression. It may
depend on an arbitrary set of positions {\ :math:`x_i`\ }, distances {\ :math:`r_i`\ }, depend on an arbitrary set of positions {\ :math:`x_i`\ }, distances {\ :math:`r_i`\ },
angles {\ :math:`\theta_i`\ }, and dihedral angles {\ :math:`\phi_i`\ } angles {\ :math:`\theta_i`\ }, and dihedral angles {\ :math:`\phi_i`\ }
guaranteed to be in the range [-π, π]. guaranteed to be in the range :math:`[-\pi, +\pi]`\ .
Each distance, angle, or dihedral is defined by specifying a sequence of Each distance, angle, or dihedral is defined by specifying a sequence of
particles chosen from among the particles that make up the bond. A distance particles chosen from among the particles that make up the bond. A distance
...@@ -1209,7 +1209,7 @@ The following operators are supported: + (add), - (subtract), * (multiply), / ...@@ -1209,7 +1209,7 @@ The following operators are supported: + (add), - (subtract), * (multiply), /
(divide), and ^ (power). Parentheses “(“ and “)” may be used for grouping. (divide), and ^ (power). Parentheses “(“ and “)” may be used for grouping.
The following standard functions are supported: sqrt, exp, log, sin, cos, sec, The following standard functions are supported: sqrt, exp, log, sin, cos, sec,
csc, tan, cot, asin, acos, atan, sinh, cosh, tanh, erf, erfc, min, max, abs, csc, tan, cot, asin, acos, atan, atan2, sinh, cosh, tanh, erf, erfc, min, max, abs,
floor, ceil, step, delta, select. step(x) = 0 if x < 0, 1 otherwise. floor, ceil, step, delta, select. step(x) = 0 if x < 0, 1 otherwise.
delta(x) = 1 if x is 0, 0 otherwise. select(x,y,z) = z if x = 0, y otherwise. delta(x) = 1 if x is 0, 0 otherwise. select(x,y,z) = z if x = 0, y otherwise.
Some custom forces allow additional functions to be defined from tabulated values. Some custom forces allow additional functions to be defined from tabulated values.
......
AsmJit - Complete x86/x64 JIT and Remote Assembler for C++ Copyright (c) 2008-2017, Petr Kobalicek
Copyright (c) 2008-2014, Petr Kobalicek <kobalicek.petr@gmail.com>
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
......
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Guard]
#ifndef _ASMJIT_ARM_H
#define _ASMJIT_ARM_H
// [Dependencies]
#include "./base.h"
#include "./arm/armassembler.h"
#include "./arm/armbuilder.h"
#include "./arm/armcompiler.h"
#include "./arm/arminst.h"
#include "./arm/armoperand.h"
// [Guard]
#endif // _ASMJIT_ARM_H
...@@ -12,368 +12,36 @@ ...@@ -12,368 +12,36 @@
// [asmjit_mainpage] // [asmjit_mainpage]
// ============================================================================ // ============================================================================
//! @mainpage //! \mainpage
//! //!
//! AsmJit - Complete x86/x64 JIT and Remote Assembler for C++. //! AsmJit - Complete x86/x64 JIT and Remote Assembler for C++.
//! //!
//! AsmJit is a complete JIT and remote assembler for C++ language. It can //! Introduction provided by the project page at https://github.com/asmjit/asmjit.
//! generate native code for x86 and x64 architectures having support for
//! a full instruction set, from legacy MMX to the newest AVX2. It has a
//! type-safe API that allows C++ compiler to do a semantic checks at
//! compile-time even before the assembled code is generated or run.
//!
//! AsmJit is not a virtual machine (VM). It doesn't have functionality to
//! implement VM out of the box; however, it can be be used as a JIT backend
//! for your own VM. The usage of AsmJit is not limited at all; it's suitable
//! for multimedia, VM backends or remote code generation.
//!
//! @section AsmJit_Concepts Code Generation Concepts
//!
//! AsmJit has two completely different code generation concepts. The difference
//! is in how the code is generated. The first concept, also referred as the low
//! level concept, is called 'Assembler' and it's the same as writing RAW
//! assembly by using physical registers directly. In this case AsmJit does only
//! instruction encoding, verification and relocation.
//!
//! The second concept, also referred as the high level concept, is called
//! 'Compiler'. Compiler lets you use virtually unlimited number of registers
//! (called variables) significantly simplifying the code generation process.
//! Compiler allocates these virtual registers to physical registers after the
//! code generation is done. This requires some extra effort - Compiler has to
//! generate information for each node (instruction, function declaration,
//! function call) in the code, perform a variable liveness analysis and
//! translate the code having variables into code having only registers.
//!
//! In addition, Compiler understands functions and function calling conventions.
//! It has been designed in a way that the code generated is always a function
//! having prototype like in a programming language. By having a function
//! prototype the Compiler is able to insert prolog and epilog to a function
//! being generated and it is able to call a function inside a generated one.
//!
//! There is no conclusion on which concept is better. Assembler brings full
//! control on how the code is generated, while Compiler makes the generation
//! more portable.
//!
//! @section AsmJit_Main_CodeGeneration Code Generation
//!
//! - \ref asmjit_base_general "Assembler core" - Operands, intrinsics and low-level assembler.
//! - \ref asmjit_compiler "Compiler" - High level code generation.
//! - \ref asmjit_cpuinfo "Cpu Information" - Get information about host processor.
//! - \ref asmjit_logging "Logging" - Logging and error handling.
//! - \ref AsmJit_MemoryManagement "Memory Management" - Virtual memory management.
//!
//! @section AsmJit_Main_HomePage AsmJit Homepage
//!
//! - https://github.com/kobalicek/asmjit
// ============================================================================
// [asmjit_base]
// ============================================================================
//! \defgroup asmjit_base AsmJit
//!
//! \brief AsmJit.
// ============================================================================
// [asmjit_base_general]
// ============================================================================
//! \defgroup asmjit_base_general AsmJit General API
//! \ingroup asmjit_base
//!
//! \brief AsmJit general API.
//!
//! Contains all `asmjit` classes and helper functions that are architecture
//! independent or abstract. Abstract classes are implemented by the backend,
//! for example `Assembler` is implemented by `X86Assembler`.
//!
//! - See `Assembler` for low level code generation documentation.
//! - See `Compiler` for high level code generation documentation.
//! - See `Operand` for operand's overview.
//!
//! Logging and Error Handling
//! --------------------------
//!
//! AsmJit contains robust interface that can be used to log the generated code
//! and to handle possible errors. Base logging interface is defined in `Logger`
//! class that is abstract and can be overridden. AsmJit contains two loggers
//! that can be used out of the box - `FileLogger` that logs into a pure C
//! `FILE*` stream and `StringLogger` that just concatenates all log messages
//! by using a `StringBuilder` class.
//!
//! The following snippet shows how to setup a logger that logs to `stderr`:
//!
//! ~~~
//! // `FileLogger` instance.
//! FileLogger logger(stderr);
//!
//! // `Compiler` or any other `CodeGen` interface.
//! host::Compiler c;
//!
//! // use `setLogger` to replace the `CodeGen` logger.
//! c.setLogger(&logger);
//! ~~~
//!
//! \sa \ref Logger, \ref FileLogger, \ref StringLogger.
// ============================================================================ //! \defgroup asmjit_base AsmJit Base API (architecture independent)
// [asmjit_base_compiler]
// ============================================================================
//! \defgroup asmjit_base_compiler AsmJit Compiler
//! \ingroup asmjit_base
//!
//! \brief AsmJit code-tree used by Compiler.
//! //!
//! AsmJit intermediate code-tree is a double-linked list that is made of nodes //! \brief Backend Neutral API.
//! that represent assembler instructions, directives, labels and high-level
//! constructs compiler is using to represent functions and function calls. The
//! node list can only be used together with \ref Compiler.
//!
//! TODO
// ============================================================================
// [asmjit_base_util]
// ============================================================================
//! \defgroup asmjit_base_util AsmJit Utilities //! \defgroup asmjit_x86 AsmJit X86/X64 API
//! \ingroup asmjit_base
//!
//! \brief AsmJit utility classes.
//!
//! AsmJit contains numerous utility classes that are needed by the library
//! itself. The most useful ones have been made public and are now exported.
//! //!
//! POD Containers //! \brief X86/X64 Backend API.
//! --------------
//!
//! POD containers are used by AsmJit to manage its own data structures. The
//! following classes can be used by AsmJit consumers:
//!
//! - \ref PodVector - Simple growing array-like container for POD data.
//! - \ref StringBuilder - Simple string builder that can append string
//! and integers.
//!
//! Zone Memory Allocator
//! ---------------------
//!
//! Zone memory allocator is an incremental memory allocator that can be used
//! to allocate data of short life-time. It has much better performance
//! characteristics than all other allocators, because the only thing it can do
//! is to increment a pointer and return its previous address. See \ref Zone
//! for more details.
//!
//! CPU Ticks
//! ---------
//!
//! CPU Ticks is a simple helper that can be used to do basic benchmarks. See
//! \ref CpuTicks class for more details.
//!
//! Integer Utilities
//! -----------------
//!
//! Integer utilities are all implemented by a static class \ref IntUtil.
//! There are utilities for bit manipulation and bit counting, utilities to get
//! an integer minimum / maximum and various other helpers required to perform
//! alignment checks and binary casting from float to integer and vica versa.
//!
//! Vector Utilities
//! ----------------
//!
//! SIMD code generation often requires to embed constants after each function
//! or a block of functions generated. AsmJit contains classes `Vec64`,
//! `Vec128` and `Vec256` that can be used to prepare data useful when
//! generating SIMD code.
//!
//! X86/X64 code generator contains member functions `dmm`, `dxmm` and `dymm`
//! which can be used to embed 64-bit, 128-bit and 256-bit data structures into
//! machine code (both assembler and compiler are supported).
//!
//! \note Compiler contains a constant pool, which should be used instead of
//! embedding constants manually after the function body.
// ============================================================================
// [asmjit_x86]
// ============================================================================
//! \defgroup asmjit_x86 X86/X64
//!
//! \brief X86/X64 module
// ============================================================================
// [asmjit_x86_general]
// ============================================================================
//! \defgroup asmjit_x86_general X86/X64 General API
//! \ingroup asmjit_x86
//!
//! \brief X86/X64 general API.
//!
//! X86/X64 Registers
//! -----------------
//!
//! There are static objects that represents X86 and X64 registers. They can
//! be used directly (like `eax`, `mm`, `xmm`, ...) or created through
//! these functions:
//!
//! - `asmjit::gpb_lo()` - Get Gpb-lo register.
//! - `asmjit::gpb_hi()` - Get Gpb-hi register.
//! - `asmjit::gpw()` - Get Gpw register.
//! - `asmjit::gpd()` - Get Gpd register.
//! - `asmjit::gpq()` - Get Gpq Gp register.
//! - `asmjit::gpz()` - Get Gpd/Gpq register.
//! - `asmjit::fp()` - Get Fp register.
//! - `asmjit::mm()` - Get Mm register.
//! - `asmjit::xmm()` - Get Xmm register.
//! - `asmjit::ymm()` - Get Ymm register.
//!
//! X86/X64 Addressing
//! ------------------
//!
//! X86 and x64 architectures contains several addressing modes and most ones
//! are possible with AsmJit library. Memory represents are represented by
//! `BaseMem` class. These functions are used to make operands that represents
//! memory addresses:
//!
//! - `asmjit::ptr()` - Address size not specified.
//! - `asmjit::byte_ptr()` - 1 byte.
//! - `asmjit::word_ptr()` - 2 bytes (Gpw size).
//! - `asmjit::dword_ptr()` - 4 bytes (Gpd size).
//! - `asmjit::qword_ptr()` - 8 bytes (Gpq/Mm size).
//! - `asmjit::tword_ptr()` - 10 bytes (FPU).
//! - `asmjit::oword_ptr()` - 16 bytes (Xmm size).
//! - `asmjit::yword_ptr()` - 32 bytes (Ymm size).
//! - `asmjit::zword_ptr()` - 64 bytes (Zmm size).
//!
//! Most useful function to make pointer should be `asmjit::ptr()`. It creates
//! pointer to the target with unspecified size. Unspecified size works in all
//! intrinsics where are used registers (this means that size is specified by
//! register operand or by instruction itself). For example `asmjit::ptr()`
//! can't be used with `Assembler::inc()` instruction. In this case size must
//! be specified and it's also reason to make difference between pointer sizes.
//!
//! Supported are simple address forms `[base + displacement]` and complex
//! address forms `[base + index * scale + displacement]`.
//!
//! X86/X64 Immediates
//! ------------------
//!
//! Immediate values are constants thats passed directly after instruction
//! opcode. To create such value use `imm()` or `imm_u()` methods to create
//! signed or unsigned immediate value.
//!
//! X86/X64 CPU Information
//! -----------------------
//!
//! The CPUID instruction can be used to get an exhaustive information about
//! the host X86/X64 processor. AsmJit contains utilities that can get the most
//! important information related to the features supported by the CPU and the
//! host operating system, in addition to host processor name and number of
//! cores. Class `X86CpuInfo` extends `CpuInfo` and provides functionality
//! specific to X86 and X64.
//!
//! By default AsmJit queries the CPU information after the library is loaded
//! and the queried information is reused by all instances of `JitRuntime`.
//! The global instance of `X86CpuInfo` can't be changed, because it will affect
//! the code generation of all `Runtime`s. If there is a need to have a
//! specific CPU information which contains modified features or processor
//! vendor it's possible by creating a new instance of `X86CpuInfo` and setting
//! up its members. `X86CpuUtil::detect` can be used to detect CPU features into
//! an existing `X86CpuInfo` instance - it may become handly if only one property
//! has to be turned on/off.
//!
//! If the high-level interface `X86CpuInfo` offers is not enough there is also
//! `X86CpuUtil::callCpuId` helper that can be used to call CPUID instruction
//! with a given parameters and to consume the output.
//!
//! Cpu detection is important when generating a JIT code that may or may not
//! use certain CPU features. For example there used to be a SSE/SSE2 detection
//! in the past and today there is often AVX/AVX2 detection.
//!
//! The example below shows how to detect SSE2:
//!
//! ~~~
//! using namespace asmjit;
//!
//! // Get `X86CpuInfo` global instance.
//! const X86CpuInfo* cpuInfo = X86CpuInfo::getHost();
//!
//! if (cpuInfo->hasFeature(kX86CpuFeatureSSE2)) {
//! // Processor has SSE2.
//! }
//! else if (cpuInfo->hasFeature(kX86CpuFeatureMMX)) {
//! // Processor doesn't have SSE2, but has MMX.
//! }
//! else {
//! // Processor is archaic; it's a wonder AsmJit works here!
//! }
//! ~~~
//!
//! The next example shows how to call `CPUID` directly:
//!
//! ~~~
//! using namespace asmjit;
//!
//! // Call cpuid, first two arguments are passed in Eax/Ecx.
//! X86CpuId out;
//! X86CpuUtil::callCpuId(0, 0, &out);
//!
//! // If Eax argument is 0, Ebx, Ecx and Edx registers are filled with a cpu vendor.
//! char cpuVendor[13];
//! ::memcpy(cpuVendor, &out.ebx, 4);
//! ::memcpy(cpuVendor + 4, &out.edx, 4);
//! ::memcpy(cpuVendor + 8, &out.ecx, 4);
//! vendor[12] = '\0';
//!
//! // Print a CPU vendor retrieved from CPUID.
//! ::printf("%s", cpuVendor);
//! ~~~
// ============================================================================
// [asmjit_x86_compiler]
// ============================================================================
//! \defgroup asmjit_x86_compiler X86/X64 Code-Tree
//! \ingroup asmjit_x86
//!
//! \brief X86/X64 code-tree and helpers.
// ============================================================================
// [asmjit_x86_inst]
// ============================================================================
//! \defgroup asmjit_x86_inst X86/X64 Instructions
//! \ingroup asmjit_x86
//!
//! \brief X86/X64 low-level instruction definitions.
// ============================================================================
// [asmjit_x86_util]
// ============================================================================
//! \defgroup asmjit_x86_util X86/X64 Utilities
//! \ingroup asmjit_x86
//!
//! \brief X86/X64 utility classes.
// ============================================================================
// [asmjit_contrib]
// ============================================================================
//! \defgroup asmjit_contrib Contributions //! \defgroup asmjit_arm AsmJit ARM32/ARM64 API
//! //!
//! \brief Contributions. //! \brief ARM32/ARM64 Backend API.
// [Dependencies - Base] // [Dependencies]
#include "base.h" #include "./base.h"
// [Dependencies - X86/X64] // [X86/X64]
#if defined(ASMJIT_BUILD_X86) || defined(ASMJIT_BUILD_X64) #if defined(ASMJIT_BUILD_X86)
#include "x86.h" #include "./x86.h"
#endif // ASMJIT_BUILD_X86 || ASMJIT_BUILD_X64 #endif // ASMJIT_BUILD_X86
// [Dependencies - Host] // [ARM32/ARM64]
#include "host.h" #if defined(ASMJIT_BUILD_ARM)
#include "./arm.h"
#endif // ASMJIT_BUILD_ARM
// [Guard] // [Guard]
#endif // _ASMJIT_ASMJIT_H #endif // _ASMJIT_ASMJIT_H
...@@ -4,81 +4,119 @@ ...@@ -4,81 +4,119 @@
// [License] // [License]
// Zlib - See LICENSE.md file in the package. // Zlib - See LICENSE.md file in the package.
// [Dependencies - AsmJit] // [Dependencies]
#if !defined(_ASMJIT_BUILD_H) #if !defined(_ASMJIT_BUILD_H)
#include "build.h" # include "./build.h"
#endif // !_ASMJIT_BUILD_H #endif // !_ASMJIT_BUILD_H
// [Guard] // [Guard]
#if !defined(ASMJIT_API_SCOPE) #if !defined(ASMJIT_API_SCOPE)
# define ASMJIT_API_SCOPE # define ASMJIT_API_SCOPE
#else #else
# error "AsmJit - Api-Scope is already active, previous scope not closed by apiend.h?" # error "[asmjit] api-scope is already active, previous scope not closed by asmjit_apiend.h?"
#endif // ASMJIT_API_SCOPE #endif // ASMJIT_API_SCOPE
// ============================================================================ // ============================================================================
// [Override] // [C++ Support]
// ============================================================================ // ============================================================================
#if !defined(ASMJIT_CC_HAS_OVERRIDE) && !defined(override) // [NoExcept]
#if !ASMJIT_CC_HAS_NOEXCEPT && !defined(noexcept)
# define noexcept ASMJIT_NOEXCEPT
# define ASMJIT_UNDEF_NOEXCEPT
#endif // !ASMJIT_CC_HAS_NOEXCEPT && !noexcept
// [NullPtr]
#if !ASMJIT_CC_HAS_NULLPTR && !defined(nullptr)
# define nullptr NULL
# define ASMJIT_UNDEF_NULLPTR
#endif // !ASMJIT_CC_HAS_NULLPTR && !nullptr
// [Override]
#if !ASMJIT_CC_HAS_OVERRIDE && !defined(override)
# define override # define override
# define ASMJIT_UNDEF_OVERRIDE # define ASMJIT_UNDEF_OVERRIDE
#endif // !ASMJIT_CC_HAS_OVERRIDE && !override #endif // !ASMJIT_CC_HAS_OVERRIDE && !override
// ============================================================================ // ============================================================================
// [NoExcept] // [Compiler Support]
// ============================================================================ // ============================================================================
#if !defined(ASMJIT_CC_HAS_NOEXCEPT) && !defined(noexcept) // [Clang]
# define noexcept ASMJIT_NOEXCEPT #if ASMJIT_CC_CLANG
# define ASMJIT_UNDEF_NOEXCEPT # pragma clang diagnostic push
#endif // !ASMJIT_CC_HAS_NOEXCEPT && !noexcept # pragma clang diagnostic ignored "-Wc++11-extensions"
# pragma clang diagnostic ignored "-Wconstant-logical-operand"
# pragma clang diagnostic ignored "-Wunnamed-type-template-args"
#endif // ASMJIT_CC_CLANG
// ============================================================================ // [GCC]
// [MSC] #if ASMJIT_CC_GCC
// ============================================================================ # pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wbool-operation"
# if ASMJIT_CC_GCC_GE(8, 0, 0)
# pragma GCC diagnostic ignored "-Wclass-memaccess"
# endif
#endif // ASMJIT_CC_GCC
#if defined(_MSC_VER) // [MSC]
// Disable some warnings we know about #if ASMJIT_CC_MSC
# pragma warning(push) # pragma warning(push)
# pragma warning(disable: 4127) // conditional expression is constant # pragma warning(disable: 4127) // conditional expression is constant
# pragma warning(disable: 4201) // nameless struct/union # pragma warning(disable: 4201) // nameless struct/union
# pragma warning(disable: 4244) // '+=' : conversion from 'int' to 'x', possible # pragma warning(disable: 4244) // '+=' : conversion from 'int' to 'x', possible loss of data
// loss of data # pragma warning(disable: 4251) // struct needs to have dll-interface to be used by clients of struct ...
# pragma warning(disable: 4251) // struct needs to have dll-interface to be used # pragma warning(disable: 4275) // non dll-interface struct ... used as base for dll-interface struct
// by clients of struct ...
# pragma warning(disable: 4275) // non dll-interface struct ... used as base for
// dll-interface struct
# pragma warning(disable: 4355) // this used in base member initializer list # pragma warning(disable: 4355) // this used in base member initializer list
# pragma warning(disable: 4480) // specifying underlying type for enum # pragma warning(disable: 4480) // specifying underlying type for enum
# pragma warning(disable: 4800) // forcing value to bool 'true' or 'false' # pragma warning(disable: 4800) // forcing value to bool 'true' or 'false'
# pragma warning(disable: 4838) // comversion from 'int' to ...
// Rename symbols. # if _MSC_VER < 1900
# if !defined(vsnprintf) # if !defined(vsnprintf)
# define ASMJIT_UNDEF_VSNPRINTF # define ASMJIT_UNDEF_VSNPRINTF
# define vsnprintf _vsnprintf # define vsnprintf _vsnprintf
# endif // !vsnprintf # endif // !vsnprintf
# if !defined(snprintf) # if !defined(snprintf)
# define ASMJIT_UNDEF_SNPRINTF # define ASMJIT_UNDEF_SNPRINTF
# define snprintf _snprintf # define snprintf _snprintf
# endif // !snprintf # endif // !snprintf
#endif // _MSC_VER # endif
#endif // ASMJIT_CC_MSC
// ============================================================================ // ============================================================================
// [CLang] // [Custom Macros]
// ============================================================================ // ============================================================================
#if defined(__clang__) // [ASMJIT_NON...]
# pragma clang diagnostic push #if ASMJIT_CC_HAS_DELETE_FUNCTION
# pragma clang diagnostic ignored "-Wunnamed-type-template-args" #define ASMJIT_NONCONSTRUCTIBLE(...) \
#endif // __clang__ private: \
__VA_ARGS__() = delete; \
// ============================================================================ __VA_ARGS__(const __VA_ARGS__& other) = delete; \
// [GCC] __VA_ARGS__& operator=(const __VA_ARGS__& other) = delete; \
// ============================================================================ public:
#define ASMJIT_NONCOPYABLE(...) \
private: \
__VA_ARGS__(const __VA_ARGS__& other) = delete; \
__VA_ARGS__& operator=(const __VA_ARGS__& other) = delete; \
public:
#else
#define ASMJIT_NONCONSTRUCTIBLE(...) \
private: \
inline __VA_ARGS__(); \
inline __VA_ARGS__(const __VA_ARGS__& other); \
inline __VA_ARGS__& operator=(const __VA_ARGS__& other); \
public:
#define ASMJIT_NONCOPYABLE(...) \
private: \
inline __VA_ARGS__(const __VA_ARGS__& other); \
inline __VA_ARGS__& operator=(const __VA_ARGS__& other); \
public:
#endif // ASMJIT_CC_HAS_DELETE_FUNCTION
#if defined(__GNUC__) && !defined(__clang__) // [ASMJIT_ENUM]
# if __GNUC__ >= 4 && !defined(__MINGW32__) #if defined(_MSC_VER) && _MSC_VER >= 1400
# pragma GCC visibility push(hidden) # define ASMJIT_ENUM(NAME) enum NAME : uint32_t
# endif // GCC 4+ #else
#endif // __GNUC__ # define ASMJIT_ENUM(NAME) enum NAME
#endif
...@@ -8,60 +8,67 @@ ...@@ -8,60 +8,67 @@
#if defined(ASMJIT_API_SCOPE) #if defined(ASMJIT_API_SCOPE)
# undef ASMJIT_API_SCOPE # undef ASMJIT_API_SCOPE
#else #else
# error "AsmJit - Api-Scope not active, forgot to include apibegin.h?" # error "[asmjit] api-scope not active, forgot to include asmjit_apibegin.h?"
#endif // ASMJIT_API_SCOPE #endif // ASMJIT_API_SCOPE
// ============================================================================ // ============================================================================
// [Override] // [C++ Support]
// ============================================================================ // ============================================================================
#if defined(ASMJIT_UNDEF_OVERRIDE)
# undef override
# undef ASMJIT_UNDEF_OVERRIDE
#endif // ASMJIT_UNDEF_OVERRIDE
// ============================================================================
// [NoExcept] // [NoExcept]
// ============================================================================
#if defined(ASMJIT_UNDEF_NOEXCEPT) #if defined(ASMJIT_UNDEF_NOEXCEPT)
# undef noexcept # undef noexcept
# undef ASMJIT_UNDEF_NOEXCEPT # undef ASMJIT_UNDEF_NOEXCEPT
#endif // ASMJIT_UNDEF_NOEXCEPT #endif // ASMJIT_UNDEF_NOEXCEPT
// ============================================================================ // [NullPtr]
// [MSC] #if defined(ASMJIT_UNDEF_NULLPTR)
// ============================================================================ # undef nullptr
# undef ASMJIT_UNDEF_NULLPTR
#if defined(_MSC_VER) #endif // ASMJIT_UNDEF_NULLPTR
# pragma warning(pop)
# if defined(ASMJIT_UNDEF_VSNPRINTF)
# undef vsnprintf
# undef ASMJIT_UNDEF_VSNPRINTF
# endif // ASMJIT_UNDEF_VSNPRINTF
# if defined(ASMJIT_UNDEF_SNPRINTF)
# undef snprintf
# undef ASMJIT_UNDEF_SNPRINTF
# endif // ASMJIT_UNDEF_SNPRINTF
#endif // _MSC_VER // [Override]
#if defined(ASMJIT_UNDEF_OVERRIDE)
# undef override
# undef ASMJIT_UNDEF_OVERRIDE
#endif // ASMJIT_UNDEF_OVERRIDE
// ============================================================================ // ============================================================================
// [CLang] // [Compiler Support]
// ============================================================================ // ============================================================================
#if defined(__clang__) // [Clang]
#if ASMJIT_CC_CLANG
# pragma clang diagnostic pop # pragma clang diagnostic pop
#endif // __clang__ #endif // ASMJIT_CC_CLANG
// ============================================================================
// [GCC] // [GCC]
#if ASMJIT_CC_GCC
# pragma GCC diagnostic pop
#endif // ASMJIT_CC_GCC
// [MSC]
#if ASMJIT_CC_MSC
# pragma warning(pop)
# if _MSC_VER < 1900
# if defined(ASMJIT_UNDEF_VSNPRINTF)
# undef vsnprintf
# undef ASMJIT_UNDEF_VSNPRINTF
# endif // ASMJIT_UNDEF_VSNPRINTF
# if defined(ASMJIT_UNDEF_SNPRINTF)
# undef snprintf
# undef ASMJIT_UNDEF_SNPRINTF
# endif // ASMJIT_UNDEF_SNPRINTF
# endif
#endif // ASMJIT_CC_MSC
// ============================================================================
// [Custom Macros]
// ============================================================================ // ============================================================================
#if defined(__GNUC__) && !defined(__clang__) // [ASMJIT_NON...]
# if __GNUC__ >= 4 && !defined(__MINGW32__) #undef ASMJIT_NONCONSTRUCTIBLE
# pragma GCC visibility pop #undef ASMJIT_NONCOPYABLE
# endif // GCC 4+
#endif // __GNUC__ // [ASMJIT_ENUM]
#undef ASMJIT_ENUM
This diff is collapsed.
...@@ -8,27 +8,27 @@ ...@@ -8,27 +8,27 @@
#ifndef _ASMJIT_BASE_H #ifndef _ASMJIT_BASE_H
#define _ASMJIT_BASE_H #define _ASMJIT_BASE_H
// [Dependencies - AsmJit] // [Dependencies]
#include "build.h" #include "./base/arch.h"
#include "./base/assembler.h"
#include "base/assembler.h" #include "./base/codebuilder.h"
#include "base/codegen.h" #include "./base/codecompiler.h"
#include "base/compiler.h" #include "./base/codeemitter.h"
#include "base/constpool.h" #include "./base/codeholder.h"
#include "base/containers.h" #include "./base/constpool.h"
#include "base/cpuinfo.h" #include "./base/cpuinfo.h"
#include "base/cputicks.h" #include "./base/func.h"
#include "base/error.h" #include "./base/globals.h"
#include "base/globals.h" #include "./base/inst.h"
#include "base/intutil.h" #include "./base/logging.h"
#include "base/lock.h" #include "./base/operand.h"
#include "base/logger.h" #include "./base/osutils.h"
#include "base/operand.h" #include "./base/runtime.h"
#include "base/runtime.h" #include "./base/simdtypes.h"
#include "base/string.h" #include "./base/string.h"
#include "base/vectypes.h" #include "./base/utils.h"
#include "base/vmem.h" #include "./base/vmem.h"
#include "base/zone.h" #include "./base/zone.h"
// [Guard] // [Guard]
#endif // _ASMJIT_BASE_H #endif // _ASMJIT_BASE_H
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Export]
#define ASMJIT_EXPORTS
// [Dependencies]
#include "../base/arch.h"
#if defined(ASMJIT_BUILD_X86)
#include "../x86/x86operand.h"
#endif // ASMJIT_BUILD_X86
// [Api-Begin]
#include "../asmjit_apibegin.h"
namespace asmjit {
// ============================================================================
// [asmjit::ArchInfo]
// ============================================================================
static const uint32_t archInfoTable[] = {
// <-------------+---------------------+-----------------------+-------+
// | Type | SubType | GPInfo|
// <-------------+---------------------+-----------------------+-------+
ASMJIT_PACK32_4x8(ArchInfo::kTypeNone , ArchInfo::kSubTypeNone, 0, 0),
ASMJIT_PACK32_4x8(ArchInfo::kTypeX86 , ArchInfo::kSubTypeNone, 4, 8),
ASMJIT_PACK32_4x8(ArchInfo::kTypeX64 , ArchInfo::kSubTypeNone, 8, 16),
ASMJIT_PACK32_4x8(ArchInfo::kTypeX32 , ArchInfo::kSubTypeNone, 8, 16),
ASMJIT_PACK32_4x8(ArchInfo::kTypeA32 , ArchInfo::kSubTypeNone, 4, 16),
ASMJIT_PACK32_4x8(ArchInfo::kTypeA64 , ArchInfo::kSubTypeNone, 8, 32)
};
ASMJIT_FAVOR_SIZE void ArchInfo::init(uint32_t type, uint32_t subType) noexcept {
uint32_t index = type < ASMJIT_ARRAY_SIZE(archInfoTable) ? type : uint32_t(0);
// Make sure the `archInfoTable` array is correctly indexed.
_signature = archInfoTable[index];
ASMJIT_ASSERT(_type == index);
// Even if the architecture is not known we setup its type and sub-type,
// however, such architecture is not really useful.
_type = type;
_subType = subType;
}
// ============================================================================
// [asmjit::ArchUtils]
// ============================================================================
ASMJIT_FAVOR_SIZE Error ArchUtils::typeIdToRegInfo(uint32_t archType, uint32_t& typeIdInOut, RegInfo& regInfo) noexcept {
uint32_t typeId = typeIdInOut;
// Zero the signature so it's clear in case that typeId is not invalid.
regInfo._signature = 0;
#if defined(ASMJIT_BUILD_X86)
if (ArchInfo::isX86Family(archType)) {
// Passed RegType instead of TypeId?
if (typeId <= Reg::kRegMax)
typeId = x86OpData.archRegs.regTypeToTypeId[typeId];
if (ASMJIT_UNLIKELY(!TypeId::isValid(typeId)))
return DebugUtils::errored(kErrorInvalidTypeId);
// First normalize architecture dependent types.
if (TypeId::isAbstract(typeId)) {
if (typeId == TypeId::kIntPtr)
typeId = (archType == ArchInfo::kTypeX86) ? TypeId::kI32 : TypeId::kI64;
else
typeId = (archType == ArchInfo::kTypeX86) ? TypeId::kU32 : TypeId::kU64;
}
// Type size helps to construct all kinds of registers. If the size is zero
// then the TypeId is invalid.
uint32_t size = TypeId::sizeOf(typeId);
if (ASMJIT_UNLIKELY(!size))
return DebugUtils::errored(kErrorInvalidTypeId);
if (ASMJIT_UNLIKELY(typeId == TypeId::kF80))
return DebugUtils::errored(kErrorInvalidUseOfF80);
uint32_t regType = 0;
switch (typeId) {
case TypeId::kI8:
case TypeId::kU8:
regType = X86Reg::kRegGpbLo;
break;
case TypeId::kI16:
case TypeId::kU16:
regType = X86Reg::kRegGpw;
break;
case TypeId::kI32:
case TypeId::kU32:
regType = X86Reg::kRegGpd;
break;
case TypeId::kI64:
case TypeId::kU64:
if (archType == ArchInfo::kTypeX86)
return DebugUtils::errored(kErrorInvalidUseOfGpq);
regType = X86Reg::kRegGpq;
break;
// F32 and F64 are always promoted to use vector registers.
case TypeId::kF32:
typeId = TypeId::kF32x1;
regType = X86Reg::kRegXmm;
break;
case TypeId::kF64:
typeId = TypeId::kF64x1;
regType = X86Reg::kRegXmm;
break;
// Mask registers {k}.
case TypeId::kMask8:
case TypeId::kMask16:
case TypeId::kMask32:
case TypeId::kMask64:
regType = X86Reg::kRegK;
break;
// MMX registers.
case TypeId::kMmx32:
case TypeId::kMmx64:
regType = X86Reg::kRegMm;
break;
// XMM|YMM|ZMM registers.
default:
if (size <= 16)
regType = X86Reg::kRegXmm;
else if (size == 32)
regType = X86Reg::kRegYmm;
else
regType = X86Reg::kRegZmm;
break;
}
typeIdInOut = typeId;
regInfo._signature = x86OpData.archRegs.regInfo[regType].getSignature();
return kErrorOk;
}
#endif // ASMJIT_BUILD_X86
return DebugUtils::errored(kErrorInvalidArch);
}
} // asmjit namespace
// [Api-End]
#include "../asmjit_apiend.h"
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Guard]
#ifndef _ASMJIT_BASE_ARCH_H
#define _ASMJIT_BASE_ARCH_H
// [Dependencies]
#include "../base/globals.h"
#include "../base/operand.h"
// [Api-Begin]
#include "../asmjit_apibegin.h"
namespace asmjit {
//! \addtogroup asmjit_base
//! \{
// ============================================================================
// [asmjit::ArchInfo]
// ============================================================================
class ArchInfo {
public:
//! Architecture type.
ASMJIT_ENUM(Type) {
kTypeNone = 0, //!< No/Unknown architecture.
// X86 architectures.
kTypeX86 = 1, //!< X86 architecture (32-bit).
kTypeX64 = 2, //!< X64 architecture (64-bit) (AMD64).
kTypeX32 = 3, //!< X32 architecture (DEAD-END).
// ARM architectures.
kTypeA32 = 4, //!< ARM 32-bit architecture (AArch32/ARM/THUMB).
kTypeA64 = 5, //!< ARM 64-bit architecture (AArch64).
//! Architecture detected at compile-time (architecture of the host).
kTypeHost = ASMJIT_ARCH_X86 ? kTypeX86 :
ASMJIT_ARCH_X64 ? kTypeX64 :
ASMJIT_ARCH_ARM32 ? kTypeA32 :
ASMJIT_ARCH_ARM64 ? kTypeA64 : kTypeNone
};
//! Architecture sub-type or execution mode.
ASMJIT_ENUM(SubType) {
kSubTypeNone = 0, //!< Default mode (or no specific mode).
// X86 sub-types.
kSubTypeX86_AVX = 1, //!< Code generation uses AVX by default (VEC instructions).
kSubTypeX86_AVX2 = 2, //!< Code generation uses AVX2 by default (VEC instructions).
kSubTypeX86_AVX512 = 3, //!< Code generation uses AVX-512F by default (+32 vector regs).
kSubTypeX86_AVX512VL = 4, //!< Code generation uses AVX-512F-VL by default (+VL extensions).
// ARM sub-types.
kSubTypeA32_Thumb = 8, //!< THUMB|THUMB2 sub-type (only ARM in 32-bit mode).
#if (ASMJIT_ARCH_X86 || ASMJIT_ARCH_X64) && defined(__AVX512VL__)
kSubTypeHost = kSubTypeX86_AVX512VL
#elif (ASMJIT_ARCH_X86 || ASMJIT_ARCH_X64) && defined(__AVX512F__)
kSubTypeHost = kSubTypeX86_AVX512
#elif (ASMJIT_ARCH_X86 || ASMJIT_ARCH_X64) && defined(__AVX2__)
kSubTypeHost = kSubTypeX86_AVX2
#elif (ASMJIT_ARCH_X86 || ASMJIT_ARCH_X64) && defined(__AVX__)
kSubTypeHost = kSubTypeX86_AVX
#elif (ASMJIT_ARCH_ARM32) && (defined(_M_ARMT) || defined(__thumb__) || defined(__thumb2__))
kSubTypeHost = kSubTypeA32_Thumb
#else
kSubTypeHost = 0
#endif
};
// --------------------------------------------------------------------------
// [Utilities]
// --------------------------------------------------------------------------
static ASMJIT_INLINE bool isX86Family(uint32_t archType) noexcept { return archType >= kTypeX86 && archType <= kTypeX32; }
static ASMJIT_INLINE bool isArmFamily(uint32_t archType) noexcept { return archType >= kTypeA32 && archType <= kTypeA64; }
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
ASMJIT_INLINE ArchInfo() noexcept : _signature(0) {}
ASMJIT_INLINE ArchInfo(const ArchInfo& other) noexcept = default;
explicit ASMJIT_INLINE ArchInfo(uint32_t type, uint32_t subType = kSubTypeNone) noexcept { init(type, subType); }
ASMJIT_INLINE static ArchInfo host() noexcept { return ArchInfo(kTypeHost, kSubTypeHost); }
// --------------------------------------------------------------------------
// [Init / Reset]
// --------------------------------------------------------------------------
ASMJIT_INLINE bool isInitialized() const noexcept { return _type != kTypeNone; }
ASMJIT_API void init(uint32_t type, uint32_t subType = kSubTypeNone) noexcept;
ASMJIT_INLINE void reset() noexcept { _signature = 0; }
// --------------------------------------------------------------------------
// [Accessors]
// --------------------------------------------------------------------------
//! Get if the architecture is 32-bit.
ASMJIT_INLINE bool is32Bit() const noexcept { return _gpSize == 4; }
//! Get if the architecture is 64-bit.
ASMJIT_INLINE bool is64Bit() const noexcept { return _gpSize == 8; }
//! Get architecture type, see \ref Type.
ASMJIT_INLINE uint32_t getType() const noexcept { return _type; }
//! Get architecture sub-type, see \ref SubType.
//!
//! X86 & X64
//! ---------
//!
//! Architecture subtype describe the highest instruction-set level that can
//! be used.
//!
//! ARM32
//! -----
//!
//! Architecture mode means the instruction encoding to be used when generating
//! machine code, thus mode can be used to force generation of THUMB and THUMB2
//! encoding or regular ARM encoding.
//!
//! ARM64
//! -----
//!
//! No meaning yet.
ASMJIT_INLINE uint32_t getSubType() const noexcept { return _subType; }
//! Get if the architecture is X86, X64, or X32.
ASMJIT_INLINE bool isX86Family() const noexcept { return isX86Family(_type); }
//! Get if the architecture is ARM32 or ARM64.
ASMJIT_INLINE bool isArmFamily() const noexcept { return isArmFamily(_type); }
//! Get a size of a general-purpose register.
ASMJIT_INLINE uint32_t getGpSize() const noexcept { return _gpSize; }
//! Get number of general-purpose registers.
ASMJIT_INLINE uint32_t getGpCount() const noexcept { return _gpCount; }
// --------------------------------------------------------------------------
// [Operator Overload]
// --------------------------------------------------------------------------
ASMJIT_INLINE ArchInfo& operator=(const ArchInfo& other) noexcept = default;
ASMJIT_INLINE bool operator==(const ArchInfo& other) const noexcept { return _signature == other._signature; }
ASMJIT_INLINE bool operator!=(const ArchInfo& other) const noexcept { return _signature != other._signature; }
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
union {
struct {
uint8_t _type; //!< Architecture type.
uint8_t _subType; //!< Architecture sub-type.
uint8_t _gpSize; //!< Default size of a general purpose register.
uint8_t _gpCount; //!< Count of all general purpose registers.
};
uint32_t _signature; //!< Architecture signature (32-bit int).
};
};
// ============================================================================
// [asmjit::ArchRegs]
// ============================================================================
//! Information about all architecture registers.
struct ArchRegs {
//! Register information and signatures indexed by \ref Reg::Type.
RegInfo regInfo[Reg::kRegMax + 1];
//! Count (maximum) of registers per \ref Reg::Type.
uint8_t regCount[Reg::kRegMax + 1];
//! Converts RegType to TypeId, see \ref TypeId::Id.
uint8_t regTypeToTypeId[Reg::kRegMax + 1];
};
// ============================================================================
// [asmjit::ArchUtils]
// ============================================================================
struct ArchUtils {
ASMJIT_API static Error typeIdToRegInfo(uint32_t archType, uint32_t& typeIdInOut, RegInfo& regInfo) noexcept;
};
//! \}
} // asmjit namespace
// [Api-End]
#include "../asmjit_apiend.h"
// [Guard]
#endif // _ASMJIT_BASE_ARCH_H
This diff is collapsed.
This diff is collapsed.
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Export]
#define ASMJIT_EXPORTS
// [Guard]
#include "../asmjit_build.h"
#if !defined(ASMJIT_DISABLE_BUILDER)
// [Dependencies]
#include "../base/codebuilder.h"
// [Api-Begin]
#include "../asmjit_apibegin.h"
namespace asmjit {
// ============================================================================
// [asmjit::CodeBuilder - Construction / Destruction]
// ============================================================================
CodeBuilder::CodeBuilder() noexcept
: CodeEmitter(kTypeBuilder),
_cbBaseZone(32768 - Zone::kZoneOverhead),
_cbDataZone(16384 - Zone::kZoneOverhead),
_cbPassZone(32768 - Zone::kZoneOverhead),
_cbHeap(&_cbBaseZone),
_cbPasses(),
_cbLabels(),
_firstNode(nullptr),
_lastNode(nullptr),
_cursor(nullptr),
_position(0),
_nodeFlags(0) {}
CodeBuilder::~CodeBuilder() noexcept {}
// ============================================================================
// [asmjit::CodeBuilder - Events]
// ============================================================================
Error CodeBuilder::onAttach(CodeHolder* code) noexcept {
return Base::onAttach(code);
}
Error CodeBuilder::onDetach(CodeHolder* code) noexcept {
_cbPasses.reset();
_cbLabels.reset();
_cbHeap.reset(&_cbBaseZone);
_cbBaseZone.reset(false);
_cbDataZone.reset(false);
_cbPassZone.reset(false);
_position = 0;
_nodeFlags = 0;
_firstNode = nullptr;
_lastNode = nullptr;
_cursor = nullptr;
return Base::onDetach(code);
}
// ============================================================================
// [asmjit::CodeBuilder - Node-Factory]
// ============================================================================
Error CodeBuilder::getCBLabel(CBLabel** pOut, uint32_t id) noexcept {
if (_lastError) return _lastError;
ASMJIT_ASSERT(_code != nullptr);
size_t index = Operand::unpackId(id);
if (ASMJIT_UNLIKELY(index >= _code->getLabelsCount()))
return DebugUtils::errored(kErrorInvalidLabel);
if (index >= _cbLabels.getLength())
ASMJIT_PROPAGATE(_cbLabels.resize(&_cbHeap, index + 1));
CBLabel* node = _cbLabels[index];
if (!node) {
node = newNodeT<CBLabel>(id);
if (ASMJIT_UNLIKELY(!node))
return DebugUtils::errored(kErrorNoHeapMemory);
_cbLabels[index] = node;
}
*pOut = node;
return kErrorOk;
}
Error CodeBuilder::registerLabelNode(CBLabel* node) noexcept {
if (_lastError) return _lastError;
ASMJIT_ASSERT(_code != nullptr);
// Don't call setLastError() from here, we are noexcept and we are called
// by `newLabelNode()` and `newFuncNode()`, which are noexcept as well.
uint32_t id;
ASMJIT_PROPAGATE(_code->newLabelId(id));
size_t index = Operand::unpackId(id);
// We just added one label so it must be true.
ASMJIT_ASSERT(_cbLabels.getLength() < index + 1);
ASMJIT_PROPAGATE(_cbLabels.resize(&_cbHeap, index + 1));
_cbLabels[index] = node;
node->_id = id;
return kErrorOk;
}
CBLabel* CodeBuilder::newLabelNode() noexcept {
CBLabel* node = newNodeT<CBLabel>();
if (!node || registerLabelNode(node) != kErrorOk)
return nullptr;
return node;
}
CBAlign* CodeBuilder::newAlignNode(uint32_t mode, uint32_t alignment) noexcept {
return newNodeT<CBAlign>(mode, alignment);
}
CBData* CodeBuilder::newDataNode(const void* data, uint32_t size) noexcept {
if (size > CBData::kInlineBufferSize) {
void* cloned = _cbDataZone.alloc(size);
if (!cloned) return nullptr;
if (data) ::memcpy(cloned, data, size);
data = cloned;
}
return newNodeT<CBData>(const_cast<void*>(data), size);
}
CBConstPool* CodeBuilder::newConstPool() noexcept {
CBConstPool* node = newNodeT<CBConstPool>();
if (!node || registerLabelNode(node) != kErrorOk)
return nullptr;
return node;
}
CBComment* CodeBuilder::newCommentNode(const char* s, size_t len) noexcept {
if (s) {
if (len == Globals::kInvalidIndex) len = ::strlen(s);
if (len > 0) {
s = static_cast<char*>(_cbDataZone.dup(s, len, true));
if (!s) return nullptr;
}
}
return newNodeT<CBComment>(s);
}
// ============================================================================
// [asmjit::CodeBuilder - Code-Emitter]
// ============================================================================
Label CodeBuilder::newLabel() {
uint32_t id = kInvalidValue;
if (!_lastError) {
CBLabel* node = newNodeT<CBLabel>(id);
if (ASMJIT_UNLIKELY(!node)) {
setLastError(DebugUtils::errored(kErrorNoHeapMemory));
}
else {
Error err = registerLabelNode(node);
if (ASMJIT_UNLIKELY(err))
setLastError(err);
else
id = node->getId();
}
}
return Label(id);
}
Label CodeBuilder::newNamedLabel(const char* name, size_t nameLength, uint32_t type, uint32_t parentId) {
uint32_t id = kInvalidValue;
if (!_lastError) {
CBLabel* node = newNodeT<CBLabel>(id);
if (ASMJIT_UNLIKELY(!node)) {
setLastError(DebugUtils::errored(kErrorNoHeapMemory));
}
else {
Error err = _code->newNamedLabelId(id, name, nameLength, type, parentId);
if (ASMJIT_UNLIKELY(err))
setLastError(err);
else
id = node->getId();
}
}
return Label(id);
}
Error CodeBuilder::bind(const Label& label) {
if (_lastError) return _lastError;
CBLabel* node;
Error err = getCBLabel(&node, label);
if (ASMJIT_UNLIKELY(err))
return setLastError(err);
addNode(node);
return kErrorOk;
}
Error CodeBuilder::align(uint32_t mode, uint32_t alignment) {
if (_lastError) return _lastError;
CBAlign* node = newAlignNode(mode, alignment);
if (ASMJIT_UNLIKELY(!node))
return setLastError(DebugUtils::errored(kErrorNoHeapMemory));
addNode(node);
return kErrorOk;
}
Error CodeBuilder::embed(const void* data, uint32_t size) {
if (_lastError) return _lastError;
CBData* node = newDataNode(data, size);
if (ASMJIT_UNLIKELY(!node))
return setLastError(DebugUtils::errored(kErrorNoHeapMemory));
addNode(node);
return kErrorOk;
}
Error CodeBuilder::embedLabel(const Label& label) {
if (_lastError) return _lastError;
CBLabelData* node = newNodeT<CBLabelData>(label.getId());
if (ASMJIT_UNLIKELY(!node))
return setLastError(DebugUtils::errored(kErrorNoHeapMemory));
addNode(node);
return kErrorOk;
}
Error CodeBuilder::embedConstPool(const Label& label, const ConstPool& pool) {
if (_lastError) return _lastError;
if (!isLabelValid(label))
return setLastError(DebugUtils::errored(kErrorInvalidLabel));
ASMJIT_PROPAGATE(align(kAlignData, static_cast<uint32_t>(pool.getAlignment())));
ASMJIT_PROPAGATE(bind(label));
CBData* node = newDataNode(nullptr, static_cast<uint32_t>(pool.getSize()));
if (ASMJIT_UNLIKELY(!node))
return setLastError(DebugUtils::errored(kErrorNoHeapMemory));
pool.fill(node->getData());
addNode(node);
return kErrorOk;
}
Error CodeBuilder::comment(const char* s, size_t len) {
if (_lastError) return _lastError;
CBComment* node = newCommentNode(s, len);
if (ASMJIT_UNLIKELY(!node))
return setLastError(DebugUtils::errored(kErrorNoHeapMemory));
addNode(node);
return kErrorOk;
}
// ============================================================================
// [asmjit::CodeBuilder - Node-Management]
// ============================================================================
CBNode* CodeBuilder::addNode(CBNode* node) noexcept {
ASMJIT_ASSERT(node);
ASMJIT_ASSERT(node->_prev == nullptr);
ASMJIT_ASSERT(node->_next == nullptr);
if (!_cursor) {
if (!_firstNode) {
_firstNode = node;
_lastNode = node;
}
else {
node->_next = _firstNode;
_firstNode->_prev = node;
_firstNode = node;
}
}
else {
CBNode* prev = _cursor;
CBNode* next = _cursor->_next;
node->_prev = prev;
node->_next = next;
prev->_next = node;
if (next)
next->_prev = node;
else
_lastNode = node;
}
_cursor = node;
return node;
}
CBNode* CodeBuilder::addAfter(CBNode* node, CBNode* ref) noexcept {
ASMJIT_ASSERT(node);
ASMJIT_ASSERT(ref);
ASMJIT_ASSERT(node->_prev == nullptr);
ASMJIT_ASSERT(node->_next == nullptr);
CBNode* prev = ref;
CBNode* next = ref->_next;
node->_prev = prev;
node->_next = next;
prev->_next = node;
if (next)
next->_prev = node;
else
_lastNode = node;
return node;
}
CBNode* CodeBuilder::addBefore(CBNode* node, CBNode* ref) noexcept {
ASMJIT_ASSERT(node != nullptr);
ASMJIT_ASSERT(node->_prev == nullptr);
ASMJIT_ASSERT(node->_next == nullptr);
ASMJIT_ASSERT(ref != nullptr);
CBNode* prev = ref->_prev;
CBNode* next = ref;
node->_prev = prev;
node->_next = next;
next->_prev = node;
if (prev)
prev->_next = node;
else
_firstNode = node;
return node;
}
static ASMJIT_INLINE void CodeBuilder_nodeRemoved(CodeBuilder* self, CBNode* node_) noexcept {
if (node_->isJmpOrJcc()) {
CBJump* node = static_cast<CBJump*>(node_);
CBLabel* label = node->getTarget();
if (label) {
// Disconnect.
CBJump** pPrev = &label->_from;
for (;;) {
ASMJIT_ASSERT(*pPrev != nullptr);
CBJump* current = *pPrev;
if (!current) break;
if (current == node) {
*pPrev = node->_jumpNext;
break;
}
pPrev = &current->_jumpNext;
}
label->subNumRefs();
}
}
}
CBNode* CodeBuilder::removeNode(CBNode* node) noexcept {
CBNode* prev = node->_prev;
CBNode* next = node->_next;
if (_firstNode == node)
_firstNode = next;
else
prev->_next = next;
if (_lastNode == node)
_lastNode = prev;
else
next->_prev = prev;
node->_prev = nullptr;
node->_next = nullptr;
if (_cursor == node)
_cursor = prev;
CodeBuilder_nodeRemoved(this, node);
return node;
}
void CodeBuilder::removeNodes(CBNode* first, CBNode* last) noexcept {
if (first == last) {
removeNode(first);
return;
}
CBNode* prev = first->_prev;
CBNode* next = last->_next;
if (_firstNode == first)
_firstNode = next;
else
prev->_next = next;
if (_lastNode == last)
_lastNode = prev;
else
next->_prev = prev;
CBNode* node = first;
for (;;) {
CBNode* next = node->getNext();
ASMJIT_ASSERT(next != nullptr);
node->_prev = nullptr;
node->_next = nullptr;
if (_cursor == node)
_cursor = prev;
CodeBuilder_nodeRemoved(this, node);
if (node == last)
break;
node = next;
}
}
CBNode* CodeBuilder::setCursor(CBNode* node) noexcept {
CBNode* old = _cursor;
_cursor = node;
return old;
}
// ============================================================================
// [asmjit::CodeBuilder - Passes]
// ============================================================================
ASMJIT_FAVOR_SIZE CBPass* CodeBuilder::getPassByName(const char* name) const noexcept {
for (size_t i = 0, len = _cbPasses.getLength(); i < len; i++) {
CBPass* pass = _cbPasses[i];
if (::strcmp(pass->getName(), name) == 0)
return pass;
}
return nullptr;
}
ASMJIT_FAVOR_SIZE Error CodeBuilder::addPass(CBPass* pass) noexcept {
if (ASMJIT_UNLIKELY(pass == nullptr)) {
// Since this is directly called by `addPassT()` we treat `null` argument
// as out-of-memory condition. Otherwise it would be API misuse.
return DebugUtils::errored(kErrorNoHeapMemory);
}
else if (ASMJIT_UNLIKELY(pass->_cb)) {
// Kind of weird, but okay...
if (pass->_cb == this)
return kErrorOk;
return DebugUtils::errored(kErrorInvalidState);
}
ASMJIT_PROPAGATE(_cbPasses.append(&_cbHeap, pass));
pass->_cb = this;
return kErrorOk;
}
ASMJIT_FAVOR_SIZE Error CodeBuilder::deletePass(CBPass* pass) noexcept {
if (ASMJIT_UNLIKELY(pass == nullptr))
return DebugUtils::errored(kErrorInvalidArgument);
if (pass->_cb != nullptr) {
if (pass->_cb != this)
return DebugUtils::errored(kErrorInvalidState);
size_t index = _cbPasses.indexOf(pass);
ASMJIT_ASSERT(index != Globals::kInvalidIndex);
pass->_cb = nullptr;
_cbPasses.removeAt(index);
}
pass->~CBPass();
return kErrorOk;
}
// ============================================================================
// [asmjit::CodeBuilder - Serialization]
// ============================================================================
Error CodeBuilder::serialize(CodeEmitter* dst) {
Error err = kErrorOk;
CBNode* node_ = getFirstNode();
do {
dst->setInlineComment(node_->getInlineComment());
switch (node_->getType()) {
case CBNode::kNodeAlign: {
CBAlign* node = static_cast<CBAlign*>(node_);
err = dst->align(node->getMode(), node->getAlignment());
break;
}
case CBNode::kNodeData: {
CBData* node = static_cast<CBData*>(node_);
err = dst->embed(node->getData(), node->getSize());
break;
}
case CBNode::kNodeFunc:
case CBNode::kNodeLabel: {
CBLabel* node = static_cast<CBLabel*>(node_);
err = dst->bind(node->getLabel());
break;
}
case CBNode::kNodeLabelData: {
CBLabelData* node = static_cast<CBLabelData*>(node_);
err = dst->embedLabel(node->getLabel());
break;
}
case CBNode::kNodeConstPool: {
CBConstPool* node = static_cast<CBConstPool*>(node_);
err = dst->embedConstPool(node->getLabel(), node->getConstPool());
break;
}
case CBNode::kNodeInst:
case CBNode::kNodeFuncCall: {
CBInst* node = node_->as<CBInst>();
dst->setOptions(node->getOptions());
dst->setExtraReg(node->getExtraReg());
err = dst->emitOpArray(node->getInstId(), node->getOpArray(), node->getOpCount());
break;
}
case CBNode::kNodeComment: {
CBComment* node = static_cast<CBComment*>(node_);
err = dst->comment(node->getInlineComment());
break;
}
default:
break;
}
if (err) break;
node_ = node_->getNext();
} while (node_);
return err;
}
// ============================================================================
// [asmjit::CBPass]
// ============================================================================
CBPass::CBPass(const char* name) noexcept
: _cb(nullptr),
_name(name) {}
CBPass::~CBPass() noexcept {}
} // asmjit namespace
// [Api-End]
#include "../asmjit_apiend.h"
// [Guard]
#endif // !ASMJIT_DISABLE_BUILDER
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Export]
#define ASMJIT_EXPORTS
// [Dependencies - AsmJit]
#include "../base/codegen.h"
#include "../base/intutil.h"
// [Api-Begin]
#include "../apibegin.h"
namespace asmjit {
// ============================================================================
// [asmjit::CodeGen - Construction / Destruction]
// ============================================================================
CodeGen::CodeGen(Runtime* runtime) :
_runtime(runtime),
_logger(NULL),
_errorHandler(NULL),
_baseAddress(runtime->getBaseAddress()),
_arch(kArchNone),
_regSize(0),
_reserved(0),
_features(IntUtil::mask(kCodeGenOptimizedAlign)),
_instOptions(0),
_error(kErrorOk),
_baseZone(16384 - kZoneOverhead) {}
CodeGen::~CodeGen() {
if (_errorHandler != NULL)
_errorHandler->release();
}
// ============================================================================
// [asmjit::CodeGen - Logging]
// ============================================================================
#if !defined(ASMJIT_DISABLE_LOGGER)
Error CodeGen::setLogger(Logger* logger) {
_logger = logger;
return kErrorOk;
}
#endif // !ASMJIT_DISABLE_LOGGER
// ============================================================================
// [asmjit::CodeGen - Error]
// ============================================================================
Error CodeGen::setError(Error error, const char* message) {
if (error == kErrorOk) {
_error = kErrorOk;
return kErrorOk;
}
if (message == NULL) {
#if !defined(ASMJIT_DISABLE_NAMES)
message = ErrorUtil::asString(error);
#else
static const char noMessage[] = "";
message = noMessage;
#endif // ASMJIT_DISABLE_NAMES
}
// Error handler is called before logger so logging can be skipped if error
// has been handled.
ErrorHandler* handler = _errorHandler;
ASMJIT_TLOG("[ERROR] %s %s\n", message, !handler ? "(Possibly unhandled?)" : "");
if (handler != NULL && handler->handleError(error, message))
return error;
#if !defined(ASMJIT_DISABLE_LOGGER)
Logger* logger = _logger;
if (logger != NULL) {
logger->logFormat(kLoggerStyleComment,
"*** ERROR: %s (%u).\n", message, static_cast<unsigned int>(error));
}
#endif // !ASMJIT_DISABLE_LOGGER
// The handler->handleError() function may throw an exception or longjmp()
// to terminate the execution of setError(). This is the reason why we have
// delayed changing the _error member until now.
_error = error;
return error;
}
Error CodeGen::setErrorHandler(ErrorHandler* handler) {
ErrorHandler* oldHandler = _errorHandler;
if (oldHandler != NULL)
oldHandler->release();
if (handler != NULL)
handler = handler->addRef();
_errorHandler = handler;
return kErrorOk;
}
} // asmjit namespace
// [Api-End]
#include "../apiend.h"
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment