LCOV - code coverage report
Current view: top level - asmjit - builder.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage (other modules) Lines: 125 376 33.2 %
Date: 2026-11-05 10:19:06 Functions: 16 44 36.4 %

          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_BUILDER
       9             : 
      10             : #include "builder.h"
      11             : #include "emitterutils_p.h"
      12             : #include "errorhandler.h"
      13             : #include "formatter.h"
      14             : #include "logger.h"
      15             : #include "support.h"
      16             : 
      17             : ASMJIT_BEGIN_NAMESPACE
      18             : 
      19             : // PostponedErrorHandler (Internal)
      20             : // ================================
      21             : 
      22             : //! Postponed error handler that never throws. Used as a temporal error handler
      23             : //! to run passes. If error occurs, the caller is notified and will call the
      24             : //! real error handler, that can throw.
      25             : class PostponedErrorHandler : public ErrorHandler {
      26             : public:
      27           0 :   void handleError(Error err, const char* message, BaseEmitter* origin) override {
      28             :     DebugUtils::unused(err, origin);
      29           0 :     _message.assign(message);
      30           0 :   }
      31             : 
      32             :   StringTmp<128> _message;
      33             : };
      34             : 
      35             : // BaseBuilder - Utilities
      36             : // =======================
      37             : 
      38       27492 : static void BaseBuilder_deletePasses(BaseBuilder* self) noexcept {
      39       82476 :   for (Pass* pass : self->_passes)
      40       54984 :     pass->~Pass();
      41             :   self->_passes.reset();
      42       27492 : }
      43             : 
      44             : // BaseBuilder - Construction & Destruction
      45             : // ========================================
      46             : 
      47       27492 : BaseBuilder::BaseBuilder() noexcept
      48             :   : BaseEmitter(EmitterType::kBuilder),
      49       27492 :     _codeZone(32768 - Zone::kBlockOverhead),
      50       27492 :     _dataZone(16384 - Zone::kBlockOverhead),
      51       27492 :     _passZone(65536 - Zone::kBlockOverhead),
      52       54984 :     _allocator(&_codeZone) {}
      53             : 
      54       27492 : BaseBuilder::~BaseBuilder() noexcept {
      55       27492 :   BaseBuilder_deletePasses(this);
      56       27492 : }
      57             : 
      58             : // BaseBuilder - Node Management
      59             : // =============================
      60             : 
      61           0 : Error BaseBuilder::newInstNode(InstNode** out, InstId instId, InstOptions instOptions, uint32_t opCount) {
      62             :   uint32_t opCapacity = InstNode::capacityOfOpCount(opCount);
      63             :   ASMJIT_ASSERT(opCapacity >= InstNode::kBaseOpCapacity);
      64             : 
      65           0 :   InstNode* node = _allocator.allocT<InstNode>(InstNode::nodeSizeOfOpCapacity(opCapacity));
      66           0 :   if (ASMJIT_UNLIKELY(!node))
      67           0 :     return reportError(DebugUtils::errored(kErrorOutOfMemory));
      68             : 
      69           0 :   *out = new(node) InstNode(this, instId, instOptions, opCount, opCapacity);
      70           0 :   return kErrorOk;
      71             : }
      72             : 
      73             : 
      74       27492 : Error BaseBuilder::newLabelNode(LabelNode** out) {
      75       27492 :   *out = nullptr;
      76             : 
      77       27492 :   ASMJIT_PROPAGATE(_newNodeT<LabelNode>(out));
      78       27492 :   return registerLabelNode(*out);
      79             : }
      80             : 
      81           0 : Error BaseBuilder::newAlignNode(AlignNode** out, AlignMode alignMode, uint32_t alignment) {
      82           0 :   *out = nullptr;
      83           0 :   return _newNodeT<AlignNode>(out, alignMode, alignment);
      84             : }
      85             : 
      86           0 : Error BaseBuilder::newEmbedDataNode(EmbedDataNode** out, TypeId typeId, const void* data, size_t itemCount, size_t repeatCount) {
      87           0 :   *out = nullptr;
      88             : 
      89             :   uint32_t deabstractDelta = TypeUtils::deabstractDeltaOfSize(registerSize());
      90             :   TypeId finalTypeId = TypeUtils::deabstract(typeId, deabstractDelta);
      91             : 
      92           0 :   if (ASMJIT_UNLIKELY(!TypeUtils::isValid(finalTypeId)))
      93           0 :     return reportError(DebugUtils::errored(kErrorInvalidArgument));
      94             : 
      95             :   uint32_t typeSize = TypeUtils::sizeOf(finalTypeId);
      96             :   Support::FastUInt8 of = 0;
      97             : 
      98             :   size_t dataSize = Support::mulOverflow(itemCount, size_t(typeSize), &of);
      99           0 :   if (ASMJIT_UNLIKELY(of))
     100           0 :     return reportError(DebugUtils::errored(kErrorOutOfMemory));
     101             : 
     102             :   EmbedDataNode* node;
     103           0 :   ASMJIT_PROPAGATE(_newNodeT<EmbedDataNode>(&node));
     104             : 
     105           0 :   node->_embed._typeId = typeId;
     106           0 :   node->_embed._typeSize = uint8_t(typeSize);
     107           0 :   node->_itemCount = itemCount;
     108           0 :   node->_repeatCount = repeatCount;
     109             : 
     110           0 :   uint8_t* dstData = node->_inlineData;
     111           0 :   if (dataSize > EmbedDataNode::kInlineBufferSize) {
     112           0 :     dstData = static_cast<uint8_t*>(_dataZone.alloc(dataSize, 8));
     113           0 :     if (ASMJIT_UNLIKELY(!dstData))
     114           0 :       return reportError(DebugUtils::errored(kErrorOutOfMemory));
     115           0 :     node->_externalData = dstData;
     116             :   }
     117             : 
     118           0 :   if (data)
     119             :     memcpy(dstData, data, dataSize);
     120             : 
     121           0 :   *out = node;
     122           0 :   return kErrorOk;
     123             : }
     124             : 
     125           0 : Error BaseBuilder::newConstPoolNode(ConstPoolNode** out) {
     126           0 :   *out = nullptr;
     127             : 
     128           0 :   ASMJIT_PROPAGATE(_newNodeT<ConstPoolNode>(out));
     129           0 :   return registerLabelNode(*out);
     130             : }
     131             : 
     132           0 : Error BaseBuilder::newCommentNode(CommentNode** out, const char* data, size_t size) {
     133           0 :   *out = nullptr;
     134             : 
     135           0 :   if (data) {
     136           0 :     if (size == SIZE_MAX)
     137           0 :       size = strlen(data);
     138             : 
     139           0 :     if (size > 0) {
     140           0 :       data = static_cast<char*>(_dataZone.dup(data, size, true));
     141           0 :       if (ASMJIT_UNLIKELY(!data))
     142           0 :         return reportError(DebugUtils::errored(kErrorOutOfMemory));
     143             :     }
     144             :   }
     145             : 
     146           0 :   return _newNodeT<CommentNode>(out, data);
     147             : }
     148             : 
     149      501977 : BaseNode* BaseBuilder::addNode(BaseNode* node) noexcept {
     150             :   ASMJIT_ASSERT(!node->_prev);
     151             :   ASMJIT_ASSERT(!node->_next);
     152             :   ASMJIT_ASSERT(!node->isActive());
     153             : 
     154      501977 :   if (!_cursor) {
     155           0 :     if (!_firstNode) {
     156           0 :       _firstNode = node;
     157           0 :       _lastNode = node;
     158             :     }
     159             :     else {
     160           0 :       node->_next = _firstNode;
     161           0 :       _firstNode->_prev = node;
     162           0 :       _firstNode = node;
     163             :     }
     164             :   }
     165             :   else {
     166             :     BaseNode* prev = _cursor;
     167             :     BaseNode* next = _cursor->next();
     168             : 
     169      501977 :     node->_prev = prev;
     170      501977 :     node->_next = next;
     171             : 
     172      501977 :     prev->_next = node;
     173      501977 :     if (next)
     174      419501 :       next->_prev = node;
     175             :     else
     176       82476 :       _lastNode = node;
     177             :   }
     178             : 
     179             :   node->addFlags(NodeFlags::kIsActive);
     180      501977 :   if (node->isSection())
     181           0 :     _dirtySectionLinks = true;
     182             : 
     183      501977 :   _cursor = node;
     184      501977 :   return node;
     185             : }
     186             : 
     187           0 : BaseNode* BaseBuilder::addAfter(BaseNode* node, BaseNode* ref) noexcept {
     188             :   ASMJIT_ASSERT(!node->_prev);
     189             :   ASMJIT_ASSERT(!node->_next);
     190             : 
     191             :   BaseNode* prev = ref;
     192             :   BaseNode* next = ref->next();
     193             : 
     194           0 :   node->_prev = prev;
     195           0 :   node->_next = next;
     196             : 
     197             :   node->addFlags(NodeFlags::kIsActive);
     198           0 :   if (node->isSection())
     199           0 :     _dirtySectionLinks = true;
     200             : 
     201           0 :   prev->_next = node;
     202           0 :   if (next)
     203           0 :     next->_prev = node;
     204             :   else
     205           0 :     _lastNode = node;
     206             : 
     207           0 :   return node;
     208             : }
     209             : 
     210           0 : BaseNode* BaseBuilder::addBefore(BaseNode* node, BaseNode* ref) noexcept {
     211             :   ASMJIT_ASSERT(!node->_prev);
     212             :   ASMJIT_ASSERT(!node->_next);
     213             :   ASMJIT_ASSERT(!node->isActive());
     214             :   ASMJIT_ASSERT(ref->isActive());
     215             : 
     216             :   BaseNode* prev = ref->prev();
     217             :   BaseNode* next = ref;
     218             : 
     219           0 :   node->_prev = prev;
     220           0 :   node->_next = next;
     221             : 
     222             :   node->addFlags(NodeFlags::kIsActive);
     223           0 :   if (node->isSection())
     224           0 :     _dirtySectionLinks = true;
     225             : 
     226           0 :   next->_prev = node;
     227           0 :   if (prev)
     228           0 :     prev->_next = node;
     229             :   else
     230           0 :     _firstNode = node;
     231             : 
     232           0 :   return node;
     233             : }
     234             : 
     235       27492 : BaseNode* BaseBuilder::removeNode(BaseNode* node) noexcept {
     236       27492 :   if (!node->isActive())
     237             :     return node;
     238             : 
     239             :   BaseNode* prev = node->prev();
     240             :   BaseNode* next = node->next();
     241             : 
     242       27492 :   if (_firstNode == node)
     243           0 :     _firstNode = next;
     244             :   else
     245       27492 :     prev->_next = next;
     246             : 
     247       27492 :   if (_lastNode == node)
     248           0 :     _lastNode  = prev;
     249             :   else
     250       27492 :     next->_prev = prev;
     251             : 
     252       27492 :   node->_prev = nullptr;
     253       27492 :   node->_next = nullptr;
     254             :   node->clearFlags(NodeFlags::kIsActive);
     255       27492 :   if (node->isSection())
     256           0 :     _dirtySectionLinks = true;
     257             : 
     258       27492 :   if (_cursor == node)
     259           0 :     _cursor = prev;
     260             : 
     261             :   return node;
     262             : }
     263             : 
     264           0 : void BaseBuilder::removeNodes(BaseNode* first, BaseNode* last) noexcept {
     265           0 :   if (first == last) {
     266           0 :     removeNode(first);
     267           0 :     return;
     268             :   }
     269             : 
     270           0 :   if (!first->isActive())
     271             :     return;
     272             : 
     273             :   BaseNode* prev = first->prev();
     274             :   BaseNode* next = last->next();
     275             : 
     276           0 :   if (_firstNode == first)
     277           0 :     _firstNode = next;
     278             :   else
     279           0 :     prev->_next = next;
     280             : 
     281           0 :   if (_lastNode == last)
     282           0 :     _lastNode  = prev;
     283             :   else
     284           0 :     next->_prev = prev;
     285             : 
     286             :   BaseNode* node = first;
     287             :   uint32_t didRemoveSection = false;
     288             : 
     289             :   for (;;) {
     290             :     next = node->next();
     291             :     ASMJIT_ASSERT(next != nullptr);
     292             : 
     293           0 :     node->_prev = nullptr;
     294           0 :     node->_next = nullptr;
     295             :     node->clearFlags(NodeFlags::kIsActive);
     296           0 :     didRemoveSection |= uint32_t(node->isSection());
     297             : 
     298           0 :     if (_cursor == node)
     299           0 :       _cursor = prev;
     300             : 
     301           0 :     if (node == last)
     302             :       break;
     303             :     node = next;
     304             :   }
     305             : 
     306           0 :   if (didRemoveSection)
     307           0 :     _dirtySectionLinks = true;
     308             : }
     309             : 
     310       27492 : BaseNode* BaseBuilder::setCursor(BaseNode* node) noexcept {
     311       27492 :   BaseNode* old = _cursor;
     312       27492 :   _cursor = node;
     313       27492 :   return old;
     314             : }
     315             : 
     316             : // BaseBuilder - Sections
     317             : // ======================
     318             : 
     319       27492 : Error BaseBuilder::sectionNodeOf(SectionNode** out, uint32_t sectionId) {
     320       27492 :   *out = nullptr;
     321             : 
     322       27492 :   if (ASMJIT_UNLIKELY(!_code))
     323             :     return DebugUtils::errored(kErrorNotInitialized);
     324             : 
     325       27492 :   if (ASMJIT_UNLIKELY(!_code->isSectionValid(sectionId)))
     326           0 :     return reportError(DebugUtils::errored(kErrorInvalidSection));
     327             : 
     328       27492 :   if (sectionId >= _sectionNodes.size()) {
     329       27492 :     Error err = _sectionNodes.reserve(&_allocator, sectionId + 1);
     330       27492 :     if (ASMJIT_UNLIKELY(err != kErrorOk))
     331           0 :       return reportError(err);
     332             :   }
     333             : 
     334       27492 :   SectionNode* node = nullptr;
     335       27492 :   if (sectionId < _sectionNodes.size())
     336           0 :     node = _sectionNodes[sectionId];
     337             : 
     338       27492 :   if (!node) {
     339       27492 :     ASMJIT_PROPAGATE(_newNodeT<SectionNode>(&node, sectionId));
     340             : 
     341             :     // We have already reserved enough space, this cannot fail now.
     342       27492 :     if (sectionId >= _sectionNodes.size())
     343       27492 :       _sectionNodes.resize(&_allocator, sectionId + 1);
     344             : 
     345       27492 :     _sectionNodes[sectionId] = node;
     346             :   }
     347             : 
     348       27492 :   *out = node;
     349       27492 :   return kErrorOk;
     350             : }
     351             : 
     352           0 : Error BaseBuilder::section(Section* section) {
     353             :   SectionNode* node;
     354           0 :   ASMJIT_PROPAGATE(sectionNodeOf(&node, section->id()));
     355           0 :   ASMJIT_ASSUME(node != nullptr);
     356             : 
     357           0 :   if (!node->isActive()) {
     358             :     // Insert the section at the end if it was not part of the code.
     359           0 :     addAfter(node, lastNode());
     360           0 :     _cursor = node;
     361             :   }
     362             :   else {
     363             :     // This is a bit tricky. We cache section links to make sure that
     364             :     // switching sections doesn't involve traversal in linked-list unless
     365             :     // the position of the section has changed.
     366           0 :     if (hasDirtySectionLinks())
     367           0 :       updateSectionLinks();
     368             : 
     369           0 :     if (node->_nextSection)
     370           0 :       _cursor = node->_nextSection->_prev;
     371             :     else
     372           0 :       _cursor = _lastNode;
     373             :   }
     374             : 
     375             :   return kErrorOk;
     376             : }
     377             : 
     378           0 : void BaseBuilder::updateSectionLinks() noexcept {
     379           0 :   if (!_dirtySectionLinks)
     380             :     return;
     381             : 
     382           0 :   BaseNode* node_ = _firstNode;
     383             :   SectionNode* currentSection = nullptr;
     384             : 
     385           0 :   while (node_) {
     386           0 :     if (node_->isSection()) {
     387           0 :       if (currentSection)
     388           0 :         currentSection->_nextSection = node_->as<SectionNode>();
     389             :       currentSection = node_->as<SectionNode>();
     390             :     }
     391             :     node_ = node_->next();
     392             :   }
     393             : 
     394           0 :   if (currentSection)
     395           0 :     currentSection->_nextSection = nullptr;
     396             : 
     397           0 :   _dirtySectionLinks = false;
     398             : }
     399             : 
     400             : // BaseBuilder - Labels
     401             : // ====================
     402             : 
     403           0 : Error BaseBuilder::labelNodeOf(LabelNode** out, uint32_t labelId) {
     404           0 :   *out = nullptr;
     405             : 
     406           0 :   if (ASMJIT_UNLIKELY(!_code))
     407             :     return DebugUtils::errored(kErrorNotInitialized);
     408             : 
     409           0 :   uint32_t index = labelId;
     410           0 :   if (ASMJIT_UNLIKELY(index >= _code->labelCount()))
     411             :     return DebugUtils::errored(kErrorInvalidLabel);
     412             : 
     413           0 :   if (index >= _labelNodes.size())
     414           0 :     ASMJIT_PROPAGATE(_labelNodes.resize(&_allocator, index + 1));
     415             : 
     416           0 :   LabelNode* node = _labelNodes[index];
     417           0 :   if (!node) {
     418           0 :     ASMJIT_PROPAGATE(_newNodeT<LabelNode>(&node, labelId));
     419           0 :     _labelNodes[index] = node;
     420             :   }
     421             : 
     422           0 :   *out = node;
     423           0 :   return kErrorOk;
     424             : }
     425             : 
     426       54984 : Error BaseBuilder::registerLabelNode(LabelNode* node) {
     427       54984 :   if (ASMJIT_UNLIKELY(!_code))
     428             :     return DebugUtils::errored(kErrorNotInitialized);
     429             : 
     430             :   LabelEntry* le;
     431       54984 :   ASMJIT_PROPAGATE(_code->newLabelEntry(&le));
     432       54984 :   uint32_t labelId = le->id();
     433             : 
     434             :   // We just added one label so it must be true.
     435             :   ASMJIT_ASSERT(_labelNodes.size() < labelId + 1);
     436       54984 :   ASMJIT_PROPAGATE(_labelNodes.resize(&_allocator, labelId + 1));
     437             : 
     438       54984 :   _labelNodes[labelId] = node;
     439       54984 :   node->_labelId = labelId;
     440             : 
     441       54984 :   return kErrorOk;
     442             : }
     443             : 
     444           0 : static Error BaseBuilder_newLabelInternal(BaseBuilder* self, uint32_t labelId) {
     445             :   ASMJIT_ASSERT(self->_labelNodes.size() < labelId + 1);
     446             : 
     447           0 :   uint32_t growBy = labelId - self->_labelNodes.size();
     448           0 :   Error err = self->_labelNodes.willGrow(&self->_allocator, growBy);
     449             : 
     450           0 :   if (ASMJIT_UNLIKELY(err))
     451           0 :     return self->reportError(err);
     452             : 
     453             :   LabelNode* node;
     454           0 :   ASMJIT_PROPAGATE(self->_newNodeT<LabelNode>(&node, labelId));
     455             : 
     456           0 :   self->_labelNodes.resize(&self->_allocator, labelId + 1);
     457           0 :   self->_labelNodes[labelId] = node;
     458           0 :   node->_labelId = labelId;
     459           0 :   return kErrorOk;
     460             : }
     461             : 
     462           0 : Label BaseBuilder::newLabel() {
     463             :   uint32_t labelId = Globals::kInvalidId;
     464             :   LabelEntry* le;
     465             : 
     466           0 :   if (_code &&
     467           0 :       _code->newLabelEntry(&le) == kErrorOk &&
     468           0 :       BaseBuilder_newLabelInternal(this, le->id()) == kErrorOk) {
     469           0 :     labelId = le->id();
     470             :   }
     471             : 
     472           0 :   return Label(labelId);
     473             : }
     474             : 
     475           0 : Label BaseBuilder::newNamedLabel(const char* name, size_t nameSize, LabelType type, uint32_t parentId) {
     476             :   uint32_t labelId = Globals::kInvalidId;
     477             :   LabelEntry* le;
     478             : 
     479           0 :   if (_code &&
     480           0 :       _code->newNamedLabelEntry(&le, name, nameSize, type, parentId) == kErrorOk &&
     481           0 :       BaseBuilder_newLabelInternal(this, le->id()) == kErrorOk) {
     482           0 :     labelId = le->id();
     483             :   }
     484             : 
     485           0 :   return Label(labelId);
     486             : }
     487             : 
     488           0 : Error BaseBuilder::bind(const Label& label) {
     489             :   LabelNode* node;
     490           0 :   ASMJIT_PROPAGATE(labelNodeOf(&node, label));
     491             : 
     492           0 :   addNode(node);
     493           0 :   return kErrorOk;
     494             : }
     495             : 
     496             : // BaseBuilder - Passes
     497             : // ====================
     498             : 
     499           0 : ASMJIT_FAVOR_SIZE Pass* BaseBuilder::passByName(const char* name) const noexcept {
     500           0 :   for (Pass* pass : _passes)
     501           0 :     if (strcmp(pass->name(), name) == 0)
     502           0 :       return pass;
     503             :   return nullptr;
     504             : }
     505             : 
     506       54984 : ASMJIT_FAVOR_SIZE Error BaseBuilder::addPass(Pass* pass) noexcept {
     507       54984 :   if (ASMJIT_UNLIKELY(!_code))
     508             :     return DebugUtils::errored(kErrorNotInitialized);
     509             : 
     510       54984 :   if (ASMJIT_UNLIKELY(pass == nullptr)) {
     511             :     // Since this is directly called by `addPassT()` we treat `null` argument
     512             :     // as out-of-memory condition. Otherwise it would be API misuse.
     513             :     return DebugUtils::errored(kErrorOutOfMemory);
     514             :   }
     515       54984 :   else if (ASMJIT_UNLIKELY(pass->_cb)) {
     516             :     // Kinda weird, but okay...
     517           0 :     if (pass->_cb == this)
     518             :       return kErrorOk;
     519             :     return DebugUtils::errored(kErrorInvalidState);
     520             :   }
     521             : 
     522      109968 :   ASMJIT_PROPAGATE(_passes.append(&_allocator, pass));
     523       54984 :   pass->_cb = this;
     524       54984 :   return kErrorOk;
     525             : }
     526             : 
     527           0 : ASMJIT_FAVOR_SIZE Error BaseBuilder::deletePass(Pass* pass) noexcept {
     528           0 :   if (ASMJIT_UNLIKELY(!_code))
     529             :     return DebugUtils::errored(kErrorNotInitialized);
     530             : 
     531           0 :   if (ASMJIT_UNLIKELY(pass == nullptr))
     532             :     return DebugUtils::errored(kErrorInvalidArgument);
     533             : 
     534           0 :   if (pass->_cb != nullptr) {
     535           0 :     if (pass->_cb != this)
     536             :       return DebugUtils::errored(kErrorInvalidState);
     537             : 
     538             :     uint32_t index = _passes.indexOf(pass);
     539             :     ASMJIT_ASSERT(index != Globals::kNotFound);
     540             : 
     541           0 :     pass->_cb = nullptr;
     542           0 :     _passes.removeAt(index);
     543             :   }
     544             : 
     545           0 :   pass->~Pass();
     546           0 :   return kErrorOk;
     547             : }
     548             : 
     549       27492 : Error BaseBuilder::runPasses() {
     550       27492 :   if (ASMJIT_UNLIKELY(!_code))
     551             :     return DebugUtils::errored(kErrorNotInitialized);
     552             : 
     553       27492 :   if (_passes.empty())
     554             :     return kErrorOk;
     555             : 
     556             :   ErrorHandler* prev = errorHandler();
     557       27492 :   PostponedErrorHandler postponed;
     558             : 
     559             :   Error err = kErrorOk;
     560       27492 :   setErrorHandler(&postponed);
     561             : 
     562       82476 :   for (Pass* pass : _passes) {
     563       54984 :     _passZone.reset();
     564       54984 :     err = pass->run(&_passZone, _logger);
     565       54984 :     if (err)
     566             :       break;
     567             :   }
     568       27492 :   _passZone.reset();
     569       27492 :   setErrorHandler(prev);
     570             : 
     571       27492 :   if (ASMJIT_UNLIKELY(err))
     572           0 :     return reportError(err, !postponed._message.empty() ? postponed._message.data() : nullptr);
     573             : 
     574             :   return kErrorOk;
     575       27492 : }
     576             : 
     577             : // BaseBuilder - Emit
     578             : // ==================
     579             : 
     580      382370 : Error BaseBuilder::_emit(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) {
     581             :   uint32_t opCount = EmitterUtils::opCountFromEmitArgs(o0, o1, o2, opExt);
     582             :   InstOptions options = instOptions() | forcedInstOptions();
     583             : 
     584      382370 :   if (Support::test(options, InstOptions::kReserved)) {
     585           0 :     if (ASMJIT_UNLIKELY(!_code))
     586             :       return DebugUtils::errored(kErrorNotInitialized);
     587             : 
     588             : #ifndef ASMJIT_NO_VALIDATION
     589             :     // Strict validation.
     590           0 :     if (hasDiagnosticOption(DiagnosticOptions::kValidateIntermediate)) {
     591             :       Operand_ opArray[Globals::kMaxOpCount];
     592             :       EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt);
     593             : 
     594           0 :       ValidationFlags validationFlags = isCompiler() ? ValidationFlags::kEnableVirtRegs : ValidationFlags::kNone;
     595           0 :       Error err = _funcs.validate(arch(), BaseInst(instId, options, _extraReg), opArray, opCount, validationFlags);
     596             : 
     597           0 :       if (ASMJIT_UNLIKELY(err)) {
     598             :         resetInstOptions();
     599             :         resetExtraReg();
     600             :         resetInlineComment();
     601           0 :         return reportError(err);
     602             :       }
     603             :     }
     604             : #endif
     605             : 
     606             :     // Clear instruction options that should never be part of a regular instruction.
     607             :     options &= ~InstOptions::kReserved;
     608             :   }
     609             : 
     610             :   uint32_t opCapacity = InstNode::capacityOfOpCount(opCount);
     611             :   ASMJIT_ASSERT(opCapacity >= InstNode::kBaseOpCapacity);
     612             : 
     613      382370 :   InstNode* node = _allocator.allocT<InstNode>(InstNode::nodeSizeOfOpCapacity(opCapacity));
     614             :   const char* comment = inlineComment();
     615             : 
     616             :   resetInstOptions();
     617             :   resetInlineComment();
     618             : 
     619      382370 :   if (ASMJIT_UNLIKELY(!node)) {
     620             :     resetExtraReg();
     621           0 :     return reportError(DebugUtils::errored(kErrorOutOfMemory));
     622             :   }
     623             : 
     624             :   node = new(node) InstNode(this, instId, options, opCount, opCapacity);
     625             :   node->setExtraReg(extraReg());
     626             :   node->setOp(0, o0);
     627             :   node->setOp(1, o1);
     628             :   node->setOp(2, o2);
     629      384503 :   for (uint32_t i = 3; i < opCount; i++)
     630        2133 :     node->setOp(i, opExt[i - 3]);
     631             :   node->resetOpRange(opCount, opCapacity);
     632             : 
     633      382370 :   if (comment)
     634           0 :     node->setInlineComment(static_cast<char*>(_dataZone.dup(comment, strlen(comment), true)));
     635             : 
     636      382370 :   addNode(node);
     637             :   resetExtraReg();
     638      382370 :   return kErrorOk;
     639             : }
     640             : 
     641             : // BaseBuilder - Align
     642             : // ===================
     643             : 
     644           0 : Error BaseBuilder::align(AlignMode alignMode, uint32_t alignment) {
     645           0 :   if (ASMJIT_UNLIKELY(!_code))
     646             :     return DebugUtils::errored(kErrorNotInitialized);
     647             : 
     648             :   AlignNode* node;
     649           0 :   ASMJIT_PROPAGATE(newAlignNode(&node, alignMode, alignment));
     650           0 :   ASMJIT_ASSUME(node != nullptr);
     651             : 
     652           0 :   addNode(node);
     653           0 :   return kErrorOk;
     654             : }
     655             : 
     656             : // BaseBuilder - Embed
     657             : // ===================
     658             : 
     659           0 : Error BaseBuilder::embed(const void* data, size_t dataSize) {
     660           0 :   if (ASMJIT_UNLIKELY(!_code))
     661             :     return DebugUtils::errored(kErrorNotInitialized);
     662             : 
     663             :   EmbedDataNode* node;
     664           0 :   ASMJIT_PROPAGATE(newEmbedDataNode(&node, TypeId::kUInt8, data, dataSize));
     665           0 :   ASMJIT_ASSUME(node != nullptr);
     666             : 
     667           0 :   addNode(node);
     668           0 :   return kErrorOk;
     669             : }
     670             : 
     671           0 : Error BaseBuilder::embedDataArray(TypeId typeId, const void* data, size_t itemCount, size_t itemRepeat) {
     672           0 :   if (ASMJIT_UNLIKELY(!_code))
     673             :     return DebugUtils::errored(kErrorNotInitialized);
     674             : 
     675             :   EmbedDataNode* node;
     676           0 :   ASMJIT_PROPAGATE(newEmbedDataNode(&node, typeId, data, itemCount, itemRepeat));
     677           0 :   ASMJIT_ASSUME(node != nullptr);
     678             : 
     679           0 :   addNode(node);
     680           0 :   return kErrorOk;
     681             : }
     682             : 
     683           0 : Error BaseBuilder::embedConstPool(const Label& label, const ConstPool& pool) {
     684           0 :   if (ASMJIT_UNLIKELY(!_code))
     685             :     return DebugUtils::errored(kErrorNotInitialized);
     686             : 
     687           0 :   if (!isLabelValid(label))
     688           0 :     return reportError(DebugUtils::errored(kErrorInvalidLabel));
     689             : 
     690           0 :   ASMJIT_PROPAGATE(align(AlignMode::kData, uint32_t(pool.alignment())));
     691           0 :   ASMJIT_PROPAGATE(bind(label));
     692             : 
     693             :   EmbedDataNode* node;
     694           0 :   ASMJIT_PROPAGATE(newEmbedDataNode(&node, TypeId::kUInt8, nullptr, pool.size()));
     695           0 :   ASMJIT_ASSUME(node != nullptr);
     696             : 
     697           0 :   pool.fill(node->data());
     698           0 :   addNode(node);
     699           0 :   return kErrorOk;
     700             : }
     701             : 
     702             : // BaseBuilder - EmbedLabel & EmbedLabelDelta
     703             : // ==========================================
     704             : //
     705             : // If dataSize is zero it means that the size is the same as target register width, however,
     706             : // if it's provided we really want to validate whether it's within the possible range.
     707             : 
     708             : static inline bool BaseBuilder_checkDataSize(size_t dataSize) noexcept {
     709           0 :   return !dataSize || (Support::isPowerOf2(dataSize) && dataSize <= 8);
     710             : }
     711             : 
     712           0 : Error BaseBuilder::embedLabel(const Label& label, size_t dataSize) {
     713           0 :   if (ASMJIT_UNLIKELY(!_code))
     714             :     return DebugUtils::errored(kErrorNotInitialized);
     715             : 
     716             :   if (!BaseBuilder_checkDataSize(dataSize))
     717           0 :     return reportError(DebugUtils::errored(kErrorInvalidArgument));
     718             : 
     719             :   EmbedLabelNode* node;
     720           0 :   ASMJIT_PROPAGATE(_newNodeT<EmbedLabelNode>(&node, label.id(), uint32_t(dataSize)));
     721             : 
     722           0 :   addNode(node);
     723           0 :   return kErrorOk;
     724             : }
     725             : 
     726           0 : Error BaseBuilder::embedLabelDelta(const Label& label, const Label& base, size_t dataSize) {
     727           0 :   if (ASMJIT_UNLIKELY(!_code))
     728             :     return DebugUtils::errored(kErrorNotInitialized);
     729             : 
     730             :   if (!BaseBuilder_checkDataSize(dataSize))
     731           0 :     return reportError(DebugUtils::errored(kErrorInvalidArgument));
     732             : 
     733             :   EmbedLabelDeltaNode* node;
     734           0 :   ASMJIT_PROPAGATE(_newNodeT<EmbedLabelDeltaNode>(&node, label.id(), base.id(), uint32_t(dataSize)));
     735             : 
     736           0 :   addNode(node);
     737           0 :   return kErrorOk;
     738             : }
     739             : 
     740             : // BaseBuilder - Comment
     741             : // =====================
     742             : 
     743           0 : Error BaseBuilder::comment(const char* data, size_t size) {
     744           0 :   if (ASMJIT_UNLIKELY(!_code))
     745             :     return DebugUtils::errored(kErrorNotInitialized);
     746             : 
     747             :   CommentNode* node;
     748           0 :   ASMJIT_PROPAGATE(newCommentNode(&node, data, size));
     749           0 :   ASMJIT_ASSUME(node != nullptr);
     750             : 
     751           0 :   addNode(node);
     752           0 :   return kErrorOk;
     753             : }
     754             : 
     755             : // BaseBuilder - SerializeTo
     756             : // =========================
     757             : 
     758       27492 : Error BaseBuilder::serializeTo(BaseEmitter* dst) {
     759             :   Error err = kErrorOk;
     760       27492 :   BaseNode* node_ = _firstNode;
     761             : 
     762             :   Operand_ opArray[Globals::kMaxOpCount];
     763             : 
     764             :   do {
     765             :     dst->setInlineComment(node_->inlineComment());
     766             : 
     767      501977 :     if (node_->isInst()) {
     768             :       InstNode* node = node_->as<InstNode>();
     769             : 
     770             :       // NOTE: Inlined to remove one additional call per instruction.
     771             :       dst->setInstOptions(node->options());
     772             :       dst->setExtraReg(node->extraReg());
     773             : 
     774             :       const Operand_* op = node->operands();
     775             :       const Operand_* opExt = EmitterUtils::noExt;
     776             : 
     777             :       uint32_t opCount = node->opCount();
     778      392009 :       if (opCount > 3) {
     779             :         uint32_t i = 4;
     780        2133 :         opArray[3] = op[3];
     781             : 
     782        2133 :         while (i < opCount) {
     783           0 :           opArray[i].copyFrom(op[i]);
     784           0 :           i++;
     785             :         }
     786        6399 :         while (i < Globals::kMaxOpCount) {
     787        4266 :           opArray[i].reset();
     788        4266 :           i++;
     789             :         }
     790             :         opExt = opArray + 3;
     791             :       }
     792             : 
     793      392009 :       err = dst->_emit(node->id(), op[0], op[1], op[2], opExt);
     794             :     }
     795      109968 :     else if (node_->isLabel()) {
     796       54984 :       if (node_->isConstPool()) {
     797             :         ConstPoolNode* node = node_->as<ConstPoolNode>();
     798           0 :         err = dst->embedConstPool(node->label(), node->constPool());
     799             :       }
     800             :       else {
     801             :         LabelNode* node = node_->as<LabelNode>();
     802       54984 :         err = dst->bind(node->label());
     803             :       }
     804             :     }
     805             :     else if (node_->isAlign()) {
     806             :       AlignNode* node = node_->as<AlignNode>();
     807           0 :       err = dst->align(node->alignMode(), node->alignment());
     808             :     }
     809             :     else if (node_->isEmbedData()) {
     810             :       EmbedDataNode* node = node_->as<EmbedDataNode>();
     811           0 :       err = dst->embedDataArray(node->typeId(), node->data(), node->itemCount(), node->repeatCount());
     812             :     }
     813             :     else if (node_->isEmbedLabel()) {
     814             :       EmbedLabelNode* node = node_->as<EmbedLabelNode>();
     815           0 :       err = dst->embedLabel(node->label(), node->dataSize());
     816             :     }
     817             :     else if (node_->isEmbedLabelDelta()) {
     818             :       EmbedLabelDeltaNode* node = node_->as<EmbedLabelDeltaNode>();
     819           0 :       err = dst->embedLabelDelta(node->label(), node->baseLabel(), node->dataSize());
     820             :     }
     821             :     else if (node_->isSection()) {
     822             :       SectionNode* node = node_->as<SectionNode>();
     823       27492 :       err = dst->section(_code->sectionById(node->id()));
     824             :     }
     825             :     else if (node_->isComment()) {
     826             :       CommentNode* node = node_->as<CommentNode>();
     827           0 :       err = dst->comment(node->inlineComment());
     828             :     }
     829             : 
     830      501977 :     if (err) break;
     831             :     node_ = node_->next();
     832      501977 :   } while (node_);
     833             : 
     834       27492 :   return err;
     835             : }
     836             : 
     837             : // BaseBuilder - Events
     838             : // ====================
     839             : 
     840       27492 : Error BaseBuilder::onAttach(CodeHolder* code) noexcept {
     841       27492 :   ASMJIT_PROPAGATE(Base::onAttach(code));
     842             : 
     843             :   SectionNode* initialSection;
     844       27492 :   Error err = sectionNodeOf(&initialSection, 0);
     845             : 
     846       27492 :   if (!err)
     847       27492 :     err = _passes.willGrow(&_allocator, 8);
     848             : 
     849       27492 :   if (ASMJIT_UNLIKELY(err)) {
     850           0 :     onDetach(code);
     851           0 :     return err;
     852             :   }
     853             : 
     854       27492 :   ASMJIT_ASSUME(initialSection != nullptr);
     855       27492 :   _cursor = initialSection;
     856       27492 :   _firstNode = initialSection;
     857       27492 :   _lastNode = initialSection;
     858             :   initialSection->setFlags(NodeFlags::kIsActive);
     859             : 
     860       27492 :   return kErrorOk;
     861             : }
     862             : 
     863           0 : Error BaseBuilder::onDetach(CodeHolder* code) noexcept {
     864           0 :   BaseBuilder_deletePasses(this);
     865             :   _sectionNodes.reset();
     866             :   _labelNodes.reset();
     867             : 
     868           0 :   _allocator.reset(&_codeZone);
     869           0 :   _codeZone.reset();
     870           0 :   _dataZone.reset();
     871           0 :   _passZone.reset();
     872             : 
     873           0 :   _nodeFlags = NodeFlags::kNone;
     874           0 :   _cursor = nullptr;
     875           0 :   _firstNode = nullptr;
     876           0 :   _lastNode = nullptr;
     877             : 
     878           0 :   return Base::onDetach(code);
     879             : }
     880             : 
     881             : // Pass - Construction & Destruction
     882             : // =================================
     883             : 
     884       54984 : Pass::Pass(const char* name) noexcept
     885       54984 :   : _name(name) {}
     886       54984 : Pass::~Pass() noexcept {}
     887             : 
     888             : ASMJIT_END_NAMESPACE
     889             : 
     890             : #endif // !ASMJIT_NO_BUILDER
     891             : 
     892             : #endif // __PLUMED_HAS_ASMJIT

Generated by: LCOV version 1.16