LCOV - code coverage report
Current view: top level - asmjit - codebuilder.h (source / functions) Hit Total Coverage
Test: plumed test coverage (other modules) Lines: 50 94 53.2 %
Date: 2024-10-11 08:09:49 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_codebuilder_h
      21             : #define __PLUMED_asmjit_codebuilder_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_CODEBUILDER_H
      33             : #define _ASMJIT_BASE_CODEBUILDER_H
      34             : 
      35             : #include "./asmjit_build.h"
      36             : #if !defined(ASMJIT_DISABLE_BUILDER)
      37             : 
      38             : // [Dependencies]
      39             : #include "./assembler.h"
      40             : #include "./codeholder.h"
      41             : #include "./constpool.h"
      42             : #include "./inst.h"
      43             : #include "./operand.h"
      44             : #include "./utils.h"
      45             : #include "./zone.h"
      46             : 
      47             : // [Api-Begin]
      48             : #include "./asmjit_apibegin.h"
      49             : 
      50             : namespace PLMD {
      51             : namespace asmjit {
      52             : 
      53             : // ============================================================================
      54             : // [Forward Declarations]
      55             : // ============================================================================
      56             : 
      57             : class CBNode;
      58             : class CBPass;
      59             : 
      60             : class CBAlign;
      61             : class CBComment;
      62             : class CBConstPool;
      63             : class CBData;
      64             : class CBInst;
      65             : class CBJump;
      66             : class CBLabel;
      67             : class CBLabelData;
      68             : class CBSentinel;
      69             : 
      70             : //! \addtogroup asmjit_base
      71             : //! \{
      72             : 
      73             : // ============================================================================
      74             : // [asmjit::CodeBuilder]
      75             : // ============================================================================
      76             : 
      77             : class ASMJIT_VIRTAPI CodeBuilder : public CodeEmitter {
      78             : public:
      79             :   ASMJIT_NONCOPYABLE(CodeBuilder)
      80             :   typedef CodeEmitter Base;
      81             : 
      82             :   // --------------------------------------------------------------------------
      83             :   // [Construction / Destruction]
      84             :   // --------------------------------------------------------------------------
      85             : 
      86             :   //! Create a new `CodeBuilder` instance.
      87             :   ASMJIT_API CodeBuilder() noexcept;
      88             :   //! Destroy the `CodeBuilder` instance.
      89             :   ASMJIT_API virtual ~CodeBuilder() noexcept;
      90             : 
      91             :   // --------------------------------------------------------------------------
      92             :   // [Events]
      93             :   // --------------------------------------------------------------------------
      94             : 
      95             :   ASMJIT_API virtual Error onAttach(CodeHolder* code) noexcept override;
      96             :   ASMJIT_API virtual Error onDetach(CodeHolder* code) noexcept override;
      97             : 
      98             :   // --------------------------------------------------------------------------
      99             :   // [Accessors]
     100             :   // --------------------------------------------------------------------------
     101             : 
     102             :   //! Get a vector of CBPass objects that will be executed by `process()`.
     103             :   ASMJIT_INLINE const ZoneVector<CBPass*>& getPasses() const noexcept { return _cbPasses; }
     104             : 
     105             :   //! Get a vector of CBLabel nodes.
     106             :   //!
     107             :   //! NOTE: If a label of some index is not associated with `CodeBuilder` it
     108             :   //! would be null, so always check for nulls if you iterate over the vector.
     109             :   ASMJIT_INLINE const ZoneVector<CBLabel*>& getLabels() const noexcept { return _cbLabels; }
     110             : 
     111             :   //! Get the first node.
     112        3888 :   ASMJIT_INLINE CBNode* getFirstNode() const noexcept { return _firstNode; }
     113             :   //! Get the last node.
     114             :   ASMJIT_INLINE CBNode* getLastNode() const noexcept { return _lastNode; }
     115             : 
     116             :   // --------------------------------------------------------------------------
     117             :   // [Node-Management]
     118             :   // --------------------------------------------------------------------------
     119             : 
     120             :   //! \internal
     121             :   template<typename T>
     122        3888 :   ASMJIT_INLINE T* newNodeT() noexcept { return new(_cbHeap.alloc(sizeof(T))) T(this); }
     123             : 
     124             :   //! \internal
     125             :   template<typename T, typename P0>
     126           0 :   ASMJIT_INLINE T* newNodeT(P0 p0) noexcept { return new(_cbHeap.alloc(sizeof(T))) T(this, p0); }
     127             : 
     128             :   //! \internal
     129             :   template<typename T, typename P0, typename P1>
     130        1944 :   ASMJIT_INLINE T* newNodeT(P0 p0, P1 p1) noexcept { return new(_cbHeap.alloc(sizeof(T))) T(this, p0, p1); }
     131             : 
     132             :   //! \internal
     133             :   template<typename T, typename P0, typename P1, typename P2>
     134           0 :   ASMJIT_INLINE T* newNodeT(P0 p0, P1 p1, P2 p2) noexcept { return new(_cbHeap.alloc(sizeof(T))) T(this, p0, p1, p2); }
     135             : 
     136             :   ASMJIT_API Error registerLabelNode(CBLabel* node) noexcept;
     137             :   //! Get `CBLabel` by `id`.
     138             :   ASMJIT_API Error getCBLabel(CBLabel** pOut, uint32_t id) noexcept;
     139             :   //! Get `CBLabel` by `label`.
     140           0 :   ASMJIT_INLINE Error getCBLabel(CBLabel** pOut, const Label& label) noexcept { return getCBLabel(pOut, label.getId()); }
     141             : 
     142             :   //! Create a new \ref CBLabel node.
     143             :   ASMJIT_API CBLabel* newLabelNode() noexcept;
     144             :   //! Create a new \ref CBAlign node.
     145             :   ASMJIT_API CBAlign* newAlignNode(uint32_t mode, uint32_t alignment) noexcept;
     146             :   //! Create a new \ref CBData node.
     147             :   ASMJIT_API CBData* newDataNode(const void* data, uint32_t size) noexcept;
     148             :   //! Create a new \ref CBConstPool node.
     149             :   ASMJIT_API CBConstPool* newConstPool() noexcept;
     150             :   //! Create a new \ref CBComment node.
     151             :   ASMJIT_API CBComment* newCommentNode(const char* s, size_t len) noexcept;
     152             : 
     153             :   // --------------------------------------------------------------------------
     154             :   // [Code-Emitter]
     155             :   // --------------------------------------------------------------------------
     156             : 
     157             :   ASMJIT_API virtual Label newLabel() override;
     158             :   ASMJIT_API virtual Label newNamedLabel(const char* name, size_t nameLength = Globals::kInvalidIndex, uint32_t type = Label::kTypeGlobal, uint32_t parentId = kInvalidValue) override;
     159             :   ASMJIT_API virtual Error bind(const Label& label) override;
     160             :   ASMJIT_API virtual Error align(uint32_t mode, uint32_t alignment) override;
     161             :   ASMJIT_API virtual Error embed(const void* data, uint32_t size) override;
     162             :   ASMJIT_API virtual Error embedLabel(const Label& label) override;
     163             :   ASMJIT_API virtual Error embedConstPool(const Label& label, const ConstPool& pool) override;
     164             :   ASMJIT_API virtual Error comment(const char* s, size_t len = Globals::kInvalidIndex) override;
     165             : 
     166             :   // --------------------------------------------------------------------------
     167             :   // [Node-Management]
     168             :   // --------------------------------------------------------------------------
     169             : 
     170             :   //! Add `node` after the current and set current to `node`.
     171             :   ASMJIT_API CBNode* addNode(CBNode* node) noexcept;
     172             :   //! Insert `node` after `ref`.
     173             :   ASMJIT_API CBNode* addAfter(CBNode* node, CBNode* ref) noexcept;
     174             :   //! Insert `node` before `ref`.
     175             :   ASMJIT_API CBNode* addBefore(CBNode* node, CBNode* ref) noexcept;
     176             :   //! Remove `node`.
     177             :   ASMJIT_API CBNode* removeNode(CBNode* node) noexcept;
     178             :   //! Remove multiple nodes.
     179             :   ASMJIT_API void removeNodes(CBNode* first, CBNode* last) noexcept;
     180             : 
     181             :   //! Get current node.
     182             :   //!
     183             :   //! \note If this method returns null it means that nothing has been
     184             :   //! emitted yet.
     185        1944 :   ASMJIT_INLINE CBNode* getCursor() const noexcept { return _cursor; }
     186             :   //! Set the current node without returning the previous node.
     187        9412 :   ASMJIT_INLINE void _setCursor(CBNode* node) noexcept { _cursor = node; }
     188             :   //! Set the current node to `node` and return the previous one.
     189             :   ASMJIT_API CBNode* setCursor(CBNode* node) noexcept;
     190             : 
     191             :   // --------------------------------------------------------------------------
     192             :   // [Passes]
     193             :   // --------------------------------------------------------------------------
     194             : 
     195             :   template<typename T>
     196        1944 :   ASMJIT_INLINE T* newPassT() noexcept { return new(_cbBaseZone.alloc(sizeof(T))) T(); }
     197             :   template<typename T, typename P0>
     198             :   ASMJIT_INLINE T* newPassT(P0 p0) noexcept { return new(_cbBaseZone.alloc(sizeof(T))) T(p0); }
     199             :   template<typename T, typename P0, typename P1>
     200             :   ASMJIT_INLINE T* newPassT(P0 p0, P1 p1) noexcept { return new(_cbBaseZone.alloc(sizeof(T))) T(p0, p1); }
     201             : 
     202             :   template<typename T>
     203        1944 :   ASMJIT_INLINE Error addPassT() noexcept { return addPass(newPassT<T>()); }
     204             :   template<typename T, typename P0>
     205             :   ASMJIT_INLINE Error addPassT(P0 p0) noexcept { return addPass(newPassT<P0>(p0)); }
     206             :   template<typename T, typename P0, typename P1>
     207             :   ASMJIT_INLINE Error addPassT(P0 p0, P1 p1) noexcept { return addPass(newPassT<P0, P1>(p0, p1)); }
     208             : 
     209             :   //! Get a `CBPass` by name.
     210             :   ASMJIT_API CBPass* getPassByName(const char* name) const noexcept;
     211             :   //! Add `pass` to the list of passes.
     212             :   ASMJIT_API Error addPass(CBPass* pass) noexcept;
     213             :   //! Remove `pass` from the list of passes and delete it.
     214             :   ASMJIT_API Error deletePass(CBPass* pass) noexcept;
     215             : 
     216             :   // --------------------------------------------------------------------------
     217             :   // [Serialization]
     218             :   // --------------------------------------------------------------------------
     219             : 
     220             :   ASMJIT_API virtual Error serialize(CodeEmitter* dst);
     221             : 
     222             :   // --------------------------------------------------------------------------
     223             :   // [Members]
     224             :   // --------------------------------------------------------------------------
     225             : 
     226             :   Zone _cbBaseZone;                      //!< Base zone used to allocate nodes and `CBPass`.
     227             :   Zone _cbDataZone;                      //!< Data zone used to allocate data and names.
     228             :   Zone _cbPassZone;                      //!< Zone passed to `CBPass::process()`.
     229             :   ZoneHeap _cbHeap;                      //!< ZoneHeap that uses `_cbBaseZone`.
     230             : 
     231             :   ZoneVector<CBPass*> _cbPasses;         //!< Array of `CBPass` objects.
     232             :   ZoneVector<CBLabel*> _cbLabels;        //!< Maps label indexes to `CBLabel` nodes.
     233             : 
     234             :   CBNode* _firstNode;                    //!< First node of the current section.
     235             :   CBNode* _lastNode;                     //!< Last node of the current section.
     236             :   CBNode* _cursor;                       //!< Current node (cursor).
     237             : 
     238             :   uint32_t _position;                    //!< Flow-id assigned to each new node.
     239             :   uint32_t _nodeFlags;                   //!< Flags assigned to each new node.
     240             : };
     241             : 
     242             : // ============================================================================
     243             : // [asmjit::CBPass]
     244             : // ============================================================================
     245             : 
     246             : //! `CodeBuilder` pass used to  code transformations, analysis, and lowering.
     247             : class ASMJIT_VIRTAPI CBPass {
     248             : public:
     249             :   ASMJIT_NONCOPYABLE(CBPass);
     250             : 
     251             :   // --------------------------------------------------------------------------
     252             :   // [Construction / Destruction]
     253             :   // --------------------------------------------------------------------------
     254             : 
     255             :   ASMJIT_API CBPass(const char* name) noexcept;
     256             :   ASMJIT_API virtual ~CBPass() noexcept;
     257             : 
     258             :   // --------------------------------------------------------------------------
     259             :   // [Interface]
     260             :   // --------------------------------------------------------------------------
     261             : 
     262             :   //! Process the code stored in CodeBuffer `cb`.
     263             :   //!
     264             :   //! This is the only function that is called by the `CodeBuilder` to process
     265             :   //! the code. It passes the CodeBuilder itself (`cb`) and also a zone memory
     266             :   //! allocator `zone`, which will be reset after the `process()` returns. The
     267             :   //! allocator should be used for all allocations as it's fast and everything
     268             :   //! it allocates will be released at once when `process()` returns.
     269             :   virtual Error process(Zone* zone) noexcept = 0;
     270             : 
     271             :   // --------------------------------------------------------------------------
     272             :   // [Accessors]
     273             :   // --------------------------------------------------------------------------
     274             : 
     275        1944 :   ASMJIT_INLINE const CodeBuilder* cb() const noexcept { return _cb; }
     276           0 :   ASMJIT_INLINE const char* getName() const noexcept { return _name; }
     277             : 
     278             :   // --------------------------------------------------------------------------
     279             :   // [Members]
     280             :   // --------------------------------------------------------------------------
     281             : 
     282             :   CodeBuilder* _cb;                      //!< CodeBuilder this pass is assigned to.
     283             :   const char* _name;                     //!< Name of the pass.
     284             : };
     285             : 
     286             : // ============================================================================
     287             : // [asmjit::CBNode]
     288             : // ============================================================================
     289             : 
     290             : //! Node (CodeBuilder).
     291             : //!
     292             : //! Every node represents a building-block used by \ref CodeBuilder. It can be
     293             : //! instruction, data, label, comment, directive, or any other high-level
     294             : //! representation that can be transformed to the building blocks mentioned.
     295             : //! Every class that inherits \ref CodeBuilder can define its own nodes that it
     296             : //! can lower to basic nodes.
     297             : class CBNode {
     298             : public:
     299             :   ASMJIT_NONCOPYABLE(CBNode)
     300             : 
     301             :   // --------------------------------------------------------------------------
     302             :   // [Type]
     303             :   // --------------------------------------------------------------------------
     304             : 
     305             :   //! Type of \ref CBNode.
     306             :   ASMJIT_ENUM(NodeType) {
     307             :     kNodeNone       = 0,                 //!< Invalid node (internal, don't use).
     308             : 
     309             :     // [CodeBuilder]
     310             :     kNodeInst       = 1,                 //!< Node is \ref CBInst or \ref CBJump.
     311             :     kNodeData       = 2,                 //!< Node is \ref CBData.
     312             :     kNodeAlign      = 3,                 //!< Node is \ref CBAlign.
     313             :     kNodeLabel      = 4,                 //!< Node is \ref CBLabel.
     314             :     kNodeLabelData  = 5,                 //!< Node is \ref CBLabelData.
     315             :     kNodeConstPool  = 6,                 //!< Node is \ref CBConstPool.
     316             :     kNodeComment    = 7,                 //!< Node is \ref CBComment.
     317             :     kNodeSentinel   = 8,                 //!< Node is \ref CBSentinel.
     318             : 
     319             :     // [CodeCompiler]
     320             :     kNodeFunc       = 16,                //!< Node is \ref CCFunc (considered as \ref CBLabel by \ref CodeBuilder).
     321             :     kNodeFuncExit   = 17,                //!< Node is \ref CCFuncRet.
     322             :     kNodeFuncCall   = 18,                //!< Node is \ref CCFuncCall.
     323             :     kNodePushArg    = 19,                //!< Node is \ref CCPushArg.
     324             :     kNodeHint       = 20,                //!< Node is \ref CCHint.
     325             : 
     326             :     // [UserDefined]
     327             :     kNodeUser       = 32                 //!< First id of a user-defined node.
     328             :   };
     329             : 
     330             :   // --------------------------------------------------------------------------
     331             :   // [Flags]
     332             :   // --------------------------------------------------------------------------
     333             : 
     334             :   ASMJIT_ENUM(Flags) {
     335             :     //! The node has been translated by the CodeCompiler.
     336             :     kFlagIsTranslated = 0x0001,
     337             :     //! If the node can be safely removed (has no effect).
     338             :     kFlagIsRemovable = 0x0004,
     339             :     //! If the node is informative only and can be safely removed.
     340             :     kFlagIsInformative = 0x0008,
     341             : 
     342             :     //! If the `CBInst` is a jump.
     343             :     kFlagIsJmp = 0x0010,
     344             :     //! If the `CBInst` is a conditional jump.
     345             :     kFlagIsJcc = 0x0020,
     346             : 
     347             :     //! If the `CBInst` is an unconditional jump or conditional jump that is
     348             :     //! likely to be taken.
     349             :     kFlagIsTaken = 0x0040,
     350             : 
     351             :     //! If the `CBNode` will return from a function.
     352             :     //!
     353             :     //! This flag is used by both `CBSentinel` and `CCFuncRet`.
     354             :     kFlagIsRet = 0x0080,
     355             : 
     356             :     //! Whether the instruction is special.
     357             :     kFlagIsSpecial = 0x0100,
     358             : 
     359             :     //! Whether the instruction is an FPU instruction.
     360             :     kFlagIsFp = 0x0200
     361             :   };
     362             : 
     363             :   // --------------------------------------------------------------------------
     364             :   // [Construction / Destruction]
     365             :   // --------------------------------------------------------------------------
     366             : 
     367             :   //! Create a new \ref CBNode - always use \ref CodeBuilder to allocate nodes.
     368       56030 :   ASMJIT_INLINE CBNode(CodeBuilder* cb, uint32_t type) noexcept {
     369       56030 :     _prev = nullptr;
     370       56030 :     _next = nullptr;
     371       54086 :     _type = static_cast<uint8_t>(type);
     372        7776 :     _opCount = 0;
     373       56030 :     _flags = static_cast<uint16_t>(cb->_nodeFlags);
     374       56030 :     _position = cb->_position;
     375       56030 :     _inlineComment = nullptr;
     376       50506 :     _passData = nullptr;
     377             :   }
     378             :   //! Destroy the `CBNode` instance (NEVER CALLED).
     379             :   ASMJIT_INLINE ~CBNode() noexcept {}
     380             : 
     381             :   // --------------------------------------------------------------------------
     382             :   // [Accessors]
     383             :   // --------------------------------------------------------------------------
     384             : 
     385             :   template<typename T>
     386             :   ASMJIT_INLINE T* as() noexcept { return static_cast<T*>(this); }
     387             :   template<typename T>
     388             :   ASMJIT_INLINE const T* as() const noexcept { return static_cast<const T*>(this); }
     389             : 
     390             :   //! Get previous node in the compiler stream.
     391       73260 :   ASMJIT_INLINE CBNode* getPrev() const noexcept { return _prev; }
     392             :   //! Get next node in the compiler stream.
     393      144610 :   ASMJIT_INLINE CBNode* getNext() const noexcept { return _next; }
     394             : 
     395             :   //! Get the node type, see \ref Type.
     396      250920 :   ASMJIT_INLINE uint32_t getType() const noexcept { return _type; }
     397             :   //! Get the node flags.
     398       31106 :   ASMJIT_INLINE uint32_t getFlags() const noexcept { return _flags; }
     399             : 
     400             :   //! Get whether the instruction has flag `flag`.
     401      170672 :   ASMJIT_INLINE bool hasFlag(uint32_t flag) const noexcept { return (static_cast<uint32_t>(_flags) & flag) != 0; }
     402             :   //! Set node flags to `flags`.
     403       31106 :   ASMJIT_INLINE void setFlags(uint32_t flags) noexcept { _flags = static_cast<uint16_t>(flags); }
     404             :   //! Add instruction `flags`.
     405        1944 :   ASMJIT_INLINE void orFlags(uint32_t flags) noexcept { _flags |= static_cast<uint16_t>(flags); }
     406             :   //! And instruction `flags`.
     407             :   ASMJIT_INLINE void andFlags(uint32_t flags) noexcept { _flags &= static_cast<uint16_t>(flags); }
     408             :   //! Clear instruction `flags`.
     409             :   ASMJIT_INLINE void andNotFlags(uint32_t flags) noexcept { _flags &= ~static_cast<uint16_t>(flags); }
     410             : 
     411             :   //! Get whether the node has been translated.
     412             :   ASMJIT_INLINE bool isTranslated() const noexcept { return hasFlag(kFlagIsTranslated); }
     413             : 
     414             :   //! Get whether the node is removable if it's in unreachable code block.
     415             :   ASMJIT_INLINE bool isRemovable() const noexcept { return hasFlag(kFlagIsRemovable); }
     416             :   //! Get whether the node is informative only (comment, hint).
     417             :   ASMJIT_INLINE bool isInformative() const noexcept { return hasFlag(kFlagIsInformative); }
     418             : 
     419             :   //! Whether the node is `CBLabel`.
     420           0 :   ASMJIT_INLINE bool isLabel() const noexcept { return _type == kNodeLabel; }
     421             :   //! Whether the `CBInst` node is an unconditional jump.
     422             :   ASMJIT_INLINE bool isJmp() const noexcept { return hasFlag(kFlagIsJmp); }
     423             :   //! Whether the `CBInst` node is a conditional jump.
     424             :   ASMJIT_INLINE bool isJcc() const noexcept { return hasFlag(kFlagIsJcc); }
     425             :   //! Whether the `CBInst` node is a conditional/unconditional jump.
     426             :   ASMJIT_INLINE bool isJmpOrJcc() const noexcept { return hasFlag(kFlagIsJmp | kFlagIsJcc); }
     427             :   //! Whether the `CBInst` node is a return.
     428             :   ASMJIT_INLINE bool isRet() const noexcept { return hasFlag(kFlagIsRet); }
     429             : 
     430             :   //! Get whether the node is `CBInst` and the instruction is special.
     431             :   ASMJIT_INLINE bool isSpecial() const noexcept { return hasFlag(kFlagIsSpecial); }
     432             :   //! Get whether the node is `CBInst` and the instruction uses x87-FPU.
     433             :   ASMJIT_INLINE bool isFp() const noexcept { return hasFlag(kFlagIsFp); }
     434             : 
     435           0 :   ASMJIT_INLINE bool hasPosition() const noexcept { return _position != 0; }
     436             :   //! Get flow index.
     437           0 :   ASMJIT_INLINE uint32_t getPosition() const noexcept { return _position; }
     438             :   //! Set flow index.
     439       40518 :   ASMJIT_INLINE void setPosition(uint32_t position) noexcept { _position = position; }
     440             : 
     441             :   //! Get if the node has an inline comment.
     442           0 :   ASMJIT_INLINE bool hasInlineComment() const noexcept { return _inlineComment != nullptr; }
     443             :   //! Get an inline comment string.
     444       56030 :   ASMJIT_INLINE const char* getInlineComment() const noexcept { return _inlineComment; }
     445             :   //! Set an inline comment string to `s`.
     446           0 :   ASMJIT_INLINE void setInlineComment(const char* s) noexcept { _inlineComment = s; }
     447             :   //! Set an inline comment string to null.
     448             :   ASMJIT_INLINE void resetInlineComment() noexcept { _inlineComment = nullptr; }
     449             : 
     450             :   //! Get if the node has associated work-data.
     451      111834 :   ASMJIT_INLINE bool hasPassData() const noexcept { return _passData != nullptr; }
     452             :   //! Get work-data - data used during processing & transformations.
     453             :   template<typename T>
     454      329748 :   ASMJIT_INLINE T* getPassData() const noexcept { return (T*)_passData; }
     455             :   //! Set work-data to `data`.
     456             :   template<typename T>
     457       40518 :   ASMJIT_INLINE void setPassData(T* data) noexcept { _passData = (void*)data; }
     458             :   //! Reset work-data to null.
     459             :   ASMJIT_INLINE void resetPassData() noexcept { _passData = nullptr; }
     460             : 
     461             :   // --------------------------------------------------------------------------
     462             :   // [Members]
     463             :   // --------------------------------------------------------------------------
     464             : 
     465             :   CBNode* _prev;                         //!< Previous node.
     466             :   CBNode* _next;                         //!< Next node.
     467             : 
     468             :   uint8_t _type;                         //!< Node type, see \ref NodeType.
     469             :   uint8_t _opCount;                      //!< Count of operands or zero.
     470             :   uint16_t _flags;                       //!< Flags, different meaning for every type of the node.
     471             :   uint32_t _position;                    //!< Flow index.
     472             : 
     473             :   const char* _inlineComment;            //!< Inline comment or null if not used.
     474             :   void* _passData;                       //!< Data used exclusively by the current `CBPass`.
     475             : };
     476             : 
     477             : // ============================================================================
     478             : // [asmjit::CBInst]
     479             : // ============================================================================
     480             : 
     481             : //! Instruction (CodeBuilder).
     482             : //!
     483             : //! Wraps an instruction with its options and operands.
     484             : class CBInst : public CBNode {
     485             : public:
     486             :   ASMJIT_NONCOPYABLE(CBInst)
     487             : 
     488             :   // --------------------------------------------------------------------------
     489             :   // [Construction / Destruction]
     490             :   // --------------------------------------------------------------------------
     491             : 
     492             :   //! Create a new `CBInst` instance.
     493             :   ASMJIT_INLINE CBInst(CodeBuilder* cb, uint32_t instId, uint32_t options, Operand* opArray, uint32_t opCount) noexcept
     494       48254 :     : CBNode(cb, kNodeInst) {
     495             : 
     496             :     orFlags(kFlagIsRemovable);
     497       48254 :     _instDetail.instId = static_cast<uint16_t>(instId);
     498       48254 :     _instDetail.options = options;
     499             : 
     500       48254 :     _opCount = static_cast<uint8_t>(opCount);
     501       48254 :     _opArray = opArray;
     502             : 
     503             :     _updateMemOp();
     504             :   }
     505             : 
     506             :   //! Destroy the `CBInst` instance (NEVER CALLED).
     507             :   ASMJIT_INLINE ~CBInst() noexcept {}
     508             : 
     509             :   // --------------------------------------------------------------------------
     510             :   // [Accessors]
     511             :   // --------------------------------------------------------------------------
     512             : 
     513           0 :   ASMJIT_INLINE Inst::Detail& getInstDetail() noexcept { return _instDetail; }
     514           0 :   ASMJIT_INLINE const Inst::Detail& getInstDetail() const noexcept { return _instDetail; }
     515             : 
     516             :   //! Get the instruction id, see \ref Inst::Id.
     517       79360 :   ASMJIT_INLINE uint32_t getInstId() const noexcept { return _instDetail.instId; }
     518             :   //! Set the instruction id to `instId`, see \ref Inst::Id.
     519             :   ASMJIT_INLINE void setInstId(uint32_t instId) noexcept { _instDetail.instId = instId; }
     520             : 
     521             :   //! Whether the instruction is either a jump or a conditional jump likely to be taken.
     522             :   ASMJIT_INLINE bool isTaken() const noexcept { return hasFlag(kFlagIsTaken); }
     523             : 
     524             :   //! Get emit options.
     525       79118 :   ASMJIT_INLINE uint32_t getOptions() const noexcept { return _instDetail.options; }
     526             :   //! Set emit options.
     527           0 :   ASMJIT_INLINE void setOptions(uint32_t options) noexcept { _instDetail.options = options; }
     528             :   //! Add emit options.
     529             :   ASMJIT_INLINE void addOptions(uint32_t options) noexcept { _instDetail.options |= options; }
     530             :   //! Mask emit options.
     531             :   ASMJIT_INLINE void andOptions(uint32_t options) noexcept { _instDetail.options &= options; }
     532             :   //! Clear emit options.
     533           0 :   ASMJIT_INLINE void delOptions(uint32_t options) noexcept { _instDetail.options &= ~options; }
     534             : 
     535             :   //! Get if the node has an extra register operand.
     536             :   ASMJIT_INLINE bool hasExtraReg() const noexcept { return _instDetail.hasExtraReg(); }
     537             :   //! Get extra register operand.
     538             :   ASMJIT_INLINE RegOnly& getExtraReg() noexcept { return _instDetail.extraReg; }
     539             :   //! \overload
     540             :   ASMJIT_INLINE const RegOnly& getExtraReg() const noexcept { return _instDetail.extraReg; }
     541             :   //! Set extra register operand to `reg`.
     542             :   ASMJIT_INLINE void setExtraReg(const Reg& reg) noexcept { _instDetail.extraReg.init(reg); }
     543             :   //! Set extra register operand to `reg`.
     544             :   ASMJIT_INLINE void setExtraReg(const RegOnly& reg) noexcept { _instDetail.extraReg.init(reg); }
     545             :   //! Reset extra register operand.
     546             :   ASMJIT_INLINE void resetExtraReg() noexcept { _instDetail.extraReg.reset(); }
     547             : 
     548             :   //! Get operands count.
     549       48254 :   ASMJIT_INLINE uint32_t getOpCount() const noexcept { return _opCount; }
     550             :   //! Get operands list.
     551      112102 :   ASMJIT_INLINE Operand* getOpArray() noexcept { return _opArray; }
     552             :   //! \overload
     553           0 :   ASMJIT_INLINE const Operand* getOpArray() const noexcept { return _opArray; }
     554             : 
     555             :   //! Get whether the instruction contains a memory operand.
     556       40846 :   ASMJIT_INLINE bool hasMemOp() const noexcept { return _memOpIndex != 0xFF; }
     557             :   //! Get memory operand.
     558             :   //!
     559             :   //! NOTE: Can only be called if the instruction has such operand,
     560             :   //! see `hasMemOp()`.
     561             :   ASMJIT_INLINE Mem* getMemOp() const noexcept {
     562             :     ASMJIT_ASSERT(hasMemOp());
     563             :     return static_cast<Mem*>(&_opArray[_memOpIndex]);
     564             :   }
     565             :   //! \overload
     566             :   template<typename T>
     567             :   ASMJIT_INLINE T* getMemOp() const noexcept {
     568             :     ASMJIT_ASSERT(hasMemOp());
     569       14496 :     return static_cast<T*>(&_opArray[_memOpIndex]);
     570             :   }
     571             : 
     572             :   //! Set memory operand index, `0xFF` means no memory operand.
     573       54322 :   ASMJIT_INLINE void setMemOpIndex(uint32_t index) noexcept { _memOpIndex = static_cast<uint8_t>(index); }
     574             :   //! Reset memory operand index to `0xFF` (no operand).
     575             :   ASMJIT_INLINE void resetMemOpIndex() noexcept { _memOpIndex = 0xFF; }
     576             : 
     577             :   // --------------------------------------------------------------------------
     578             :   // [Utils]
     579             :   // --------------------------------------------------------------------------
     580             : 
     581             :   ASMJIT_INLINE void _updateMemOp() noexcept {
     582             :     Operand* opArray = getOpArray();
     583             :     uint32_t opCount = getOpCount();
     584             : 
     585             :     uint32_t i;
     586      118400 :     for (i = 0; i < opCount; i++)
     587       84642 :       if (opArray[i].isMem())
     588       14496 :         goto Update;
     589             :     i = 0xFF;
     590             : 
     591       48254 : Update:
     592             :     setMemOpIndex(i);
     593             :   }
     594             : 
     595             :   // --------------------------------------------------------------------------
     596             :   // [Members]
     597             :   // --------------------------------------------------------------------------
     598             : 
     599             :   Inst::Detail _instDetail;              //!< Instruction id, options, and extra register.
     600             :   uint8_t _memOpIndex;                   //!< \internal
     601             :   uint8_t _reserved[7];                  //!< \internal
     602             :   Operand* _opArray;                     //!< Instruction operands.
     603             : };
     604             : 
     605             : // ============================================================================
     606             : // [asmjit::CBInstEx]
     607             : // ============================================================================
     608             : 
     609             : struct CBInstEx : public CBInst {
     610             :   Operand _op4;
     611             :   Operand _op5;
     612             : };
     613             : 
     614             : // ============================================================================
     615             : // [asmjit::CBJump]
     616             : // ============================================================================
     617             : 
     618             : //! Asm jump (conditional or direct).
     619             : //!
     620             : //! Extension of `CBInst` node, which stores more information about the jump.
     621             : class CBJump : public CBInst {
     622             : public:
     623             :   ASMJIT_NONCOPYABLE(CBJump)
     624             : 
     625             :   // --------------------------------------------------------------------------
     626             :   // [Construction / Destruction]
     627             :   // --------------------------------------------------------------------------
     628             : 
     629             :   ASMJIT_INLINE CBJump(CodeBuilder* cb, uint32_t instId, uint32_t options, Operand* opArray, uint32_t opCount) noexcept
     630           0 :     : CBInst(cb, instId, options, opArray, opCount),
     631           0 :       _target(nullptr),
     632           0 :       _jumpNext(nullptr) {}
     633             :   ASMJIT_INLINE ~CBJump() noexcept {}
     634             : 
     635             :   // --------------------------------------------------------------------------
     636             :   // [Accessors]
     637             :   // --------------------------------------------------------------------------
     638             : 
     639           0 :   ASMJIT_INLINE CBLabel* getTarget() const noexcept { return _target; }
     640           0 :   ASMJIT_INLINE CBJump* getJumpNext() const noexcept { return _jumpNext; }
     641             : 
     642             :   // --------------------------------------------------------------------------
     643             :   // [Members]
     644             :   // --------------------------------------------------------------------------
     645             : 
     646             :   CBLabel* _target;                     //!< Target node.
     647             :   CBJump* _jumpNext;                    //!< Next jump to the same target in a single linked-list.
     648             : };
     649             : 
     650             : // ============================================================================
     651             : // [asmjit::CBData]
     652             : // ============================================================================
     653             : 
     654             : //! Asm data (CodeBuilder).
     655             : //!
     656             : //! Wraps `.data` directive. The node contains data that will be placed at the
     657             : //! node's position in the assembler stream. The data is considered to be RAW;
     658             : //! no analysis nor byte-order conversion is performed on RAW data.
     659             : class CBData : public CBNode {
     660             : public:
     661             :   ASMJIT_NONCOPYABLE(CBData)
     662             :   enum { kInlineBufferSize = static_cast<int>(64 - sizeof(CBNode) - 4) };
     663             : 
     664             :   // --------------------------------------------------------------------------
     665             :   // [Construction / Destruction]
     666             :   // --------------------------------------------------------------------------
     667             : 
     668             :   //! Create a new `CBData` instance.
     669           0 :   ASMJIT_INLINE CBData(CodeBuilder* cb, void* data, uint32_t size) noexcept : CBNode(cb, kNodeData) {
     670           0 :     if (size <= kInlineBufferSize) {
     671           0 :       if (data) ::memcpy(_buf, data, size);
     672             :     }
     673             :     else {
     674           0 :       _externalPtr = static_cast<uint8_t*>(data);
     675             :     }
     676           0 :     _size = size;
     677             :   }
     678             : 
     679             :   //! Destroy the `CBData` instance (NEVER CALLED).
     680             :   ASMJIT_INLINE ~CBData() noexcept {}
     681             : 
     682             :   // --------------------------------------------------------------------------
     683             :   // [Accessors]
     684             :   // --------------------------------------------------------------------------
     685             : 
     686             :   //! Get size of the data.
     687           0 :   uint32_t getSize() const noexcept { return _size; }
     688             :   //! Get pointer to the data.
     689           0 :   uint8_t* getData() const noexcept { return _size <= kInlineBufferSize ? const_cast<uint8_t*>(_buf) : _externalPtr; }
     690             : 
     691             :   // --------------------------------------------------------------------------
     692             :   // [Members]
     693             :   // --------------------------------------------------------------------------
     694             : 
     695             :   union {
     696             :     struct {
     697             :       uint8_t _buf[kInlineBufferSize];   //!< Embedded data buffer.
     698             :       uint32_t _size;                    //!< Size of the data.
     699             :     };
     700             :     struct {
     701             :       uint8_t* _externalPtr;             //!< Pointer to external data.
     702             :     };
     703             :   };
     704             : };
     705             : 
     706             : // ============================================================================
     707             : // [asmjit::CBAlign]
     708             : // ============================================================================
     709             : 
     710             : //! Align directive (CodeBuilder).
     711             : //!
     712             : //! Wraps `.align` directive.
     713             : class CBAlign : public CBNode {
     714             : public:
     715             :   ASMJIT_NONCOPYABLE(CBAlign)
     716             : 
     717             :   // --------------------------------------------------------------------------
     718             :   // [Construction / Destruction]
     719             :   // --------------------------------------------------------------------------
     720             : 
     721             :   //! Create a new `CBAlign` instance.
     722             :   ASMJIT_INLINE CBAlign(CodeBuilder* cb, uint32_t mode, uint32_t alignment) noexcept
     723           0 :     : CBNode(cb, kNodeAlign),
     724           0 :       _mode(mode),
     725           0 :       _alignment(alignment) {}
     726             :   //! Destroy the `CBAlign` instance (NEVER CALLED).
     727             :   ASMJIT_INLINE ~CBAlign() noexcept {}
     728             : 
     729             :   // --------------------------------------------------------------------------
     730             :   // [Accessors]
     731             :   // --------------------------------------------------------------------------
     732             : 
     733             :   //! Get align mode.
     734           0 :   ASMJIT_INLINE uint32_t getMode() const noexcept { return _mode; }
     735             :   //! Set align mode.
     736             :   ASMJIT_INLINE void setMode(uint32_t mode) noexcept { _mode = mode; }
     737             : 
     738             :   //! Get align offset in bytes.
     739           0 :   ASMJIT_INLINE uint32_t getAlignment() const noexcept { return _alignment; }
     740             :   //! Set align offset in bytes to `offset`.
     741             :   ASMJIT_INLINE void setAlignment(uint32_t alignment) noexcept { _alignment = alignment; }
     742             : 
     743             :   // --------------------------------------------------------------------------
     744             :   // [Members]
     745             :   // --------------------------------------------------------------------------
     746             : 
     747             :   uint32_t _mode;                        //!< Align mode, see \ref AlignMode.
     748             :   uint32_t _alignment;                   //!< Alignment (in bytes).
     749             : };
     750             : 
     751             : // ============================================================================
     752             : // [asmjit::CBLabel]
     753             : // ============================================================================
     754             : 
     755             : //! Label (CodeBuilder).
     756             : class CBLabel : public CBNode {
     757             : public:
     758             :   ASMJIT_NONCOPYABLE(CBLabel)
     759             : 
     760             :   // --------------------------------------------------------------------------
     761             :   // [Construction / Destruction]
     762             :   // --------------------------------------------------------------------------
     763             : 
     764             :   //! Create a new `CBLabel` instance.
     765             :   ASMJIT_INLINE CBLabel(CodeBuilder* cb, uint32_t id = kInvalidValue) noexcept
     766        3888 :     : CBNode(cb, kNodeLabel),
     767        3888 :       _id(id),
     768        3888 :       _numRefs(0),
     769        3888 :       _from(nullptr) {}
     770             :   //! Destroy the `CBLabel` instance (NEVER CALLED).
     771             :   ASMJIT_INLINE ~CBLabel() noexcept {}
     772             : 
     773             :   // --------------------------------------------------------------------------
     774             :   // [Accessors]
     775             :   // --------------------------------------------------------------------------
     776             : 
     777             :   //! Get the label id.
     778           0 :   ASMJIT_INLINE uint32_t getId() const noexcept { return _id; }
     779             :   //! Get the label as `Label` operand.
     780        3888 :   ASMJIT_INLINE Label getLabel() const noexcept { return Label(_id); }
     781             : 
     782             :   //! Get first jmp instruction.
     783           0 :   ASMJIT_INLINE CBJump* getFrom() const noexcept { return _from; }
     784             : 
     785             :   //! Get number of jumps to this target.
     786           0 :   ASMJIT_INLINE uint32_t getNumRefs() const noexcept { return _numRefs; }
     787             :   //! Set number of jumps to this target.
     788             :   ASMJIT_INLINE void setNumRefs(uint32_t i) noexcept { _numRefs = i; }
     789             : 
     790             :   //! Add number of jumps to this target.
     791           0 :   ASMJIT_INLINE void addNumRefs(uint32_t i = 1) noexcept { _numRefs += i; }
     792             :   //! Subtract number of jumps to this target.
     793           0 :   ASMJIT_INLINE void subNumRefs(uint32_t i = 1) noexcept { _numRefs -= i; }
     794             : 
     795             :   // --------------------------------------------------------------------------
     796             :   // [Members]
     797             :   // --------------------------------------------------------------------------
     798             : 
     799             :   uint32_t _id;                          //!< Label id.
     800             :   uint32_t _numRefs;                     //!< Count of jumps here.
     801             :   CBJump* _from;                         //!< Linked-list of nodes that can jump here.
     802             : };
     803             : 
     804             : // ============================================================================
     805             : // [asmjit::CBLabelData]
     806             : // ============================================================================
     807             : 
     808             : class CBLabelData : public CBNode {
     809             : public:
     810             :   ASMJIT_NONCOPYABLE(CBLabelData)
     811             : 
     812             :   // --------------------------------------------------------------------------
     813             :   // [Construction / Destruction]
     814             :   // --------------------------------------------------------------------------
     815             : 
     816             :   //! Create a new `CBLabelData` instance.
     817             :   ASMJIT_INLINE CBLabelData(CodeBuilder* cb, uint32_t id = kInvalidValue) noexcept
     818           0 :     : CBNode(cb, kNodeLabelData),
     819           0 :       _id(id) {}
     820             : 
     821             :   //! Destroy the `CBLabelData` instance (NEVER CALLED).
     822             :   ASMJIT_INLINE ~CBLabelData() noexcept {}
     823             : 
     824             :   // --------------------------------------------------------------------------
     825             :   // [Interface]
     826             :   // --------------------------------------------------------------------------
     827             : 
     828             :   //! Get the label id.
     829             :   ASMJIT_INLINE uint32_t getId() const noexcept { return _id; }
     830             :   //! Get the label as `Label` operand.
     831           0 :   ASMJIT_INLINE Label getLabel() const noexcept { return Label(_id); }
     832             : 
     833             :   // --------------------------------------------------------------------------
     834             :   // [Members]
     835             :   // --------------------------------------------------------------------------
     836             : 
     837             :   uint32_t _id;
     838             : };
     839             : 
     840             : // ============================================================================
     841             : // [asmjit::CBConstPool]
     842             : // ============================================================================
     843             : 
     844             : class CBConstPool : public CBLabel {
     845             : public:
     846             :   ASMJIT_NONCOPYABLE(CBConstPool)
     847             : 
     848             :   // --------------------------------------------------------------------------
     849             :   // [Construction / Destruction]
     850             :   // --------------------------------------------------------------------------
     851             : 
     852             :   //! Create a new `CBConstPool` instance.
     853             :   ASMJIT_INLINE CBConstPool(CodeBuilder* cb, uint32_t id = kInvalidValue) noexcept
     854           0 :     : CBLabel(cb, id),
     855           0 :       _constPool(&cb->_cbBaseZone) { _type = kNodeConstPool; }
     856             : 
     857             :   //! Destroy the `CBConstPool` instance (NEVER CALLED).
     858             :   ASMJIT_INLINE ~CBConstPool() noexcept {}
     859             : 
     860             :   // --------------------------------------------------------------------------
     861             :   // [Interface]
     862             :   // --------------------------------------------------------------------------
     863             : 
     864           0 :   ASMJIT_INLINE ConstPool& getConstPool() noexcept { return _constPool; }
     865             :   ASMJIT_INLINE const ConstPool& getConstPool() const noexcept { return _constPool; }
     866             : 
     867             :   //! Get whether the constant-pool is empty.
     868             :   ASMJIT_INLINE bool isEmpty() const noexcept { return _constPool.isEmpty(); }
     869             :   //! Get the size of the constant-pool in bytes.
     870             :   ASMJIT_INLINE size_t getSize() const noexcept { return _constPool.getSize(); }
     871             :   //! Get minimum alignment.
     872             :   ASMJIT_INLINE size_t getAlignment() const noexcept { return _constPool.getAlignment(); }
     873             : 
     874             :   //! See \ref ConstPool::add().
     875             :   ASMJIT_INLINE Error add(const void* data, size_t size, size_t& dstOffset) noexcept {
     876           0 :     return _constPool.add(data, size, dstOffset);
     877             :   }
     878             : 
     879             :   // --------------------------------------------------------------------------
     880             :   // [Members]
     881             :   // --------------------------------------------------------------------------
     882             : 
     883             :   ConstPool _constPool;
     884             : };
     885             : 
     886             : // ============================================================================
     887             : // [asmjit::CBComment]
     888             : // ============================================================================
     889             : 
     890             : //! Comment (CodeBuilder).
     891             : class CBComment : public CBNode {
     892             : public:
     893             :   ASMJIT_NONCOPYABLE(CBComment)
     894             : 
     895             :   // --------------------------------------------------------------------------
     896             :   // [Construction / Destruction]
     897             :   // --------------------------------------------------------------------------
     898             : 
     899             :   //! Create a new `CBComment` instance.
     900             :   ASMJIT_INLINE CBComment(CodeBuilder* cb, const char* comment) noexcept : CBNode(cb, kNodeComment) {
     901             :     orFlags(kFlagIsRemovable | kFlagIsInformative);
     902           0 :     _inlineComment = comment;
     903             :   }
     904             : 
     905             :   //! Destroy the `CBComment` instance (NEVER CALLED).
     906             :   ASMJIT_INLINE ~CBComment() noexcept {}
     907             : };
     908             : 
     909             : // ============================================================================
     910             : // [asmjit::CBSentinel]
     911             : // ============================================================================
     912             : 
     913             : //! Sentinel (CodeBuilder).
     914             : //!
     915             : //! Sentinel is a marker that is completely ignored by the code builder. It's
     916             : //! used to remember a position in a code as it never gets removed by any pass.
     917             : class CBSentinel : public CBNode {
     918             : public:
     919             :   ASMJIT_NONCOPYABLE(CBSentinel)
     920             : 
     921             :   // --------------------------------------------------------------------------
     922             :   // [Construction / Destruction]
     923             :   // --------------------------------------------------------------------------
     924             : 
     925             :   //! Create a new `CBSentinel` instance.
     926             :   ASMJIT_INLINE CBSentinel(CodeBuilder* cb) noexcept : CBNode(cb, kNodeSentinel) {}
     927             :   //! Destroy the `CBSentinel` instance (NEVER CALLED).
     928             :   ASMJIT_INLINE ~CBSentinel() noexcept {}
     929             : };
     930             : 
     931             : //! \}
     932             : 
     933             : } // asmjit namespace
     934             : } // namespace PLMD
     935             : 
     936             : // [Api-End]
     937             : #include "./asmjit_apiend.h"
     938             : 
     939             : // [Guard]
     940             : #endif // !ASMJIT_DISABLE_BUILDER
     941             : #endif // _ASMJIT_BASE_CODEBUILDER_H
     942             : #pragma GCC diagnostic pop
     943             : #endif // __PLUMED_HAS_ASMJIT
     944             : #endif

Generated by: LCOV version 1.15