LCOV - code coverage report
Current view: top level - asmjit - codecompiler.h (source / functions) Hit Total Coverage
Test: plumed test coverage (other modules) Lines: 41 64 64.1 %
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_codecompiler_h
      21             : #define __PLUMED_asmjit_codecompiler_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_CODECOMPILER_H
      33             : #define _ASMJIT_BASE_CODECOMPILER_H
      34             : 
      35             : #include "./asmjit_build.h"
      36             : #if !defined(ASMJIT_DISABLE_COMPILER)
      37             : 
      38             : // [Dependencies]
      39             : #include "./assembler.h"
      40             : #include "./codebuilder.h"
      41             : #include "./constpool.h"
      42             : #include "./func.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             : struct VirtReg;
      58             : struct TiedReg;
      59             : struct RAState;
      60             : struct RACell;
      61             : 
      62             : //! \addtogroup asmjit_base
      63             : //! \{
      64             : 
      65             : // ============================================================================
      66             : // [asmjit::ConstScope]
      67             : // ============================================================================
      68             : 
      69             : //! Scope of the constant.
      70             : ASMJIT_ENUM(ConstScope) {
      71             :   //! Local constant, always embedded right after the current function.
      72             :   kConstScopeLocal = 0,
      73             :   //! Global constant, embedded at the end of the currently compiled code.
      74             :   kConstScopeGlobal = 1
      75             : };
      76             : 
      77             : // ============================================================================
      78             : // [asmjit::VirtReg]
      79             : // ============================================================================
      80             : 
      81             : //! Virtual register data (CodeCompiler).
      82             : struct VirtReg {
      83             :   //! A state of a virtual register (used during register allocation).
      84             :   ASMJIT_ENUM(State) {
      85             :     kStateNone = 0,                      //!< Not allocated, not used.
      86             :     kStateReg = 1,                       //!< Allocated in register.
      87             :     kStateMem = 2                        //!< Allocated in memory or spilled.
      88             :   };
      89             : 
      90             :   // --------------------------------------------------------------------------
      91             :   // [Accessors]
      92             :   // --------------------------------------------------------------------------
      93             : 
      94             :   //! Get the virtual-register id.
      95       32168 :   ASMJIT_INLINE uint32_t getId() const noexcept { return _id; }
      96             :   //! Get virtual-register's name.
      97           0 :   ASMJIT_INLINE const char* getName() const noexcept { return _name; }
      98             : 
      99             :   //! Get a physical register type.
     100             :   ASMJIT_INLINE uint32_t getType() const noexcept { return _regInfo.getType(); }
     101             :   //! Get a physical register kind.
     102             :   ASMJIT_INLINE uint32_t getKind() const noexcept { return _regInfo.getKind(); }
     103             :   //! Get a physical register size.
     104             :   ASMJIT_INLINE uint32_t getRegSize() const noexcept { return _regInfo.getSize(); }
     105             :   //! Get a register signature of this virtual register.
     106             :   ASMJIT_INLINE uint32_t getSignature() const noexcept { return _regInfo.getSignature(); }
     107             : 
     108             :   //! Get a register's type-id, see \ref TypeId.
     109        9084 :   ASMJIT_INLINE uint32_t getTypeId() const noexcept { return _typeId; }
     110             : 
     111             :   //! Get virtual-register's size.
     112       25856 :   ASMJIT_INLINE uint32_t getSize() const noexcept { return _size; }
     113             :   //! Get virtual-register's alignment.
     114           0 :   ASMJIT_INLINE uint32_t getAlignment() const noexcept { return _alignment; }
     115             : 
     116             :   //! Get the virtual-register  priority, used by compiler to decide which variable to spill.
     117           0 :   ASMJIT_INLINE uint32_t getPriority() const noexcept { return _priority; }
     118             :   //! Set the virtual-register  priority.
     119             :   ASMJIT_INLINE void setPriority(uint32_t priority) noexcept {
     120             :     ASMJIT_ASSERT(priority <= 0xFF);
     121             :     _priority = static_cast<uint8_t>(priority);
     122             :   }
     123             : 
     124             :   //! Get variable state, only used by `RAPass`.
     125        4972 :   ASMJIT_INLINE uint32_t getState() const noexcept { return _state; }
     126             :   //! Set variable state, only used by `RAPass`.
     127             :   ASMJIT_INLINE void setState(uint32_t state) {
     128             :     ASMJIT_ASSERT(state <= 0xFF);
     129           0 :     _state = static_cast<uint8_t>(state);
     130       24694 :   }
     131             : 
     132             :   //! Get register index.
     133      181318 :   ASMJIT_INLINE uint32_t getPhysId() const noexcept { return _physId; }
     134             :   //! Set register index.
     135             :   ASMJIT_INLINE void setPhysId(uint32_t physId) {
     136             :     ASMJIT_ASSERT(physId <= Globals::kInvalidRegId);
     137         656 :     _physId = static_cast<uint8_t>(physId);
     138             :   }
     139             :   //! Reset register index.
     140             :   ASMJIT_INLINE void resetPhysId() {
     141       49960 :     _physId = static_cast<uint8_t>(Globals::kInvalidRegId);
     142             :   }
     143             : 
     144             :   //! Get home registers mask.
     145       26376 :   ASMJIT_INLINE uint32_t getHomeMask() const { return _homeMask; }
     146             :   //! Add a home register index to the home registers mask.
     147        4424 :   ASMJIT_INLINE void addHomeId(uint32_t physId) { _homeMask |= Utils::mask(physId); }
     148             : 
     149       27864 :   ASMJIT_INLINE bool isFixed() const noexcept { return static_cast<bool>(_isFixed); }
     150             : 
     151             :   //! Get whether the VirtReg is only memory allocated on the stack.
     152       10072 :   ASMJIT_INLINE bool isStack() const noexcept { return static_cast<bool>(_isStack); }
     153             : 
     154             :   //! Get whether to save variable when it's unused (spill).
     155             :   ASMJIT_INLINE bool saveOnUnuse() const noexcept { return static_cast<bool>(_saveOnUnuse); }
     156             : 
     157             :   //! Get whether the variable was changed.
     158       10458 :   ASMJIT_INLINE bool isModified() const noexcept { return static_cast<bool>(_modified); }
     159             :   //! Set whether the variable was changed.
     160       88716 :   ASMJIT_INLINE void setModified(bool modified) noexcept { _modified = modified; }
     161             : 
     162             :   //! Get home memory offset.
     163             :   ASMJIT_INLINE int32_t getMemOffset() const noexcept { return _memOffset; }
     164             :   //! Set home memory offset.
     165             :   ASMJIT_INLINE void setMemOffset(int32_t offset) noexcept { _memOffset = offset; }
     166             : 
     167             :   //! Get home memory cell.
     168        8428 :   ASMJIT_INLINE RACell* getMemCell() const noexcept { return _memCell; }
     169             :   //! Set home memory cell.
     170             :   ASMJIT_INLINE void setMemCell(RACell* cell) noexcept { _memCell = cell; }
     171             : 
     172             :   // --------------------------------------------------------------------------
     173             :   // [Members]
     174             :   // --------------------------------------------------------------------------
     175             : 
     176             :   uint32_t _id;                          //!< Virtual register id.
     177             :   RegInfo _regInfo;                      //!< Physical register info & signature.
     178             :   const char* _name;                     //!< Virtual name (user provided).
     179             :   uint32_t _size;                        //!< Virtual size (can be smaller than `regInfo._size`).
     180             :   uint8_t _typeId;                       //!< Type-id.
     181             :   uint8_t _alignment;                    //!< Register's natural alignment (for spilling).
     182             :   uint8_t _priority;                     //!< Allocation priority (hint for RAPass that can be ignored).
     183             :   uint8_t _isFixed : 1;                  //!< True if this is a fixed register, never reallocated.
     184             :   uint8_t _isStack : 1;                  //!< True if the virtual register is only used as a stack.
     185             :   uint8_t _isMaterialized : 1;           //!< Register is constant that is easily created by a single instruction.
     186             :   uint8_t _saveOnUnuse : 1;              //!< Save on unuse (at end of the variable scope).
     187             : 
     188             :   // -------------------------------------------------------------------------
     189             :   // The following members are used exclusively by RAPass. They are initialized
     190             :   // when the VirtReg is created and then changed during RAPass.
     191             :   // -------------------------------------------------------------------------
     192             : 
     193             :   uint32_t _raId;                        //!< Register allocator work-id (used by RAPass).
     194             :   int32_t _memOffset;                    //!< Home memory offset.
     195             :   uint32_t _homeMask;                    //!< Mask of all registers variable has been allocated to.
     196             : 
     197             :   uint8_t _state;                        //!< Variable state (connected with actual `RAState)`.
     198             :   uint8_t _physId;                       //!< Actual register index (only used by `RAPass)`, during translate.
     199             :   uint8_t _modified;                     //!< Whether variable was changed (connected with actual `RAState)`.
     200             : 
     201             :   RACell* _memCell;                      //!< Home memory cell, used by `RAPass` (initially nullptr).
     202             : 
     203             :   //! Temporary link to TiedReg* used by the `RAPass` used in
     204             :   //! various phases, but always set back to nullptr when finished.
     205             :   //!
     206             :   //! This temporary data is designed to be used by algorithms that need to
     207             :   //! store some data into variables themselves during compilation. But it's
     208             :   //! expected that after variable is compiled & translated the data is set
     209             :   //! back to zero/null. Initial value is nullptr.
     210             :   TiedReg* _tied;
     211             : };
     212             : 
     213             : // ============================================================================
     214             : // [asmjit::CCHint]
     215             : // ============================================================================
     216             : 
     217             : //! Hint for register allocator (CodeCompiler).
     218             : class CCHint : public CBNode {
     219             : public:
     220             :   ASMJIT_NONCOPYABLE(CCHint)
     221             : 
     222             :   //! Hint type.
     223             :   ASMJIT_ENUM(Hint) {
     224             :     //! Alloc to physical reg.
     225             :     kHintAlloc = 0,
     226             :     //! Spill to memory.
     227             :     kHintSpill = 1,
     228             :     //! Save if modified.
     229             :     kHintSave = 2,
     230             :     //! Save if modified and mark it as unused.
     231             :     kHintSaveAndUnuse = 3,
     232             :     //! Mark as unused.
     233             :     kHintUnuse = 4
     234             :   };
     235             : 
     236             :   // --------------------------------------------------------------------------
     237             :   // [Construction / Destruction]
     238             :   // --------------------------------------------------------------------------
     239             : 
     240             :   //! Create a new `CCHint` instance.
     241           0 :   ASMJIT_INLINE CCHint(CodeBuilder* cb, VirtReg* vreg, uint32_t hint, uint32_t value) noexcept : CBNode(cb, kNodeHint) {
     242             :     orFlags(kFlagIsRemovable | kFlagIsInformative);
     243           0 :     _vreg = vreg;
     244           0 :     _hint = hint;
     245           0 :     _value = value;
     246             :   }
     247             : 
     248             :   //! Destroy the `CCHint` instance (NEVER CALLED).
     249             :   ASMJIT_INLINE ~CCHint() noexcept {}
     250             : 
     251             :   // --------------------------------------------------------------------------
     252             :   // [Accessors]
     253             :   // --------------------------------------------------------------------------
     254             : 
     255             :   //! Get variable.
     256           0 :   ASMJIT_INLINE VirtReg* getVReg() const noexcept { return _vreg; }
     257             : 
     258             :   //! Get hint it, see \ref Hint.
     259           0 :   ASMJIT_INLINE uint32_t getHint() const noexcept { return _hint; }
     260             :   //! Set hint it, see \ref Hint.
     261             :   ASMJIT_INLINE void setHint(uint32_t hint) noexcept { _hint = hint; }
     262             : 
     263             :   //! Get hint value.
     264           0 :   ASMJIT_INLINE uint32_t getValue() const noexcept { return _value; }
     265             :   //! Set hint value.
     266             :   ASMJIT_INLINE void setValue(uint32_t value) noexcept { _value = value; }
     267             : 
     268             :   // --------------------------------------------------------------------------
     269             :   // [Members]
     270             :   // --------------------------------------------------------------------------
     271             : 
     272             :   //! Variable.
     273             :   VirtReg* _vreg;
     274             :   //! Hint id.
     275             :   uint32_t _hint;
     276             :   //! Value.
     277             :   uint32_t _value;
     278             : };
     279             : 
     280             : // ============================================================================
     281             : // [asmjit::CCFunc]
     282             : // ============================================================================
     283             : 
     284             : //! Function entry (CodeCompiler).
     285             : class CCFunc : public CBLabel {
     286             : public:
     287             :   ASMJIT_NONCOPYABLE(CCFunc)
     288             : 
     289             :   // --------------------------------------------------------------------------
     290             :   // [Construction / Destruction]
     291             :   // --------------------------------------------------------------------------
     292             : 
     293             :   //! Create a new `CCFunc` instance.
     294             :   //!
     295             :   //! Always use `CodeCompiler::addFunc()` to create \ref CCFunc.
     296             :   ASMJIT_INLINE CCFunc(CodeBuilder* cb) noexcept
     297        1944 :     : CBLabel(cb),
     298        1944 :       _funcDetail(),
     299        1944 :       _frameInfo(),
     300        1944 :       _exitNode(nullptr),
     301        1944 :       _end(nullptr),
     302        1944 :       _args(nullptr),
     303        1944 :       _isFinished(false) {
     304             : 
     305        1944 :     _type = kNodeFunc;
     306             :   }
     307             : 
     308             :   //! Destroy the `CCFunc` instance (NEVER CALLED).
     309             :   ASMJIT_INLINE ~CCFunc() noexcept {}
     310             : 
     311             :   // --------------------------------------------------------------------------
     312             :   // [Accessors]
     313             :   // --------------------------------------------------------------------------
     314             : 
     315             :   //! Get function exit `CBLabel`.
     316        7776 :   ASMJIT_INLINE CBLabel* getExitNode() const noexcept { return _exitNode; }
     317             :   //! Get function exit label.
     318             :   ASMJIT_INLINE Label getExitLabel() const noexcept { return _exitNode->getLabel(); }
     319             : 
     320             :   //! Get "End of Func" sentinel.
     321        7776 :   ASMJIT_INLINE CBSentinel* getEnd() const noexcept { return _end; }
     322             : 
     323             :   //! Get function declaration.
     324        1944 :   ASMJIT_INLINE FuncDetail& getDetail() noexcept { return _funcDetail; }
     325             :   //! Get function declaration.
     326           0 :   ASMJIT_INLINE const FuncDetail& getDetail() const noexcept { return _funcDetail; }
     327             : 
     328             :   //! Get function declaration.
     329        1944 :   ASMJIT_INLINE FuncFrameInfo& getFrameInfo() noexcept { return _frameInfo; }
     330             :   //! Get function declaration.
     331             :   ASMJIT_INLINE const FuncFrameInfo& getFrameInfo() const noexcept { return _frameInfo; }
     332             : 
     333             :   //! Get arguments count.
     334             :   ASMJIT_INLINE uint32_t getArgCount() const noexcept { return _funcDetail.getArgCount(); }
     335             :   //! Get returns count.
     336             :   ASMJIT_INLINE uint32_t getRetCount() const noexcept { return _funcDetail.getRetCount(); }
     337             : 
     338             :   //! Get arguments list.
     339           0 :   ASMJIT_INLINE VirtReg** getArgs() const noexcept { return _args; }
     340             : 
     341             :   //! Get argument at `i`.
     342             :   ASMJIT_INLINE VirtReg* getArg(uint32_t i) const noexcept {
     343             :     ASMJIT_ASSERT(i < getArgCount());
     344           0 :     return _args[i];
     345             :   }
     346             : 
     347             :   //! Set argument at `i`.
     348             :   ASMJIT_INLINE void setArg(uint32_t i, VirtReg* vreg) noexcept {
     349             :     ASMJIT_ASSERT(i < getArgCount());
     350           0 :     _args[i] = vreg;
     351             :   }
     352             : 
     353             :   //! Reset argument at `i`.
     354             :   ASMJIT_INLINE void resetArg(uint32_t i) noexcept {
     355             :     ASMJIT_ASSERT(i < getArgCount());
     356             :     _args[i] = nullptr;
     357             :   }
     358             : 
     359             :   ASMJIT_INLINE uint32_t getAttributes() const noexcept { return _frameInfo.getAttributes(); }
     360             :   ASMJIT_INLINE void addAttributes(uint32_t attrs) noexcept { _frameInfo.addAttributes(attrs); }
     361             : 
     362             :   // --------------------------------------------------------------------------
     363             :   // [Members]
     364             :   // --------------------------------------------------------------------------
     365             : 
     366             :   FuncDetail _funcDetail;                //!< Function detail.
     367             :   FuncFrameInfo _frameInfo;              //!< Function frame information.
     368             : 
     369             :   CBLabel* _exitNode;                    //!< Function exit.
     370             :   CBSentinel* _end;                      //!< Function end.
     371             : 
     372             :   VirtReg** _args;                       //!< Arguments array as `VirtReg`.
     373             : 
     374             :   //! Function was finished by `Compiler::endFunc()`.
     375             :   uint8_t _isFinished;
     376             : };
     377             : 
     378             : // ============================================================================
     379             : // [asmjit::CCFuncRet]
     380             : // ============================================================================
     381             : 
     382             : //! Function return (CodeCompiler).
     383             : class CCFuncRet : public CBNode {
     384             : public:
     385             :   ASMJIT_NONCOPYABLE(CCFuncRet)
     386             : 
     387             :   // --------------------------------------------------------------------------
     388             :   // [Construction / Destruction]
     389             :   // --------------------------------------------------------------------------
     390             : 
     391             :   //! Create a new `CCFuncRet` instance.
     392        1944 :   ASMJIT_INLINE CCFuncRet(CodeBuilder* cb, const Operand_& o0, const Operand_& o1) noexcept : CBNode(cb, kNodeFuncExit) {
     393             :     orFlags(kFlagIsRet);
     394        1944 :     _ret[0].copyFrom(o0);
     395        1944 :     _ret[1].copyFrom(o1);
     396             :   }
     397             : 
     398             :   //! Destroy the `CCFuncRet` instance (NEVER CALLED).
     399             :   ASMJIT_INLINE ~CCFuncRet() noexcept {}
     400             : 
     401             :   // --------------------------------------------------------------------------
     402             :   // [Accessors]
     403             :   // --------------------------------------------------------------------------
     404             : 
     405             :   //! Get the first return operand.
     406             :   ASMJIT_INLINE Operand& getFirst() noexcept { return static_cast<Operand&>(_ret[0]); }
     407             :   //! \overload
     408             :   ASMJIT_INLINE const Operand& getFirst() const noexcept { return static_cast<const Operand&>(_ret[0]); }
     409             : 
     410             :   //! Get the second return operand.
     411             :   ASMJIT_INLINE Operand& getSecond() noexcept { return static_cast<Operand&>(_ret[1]); }
     412             :    //! \overload
     413             :   ASMJIT_INLINE const Operand& getSecond() const noexcept { return static_cast<const Operand&>(_ret[1]); }
     414             : 
     415             :   // --------------------------------------------------------------------------
     416             :   // [Members]
     417             :   // --------------------------------------------------------------------------
     418             : 
     419             :   //! Return operands.
     420             :   Operand_ _ret[2];
     421             : };
     422             : 
     423             : // ============================================================================
     424             : // [asmjit::CCFuncCall]
     425             : // ============================================================================
     426             : 
     427             : //! Function call (CodeCompiler).
     428             : class CCFuncCall : public CBInst {
     429             : public:
     430             :   ASMJIT_NONCOPYABLE(CCFuncCall)
     431             : 
     432             :   // --------------------------------------------------------------------------
     433             :   // [Construction / Destruction]
     434             :   // --------------------------------------------------------------------------
     435             : 
     436             :   //! Create a new `CCFuncCall` instance.
     437             :   ASMJIT_INLINE CCFuncCall(CodeBuilder* cb, uint32_t instId, uint32_t options, Operand* opArray, uint32_t opCount) noexcept
     438        1636 :     : CBInst(cb, instId, options, opArray, opCount),
     439        1636 :       _funcDetail(),
     440        1636 :       _args(nullptr) {
     441             : 
     442        1636 :     _type = kNodeFuncCall;
     443             :     _ret[0].reset();
     444             :     _ret[1].reset();
     445             :     orFlags(kFlagIsRemovable);
     446             :   }
     447             : 
     448             :   //! Destroy the `CCFuncCall` instance (NEVER CALLED).
     449             :   ASMJIT_INLINE ~CCFuncCall() noexcept {}
     450             : 
     451             :   // --------------------------------------------------------------------------
     452             :   // [Signature]
     453             :   // --------------------------------------------------------------------------
     454             : 
     455             :   //! Set function signature.
     456             :   ASMJIT_INLINE Error setSignature(const FuncSignature& sign) noexcept {
     457             :     return _funcDetail.init(sign);
     458             :   }
     459             : 
     460             :   // --------------------------------------------------------------------------
     461             :   // [Accessors]
     462             :   // --------------------------------------------------------------------------
     463             : 
     464             :   //! Get function declaration.
     465             :   ASMJIT_INLINE FuncDetail& getDetail() noexcept { return _funcDetail; }
     466             :   //! Get function declaration.
     467             :   ASMJIT_INLINE const FuncDetail& getDetail() const noexcept { return _funcDetail; }
     468             : 
     469             :   //! Get target operand.
     470             :   ASMJIT_INLINE Operand& getTarget() noexcept { return static_cast<Operand&>(_opArray[0]); }
     471             :   //! \overload
     472             :   ASMJIT_INLINE const Operand& getTarget() const noexcept { return static_cast<const Operand&>(_opArray[0]); }
     473             : 
     474             :   //! Get return at `i`.
     475             :   ASMJIT_INLINE Operand& getRet(uint32_t i = 0) noexcept {
     476             :     ASMJIT_ASSERT(i < 2);
     477             :     return static_cast<Operand&>(_ret[i]);
     478             :   }
     479             :   //! \overload
     480             :   ASMJIT_INLINE const Operand& getRet(uint32_t i = 0) const noexcept {
     481             :     ASMJIT_ASSERT(i < 2);
     482             :     return static_cast<const Operand&>(_ret[i]);
     483             :   }
     484             : 
     485             :   //! Get argument at `i`.
     486             :   ASMJIT_INLINE Operand& getArg(uint32_t i) noexcept {
     487             :     ASMJIT_ASSERT(i < kFuncArgCountLoHi);
     488             :     return static_cast<Operand&>(_args[i]);
     489             :   }
     490             :   //! \overload
     491             :   ASMJIT_INLINE const Operand& getArg(uint32_t i) const noexcept {
     492             :     ASMJIT_ASSERT(i < kFuncArgCountLoHi);
     493             :     return static_cast<const Operand&>(_args[i]);
     494             :   }
     495             : 
     496             :   //! Set argument at `i` to `op`.
     497             :   ASMJIT_API bool _setArg(uint32_t i, const Operand_& op) noexcept;
     498             :   //! Set return at `i` to `op`.
     499             :   ASMJIT_API bool _setRet(uint32_t i, const Operand_& op) noexcept;
     500             : 
     501             :   //! Set argument at `i` to `reg`.
     502        1434 :   ASMJIT_INLINE bool setArg(uint32_t i, const Reg& reg) noexcept { return _setArg(i, reg); }
     503             :   //! Set argument at `i` to `imm`.
     504         202 :   ASMJIT_INLINE bool setArg(uint32_t i, const Imm& imm) noexcept { return _setArg(i, imm); }
     505             : 
     506             :   //! Set return at `i` to `var`.
     507        1636 :   ASMJIT_INLINE bool setRet(uint32_t i, const Reg& reg) noexcept { return _setRet(i, reg); }
     508             : 
     509             :   // --------------------------------------------------------------------------
     510             :   // [Members]
     511             :   // --------------------------------------------------------------------------
     512             : 
     513             :   FuncDetail _funcDetail;                //!< Function detail.
     514             :   Operand_ _ret[2];                      //!< Return.
     515             :   Operand_* _args;                       //!< Arguments.
     516             : };
     517             : 
     518             : // ============================================================================
     519             : // [asmjit::CCPushArg]
     520             : // ============================================================================
     521             : 
     522             : //! Push argument before a function call (CodeCompiler).
     523             : class CCPushArg : public CBNode {
     524             : public:
     525             :   ASMJIT_NONCOPYABLE(CCPushArg)
     526             : 
     527             :   // --------------------------------------------------------------------------
     528             :   // [Construction / Destruction]
     529             :   // --------------------------------------------------------------------------
     530             : 
     531             :   //! Create a new `CCPushArg` instance.
     532             :   ASMJIT_INLINE CCPushArg(CodeBuilder* cb, CCFuncCall* call, VirtReg* src, VirtReg* cvt) noexcept
     533           0 :     : CBNode(cb, kNodePushArg),
     534           0 :       _call(call),
     535           0 :       _src(src),
     536           0 :       _cvt(cvt),
     537           0 :       _args(0) {
     538             :     orFlags(kFlagIsRemovable);
     539             :   }
     540             : 
     541             :   //! Destroy the `CCPushArg` instance.
     542             :   ASMJIT_INLINE ~CCPushArg() noexcept {}
     543             : 
     544             :   // --------------------------------------------------------------------------
     545             :   // [Accessors]
     546             :   // --------------------------------------------------------------------------
     547             : 
     548             :   //! Get the associated function-call.
     549           0 :   ASMJIT_INLINE CCFuncCall* getCall() const noexcept { return _call; }
     550             :   //! Get source variable.
     551           0 :   ASMJIT_INLINE VirtReg* getSrcReg() const noexcept { return _src; }
     552             :   //! Get conversion variable.
     553           0 :   ASMJIT_INLINE VirtReg* getCvtReg() const noexcept { return _cvt; }
     554             : 
     555             :   // --------------------------------------------------------------------------
     556             :   // [Members]
     557             :   // --------------------------------------------------------------------------
     558             : 
     559             :   CCFuncCall* _call;                     //!< Associated `CCFuncCall`.
     560             :   VirtReg* _src;                         //!< Source variable.
     561             :   VirtReg* _cvt;                         //!< Temporary variable used for conversion (or null).
     562             :   uint32_t _args;                        //!< Affected arguments bit-array.
     563             : };
     564             : 
     565             : // ============================================================================
     566             : // [asmjit::CodeCompiler]
     567             : // ============================================================================
     568             : 
     569             : //! Code emitter that uses virtual registers and performs register allocation.
     570             : //!
     571             : //! Compiler is a high-level code-generation tool that provides register
     572             : //! allocation and automatic handling of function calling conventions. It was
     573             : //! primarily designed for merging multiple parts of code into a function
     574             : //! without worrying about registers and function calling conventions.
     575             : //!
     576             : //! CodeCompiler can be used, with a minimum effort, to handle 32-bit and 64-bit
     577             : //! code at the same time.
     578             : //!
     579             : //! CodeCompiler is based on CodeBuilder and contains all the features it
     580             : //! provides. It means that the code it stores can be modified (removed, added,
     581             : //! injected) and analyzed. When the code is finalized the compiler can emit
     582             : //! the code into an Assembler to translate the abstract representation into a
     583             : //! machine code.
     584             : class ASMJIT_VIRTAPI CodeCompiler : public CodeBuilder {
     585             : public:
     586             :   ASMJIT_NONCOPYABLE(CodeCompiler)
     587             :   typedef CodeBuilder Base;
     588             : 
     589             :   // --------------------------------------------------------------------------
     590             :   // [Construction / Destruction]
     591             :   // --------------------------------------------------------------------------
     592             : 
     593             :   //! Create a new `CodeCompiler` instance.
     594             :   ASMJIT_API CodeCompiler() noexcept;
     595             :   //! Destroy the `CodeCompiler` instance.
     596             :   ASMJIT_API virtual ~CodeCompiler() noexcept;
     597             : 
     598             :   // --------------------------------------------------------------------------
     599             :   // [Events]
     600             :   // --------------------------------------------------------------------------
     601             : 
     602             :   ASMJIT_API virtual Error onAttach(CodeHolder* code) noexcept override;
     603             :   ASMJIT_API virtual Error onDetach(CodeHolder* code) noexcept override;
     604             : 
     605             :   // --------------------------------------------------------------------------
     606             :   // [Node-Factory]
     607             :   // --------------------------------------------------------------------------
     608             : 
     609             :   //! \internal
     610             :   //!
     611             :   //! Create a new `CCHint`.
     612             :   ASMJIT_API CCHint* newHintNode(Reg& reg, uint32_t hint, uint32_t value) noexcept;
     613             : 
     614             :   // --------------------------------------------------------------------------
     615             :   // [Func]
     616             :   // --------------------------------------------------------------------------
     617             : 
     618             :   //! Get the current function.
     619        1944 :   ASMJIT_INLINE CCFunc* getFunc() const noexcept { return _func; }
     620             : 
     621             :   //! Create a new `CCFunc`.
     622             :   ASMJIT_API CCFunc* newFunc(const FuncSignature& sign) noexcept;
     623             :   //! Add a function `node` to the stream.
     624             :   ASMJIT_API CCFunc* addFunc(CCFunc* func);
     625             :   //! Add a new function.
     626             :   ASMJIT_API CCFunc* addFunc(const FuncSignature& sign);
     627             :   //! Emit a sentinel that marks the end of the current function.
     628             :   ASMJIT_API CBSentinel* endFunc();
     629             : 
     630             :   // --------------------------------------------------------------------------
     631             :   // [Ret]
     632             :   // --------------------------------------------------------------------------
     633             : 
     634             :   //! Create a new `CCFuncRet`.
     635             :   ASMJIT_API CCFuncRet* newRet(const Operand_& o0, const Operand_& o1) noexcept;
     636             :   //! Add a new `CCFuncRet`.
     637             :   ASMJIT_API CCFuncRet* addRet(const Operand_& o0, const Operand_& o1) noexcept;
     638             : 
     639             :   // --------------------------------------------------------------------------
     640             :   // [Call]
     641             :   // --------------------------------------------------------------------------
     642             : 
     643             :   //! Create a new `CCFuncCall`.
     644             :   ASMJIT_API CCFuncCall* newCall(uint32_t instId, const Operand_& o0, const FuncSignature& sign) noexcept;
     645             :   //! Add a new `CCFuncCall`.
     646             :   ASMJIT_API CCFuncCall* addCall(uint32_t instId, const Operand_& o0, const FuncSignature& sign) noexcept;
     647             : 
     648             :   // --------------------------------------------------------------------------
     649             :   // [Args]
     650             :   // --------------------------------------------------------------------------
     651             : 
     652             :   //! Set a function argument at `argIndex` to `reg`.
     653             :   ASMJIT_API Error setArg(uint32_t argIndex, const Reg& reg);
     654             : 
     655             :   // --------------------------------------------------------------------------
     656             :   // [Hint]
     657             :   // --------------------------------------------------------------------------
     658             : 
     659             :   //! Emit a new hint (purely informational node).
     660             :   ASMJIT_API Error _hint(Reg& reg, uint32_t hint, uint32_t value);
     661             : 
     662             :   // --------------------------------------------------------------------------
     663             :   // [VirtReg / Stack]
     664             :   // --------------------------------------------------------------------------
     665             : 
     666             :   //! Create a new virtual register representing the given `vti` and `signature`.
     667             :   //!
     668             :   //! This function accepts either register type representing a machine-specific
     669             :   //! register, like `X86Reg`, or RegTag representation, which represents
     670             :   //! machine independent register, and from the machine-specific register
     671             :   //! is deduced.
     672             :   ASMJIT_API VirtReg* newVirtReg(uint32_t typeId, uint32_t signature, const char* name) noexcept;
     673             : 
     674             :   ASMJIT_API Error _newReg(Reg& out, uint32_t typeId, const char* name);
     675             :   ASMJIT_API Error _newReg(Reg& out, uint32_t typeId, const char* nameFmt, va_list ap);
     676             : 
     677             :   ASMJIT_API Error _newReg(Reg& out, const Reg& ref, const char* name);
     678             :   ASMJIT_API Error _newReg(Reg& out, const Reg& ref, const char* nameFmt, va_list ap);
     679             : 
     680             :   ASMJIT_API Error _newStack(Mem& out, uint32_t size, uint32_t alignment, const char* name);
     681             :   ASMJIT_API Error _newConst(Mem& out, uint32_t scope, const void* data, size_t size);
     682             : 
     683             :   // --------------------------------------------------------------------------
     684             :   // [VirtReg]
     685             :   // --------------------------------------------------------------------------
     686             : 
     687             :   //! Get whether the virtual register `r` is valid.
     688             :   ASMJIT_INLINE bool isVirtRegValid(const Reg& reg) const noexcept {
     689             :     return isVirtRegValid(reg.getId());
     690             :   }
     691             :   //! \overload
     692             :   ASMJIT_INLINE bool isVirtRegValid(uint32_t id) const noexcept {
     693       12136 :     size_t index = Operand::unpackId(id);
     694             :     return index < _vRegArray.getLength();
     695             :   }
     696             : 
     697             :   //! Get \ref VirtReg associated with the given `r`.
     698             :   ASMJIT_INLINE VirtReg* getVirtReg(const Reg& reg) const noexcept {
     699             :     return getVirtRegById(reg.getId());
     700             :   }
     701             :   //! Get \ref VirtReg associated with the given `id`.
     702             :   ASMJIT_INLINE VirtReg* getVirtRegById(uint32_t id) const noexcept {
     703             :     ASMJIT_ASSERT(id != kInvalidValue);
     704      116154 :     size_t index = Operand::unpackId(id);
     705             : 
     706             :     ASMJIT_ASSERT(index < _vRegArray.getLength());
     707      128290 :     return _vRegArray[index];
     708             :   }
     709             : 
     710             :   //! Get an array of all virtual registers managed by CodeCompiler.
     711             :   ASMJIT_INLINE const ZoneVector<VirtReg*>& getVirtRegArray() const noexcept { return _vRegArray; }
     712             : 
     713             :   //! Alloc a virtual register `reg`.
     714             :   ASMJIT_API Error alloc(Reg& reg);
     715             :   //! Alloc a virtual register `reg` using `physId` as a register id.
     716             :   ASMJIT_API Error alloc(Reg& reg, uint32_t physId);
     717             :   //! Alloc a virtual register `reg` using `ref` as a register operand.
     718             :   ASMJIT_API Error alloc(Reg& reg, const Reg& ref);
     719             :   //! Spill a virtual register `reg`.
     720             :   ASMJIT_API Error spill(Reg& reg);
     721             :   //! Save a virtual register `reg` if the status is `modified` at this point.
     722             :   ASMJIT_API Error save(Reg& reg);
     723             :   //! Unuse a virtual register `reg`.
     724             :   ASMJIT_API Error unuse(Reg& reg);
     725             : 
     726             :   //! Get priority of a virtual register `reg`.
     727             :   ASMJIT_API uint32_t getPriority(Reg& reg) const;
     728             :   //! Set priority of variable `reg` to `priority`.
     729             :   ASMJIT_API void setPriority(Reg& reg, uint32_t priority);
     730             : 
     731             :   //! Get save-on-unuse `reg` property.
     732             :   ASMJIT_API bool getSaveOnUnuse(Reg& reg) const;
     733             :   //! Set save-on-unuse `reg` property to `value`.
     734             :   ASMJIT_API void setSaveOnUnuse(Reg& reg, bool value);
     735             : 
     736             :   //! Rename variable `reg` to `name`.
     737             :   //!
     738             :   //! NOTE: Only new name will appear in the logger.
     739             :   ASMJIT_API void rename(Reg& reg, const char* fmt, ...);
     740             : 
     741             :   // --------------------------------------------------------------------------
     742             :   // [Members]
     743             :   // --------------------------------------------------------------------------
     744             : 
     745             :   CCFunc* _func;                         //!< Current function.
     746             : 
     747             :   Zone _vRegZone;                        //!< Allocates \ref VirtReg objects.
     748             :   ZoneVector<VirtReg*> _vRegArray;       //!< Stores array of \ref VirtReg pointers.
     749             : 
     750             :   CBConstPool* _localConstPool;          //!< Local constant pool, flushed at the end of each function.
     751             :   CBConstPool* _globalConstPool;         //!< Global constant pool, flushed at the end of the compilation.
     752             : };
     753             : 
     754             : //! \}
     755             : 
     756             : } // asmjit namespace
     757             : } // namespace PLMD
     758             : 
     759             : // [Api-End]
     760             : #include "./asmjit_apiend.h"
     761             : 
     762             : // [Guard]
     763             : #endif // !ASMJIT_DISABLE_COMPILER
     764             : #endif // _ASMJIT_BASE_CODECOMPILER_H
     765             : #pragma GCC diagnostic pop
     766             : #endif // __PLUMED_HAS_ASMJIT
     767             : #endif

Generated by: LCOV version 1.15