LCOV - code coverage report
Current view: top level - asmjit - emitter.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage (other modules) Lines: 52 130 40.0 %
Date: 2026-11-05 10:19:06 Functions: 13 28 46.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             : #include "emitterutils_p.h"
       9             : #include "errorhandler.h"
      10             : #include "logger.h"
      11             : #include "support.h"
      12             : 
      13             : ASMJIT_BEGIN_NAMESPACE
      14             : 
      15             : // BaseEmitter - Construction & Destruction
      16             : // ========================================
      17             : 
      18       54984 : BaseEmitter::BaseEmitter(EmitterType emitterType) noexcept
      19       54984 :   : _emitterType(emitterType) {}
      20             : 
      21       54984 : BaseEmitter::~BaseEmitter() noexcept {
      22       54984 :   if (_code) {
      23             :     _addEmitterFlags(EmitterFlags::kDestroyed);
      24       54984 :     _code->detach(this);
      25             :   }
      26       54984 : }
      27             : 
      28             : // BaseEmitter - Finalize
      29             : // ======================
      30             : 
      31           0 : Error BaseEmitter::finalize() {
      32             :   // Does nothing by default, overridden by `BaseBuilder` and `BaseCompiler`.
      33           0 :   return kErrorOk;
      34             : }
      35             : 
      36             : // BaseEmitter - Internals
      37             : // =======================
      38             : 
      39             : static constexpr EmitterFlags kEmitterPreservedFlags = EmitterFlags::kOwnLogger | EmitterFlags::kOwnErrorHandler;
      40             : 
      41       82476 : static ASMJIT_NOINLINE void BaseEmitter_updateForcedOptions(BaseEmitter* self) noexcept {
      42             :   bool emitComments = false;
      43             :   bool hasDiagnosticOptions = false;
      44             : 
      45       82476 :   if (self->emitterType() == EmitterType::kAssembler) {
      46             :     // Assembler: Don't emit comments if logger is not attached.
      47       54984 :     emitComments = self->_code != nullptr && self->_logger != nullptr;
      48             :     hasDiagnosticOptions = self->hasDiagnosticOption(DiagnosticOptions::kValidateAssembler);
      49             :   }
      50             :   else {
      51             :     // Builder/Compiler: Always emit comments, we cannot assume they won't be used.
      52       27492 :     emitComments = self->_code != nullptr;
      53             :     hasDiagnosticOptions = self->hasDiagnosticOption(DiagnosticOptions::kValidateIntermediate);
      54             :   }
      55             : 
      56       82476 :   if (emitComments)
      57             :     self->_addEmitterFlags(EmitterFlags::kLogComments);
      58             :   else
      59             :     self->_clearEmitterFlags(EmitterFlags::kLogComments);
      60             : 
      61             :   // The reserved option tells emitter (Assembler/Builder/Compiler) that there may be either a border
      62             :   // case (CodeHolder not attached, for example) or that logging or validation is required.
      63       82476 :   if (self->_code == nullptr || self->_logger || hasDiagnosticOptions)
      64             :     self->_forcedInstOptions |= InstOptions::kReserved;
      65             :   else
      66             :     self->_forcedInstOptions &= ~InstOptions::kReserved;
      67       82476 : }
      68             : 
      69             : // BaseEmitter - Diagnostic Options
      70             : // ================================
      71             : 
      72       27492 : void BaseEmitter::addDiagnosticOptions(DiagnosticOptions options) noexcept {
      73             :   _diagnosticOptions |= options;
      74       27492 :   BaseEmitter_updateForcedOptions(this);
      75       27492 : }
      76             : 
      77           0 : void BaseEmitter::clearDiagnosticOptions(DiagnosticOptions options) noexcept {
      78             :   _diagnosticOptions &= ~options;
      79           0 :   BaseEmitter_updateForcedOptions(this);
      80           0 : }
      81             : 
      82             : // BaseEmitter - Logging
      83             : // =====================
      84             : 
      85           0 : void BaseEmitter::setLogger(Logger* logger) noexcept {
      86             : #ifndef ASMJIT_NO_LOGGING
      87           0 :   if (logger) {
      88           0 :     _logger = logger;
      89             :     _addEmitterFlags(EmitterFlags::kOwnLogger);
      90             :   }
      91             :   else {
      92           0 :     _logger = nullptr;
      93             :     _clearEmitterFlags(EmitterFlags::kOwnLogger);
      94           0 :     if (_code)
      95           0 :       _logger = _code->logger();
      96             :   }
      97           0 :   BaseEmitter_updateForcedOptions(this);
      98             : #else
      99             :   DebugUtils::unused(logger);
     100             : #endif
     101           0 : }
     102             : 
     103             : // BaseEmitter - Error Handling
     104             : // ============================
     105             : 
     106       54984 : void BaseEmitter::setErrorHandler(ErrorHandler* errorHandler) noexcept {
     107       54984 :   if (errorHandler) {
     108       27492 :     _errorHandler = errorHandler;
     109             :     _addEmitterFlags(EmitterFlags::kOwnErrorHandler);
     110             :   }
     111             :   else {
     112       27492 :     _errorHandler = nullptr;
     113             :     _clearEmitterFlags(EmitterFlags::kOwnErrorHandler);
     114       27492 :     if (_code)
     115       27492 :       _errorHandler = _code->errorHandler();
     116             :   }
     117       54984 : }
     118             : 
     119           0 : Error BaseEmitter::reportError(Error err, const char* message) {
     120           0 :   ErrorHandler* eh = _errorHandler;
     121           0 :   if (eh) {
     122           0 :     if (!message)
     123           0 :       message = DebugUtils::errorAsString(err);
     124           0 :     eh->handleError(err, message, this);
     125             :   }
     126           0 :   return err;
     127             : }
     128             : 
     129             : // BaseEmitter - Labels
     130             : // ====================
     131             : 
     132           0 : Label BaseEmitter::labelByName(const char* name, size_t nameSize, uint32_t parentId) noexcept {
     133           0 :   return Label(_code ? _code->labelIdByName(name, nameSize, parentId) : Globals::kInvalidId);
     134             : }
     135             : 
     136           0 : bool BaseEmitter::isLabelValid(uint32_t labelId) const noexcept {
     137           0 :   return _code && labelId < _code->labelCount();
     138             : }
     139             : 
     140             : // BaseEmitter - Emit (Low-Level)
     141             : // ==============================
     142             : 
     143             : using EmitterUtils::noExt;
     144             : 
     145       27492 : Error BaseEmitter::_emitI(InstId instId) {
     146       27492 :   return _emit(instId, noExt[0], noExt[1], noExt[2], noExt);
     147             : }
     148             : 
     149           0 : Error BaseEmitter::_emitI(InstId instId, const Operand_& o0) {
     150           0 :   return _emit(instId, o0, noExt[1], noExt[2], noExt);
     151             : }
     152             : 
     153      219411 : Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1) {
     154      219411 :   return _emit(instId, o0, o1, noExt[2], noExt);
     155             : }
     156             : 
     157      133334 : Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2) {
     158      133334 :   return _emit(instId, o0, o1, o2, noExt);
     159             : }
     160             : 
     161        2133 : Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) {
     162        2133 :   Operand_ opExt[3] = { o3 };
     163        2133 :   return _emit(instId, o0, o1, o2, opExt);
     164             : }
     165             : 
     166           0 : Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4) {
     167           0 :   Operand_ opExt[3] = { o3, o4 };
     168           0 :   return _emit(instId, o0, o1, o2, opExt);
     169             : }
     170             : 
     171           0 : Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, const Operand_& o5) {
     172           0 :   Operand_ opExt[3] = { o3, o4, o5 };
     173           0 :   return _emit(instId, o0, o1, o2, opExt);
     174             : }
     175             : 
     176           0 : Error BaseEmitter::_emitOpArray(InstId instId, const Operand_* operands, size_t opCount) {
     177             :   const Operand_* op = operands;
     178             :   Operand_ opExt[3];
     179             : 
     180           0 :   switch (opCount) {
     181           0 :     case 0:
     182           0 :       return _emit(instId, noExt[0], noExt[1], noExt[2], noExt);
     183             : 
     184           0 :     case 1:
     185           0 :       return _emit(instId, op[0], noExt[1], noExt[2], noExt);
     186             : 
     187           0 :     case 2:
     188           0 :       return _emit(instId, op[0], op[1], noExt[2], noExt);
     189             : 
     190           0 :     case 3:
     191           0 :       return _emit(instId, op[0], op[1], op[2], noExt);
     192             : 
     193           0 :     case 4:
     194           0 :       opExt[0] = op[3];
     195             :       opExt[1].reset();
     196             :       opExt[2].reset();
     197           0 :       return _emit(instId, op[0], op[1], op[2], opExt);
     198             : 
     199           0 :     case 5:
     200           0 :       opExt[0] = op[3];
     201           0 :       opExt[1] = op[4];
     202             :       opExt[2].reset();
     203           0 :       return _emit(instId, op[0], op[1], op[2], opExt);
     204             : 
     205           0 :     case 6:
     206           0 :       return _emit(instId, op[0], op[1], op[2], op + 3);
     207             : 
     208             :     default:
     209             :       return DebugUtils::errored(kErrorInvalidArgument);
     210             :   }
     211             : }
     212             : 
     213             : // BaseEmitter - Emit Utilities
     214             : // ============================
     215             : 
     216       27492 : Error BaseEmitter::emitProlog(const FuncFrame& frame) {
     217       27492 :   if (ASMJIT_UNLIKELY(!_code))
     218             :     return DebugUtils::errored(kErrorNotInitialized);
     219             : 
     220       27492 :   return _funcs.emitProlog(this, frame);
     221             : }
     222             : 
     223       27492 : Error BaseEmitter::emitEpilog(const FuncFrame& frame) {
     224       27492 :   if (ASMJIT_UNLIKELY(!_code))
     225             :     return DebugUtils::errored(kErrorNotInitialized);
     226             : 
     227       27492 :   return _funcs.emitEpilog(this, frame);
     228             : }
     229             : 
     230           0 : Error BaseEmitter::emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args) {
     231           0 :   if (ASMJIT_UNLIKELY(!_code))
     232             :     return DebugUtils::errored(kErrorNotInitialized);
     233             : 
     234           0 :   return _funcs.emitArgsAssignment(this, frame, args);
     235             : }
     236             : 
     237             : // BaseEmitter - Comment
     238             : // =====================
     239             : 
     240           0 : Error BaseEmitter::commentf(const char* fmt, ...) {
     241           0 :   if (!hasEmitterFlag(EmitterFlags::kLogComments)) {
     242           0 :     if (!hasEmitterFlag(EmitterFlags::kAttached))
     243           0 :       return reportError(DebugUtils::errored(kErrorNotInitialized));
     244             :     return kErrorOk;
     245             :   }
     246             : 
     247             : #ifndef ASMJIT_NO_LOGGING
     248             :   StringTmp<1024> sb;
     249             : 
     250             :   va_list ap;
     251           0 :   va_start(ap, fmt);
     252             :   Error err = sb.appendVFormat(fmt, ap);
     253           0 :   va_end(ap);
     254             : 
     255           0 :   ASMJIT_PROPAGATE(err);
     256           0 :   return comment(sb.data(), sb.size());
     257             : #else
     258             :   DebugUtils::unused(fmt);
     259             :   return kErrorOk;
     260             : #endif
     261             : }
     262             : 
     263           0 : Error BaseEmitter::commentv(const char* fmt, va_list ap) {
     264           0 :   if (!hasEmitterFlag(EmitterFlags::kLogComments)) {
     265           0 :     if (!hasEmitterFlag(EmitterFlags::kAttached))
     266           0 :       return reportError(DebugUtils::errored(kErrorNotInitialized));
     267             :     return kErrorOk;
     268             :   }
     269             : 
     270             : #ifndef ASMJIT_NO_LOGGING
     271             :   StringTmp<1024> sb;
     272             :   Error err = sb.appendVFormat(fmt, ap);
     273             : 
     274           0 :   ASMJIT_PROPAGATE(err);
     275           0 :   return comment(sb.data(), sb.size());
     276             : #else
     277             :   DebugUtils::unused(fmt, ap);
     278             :   return kErrorOk;
     279             : #endif
     280             : }
     281             : 
     282             : // BaseEmitter - Events
     283             : // ====================
     284             : 
     285       54984 : Error BaseEmitter::onAttach(CodeHolder* code) noexcept {
     286       54984 :   _code = code;
     287       54984 :   _environment = code->environment();
     288             :   _addEmitterFlags(EmitterFlags::kAttached);
     289             : 
     290             :   const ArchTraits& archTraits = ArchTraits::byArch(code->arch());
     291       54984 :   RegType nativeRegType = Environment::is32Bit(code->arch()) ? RegType::kGp32 : RegType::kGp64;
     292       54984 :   _gpSignature = archTraits.regTypeToSignature(nativeRegType);
     293             : 
     294       54984 :   onSettingsUpdated();
     295       54984 :   return kErrorOk;
     296             : }
     297             : 
     298           0 : Error BaseEmitter::onDetach(CodeHolder* code) noexcept {
     299             :   DebugUtils::unused(code);
     300             : 
     301           0 :   if (!hasOwnLogger())
     302           0 :     _logger = nullptr;
     303             : 
     304           0 :   if (!hasOwnErrorHandler())
     305           0 :     _errorHandler = nullptr;
     306             : 
     307             :   _clearEmitterFlags(~kEmitterPreservedFlags);
     308           0 :   _forcedInstOptions = InstOptions::kReserved;
     309           0 :   _privateData = 0;
     310             : 
     311             :   _environment.reset();
     312             :   _gpSignature.reset();
     313             : 
     314           0 :   _instOptions = InstOptions::kNone;
     315             :   _extraReg.reset();
     316           0 :   _inlineComment = nullptr;
     317             : 
     318           0 :   return kErrorOk;
     319             : }
     320             : 
     321       54984 : void BaseEmitter::onSettingsUpdated() noexcept {
     322             :   // Only called when attached to CodeHolder by CodeHolder.
     323             :   ASMJIT_ASSERT(_code != nullptr);
     324             : 
     325       54984 :   if (!hasOwnLogger())
     326       54984 :     _logger = _code->logger();
     327             : 
     328       54984 :   if (!hasOwnErrorHandler())
     329       54984 :     _errorHandler = _code->errorHandler();
     330             : 
     331       54984 :   BaseEmitter_updateForcedOptions(this);
     332       54984 : }
     333             : 
     334             : ASMJIT_END_NAMESPACE
     335             : 
     336             : #endif // __PLUMED_HAS_ASMJIT

Generated by: LCOV version 1.16