Line data Source code
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.
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.
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.
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).
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.
264 : ASMJIT_INLINE const CodeInfo& getCodeInfo() const noexcept { return _codeInfo; }
265 : //! Get \ref CodeHolder this CodeEmitter is attached to.
266 0 : ASMJIT_INLINE CodeHolder* getCode() const noexcept { return _code; }
267 :
268 : //! Get information about the architecture, see \ref ArchInfo.
269 : ASMJIT_INLINE const ArchInfo& getArchInfo() const noexcept { return _codeInfo.getArchInfo(); }
270 :
271 : //! Get if the target architecture is 32-bit.
272 : ASMJIT_INLINE bool is32Bit() const noexcept { return getArchInfo().is32Bit(); }
273 : //! Get if the target architecture is 64-bit.
274 : ASMJIT_INLINE bool is64Bit() const noexcept { return getArchInfo().is64Bit(); }
275 :
276 : //! Get the target architecture type.
277 : ASMJIT_INLINE uint32_t getArchType() const noexcept { return getArchInfo().getType(); }
278 : //! Get the target architecture sub-type.
279 : ASMJIT_INLINE uint32_t getArchSubType() const noexcept { return getArchInfo().getSubType(); }
280 : //! Get the target architecture's GP register size (4 or 8 bytes).
281 : ASMJIT_INLINE uint32_t getGpSize() const noexcept { return getArchInfo().getGpSize(); }
282 : //! Get the number of target GP registers.
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.
290 7776 : ASMJIT_INLINE uint32_t getType() const noexcept { return _type; }
291 :
292 : ASMJIT_INLINE bool isAssembler() const noexcept { return _type == kTypeAssembler; }
293 : ASMJIT_INLINE bool isCodeBuilder() const noexcept { return _type == kTypeBuilder; }
294 : ASMJIT_INLINE bool isCodeCompiler() const noexcept { return _type == kTypeCompiler; }
295 :
296 : // --------------------------------------------------------------------------
297 : // [Global Information]
298 : // --------------------------------------------------------------------------
299 :
300 : //! Get global hints.
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.
310 98760 : 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.
321 : ASMJIT_INLINE bool isInErrorState() const noexcept { return _lastError != kErrorOk; }
322 :
323 : //! Get the last error code.
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`.
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.
335 94872 : ASMJIT_INLINE uint32_t getOptions() const noexcept { return _options; }
336 : //! Set options of the next instruction.
337 48254 : ASMJIT_INLINE void setOptions(uint32_t options) noexcept { _options = options; }
338 : //! Add options of the next instruction.
339 : ASMJIT_INLINE void addOptions(uint32_t options) noexcept { _options |= options; }
340 : //! Reset options of the next instruction.
341 94872 : ASMJIT_INLINE void resetOptions() noexcept { _options = 0; }
342 :
343 : //! Get if the extra register operand is valid.
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).
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).
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).
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).
352 : ASMJIT_INLINE void resetExtraReg() noexcept { _extraReg.reset(); }
353 :
354 : //! Get annotation of the next instruction.
355 46618 : 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).
361 65114 : ASMJIT_INLINE void setInlineComment(const char* s) noexcept { _inlineComment = s; }
362 : //! Reset annotation of the next instruction to null.
363 98760 : ASMJIT_INLINE void resetInlineComment() noexcept { _inlineComment = nullptr; }
364 :
365 : // --------------------------------------------------------------------------
366 : // [Helpers]
367 : // --------------------------------------------------------------------------
368 :
369 : //! Get if the `label` is valid (i.e. registered).
370 : ASMJIT_INLINE bool isLabelValid(const Label& label) const noexcept {
371 0 : 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
436 : ASMJIT_INLINE Error emit(uint32_t instId, unsigned int o0) {
437 : return emit(instId, static_cast<int64_t>(o0));
438 : }
439 : //! \overload
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
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
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
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
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
461 : ASMJIT_INLINE Error emit(uint32_t instId, uint64_t o0) {
462 : return emit(instId, static_cast<int64_t>(o0));
463 : }
464 : //! \overload
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
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
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
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
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 :
485 : ASMJIT_INLINE Error emitOpArray(uint32_t instId, const Operand_* opArray, size_t opCount) {
486 48254 : 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
|