1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 Copyright (c) 2008-2017, Petr Kobalicek
3 
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7 
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11 
12 1. The origin of this software must not be misrepresented; you must not
13    claim that you wrote the original software. If you use this software
14    in a product, an acknowledgment in the product documentation would be
15    appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17    misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
19 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
20 #ifndef __PLUMED_asmjit_codeemitter_h
21 #define __PLUMED_asmjit_codeemitter_h
22 #ifdef __PLUMED_HAS_ASMJIT
23 #pragma GCC diagnostic push
24 #pragma GCC diagnostic ignored "-Wpedantic"
25 // [AsmJit]
26 // Complete x86/x64 JIT and Remote Assembler for C++.
27 //
28 // [License]
29 // Zlib - See LICENSE.md file in the package.
30 
31 // [Guard]
32 #ifndef _ASMJIT_BASE_CODEEMITTER_H
33 #define _ASMJIT_BASE_CODEEMITTER_H
34 
35 // [Dependencies]
36 #include "./arch.h"
37 #include "./codeholder.h"
38 #include "./operand.h"
39 
40 // [Api-Begin]
41 #include "./asmjit_apibegin.h"
42 
43 namespace PLMD {
44 namespace asmjit {
45 
46 //! \addtogroup asmjit_base
47 //! \{
48 
49 // ============================================================================
50 // [Forward Declarations]
51 // ============================================================================
52 
53 class ConstPool;
54 
55 // ============================================================================
56 // [asmjit::CodeEmitter]
57 // ============================================================================
58 
59 //! Provides a base foundation to emit code - specialized by \ref Assembler and
60 //! \ref CodeBuilder.
61 class ASMJIT_VIRTAPI CodeEmitter {
62 public:
63   //! CodeEmitter type.
ASMJIT_ENUM(Type)64   ASMJIT_ENUM(Type) {
65     kTypeNone       = 0,
66     kTypeAssembler  = 1,
67     kTypeBuilder    = 2,
68     kTypeCompiler   = 3,
69     kTypeCount      = 4
70   };
71 
72   //! CodeEmitter hints - global settings that affect machine-code generation.
ASMJIT_ENUM(Hints)73   ASMJIT_ENUM(Hints) {
74     //! Emit optimized code-alignment sequences.
75     //!
76     //! Default `true`.
77     //!
78     //! X86/X64 Specific
79     //! ----------------
80     //!
81     //! Default align sequence used by X86/X64 architecture is one-byte (0x90)
82     //! opcode that is often shown by disassemblers as nop. However there are
83     //! more optimized align sequences for 2-11 bytes that may execute faster.
84     //! If this feature is enabled AsmJit will generate specialized sequences
85     //! for alignment between 2 to 11 bytes.
86     kHintOptimizedAlign = 0x00000001U,
87 
88     //! Emit jump-prediction hints.
89     //!
90     //! Default `false`.
91     //!
92     //! X86/X64 Specific
93     //! ----------------
94     //!
95     //! Jump prediction is usually based on the direction of the jump. If the
96     //! jump is backward it is usually predicted as taken; and if the jump is
97     //! forward it is usually predicted as not-taken. The reason is that loops
98     //! generally use backward jumps and conditions usually use forward jumps.
99     //! However this behavior can be overridden by using instruction prefixes.
100     //! If this option is enabled these hints will be emitted.
101     //!
102     //! This feature is disabled by default, because the only processor that
103     //! used to take into consideration prediction hints was P4. Newer processors
104     //! implement heuristics for branch prediction that ignores any static hints.
105     kHintPredictedJumps = 0x00000002U
106   };
107 
108   //! CodeEmitter options that are merged with instruction options.
ASMJIT_ENUM(Options)109   ASMJIT_ENUM(Options) {
110     //! Reserved, used to check for errors in `Assembler::_emit()`. In addition,
111     //! if an emitter is in error state it will have `kOptionMaybeFailureCase`
112     //! set
113     kOptionMaybeFailureCase = 0x00000001U,
114 
115     //! Perform a strict validation before the instruction is emitted.
116     kOptionStrictValidation = 0x00000002U,
117 
118     //! Logging is enabled and `CodeHolder::getLogger()` should return a valid
119     //! \ref Logger pointer.
120     kOptionLoggingEnabled   = 0x00000004U,
121 
122     //! Mask of all internal options that are not used to represent instruction
123     //! options, but are used to instrument Assembler and CodeBuilder. These
124     //! options are internal and should not be used outside of AsmJit itself.
125     //!
126     //! NOTE: Reserved options should never appear in `CBInst` options.
127     kOptionReservedMask = 0x00000007U,
128 
129     //! Used only by Assembler to mark `_op4` and `_op5` are used.
130     kOptionOp4Op5Used = 0x00000008U,
131 
132     //! Prevents following a jump during compilation (CodeCompiler).
133     kOptionUnfollow = 0x00000010U,
134 
135     //! Overwrite the destination operand (CodeCompiler).
136     //!
137     //! Hint that is important for register liveness analysis. It tells the
138     //! compiler that the destination operand will be overwritten now or by
139     //! adjacent instructions. CodeCompiler knows when a register is completely
140     //! overwritten by a single instruction, for example you don't have to
141     //! mark "movaps" or "pxor x, x", however, if a pair of instructions is
142     //! used and the first of them doesn't completely overwrite the content
143     //! of the destination, CodeCompiler fails to mark that register as dead.
144     //!
145     //! X86/X64 Specific
146     //! ----------------
147     //!
148     //!   - All instructions that always overwrite at least the size of the
149     //!     register the virtual-register uses , for example "mov", "movq",
150     //!     "movaps" don't need the overwrite option to be used - conversion,
151     //!     shuffle, and other miscellaneous instructions included.
152     //!
153     //!   - All instructions that clear the destination register if all operands
154     //!     are the same, for example "xor x, x", "pcmpeqb x x", etc...
155     //!
156     //!   - Consecutive instructions that partially overwrite the variable until
157     //!     there is no old content require the `overwrite()` to be used. Some
158     //!     examples (not always the best use cases thought):
159     //!
160     //!     - `movlps xmm0, ?` followed by `movhps xmm0, ?` and vice versa
161     //!     - `movlpd xmm0, ?` followed by `movhpd xmm0, ?` and vice versa
162     //!     - `mov al, ?` followed by `and ax, 0xFF`
163     //!     - `mov al, ?` followed by `mov ah, al`
164     //!     - `pinsrq xmm0, ?, 0` followed by `pinsrq xmm0, ?, 1`
165     //!
166     //!   - If allocated variable is used temporarily for scalar operations. For
167     //!     example if you allocate a full vector like `X86Compiler::newXmm()`
168     //!     and then use that vector for scalar operations you should use
169     //!     `overwrite()` directive:
170     //!
171     //!     - `sqrtss x, y` - only LO element of `x` is changed, if you don't use
172     //!       HI elements, use `X86Compiler.overwrite().sqrtss(x, y)`.
173     kOptionOverwrite = 0x00000020U
174   };
175 
176   // --------------------------------------------------------------------------
177   // [Construction / Destruction]
178   // --------------------------------------------------------------------------
179 
180   ASMJIT_API CodeEmitter(uint32_t type) noexcept;
181   ASMJIT_API virtual ~CodeEmitter() noexcept;
182 
183   // --------------------------------------------------------------------------
184   // [Events]
185   // --------------------------------------------------------------------------
186 
187   //! Called after the \ref CodeEmitter was attached to the \ref CodeHolder.
188   virtual Error onAttach(CodeHolder* code) noexcept = 0;
189   //! Called after the \ref CodeEmitter was detached from the \ref CodeHolder.
190   virtual Error onDetach(CodeHolder* code) noexcept = 0;
191 
192   // --------------------------------------------------------------------------
193   // [Code-Generation]
194   // --------------------------------------------------------------------------
195 
196   //! Emit instruction having max 4 operands.
197   virtual Error _emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) = 0;
198   //! Emit instruction having max 6 operands.
199   virtual Error _emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, const Operand_& o5) = 0;
200   //! Emit instruction having operands stored in array.
201   virtual Error _emitOpArray(uint32_t instId, const Operand_* opArray, size_t opCount);
202 
203   //! Create a new label.
204   virtual Label newLabel() = 0;
205   //! Create a new named label.
206   virtual Label newNamedLabel(
207     const char* name,
208     size_t nameLength = Globals::kInvalidIndex,
209     uint32_t type = Label::kTypeGlobal,
210     uint32_t parentId = 0) = 0;
211 
212   //! Get a label by name.
213   //!
214   //! Returns invalid Label in case that the name is invalid or label was not found.
215   //!
216   //! NOTE: This function doesn't trigger ErrorHandler in case the name is
217   //! invalid or no such label exist. You must always check the validity of the
218   //! \ref Label returned.
219   ASMJIT_API Label getLabelByName(
220     const char* name,
221     size_t nameLength = Globals::kInvalidIndex,
222     uint32_t parentId = 0) noexcept;
223 
224   //! Bind the `label` to the current position of the current section.
225   //!
226   //! NOTE: Attempt to bind the same label multiple times will return an error.
227   virtual Error bind(const Label& label) = 0;
228 
229   //! Align to the `alignment` specified.
230   //!
231   //! The sequence that is used to fill the gap between the aligned location
232   //! and the current location depends on the align `mode`, see \ref AlignMode.
233   virtual Error align(uint32_t mode, uint32_t alignment) = 0;
234 
235   //! Embed raw data into the code-buffer.
236   virtual Error embed(const void* data, uint32_t size) = 0;
237 
238   //! Embed absolute label address as data (4 or 8 bytes).
239   virtual Error embedLabel(const Label& label) = 0;
240 
241   //! Embed a constant pool into the code-buffer in the following steps:
242   //!   1. Align by using kAlignData to the minimum `pool` alignment.
243   //!   2. Bind `label` so it's bound to an aligned location.
244   //!   3. Emit constant pool data.
245   virtual Error embedConstPool(const Label& label, const ConstPool& pool) = 0;
246 
247   //! Emit a comment string `s` with an optional `len` parameter.
248   virtual Error comment(const char* s, size_t len = Globals::kInvalidIndex) = 0;
249 
250   // --------------------------------------------------------------------------
251   // [Code-Generation Status]
252   // --------------------------------------------------------------------------
253 
254   //! Get if the CodeEmitter is initialized (i.e. attached to a \ref CodeHolder).
isInitialized()255   ASMJIT_INLINE bool isInitialized() const noexcept { return _code != nullptr; }
256 
257   ASMJIT_API virtual Error finalize();
258 
259   // --------------------------------------------------------------------------
260   // [Code Information]
261   // --------------------------------------------------------------------------
262 
263   //! Get information about the code, see \ref CodeInfo.
getCodeInfo()264   ASMJIT_INLINE const CodeInfo& getCodeInfo() const noexcept { return _codeInfo; }
265   //! Get \ref CodeHolder this CodeEmitter is attached to.
getCode()266   ASMJIT_INLINE CodeHolder* getCode() const noexcept { return _code; }
267 
268   //! Get information about the architecture, see \ref ArchInfo.
getArchInfo()269   ASMJIT_INLINE const ArchInfo& getArchInfo() const noexcept { return _codeInfo.getArchInfo(); }
270 
271   //! Get if the target architecture is 32-bit.
is32Bit()272   ASMJIT_INLINE bool is32Bit() const noexcept { return getArchInfo().is32Bit(); }
273   //! Get if the target architecture is 64-bit.
is64Bit()274   ASMJIT_INLINE bool is64Bit() const noexcept { return getArchInfo().is64Bit(); }
275 
276   //! Get the target architecture type.
getArchType()277   ASMJIT_INLINE uint32_t getArchType() const noexcept { return getArchInfo().getType(); }
278   //! Get the target architecture sub-type.
getArchSubType()279   ASMJIT_INLINE uint32_t getArchSubType() const noexcept { return getArchInfo().getSubType(); }
280   //! Get the target architecture's GP register size (4 or 8 bytes).
getGpSize()281   ASMJIT_INLINE uint32_t getGpSize() const noexcept { return getArchInfo().getGpSize(); }
282   //! Get the number of target GP registers.
getGpCount()283   ASMJIT_INLINE uint32_t getGpCount() const noexcept { return getArchInfo().getGpCount(); }
284 
285   // --------------------------------------------------------------------------
286   // [Code-Emitter Type]
287   // --------------------------------------------------------------------------
288 
289   //! Get the type of this CodeEmitter, see \ref Type.
getType()290   ASMJIT_INLINE uint32_t getType() const noexcept { return _type; }
291 
isAssembler()292   ASMJIT_INLINE bool isAssembler() const noexcept { return _type == kTypeAssembler; }
isCodeBuilder()293   ASMJIT_INLINE bool isCodeBuilder() const noexcept { return _type == kTypeBuilder; }
isCodeCompiler()294   ASMJIT_INLINE bool isCodeCompiler() const noexcept { return _type == kTypeCompiler; }
295 
296   // --------------------------------------------------------------------------
297   // [Global Information]
298   // --------------------------------------------------------------------------
299 
300   //! Get global hints.
getGlobalHints()301   ASMJIT_INLINE uint32_t getGlobalHints() const noexcept { return _globalHints; }
302 
303   //! Get global options.
304   //!
305   //! Global options are merged with instruction options before the instruction
306   //! is encoded. These options have some bits reserved that are used for error
307   //! checking, logging, and strict validation. Other options are globals that
308   //! affect each instruction, for example if VEX3 is set globally, it will all
309   //! instructions, even those that don't have such option set.
getGlobalOptions()310   ASMJIT_INLINE uint32_t getGlobalOptions() const noexcept { return _globalOptions; }
311 
312   // --------------------------------------------------------------------------
313   // [Error Handling]
314   // --------------------------------------------------------------------------
315 
316   //! Get if the object is in error state.
317   //!
318   //! Error state means that it does not consume anything unless the error
319   //! state is reset by calling `resetLastError()`. Use `getLastError()` to
320   //! get the last error that put the object into the error state.
isInErrorState()321   ASMJIT_INLINE bool isInErrorState() const noexcept { return _lastError != kErrorOk; }
322 
323   //! Get the last error code.
getLastError()324   ASMJIT_INLINE Error getLastError() const noexcept { return _lastError; }
325   //! Set the last error code and propagate it through the error handler.
326   ASMJIT_API Error setLastError(Error error, const char* message = nullptr);
327   //! Clear the last error code and return `kErrorOk`.
resetLastError()328   ASMJIT_INLINE Error resetLastError() noexcept { return setLastError(kErrorOk); }
329 
330   // --------------------------------------------------------------------------
331   // [Accessors That Affect the Next Instruction]
332   // --------------------------------------------------------------------------
333 
334   //! Get options of the next instruction.
getOptions()335   ASMJIT_INLINE uint32_t getOptions() const noexcept { return _options; }
336   //! Set options of the next instruction.
setOptions(uint32_t options)337   ASMJIT_INLINE void setOptions(uint32_t options) noexcept { _options = options; }
338   //! Add options of the next instruction.
addOptions(uint32_t options)339   ASMJIT_INLINE void addOptions(uint32_t options) noexcept { _options |= options; }
340   //! Reset options of the next instruction.
resetOptions()341   ASMJIT_INLINE void resetOptions() noexcept { _options = 0; }
342 
343   //! Get if the extra register operand is valid.
hasExtraReg()344   ASMJIT_INLINE bool hasExtraReg() const noexcept { return _extraReg.isValid(); }
345   //! Get an extra operand that will be used by the next instruction (architecture specific).
getExtraReg()346   ASMJIT_INLINE const RegOnly& getExtraReg() const noexcept { return _extraReg; }
347   //! Set an extra operand that will be used by the next instruction (architecture specific).
setExtraReg(const Reg & reg)348   ASMJIT_INLINE void setExtraReg(const Reg& reg) noexcept { _extraReg.init(reg); }
349   //! Set an extra operand that will be used by the next instruction (architecture specific).
setExtraReg(const RegOnly & reg)350   ASMJIT_INLINE void setExtraReg(const RegOnly& reg) noexcept { _extraReg.init(reg); }
351   //! Reset an extra operand that will be used by the next instruction (architecture specific).
resetExtraReg()352   ASMJIT_INLINE void resetExtraReg() noexcept { _extraReg.reset(); }
353 
354   //! Get annotation of the next instruction.
getInlineComment()355   ASMJIT_INLINE const char* getInlineComment() const noexcept { return _inlineComment; }
356   //! Set annotation of the next instruction.
357   //!
358   //! NOTE: This string is set back to null by `_emit()`, but until that it has
359   //! to remain valid as `CodeEmitter` is not required to make a copy of it (and
360   //! it would be slow to do that for each instruction).
setInlineComment(const char * s)361   ASMJIT_INLINE void setInlineComment(const char* s) noexcept { _inlineComment = s; }
362   //! Reset annotation of the next instruction to null.
resetInlineComment()363   ASMJIT_INLINE void resetInlineComment() noexcept { _inlineComment = nullptr; }
364 
365   // --------------------------------------------------------------------------
366   // [Helpers]
367   // --------------------------------------------------------------------------
368 
369   //! Get if the `label` is valid (i.e. registered).
isLabelValid(const Label & label)370   ASMJIT_INLINE bool isLabelValid(const Label& label) const noexcept {
371     return isLabelValid(label.getId());
372   }
373 
374   //! Get if the label `id` is valid (i.e. registered).
375   ASMJIT_API bool isLabelValid(uint32_t id) const noexcept;
376 
377   //! Emit a formatted string `fmt`.
378   ASMJIT_API Error commentf(const char* fmt, ...);
379   //! Emit a formatted string `fmt` (va_list version).
380   ASMJIT_API Error commentv(const char* fmt, va_list ap);
381 
382   // --------------------------------------------------------------------------
383   // [Emit]
384   // --------------------------------------------------------------------------
385 
386   // NOTE: These `emit()` helpers are designed to address a code-bloat generated
387   // by C++ compilers to call a function having many arguments. Each parameter to
388   // `_emit()` requires code to pass it, which means that if we default to 4
389   // operand parameters in `_emit()` and instId the C++ compiler would have to
390   // generate a virtual function call having 5 parameters, which is quite a lot.
391   // Since by default asm instructions have 2 to 3 operands it's better to
392   // introduce helpers that pass those and fill all the remaining with `_none`.
393 
394   //! Emit an instruction.
395   ASMJIT_API Error emit(uint32_t instId);
396   //! \overload
397   ASMJIT_API Error emit(uint32_t instId, const Operand_& o0);
398   //! \overload
399   ASMJIT_API Error emit(uint32_t instId, const Operand_& o0, const Operand_& o1);
400   //! \overload
401   ASMJIT_API Error emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2);
402   //! \overload
403   ASMJIT_API Error emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3);
404   //! \overload
405   ASMJIT_API Error emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4);
406   //! \overload
407   ASMJIT_API Error emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, const Operand_& o5);
408 
409   //! Emit an instruction that has a 32-bit signed immediate operand.
410   ASMJIT_API Error emit(uint32_t instId, int o0);
411   //! \overload
412   ASMJIT_API Error emit(uint32_t instId, const Operand_& o0, int o1);
413   //! \overload
414   ASMJIT_API Error emit(uint32_t instId, const Operand_& o0, const Operand_& o1, int o2);
415   //! \overload
416   ASMJIT_API Error emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, int o3);
417   //! \overload
418   ASMJIT_API Error emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, int o4);
419   //! \overload
420   ASMJIT_API Error emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, int o5);
421 
422   //! Emit an instruction that has a 64-bit signed immediate operand.
423   ASMJIT_API Error emit(uint32_t instId, int64_t o0);
424   //! \overload
425   ASMJIT_API Error emit(uint32_t instId, const Operand_& o0, int64_t o1);
426   //! \overload
427   ASMJIT_API Error emit(uint32_t instId, const Operand_& o0, const Operand_& o1, int64_t o2);
428   //! \overload
429   ASMJIT_API Error emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, int64_t o3);
430   //! \overload
431   ASMJIT_API Error emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, int64_t o4);
432   //! \overload
433   ASMJIT_API Error emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, int64_t o5);
434 
435   //! \overload
emit(uint32_t instId,unsigned int o0)436   ASMJIT_INLINE Error emit(uint32_t instId, unsigned int o0) {
437     return emit(instId, static_cast<int64_t>(o0));
438   }
439   //! \overload
emit(uint32_t instId,const Operand_ & o0,unsigned int o1)440   ASMJIT_INLINE Error emit(uint32_t instId, const Operand_& o0, unsigned int o1) {
441     return emit(instId, o0, static_cast<int64_t>(o1));
442   }
443   //! \overload
emit(uint32_t instId,const Operand_ & o0,const Operand_ & o1,unsigned int o2)444   ASMJIT_INLINE Error emit(uint32_t instId, const Operand_& o0, const Operand_& o1, unsigned int o2) {
445     return emit(instId, o0, o1, static_cast<int64_t>(o2));
446   }
447   //! \overload
emit(uint32_t instId,const Operand_ & o0,const Operand_ & o1,const Operand_ & o2,unsigned int o3)448   ASMJIT_INLINE Error emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, unsigned int o3) {
449     return emit(instId, o0, o1, o2, static_cast<int64_t>(o3));
450   }
451   //! \overload
emit(uint32_t instId,const Operand_ & o0,const Operand_ & o1,const Operand_ & o2,const Operand_ & o3,unsigned int o4)452   ASMJIT_INLINE Error emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, unsigned int o4) {
453     return emit(instId, o0, o1, o2, o3, static_cast<int64_t>(o4));
454   }
455   //! \overload
emit(uint32_t instId,const Operand_ & o0,const Operand_ & o1,const Operand_ & o2,const Operand_ & o3,const Operand_ & o4,unsigned int o5)456   ASMJIT_INLINE Error emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, unsigned int o5) {
457     return emit(instId, o0, o1, o2, o3, o4, static_cast<int64_t>(o5));
458   }
459 
460   //! \overload
emit(uint32_t instId,uint64_t o0)461   ASMJIT_INLINE Error emit(uint32_t instId, uint64_t o0) {
462     return emit(instId, static_cast<int64_t>(o0));
463   }
464   //! \overload
emit(uint32_t instId,const Operand_ & o0,uint64_t o1)465   ASMJIT_INLINE Error emit(uint32_t instId, const Operand_& o0, uint64_t o1) {
466     return emit(instId, o0, static_cast<int64_t>(o1));
467   }
468   //! \overload
emit(uint32_t instId,const Operand_ & o0,const Operand_ & o1,uint64_t o2)469   ASMJIT_INLINE Error emit(uint32_t instId, const Operand_& o0, const Operand_& o1, uint64_t o2) {
470     return emit(instId, o0, o1, static_cast<int64_t>(o2));
471   }
472   //! \overload
emit(uint32_t instId,const Operand_ & o0,const Operand_ & o1,const Operand_ & o2,uint64_t o3)473   ASMJIT_INLINE Error emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, uint64_t o3) {
474     return emit(instId, o0, o1, o2, static_cast<int64_t>(o3));
475   }
476   //! \overload
emit(uint32_t instId,const Operand_ & o0,const Operand_ & o1,const Operand_ & o2,const Operand_ & o3,uint64_t o4)477   ASMJIT_INLINE Error emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, uint64_t o4) {
478     return emit(instId, o0, o1, o2, o3, static_cast<int64_t>(o4));
479   }
480   //! \overload
emit(uint32_t instId,const Operand_ & o0,const Operand_ & o1,const Operand_ & o2,const Operand_ & o3,const Operand_ & o4,uint64_t o5)481   ASMJIT_INLINE Error emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, uint64_t o5) {
482     return emit(instId, o0, o1, o2, o3, o4, static_cast<int64_t>(o5));
483   }
484 
emitOpArray(uint32_t instId,const Operand_ * opArray,size_t opCount)485   ASMJIT_INLINE Error emitOpArray(uint32_t instId, const Operand_* opArray, size_t opCount) {
486     return _emitOpArray(instId, opArray, opCount);
487   }
488 
489   // --------------------------------------------------------------------------
490   // [Members]
491   // --------------------------------------------------------------------------
492 
493   CodeInfo _codeInfo;                    //!< Basic information about the code (matches CodeHolder::_codeInfo).
494   CodeHolder* _code;                     //!< CodeHolder the CodeEmitter is attached to.
495   CodeEmitter* _nextEmitter;             //!< Linked list of `CodeEmitter`s attached to the same \ref CodeHolder.
496 
497   uint8_t _type;                         //!< See CodeEmitter::Type.
498   uint8_t _destroyed;                    //!< Set by ~CodeEmitter() before calling `_code->detach()`.
499   uint8_t _finalized;                    //!< True if the CodeEmitter is finalized (CodeBuilder & CodeCompiler).
500   uint8_t _reserved;                     //!< \internal
501   Error _lastError;                      //!< Last error code.
502 
503   uint32_t _privateData;                 //!< Internal private data used freely by any CodeEmitter.
504   uint32_t _globalHints;                 //!< Global hints, always in sync with CodeHolder.
505   uint32_t _globalOptions;               //!< Global options, combined with `_options` before used by each instruction.
506 
507   uint32_t _options;                     //!< Used to pass instruction options        (affects the next instruction).
508   RegOnly _extraReg;                     //!< Extra register (op-mask {k} on AVX-512) (affects the next instruction).
509   const char* _inlineComment;            //!< Inline comment of the next instruction  (affects the next instruction).
510 
511   Operand_ _none;                        //!< Used to pass unused operands to `_emit()` instead of passing null.
512   Reg _nativeGpReg;                      //!< Native GP register with zero id.
513   const Reg* _nativeGpArray;             //!< Array of native registers indexed from zero.
514 };
515 
516 //! \}
517 
518 } // asmjit namespace
519 } // namespace PLMD
520 
521 // [Api-End]
522 #include "./asmjit_apiend.h"
523 
524 // [Guard]
525 #endif // _ASMJIT_BASE_CODEEMITTER_H
526 #pragma GCC diagnostic pop
527 #endif // __PLUMED_HAS_ASMJIT
528 #endif
529