LCOV - code coverage report
Current view: top level - asmjit - codecompiler.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage (other modules) Lines: 89 239 37.2 %
Date: 2024-10-18 14:00:27 Functions: 15 36 41.7 %

          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             : #ifdef __PLUMED_HAS_ASMJIT
      21             : #pragma GCC diagnostic push
      22             : #pragma GCC diagnostic ignored "-Wpedantic"
      23             : // [AsmJit]
      24             : // Complete x86/x64 JIT and Remote Assembler for C++.
      25             : //
      26             : // [License]
      27             : // Zlib - See LICENSE.md file in the package.
      28             : 
      29             : // [Export]
      30             : #define ASMJIT_EXPORTS
      31             : 
      32             : // [Guard]
      33             : #include "./asmjit_build.h"
      34             : #if !defined(ASMJIT_DISABLE_COMPILER)
      35             : 
      36             : // [Dependencies]
      37             : #include "./assembler.h"
      38             : #include "./codecompiler.h"
      39             : #include "./cpuinfo.h"
      40             : #include "./logging.h"
      41             : #include "./regalloc_p.h"
      42             : #include "./utils.h"
      43             : #include <stdarg.h>
      44             : 
      45             : // [Api-Begin]
      46             : #include "./asmjit_apibegin.h"
      47             : 
      48             : namespace PLMD {
      49             : namespace asmjit {
      50             : 
      51             : // ============================================================================
      52             : // [Constants]
      53             : // ============================================================================
      54             : 
      55             : static const char noName[1] = { '\0' };
      56             : 
      57             : // ============================================================================
      58             : // [asmjit::CCFuncCall - Arg / Ret]
      59             : // ============================================================================
      60             : 
      61       13640 : bool CCFuncCall::_setArg(uint32_t i, const Operand_& op) noexcept {
      62       13640 :   if ((i & ~kFuncArgHi) >= _funcDetail.getArgCount())
      63             :     return false;
      64             : 
      65       13640 :   _args[i] = op;
      66       13640 :   return true;
      67             : }
      68             : 
      69       13122 : bool CCFuncCall::_setRet(uint32_t i, const Operand_& op) noexcept {
      70       13122 :   if (i >= 2)
      71             :     return false;
      72             : 
      73       13122 :   _ret[i] = op;
      74       13122 :   return true;
      75             : }
      76             : 
      77             : // ============================================================================
      78             : // [asmjit::CodeCompiler - Construction / Destruction]
      79             : // ============================================================================
      80             : 
      81       32111 : CodeCompiler::CodeCompiler() noexcept
      82             :   : CodeBuilder(),
      83       32111 :     _func(nullptr),
      84       32111 :     _vRegZone(4096 - Zone::kZoneOverhead),
      85             :     _vRegArray(),
      86       32111 :     _localConstPool(nullptr),
      87       32111 :     _globalConstPool(nullptr) {
      88             : 
      89       32111 :   _type = kTypeCompiler;
      90       32111 : }
      91       32111 : CodeCompiler::~CodeCompiler() noexcept {}
      92             : 
      93             : // ============================================================================
      94             : // [asmjit::CodeCompiler - Events]
      95             : // ============================================================================
      96             : 
      97       32111 : Error CodeCompiler::onAttach(CodeHolder* code) noexcept {
      98       32111 :   return Base::onAttach(code);
      99             : }
     100             : 
     101           0 : Error CodeCompiler::onDetach(CodeHolder* code) noexcept {
     102           0 :   _func = nullptr;
     103             : 
     104           0 :   _localConstPool = nullptr;
     105           0 :   _globalConstPool = nullptr;
     106             : 
     107             :   _vRegArray.reset();
     108           0 :   _vRegZone.reset(false);
     109             : 
     110           0 :   return Base::onDetach(code);
     111             : }
     112             : 
     113             : // ============================================================================
     114             : // [asmjit::CodeCompiler - Node-Factory]
     115             : // ============================================================================
     116             : 
     117           0 : CCHint* CodeCompiler::newHintNode(Reg& r, uint32_t hint, uint32_t value) noexcept {
     118           0 :   if (!r.isVirtReg()) return nullptr;
     119             : 
     120             :   VirtReg* vr = getVirtReg(r);
     121           0 :   return newNodeT<CCHint>(vr, hint, value);
     122             : }
     123             : 
     124             : // ============================================================================
     125             : // [asmjit::CodeCompiler - Func]
     126             : // ============================================================================
     127             : 
     128       32111 : CCFunc* CodeCompiler::newFunc(const FuncSignature& sign) noexcept {
     129             :   Error err;
     130             : 
     131             :   CCFunc* func = newNodeT<CCFunc>();
     132       32111 :   if (!func) goto _NoMemory;
     133             : 
     134       32111 :   err = registerLabelNode(func);
     135       32111 :   if (ASMJIT_UNLIKELY(err)) {
     136             :     // TODO: Calls setLastError, maybe rethink noexcept?
     137           0 :     setLastError(err);
     138           0 :     return nullptr;
     139             :   }
     140             : 
     141             :   // Create helper nodes.
     142       32111 :   func->_exitNode = newLabelNode();
     143       32111 :   func->_end = newNodeT<CBSentinel>();
     144             : 
     145       32111 :   if (!func->_exitNode || !func->_end)
     146           0 :     goto _NoMemory;
     147             : 
     148             :   // Function prototype.
     149       32111 :   err = func->getDetail().init(sign);
     150       32111 :   if (err != kErrorOk) {
     151           0 :     setLastError(err);
     152           0 :     return nullptr;
     153             :   }
     154             : 
     155             :   // If the CodeInfo guarantees higher alignment honor it.
     156       32111 :   if (_codeInfo.getStackAlignment() > func->_funcDetail._callConv.getNaturalStackAlignment())
     157             :     func->_funcDetail._callConv.setNaturalStackAlignment(_codeInfo.getStackAlignment());
     158             : 
     159             :   // Allocate space for function arguments.
     160       32111 :   func->_args = nullptr;
     161       32111 :   if (func->getArgCount() != 0) {
     162           0 :     func->_args = _cbHeap.allocT<VirtReg*>(func->getArgCount() * sizeof(VirtReg*));
     163           0 :     if (!func->_args) goto _NoMemory;
     164             : 
     165           0 :     ::memset(func->_args, 0, func->getArgCount() * sizeof(VirtReg*));
     166             :   }
     167             : 
     168             :   return func;
     169             : 
     170           0 : _NoMemory:
     171           0 :   setLastError(DebugUtils::errored(kErrorNoHeapMemory));
     172           0 :   return nullptr;
     173             : }
     174             : 
     175       32111 : CCFunc* CodeCompiler::addFunc(CCFunc* func) {
     176             :   ASMJIT_ASSERT(_func == nullptr);
     177       32111 :   _func = func;
     178             : 
     179       32111 :   addNode(func);                 // Function node.
     180             :   CBNode* cursor = getCursor();  // {CURSOR}.
     181       32111 :   addNode(func->getExitNode());  // Function exit label.
     182       32111 :   addNode(func->getEnd());       // Function end marker.
     183             : 
     184             :   _setCursor(cursor);
     185       32111 :   return func;
     186             : }
     187             : 
     188       32111 : CCFunc* CodeCompiler::addFunc(const FuncSignature& sign) {
     189       32111 :   CCFunc* func = newFunc(sign);
     190             : 
     191       32111 :   if (!func) {
     192           0 :     setLastError(DebugUtils::errored(kErrorNoHeapMemory));
     193           0 :     return nullptr;
     194             :   }
     195             : 
     196       32111 :   return addFunc(func);
     197             : }
     198             : 
     199       32111 : CBSentinel* CodeCompiler::endFunc() {
     200             :   CCFunc* func = getFunc();
     201       32111 :   if (!func) {
     202             :     // TODO:
     203             :     return nullptr;
     204             :   }
     205             : 
     206             :   // Add the local constant pool at the end of the function (if exists).
     207       32111 :   if (_localConstPool) {
     208           0 :     setCursor(func->getEnd()->getPrev());
     209           0 :     addNode(_localConstPool);
     210           0 :     _localConstPool = nullptr;
     211             :   }
     212             : 
     213             :   // Mark as finished.
     214       32111 :   func->_isFinished = true;
     215       32111 :   _func = nullptr;
     216             : 
     217             :   CBSentinel* end = func->getEnd();
     218       32111 :   setCursor(end);
     219       32111 :   return end;
     220             : }
     221             : 
     222             : // ============================================================================
     223             : // [asmjit::CodeCompiler - Ret]
     224             : // ============================================================================
     225             : 
     226       32111 : CCFuncRet* CodeCompiler::newRet(const Operand_& o0, const Operand_& o1) noexcept {
     227       32111 :   CCFuncRet* node = newNodeT<CCFuncRet>(o0, o1);
     228       32111 :   if (!node) {
     229           0 :     setLastError(DebugUtils::errored(kErrorNoHeapMemory));
     230           0 :     return nullptr;
     231             :   }
     232             :   return node;
     233             : }
     234             : 
     235       32111 : CCFuncRet* CodeCompiler::addRet(const Operand_& o0, const Operand_& o1) noexcept {
     236       32111 :   CCFuncRet* node = newRet(o0, o1);
     237       32111 :   if (!node) return nullptr;
     238       32111 :   return static_cast<CCFuncRet*>(addNode(node));
     239             : }
     240             : 
     241             : // ============================================================================
     242             : // [asmjit::CodeCompiler - Call]
     243             : // ============================================================================
     244             : 
     245       13122 : CCFuncCall* CodeCompiler::newCall(uint32_t instId, const Operand_& o0, const FuncSignature& sign) noexcept {
     246             :   Error err;
     247             :   uint32_t nArgs;
     248             : 
     249       13122 :   CCFuncCall* node = _cbHeap.allocT<CCFuncCall>(sizeof(CCFuncCall) + sizeof(Operand));
     250       13122 :   Operand* opArray = reinterpret_cast<Operand*>(reinterpret_cast<uint8_t*>(node) + sizeof(CCFuncCall));
     251             : 
     252       13122 :   if (ASMJIT_UNLIKELY(!node))
     253           0 :     goto _NoMemory;
     254             : 
     255       13122 :   opArray[0].copyFrom(o0);
     256             :   new (node) CCFuncCall(this, instId, 0, opArray, 1);
     257             : 
     258       13122 :   if ((err = node->getDetail().init(sign)) != kErrorOk) {
     259           0 :     setLastError(err);
     260           0 :     return nullptr;
     261             :   }
     262             : 
     263             :   // If there are no arguments skip the allocation.
     264       13122 :   if ((nArgs = sign.getArgCount()) == 0)
     265             :     return node;
     266             : 
     267       13122 :   node->_args = static_cast<Operand*>(_cbHeap.alloc(nArgs * sizeof(Operand)));
     268       13122 :   if (!node->_args) goto _NoMemory;
     269             : 
     270             :   ::memset(node->_args, 0, nArgs * sizeof(Operand));
     271       13122 :   return node;
     272             : 
     273           0 : _NoMemory:
     274           0 :   setLastError(DebugUtils::errored(kErrorNoHeapMemory));
     275           0 :   return nullptr;
     276             : }
     277             : 
     278       13122 : CCFuncCall* CodeCompiler::addCall(uint32_t instId, const Operand_& o0, const FuncSignature& sign) noexcept {
     279       13122 :   CCFuncCall* node = newCall(instId, o0, sign);
     280       13122 :   if (!node) return nullptr;
     281       13122 :   return static_cast<CCFuncCall*>(addNode(node));
     282             : }
     283             : 
     284             : // ============================================================================
     285             : // [asmjit::CodeCompiler - Vars]
     286             : // ============================================================================
     287             : 
     288           0 : Error CodeCompiler::setArg(uint32_t argIndex, const Reg& r) {
     289             :   CCFunc* func = getFunc();
     290             : 
     291           0 :   if (!func)
     292           0 :     return setLastError(DebugUtils::errored(kErrorInvalidState));
     293             : 
     294           0 :   if (!isVirtRegValid(r))
     295           0 :     return setLastError(DebugUtils::errored(kErrorInvalidVirtId));
     296             : 
     297             :   VirtReg* vr = getVirtReg(r);
     298             :   func->setArg(argIndex, vr);
     299             : 
     300           0 :   return kErrorOk;
     301             : }
     302             : 
     303             : // ============================================================================
     304             : // [asmjit::CodeCompiler - Hint]
     305             : // ============================================================================
     306             : 
     307           0 : Error CodeCompiler::_hint(Reg& r, uint32_t hint, uint32_t value) {
     308           0 :   if (!r.isVirtReg()) return kErrorOk;
     309             : 
     310           0 :   CCHint* node = newHintNode(r, hint, value);
     311           0 :   if (!node) return setLastError(DebugUtils::errored(kErrorNoHeapMemory));
     312             : 
     313           0 :   addNode(node);
     314           0 :   return kErrorOk;
     315             : }
     316             : 
     317             : // ============================================================================
     318             : // [asmjit::CodeCompiler - Vars]
     319             : // ============================================================================
     320             : 
     321      317812 : VirtReg* CodeCompiler::newVirtReg(uint32_t typeId, uint32_t signature, const char* name) noexcept {
     322             :   size_t index = _vRegArray.getLength();
     323      317812 :   if (ASMJIT_UNLIKELY(index > Operand::kPackedIdCount))
     324             :     return nullptr;
     325             : 
     326             :   VirtReg* vreg;
     327      388103 :   if (_vRegArray.willGrow(&_cbHeap, 1) != kErrorOk || !(vreg = _vRegZone.allocZeroedT<VirtReg>()))
     328           0 :     return nullptr;
     329             : 
     330      317812 :   vreg->_id = Operand::packId(static_cast<uint32_t>(index));
     331      317812 :   vreg->_regInfo._signature = signature;
     332      317812 :   vreg->_name = noName;
     333             : 
     334             : #if !defined(ASMJIT_DISABLE_LOGGING)
     335      317812 :   if (name && name[0] != '\0')
     336           0 :     vreg->_name = static_cast<char*>(_cbDataZone.dup(name, ::strlen(name), true));
     337             : #endif // !ASMJIT_DISABLE_LOGGING
     338             : 
     339      317812 :   vreg->_size = TypeId::sizeOf(typeId);
     340      317812 :   vreg->_typeId = typeId;
     341      317812 :   vreg->_alignment = static_cast<uint8_t>(std::min<uint32_t>(vreg->_size, 64));
     342      317812 :   vreg->_priority = 10;
     343             : 
     344             :   // The following are only used by `RAPass`.
     345      317812 :   vreg->_raId = kInvalidValue;
     346      317812 :   vreg->_state = VirtReg::kStateNone;
     347      317812 :   vreg->_physId = Globals::kInvalidRegId;
     348             : 
     349             :   _vRegArray.appendUnsafe(vreg);
     350      317812 :   return vreg;
     351             : }
     352             : 
     353      317812 : Error CodeCompiler::_newReg(Reg& out, uint32_t typeId, const char* name) {
     354             :   RegInfo regInfo;
     355             : 
     356      317812 :   Error err = ArchUtils::typeIdToRegInfo(getArchType(), typeId, regInfo);
     357      317812 :   if (ASMJIT_UNLIKELY(err)) return setLastError(err);
     358             : 
     359      317812 :   VirtReg* vReg = newVirtReg(typeId, regInfo.getSignature(), name);
     360      317812 :   if (ASMJIT_UNLIKELY(!vReg)) {
     361             :     out.reset();
     362           0 :     return setLastError(DebugUtils::errored(kErrorNoHeapMemory));
     363             :   }
     364             : 
     365             :   out._initReg(regInfo.getSignature(), vReg->getId());
     366      317812 :   return kErrorOk;
     367             : }
     368             : 
     369           0 : Error CodeCompiler::_newReg(Reg& out, uint32_t typeId, const char* nameFmt, va_list ap) {
     370             :   StringBuilderTmp<256> sb;
     371             :   sb.appendFormatVA(nameFmt, ap);
     372           0 :   return _newReg(out, typeId, sb.getData());
     373             : }
     374             : 
     375           0 : Error CodeCompiler::_newReg(Reg& out, const Reg& ref, const char* name) {
     376             :   RegInfo regInfo;
     377             :   uint32_t typeId;
     378             : 
     379           0 :   if (isVirtRegValid(ref)) {
     380             :     VirtReg* vRef = getVirtReg(ref);
     381           0 :     typeId = vRef->getTypeId();
     382             : 
     383             :     // NOTE: It's possible to cast one register type to another if it's the
     384             :     // same register kind. However, VirtReg always contains the TypeId that
     385             :     // was used to create the register. This means that in some cases we may
     386             :     // end up having different size of `ref` and `vRef`. In such case we
     387             :     // adjust the TypeId to match the `ref` register type instead of the
     388             :     // original register type, which should be the expected behavior.
     389             :     uint32_t typeSize = TypeId::sizeOf(typeId);
     390             :     uint32_t refSize = ref.getSize();
     391             : 
     392           0 :     if (typeSize != refSize) {
     393           0 :       if (TypeId::isInt(typeId)) {
     394             :         // GP register - change TypeId to match `ref`, but keep sign of `vRef`.
     395           0 :         switch (refSize) {
     396           0 :           case  1: typeId = TypeId::kI8  | (typeId & 1); break;
     397           0 :           case  2: typeId = TypeId::kI16 | (typeId & 1); break;
     398           0 :           case  4: typeId = TypeId::kI32 | (typeId & 1); break;
     399           0 :           case  8: typeId = TypeId::kI64 | (typeId & 1); break;
     400           0 :           default: typeId = TypeId::kVoid; break;
     401             :         }
     402             :       }
     403           0 :       else if (TypeId::isMmx(typeId)) {
     404             :         // MMX register - always use 64-bit.
     405           0 :         typeId = TypeId::kMmx64;
     406             :       }
     407           0 :       else if (TypeId::isMask(typeId)) {
     408             :         // Mask register - change TypeId to match `ref` size.
     409           0 :         switch (refSize) {
     410           0 :           case  1: typeId = TypeId::kMask8; break;
     411           0 :           case  2: typeId = TypeId::kMask16; break;
     412           0 :           case  4: typeId = TypeId::kMask32; break;
     413           0 :           case  8: typeId = TypeId::kMask64; break;
     414           0 :           default: typeId = TypeId::kVoid; break;
     415             :         }
     416             :       }
     417             :       else {
     418             :         // VEC register - change TypeId to match `ref` size, keep vector metadata.
     419             :         uint32_t elementTypeId = TypeId::elementOf(typeId);
     420             : 
     421           0 :         switch (refSize) {
     422           0 :           case 16: typeId = TypeId::_kVec128Start + (elementTypeId - TypeId::kI8); break;
     423           0 :           case 32: typeId = TypeId::_kVec256Start + (elementTypeId - TypeId::kI8); break;
     424           0 :           case 64: typeId = TypeId::_kVec512Start + (elementTypeId - TypeId::kI8); break;
     425           0 :           default: typeId = TypeId::kVoid; break;
     426             :         }
     427             :       }
     428             : 
     429           0 :       if (typeId == TypeId::kVoid)
     430           0 :         return setLastError(DebugUtils::errored(kErrorInvalidState));
     431             :     }
     432             :   }
     433             :   else {
     434           0 :     typeId = ref.getType();
     435             :   }
     436             : 
     437           0 :   Error err = ArchUtils::typeIdToRegInfo(getArchType(), typeId, regInfo);
     438           0 :   if (ASMJIT_UNLIKELY(err)) return setLastError(err);
     439             : 
     440           0 :   VirtReg* vReg = newVirtReg(typeId, regInfo.getSignature(), name);
     441           0 :   if (ASMJIT_UNLIKELY(!vReg)) {
     442             :     out.reset();
     443           0 :     return setLastError(DebugUtils::errored(kErrorNoHeapMemory));
     444             :   }
     445             : 
     446             :   out._initReg(regInfo.getSignature(), vReg->getId());
     447           0 :   return kErrorOk;
     448             : }
     449             : 
     450           0 : Error CodeCompiler::_newReg(Reg& out, const Reg& ref, const char* nameFmt, va_list ap) {
     451             :   StringBuilderTmp<256> sb;
     452             :   sb.appendFormatVA(nameFmt, ap);
     453           0 :   return _newReg(out, ref, sb.getData());
     454             : }
     455             : 
     456           0 : Error CodeCompiler::_newStack(Mem& out, uint32_t size, uint32_t alignment, const char* name) {
     457           0 :   if (size == 0)
     458           0 :     return setLastError(DebugUtils::errored(kErrorInvalidArgument));
     459             : 
     460             :   if (alignment == 0) alignment = 1;
     461             :   if (!Utils::isPowerOf2(alignment))
     462           0 :     return setLastError(DebugUtils::errored(kErrorInvalidArgument));
     463             : 
     464             :   if (alignment > 64) alignment = 64;
     465             : 
     466           0 :   VirtReg* vReg = newVirtReg(0, 0, name);
     467           0 :   if (ASMJIT_UNLIKELY(!vReg)) {
     468             :     out.reset();
     469           0 :     return setLastError(DebugUtils::errored(kErrorNoHeapMemory));
     470             :   }
     471             : 
     472           0 :   vReg->_size = size;
     473           0 :   vReg->_isStack = true;
     474           0 :   vReg->_alignment = static_cast<uint8_t>(alignment);
     475             : 
     476             :   // Set the memory operand to GPD/GPQ and its id to VirtReg.
     477           0 :   out = Mem(Init, _nativeGpReg.getType(), vReg->getId(), Reg::kRegNone, kInvalidValue, 0, 0, Mem::kSignatureMemRegHomeFlag);
     478           0 :   return kErrorOk;
     479             : }
     480             : 
     481           0 : Error CodeCompiler::_newConst(Mem& out, uint32_t scope, const void* data, size_t size) {
     482             :   CBConstPool** pPool;
     483           0 :   if (scope == kConstScopeLocal)
     484           0 :     pPool = &_localConstPool;
     485           0 :   else if (scope == kConstScopeGlobal)
     486           0 :     pPool = &_globalConstPool;
     487             :   else
     488           0 :     return setLastError(DebugUtils::errored(kErrorInvalidArgument));
     489             : 
     490           0 :   if (!*pPool && !(*pPool = newConstPool()))
     491           0 :     return setLastError(DebugUtils::errored(kErrorNoHeapMemory));
     492             : 
     493           0 :   CBConstPool* pool = *pPool;
     494             :   size_t off;
     495             : 
     496             :   Error err = pool->add(data, size, off);
     497           0 :   if (ASMJIT_UNLIKELY(err)) return setLastError(err);
     498             : 
     499           0 :   out = Mem(Init,
     500             :     Label::kLabelTag,             // Base type.
     501             :     pool->getId(),                // Base id.
     502             :     0,                            // Index type.
     503             :     kInvalidValue,                // Index id.
     504             :     static_cast<int32_t>(off),    // Offset.
     505             :     static_cast<uint32_t>(size),  // Size.
     506             :     0);                           // Flags.
     507           0 :   return kErrorOk;
     508             : }
     509             : 
     510           0 : Error CodeCompiler::alloc(Reg& reg) {
     511           0 :   if (!reg.isVirtReg()) return kErrorOk;
     512           0 :   return _hint(reg, CCHint::kHintAlloc, kInvalidValue);
     513             : }
     514             : 
     515           0 : Error CodeCompiler::alloc(Reg& reg, uint32_t physId) {
     516           0 :   if (!reg.isVirtReg()) return kErrorOk;
     517           0 :   return _hint(reg, CCHint::kHintAlloc, physId);
     518             : }
     519             : 
     520           0 : Error CodeCompiler::alloc(Reg& reg, const Reg& physReg) {
     521           0 :   if (!reg.isVirtReg()) return kErrorOk;
     522           0 :   return _hint(reg, CCHint::kHintAlloc, physReg.getId());
     523             : }
     524             : 
     525           0 : Error CodeCompiler::save(Reg& reg) {
     526           0 :   if (!reg.isVirtReg()) return kErrorOk;
     527           0 :   return _hint(reg, CCHint::kHintSave, kInvalidValue);
     528             : }
     529             : 
     530           0 : Error CodeCompiler::spill(Reg& reg) {
     531           0 :   if (!reg.isVirtReg()) return kErrorOk;
     532           0 :   return _hint(reg, CCHint::kHintSpill, kInvalidValue);
     533             : }
     534             : 
     535           0 : Error CodeCompiler::unuse(Reg& reg) {
     536           0 :   if (!reg.isVirtReg()) return kErrorOk;
     537           0 :   return _hint(reg, CCHint::kHintUnuse, kInvalidValue);
     538             : }
     539             : 
     540           0 : uint32_t CodeCompiler::getPriority(Reg& reg) const {
     541           0 :   if (!reg.isVirtReg()) return 0;
     542           0 :   return getVirtRegById(reg.getId())->getPriority();
     543             : }
     544             : 
     545           0 : void CodeCompiler::setPriority(Reg& reg, uint32_t priority) {
     546           0 :   if (!reg.isVirtReg()) return;
     547             :   if (priority > 255) priority = 255;
     548             : 
     549             :   VirtReg* vreg = getVirtRegById(reg.getId());
     550           0 :   if (vreg) vreg->_priority = static_cast<uint8_t>(priority);
     551             : }
     552             : 
     553           0 : bool CodeCompiler::getSaveOnUnuse(Reg& reg) const {
     554           0 :   if (!reg.isVirtReg()) return false;
     555             : 
     556             :   VirtReg* vreg = getVirtRegById(reg.getId());
     557           0 :   return static_cast<bool>(vreg->_saveOnUnuse);
     558             : }
     559             : 
     560           0 : void CodeCompiler::setSaveOnUnuse(Reg& reg, bool value) {
     561           0 :   if (!reg.isVirtReg()) return;
     562             : 
     563             :   VirtReg* vreg = getVirtRegById(reg.getId());
     564           0 :   if (!vreg) return;
     565             : 
     566           0 :   vreg->_saveOnUnuse = value;
     567             : }
     568             : 
     569           0 : void CodeCompiler::rename(Reg& reg, const char* fmt, ...) {
     570           0 :   if (!reg.isVirtReg()) return;
     571             : 
     572             :   VirtReg* vreg = getVirtRegById(reg.getId());
     573           0 :   if (!vreg) return;
     574             : 
     575           0 :   vreg->_name = noName;
     576           0 :   if (fmt && fmt[0] != '\0') {
     577             :     char buf[64];
     578             : 
     579             :     va_list ap;
     580           0 :     va_start(ap, fmt);
     581             : 
     582             :     vsnprintf(buf, ASMJIT_ARRAY_SIZE(buf), fmt, ap);
     583           0 :     buf[ASMJIT_ARRAY_SIZE(buf) - 1] = '\0';
     584             : 
     585           0 :     vreg->_name = static_cast<char*>(_cbDataZone.dup(buf, ::strlen(buf), true));
     586           0 :     va_end(ap);
     587             :   }
     588             : }
     589             : 
     590             : } // asmjit namespace
     591             : } // namespace PLMD
     592             : 
     593             : // [Api-End]
     594             : #include "./asmjit_apiend.h"
     595             : 
     596             : // [Guard]
     597             : #endif // !ASMJIT_DISABLE_COMPILER
     598             : #pragma GCC diagnostic pop
     599             : #endif // __PLUMED_HAS_ASMJIT

Generated by: LCOV version 1.16