LCOV - code coverage report
Current view: top level - asmjit - compiler.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage (other modules) Lines: 106 240 44.2 %
Date: 2026-11-05 10:19:06 Functions: 17 29 58.6 %

          Line data    Source code
       1             : #ifdef __PLUMED_HAS_ASMJIT
       2             : // This file is part of AsmJit project <https://asmjit.com>
       3             : //
       4             : // See asmjit.h or LICENSE.md for license and copyright information
       5             : // SPDX-License-Identifier: Zlib
       6             : 
       7             : #include "api-build_p.h"
       8             : #ifndef ASMJIT_NO_COMPILER
       9             : 
      10             : #include "assembler.h"
      11             : #include "compiler.h"
      12             : #include "cpuinfo.h"
      13             : #include "logger.h"
      14             : #include "rapass_p.h"
      15             : #include "rastack_p.h"
      16             : #include "support.h"
      17             : #include "type.h"
      18             : 
      19             : ASMJIT_BEGIN_NAMESPACE
      20             : 
      21             : // GlobalConstPoolPass
      22             : // ===================
      23             : 
      24             : class GlobalConstPoolPass : public Pass {
      25             : public:
      26             :   typedef Pass Base;
      27             : public:
      28             :   ASMJIT_NONCOPYABLE(GlobalConstPoolPass)
      29             : 
      30       27492 :   GlobalConstPoolPass() noexcept : Pass("GlobalConstPoolPass") {}
      31             : 
      32       27492 :   Error run(Zone* zone, Logger* logger) override {
      33             :     DebugUtils::unused(zone, logger);
      34             : 
      35             :     // Flush the global constant pool.
      36       27492 :     BaseCompiler* compiler = static_cast<BaseCompiler*>(_cb);
      37       27492 :     ConstPoolNode* globalConstPool = compiler->_constPools[uint32_t(ConstPoolScope::kGlobal)];
      38             : 
      39       27492 :     if (globalConstPool) {
      40           0 :       compiler->addAfter(globalConstPool, compiler->lastNode());
      41           0 :       compiler->_constPools[uint32_t(ConstPoolScope::kGlobal)] = nullptr;
      42             :     }
      43             : 
      44       27492 :     return kErrorOk;
      45             :   }
      46             : };
      47             : 
      48             : // BaseCompiler - Construction & Destruction
      49             : // =========================================
      50             : 
      51       27492 : BaseCompiler::BaseCompiler() noexcept
      52             :   : BaseBuilder(),
      53       27492 :     _func(nullptr),
      54       27492 :     _vRegZone(4096 - Zone::kBlockOverhead),
      55             :     _vRegArray(),
      56       27492 :     _constPools { nullptr, nullptr } {
      57       27492 :   _emitterType = EmitterType::kCompiler;
      58       27492 :   _validationFlags = ValidationFlags::kEnableVirtRegs;
      59       27492 : }
      60       27492 : BaseCompiler::~BaseCompiler() noexcept {}
      61             : 
      62             : // BaseCompiler - Function Management
      63             : // ==================================
      64             : 
      65       27492 : Error BaseCompiler::newFuncNode(FuncNode** out, const FuncSignature& signature) {
      66       27492 :   *out = nullptr;
      67             : 
      68             :   // Create FuncNode together with all the required surrounding nodes.
      69             :   FuncNode* funcNode;
      70       27492 :   ASMJIT_PROPAGATE(_newNodeT<FuncNode>(&funcNode));
      71       27492 :   ASMJIT_PROPAGATE(newLabelNode(&funcNode->_exitNode));
      72       27492 :   ASMJIT_PROPAGATE(_newNodeT<SentinelNode>(&funcNode->_end, SentinelType::kFuncEnd));
      73             : 
      74             :   // Initialize the function's detail info.
      75       27492 :   Error err = funcNode->detail().init(signature, environment());
      76       27492 :   if (ASMJIT_UNLIKELY(err))
      77           0 :     return reportError(err);
      78             : 
      79             :   // If the Target guarantees greater stack alignment than required by the calling convention
      80             :   // then override it as we can prevent having to perform dynamic stack alignment
      81       27492 :   uint32_t environmentStackAlignment = _environment.stackAlignment();
      82             : 
      83       27492 :   if (funcNode->_funcDetail._callConv.naturalStackAlignment() < environmentStackAlignment)
      84             :     funcNode->_funcDetail._callConv.setNaturalStackAlignment(environmentStackAlignment);
      85             : 
      86             :   // Initialize the function frame.
      87       27492 :   err = funcNode->_frame.init(funcNode->_funcDetail);
      88       27492 :   if (ASMJIT_UNLIKELY(err))
      89           0 :     return reportError(err);
      90             : 
      91             :   // Allocate space for function arguments.
      92       27492 :   funcNode->_args = nullptr;
      93       27492 :   if (funcNode->argCount() != 0) {
      94           0 :     funcNode->_args = _allocator.allocT<FuncNode::ArgPack>(funcNode->argCount() * sizeof(FuncNode::ArgPack));
      95           0 :     if (ASMJIT_UNLIKELY(!funcNode->_args))
      96           0 :       return reportError(DebugUtils::errored(kErrorOutOfMemory));
      97           0 :     memset(funcNode->_args, 0, funcNode->argCount() * sizeof(FuncNode::ArgPack));
      98             :   }
      99             : 
     100       27492 :   ASMJIT_PROPAGATE(registerLabelNode(funcNode));
     101             : 
     102       27492 :   *out = funcNode;
     103       27492 :   return kErrorOk;
     104             : }
     105             : 
     106       27492 : Error BaseCompiler::addFuncNode(FuncNode** out, const FuncSignature& signature) {
     107       27492 :   ASMJIT_PROPAGATE(newFuncNode(out, signature));
     108       27492 :   ASMJIT_ASSUME(*out != nullptr);
     109             : 
     110       27492 :   addFunc(*out);
     111       27492 :   return kErrorOk;
     112             : }
     113             : 
     114       27492 : Error BaseCompiler::newFuncRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1) {
     115       27492 :   uint32_t opCount = !o1.isNone() ? 2u : !o0.isNone() ? 1u : 0u;
     116             :   FuncRetNode* node;
     117             : 
     118       27492 :   ASMJIT_PROPAGATE(_newNodeT<FuncRetNode>(&node));
     119       27492 :   ASMJIT_ASSUME(node != nullptr);
     120             : 
     121             :   node->setOpCount(opCount);
     122             :   node->setOp(0, o0);
     123             :   node->setOp(1, o1);
     124             :   node->resetOpRange(2, node->opCapacity());
     125             : 
     126       27492 :   *out = node;
     127       27492 :   return kErrorOk;
     128             : }
     129             : 
     130       27492 : Error BaseCompiler::addFuncRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1) {
     131       27492 :   ASMJIT_PROPAGATE(newFuncRetNode(out, o0, o1));
     132       27492 :   addNode(*out);
     133       27492 :   return kErrorOk;
     134             : }
     135             : 
     136       27492 : FuncNode* BaseCompiler::addFunc(FuncNode* func) {
     137       27492 :   _func = func;
     138             : 
     139       27492 :   addNode(func);                 // Function node.
     140             :   BaseNode* prev = cursor();     // {CURSOR}.
     141       27492 :   addNode(func->exitNode());     // Function exit label.
     142       27492 :   addNode(func->endNode());      // Function end sentinel.
     143             : 
     144             :   _setCursor(prev);
     145       27492 :   return func;
     146             : }
     147             : 
     148       27492 : Error BaseCompiler::endFunc() {
     149       27492 :   FuncNode* func = _func;
     150             : 
     151       27492 :   if (ASMJIT_UNLIKELY(!func))
     152           0 :     return reportError(DebugUtils::errored(kErrorInvalidState));
     153             : 
     154             :   // Add the local constant pool at the end of the function (if exists).
     155       27492 :   ConstPoolNode* localConstPool = _constPools[uint32_t(ConstPoolScope::kLocal)];
     156       27492 :   if (localConstPool) {
     157           0 :     setCursor(func->endNode()->prev());
     158           0 :     addNode(localConstPool);
     159           0 :     _constPools[uint32_t(ConstPoolScope::kLocal)] = nullptr;
     160             :   }
     161             : 
     162             :   // Mark as finished.
     163       27492 :   _func = nullptr;
     164             : 
     165             :   SentinelNode* end = func->endNode();
     166       27492 :   setCursor(end);
     167             : 
     168       27492 :   return kErrorOk;
     169             : }
     170             : 
     171             : // BaseCompiler - Function Invocation
     172             : // ==================================
     173             : 
     174        9639 : Error BaseCompiler::newInvokeNode(InvokeNode** out, InstId instId, const Operand_& o0, const FuncSignature& signature) {
     175             :   InvokeNode* node;
     176        9639 :   ASMJIT_PROPAGATE(_newNodeT<InvokeNode>(&node, instId, InstOptions::kNone));
     177             : 
     178        9639 :   node->setOpCount(1);
     179             :   node->setOp(0, o0);
     180             :   node->resetOpRange(1, node->opCapacity());
     181             : 
     182        9639 :   Error err = node->detail().init(signature, environment());
     183        9639 :   if (ASMJIT_UNLIKELY(err))
     184           0 :     return reportError(err);
     185             : 
     186             :   // Skip the allocation if there are no arguments.
     187             :   uint32_t argCount = signature.argCount();
     188        9639 :   if (argCount) {
     189        9639 :     node->_args = static_cast<InvokeNode::OperandPack*>(_allocator.alloc(argCount * sizeof(InvokeNode::OperandPack)));
     190        9639 :     if (!node->_args)
     191           0 :       return reportError(DebugUtils::errored(kErrorOutOfMemory));
     192             :     memset(node->_args, 0, argCount * sizeof(InvokeNode::OperandPack));
     193             :   }
     194             : 
     195        9639 :   *out = node;
     196        9639 :   return kErrorOk;
     197             : }
     198             : 
     199        9639 : Error BaseCompiler::addInvokeNode(InvokeNode** out, InstId instId, const Operand_& o0, const FuncSignature& signature) {
     200        9639 :   ASMJIT_PROPAGATE(newInvokeNode(out, instId, o0, signature));
     201        9639 :   addNode(*out);
     202        9639 :   return kErrorOk;
     203             : }
     204             : 
     205             : // BaseCompiler - Virtual Registers
     206             : // ================================
     207             : 
     208      273777 : static void BaseCompiler_assignGenericName(BaseCompiler* self, VirtReg* vReg) {
     209      273777 :   uint32_t index = unsigned(Operand::virtIdToIndex(vReg->_id));
     210             : 
     211             :   char buf[64];
     212             :   int size = snprintf(buf, ASMJIT_ARRAY_SIZE(buf), "%%%u", unsigned(index));
     213             : 
     214             :   ASMJIT_ASSERT(size > 0 && size < int(ASMJIT_ARRAY_SIZE(buf)));
     215      273777 :   vReg->_name.setData(&self->_dataZone, buf, unsigned(size));
     216      273777 : }
     217             : 
     218      273777 : Error BaseCompiler::newVirtReg(VirtReg** out, TypeId typeId, OperandSignature signature, const char* name) {
     219      273777 :   *out = nullptr;
     220             :   uint32_t index = _vRegArray.size();
     221             : 
     222      273777 :   if (ASMJIT_UNLIKELY(index >= uint32_t(Operand::kVirtIdCount)))
     223           0 :     return reportError(DebugUtils::errored(kErrorTooManyVirtRegs));
     224             : 
     225      273777 :   if (ASMJIT_UNLIKELY(_vRegArray.willGrow(&_allocator) != kErrorOk))
     226           0 :     return reportError(DebugUtils::errored(kErrorOutOfMemory));
     227             : 
     228      273777 :   VirtReg* vReg = _vRegZone.allocZeroedT<VirtReg>();
     229      273777 :   if (ASMJIT_UNLIKELY(!vReg))
     230           0 :     return reportError(DebugUtils::errored(kErrorOutOfMemory));
     231             : 
     232             :   uint32_t size = TypeUtils::sizeOf(typeId);
     233             :   uint32_t alignment = Support::min<uint32_t>(size, 64);
     234             : 
     235             :   vReg = new(vReg) VirtReg(signature, Operand::indexToVirtId(index), size, alignment, typeId);
     236             : 
     237             : #ifndef ASMJIT_NO_LOGGING
     238      273777 :   if (name && name[0] != '\0')
     239           0 :     vReg->_name.setData(&_dataZone, name, SIZE_MAX);
     240             :   else
     241      273777 :     BaseCompiler_assignGenericName(this, vReg);
     242             : #else
     243             :   DebugUtils::unused(name);
     244             : #endif
     245             : 
     246             :   _vRegArray.appendUnsafe(vReg);
     247      273777 :   *out = vReg;
     248             : 
     249      273777 :   return kErrorOk;
     250             : }
     251             : 
     252      273777 : Error BaseCompiler::_newReg(BaseReg* out, TypeId typeId, const char* name) {
     253             :   OperandSignature regSignature;
     254             :   out->reset();
     255             : 
     256      273777 :   Error err = ArchUtils::typeIdToRegSignature(arch(), typeId, &typeId, &regSignature);
     257      273777 :   if (ASMJIT_UNLIKELY(err))
     258           0 :     return reportError(err);
     259             : 
     260             :   VirtReg* vReg;
     261      273777 :   ASMJIT_PROPAGATE(newVirtReg(&vReg, typeId, regSignature, name));
     262      273777 :   ASMJIT_ASSUME(vReg != nullptr);
     263             : 
     264             :   out->_initReg(regSignature, vReg->id());
     265      273777 :   return kErrorOk;
     266             : }
     267             : 
     268           0 : Error BaseCompiler::_newRegFmt(BaseReg* out, TypeId typeId, const char* fmt, ...) {
     269             :   va_list ap;
     270             :   StringTmp<256> sb;
     271             : 
     272           0 :   va_start(ap, fmt);
     273             :   sb.appendVFormat(fmt, ap);
     274           0 :   va_end(ap);
     275             : 
     276           0 :   return _newReg(out, typeId, sb.data());
     277             : }
     278             : 
     279           0 : Error BaseCompiler::_newReg(BaseReg* out, const BaseReg& ref, const char* name) {
     280             :   out->reset();
     281             : 
     282             :   OperandSignature regSignature;
     283             :   TypeId typeId;
     284             : 
     285           0 :   if (isVirtRegValid(ref)) {
     286             :     VirtReg* vRef = virtRegByReg(ref);
     287           0 :     typeId = vRef->typeId();
     288             : 
     289             :     // NOTE: It's possible to cast one register type to another if it's the same register group. However, VirtReg
     290             :     // always contains the TypeId that was used to create the register. This means that in some cases we may end
     291             :     // up having different size of `ref` and `vRef`. In such case we adjust the TypeId to match the `ref` register
     292             :     // type instead of the original register type, which should be the expected behavior.
     293             :     uint32_t typeSize = TypeUtils::sizeOf(typeId);
     294             :     uint32_t refSize = ref.size();
     295             : 
     296           0 :     if (typeSize != refSize) {
     297             :       if (TypeUtils::isInt(typeId)) {
     298             :         // GP register - change TypeId to match `ref`, but keep sign of `vRef`.
     299           0 :         switch (refSize) {
     300           0 :           case  1: typeId = TypeId(uint32_t(TypeId::kInt8 ) | (uint32_t(typeId) & 1)); break;
     301           0 :           case  2: typeId = TypeId(uint32_t(TypeId::kInt16) | (uint32_t(typeId) & 1)); break;
     302           0 :           case  4: typeId = TypeId(uint32_t(TypeId::kInt32) | (uint32_t(typeId) & 1)); break;
     303           0 :           case  8: typeId = TypeId(uint32_t(TypeId::kInt64) | (uint32_t(typeId) & 1)); break;
     304           0 :           default: typeId = TypeId::kVoid; break;
     305             :         }
     306             :       }
     307             :       else if (TypeUtils::isMmx(typeId)) {
     308             :         // MMX register - always use 64-bit.
     309           0 :         typeId = TypeId::kMmx64;
     310             :       }
     311             :       else if (TypeUtils::isMask(typeId)) {
     312             :         // Mask register - change TypeId to match `ref` size.
     313           0 :         switch (refSize) {
     314           0 :           case  1: typeId = TypeId::kMask8; break;
     315           0 :           case  2: typeId = TypeId::kMask16; break;
     316           0 :           case  4: typeId = TypeId::kMask32; break;
     317           0 :           case  8: typeId = TypeId::kMask64; break;
     318           0 :           default: typeId = TypeId::kVoid; break;
     319             :         }
     320             :       }
     321             :       else {
     322             :         // Vector register - change TypeId to match `ref` size, keep vector metadata.
     323             :         TypeId scalarTypeId = TypeUtils::scalarOf(typeId);
     324           0 :         switch (refSize) {
     325           0 :           case 16: typeId = TypeUtils::scalarToVector(scalarTypeId, TypeId::_kVec128Start); break;
     326           0 :           case 32: typeId = TypeUtils::scalarToVector(scalarTypeId, TypeId::_kVec256Start); break;
     327           0 :           case 64: typeId = TypeUtils::scalarToVector(scalarTypeId, TypeId::_kVec512Start); break;
     328           0 :           default: typeId = TypeId::kVoid; break;
     329             :         }
     330             :       }
     331             : 
     332           0 :       if (typeId == TypeId::kVoid)
     333           0 :         return reportError(DebugUtils::errored(kErrorInvalidState));
     334             :     }
     335             :   }
     336             :   else {
     337           0 :     typeId = ArchTraits::byArch(arch()).regTypeToTypeId(ref.type());
     338             :   }
     339             : 
     340           0 :   Error err = ArchUtils::typeIdToRegSignature(arch(), typeId, &typeId, &regSignature);
     341           0 :   if (ASMJIT_UNLIKELY(err))
     342           0 :     return reportError(err);
     343             : 
     344             :   VirtReg* vReg;
     345           0 :   ASMJIT_PROPAGATE(newVirtReg(&vReg, typeId, regSignature, name));
     346           0 :   ASMJIT_ASSUME(vReg != nullptr);
     347             : 
     348             :   out->_initReg(regSignature, vReg->id());
     349           0 :   return kErrorOk;
     350             : }
     351             : 
     352           0 : Error BaseCompiler::_newRegFmt(BaseReg* out, const BaseReg& ref, const char* fmt, ...) {
     353             :   va_list ap;
     354             :   StringTmp<256> sb;
     355             : 
     356           0 :   va_start(ap, fmt);
     357             :   sb.appendVFormat(fmt, ap);
     358           0 :   va_end(ap);
     359             : 
     360           0 :   return _newReg(out, ref, sb.data());
     361             : }
     362             : 
     363           0 : Error BaseCompiler::_newStack(BaseMem* out, uint32_t size, uint32_t alignment, const char* name) {
     364             :   out->reset();
     365             : 
     366           0 :   if (size == 0)
     367           0 :     return reportError(DebugUtils::errored(kErrorInvalidArgument));
     368             : 
     369             :   if (alignment == 0)
     370             :     alignment = 1;
     371             : 
     372             :   if (!Support::isPowerOf2(alignment))
     373           0 :     return reportError(DebugUtils::errored(kErrorInvalidArgument));
     374             : 
     375           0 :   if (alignment > 64)
     376             :     alignment = 64;
     377             : 
     378             :   VirtReg* vReg;
     379           0 :   ASMJIT_PROPAGATE(newVirtReg(&vReg, TypeId::kVoid, OperandSignature{0}, name));
     380           0 :   ASMJIT_ASSUME(vReg != nullptr);
     381             : 
     382           0 :   vReg->_virtSize = size;
     383           0 :   vReg->_isStack = true;
     384           0 :   vReg->_alignment = uint8_t(alignment);
     385             : 
     386             :   // Set the memory operand to GPD/GPQ and its id to VirtReg.
     387           0 :   *out = BaseMem(OperandSignature::fromOpType(OperandType::kMem) |
     388             :                  OperandSignature::fromMemBaseType(_gpSignature.regType()) |
     389             :                  OperandSignature::fromBits(OperandSignature::kMemRegHomeFlag),
     390             :                  vReg->id(), 0, 0);
     391           0 :   return kErrorOk;
     392             : }
     393             : 
     394           0 : Error BaseCompiler::setStackSize(uint32_t virtId, uint32_t newSize, uint32_t newAlignment) {
     395           0 :   if (!isVirtIdValid(virtId))
     396             :     return DebugUtils::errored(kErrorInvalidVirtId);
     397             : 
     398           0 :   if (newAlignment && !Support::isPowerOf2(newAlignment))
     399           0 :     return reportError(DebugUtils::errored(kErrorInvalidArgument));
     400             : 
     401           0 :   if (newAlignment > 64)
     402             :     newAlignment = 64;
     403             : 
     404             :   VirtReg* vReg = virtRegById(virtId);
     405           0 :   if (newSize)
     406           0 :     vReg->_virtSize = newSize;
     407             : 
     408           0 :   if (newAlignment)
     409           0 :     vReg->_alignment = uint8_t(newAlignment);
     410             : 
     411             :   // This is required if the RAPass is already running. There is a chance that a stack-slot has been already
     412             :   // allocated and in that case it has to be updated as well, otherwise we would allocate wrong amount of memory.
     413           0 :   RAWorkReg* workReg = vReg->_workReg;
     414           0 :   if (workReg && workReg->_stackSlot) {
     415           0 :     workReg->_stackSlot->_size = vReg->_virtSize;
     416           0 :     workReg->_stackSlot->_alignment = vReg->_alignment;
     417             :   }
     418             : 
     419             :   return kErrorOk;
     420             : }
     421             : 
     422           0 : Error BaseCompiler::_newConst(BaseMem* out, ConstPoolScope scope, const void* data, size_t size) {
     423             :   out->reset();
     424             : 
     425           0 :   if (uint32_t(scope) > 1)
     426           0 :     return reportError(DebugUtils::errored(kErrorInvalidArgument));
     427             : 
     428           0 :   if (!_constPools[uint32_t(scope)])
     429           0 :     ASMJIT_PROPAGATE(newConstPoolNode(&_constPools[uint32_t(scope)]));
     430             : 
     431           0 :   ConstPoolNode* pool = _constPools[uint32_t(scope)];
     432             :   size_t off;
     433             :   Error err = pool->add(data, size, off);
     434             : 
     435           0 :   if (ASMJIT_UNLIKELY(err))
     436           0 :     return reportError(err);
     437             : 
     438           0 :   *out = BaseMem(OperandSignature::fromOpType(OperandType::kMem) |
     439             :                  OperandSignature::fromMemBaseType(RegType::kLabelTag) |
     440           0 :                  OperandSignature::fromSize(uint32_t(size)),
     441             :                  pool->labelId(), 0, int32_t(off));
     442           0 :   return kErrorOk;
     443             : }
     444             : 
     445           0 : void BaseCompiler::rename(const BaseReg& reg, const char* fmt, ...) {
     446           0 :   if (!reg.isVirtReg()) return;
     447             : 
     448             :   VirtReg* vReg = virtRegById(reg.id());
     449           0 :   if (!vReg) return;
     450             : 
     451           0 :   if (fmt && fmt[0] != '\0') {
     452             :     char buf[128];
     453             :     va_list ap;
     454             : 
     455           0 :     va_start(ap, fmt);
     456             :     vsnprintf(buf, ASMJIT_ARRAY_SIZE(buf), fmt, ap);
     457           0 :     va_end(ap);
     458             : 
     459           0 :     vReg->_name.setData(&_dataZone, buf, SIZE_MAX);
     460           0 :   }
     461             :   else {
     462           0 :     BaseCompiler_assignGenericName(this, vReg);
     463             :   }
     464             : }
     465             : 
     466             : // BaseCompiler - Jump Annotations
     467             : // ===============================
     468             : 
     469           0 : Error BaseCompiler::newJumpNode(JumpNode** out, InstId instId, InstOptions instOptions, const Operand_& o0, JumpAnnotation* annotation) {
     470           0 :   JumpNode* node = _allocator.allocT<JumpNode>();
     471             :   uint32_t opCount = 1;
     472             : 
     473           0 :   *out = node;
     474           0 :   if (ASMJIT_UNLIKELY(!node))
     475           0 :     return reportError(DebugUtils::errored(kErrorOutOfMemory));
     476             : 
     477             :   node = new(node) JumpNode(this, instId, instOptions, opCount, annotation);
     478             :   node->setOp(0, o0);
     479             :   node->resetOpRange(opCount, JumpNode::kBaseOpCapacity);
     480             : 
     481             :   return kErrorOk;
     482             : }
     483             : 
     484           0 : Error BaseCompiler::emitAnnotatedJump(InstId instId, const Operand_& o0, JumpAnnotation* annotation) {
     485             :   InstOptions options = instOptions() | forcedInstOptions();
     486           0 :   RegOnly extra = extraReg();
     487             :   const char* comment = inlineComment();
     488             : 
     489             :   resetInstOptions();
     490             :   resetInlineComment();
     491             :   resetExtraReg();
     492             : 
     493             :   JumpNode* node;
     494           0 :   ASMJIT_PROPAGATE(newJumpNode(&node, instId, options, o0, annotation));
     495             : 
     496           0 :   node->setExtraReg(extra);
     497           0 :   if (comment)
     498           0 :     node->setInlineComment(static_cast<char*>(_dataZone.dup(comment, strlen(comment), true)));
     499             : 
     500           0 :   addNode(node);
     501           0 :   return kErrorOk;
     502             : }
     503             : 
     504           0 : JumpAnnotation* BaseCompiler::newJumpAnnotation() {
     505           0 :   if (_jumpAnnotations.grow(&_allocator, 1) != kErrorOk) {
     506           0 :     reportError(DebugUtils::errored(kErrorOutOfMemory));
     507           0 :     return nullptr;
     508             :   }
     509             : 
     510           0 :   uint32_t id = _jumpAnnotations.size();
     511           0 :   JumpAnnotation* jumpAnnotation = _allocator.newT<JumpAnnotation>(this, id);
     512             : 
     513           0 :   if (!jumpAnnotation) {
     514           0 :     reportError(DebugUtils::errored(kErrorOutOfMemory));
     515           0 :     return nullptr;
     516             :   }
     517             : 
     518             :   _jumpAnnotations.appendUnsafe(jumpAnnotation);
     519           0 :   return jumpAnnotation;
     520             : }
     521             : 
     522             : // BaseCompiler - Events
     523             : // =====================
     524             : 
     525       27492 : Error BaseCompiler::onAttach(CodeHolder* code) noexcept {
     526       27492 :   ASMJIT_PROPAGATE(Base::onAttach(code));
     527             : 
     528             :   const ArchTraits& archTraits = ArchTraits::byArch(code->arch());
     529       27492 :   RegType nativeRegType = Environment::is32Bit(code->arch()) ? RegType::kGp32 : RegType::kGp64;
     530       27492 :   _gpSignature = archTraits.regTypeToSignature(nativeRegType);
     531             : 
     532       27492 :   Error err = addPassT<GlobalConstPoolPass>();
     533       27492 :   if (ASMJIT_UNLIKELY(err)) {
     534           0 :     onDetach(code);
     535           0 :     return err;
     536             :   }
     537             : 
     538             :   return kErrorOk;
     539             : }
     540             : 
     541           0 : Error BaseCompiler::onDetach(CodeHolder* code) noexcept {
     542           0 :   _func = nullptr;
     543           0 :   _constPools[uint32_t(ConstPoolScope::kLocal)] = nullptr;
     544           0 :   _constPools[uint32_t(ConstPoolScope::kGlobal)] = nullptr;
     545             : 
     546             :   _vRegArray.reset();
     547           0 :   _vRegZone.reset();
     548             : 
     549           0 :   return Base::onDetach(code);
     550             : }
     551             : 
     552             : // FuncPass - Construction & Destruction
     553             : // =====================================
     554             : 
     555       27492 : FuncPass::FuncPass(const char* name) noexcept
     556       27492 :   : Pass(name) {}
     557             : 
     558             : // FuncPass - Run
     559             : // ==============
     560             : 
     561       27492 : Error FuncPass::run(Zone* zone, Logger* logger) {
     562             :   BaseNode* node = cb()->firstNode();
     563       27492 :   if (!node) return kErrorOk;
     564             : 
     565             :   do {
     566             :     if (node->type() == NodeType::kFunc) {
     567             :       FuncNode* func = node->as<FuncNode>();
     568             :       node = func->endNode();
     569       27492 :       ASMJIT_PROPAGATE(runOnFunction(zone, logger, func));
     570             :     }
     571             : 
     572             :     // Find a function by skipping all nodes that are not `NodeType::kFunc`.
     573             :     do {
     574             :       node = node->next();
     575       82476 :     } while (node && node->type() != NodeType::kFunc);
     576       54984 :   } while (node);
     577             : 
     578             :   return kErrorOk;
     579             : }
     580             : 
     581             : ASMJIT_END_NAMESPACE
     582             : 
     583             : #endif // !ASMJIT_NO_COMPILER
     584             : 
     585             : #endif // __PLUMED_HAS_ASMJIT

Generated by: LCOV version 1.16