LCOV - code coverage report
Current view: top level - asmjit - codeholder.h (source / functions) Hit Total Coverage
Test: plumed test coverage (other modules) Lines: 32 41 78.0 %
Date: 2024-10-18 14:00:27 Functions: 0 0 -

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             : Copyright (c) 2008-2017, Petr Kobalicek
       3             : 
       4             : This software is provided 'as-is', without any express or implied
       5             : warranty. In no event will the authors be held liable for any damages
       6             : arising from the use of this software.
       7             : 
       8             : Permission is granted to anyone to use this software for any purpose,
       9             : including commercial applications, and to alter it and redistribute it
      10             : freely, subject to the following restrictions:
      11             : 
      12             : 1. The origin of this software must not be misrepresented; you must not
      13             :    claim that you wrote the original software. If you use this software
      14             :    in a product, an acknowledgment in the product documentation would be
      15             :    appreciated but is not required.
      16             : 2. Altered source versions must be plainly marked as such, and must not be
      17             :    misrepresented as being the original software.
      18             : 3. This notice may not be removed or altered from any source distribution.
      19             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      20             : #ifndef __PLUMED_asmjit_codeholder_h
      21             : #define __PLUMED_asmjit_codeholder_h
      22             : #ifdef __PLUMED_HAS_ASMJIT
      23             : #pragma GCC diagnostic push
      24             : #pragma GCC diagnostic ignored "-Wpedantic"
      25             : // [AsmJit]
      26             : // Complete x86/x64 JIT and Remote Assembler for C++.
      27             : //
      28             : // [License]
      29             : // Zlib - See LICENSE.md file in the package.
      30             : 
      31             : // [Guard]
      32             : #ifndef _ASMJIT_BASE_CODEHOLDER_H
      33             : #define _ASMJIT_BASE_CODEHOLDER_H
      34             : 
      35             : // [Dependencies]
      36             : #include "./arch.h"
      37             : #include "./func.h"
      38             : #include "./logging.h"
      39             : #include "./operand.h"
      40             : #include "./simdtypes.h"
      41             : #include "./utils.h"
      42             : #include "./zone.h"
      43             : 
      44             : // [Api-Begin]
      45             : #include "./asmjit_apibegin.h"
      46             : 
      47             : namespace PLMD {
      48             : namespace asmjit {
      49             : 
      50             : //! \addtogroup asmjit_base
      51             : //! \{
      52             : 
      53             : // ============================================================================
      54             : // [Forward Declarations]
      55             : // ============================================================================
      56             : 
      57             : class Assembler;
      58             : class CodeEmitter;
      59             : class CodeHolder;
      60             : 
      61             : // ============================================================================
      62             : // [asmjit::AlignMode]
      63             : // ============================================================================
      64             : 
      65             : //! Align mode.
      66             : ASMJIT_ENUM(AlignMode) {
      67             :   kAlignCode = 0,                        //!< Align executable code.
      68             :   kAlignData = 1,                        //!< Align non-executable code.
      69             :   kAlignZero = 2,                        //!< Align by a sequence of zeros.
      70             :   kAlignCount                            //!< Count of alignment modes.
      71             : };
      72             : 
      73             : // ============================================================================
      74             : // [asmjit::ErrorHandler]
      75             : // ============================================================================
      76             : 
      77             : //! Error handler can be used to override the default behavior of error handling
      78             : //! available to all classes that inherit \ref CodeEmitter. See \ref handleError().
      79             : class ASMJIT_VIRTAPI ErrorHandler {
      80             : public:
      81             :   // --------------------------------------------------------------------------
      82             :   // [Construction / Destruction]
      83             :   // --------------------------------------------------------------------------
      84             : 
      85             :   //! Create a new `ErrorHandler` instance.
      86             :   ASMJIT_API ErrorHandler() noexcept;
      87             :   //! Destroy the `ErrorHandler` instance.
      88             :   ASMJIT_API virtual ~ErrorHandler() noexcept;
      89             : 
      90             :   // --------------------------------------------------------------------------
      91             :   // [Handle Error]
      92             :   // --------------------------------------------------------------------------
      93             : 
      94             :   //! Error handler (abstract).
      95             :   //!
      96             :   //! Error handler is called after an error happened and before it's propagated
      97             :   //! to the caller. There are multiple ways how the error handler can be used:
      98             :   //!
      99             :   //! 1. Returning `true` or `false` from `handleError()`. If `true` is returned
     100             :   //!    it means that the error was reported and AsmJit can continue execution.
     101             :   //!    The reported error still be propagated to the caller, but won't put the
     102             :   //!    CodeEmitter into an error state (it won't set last-error). However,
     103             :   //!    returning `false` means that the error cannot be handled - in such case
     104             :   //!    it stores the error, which can be then retrieved by using `getLastError()`.
     105             :   //!    Returning `false` is the default behavior when no error handler is present.
     106             :   //!    To put the assembler into a non-error state again a `resetLastError()` must
     107             :   //!    be called.
     108             :   //!
     109             :   //! 2. Throwing an exception. AsmJit doesn't use exceptions and is completely
     110             :   //!    exception-safe, but you can throw exception from your error handler if
     111             :   //!    this way is the preferred way of handling errors in your project. Throwing
     112             :   //!    an exception acts virtually as returning `true` as AsmJit won't be able
     113             :   //!    to store the error because the exception changes execution path.
     114             :   //!
     115             :   //! 3. Using plain old C's `setjmp()` and `longjmp()`. Asmjit always puts
     116             :   //!    `CodeEmitter` to a consistent state before calling the `handleError()`
     117             :   //!    so `longjmp()` can be used without any issues to cancel the code
     118             :   //!    generation if an error occurred. There is no difference between
     119             :   //!    exceptions and longjmp() from AsmJit's perspective.
     120             :   virtual bool handleError(Error err, const char* message, CodeEmitter* origin) = 0;
     121             : };
     122             : 
     123             : // ============================================================================
     124             : // [asmjit::CodeInfo]
     125             : // ============================================================================
     126             : 
     127             : //! Basic information about a code (or target). It describes its architecture,
     128             : //! code generation mode (or optimization level), and base address.
     129             : class CodeInfo {
     130             : public:
     131             :   // --------------------------------------------------------------------------
     132             :   // [Construction / Destruction]
     133             :   // --------------------------------------------------------------------------
     134             : 
     135             :   ASMJIT_INLINE CodeInfo() noexcept
     136      128474 :     : _archInfo(),
     137      128474 :       _stackAlignment(0),
     138      128474 :       _cdeclCallConv(CallConv::kIdNone),
     139      128474 :       _stdCallConv(CallConv::kIdNone),
     140      128474 :       _fastCallConv(CallConv::kIdNone),
     141      128474 :       _baseAddress(Globals::kNoBaseAddress) {}
     142             :   ASMJIT_INLINE CodeInfo(const CodeInfo& other) noexcept { init(other); }
     143             : 
     144             :   explicit ASMJIT_INLINE CodeInfo(uint32_t archType, uint32_t archMode = 0, uint64_t baseAddress = Globals::kNoBaseAddress) noexcept
     145             :     : _archInfo(archType, archMode),
     146             :       _packedMiscInfo(0),
     147             :       _baseAddress(baseAddress) {}
     148             : 
     149             :   // --------------------------------------------------------------------------
     150             :   // [Init / Reset]
     151             :   // --------------------------------------------------------------------------
     152             : 
     153             :   ASMJIT_INLINE bool isInitialized() const noexcept {
     154       32111 :     return _archInfo._type != ArchInfo::kTypeNone;
     155             :   }
     156             : 
     157             :   ASMJIT_INLINE void init(const CodeInfo& other) noexcept {
     158       96333 :     _archInfo = other._archInfo;
     159       96333 :     _packedMiscInfo = other._packedMiscInfo;
     160       96333 :     _baseAddress = other._baseAddress;
     161             :   }
     162             : 
     163             :   ASMJIT_INLINE void init(uint32_t archType, uint32_t archMode = 0, uint64_t baseAddress = Globals::kNoBaseAddress) noexcept {
     164             :     _archInfo.init(archType, archMode);
     165             :     _packedMiscInfo = 0;
     166             :     _baseAddress = baseAddress;
     167             :   }
     168             : 
     169             :   ASMJIT_INLINE void reset() noexcept {
     170             :     _archInfo.reset();
     171       32111 :     _stackAlignment = 0;
     172       32111 :     _cdeclCallConv = CallConv::kIdNone;
     173       32111 :     _stdCallConv = CallConv::kIdNone;
     174       32111 :     _fastCallConv = CallConv::kIdNone;
     175       32111 :     _baseAddress = Globals::kNoBaseAddress;
     176             :   }
     177             : 
     178             :   // --------------------------------------------------------------------------
     179             :   // [Architecture Information]
     180             :   // --------------------------------------------------------------------------
     181             : 
     182             :   //! Get architecture information, see \ref ArchInfo.
     183             :   ASMJIT_INLINE const ArchInfo& getArchInfo() const noexcept { return _archInfo; }
     184             : 
     185             :   //! Get architecture type, see \ref ArchInfo::Type.
     186             :   ASMJIT_INLINE uint32_t getArchType() const noexcept { return _archInfo.getType(); }
     187             :   //! Get architecture sub-type, see \ref ArchInfo::SubType.
     188             :   ASMJIT_INLINE uint32_t getArchSubType() const noexcept { return _archInfo.getSubType(); }
     189             :   //! Get a size of a GP register of the architecture the code is using.
     190             :   ASMJIT_INLINE uint32_t getGpSize() const noexcept { return _archInfo.getGpSize(); }
     191             :   //! Get number of GP registers available of the architecture the code is using.
     192             :   ASMJIT_INLINE uint32_t getGpCount() const noexcept { return _archInfo.getGpCount(); }
     193             : 
     194             :   // --------------------------------------------------------------------------
     195             :   // [High-Level Information]
     196             :   // --------------------------------------------------------------------------
     197             : 
     198             :   //! Get a natural stack alignment that must be honored (or 0 if not known).
     199       32111 :   ASMJIT_INLINE uint32_t getStackAlignment() const noexcept { return _stackAlignment; }
     200             :   //! Set a natural stack alignment that must be honored.
     201             :   ASMJIT_INLINE void setStackAlignment(uint8_t sa) noexcept { _stackAlignment = static_cast<uint8_t>(sa); }
     202             : 
     203             :   ASMJIT_INLINE uint32_t getCdeclCallConv() const noexcept { return _cdeclCallConv; }
     204             :   ASMJIT_INLINE void setCdeclCallConv(uint32_t cc) noexcept { _cdeclCallConv = static_cast<uint8_t>(cc); }
     205             : 
     206             :   ASMJIT_INLINE uint32_t getStdCallConv() const noexcept { return _stdCallConv; }
     207             :   ASMJIT_INLINE void setStdCallConv(uint32_t cc) noexcept { _stdCallConv = static_cast<uint8_t>(cc); }
     208             : 
     209             :   ASMJIT_INLINE uint32_t getFastCallConv() const noexcept { return _fastCallConv; }
     210             :   ASMJIT_INLINE void setFastCallConv(uint32_t cc) noexcept { _fastCallConv = static_cast<uint8_t>(cc); }
     211             : 
     212             :   // --------------------------------------------------------------------------
     213             :   // [Addressing Information]
     214             :   // --------------------------------------------------------------------------
     215             : 
     216             :   ASMJIT_INLINE bool hasBaseAddress() const noexcept { return _baseAddress != Globals::kNoBaseAddress; }
     217           0 :   ASMJIT_INLINE uint64_t getBaseAddress() const noexcept { return _baseAddress; }
     218             :   ASMJIT_INLINE void setBaseAddress(uint64_t p) noexcept { _baseAddress = p; }
     219             :   ASMJIT_INLINE void resetBaseAddress() noexcept { _baseAddress = Globals::kNoBaseAddress; }
     220             : 
     221             :   // --------------------------------------------------------------------------
     222             :   // [Operator Overload]
     223             :   // --------------------------------------------------------------------------
     224             : 
     225             :   ASMJIT_INLINE CodeInfo& operator=(const CodeInfo& other) noexcept { init(other); return *this; }
     226             :   ASMJIT_INLINE bool operator==(const CodeInfo& other) const noexcept { return ::memcmp(this, &other, sizeof(*this)) == 0; }
     227             :   ASMJIT_INLINE bool operator!=(const CodeInfo& other) const noexcept { return ::memcmp(this, &other, sizeof(*this)) != 0; }
     228             : 
     229             :   // --------------------------------------------------------------------------
     230             :   // [Members]
     231             :   // --------------------------------------------------------------------------
     232             : 
     233             :   ArchInfo _archInfo;                    //!< Architecture information.
     234             : 
     235             :   union {
     236             :     struct {
     237             :       uint8_t _stackAlignment;           //!< Natural stack alignment (ARCH+OS).
     238             :       uint8_t _cdeclCallConv;            //!< Default CDECL calling convention.
     239             :       uint8_t _stdCallConv;              //!< Default STDCALL calling convention.
     240             :       uint8_t _fastCallConv;             //!< Default FASTCALL calling convention.
     241             :     };
     242             :     uint32_t _packedMiscInfo;            //!< \internal
     243             :   };
     244             : 
     245             :   uint64_t _baseAddress;                 //!< Base address.
     246             : };
     247             : 
     248             : // ============================================================================
     249             : // [asmjit::CodeBuffer]
     250             : // ============================================================================
     251             : 
     252             : //! Code or data buffer.
     253             : struct CodeBuffer {
     254             :   // --------------------------------------------------------------------------
     255             :   // [Accessors]
     256             :   // --------------------------------------------------------------------------
     257             : 
     258       32111 :   ASMJIT_INLINE bool hasData() const noexcept { return _data != nullptr; }
     259             :   ASMJIT_INLINE uint8_t* getData() noexcept { return _data; }
     260             :   ASMJIT_INLINE const uint8_t* getData() const noexcept { return _data; }
     261             : 
     262       96333 :   ASMJIT_INLINE size_t getLength() const noexcept { return _length; }
     263       32111 :   ASMJIT_INLINE size_t getCapacity() const noexcept { return _capacity; }
     264             : 
     265       32111 :   ASMJIT_INLINE bool isExternal() const noexcept { return _isExternal; }
     266       32111 :   ASMJIT_INLINE bool isFixedSize() const noexcept { return _isFixedSize; }
     267             : 
     268             :   // --------------------------------------------------------------------------
     269             :   // [Members]
     270             :   // --------------------------------------------------------------------------
     271             : 
     272             :   uint8_t* _data;                        //!< The content of the buffer (data).
     273             :   size_t _length;                        //!< Number of bytes of `data` used.
     274             :   size_t _capacity;                      //!< Buffer capacity (in bytes).
     275             :   bool _isExternal;                      //!< True if this is external buffer.
     276             :   bool _isFixedSize;                     //!< True if this buffer cannot grow.
     277             : };
     278             : 
     279             : // ============================================================================
     280             : // [asmjit::SectionEntry]
     281             : // ============================================================================
     282             : 
     283             : //! Section entry.
     284             : class SectionEntry {
     285             : public:
     286             :   ASMJIT_ENUM(Id) {
     287             :     kInvalidId       = 0xFFFFFFFFU       //!< Invalid section id.
     288             :   };
     289             : 
     290             :   //! Section flags.
     291             :   ASMJIT_ENUM(Flags) {
     292             :     kFlagExec        = 0x00000001U,      //!< Executable (.text sections).
     293             :     kFlagConst       = 0x00000002U,      //!< Read-only (.text and .data sections).
     294             :     kFlagZero        = 0x00000004U,      //!< Zero initialized by the loader (BSS).
     295             :     kFlagInfo        = 0x00000008U,      //!< Info / comment flag.
     296             :     kFlagImplicit    = 0x80000000U       //!< Section created implicitly (can be deleted by the Runtime).
     297             :   };
     298             : 
     299             :   // --------------------------------------------------------------------------
     300             :   // [Accessors]
     301             :   // --------------------------------------------------------------------------
     302             : 
     303       64222 :   ASMJIT_INLINE uint32_t getId() const noexcept { return _id; }
     304             :   ASMJIT_INLINE const char* getName() const noexcept { return _name; }
     305             : 
     306             :   ASMJIT_INLINE void _setDefaultName(
     307             :       char c0 = 0, char c1 = 0, char c2 = 0, char c3 = 0,
     308             :       char c4 = 0, char c5 = 0, char c6 = 0, char c7 = 0) noexcept {
     309       32111 :     _nameAsU32[0] = Utils::pack32_4x8(c0, c1, c2, c3);
     310       32111 :     _nameAsU32[1] = Utils::pack32_4x8(c4, c5, c6, c7);
     311             :   }
     312             : 
     313             :   ASMJIT_INLINE uint32_t getFlags() const noexcept { return _flags; }
     314             :   ASMJIT_INLINE bool hasFlag(uint32_t flag) const noexcept { return (_flags & flag) != 0; }
     315             :   ASMJIT_INLINE void addFlags(uint32_t flags) noexcept { _flags |= flags; }
     316             :   ASMJIT_INLINE void clearFlags(uint32_t flags) noexcept { _flags &= ~flags; }
     317             : 
     318             :   ASMJIT_INLINE uint32_t getAlignment() const noexcept { return _alignment; }
     319             :   ASMJIT_INLINE void setAlignment(uint32_t alignment) noexcept { _alignment = alignment; }
     320             : 
     321             :   ASMJIT_INLINE size_t getPhysicalSize() const noexcept { return _buffer.getLength(); }
     322             : 
     323             :   ASMJIT_INLINE size_t getVirtualSize() const noexcept { return _virtualSize; }
     324             :   ASMJIT_INLINE void setVirtualSize(uint32_t size) noexcept { _virtualSize = size; }
     325             : 
     326             :   ASMJIT_INLINE CodeBuffer& getBuffer() noexcept { return _buffer; }
     327             :   ASMJIT_INLINE const CodeBuffer& getBuffer() const noexcept { return _buffer; }
     328             : 
     329             :   // --------------------------------------------------------------------------
     330             :   // [Members]
     331             :   // --------------------------------------------------------------------------
     332             : 
     333             :   uint32_t _id;                          //!< Section id.
     334             :   uint32_t _flags;                       //!< Section flags.
     335             :   uint32_t _alignment;                   //!< Section alignment requirements (0 if no requirements).
     336             :   uint32_t _virtualSize;                 //!< Virtual size of the section (zero initialized mostly).
     337             :   union {
     338             :     char _name[36];                      //!< Section name (max 35 characters, PE allows max 8).
     339             :     uint32_t _nameAsU32[36 / 4];         //!< Section name as `uint32_t[]` (only optimization).
     340             :   };
     341             :   CodeBuffer _buffer;                    //!< Code or data buffer.
     342             : };
     343             : 
     344             : // ============================================================================
     345             : // [asmjit::LabelLink]
     346             : // ============================================================================
     347             : 
     348             : //! Data structure used to link labels.
     349             : struct LabelLink {
     350             :   LabelLink* prev;                       //!< Previous link (single-linked list).
     351             :   uint32_t sectionId;                    //!< Section id.
     352             :   uint32_t relocId;                      //!< Relocation id or RelocEntry::kInvalidId.
     353             :   size_t offset;                         //!< Label offset relative to the start of the section.
     354             :   intptr_t rel;                          //!< Inlined rel8/rel32.
     355             : };
     356             : 
     357             : // ============================================================================
     358             : // [asmjit::LabelEntry]
     359             : // ============================================================================
     360             : 
     361             : //! Label entry.
     362             : //!
     363             : //! Contains the following properties:
     364             : //!   * Label id - This is the only thing that is set to the `Label` operand.
     365             : //!   * Label name - Optional, used mostly to create executables and libraries.
     366             : //!   * Label type - Type of the label, default `Label::kTypeAnonymous`.
     367             : //!   * Label parent id - Derived from many assemblers that allow to define a
     368             : //!       local label that falls under a global label. This allows to define
     369             : //!       many labels of the same name that have different parent (global) label.
     370             : //!   * Offset - offset of the label bound by `Assembler`.
     371             : //!   * Links - single-linked list that contains locations of code that has
     372             : //!       to be patched when the label gets bound. Every use of unbound label
     373             : //!       adds one link to `_links` list.
     374             : //!   * HVal - Hash value of label's name and optionally parentId.
     375             : //!   * HashNext - Hash-table implementation detail.
     376             : class LabelEntry : public ZoneHashNode {
     377             : public:
     378             :   // NOTE: Label id is stored in `_customData`, which is provided by ZoneHashNode
     379             :   // to fill a padding that a C++ compiler targeting 64-bit CPU will add to align
     380             :   // the structure to 64-bits.
     381             : 
     382             :   //! Get label id.
     383           0 :   ASMJIT_INLINE uint32_t getId() const noexcept { return _customData; }
     384             :   //! Set label id (internal, used only by \ref CodeHolder).
     385       64222 :   ASMJIT_INLINE void _setId(uint32_t id) noexcept { _customData = id; }
     386             : 
     387             :   //! Get label type, see \ref Label::Type.
     388             :   ASMJIT_INLINE uint32_t getType() const noexcept { return _type; }
     389             :   //! Get label flags, returns 0 at the moment.
     390             :   ASMJIT_INLINE uint32_t getFlags() const noexcept { return _flags; }
     391             : 
     392           0 :   ASMJIT_INLINE bool hasParent() const noexcept { return _parentId != 0; }
     393             :   //! Get label's parent id.
     394             :   ASMJIT_INLINE uint32_t getParentId() const noexcept { return _parentId; }
     395             : 
     396             :   //! Get label's section id where it's bound to (or `SectionEntry::kInvalidId` if it's not bound yet).
     397             :   ASMJIT_INLINE uint32_t getSectionId() const noexcept { return _sectionId; }
     398             : 
     399             :   //! Get if the label has name.
     400             :   ASMJIT_INLINE bool hasName() const noexcept { return !_name.isEmpty(); }
     401             : 
     402             :   //! Get the label's name.
     403             :   //!
     404             :   //! NOTE: Local labels will return their local name without their parent
     405             :   //! part, for example ".L1".
     406             :   ASMJIT_INLINE const char* getName() const noexcept { return _name.getData(); }
     407             : 
     408             :   //! Get length of label's name.
     409             :   //!
     410             :   //! NOTE: Label name is always null terminated, so you can use `strlen()` to
     411             :   //! get it, however, it's also cached in `LabelEntry`, so if you want to know
     412             :   //! the length the easiest way is to use `LabelEntry::getNameLength()`.
     413             :   ASMJIT_INLINE size_t getNameLength() const noexcept { return _name.getLength(); }
     414             : 
     415             :   //! Get if the label is bound.
     416       64222 :   ASMJIT_INLINE bool isBound() const noexcept { return _sectionId != SectionEntry::kInvalidId; }
     417             :   //! Get the label offset (only useful if the label is bound).
     418           0 :   ASMJIT_INLINE intptr_t getOffset() const noexcept { return _offset; }
     419             : 
     420             :   //! Get the hash-value of label's name and its parent label (if any).
     421             :   //!
     422             :   //! Label hash is calculated as `HASH(Name) ^ ParentId`. The hash function
     423             :   //! is implemented in `Utils::hashString()` and `Utils::hashRound()`.
     424             :   ASMJIT_INLINE uint32_t getHVal() const noexcept { return _hVal; }
     425             : 
     426             :   // ------------------------------------------------------------------------
     427             :   // [Members]
     428             :   // ------------------------------------------------------------------------
     429             : 
     430             :   // Let's round the size of `LabelEntry` to 64 bytes (as ZoneHeap has 32
     431             :   // bytes granularity anyway). This gives `_name` the remaining space, which
     432             :   // is roughly 16 bytes on 64-bit and 28 bytes on 32-bit architectures.
     433             :   enum { kNameBytes = 64 - (sizeof(ZoneHashNode) + 16 + sizeof(intptr_t) + sizeof(LabelLink*)) };
     434             : 
     435             :   uint8_t _type;                         //!< Label type, see Label::Type.
     436             :   uint8_t _flags;                        //!< Must be zero.
     437             :   uint16_t _reserved16;                  //!< Reserved.
     438             :   uint32_t _parentId;                    //!< Label parent id or zero.
     439             :   uint32_t _sectionId;                   //!< Section id or `SectionEntry::kInvalidId`.
     440             :   uint32_t _reserved32;                  //!< Reserved.
     441             :   intptr_t _offset;                      //!< Label offset.
     442             :   LabelLink* _links;                     //!< Label links.
     443             :   SmallString<kNameBytes> _name;         //!< Label name.
     444             : };
     445             : 
     446             : // ============================================================================
     447             : // [asmjit::RelocEntry]
     448             : // ============================================================================
     449             : 
     450             : //! Relocation entry.
     451             : struct RelocEntry {
     452             :   ASMJIT_ENUM(Id) {
     453             :     kInvalidId       = 0xFFFFFFFFU       //!< Invalid relocation id.
     454             :   };
     455             : 
     456             :   //! Relocation type.
     457             :   ASMJIT_ENUM(Type) {
     458             :     kTypeNone        = 0,                //!< Deleted entry (no relocation).
     459             :     kTypeAbsToAbs    = 1,                //!< Relocate absolute to absolute.
     460             :     kTypeRelToAbs    = 2,                //!< Relocate relative to absolute.
     461             :     kTypeAbsToRel    = 3,                //!< Relocate absolute to relative.
     462             :     kTypeTrampoline  = 4                 //!< Relocate absolute to relative or use trampoline.
     463             :   };
     464             : 
     465             :   // ------------------------------------------------------------------------
     466             :   // [Accessors]
     467             :   // ------------------------------------------------------------------------
     468             : 
     469           0 :   ASMJIT_INLINE uint32_t getId() const noexcept { return _id; }
     470             : 
     471           0 :   ASMJIT_INLINE uint32_t getType() const noexcept { return _type; }
     472           0 :   ASMJIT_INLINE uint32_t getSize() const noexcept { return _size; }
     473             : 
     474             :   ASMJIT_INLINE uint32_t getSourceSectionId() const noexcept { return _sourceSectionId; }
     475             :   ASMJIT_INLINE uint32_t getTargetSectionId() const noexcept { return _targetSectionId; }
     476             : 
     477           0 :   ASMJIT_INLINE uint64_t getSourceOffset() const noexcept { return _sourceOffset; }
     478           0 :   ASMJIT_INLINE uint64_t getData() const noexcept { return _data; }
     479             : 
     480             :   // ------------------------------------------------------------------------
     481             :   // [Members]
     482             :   // ------------------------------------------------------------------------
     483             : 
     484             :   uint32_t _id;                          //!< Relocation id.
     485             :   uint8_t _type;                         //!< Type of the relocation.
     486             :   uint8_t _size;                         //!< Size of the relocation (1, 2, 4 or 8 bytes).
     487             :   uint8_t _reserved[2];                  //!< Reserved.
     488             :   uint32_t _sourceSectionId;             //!< Source section id.
     489             :   uint32_t _targetSectionId;             //!< Destination section id.
     490             :   uint64_t _sourceOffset;                //!< Source offset (relative to start of the section).
     491             :   uint64_t _data;                        //!< Relocation data (target offset, target address, etc).
     492             : };
     493             : 
     494             : // ============================================================================
     495             : // [asmjit::CodeHolder]
     496             : // ============================================================================
     497             : 
     498             : //! Contains basic information about the target architecture plus its settings,
     499             : //! and holds code & data (including sections, labels, and relocation information).
     500             : //! CodeHolder can store both binary and intermediate representation of assembly,
     501             : //! which can be generated by \ref Assembler and/or \ref CodeBuilder.
     502             : //!
     503             : //! NOTE: CodeHolder has ability to attach an \ref ErrorHandler, however, this
     504             : //! error handler is not triggered by CodeHolder itself, it's only used by the
     505             : //! attached code generators.
     506             : class CodeHolder {
     507             : public:
     508             :   ASMJIT_NONCOPYABLE(CodeHolder)
     509             : 
     510             :   // --------------------------------------------------------------------------
     511             :   // [Construction / Destruction]
     512             :   // --------------------------------------------------------------------------
     513             : 
     514             :   //! Create an uninitialized CodeHolder (you must init() it before it can be used).
     515             :   ASMJIT_API CodeHolder() noexcept;
     516             :   //! Destroy the CodeHolder.
     517             :   ASMJIT_API ~CodeHolder() noexcept;
     518             : 
     519             :   // --------------------------------------------------------------------------
     520             :   // [Init / Reset]
     521             :   // --------------------------------------------------------------------------
     522             : 
     523             :   ASMJIT_INLINE bool isInitialized() const noexcept { return _codeInfo.isInitialized(); }
     524             : 
     525             :   //! Initialize to CodeHolder to hold code described by `codeInfo`.
     526             :   ASMJIT_API Error init(const CodeInfo& info) noexcept;
     527             :   //! Detach all code-generators attached and reset the \ref CodeHolder.
     528             :   ASMJIT_API void reset(bool releaseMemory = false) noexcept;
     529             : 
     530             :   // --------------------------------------------------------------------------
     531             :   // [Attach / Detach]
     532             :   // --------------------------------------------------------------------------
     533             : 
     534             :   //! Attach a \ref CodeEmitter to this \ref CodeHolder.
     535             :   ASMJIT_API Error attach(CodeEmitter* emitter) noexcept;
     536             :   //! Detach a \ref CodeEmitter from this \ref CodeHolder.
     537             :   ASMJIT_API Error detach(CodeEmitter* emitter) noexcept;
     538             : 
     539             :   // --------------------------------------------------------------------------
     540             :   // [Sync]
     541             :   // --------------------------------------------------------------------------
     542             : 
     543             :   //! Synchronize all states of all `CodeEmitter`s associated with the CodeHolder.
     544             :   //! This is required as some code generators don't sync every time they do
     545             :   //! something - for example \ref Assembler generally syncs when it needs to
     546             :   //! reallocate the \ref CodeBuffer, but not each time it encodes instruction
     547             :   //! or directive.
     548             :   ASMJIT_API void sync() noexcept;
     549             : 
     550             :   // --------------------------------------------------------------------------
     551             :   // [Code-Information]
     552             :   // --------------------------------------------------------------------------
     553             : 
     554             :   //! Get code/target information, see \ref CodeInfo.
     555             :   ASMJIT_INLINE const CodeInfo& getCodeInfo() const noexcept { return _codeInfo; }
     556             :   //! Get architecture information, see \ref ArchInfo.
     557             :   ASMJIT_INLINE const ArchInfo& getArchInfo() const noexcept { return _codeInfo.getArchInfo(); }
     558             : 
     559             :   //! Get the target's architecture type.
     560             :   ASMJIT_INLINE uint32_t getArchType() const noexcept { return getArchInfo().getType(); }
     561             :   //! Get the target's architecture sub-type.
     562             :   ASMJIT_INLINE uint32_t getArchSubType() const noexcept { return getArchInfo().getSubType(); }
     563             : 
     564             :   //! Get if a static base-address is set.
     565             :   ASMJIT_INLINE bool hasBaseAddress() const noexcept { return _codeInfo.hasBaseAddress(); }
     566             :   //! Get a static base-address (uint64_t).
     567             :   ASMJIT_INLINE uint64_t getBaseAddress() const noexcept { return _codeInfo.getBaseAddress(); }
     568             : 
     569             :   // --------------------------------------------------------------------------
     570             :   // [Global Information]
     571             :   // --------------------------------------------------------------------------
     572             : 
     573             :   //! Get global hints, internally propagated to all `CodeEmitter`s attached.
     574       64222 :   ASMJIT_INLINE uint32_t getGlobalHints() const noexcept { return _globalHints; }
     575             :   //! Get global options, internally propagated to all `CodeEmitter`s attached.
     576       64222 :   ASMJIT_INLINE uint32_t getGlobalOptions() const noexcept { return _globalOptions; }
     577             : 
     578             :   // --------------------------------------------------------------------------
     579             :   // [Result Information]
     580             :   // --------------------------------------------------------------------------
     581             : 
     582             :   //! Get the size code & data of all sections.
     583             :   ASMJIT_API size_t getCodeSize() const noexcept;
     584             : 
     585             :   //! Get size of all possible trampolines.
     586             :   //!
     587             :   //! Trampolines are needed to successfully generate relative jumps to absolute
     588             :   //! addresses. This value is only non-zero if jmp of call instructions were
     589             :   //! used with immediate operand (this means jumping or calling an absolute
     590             :   //! address directly).
     591       64222 :   ASMJIT_INLINE size_t getTrampolinesSize() const noexcept { return _trampolinesSize; }
     592             : 
     593             :   // --------------------------------------------------------------------------
     594             :   // [Logging & Error Handling]
     595             :   // --------------------------------------------------------------------------
     596             : 
     597             : #if !defined(ASMJIT_DISABLE_LOGGING)
     598             :   //! Get if a logger attached.
     599             :   ASMJIT_INLINE bool hasLogger() const noexcept { return _logger != nullptr; }
     600             :   //! Get the attached logger.
     601       32111 :   ASMJIT_INLINE Logger* getLogger() const noexcept { return _logger; }
     602             :   //! Attach a `logger` to CodeHolder and propagate it to all attached `CodeEmitter`s.
     603             :   ASMJIT_API void setLogger(Logger* logger) noexcept;
     604             :   //! Reset the logger (does nothing if not attached).
     605             :   ASMJIT_INLINE void resetLogger() noexcept { setLogger(nullptr); }
     606             : #endif // !ASMJIT_DISABLE_LOGGING
     607             : 
     608             :   //! Get if error-handler is attached.
     609             :   ASMJIT_INLINE bool hasErrorHandler() const noexcept { return _errorHandler != nullptr; }
     610             :   //! Get the error-handler.
     611             :   ASMJIT_INLINE ErrorHandler* getErrorHandler() const noexcept { return _errorHandler; }
     612             :   //! Set the error handler, will affect all attached `CodeEmitter`s.
     613             :   ASMJIT_API Error setErrorHandler(ErrorHandler* handler) noexcept;
     614             :   //! Reset the error handler (does nothing if not attached).
     615             :   ASMJIT_INLINE void resetErrorHandler() noexcept { setErrorHandler(nullptr); }
     616             : 
     617             :   // --------------------------------------------------------------------------
     618             :   // [Sections]
     619             :   // --------------------------------------------------------------------------
     620             : 
     621             :   //! Get array of `SectionEntry*` records.
     622             :   ASMJIT_INLINE const ZoneVector<SectionEntry*>& getSections() const noexcept { return _sections; }
     623             : 
     624             :   //! Get a section entry of the given index.
     625             :   ASMJIT_INLINE SectionEntry* getSectionEntry(size_t index) const noexcept { return _sections[index]; }
     626             : 
     627             :   ASMJIT_API Error growBuffer(CodeBuffer* cb, size_t n) noexcept;
     628             :   ASMJIT_API Error reserveBuffer(CodeBuffer* cb, size_t n) noexcept;
     629             : 
     630             :   // --------------------------------------------------------------------------
     631             :   // [Labels & Symbols]
     632             :   // --------------------------------------------------------------------------
     633             : 
     634             :   //! Create a new anonymous label and return its id in `idOut`.
     635             :   //!
     636             :   //! Returns `Error`, does not report error to \ref ErrorHandler.
     637             :   ASMJIT_API Error newLabelId(uint32_t& idOut) noexcept;
     638             : 
     639             :   //! Create a new named label label-type `type`.
     640             :   //!
     641             :   //! Returns `Error`, does not report error to \ref ErrorHandler.
     642             :   ASMJIT_API Error newNamedLabelId(uint32_t& idOut, const char* name, size_t nameLength, uint32_t type, uint32_t parentId) noexcept;
     643             : 
     644             :   //! Get a label id by name.
     645             :   ASMJIT_API uint32_t getLabelIdByName(const char* name, size_t nameLength = Globals::kInvalidIndex, uint32_t parentId = 0) noexcept;
     646             : 
     647             :   //! Create a new label-link used to store information about yet unbound labels.
     648             :   //!
     649             :   //! Returns `null` if the allocation failed.
     650             :   ASMJIT_API LabelLink* newLabelLink(LabelEntry* le, uint32_t sectionId, size_t offset, intptr_t rel) noexcept;
     651             : 
     652             :   //! Get array of `LabelEntry*` records.
     653             :   ASMJIT_INLINE const ZoneVector<LabelEntry*>& getLabelEntries() const noexcept { return _labels; }
     654             : 
     655             :   //! Get number of labels created.
     656             :   ASMJIT_INLINE size_t getLabelsCount() const noexcept { return _labels.getLength(); }
     657             : 
     658             :   //! Get number of label references, which are unresolved at the moment.
     659             :   ASMJIT_INLINE size_t getUnresolvedLabelsCount() const noexcept { return _unresolvedLabelsCount; }
     660             : 
     661             :   //! Get if the `label` is valid (i.e. created by `newLabelId()`).
     662             :   ASMJIT_INLINE bool isLabelValid(const Label& label) const noexcept {
     663             :     return isLabelValid(label.getId());
     664             :   }
     665             :   //! Get if the label having `id` is valid (i.e. created by `newLabelId()`).
     666             :   ASMJIT_INLINE bool isLabelValid(uint32_t labelId) const noexcept {
     667             :     size_t index = Operand::unpackId(labelId);
     668             :     return index < _labels.getLength();
     669             :   }
     670             : 
     671             :   //! Get if the `label` is already bound.
     672             :   //!
     673             :   //! Returns `false` if the `label` is not valid.
     674             :   ASMJIT_INLINE bool isLabelBound(const Label& label) const noexcept {
     675             :     return isLabelBound(label.getId());
     676             :   }
     677             :   //! \overload
     678             :   ASMJIT_INLINE bool isLabelBound(uint32_t id) const noexcept {
     679             :     size_t index = Operand::unpackId(id);
     680             :     return index < _labels.getLength() && _labels[index]->isBound();
     681             :   }
     682             : 
     683             :   //! Get a `label` offset or -1 if the label is not yet bound.
     684             :   ASMJIT_INLINE intptr_t getLabelOffset(const Label& label) const noexcept {
     685             :     return getLabelOffset(label.getId());
     686             :   }
     687             :   //! \overload
     688             :   ASMJIT_INLINE intptr_t getLabelOffset(uint32_t id) const noexcept {
     689             :     ASMJIT_ASSERT(isLabelValid(id));
     690             :     return _labels[Operand::unpackId(id)]->getOffset();
     691             :   }
     692             : 
     693             :   //! Get information about the given `label`.
     694             :   ASMJIT_INLINE LabelEntry* getLabelEntry(const Label& label) const noexcept {
     695             :     return getLabelEntry(label.getId());
     696             :   }
     697             :   //! Get information about a label having the given `id`.
     698             :   ASMJIT_INLINE LabelEntry* getLabelEntry(uint32_t id) const noexcept {
     699       64222 :     size_t index = static_cast<size_t>(Operand::unpackId(id));
     700       64222 :     return index < _labels.getLength() ? _labels[index] : static_cast<LabelEntry*>(nullptr);
     701             :   }
     702             : 
     703             :   // --------------------------------------------------------------------------
     704             :   // [Relocations]
     705             :   // --------------------------------------------------------------------------
     706             : 
     707             :   //! Create a new relocation entry of type `type` and size `size`.
     708             :   //!
     709             :   //! Additional fields can be set after the relocation entry was created.
     710             :   ASMJIT_API Error newRelocEntry(RelocEntry** dst, uint32_t type, uint32_t size) noexcept;
     711             : 
     712             :   //! Get if the code contains relocations.
     713             :   ASMJIT_INLINE bool hasRelocations() const noexcept { return !_relocations.isEmpty(); }
     714             :   //! Get array of `RelocEntry*` records.
     715             :   ASMJIT_INLINE const ZoneVector<RelocEntry*>& getRelocEntries() const noexcept { return _relocations; }
     716             : 
     717             :   ASMJIT_INLINE RelocEntry* getRelocEntry(uint32_t id) const noexcept { return _relocations[id]; }
     718             : 
     719             :   //! Relocate the code to `baseAddress` and copy it to `dst`.
     720             :   //!
     721             :   //! \param dst Contains the location where the relocated code should be
     722             :   //! copied. The pointer can be address returned by virtual memory allocator
     723             :   //! or any other address that has sufficient space.
     724             :   //!
     725             :   //! \param baseAddress Base address used for relocation. `JitRuntime` always
     726             :   //! sets the `baseAddress` to be the same as `dst`.
     727             :   //!
     728             :   //! \return The number bytes actually used. If the code emitter reserved
     729             :   //! space for possible trampolines, but didn't use it, the number of bytes
     730             :   //! used can actually be less than the expected worst case. Virtual memory
     731             :   //! allocator can shrink the memory it allocated initially.
     732             :   //!
     733             :   //! A given buffer will be overwritten, to get the number of bytes required,
     734             :   //! use `getCodeSize()`.
     735             :   ASMJIT_API size_t relocate(void* dst, uint64_t baseAddress = Globals::kNoBaseAddress) const noexcept;
     736             : 
     737             :   // --------------------------------------------------------------------------
     738             :   // [Members]
     739             :   // --------------------------------------------------------------------------
     740             : 
     741             :   CodeInfo _codeInfo;                    //!< Basic information about the code (architecture and other info).
     742             : 
     743             :   uint32_t _globalHints;                 //!< Global hints, propagated to all `CodeEmitter`s.
     744             :   uint32_t _globalOptions;               //!< Global options, propagated to all `CodeEmitter`s.
     745             : 
     746             :   CodeEmitter* _emitters;                //!< Linked-list of all attached `CodeEmitter`s.
     747             :   Assembler* _cgAsm;                     //!< Attached \ref Assembler (only one at a time).
     748             : 
     749             :   Logger* _logger;                       //!< Attached \ref Logger, used by all consumers.
     750             :   ErrorHandler* _errorHandler;           //!< Attached \ref ErrorHandler.
     751             : 
     752             :   uint32_t _unresolvedLabelsCount;       //!< Count of label references which were not resolved.
     753             :   uint32_t _trampolinesSize;             //!< Size of all possible trampolines.
     754             : 
     755             :   Zone _baseZone;                        //!< Base zone (used to allocate core structures).
     756             :   Zone _dataZone;                        //!< Data zone (used to allocate extra data like label names).
     757             :   ZoneHeap _baseHeap;                    //!< Zone allocator, used to manage internal containers.
     758             : 
     759             :   ZoneVector<SectionEntry*> _sections;   //!< Section entries.
     760             :   ZoneVector<LabelEntry*> _labels;       //!< Label entries (each label is stored here).
     761             :   ZoneVector<RelocEntry*> _relocations;  //!< Relocation entries.
     762             :   ZoneHash<LabelEntry> _namedLabels;     //!< Label name -> LabelEntry (only named labels).
     763             : };
     764             : 
     765             : //! \}
     766             : 
     767             : } // asmjit namespace
     768             : } // namespace PLMD
     769             : 
     770             : // [Api-End]
     771             : #include "./asmjit_apiend.h"
     772             : 
     773             : // [Guard]
     774             : #endif // _ASMJIT_BASE_CODEHOLDER_H
     775             : #pragma GCC diagnostic pop
     776             : #endif // __PLUMED_HAS_ASMJIT
     777             : #endif

Generated by: LCOV version 1.16