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