LCOV - code coverage report
Current view: top level - asmjit - assembler.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage (other modules) Lines: 25 156 16.0 %
Date: 2026-11-05 10:19:06 Functions: 6 17 35.3 %

          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             : #include "assembler.h"
       9             : #include "codewriter_p.h"
      10             : #include "constpool.h"
      11             : #include "emitterutils_p.h"
      12             : #include "formatter.h"
      13             : #include "logger.h"
      14             : #include "support.h"
      15             : 
      16             : ASMJIT_BEGIN_NAMESPACE
      17             : 
      18             : // BaseAssembler - Construction & Destruction
      19             : // ==========================================
      20             : 
      21       27492 : BaseAssembler::BaseAssembler() noexcept
      22       27492 :   : BaseEmitter(EmitterType::kAssembler) {}
      23             : 
      24       27492 : BaseAssembler::~BaseAssembler() noexcept {}
      25             : 
      26             : // BaseAssembler - Buffer Management
      27             : // =================================
      28             : 
      29           0 : Error BaseAssembler::setOffset(size_t offset) {
      30           0 :   if (ASMJIT_UNLIKELY(!_code))
      31           0 :     return reportError(DebugUtils::errored(kErrorNotInitialized));
      32             : 
      33           0 :   size_t size = Support::max<size_t>(_section->bufferSize(), this->offset());
      34           0 :   if (ASMJIT_UNLIKELY(offset > size))
      35           0 :     return reportError(DebugUtils::errored(kErrorInvalidArgument));
      36             : 
      37           0 :   _bufferPtr = _bufferData + offset;
      38           0 :   return kErrorOk;
      39             : }
      40             : 
      41             : // BaseAssembler - Section Management
      42             : // ==================================
      43             : 
      44       54984 : static void BaseAssembler_initSection(BaseAssembler* self, Section* section) noexcept {
      45       54984 :   uint8_t* p = section->_buffer._data;
      46             : 
      47       54984 :   self->_section = section;
      48       54984 :   self->_bufferData = p;
      49       54984 :   self->_bufferPtr  = p + section->_buffer._size;
      50       54984 :   self->_bufferEnd  = p + section->_buffer._capacity;
      51       54984 : }
      52             : 
      53       27492 : Error BaseAssembler::section(Section* section) {
      54       27492 :   if (ASMJIT_UNLIKELY(!_code))
      55           0 :     return reportError(DebugUtils::errored(kErrorNotInitialized));
      56             : 
      57       27492 :   if (!_code->isSectionValid(section->id()) || _code->_sections[section->id()] != section)
      58           0 :     return reportError(DebugUtils::errored(kErrorInvalidSection));
      59             : 
      60             : #ifndef ASMJIT_NO_LOGGING
      61       27492 :   if (_logger)
      62           0 :     _logger->logf(".section %s {#%u}\n", section->name(), section->id());
      63             : #endif
      64             : 
      65       27492 :   BaseAssembler_initSection(this, section);
      66       27492 :   return kErrorOk;
      67             : }
      68             : 
      69             : // BaseAssembler - Label Management
      70             : // ================================
      71             : 
      72           0 : Label BaseAssembler::newLabel() {
      73             :   uint32_t labelId = Globals::kInvalidId;
      74           0 :   if (ASMJIT_LIKELY(_code)) {
      75             :     LabelEntry* le;
      76           0 :     Error err = _code->newLabelEntry(&le);
      77           0 :     if (ASMJIT_UNLIKELY(err))
      78           0 :       reportError(err);
      79             :     else
      80           0 :       labelId = le->id();
      81             :   }
      82           0 :   return Label(labelId);
      83             : }
      84             : 
      85           0 : Label BaseAssembler::newNamedLabel(const char* name, size_t nameSize, LabelType type, uint32_t parentId) {
      86             :   uint32_t labelId = Globals::kInvalidId;
      87           0 :   if (ASMJIT_LIKELY(_code)) {
      88             :     LabelEntry* le;
      89           0 :     Error err = _code->newNamedLabelEntry(&le, name, nameSize, type, parentId);
      90           0 :     if (ASMJIT_UNLIKELY(err))
      91           0 :       reportError(err);
      92             :     else
      93           0 :       labelId = le->id();
      94             :   }
      95           0 :   return Label(labelId);
      96             : }
      97             : 
      98       54984 : Error BaseAssembler::bind(const Label& label) {
      99       54984 :   if (ASMJIT_UNLIKELY(!_code))
     100           0 :     return reportError(DebugUtils::errored(kErrorNotInitialized));
     101             : 
     102       54984 :   Error err = _code->bindLabel(label, _section->id(), offset());
     103             : 
     104             : #ifndef ASMJIT_NO_LOGGING
     105       54984 :   if (_logger)
     106           0 :     EmitterUtils::logLabelBound(this, label);
     107             : #endif
     108             : 
     109             :   resetInlineComment();
     110       54984 :   if (err)
     111           0 :     return reportError(err);
     112             : 
     113             :   return kErrorOk;
     114             : }
     115             : 
     116             : // BaseAssembler - Embed
     117             : // =====================
     118             : 
     119           0 : Error BaseAssembler::embed(const void* data, size_t dataSize) {
     120           0 :   if (ASMJIT_UNLIKELY(!_code))
     121           0 :     return reportError(DebugUtils::errored(kErrorNotInitialized));
     122             : 
     123           0 :   if (dataSize == 0)
     124             :     return kErrorOk;
     125             : 
     126             :   CodeWriter writer(this);
     127           0 :   ASMJIT_PROPAGATE(writer.ensureSpace(this, dataSize));
     128             : 
     129             :   writer.emitData(data, dataSize);
     130             :   writer.done(this);
     131             : 
     132             : #ifndef ASMJIT_NO_LOGGING
     133           0 :   if (_logger) {
     134             :     StringTmp<512> sb;
     135           0 :     Formatter::formatData(sb, _logger->flags(), arch(), TypeId::kUInt8, data, dataSize, 1);
     136             :     sb.append('\n');
     137           0 :     _logger->log(sb);
     138             :   }
     139             : #endif
     140             : 
     141             :   return kErrorOk;
     142             : }
     143             : 
     144           0 : Error BaseAssembler::embedDataArray(TypeId typeId, const void* data, size_t itemCount, size_t repeatCount) {
     145             :   uint32_t deabstractDelta = TypeUtils::deabstractDeltaOfSize(registerSize());
     146             :   TypeId finalTypeId = TypeUtils::deabstract(typeId, deabstractDelta);
     147             : 
     148           0 :   if (ASMJIT_UNLIKELY(!TypeUtils::isValid(finalTypeId)))
     149           0 :     return reportError(DebugUtils::errored(kErrorInvalidArgument));
     150             : 
     151           0 :   if (itemCount == 0 || repeatCount == 0)
     152             :     return kErrorOk;
     153             : 
     154             :   uint32_t typeSize = TypeUtils::sizeOf(finalTypeId);
     155             :   Support::FastUInt8 of = 0;
     156             : 
     157             :   size_t dataSize = Support::mulOverflow(itemCount, size_t(typeSize), &of);
     158             :   size_t totalSize = Support::mulOverflow(dataSize, repeatCount, &of);
     159             : 
     160           0 :   if (ASMJIT_UNLIKELY(of))
     161           0 :     return reportError(DebugUtils::errored(kErrorOutOfMemory));
     162             : 
     163             :   CodeWriter writer(this);
     164           0 :   ASMJIT_PROPAGATE(writer.ensureSpace(this, totalSize));
     165             : 
     166           0 :   for (size_t i = 0; i < repeatCount; i++)
     167             :     writer.emitData(data, dataSize);
     168             : 
     169             :   writer.done(this);
     170             : 
     171             : #ifndef ASMJIT_NO_LOGGING
     172           0 :   if (_logger) {
     173             :     StringTmp<512> sb;
     174           0 :     Formatter::formatData(sb, _logger->flags(), arch(), typeId, data, itemCount, repeatCount);
     175             :     sb.append('\n');
     176           0 :     _logger->log(sb);
     177             :   }
     178             : #endif
     179             : 
     180             :   return kErrorOk;
     181             : }
     182             : 
     183             : #ifndef ASMJIT_NO_LOGGING
     184             : static const TypeId dataTypeIdBySize[9] = {
     185             :   TypeId::kVoid,   // [0] (invalid)
     186             :   TypeId::kUInt8,  // [1] (uint8_t)
     187             :   TypeId::kUInt16, // [2] (uint16_t)
     188             :   TypeId::kVoid,   // [3] (invalid)
     189             :   TypeId::kUInt32, // [4] (uint32_t)
     190             :   TypeId::kVoid,   // [5] (invalid)
     191             :   TypeId::kVoid,   // [6] (invalid)
     192             :   TypeId::kVoid,   // [7] (invalid)
     193             :   TypeId::kUInt64  // [8] (uint64_t)
     194             : };
     195             : #endif
     196             : 
     197           0 : Error BaseAssembler::embedConstPool(const Label& label, const ConstPool& pool) {
     198           0 :   if (ASMJIT_UNLIKELY(!_code))
     199           0 :     return reportError(DebugUtils::errored(kErrorNotInitialized));
     200             : 
     201           0 :   if (ASMJIT_UNLIKELY(!isLabelValid(label)))
     202           0 :     return reportError(DebugUtils::errored(kErrorInvalidLabel));
     203             : 
     204           0 :   ASMJIT_PROPAGATE(align(AlignMode::kData, uint32_t(pool.alignment())));
     205           0 :   ASMJIT_PROPAGATE(bind(label));
     206             : 
     207             :   size_t size = pool.size();
     208           0 :   if (!size)
     209             :     return kErrorOk;
     210             : 
     211             :   CodeWriter writer(this);
     212           0 :   ASMJIT_PROPAGATE(writer.ensureSpace(this, size));
     213             : 
     214             : #ifndef ASMJIT_NO_LOGGING
     215             :   uint8_t* data = writer.cursor();
     216             : #endif
     217             : 
     218           0 :   pool.fill(writer.cursor());
     219             :   writer.advance(size);
     220             :   writer.done(this);
     221             : 
     222             : #ifndef ASMJIT_NO_LOGGING
     223           0 :   if (_logger) {
     224             :     uint32_t dataSizeLog2 = Support::min<uint32_t>(Support::ctz(pool.minItemSize()), 3);
     225           0 :     uint32_t dataSize = 1 << dataSizeLog2;
     226             : 
     227             :     StringTmp<512> sb;
     228           0 :     Formatter::formatData(sb, _logger->flags(), arch(), dataTypeIdBySize[dataSize], data, size >> dataSizeLog2);
     229             :     sb.append('\n');
     230           0 :     _logger->log(sb);
     231             :   }
     232             : #endif
     233             : 
     234             :   return kErrorOk;
     235             : }
     236             : 
     237           0 : Error BaseAssembler::embedLabel(const Label& label, size_t dataSize) {
     238           0 :   if (ASMJIT_UNLIKELY(!_code))
     239           0 :     return reportError(DebugUtils::errored(kErrorNotInitialized));
     240             : 
     241             :   ASMJIT_ASSERT(_code != nullptr);
     242             :   RelocEntry* re;
     243             :   LabelEntry* le = _code->labelEntry(label);
     244             : 
     245           0 :   if (ASMJIT_UNLIKELY(!le))
     246           0 :     return reportError(DebugUtils::errored(kErrorInvalidLabel));
     247             : 
     248           0 :   if (dataSize == 0)
     249           0 :     dataSize = registerSize();
     250             : 
     251           0 :   if (ASMJIT_UNLIKELY(!Support::isPowerOf2(dataSize) || dataSize > 8))
     252           0 :     return reportError(DebugUtils::errored(kErrorInvalidOperandSize));
     253             : 
     254             :   CodeWriter writer(this);
     255           0 :   ASMJIT_PROPAGATE(writer.ensureSpace(this, dataSize));
     256             : 
     257             : #ifndef ASMJIT_NO_LOGGING
     258           0 :   if (_logger) {
     259             :     StringTmp<256> sb;
     260             :     sb.append('.');
     261           0 :     Formatter::formatDataType(sb, _logger->flags(), arch(), dataTypeIdBySize[dataSize]);
     262             :     sb.append(' ');
     263           0 :     Formatter::formatLabel(sb, FormatFlags::kNone, this, label.id());
     264             :     sb.append('\n');
     265           0 :     _logger->log(sb);
     266             :   }
     267             : #endif
     268             : 
     269           0 :   Error err = _code->newRelocEntry(&re, RelocType::kRelToAbs);
     270           0 :   if (ASMJIT_UNLIKELY(err))
     271           0 :     return reportError(err);
     272             : 
     273           0 :   re->_sourceSectionId = _section->id();
     274           0 :   re->_sourceOffset = offset();
     275             :   re->_format.resetToSimpleValue(OffsetType::kUnsignedOffset, dataSize);
     276             : 
     277           0 :   if (le->isBound()) {
     278           0 :     re->_targetSectionId = le->section()->id();
     279           0 :     re->_payload = le->offset();
     280             :   }
     281             :   else {
     282             :     OffsetFormat of;
     283             :     of.resetToSimpleValue(OffsetType::kUnsignedOffset, dataSize);
     284             : 
     285           0 :     LabelLink* link = _code->newLabelLink(le, _section->id(), offset(), 0, of);
     286           0 :     if (ASMJIT_UNLIKELY(!link))
     287           0 :       return reportError(DebugUtils::errored(kErrorOutOfMemory));
     288             : 
     289           0 :     link->relocId = re->id();
     290             :   }
     291             : 
     292             :   // Emit dummy DWORD/QWORD depending on the data size.
     293             :   writer.emitZeros(dataSize);
     294             :   writer.done(this);
     295             : 
     296           0 :   return kErrorOk;
     297             : }
     298             : 
     299           0 : Error BaseAssembler::embedLabelDelta(const Label& label, const Label& base, size_t dataSize) {
     300           0 :   if (ASMJIT_UNLIKELY(!_code))
     301           0 :     return reportError(DebugUtils::errored(kErrorNotInitialized));
     302             : 
     303             :   LabelEntry* labelEntry = _code->labelEntry(label);
     304             :   LabelEntry* baseEntry = _code->labelEntry(base);
     305             : 
     306           0 :   if (ASMJIT_UNLIKELY(!labelEntry || !baseEntry))
     307           0 :     return reportError(DebugUtils::errored(kErrorInvalidLabel));
     308             : 
     309           0 :   if (dataSize == 0)
     310           0 :     dataSize = registerSize();
     311             : 
     312           0 :   if (ASMJIT_UNLIKELY(!Support::isPowerOf2(dataSize) || dataSize > 8))
     313           0 :     return reportError(DebugUtils::errored(kErrorInvalidOperandSize));
     314             : 
     315             :   CodeWriter writer(this);
     316           0 :   ASMJIT_PROPAGATE(writer.ensureSpace(this, dataSize));
     317             : 
     318             : #ifndef ASMJIT_NO_LOGGING
     319           0 :   if (_logger) {
     320             :     StringTmp<256> sb;
     321             :     sb.append('.');
     322           0 :     Formatter::formatDataType(sb, _logger->flags(), arch(), dataTypeIdBySize[dataSize]);
     323             :     sb.append(" (");
     324           0 :     Formatter::formatLabel(sb, FormatFlags::kNone, this, label.id());
     325             :     sb.append(" - ");
     326           0 :     Formatter::formatLabel(sb, FormatFlags::kNone, this, base.id());
     327             :     sb.append(")\n");
     328           0 :     _logger->log(sb);
     329             :   }
     330             : #endif
     331             : 
     332             :   // If both labels are bound within the same section it means the delta can be calculated now.
     333           0 :   if (labelEntry->isBound() && baseEntry->isBound() && labelEntry->section() == baseEntry->section()) {
     334           0 :     uint64_t delta = labelEntry->offset() - baseEntry->offset();
     335             :     writer.emitValueLE(delta, dataSize);
     336             :   }
     337             :   else {
     338             :     RelocEntry* re;
     339           0 :     Error err = _code->newRelocEntry(&re, RelocType::kExpression);
     340           0 :     if (ASMJIT_UNLIKELY(err))
     341           0 :       return reportError(err);
     342             : 
     343           0 :     Expression* exp = _code->_zone.newT<Expression>();
     344           0 :     if (ASMJIT_UNLIKELY(!exp))
     345           0 :       return reportError(DebugUtils::errored(kErrorOutOfMemory));
     346             : 
     347           0 :     exp->reset();
     348           0 :     exp->opType = ExpressionOpType::kSub;
     349             :     exp->setValueAsLabel(0, labelEntry);
     350             :     exp->setValueAsLabel(1, baseEntry);
     351             : 
     352           0 :     re->_format.resetToSimpleValue(OffsetType::kSignedOffset, dataSize);
     353           0 :     re->_sourceSectionId = _section->id();
     354           0 :     re->_sourceOffset = offset();
     355           0 :     re->_payload = (uint64_t)(uintptr_t)exp;
     356             : 
     357             :     writer.emitZeros(dataSize);
     358             :   }
     359             : 
     360             :   writer.done(this);
     361           0 :   return kErrorOk;
     362             : }
     363             : 
     364             : // BaseAssembler - Comment
     365             : // =======================
     366             : 
     367           0 : Error BaseAssembler::comment(const char* data, size_t size) {
     368           0 :   if (!hasEmitterFlag(EmitterFlags::kLogComments)) {
     369           0 :     if (!hasEmitterFlag(EmitterFlags::kAttached))
     370           0 :       return reportError(DebugUtils::errored(kErrorNotInitialized));
     371             :     return kErrorOk;
     372             :   }
     373             : 
     374             : #ifndef ASMJIT_NO_LOGGING
     375             :   // Logger cannot be NULL if `EmitterFlags::kLogComments` is set.
     376             :   ASMJIT_ASSERT(_logger != nullptr);
     377             : 
     378           0 :   _logger->log(data, size);
     379           0 :   _logger->log("\n", 1);
     380           0 :   return kErrorOk;
     381             : #else
     382             :   DebugUtils::unused(data, size);
     383             :   return kErrorOk;
     384             : #endif
     385             : }
     386             : 
     387             : // BaseAssembler - Events
     388             : // ======================
     389             : 
     390       27492 : Error BaseAssembler::onAttach(CodeHolder* code) noexcept {
     391       27492 :   ASMJIT_PROPAGATE(Base::onAttach(code));
     392             : 
     393             :   // Attach to the end of the .text section.
     394       27492 :   BaseAssembler_initSection(this, code->_sections[0]);
     395             : 
     396       27492 :   return kErrorOk;
     397             : }
     398             : 
     399           0 : Error BaseAssembler::onDetach(CodeHolder* code) noexcept {
     400           0 :   _section    = nullptr;
     401           0 :   _bufferData = nullptr;
     402           0 :   _bufferEnd  = nullptr;
     403           0 :   _bufferPtr  = nullptr;
     404           0 :   return Base::onDetach(code);
     405             : }
     406             : 
     407             : ASMJIT_END_NAMESPACE
     408             : 
     409             : #endif // __PLUMED_HAS_ASMJIT

Generated by: LCOV version 1.16