LCOV - code coverage report
Current view: top level - asmjit - codebuilder.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage (other modules) Lines: 60 257 23.3 %
Date: 2024-10-11 08:09:49 Functions: 10 33 30.3 %

          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_BUILDER)
      35             : 
      36             : // [Dependencies]
      37             : #include "./codebuilder.h"
      38             : 
      39             : // [Api-Begin]
      40             : #include "./asmjit_apibegin.h"
      41             : 
      42             : namespace PLMD {
      43             : namespace asmjit {
      44             : 
      45             : // ============================================================================
      46             : // [asmjit::CodeBuilder - Construction / Destruction]
      47             : // ============================================================================
      48             : 
      49        1944 : CodeBuilder::CodeBuilder() noexcept
      50             :   : CodeEmitter(kTypeBuilder),
      51        1944 :     _cbBaseZone(32768 - Zone::kZoneOverhead),
      52        1944 :     _cbDataZone(16384 - Zone::kZoneOverhead),
      53        1944 :     _cbPassZone(32768 - Zone::kZoneOverhead),
      54        1944 :     _cbHeap(&_cbBaseZone),
      55             :     _cbPasses(),
      56             :     _cbLabels(),
      57        1944 :     _firstNode(nullptr),
      58        1944 :     _lastNode(nullptr),
      59        1944 :     _cursor(nullptr),
      60        1944 :     _position(0),
      61        1944 :     _nodeFlags(0) {}
      62        1944 : CodeBuilder::~CodeBuilder() noexcept {}
      63             : 
      64             : // ============================================================================
      65             : // [asmjit::CodeBuilder - Events]
      66             : // ============================================================================
      67             : 
      68        1944 : Error CodeBuilder::onAttach(CodeHolder* code) noexcept {
      69        1944 :   return Base::onAttach(code);
      70             : }
      71             : 
      72           0 : Error CodeBuilder::onDetach(CodeHolder* code) noexcept {
      73             :   _cbPasses.reset();
      74             :   _cbLabels.reset();
      75           0 :   _cbHeap.reset(&_cbBaseZone);
      76             : 
      77           0 :   _cbBaseZone.reset(false);
      78           0 :   _cbDataZone.reset(false);
      79           0 :   _cbPassZone.reset(false);
      80             : 
      81           0 :   _position = 0;
      82           0 :   _nodeFlags = 0;
      83             : 
      84           0 :   _firstNode = nullptr;
      85           0 :   _lastNode = nullptr;
      86           0 :   _cursor = nullptr;
      87             : 
      88           0 :   return Base::onDetach(code);
      89             : }
      90             : 
      91             : // ============================================================================
      92             : // [asmjit::CodeBuilder - Node-Factory]
      93             : // ============================================================================
      94             : 
      95           0 : Error CodeBuilder::getCBLabel(CBLabel** pOut, uint32_t id) noexcept {
      96           0 :   if (_lastError) return _lastError;
      97             :   ASMJIT_ASSERT(_code != nullptr);
      98             : 
      99           0 :   size_t index = Operand::unpackId(id);
     100           0 :   if (ASMJIT_UNLIKELY(index >= _code->getLabelsCount()))
     101             :     return DebugUtils::errored(kErrorInvalidLabel);
     102             : 
     103           0 :   if (index >= _cbLabels.getLength())
     104           0 :     ASMJIT_PROPAGATE(_cbLabels.resize(&_cbHeap, index + 1));
     105             : 
     106           0 :   CBLabel* node = _cbLabels[index];
     107           0 :   if (!node) {
     108             :     node = newNodeT<CBLabel>(id);
     109           0 :     if (ASMJIT_UNLIKELY(!node))
     110             :       return DebugUtils::errored(kErrorNoHeapMemory);
     111           0 :     _cbLabels[index] = node;
     112             :   }
     113             : 
     114           0 :   *pOut = node;
     115           0 :   return kErrorOk;
     116             : }
     117             : 
     118        3888 : Error CodeBuilder::registerLabelNode(CBLabel* node) noexcept {
     119        3888 :   if (_lastError) return _lastError;
     120             :   ASMJIT_ASSERT(_code != nullptr);
     121             : 
     122             :   // Don't call setLastError() from here, we are noexcept and we are called
     123             :   // by `newLabelNode()` and `newFuncNode()`, which are noexcept as well.
     124             :   uint32_t id;
     125        3888 :   ASMJIT_PROPAGATE(_code->newLabelId(id));
     126        3888 :   size_t index = Operand::unpackId(id);
     127             : 
     128             :   // We just added one label so it must be true.
     129             :   ASMJIT_ASSERT(_cbLabels.getLength() < index + 1);
     130        3888 :   ASMJIT_PROPAGATE(_cbLabels.resize(&_cbHeap, index + 1));
     131             : 
     132        3888 :   _cbLabels[index] = node;
     133        3888 :   node->_id = id;
     134        3888 :   return kErrorOk;
     135             : }
     136             : 
     137        1944 : CBLabel* CodeBuilder::newLabelNode() noexcept {
     138             :   CBLabel* node = newNodeT<CBLabel>();
     139        1944 :   if (!node || registerLabelNode(node) != kErrorOk)
     140           0 :     return nullptr;
     141             :   return node;
     142             : }
     143             : 
     144           0 : CBAlign* CodeBuilder::newAlignNode(uint32_t mode, uint32_t alignment) noexcept {
     145           0 :   return newNodeT<CBAlign>(mode, alignment);
     146             : }
     147             : 
     148           0 : CBData* CodeBuilder::newDataNode(const void* data, uint32_t size) noexcept {
     149           0 :   if (size > CBData::kInlineBufferSize) {
     150           0 :     void* cloned = _cbDataZone.alloc(size);
     151           0 :     if (!cloned) return nullptr;
     152             : 
     153           0 :     if (data) ::memcpy(cloned, data, size);
     154             :     data = cloned;
     155             :   }
     156             : 
     157           0 :   return newNodeT<CBData>(const_cast<void*>(data), size);
     158             : }
     159             : 
     160           0 : CBConstPool* CodeBuilder::newConstPool() noexcept {
     161             :   CBConstPool* node = newNodeT<CBConstPool>();
     162           0 :   if (!node || registerLabelNode(node) != kErrorOk)
     163           0 :     return nullptr;
     164             :   return node;
     165             : }
     166             : 
     167           0 : CBComment* CodeBuilder::newCommentNode(const char* s, size_t len) noexcept {
     168           0 :   if (s) {
     169           0 :     if (len == Globals::kInvalidIndex) len = ::strlen(s);
     170           0 :     if (len > 0) {
     171           0 :       s = static_cast<char*>(_cbDataZone.dup(s, len, true));
     172           0 :       if (!s) return nullptr;
     173             :     }
     174             :   }
     175             : 
     176           0 :   return newNodeT<CBComment>(s);
     177             : }
     178             : 
     179             : // ============================================================================
     180             : // [asmjit::CodeBuilder - Code-Emitter]
     181             : // ============================================================================
     182             : 
     183           0 : Label CodeBuilder::newLabel() {
     184             :   uint32_t id = kInvalidValue;
     185             : 
     186           0 :   if (!_lastError) {
     187             :     CBLabel* node = newNodeT<CBLabel>(id);
     188           0 :     if (ASMJIT_UNLIKELY(!node)) {
     189           0 :       setLastError(DebugUtils::errored(kErrorNoHeapMemory));
     190             :     }
     191             :     else {
     192           0 :       Error err = registerLabelNode(node);
     193           0 :       if (ASMJIT_UNLIKELY(err))
     194           0 :         setLastError(err);
     195             :       else
     196             :         id = node->getId();
     197             :     }
     198             :   }
     199             : 
     200           0 :   return Label(id);
     201             : }
     202             : 
     203           0 : Label CodeBuilder::newNamedLabel(const char* name, size_t nameLength, uint32_t type, uint32_t parentId) {
     204           0 :   uint32_t id = kInvalidValue;
     205             : 
     206           0 :   if (!_lastError) {
     207             :     CBLabel* node = newNodeT<CBLabel>(id);
     208           0 :     if (ASMJIT_UNLIKELY(!node)) {
     209           0 :       setLastError(DebugUtils::errored(kErrorNoHeapMemory));
     210             :     }
     211             :     else {
     212           0 :       Error err = _code->newNamedLabelId(id, name, nameLength, type, parentId);
     213           0 :       if (ASMJIT_UNLIKELY(err))
     214           0 :         setLastError(err);
     215             :       else
     216           0 :         id = node->getId();
     217             :     }
     218             :   }
     219             : 
     220           0 :   return Label(id);
     221             : }
     222             : 
     223           0 : Error CodeBuilder::bind(const Label& label) {
     224           0 :   if (_lastError) return _lastError;
     225             : 
     226             :   CBLabel* node;
     227             :   Error err = getCBLabel(&node, label);
     228           0 :   if (ASMJIT_UNLIKELY(err))
     229           0 :     return setLastError(err);
     230             : 
     231           0 :   addNode(node);
     232           0 :   return kErrorOk;
     233             : }
     234             : 
     235           0 : Error CodeBuilder::align(uint32_t mode, uint32_t alignment) {
     236           0 :   if (_lastError) return _lastError;
     237             : 
     238           0 :   CBAlign* node = newAlignNode(mode, alignment);
     239           0 :   if (ASMJIT_UNLIKELY(!node))
     240           0 :     return setLastError(DebugUtils::errored(kErrorNoHeapMemory));
     241             : 
     242           0 :   addNode(node);
     243           0 :   return kErrorOk;
     244             : }
     245             : 
     246           0 : Error CodeBuilder::embed(const void* data, uint32_t size) {
     247           0 :   if (_lastError) return _lastError;
     248             : 
     249           0 :   CBData* node = newDataNode(data, size);
     250           0 :   if (ASMJIT_UNLIKELY(!node))
     251           0 :     return setLastError(DebugUtils::errored(kErrorNoHeapMemory));
     252             : 
     253           0 :   addNode(node);
     254           0 :   return kErrorOk;
     255             : }
     256             : 
     257           0 : Error CodeBuilder::embedLabel(const Label& label) {
     258           0 :   if (_lastError) return _lastError;
     259             : 
     260             :   CBLabelData* node = newNodeT<CBLabelData>(label.getId());
     261           0 :   if (ASMJIT_UNLIKELY(!node))
     262           0 :     return setLastError(DebugUtils::errored(kErrorNoHeapMemory));
     263             : 
     264           0 :   addNode(node);
     265           0 :   return kErrorOk;
     266             : }
     267             : 
     268           0 : Error CodeBuilder::embedConstPool(const Label& label, const ConstPool& pool) {
     269           0 :   if (_lastError) return _lastError;
     270             : 
     271           0 :   if (!isLabelValid(label))
     272           0 :     return setLastError(DebugUtils::errored(kErrorInvalidLabel));
     273             : 
     274           0 :   ASMJIT_PROPAGATE(align(kAlignData, static_cast<uint32_t>(pool.getAlignment())));
     275           0 :   ASMJIT_PROPAGATE(bind(label));
     276             : 
     277           0 :   CBData* node = newDataNode(nullptr, static_cast<uint32_t>(pool.getSize()));
     278           0 :   if (ASMJIT_UNLIKELY(!node))
     279           0 :     return setLastError(DebugUtils::errored(kErrorNoHeapMemory));
     280             : 
     281           0 :   pool.fill(node->getData());
     282           0 :   addNode(node);
     283           0 :   return kErrorOk;
     284             : }
     285             : 
     286           0 : Error CodeBuilder::comment(const char* s, size_t len) {
     287           0 :   if (_lastError) return _lastError;
     288             : 
     289           0 :   CBComment* node = newCommentNode(s, len);
     290           0 :   if (ASMJIT_UNLIKELY(!node))
     291           0 :     return setLastError(DebugUtils::errored(kErrorNoHeapMemory));
     292             : 
     293           0 :   addNode(node);
     294           0 :   return kErrorOk;
     295             : }
     296             : 
     297             : // ============================================================================
     298             : // [asmjit::CodeBuilder - Node-Management]
     299             : // ============================================================================
     300             : 
     301       56030 : CBNode* CodeBuilder::addNode(CBNode* node) noexcept {
     302             :   ASMJIT_ASSERT(node);
     303             :   ASMJIT_ASSERT(node->_prev == nullptr);
     304             :   ASMJIT_ASSERT(node->_next == nullptr);
     305             : 
     306       56030 :   if (!_cursor) {
     307        1944 :     if (!_firstNode) {
     308        1944 :       _firstNode = node;
     309        1944 :       _lastNode = node;
     310             :     }
     311             :     else {
     312           0 :       node->_next = _firstNode;
     313           0 :       _firstNode->_prev = node;
     314           0 :       _firstNode = node;
     315             :     }
     316             :   }
     317             :   else {
     318             :     CBNode* prev = _cursor;
     319       54086 :     CBNode* next = _cursor->_next;
     320             : 
     321       54086 :     node->_prev = prev;
     322       54086 :     node->_next = next;
     323             : 
     324       54086 :     prev->_next = node;
     325       54086 :     if (next)
     326       50198 :       next->_prev = node;
     327             :     else
     328        3888 :       _lastNode = node;
     329             :   }
     330             : 
     331       56030 :   _cursor = node;
     332       56030 :   return node;
     333             : }
     334             : 
     335           0 : CBNode* CodeBuilder::addAfter(CBNode* node, CBNode* ref) noexcept {
     336             :   ASMJIT_ASSERT(node);
     337             :   ASMJIT_ASSERT(ref);
     338             : 
     339             :   ASMJIT_ASSERT(node->_prev == nullptr);
     340             :   ASMJIT_ASSERT(node->_next == nullptr);
     341             : 
     342             :   CBNode* prev = ref;
     343           0 :   CBNode* next = ref->_next;
     344             : 
     345           0 :   node->_prev = prev;
     346           0 :   node->_next = next;
     347             : 
     348           0 :   prev->_next = node;
     349           0 :   if (next)
     350           0 :     next->_prev = node;
     351             :   else
     352           0 :     _lastNode = node;
     353             : 
     354           0 :   return node;
     355             : }
     356             : 
     357           0 : CBNode* CodeBuilder::addBefore(CBNode* node, CBNode* ref) noexcept {
     358             :   ASMJIT_ASSERT(node != nullptr);
     359             :   ASMJIT_ASSERT(node->_prev == nullptr);
     360             :   ASMJIT_ASSERT(node->_next == nullptr);
     361             :   ASMJIT_ASSERT(ref != nullptr);
     362             : 
     363           0 :   CBNode* prev = ref->_prev;
     364             :   CBNode* next = ref;
     365             : 
     366           0 :   node->_prev = prev;
     367           0 :   node->_next = next;
     368             : 
     369           0 :   next->_prev = node;
     370           0 :   if (prev)
     371           0 :     prev->_next = node;
     372             :   else
     373           0 :     _firstNode = node;
     374             : 
     375           0 :   return node;
     376             : }
     377             : 
     378             : static ASMJIT_INLINE void CodeBuilder_nodeRemoved(CodeBuilder* self, CBNode* node_) noexcept {
     379           0 :   if (node_->isJmpOrJcc()) {
     380             :     CBJump* node = static_cast<CBJump*>(node_);
     381             :     CBLabel* label = node->getTarget();
     382             : 
     383           0 :     if (label) {
     384             :       // Disconnect.
     385           0 :       CBJump** pPrev = &label->_from;
     386             :       for (;;) {
     387             :         ASMJIT_ASSERT(*pPrev != nullptr);
     388             : 
     389           0 :         CBJump* current = *pPrev;
     390           0 :         if (!current) break;
     391             : 
     392           0 :         if (current == node) {
     393           0 :           *pPrev = node->_jumpNext;
     394           0 :           break;
     395             :         }
     396             : 
     397           0 :         pPrev = &current->_jumpNext;
     398           0 :       }
     399             : 
     400             :       label->subNumRefs();
     401             :     }
     402             :   }
     403             : }
     404             : 
     405           0 : CBNode* CodeBuilder::removeNode(CBNode* node) noexcept {
     406           0 :   CBNode* prev = node->_prev;
     407           0 :   CBNode* next = node->_next;
     408             : 
     409           0 :   if (_firstNode == node)
     410           0 :     _firstNode = next;
     411             :   else
     412           0 :     prev->_next = next;
     413             : 
     414           0 :   if (_lastNode == node)
     415           0 :     _lastNode  = prev;
     416             :   else
     417           0 :     next->_prev = prev;
     418             : 
     419           0 :   node->_prev = nullptr;
     420           0 :   node->_next = nullptr;
     421             : 
     422           0 :   if (_cursor == node)
     423           0 :     _cursor = prev;
     424             :   CodeBuilder_nodeRemoved(this, node);
     425             : 
     426           0 :   return node;
     427             : }
     428             : 
     429           0 : void CodeBuilder::removeNodes(CBNode* first, CBNode* last) noexcept {
     430           0 :   if (first == last) {
     431           0 :     removeNode(first);
     432           0 :     return;
     433             :   }
     434             : 
     435           0 :   CBNode* prev = first->_prev;
     436           0 :   CBNode* next = last->_next;
     437             : 
     438           0 :   if (_firstNode == first)
     439           0 :     _firstNode = next;
     440             :   else
     441           0 :     prev->_next = next;
     442             : 
     443           0 :   if (_lastNode == last)
     444           0 :     _lastNode  = prev;
     445             :   else
     446           0 :     next->_prev = prev;
     447             : 
     448             :   CBNode* node = first;
     449             :   for (;;) {
     450             :     CBNode* next = node->getNext();
     451             :     ASMJIT_ASSERT(next != nullptr);
     452             : 
     453           0 :     node->_prev = nullptr;
     454           0 :     node->_next = nullptr;
     455             : 
     456           0 :     if (_cursor == node)
     457           0 :       _cursor = prev;
     458             :     CodeBuilder_nodeRemoved(this, node);
     459             : 
     460           0 :     if (node == last)
     461             :       break;
     462             :     node = next;
     463             :   }
     464             : }
     465             : 
     466        3888 : CBNode* CodeBuilder::setCursor(CBNode* node) noexcept {
     467        3888 :   CBNode* old = _cursor;
     468        3888 :   _cursor = node;
     469        3888 :   return old;
     470             : }
     471             : 
     472             : // ============================================================================
     473             : // [asmjit::CodeBuilder - Passes]
     474             : // ============================================================================
     475             : 
     476           0 : ASMJIT_FAVOR_SIZE CBPass* CodeBuilder::getPassByName(const char* name) const noexcept {
     477           0 :   for (size_t i = 0, len = _cbPasses.getLength(); i < len; i++) {
     478           0 :     CBPass* pass = _cbPasses[i];
     479           0 :     if (::strcmp(pass->getName(), name) == 0)
     480           0 :       return pass;
     481             :   }
     482             : 
     483             :   return nullptr;
     484             : }
     485             : 
     486        1944 : ASMJIT_FAVOR_SIZE Error CodeBuilder::addPass(CBPass* pass) noexcept {
     487        1944 :   if (ASMJIT_UNLIKELY(pass == nullptr)) {
     488             :     // Since this is directly called by `addPassT()` we treat `null` argument
     489             :     // as out-of-memory condition. Otherwise it would be API misuse.
     490             :     return DebugUtils::errored(kErrorNoHeapMemory);
     491             :   }
     492        1944 :   else if (ASMJIT_UNLIKELY(pass->_cb)) {
     493             :     // Kind of weird, but okay...
     494           0 :     if (pass->_cb == this)
     495           0 :       return kErrorOk;
     496             :     return DebugUtils::errored(kErrorInvalidState);
     497             :   }
     498             : 
     499        1944 :   ASMJIT_PROPAGATE(_cbPasses.append(&_cbHeap, pass));
     500        1944 :   pass->_cb = this;
     501        1944 :   return kErrorOk;
     502             : }
     503             : 
     504           0 : ASMJIT_FAVOR_SIZE Error CodeBuilder::deletePass(CBPass* pass) noexcept {
     505           0 :   if (ASMJIT_UNLIKELY(pass == nullptr))
     506             :     return DebugUtils::errored(kErrorInvalidArgument);
     507             : 
     508           0 :   if (pass->_cb != nullptr) {
     509           0 :     if (pass->_cb != this)
     510             :       return DebugUtils::errored(kErrorInvalidState);
     511             : 
     512             :     size_t index = _cbPasses.indexOf(pass);
     513             :     ASMJIT_ASSERT(index != Globals::kInvalidIndex);
     514             : 
     515           0 :     pass->_cb = nullptr;
     516             :     _cbPasses.removeAt(index);
     517             :   }
     518             : 
     519           0 :   pass->~CBPass();
     520           0 :   return kErrorOk;
     521             : }
     522             : 
     523             : // ============================================================================
     524             : // [asmjit::CodeBuilder - Serialization]
     525             : // ============================================================================
     526             : 
     527        1944 : Error CodeBuilder::serialize(CodeEmitter* dst) {
     528             :   Error err = kErrorOk;
     529             :   CBNode* node_ = getFirstNode();
     530             : 
     531             :   do {
     532             :     dst->setInlineComment(node_->getInlineComment());
     533             : 
     534       56030 :     switch (node_->getType()) {
     535           0 :       case CBNode::kNodeAlign: {
     536             :         CBAlign* node = static_cast<CBAlign*>(node_);
     537           0 :         err = dst->align(node->getMode(), node->getAlignment());
     538           0 :         break;
     539             :       }
     540             : 
     541           0 :       case CBNode::kNodeData: {
     542             :         CBData* node = static_cast<CBData*>(node_);
     543           0 :         err = dst->embed(node->getData(), node->getSize());
     544           0 :         break;
     545             :       }
     546             : 
     547        3888 :       case CBNode::kNodeFunc:
     548             :       case CBNode::kNodeLabel: {
     549             :         CBLabel* node = static_cast<CBLabel*>(node_);
     550        3888 :         err = dst->bind(node->getLabel());
     551        3888 :         break;
     552             :       }
     553             : 
     554           0 :       case CBNode::kNodeLabelData: {
     555             :         CBLabelData* node = static_cast<CBLabelData*>(node_);
     556           0 :         err = dst->embedLabel(node->getLabel());
     557           0 :         break;
     558             :       }
     559             : 
     560           0 :       case CBNode::kNodeConstPool: {
     561             :         CBConstPool* node = static_cast<CBConstPool*>(node_);
     562           0 :         err = dst->embedConstPool(node->getLabel(), node->getConstPool());
     563           0 :         break;
     564             :       }
     565             : 
     566             :       case CBNode::kNodeInst:
     567             :       case CBNode::kNodeFuncCall: {
     568             :         CBInst* node = node_->as<CBInst>();
     569             :         dst->setOptions(node->getOptions());
     570             :         dst->setExtraReg(node->getExtraReg());
     571       48254 :         err = dst->emitOpArray(node->getInstId(), node->getOpArray(), node->getOpCount());
     572       48254 :         break;
     573             :       }
     574             : 
     575           0 :       case CBNode::kNodeComment: {
     576             :         CBComment* node = static_cast<CBComment*>(node_);
     577           0 :         err = dst->comment(node->getInlineComment());
     578           0 :         break;
     579             :       }
     580             : 
     581             :       default:
     582             :         break;
     583             :     }
     584             : 
     585       56030 :     if (err) break;
     586             :     node_ = node_->getNext();
     587       56030 :   } while (node_);
     588             : 
     589        1944 :   return err;
     590             : }
     591             : 
     592             : // ============================================================================
     593             : // [asmjit::CBPass]
     594             : // ============================================================================
     595             : 
     596        1944 : CBPass::CBPass(const char* name) noexcept
     597        1944 :   : _cb(nullptr),
     598        1944 :     _name(name) {}
     599           0 : CBPass::~CBPass() noexcept {}
     600             : 
     601             : } // asmjit namespace
     602             : } // namespace PLMD
     603             : 
     604             : // [Api-End]
     605             : #include "./asmjit_apiend.h"
     606             : 
     607             : // [Guard]
     608             : #endif // !ASMJIT_DISABLE_BUILDER
     609             : #pragma GCC diagnostic pop
     610             : #endif // __PLUMED_HAS_ASMJIT

Generated by: LCOV version 1.15