LCOV - code coverage report
Current view: top level - asmjit - emitter.h (source / functions) Hit Total Coverage
Test: plumed test coverage (other modules) Lines: 22 27 81.5 %
Date: 2026-11-05 10:19:06 Functions: 1 1 100.0 %

          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             : #ifndef ASMJIT_CORE_EMITTER_H_INCLUDED
       8             : #define ASMJIT_CORE_EMITTER_H_INCLUDED
       9             : 
      10             : #include "archtraits.h"
      11             : #include "codeholder.h"
      12             : #include "formatter.h"
      13             : #include "inst.h"
      14             : #include "operand.h"
      15             : #include "type.h"
      16             : 
      17             : ASMJIT_BEGIN_NAMESPACE
      18             : 
      19             : //! \addtogroup asmjit_core
      20             : //! \{
      21             : 
      22             : class ConstPool;
      23             : class FuncFrame;
      24             : class FuncArgsAssignment;
      25             : 
      26             : //! Align mode, used by \ref BaseEmitter::align().
      27             : enum class AlignMode : uint8_t {
      28             :   //! Align executable code.
      29             :   kCode = 0,
      30             :   //! Align non-executable code.
      31             :   kData = 1,
      32             :   //! Align by a sequence of zeros.
      33             :   kZero = 2,
      34             : 
      35             :   //! Maximum value of `AlignMode`.
      36             :   kMaxValue = kZero
      37             : };
      38             : 
      39             : //! Emitter type used by \ref BaseEmitter.
      40             : enum class EmitterType : uint8_t {
      41             :   //! Unknown or uninitialized.
      42             :   kNone = 0,
      43             :   //! Emitter inherits from \ref BaseAssembler.
      44             :   kAssembler = 1,
      45             :   //! Emitter inherits from \ref BaseBuilder.
      46             :   kBuilder = 2,
      47             :   //! Emitter inherits from \ref BaseCompiler.
      48             :   kCompiler = 3,
      49             : 
      50             :   //! Maximum value of `EmitterType`.
      51             :   kMaxValue = kCompiler
      52             : };
      53             : 
      54             : //! Emitter flags, used by \ref BaseEmitter.
      55             : enum class EmitterFlags : uint8_t {
      56             :   //! No flags.
      57             :   kNone = 0u,
      58             :   //! Emitter is attached to CodeHolder.
      59             :   kAttached = 0x01u,
      60             :   //! The emitter must emit comments.
      61             :   kLogComments = 0x08u,
      62             :   //! The emitter has its own \ref Logger (not propagated from \ref CodeHolder).
      63             :   kOwnLogger = 0x10u,
      64             :   //! The emitter has its own \ref ErrorHandler (not propagated from \ref CodeHolder).
      65             :   kOwnErrorHandler = 0x20u,
      66             :   //! The emitter was finalized.
      67             :   kFinalized = 0x40u,
      68             :   //! The emitter was destroyed.
      69             :   //!
      70             :   //! This flag is used for a very short time when an emitter is being destroyed by
      71             :   //! CodeHolder.
      72             :   kDestroyed = 0x80u
      73             : };
      74      109968 : ASMJIT_DEFINE_ENUM_FLAGS(EmitterFlags)
      75             : 
      76             : //! Encoding options.
      77             : enum class EncodingOptions : uint32_t {
      78             :   //! No encoding options.
      79             :   kNone = 0,
      80             : 
      81             :   //! Emit instructions that are optimized for size, if possible.
      82             :   //!
      83             :   //! Default: false.
      84             :   //!
      85             :   //! X86 Specific
      86             :   //! ------------
      87             :   //!
      88             :   //! When this option is set it the assembler will try to fix instructions if possible into operation equivalent
      89             :   //! instructions that take less bytes by taking advantage of implicit zero extension. For example instruction
      90             :   //! like `mov r64, imm` and `and r64, imm` can be translated to `mov r32, imm` and `and r32, imm` when the
      91             :   //! immediate constant is lesser than `2^31`.
      92             :   kOptimizeForSize = 0x00000001u,
      93             : 
      94             :   //! Emit optimized code-alignment sequences.
      95             :   //!
      96             :   //! Default: false.
      97             :   //!
      98             :   //! X86 Specific
      99             :   //! ------------
     100             :   //!
     101             :   //! Default align sequence used by X86 architecture is one-byte (0x90) opcode that is often shown by disassemblers
     102             :   //! as NOP. However there are more optimized align sequences for 2-11 bytes that may execute faster on certain CPUs.
     103             :   //! If this feature is enabled AsmJit will generate specialized sequences for alignment between 2 to 11 bytes.
     104             :   kOptimizedAlign = 0x00000002u,
     105             : 
     106             :   //! Emit jump-prediction hints.
     107             :   //!
     108             :   //! Default: false.
     109             :   //!
     110             :   //! X86 Specific
     111             :   //! ------------
     112             :   //!
     113             :   //! Jump prediction is usually based on the direction of the jump. If the jump is backward it is usually predicted as
     114             :   //! taken; and if the jump is forward it is usually predicted as not-taken. The reason is that loops generally use
     115             :   //! backward jumps and conditions usually use forward jumps. However this behavior can be overridden by using
     116             :   //! instruction prefixes. If this option is enabled these hints will be emitted.
     117             :   //!
     118             :   //! This feature is disabled by default, because the only processor that used to take into consideration prediction
     119             :   //! hints was P4. Newer processors implement heuristics for branch prediction and ignore static hints. This means
     120             :   //! that this feature can be only used for annotation purposes.
     121             :   kPredictedJumps = 0x00000010u
     122             : };
     123       27492 : ASMJIT_DEFINE_ENUM_FLAGS(EncodingOptions)
     124             : 
     125             : //! Diagnostic options are used to tell emitters and their passes to perform diagnostics when emitting or processing
     126             : //! user code. These options control validation and extra diagnostics that can be performed by higher level emitters.
     127             : //!
     128             : //! Instruction Validation
     129             : //! ----------------------
     130             : //!
     131             : //! \ref BaseAssembler implementation perform by default only basic checks that are necessary to identify all
     132             : //! variations of an instruction so the correct encoding can be selected. This is fine for production-ready code
     133             : //! as the assembler doesn't have to perform checks that would slow it down. However, sometimes these checks are
     134             : //! beneficial especially when the project that uses AsmJit is in a development phase, in which mistakes happen
     135             : //! often. To make the experience of using AsmJit seamless it offers validation features that can be controlled
     136             : //! by \ref DiagnosticOptions.
     137             : //!
     138             : //! Compiler Diagnostics
     139             : //! --------------------
     140             : //!
     141             : //! Diagnostic options work with \ref BaseCompiler passes (precisely with its register allocation pass). These options
     142             : //! can be used to enable logging of all operations that the Compiler does.
     143             : enum class DiagnosticOptions : uint32_t {
     144             :   //! No validation options.
     145             :   kNone = 0,
     146             : 
     147             :   //! Perform strict validation in \ref BaseAssembler::emit() implementations.
     148             :   //!
     149             :   //! This flag ensures that each instruction is checked before it's encoded into a binary representation. This flag
     150             :   //! is only relevant for \ref BaseAssembler implementations, but can be set in any other emitter type, in that case
     151             :   //! if that emitter needs to create an assembler on its own, for the purpose of \ref BaseEmitter::finalize() it
     152             :   //! would propagate this flag to such assembler so all instructions passed to it are explicitly validated.
     153             :   //!
     154             :   //! Default: false.
     155             :   kValidateAssembler = 0x00000001u,
     156             : 
     157             :   //! Perform strict validation in \ref BaseBuilder::emit() and \ref BaseCompiler::emit() implementations.
     158             :   //!
     159             :   //! This flag ensures that each instruction is checked before an \ref InstNode representing the instruction is
     160             :   //! created by \ref BaseBuilder or \ref BaseCompiler. This option could be more useful than \ref kValidateAssembler
     161             :   //! in cases in which there is an invalid instruction passed to an assembler, which was invalid much earlier, most
     162             :   //! likely when such instruction was passed to Builder/Compiler.
     163             :   //!
     164             :   //! This is a separate option that was introduced, because it's possible to manipulate the instruction stream
     165             :   //! emitted by \ref BaseBuilder and \ref BaseCompiler - this means that it's allowed to emit invalid instructions
     166             :   //! (for example with missing operands) that will be fixed later before finalizing it.
     167             :   //!
     168             :   //! Default: false.
     169             :   kValidateIntermediate = 0x00000002u,
     170             : 
     171             :   //! Annotate all nodes processed by register allocator (Compiler/RA).
     172             :   //!
     173             :   //! \note Annotations don't need debug options, however, some debug options like `kRADebugLiveness` may influence
     174             :   //! their output (for example the mentioned option would add liveness information to per-instruction annotation).
     175             :   kRAAnnotate = 0x00000080u,
     176             : 
     177             :   //! Debug CFG generation and other related algorithms / operations (Compiler/RA).
     178             :   kRADebugCFG = 0x00000100u,
     179             : 
     180             :   //! Debug liveness analysis (Compiler/RA).
     181             :   kRADebugLiveness = 0x00000200u,
     182             : 
     183             :   //! Debug register allocation assignment (Compiler/RA).
     184             :   kRADebugAssignment = 0x00000400u,
     185             : 
     186             :   //! Debug the removal of code part of unreachable blocks.
     187             :   kRADebugUnreachable = 0x00000800u,
     188             : 
     189             :   //! Enable all debug options (Compiler/RA).
     190             :   kRADebugAll = 0x0000FF00u,
     191             : };
     192       27492 : ASMJIT_DEFINE_ENUM_FLAGS(DiagnosticOptions)
     193             : 
     194             : //! Provides a base foundation to emitting code - specialized by \ref BaseAssembler and \ref BaseBuilder.
     195             : class ASMJIT_VIRTAPI BaseEmitter {
     196             : public:
     197             :   ASMJIT_BASE_CLASS(BaseEmitter)
     198             : 
     199             :   //! \name Members
     200             :   //! \{
     201             : 
     202             :   //! See \ref EmitterType.
     203             :   EmitterType _emitterType = EmitterType::kNone;
     204             :   //! See \ref EmitterFlags.
     205             :   EmitterFlags _emitterFlags = EmitterFlags::kNone;
     206             :   //! Validation flags in case validation is used.
     207             :   //!
     208             :   //! \note Validation flags are specific to the emitter and they are setup at construction time and then never
     209             :   //! changed.
     210             :   ValidationFlags _validationFlags = ValidationFlags::kNone;
     211             :   //! Validation options.
     212             :   DiagnosticOptions _diagnosticOptions = DiagnosticOptions::kNone;
     213             : 
     214             :   //! All supported architectures in a bit-mask, where LSB is the bit with a zero index.
     215             :   uint64_t _archMask = 0;
     216             : 
     217             :   //! Encoding options.
     218             :   EncodingOptions _encodingOptions = EncodingOptions::kNone;
     219             : 
     220             :   //! Forced instruction options, combined with \ref _instOptions by \ref emit().
     221             :   InstOptions _forcedInstOptions = InstOptions::kReserved;
     222             :   //! Internal private data used freely by any emitter.
     223             :   uint32_t _privateData = 0;
     224             : 
     225             :   //! CodeHolder the emitter is attached to.
     226             :   CodeHolder* _code = nullptr;
     227             :   //! Attached \ref Logger.
     228             :   Logger* _logger = nullptr;
     229             :   //! Attached \ref ErrorHandler.
     230             :   ErrorHandler* _errorHandler = nullptr;
     231             : 
     232             :   //! Describes the target environment, matches \ref CodeHolder::environment().
     233             :   Environment _environment {};
     234             :   //! Native GP register signature and signature related information.
     235             :   OperandSignature _gpSignature {};
     236             : 
     237             :   //! Next instruction options (affects the next instruction).
     238             :   InstOptions _instOptions = InstOptions::kNone;
     239             :   //! Extra register (op-mask {k} on AVX-512) (affects the next instruction).
     240             :   RegOnly _extraReg {};
     241             :   //! Inline comment of the next instruction (affects the next instruction).
     242             :   const char* _inlineComment = nullptr;
     243             : 
     244             :   //! Function callbacks used by emitter implementation.
     245             :   //!
     246             :   //! These are typically shared between Assembler/Builder/Compiler of a single backend.
     247             :   struct Funcs {
     248             :     typedef Error (ASMJIT_CDECL* EmitProlog)(BaseEmitter* emitter, const FuncFrame& frame);
     249             :     typedef Error (ASMJIT_CDECL* EmitEpilog)(BaseEmitter* emitter, const FuncFrame& frame);
     250             :     typedef Error (ASMJIT_CDECL* EmitArgsAssignment)(BaseEmitter* emitter, const FuncFrame& frame, const FuncArgsAssignment& args);
     251             : 
     252             :     typedef Error (ASMJIT_CDECL* FormatInstruction)(
     253             :       String& sb,
     254             :       FormatFlags formatFlags,
     255             :       const BaseEmitter* emitter,
     256             :       Arch arch,
     257             :       const BaseInst& inst, const Operand_* operands, size_t opCount) ASMJIT_NOEXCEPT_TYPE;
     258             : 
     259             :     typedef Error (ASMJIT_CDECL* ValidateFunc)(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) ASMJIT_NOEXCEPT_TYPE;
     260             : 
     261             :     //! Emit prolog implementation.
     262             :     EmitProlog emitProlog;
     263             :     //! Emit epilog implementation.
     264             :     EmitEpilog emitEpilog;
     265             :     //! Emit arguments assignment implementation.
     266             :     EmitArgsAssignment emitArgsAssignment;
     267             :     //! Instruction formatter implementation.
     268             :     FormatInstruction formatInstruction;
     269             :     //! Instruction validation implementation.
     270             :     ValidateFunc validate;
     271             : 
     272             :     //! Resets all functions to nullptr.
     273             :     inline void reset() noexcept {
     274             :       emitProlog = nullptr;
     275             :       emitEpilog = nullptr;
     276             :       emitArgsAssignment = nullptr;
     277             :       validate = nullptr;
     278             :     }
     279             :   };
     280             : 
     281             :   Funcs _funcs {};
     282             : 
     283             :   //! \}
     284             : 
     285             :   //! \name Construction & Destruction
     286             :   //! \{
     287             : 
     288             :   ASMJIT_API explicit BaseEmitter(EmitterType emitterType) noexcept;
     289             :   ASMJIT_API virtual ~BaseEmitter() noexcept;
     290             : 
     291             :   //! \}
     292             : 
     293             :   //! \name Cast
     294             :   //! \{
     295             : 
     296             :   template<typename T>
     297             :   inline T* as() noexcept { return reinterpret_cast<T*>(this); }
     298             : 
     299             :   template<typename T>
     300             :   inline const T* as() const noexcept { return reinterpret_cast<const T*>(this); }
     301             : 
     302             :   //! \}
     303             : 
     304             :   //! \name Emitter Type & Flags
     305             :   //! \{
     306             : 
     307             :   //! Returns the type of this emitter, see `EmitterType`.
     308      137460 :   inline EmitterType emitterType() const noexcept { return _emitterType; }
     309             :   //! Returns emitter flags , see `Flags`.
     310             :   inline EmitterFlags emitterFlags() const noexcept { return _emitterFlags; }
     311             : 
     312             :   //! Tests whether the emitter inherits from `BaseAssembler`.
     313       54984 :   inline bool isAssembler() const noexcept { return _emitterType == EmitterType::kAssembler; }
     314             :   //! Tests whether the emitter inherits from `BaseBuilder`.
     315             :   //!
     316             :   //! \note Both Builder and Compiler emitters would return `true`.
     317             :   inline bool isBuilder() const noexcept { return uint32_t(_emitterType) >= uint32_t(EmitterType::kBuilder); }
     318             :   //! Tests whether the emitter inherits from `BaseCompiler`.
     319           0 :   inline bool isCompiler() const noexcept { return _emitterType == EmitterType::kCompiler; }
     320             : 
     321             :   //! Tests whether the emitter has the given `flag` enabled.
     322      109968 :   inline bool hasEmitterFlag(EmitterFlags flag) const noexcept { return Support::test(_emitterFlags, flag); }
     323             :   //! Tests whether the emitter is finalized.
     324             :   inline bool isFinalized() const noexcept { return hasEmitterFlag(EmitterFlags::kFinalized); }
     325             :   //! Tests whether the emitter is destroyed (only used during destruction).
     326             :   inline bool isDestroyed() const noexcept { return hasEmitterFlag(EmitterFlags::kDestroyed); }
     327             : 
     328       54984 :   inline void _addEmitterFlags(EmitterFlags flags) noexcept { _emitterFlags |= flags; }
     329       82476 :   inline void _clearEmitterFlags(EmitterFlags flags) noexcept { _emitterFlags &= _emitterFlags & ~flags; }
     330             : 
     331             :   //! \}
     332             : 
     333             :   //! \name Target Information
     334             :   //! \{
     335             : 
     336             :   //! Returns the CodeHolder this emitter is attached to.
     337           0 :   inline CodeHolder* code() const noexcept { return _code; }
     338             : 
     339             :   //! Returns the target environment.
     340             :   //!
     341             :   //! The returned \ref Environment reference matches \ref CodeHolder::environment().
     342       37131 :   inline const Environment& environment() const noexcept { return _environment; }
     343             : 
     344             :   //! Tests whether the target architecture is 32-bit.
     345             :   inline bool is32Bit() const noexcept { return environment().is32Bit(); }
     346             :   //! Tests whether the target architecture is 64-bit.
     347             :   inline bool is64Bit() const noexcept { return environment().is64Bit(); }
     348             : 
     349             :   //! Returns the target architecture type.
     350             :   inline Arch arch() const noexcept { return environment().arch(); }
     351             :   //! Returns the target architecture sub-type.
     352             :   inline SubArch subArch() const noexcept { return environment().subArch(); }
     353             : 
     354             :   //! Returns the target architecture's GP register size (4 or 8 bytes).
     355       27492 :   inline uint32_t registerSize() const noexcept { return environment().registerSize(); }
     356             : 
     357             :   //! \}
     358             : 
     359             :   //! \name Initialization & Finalization
     360             :   //! \{
     361             : 
     362             :   //! Tests whether the emitter is initialized (i.e. attached to \ref CodeHolder).
     363             :   inline bool isInitialized() const noexcept { return _code != nullptr; }
     364             : 
     365             :   //! Finalizes this emitter.
     366             :   //!
     367             :   //! Materializes the content of the emitter by serializing it to the attached \ref CodeHolder through an architecture
     368             :   //! specific \ref BaseAssembler. This function won't do anything if the emitter inherits from \ref BaseAssembler as
     369             :   //! assemblers emit directly to a \ref CodeBuffer held by \ref CodeHolder. However, if this is an emitter that
     370             :   //! inherits from \ref BaseBuilder or \ref BaseCompiler then these emitters need the materialization phase as they
     371             :   //! store their content in a representation not visible to \ref CodeHolder.
     372             :   ASMJIT_API virtual Error finalize();
     373             : 
     374             :   //! \}
     375             : 
     376             :   //! \name Logging
     377             :   //! \{
     378             : 
     379             :   //! Tests whether the emitter has a logger.
     380             :   inline bool hasLogger() const noexcept { return _logger != nullptr; }
     381             : 
     382             :   //! Tests whether the emitter has its own logger.
     383             :   //!
     384             :   //! Own logger means that it overrides the possible logger that may be used by \ref CodeHolder this emitter is
     385             :   //! attached to.
     386             :   inline bool hasOwnLogger() const noexcept { return hasEmitterFlag(EmitterFlags::kOwnLogger); }
     387             : 
     388             :   //! Returns the logger this emitter uses.
     389             :   //!
     390             :   //! The returned logger is either the emitter's own logger or it's logger used by \ref CodeHolder this emitter
     391             :   //! is attached to.
     392           0 :   inline Logger* logger() const noexcept { return _logger; }
     393             : 
     394             :   //! Sets or resets the logger of the emitter.
     395             :   //!
     396             :   //! If the `logger` argument is non-null then the logger will be considered emitter's own logger, see \ref
     397             :   //! hasOwnLogger() for more details. If the given `logger` is null then the emitter will automatically use logger
     398             :   //! that is attached to the \ref CodeHolder this emitter is attached to.
     399             :   ASMJIT_API void setLogger(Logger* logger) noexcept;
     400             : 
     401             :   //! Resets the logger of this emitter.
     402             :   //!
     403             :   //! The emitter will bail to using a logger attached to \ref CodeHolder this emitter is attached to, or no logger
     404             :   //! at all if \ref CodeHolder doesn't have one.
     405             :   inline void resetLogger() noexcept { return setLogger(nullptr); }
     406             : 
     407             :   //! \}
     408             : 
     409             :   //! \name Error Handling
     410             :   //! \{
     411             : 
     412             :   //! Tests whether the emitter has an error handler attached.
     413             :   inline bool hasErrorHandler() const noexcept { return _errorHandler != nullptr; }
     414             : 
     415             :   //! Tests whether the emitter has its own error handler.
     416             :   //!
     417             :   //! Own error handler means that it overrides the possible error handler that may be used by \ref CodeHolder this
     418             :   //! emitter is attached to.
     419             :   inline bool hasOwnErrorHandler() const noexcept { return hasEmitterFlag(EmitterFlags::kOwnErrorHandler); }
     420             : 
     421             :   //! Returns the error handler this emitter uses.
     422             :   //!
     423             :   //! The returned error handler is either the emitter's own error handler or it's error handler used by
     424             :   //! \ref CodeHolder this emitter is attached to.
     425       27492 :   inline ErrorHandler* errorHandler() const noexcept { return _errorHandler; }
     426             : 
     427             :   //! Sets or resets the error handler of the emitter.
     428             :   ASMJIT_API void setErrorHandler(ErrorHandler* errorHandler) noexcept;
     429             : 
     430             :   //! Resets the error handler.
     431             :   inline void resetErrorHandler() noexcept { setErrorHandler(nullptr); }
     432             : 
     433             :   //! Handles the given error in the following way:
     434             :   //!   1. If the emitter has \ref ErrorHandler attached, it calls its \ref ErrorHandler::handleError() member function
     435             :   //!      first, and then returns the error. The `handleError()` function may throw.
     436             :   //!   2. if the emitter doesn't have \ref ErrorHandler, the error is simply returned.
     437             :   ASMJIT_API Error reportError(Error err, const char* message = nullptr);
     438             : 
     439             :   //! \}
     440             : 
     441             :   //! \name Encoding Options
     442             :   //! \{
     443             : 
     444             :   //! Returns encoding options.
     445       27492 :   inline EncodingOptions encodingOptions() const noexcept { return _encodingOptions; }
     446             :   //! Tests whether the encoding `option` is set.
     447           0 :   inline bool hasEncodingOption(EncodingOptions option) const noexcept { return Support::test(_encodingOptions, option); }
     448             : 
     449             :   //! Enables the given encoding `options`.
     450             :   inline void addEncodingOptions(EncodingOptions options) noexcept { _encodingOptions |= options; }
     451             :   //! Disables the given encoding `options`.
     452             :   inline void clearEncodingOptions(EncodingOptions options) noexcept { _encodingOptions &= ~options; }
     453             : 
     454             :   //! \}
     455             : 
     456             :   //! \name Diagnostic Options
     457             :   //! \{
     458             : 
     459             :   //! Returns the emitter's diagnostic options.
     460       27492 :   inline DiagnosticOptions diagnosticOptions() const noexcept { return _diagnosticOptions; }
     461             : 
     462             :   //! Tests whether the given `option` is present in the emitter's diagnostic options.
     463      109968 :   inline bool hasDiagnosticOption(DiagnosticOptions option) const noexcept { return Support::test(_diagnosticOptions, option); }
     464             : 
     465             :   //! Activates the given diagnostic `options`.
     466             :   //!
     467             :   //! This function is used to activate explicit validation options that will be then used by all emitter
     468             :   //! implementations. There are in general two possibilities:
     469             :   //!
     470             :   //!   - Architecture specific assembler is used. In this case a \ref DiagnosticOptions::kValidateAssembler can be
     471             :   //!     used to turn on explicit validation that will be used before an instruction is emitted. This means that
     472             :   //!     internally an extra step will be performed to make sure that the instruction is correct. This is needed,
     473             :   //!     because by default assemblers prefer speed over strictness.
     474             :   //!
     475             :   //!     This option should be used in debug builds as it's pretty expensive.
     476             :   //!
     477             :   //!   - Architecture specific builder or compiler is used. In this case the user can turn on
     478             :   //!     \ref DiagnosticOptions::kValidateIntermediate option that adds explicit validation step before the Builder
     479             :   //!     or Compiler creates an \ref InstNode to represent an emitted instruction. Error will be returned if the
     480             :   //!     instruction is ill-formed. In addition, also \ref DiagnosticOptions::kValidateAssembler can be used, which
     481             :   //!     would not be consumed by Builder / Compiler directly, but it would be propagated to an architecture specific
     482             :   //!     \ref BaseAssembler implementation it creates during \ref BaseEmitter::finalize().
     483             :   ASMJIT_API void addDiagnosticOptions(DiagnosticOptions options) noexcept;
     484             : 
     485             :   //! Deactivates the given validation `options`.
     486             :   //!
     487             :   //! See \ref addDiagnosticOptions() and \ref DiagnosticOptions for more details.
     488             :   ASMJIT_API void clearDiagnosticOptions(DiagnosticOptions options) noexcept;
     489             : 
     490             :   //! \}
     491             : 
     492             :   //! \name Instruction Options
     493             :   //! \{
     494             : 
     495             :   //! Returns forced instruction options.
     496             :   //!
     497             :   //! Forced instruction options are merged with next instruction options before the instruction is encoded. These
     498             :   //! options have some bits reserved that are used by error handling, logging, and instruction validation purposes.
     499             :   //! Other options are globals that affect each instruction.
     500      774379 :   inline InstOptions forcedInstOptions() const noexcept { return _forcedInstOptions; }
     501             : 
     502             :   //! Returns options of the next instruction.
     503      774379 :   inline InstOptions instOptions() const noexcept { return _instOptions; }
     504             :   //! Returns options of the next instruction.
     505      392009 :   inline void setInstOptions(InstOptions options) noexcept { _instOptions = options; }
     506             :   //! Adds options of the next instruction.
     507             :   inline void addInstOptions(InstOptions options) noexcept { _instOptions |= options; }
     508             :   //! Resets options of the next instruction.
     509      392009 :   inline void resetInstOptions() noexcept { _instOptions = InstOptions::kNone; }
     510             : 
     511             :   //! Tests whether the extra register operand is valid.
     512             :   inline bool hasExtraReg() const noexcept { return _extraReg.isReg(); }
     513             :   //! Returns an extra operand that will be used by the next instruction (architecture specific).
     514             :   inline const RegOnly& extraReg() const noexcept { return _extraReg; }
     515             :   //! Sets an extra operand that will be used by the next instruction (architecture specific).
     516             :   inline void setExtraReg(const BaseReg& reg) noexcept { _extraReg.init(reg); }
     517             :   //! Sets an extra operand that will be used by the next instruction (architecture specific).
     518             :   inline void setExtraReg(const RegOnly& reg) noexcept { _extraReg.init(reg); }
     519             :   //! Resets an extra operand that will be used by the next instruction (architecture specific).
     520             :   inline void resetExtraReg() noexcept { _extraReg.reset(); }
     521             : 
     522             :   //! Returns comment/annotation of the next instruction.
     523      382370 :   inline const char* inlineComment() const noexcept { return _inlineComment; }
     524             :   //! Sets comment/annotation of the next instruction.
     525             :   //!
     526             :   //! \note This string is set back to null by `_emit()`, but until that it has to remain valid as the Emitter is not
     527             :   //! required to make a copy of it (and it would be slow to do that for each instruction).
     528      552198 :   inline void setInlineComment(const char* s) noexcept { _inlineComment = s; }
     529             :   //! Resets the comment/annotation to nullptr.
     530      829363 :   inline void resetInlineComment() noexcept { _inlineComment = nullptr; }
     531             : 
     532             :   //! \}
     533             : 
     534             :   //! \name Sections
     535             :   //! \{
     536             : 
     537             :   virtual Error section(Section* section) = 0;
     538             : 
     539             :   //! \}
     540             : 
     541             :   //! \name Labels
     542             :   //! \{
     543             : 
     544             :   //! Creates a new label.
     545             :   virtual Label newLabel() = 0;
     546             :   //! Creates a new named label.
     547             :   virtual Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, LabelType type = LabelType::kGlobal, uint32_t parentId = Globals::kInvalidId) = 0;
     548             : 
     549             :   //! Creates a new anonymous label with a name, which can only be used for debugging purposes.
     550             :   inline Label newAnonymousLabel(const char* name, size_t nameSize = SIZE_MAX) { return newNamedLabel(name, nameSize, LabelType::kAnonymous); }
     551             :   //! Creates a new external label.
     552             :   inline Label newExternalLabel(const char* name, size_t nameSize = SIZE_MAX) { return newNamedLabel(name, nameSize, LabelType::kExternal); }
     553             : 
     554             :   //! Returns `Label` by `name`.
     555             :   //!
     556             :   //! Returns invalid Label in case that the name is invalid or label was not found.
     557             :   //!
     558             :   //! \note This function doesn't trigger ErrorHandler in case the name is invalid or no such label exist. You must
     559             :   //! always check the validity of the `Label` returned.
     560             :   ASMJIT_API Label labelByName(const char* name, size_t nameSize = SIZE_MAX, uint32_t parentId = Globals::kInvalidId) noexcept;
     561             : 
     562             :   //! Binds the `label` to the current position of the current section.
     563             :   //!
     564             :   //! \note Attempt to bind the same label multiple times will return an error.
     565             :   virtual Error bind(const Label& label) = 0;
     566             : 
     567             :   //! Tests whether the label `id` is valid (i.e. registered).
     568             :   ASMJIT_API bool isLabelValid(uint32_t labelId) const noexcept;
     569             :   //! Tests whether the `label` is valid (i.e. registered).
     570           0 :   inline bool isLabelValid(const Label& label) const noexcept { return isLabelValid(label.id()); }
     571             : 
     572             :   //! \}
     573             : 
     574             :   //! \name Emit
     575             :   //! \{
     576             : 
     577             :   // NOTE: These `emit()` helpers are designed to address a code-bloat generated by C++ compilers to call a function
     578             :   // having many arguments. Each parameter to `_emit()` requires some code to pass it, which means that if we default
     579             :   // to 5 arguments in `_emit()` and instId the C++ compiler would have to generate a virtual function call having 5
     580             :   // parameters and additional `this` argument, which is quite a lot. Since by default most instructions have 2 to 3
     581             :   // operands it's better to introduce helpers that pass from 0 to 6 operands that help to reduce the size of emit(...)
     582             :   // function call.
     583             : 
     584             :   //! Emits an instruction (internal).
     585             :   ASMJIT_API Error _emitI(InstId instId);
     586             :   //! \overload
     587             :   ASMJIT_API Error _emitI(InstId instId, const Operand_& o0);
     588             :   //! \overload
     589             :   ASMJIT_API Error _emitI(InstId instId, const Operand_& o0, const Operand_& o1);
     590             :   //! \overload
     591             :   ASMJIT_API Error _emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2);
     592             :   //! \overload
     593             :   ASMJIT_API Error _emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3);
     594             :   //! \overload
     595             :   ASMJIT_API Error _emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4);
     596             :   //! \overload
     597             :   ASMJIT_API Error _emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, const Operand_& o5);
     598             : 
     599             :   //! Emits an instruction `instId` with the given `operands`.
     600             :   template<typename... Args>
     601             :   ASMJIT_FORCE_INLINE Error emit(InstId instId, Args&&... operands) {
     602       77713 :     return _emitI(instId, Support::ForwardOp<Args>::forward(operands)...);
     603             :   }
     604             : 
     605             :   ASMJIT_FORCE_INLINE Error emitOpArray(InstId instId, const Operand_* operands, size_t opCount) {
     606             :     return _emitOpArray(instId, operands, opCount);
     607             :   }
     608             : 
     609             :   ASMJIT_FORCE_INLINE Error emitInst(const BaseInst& inst, const Operand_* operands, size_t opCount) {
     610             :     setInstOptions(inst.options());
     611             :     setExtraReg(inst.extraReg());
     612             :     return _emitOpArray(inst.id(), operands, opCount);
     613             :   }
     614             : 
     615             :   //! \cond INTERNAL
     616             :   //! Emits an instruction - all 6 operands must be defined.
     617             :   virtual Error _emit(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* oExt) = 0;
     618             :   //! Emits instruction having operands stored in array.
     619             :   ASMJIT_API virtual Error _emitOpArray(InstId instId, const Operand_* operands, size_t opCount);
     620             :   //! \endcond
     621             : 
     622             :   //! \}
     623             : 
     624             :   //! \name Emit Utilities
     625             :   //! \{
     626             : 
     627             :   ASMJIT_API Error emitProlog(const FuncFrame& frame);
     628             :   ASMJIT_API Error emitEpilog(const FuncFrame& frame);
     629             :   ASMJIT_API Error emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args);
     630             : 
     631             :   //! \}
     632             : 
     633             :   //! \name Align
     634             :   //! \{
     635             : 
     636             :   //! Aligns the current CodeBuffer position to the `alignment` specified.
     637             :   //!
     638             :   //! The sequence that is used to fill the gap between the aligned location and the current location depends on the
     639             :   //! align `mode`, see \ref AlignMode. The `alignment` argument specifies alignment in bytes, so for example when
     640             :   //! it's `32` it means that the code buffer will be aligned to `32` bytes.
     641             :   virtual Error align(AlignMode alignMode, uint32_t alignment) = 0;
     642             : 
     643             :   //! \}
     644             : 
     645             :   //! \name Embed
     646             :   //! \{
     647             : 
     648             :   //! Embeds raw data into the \ref CodeBuffer.
     649             :   virtual Error embed(const void* data, size_t dataSize) = 0;
     650             : 
     651             :   //! Embeds a typed data array.
     652             :   //!
     653             :   //! This is the most flexible function for embedding data as it allows to:
     654             :   //!
     655             :   //!   - Assign a `typeId` to the data, so the emitter knows the type of items stored in `data`. Binary data should
     656             :   //!     use \ref TypeId::kUInt8.
     657             :   //!
     658             :   //!   - Repeat the given data `repeatCount` times, so the data can be used as a fill pattern for example, or as a
     659             :   //!     pattern used by SIMD instructions.
     660             :   virtual Error embedDataArray(TypeId typeId, const void* data, size_t itemCount, size_t repeatCount = 1) = 0;
     661             : 
     662             :   //! Embeds int8_t `value` repeated by `repeatCount`.
     663             :   inline Error embedInt8(int8_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt8, &value, 1, repeatCount); }
     664             :   //! Embeds uint8_t `value` repeated by `repeatCount`.
     665             :   inline Error embedUInt8(uint8_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt8, &value, 1, repeatCount); }
     666             :   //! Embeds int16_t `value` repeated by `repeatCount`.
     667             :   inline Error embedInt16(int16_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt16, &value, 1, repeatCount); }
     668             :   //! Embeds uint16_t `value` repeated by `repeatCount`.
     669             :   inline Error embedUInt16(uint16_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt16, &value, 1, repeatCount); }
     670             :   //! Embeds int32_t `value` repeated by `repeatCount`.
     671             :   inline Error embedInt32(int32_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt32, &value, 1, repeatCount); }
     672             :   //! Embeds uint32_t `value` repeated by `repeatCount`.
     673             :   inline Error embedUInt32(uint32_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt32, &value, 1, repeatCount); }
     674             :   //! Embeds int64_t `value` repeated by `repeatCount`.
     675             :   inline Error embedInt64(int64_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt64, &value, 1, repeatCount); }
     676             :   //! Embeds uint64_t `value` repeated by `repeatCount`.
     677             :   inline Error embedUInt64(uint64_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt64, &value, 1, repeatCount); }
     678             :   //! Embeds a floating point `value` repeated by `repeatCount`.
     679             :   inline Error embedFloat(float value, size_t repeatCount = 1) { return embedDataArray(TypeId(TypeUtils::TypeIdOfT<float>::kTypeId), &value, 1, repeatCount); }
     680             :   //! Embeds a floating point `value` repeated by `repeatCount`.
     681             :   inline Error embedDouble(double value, size_t repeatCount = 1) { return embedDataArray(TypeId(TypeUtils::TypeIdOfT<double>::kTypeId), &value, 1, repeatCount); }
     682             : 
     683             :   //! Embeds a constant pool at the current offset by performing the following:
     684             :   //!   1. Aligns by using AlignMode::kData to the minimum `pool` alignment.
     685             :   //!   2. Binds the ConstPool label so it's bound to an aligned location.
     686             :   //!   3. Emits ConstPool content.
     687             :   virtual Error embedConstPool(const Label& label, const ConstPool& pool) = 0;
     688             : 
     689             :   //! Embeds an absolute `label` address as data.
     690             :   //!
     691             :   //! The `dataSize` is an optional argument that can be used to specify the size of the address data. If it's zero
     692             :   //! (default) the address size is deduced from the target architecture (either 4 or 8 bytes).
     693             :   virtual Error embedLabel(const Label& label, size_t dataSize = 0) = 0;
     694             : 
     695             :   //! Embeds a delta (distance) between the `label` and `base` calculating it as `label - base`. This function was
     696             :   //! designed to make it easier to embed lookup tables where each index is a relative distance of two labels.
     697             :   virtual Error embedLabelDelta(const Label& label, const Label& base, size_t dataSize = 0) = 0;
     698             : 
     699             :   //! \}
     700             : 
     701             :   //! \name Comment
     702             :   //! \{
     703             : 
     704             :   //! Emits a comment stored in `data` with an optional `size` parameter.
     705             :   virtual Error comment(const char* data, size_t size = SIZE_MAX) = 0;
     706             : 
     707             :   //! Emits a formatted comment specified by `fmt` and variable number of arguments.
     708             :   ASMJIT_API Error commentf(const char* fmt, ...);
     709             :   //! Emits a formatted comment specified by `fmt` and `ap`.
     710             :   ASMJIT_API Error commentv(const char* fmt, va_list ap);
     711             : 
     712             :   //! \}
     713             : 
     714             :   //! \name Events
     715             :   //! \{
     716             : 
     717             :   //! Called after the emitter was attached to `CodeHolder`.
     718             :   virtual Error onAttach(CodeHolder* ASMJIT_NONNULL(code)) noexcept = 0;
     719             :   //! Called after the emitter was detached from `CodeHolder`.
     720             :   virtual Error onDetach(CodeHolder* ASMJIT_NONNULL(code)) noexcept = 0;
     721             : 
     722             :   //! Called when \ref CodeHolder has updated an important setting, which involves the following:
     723             :   //!
     724             :   //!   - \ref Logger has been changed (\ref CodeHolder::setLogger() has been called).
     725             :   //!
     726             :   //!   - \ref ErrorHandler has been changed (\ref CodeHolder::setErrorHandler() has been called).
     727             :   //!
     728             :   //! This function ensures that the settings are properly propagated from \ref CodeHolder to the emitter.
     729             :   //!
     730             :   //! \note This function is virtual and can be overridden, however, if you do so, always call \ref
     731             :   //! BaseEmitter::onSettingsUpdated() within your own implementation to ensure that the emitter is
     732             :   //! in a consistent state.
     733             :   ASMJIT_API virtual void onSettingsUpdated() noexcept;
     734             : 
     735             :   //! \}
     736             : };
     737             : 
     738             : //! \}
     739             : 
     740             : ASMJIT_END_NAMESPACE
     741             : 
     742             : #endif // ASMJIT_CORE_EMITTER_H_INCLUDED
     743             : 
     744             : #endif // __PLUMED_HAS_ASMJIT

Generated by: LCOV version 1.16