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_codebuilder_h
21 : #define __PLUMED_asmjit_codebuilder_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_CODEBUILDER_H
33 : #define _ASMJIT_BASE_CODEBUILDER_H
34 :
35 : #include "./asmjit_build.h"
36 : #if !defined(ASMJIT_DISABLE_BUILDER)
37 :
38 : // [Dependencies]
39 : #include "./assembler.h"
40 : #include "./codeholder.h"
41 : #include "./constpool.h"
42 : #include "./inst.h"
43 : #include "./operand.h"
44 : #include "./utils.h"
45 : #include "./zone.h"
46 :
47 : // [Api-Begin]
48 : #include "./asmjit_apibegin.h"
49 :
50 : namespace PLMD {
51 : namespace asmjit {
52 :
53 : // ============================================================================
54 : // [Forward Declarations]
55 : // ============================================================================
56 :
57 : class CBNode;
58 : class CBPass;
59 :
60 : class CBAlign;
61 : class CBComment;
62 : class CBConstPool;
63 : class CBData;
64 : class CBInst;
65 : class CBJump;
66 : class CBLabel;
67 : class CBLabelData;
68 : class CBSentinel;
69 :
70 : //! \addtogroup asmjit_base
71 : //! \{
72 :
73 : // ============================================================================
74 : // [asmjit::CodeBuilder]
75 : // ============================================================================
76 :
77 : class ASMJIT_VIRTAPI CodeBuilder : public CodeEmitter {
78 : public:
79 : ASMJIT_NONCOPYABLE(CodeBuilder)
80 : typedef CodeEmitter Base;
81 :
82 : // --------------------------------------------------------------------------
83 : // [Construction / Destruction]
84 : // --------------------------------------------------------------------------
85 :
86 : //! Create a new `CodeBuilder` instance.
87 : ASMJIT_API CodeBuilder() noexcept;
88 : //! Destroy the `CodeBuilder` instance.
89 : ASMJIT_API virtual ~CodeBuilder() noexcept;
90 :
91 : // --------------------------------------------------------------------------
92 : // [Events]
93 : // --------------------------------------------------------------------------
94 :
95 : ASMJIT_API virtual Error onAttach(CodeHolder* code) noexcept override;
96 : ASMJIT_API virtual Error onDetach(CodeHolder* code) noexcept override;
97 :
98 : // --------------------------------------------------------------------------
99 : // [Accessors]
100 : // --------------------------------------------------------------------------
101 :
102 : //! Get a vector of CBPass objects that will be executed by `process()`.
103 : ASMJIT_INLINE const ZoneVector<CBPass*>& getPasses() const noexcept { return _cbPasses; }
104 :
105 : //! Get a vector of CBLabel nodes.
106 : //!
107 : //! NOTE: If a label of some index is not associated with `CodeBuilder` it
108 : //! would be null, so always check for nulls if you iterate over the vector.
109 : ASMJIT_INLINE const ZoneVector<CBLabel*>& getLabels() const noexcept { return _cbLabels; }
110 :
111 : //! Get the first node.
112 3888 : ASMJIT_INLINE CBNode* getFirstNode() const noexcept { return _firstNode; }
113 : //! Get the last node.
114 : ASMJIT_INLINE CBNode* getLastNode() const noexcept { return _lastNode; }
115 :
116 : // --------------------------------------------------------------------------
117 : // [Node-Management]
118 : // --------------------------------------------------------------------------
119 :
120 : //! \internal
121 : template<typename T>
122 3888 : ASMJIT_INLINE T* newNodeT() noexcept { return new(_cbHeap.alloc(sizeof(T))) T(this); }
123 :
124 : //! \internal
125 : template<typename T, typename P0>
126 0 : ASMJIT_INLINE T* newNodeT(P0 p0) noexcept { return new(_cbHeap.alloc(sizeof(T))) T(this, p0); }
127 :
128 : //! \internal
129 : template<typename T, typename P0, typename P1>
130 1944 : ASMJIT_INLINE T* newNodeT(P0 p0, P1 p1) noexcept { return new(_cbHeap.alloc(sizeof(T))) T(this, p0, p1); }
131 :
132 : //! \internal
133 : template<typename T, typename P0, typename P1, typename P2>
134 0 : ASMJIT_INLINE T* newNodeT(P0 p0, P1 p1, P2 p2) noexcept { return new(_cbHeap.alloc(sizeof(T))) T(this, p0, p1, p2); }
135 :
136 : ASMJIT_API Error registerLabelNode(CBLabel* node) noexcept;
137 : //! Get `CBLabel` by `id`.
138 : ASMJIT_API Error getCBLabel(CBLabel** pOut, uint32_t id) noexcept;
139 : //! Get `CBLabel` by `label`.
140 0 : ASMJIT_INLINE Error getCBLabel(CBLabel** pOut, const Label& label) noexcept { return getCBLabel(pOut, label.getId()); }
141 :
142 : //! Create a new \ref CBLabel node.
143 : ASMJIT_API CBLabel* newLabelNode() noexcept;
144 : //! Create a new \ref CBAlign node.
145 : ASMJIT_API CBAlign* newAlignNode(uint32_t mode, uint32_t alignment) noexcept;
146 : //! Create a new \ref CBData node.
147 : ASMJIT_API CBData* newDataNode(const void* data, uint32_t size) noexcept;
148 : //! Create a new \ref CBConstPool node.
149 : ASMJIT_API CBConstPool* newConstPool() noexcept;
150 : //! Create a new \ref CBComment node.
151 : ASMJIT_API CBComment* newCommentNode(const char* s, size_t len) noexcept;
152 :
153 : // --------------------------------------------------------------------------
154 : // [Code-Emitter]
155 : // --------------------------------------------------------------------------
156 :
157 : ASMJIT_API virtual Label newLabel() override;
158 : ASMJIT_API virtual Label newNamedLabel(const char* name, size_t nameLength = Globals::kInvalidIndex, uint32_t type = Label::kTypeGlobal, uint32_t parentId = kInvalidValue) override;
159 : ASMJIT_API virtual Error bind(const Label& label) override;
160 : ASMJIT_API virtual Error align(uint32_t mode, uint32_t alignment) override;
161 : ASMJIT_API virtual Error embed(const void* data, uint32_t size) override;
162 : ASMJIT_API virtual Error embedLabel(const Label& label) override;
163 : ASMJIT_API virtual Error embedConstPool(const Label& label, const ConstPool& pool) override;
164 : ASMJIT_API virtual Error comment(const char* s, size_t len = Globals::kInvalidIndex) override;
165 :
166 : // --------------------------------------------------------------------------
167 : // [Node-Management]
168 : // --------------------------------------------------------------------------
169 :
170 : //! Add `node` after the current and set current to `node`.
171 : ASMJIT_API CBNode* addNode(CBNode* node) noexcept;
172 : //! Insert `node` after `ref`.
173 : ASMJIT_API CBNode* addAfter(CBNode* node, CBNode* ref) noexcept;
174 : //! Insert `node` before `ref`.
175 : ASMJIT_API CBNode* addBefore(CBNode* node, CBNode* ref) noexcept;
176 : //! Remove `node`.
177 : ASMJIT_API CBNode* removeNode(CBNode* node) noexcept;
178 : //! Remove multiple nodes.
179 : ASMJIT_API void removeNodes(CBNode* first, CBNode* last) noexcept;
180 :
181 : //! Get current node.
182 : //!
183 : //! \note If this method returns null it means that nothing has been
184 : //! emitted yet.
185 1944 : ASMJIT_INLINE CBNode* getCursor() const noexcept { return _cursor; }
186 : //! Set the current node without returning the previous node.
187 9412 : ASMJIT_INLINE void _setCursor(CBNode* node) noexcept { _cursor = node; }
188 : //! Set the current node to `node` and return the previous one.
189 : ASMJIT_API CBNode* setCursor(CBNode* node) noexcept;
190 :
191 : // --------------------------------------------------------------------------
192 : // [Passes]
193 : // --------------------------------------------------------------------------
194 :
195 : template<typename T>
196 1944 : ASMJIT_INLINE T* newPassT() noexcept { return new(_cbBaseZone.alloc(sizeof(T))) T(); }
197 : template<typename T, typename P0>
198 : ASMJIT_INLINE T* newPassT(P0 p0) noexcept { return new(_cbBaseZone.alloc(sizeof(T))) T(p0); }
199 : template<typename T, typename P0, typename P1>
200 : ASMJIT_INLINE T* newPassT(P0 p0, P1 p1) noexcept { return new(_cbBaseZone.alloc(sizeof(T))) T(p0, p1); }
201 :
202 : template<typename T>
203 1944 : ASMJIT_INLINE Error addPassT() noexcept { return addPass(newPassT<T>()); }
204 : template<typename T, typename P0>
205 : ASMJIT_INLINE Error addPassT(P0 p0) noexcept { return addPass(newPassT<P0>(p0)); }
206 : template<typename T, typename P0, typename P1>
207 : ASMJIT_INLINE Error addPassT(P0 p0, P1 p1) noexcept { return addPass(newPassT<P0, P1>(p0, p1)); }
208 :
209 : //! Get a `CBPass` by name.
210 : ASMJIT_API CBPass* getPassByName(const char* name) const noexcept;
211 : //! Add `pass` to the list of passes.
212 : ASMJIT_API Error addPass(CBPass* pass) noexcept;
213 : //! Remove `pass` from the list of passes and delete it.
214 : ASMJIT_API Error deletePass(CBPass* pass) noexcept;
215 :
216 : // --------------------------------------------------------------------------
217 : // [Serialization]
218 : // --------------------------------------------------------------------------
219 :
220 : ASMJIT_API virtual Error serialize(CodeEmitter* dst);
221 :
222 : // --------------------------------------------------------------------------
223 : // [Members]
224 : // --------------------------------------------------------------------------
225 :
226 : Zone _cbBaseZone; //!< Base zone used to allocate nodes and `CBPass`.
227 : Zone _cbDataZone; //!< Data zone used to allocate data and names.
228 : Zone _cbPassZone; //!< Zone passed to `CBPass::process()`.
229 : ZoneHeap _cbHeap; //!< ZoneHeap that uses `_cbBaseZone`.
230 :
231 : ZoneVector<CBPass*> _cbPasses; //!< Array of `CBPass` objects.
232 : ZoneVector<CBLabel*> _cbLabels; //!< Maps label indexes to `CBLabel` nodes.
233 :
234 : CBNode* _firstNode; //!< First node of the current section.
235 : CBNode* _lastNode; //!< Last node of the current section.
236 : CBNode* _cursor; //!< Current node (cursor).
237 :
238 : uint32_t _position; //!< Flow-id assigned to each new node.
239 : uint32_t _nodeFlags; //!< Flags assigned to each new node.
240 : };
241 :
242 : // ============================================================================
243 : // [asmjit::CBPass]
244 : // ============================================================================
245 :
246 : //! `CodeBuilder` pass used to code transformations, analysis, and lowering.
247 : class ASMJIT_VIRTAPI CBPass {
248 : public:
249 : ASMJIT_NONCOPYABLE(CBPass);
250 :
251 : // --------------------------------------------------------------------------
252 : // [Construction / Destruction]
253 : // --------------------------------------------------------------------------
254 :
255 : ASMJIT_API CBPass(const char* name) noexcept;
256 : ASMJIT_API virtual ~CBPass() noexcept;
257 :
258 : // --------------------------------------------------------------------------
259 : // [Interface]
260 : // --------------------------------------------------------------------------
261 :
262 : //! Process the code stored in CodeBuffer `cb`.
263 : //!
264 : //! This is the only function that is called by the `CodeBuilder` to process
265 : //! the code. It passes the CodeBuilder itself (`cb`) and also a zone memory
266 : //! allocator `zone`, which will be reset after the `process()` returns. The
267 : //! allocator should be used for all allocations as it's fast and everything
268 : //! it allocates will be released at once when `process()` returns.
269 : virtual Error process(Zone* zone) noexcept = 0;
270 :
271 : // --------------------------------------------------------------------------
272 : // [Accessors]
273 : // --------------------------------------------------------------------------
274 :
275 1944 : ASMJIT_INLINE const CodeBuilder* cb() const noexcept { return _cb; }
276 0 : ASMJIT_INLINE const char* getName() const noexcept { return _name; }
277 :
278 : // --------------------------------------------------------------------------
279 : // [Members]
280 : // --------------------------------------------------------------------------
281 :
282 : CodeBuilder* _cb; //!< CodeBuilder this pass is assigned to.
283 : const char* _name; //!< Name of the pass.
284 : };
285 :
286 : // ============================================================================
287 : // [asmjit::CBNode]
288 : // ============================================================================
289 :
290 : //! Node (CodeBuilder).
291 : //!
292 : //! Every node represents a building-block used by \ref CodeBuilder. It can be
293 : //! instruction, data, label, comment, directive, or any other high-level
294 : //! representation that can be transformed to the building blocks mentioned.
295 : //! Every class that inherits \ref CodeBuilder can define its own nodes that it
296 : //! can lower to basic nodes.
297 : class CBNode {
298 : public:
299 : ASMJIT_NONCOPYABLE(CBNode)
300 :
301 : // --------------------------------------------------------------------------
302 : // [Type]
303 : // --------------------------------------------------------------------------
304 :
305 : //! Type of \ref CBNode.
306 : ASMJIT_ENUM(NodeType) {
307 : kNodeNone = 0, //!< Invalid node (internal, don't use).
308 :
309 : // [CodeBuilder]
310 : kNodeInst = 1, //!< Node is \ref CBInst or \ref CBJump.
311 : kNodeData = 2, //!< Node is \ref CBData.
312 : kNodeAlign = 3, //!< Node is \ref CBAlign.
313 : kNodeLabel = 4, //!< Node is \ref CBLabel.
314 : kNodeLabelData = 5, //!< Node is \ref CBLabelData.
315 : kNodeConstPool = 6, //!< Node is \ref CBConstPool.
316 : kNodeComment = 7, //!< Node is \ref CBComment.
317 : kNodeSentinel = 8, //!< Node is \ref CBSentinel.
318 :
319 : // [CodeCompiler]
320 : kNodeFunc = 16, //!< Node is \ref CCFunc (considered as \ref CBLabel by \ref CodeBuilder).
321 : kNodeFuncExit = 17, //!< Node is \ref CCFuncRet.
322 : kNodeFuncCall = 18, //!< Node is \ref CCFuncCall.
323 : kNodePushArg = 19, //!< Node is \ref CCPushArg.
324 : kNodeHint = 20, //!< Node is \ref CCHint.
325 :
326 : // [UserDefined]
327 : kNodeUser = 32 //!< First id of a user-defined node.
328 : };
329 :
330 : // --------------------------------------------------------------------------
331 : // [Flags]
332 : // --------------------------------------------------------------------------
333 :
334 : ASMJIT_ENUM(Flags) {
335 : //! The node has been translated by the CodeCompiler.
336 : kFlagIsTranslated = 0x0001,
337 : //! If the node can be safely removed (has no effect).
338 : kFlagIsRemovable = 0x0004,
339 : //! If the node is informative only and can be safely removed.
340 : kFlagIsInformative = 0x0008,
341 :
342 : //! If the `CBInst` is a jump.
343 : kFlagIsJmp = 0x0010,
344 : //! If the `CBInst` is a conditional jump.
345 : kFlagIsJcc = 0x0020,
346 :
347 : //! If the `CBInst` is an unconditional jump or conditional jump that is
348 : //! likely to be taken.
349 : kFlagIsTaken = 0x0040,
350 :
351 : //! If the `CBNode` will return from a function.
352 : //!
353 : //! This flag is used by both `CBSentinel` and `CCFuncRet`.
354 : kFlagIsRet = 0x0080,
355 :
356 : //! Whether the instruction is special.
357 : kFlagIsSpecial = 0x0100,
358 :
359 : //! Whether the instruction is an FPU instruction.
360 : kFlagIsFp = 0x0200
361 : };
362 :
363 : // --------------------------------------------------------------------------
364 : // [Construction / Destruction]
365 : // --------------------------------------------------------------------------
366 :
367 : //! Create a new \ref CBNode - always use \ref CodeBuilder to allocate nodes.
368 56030 : ASMJIT_INLINE CBNode(CodeBuilder* cb, uint32_t type) noexcept {
369 56030 : _prev = nullptr;
370 56030 : _next = nullptr;
371 54086 : _type = static_cast<uint8_t>(type);
372 7776 : _opCount = 0;
373 56030 : _flags = static_cast<uint16_t>(cb->_nodeFlags);
374 56030 : _position = cb->_position;
375 56030 : _inlineComment = nullptr;
376 50506 : _passData = nullptr;
377 : }
378 : //! Destroy the `CBNode` instance (NEVER CALLED).
379 : ASMJIT_INLINE ~CBNode() noexcept {}
380 :
381 : // --------------------------------------------------------------------------
382 : // [Accessors]
383 : // --------------------------------------------------------------------------
384 :
385 : template<typename T>
386 : ASMJIT_INLINE T* as() noexcept { return static_cast<T*>(this); }
387 : template<typename T>
388 : ASMJIT_INLINE const T* as() const noexcept { return static_cast<const T*>(this); }
389 :
390 : //! Get previous node in the compiler stream.
391 73260 : ASMJIT_INLINE CBNode* getPrev() const noexcept { return _prev; }
392 : //! Get next node in the compiler stream.
393 144610 : ASMJIT_INLINE CBNode* getNext() const noexcept { return _next; }
394 :
395 : //! Get the node type, see \ref Type.
396 250920 : ASMJIT_INLINE uint32_t getType() const noexcept { return _type; }
397 : //! Get the node flags.
398 31106 : ASMJIT_INLINE uint32_t getFlags() const noexcept { return _flags; }
399 :
400 : //! Get whether the instruction has flag `flag`.
401 170672 : ASMJIT_INLINE bool hasFlag(uint32_t flag) const noexcept { return (static_cast<uint32_t>(_flags) & flag) != 0; }
402 : //! Set node flags to `flags`.
403 31106 : ASMJIT_INLINE void setFlags(uint32_t flags) noexcept { _flags = static_cast<uint16_t>(flags); }
404 : //! Add instruction `flags`.
405 1944 : ASMJIT_INLINE void orFlags(uint32_t flags) noexcept { _flags |= static_cast<uint16_t>(flags); }
406 : //! And instruction `flags`.
407 : ASMJIT_INLINE void andFlags(uint32_t flags) noexcept { _flags &= static_cast<uint16_t>(flags); }
408 : //! Clear instruction `flags`.
409 : ASMJIT_INLINE void andNotFlags(uint32_t flags) noexcept { _flags &= ~static_cast<uint16_t>(flags); }
410 :
411 : //! Get whether the node has been translated.
412 : ASMJIT_INLINE bool isTranslated() const noexcept { return hasFlag(kFlagIsTranslated); }
413 :
414 : //! Get whether the node is removable if it's in unreachable code block.
415 : ASMJIT_INLINE bool isRemovable() const noexcept { return hasFlag(kFlagIsRemovable); }
416 : //! Get whether the node is informative only (comment, hint).
417 : ASMJIT_INLINE bool isInformative() const noexcept { return hasFlag(kFlagIsInformative); }
418 :
419 : //! Whether the node is `CBLabel`.
420 0 : ASMJIT_INLINE bool isLabel() const noexcept { return _type == kNodeLabel; }
421 : //! Whether the `CBInst` node is an unconditional jump.
422 : ASMJIT_INLINE bool isJmp() const noexcept { return hasFlag(kFlagIsJmp); }
423 : //! Whether the `CBInst` node is a conditional jump.
424 : ASMJIT_INLINE bool isJcc() const noexcept { return hasFlag(kFlagIsJcc); }
425 : //! Whether the `CBInst` node is a conditional/unconditional jump.
426 : ASMJIT_INLINE bool isJmpOrJcc() const noexcept { return hasFlag(kFlagIsJmp | kFlagIsJcc); }
427 : //! Whether the `CBInst` node is a return.
428 : ASMJIT_INLINE bool isRet() const noexcept { return hasFlag(kFlagIsRet); }
429 :
430 : //! Get whether the node is `CBInst` and the instruction is special.
431 : ASMJIT_INLINE bool isSpecial() const noexcept { return hasFlag(kFlagIsSpecial); }
432 : //! Get whether the node is `CBInst` and the instruction uses x87-FPU.
433 : ASMJIT_INLINE bool isFp() const noexcept { return hasFlag(kFlagIsFp); }
434 :
435 0 : ASMJIT_INLINE bool hasPosition() const noexcept { return _position != 0; }
436 : //! Get flow index.
437 0 : ASMJIT_INLINE uint32_t getPosition() const noexcept { return _position; }
438 : //! Set flow index.
439 40518 : ASMJIT_INLINE void setPosition(uint32_t position) noexcept { _position = position; }
440 :
441 : //! Get if the node has an inline comment.
442 0 : ASMJIT_INLINE bool hasInlineComment() const noexcept { return _inlineComment != nullptr; }
443 : //! Get an inline comment string.
444 56030 : ASMJIT_INLINE const char* getInlineComment() const noexcept { return _inlineComment; }
445 : //! Set an inline comment string to `s`.
446 0 : ASMJIT_INLINE void setInlineComment(const char* s) noexcept { _inlineComment = s; }
447 : //! Set an inline comment string to null.
448 : ASMJIT_INLINE void resetInlineComment() noexcept { _inlineComment = nullptr; }
449 :
450 : //! Get if the node has associated work-data.
451 111834 : ASMJIT_INLINE bool hasPassData() const noexcept { return _passData != nullptr; }
452 : //! Get work-data - data used during processing & transformations.
453 : template<typename T>
454 329748 : ASMJIT_INLINE T* getPassData() const noexcept { return (T*)_passData; }
455 : //! Set work-data to `data`.
456 : template<typename T>
457 40518 : ASMJIT_INLINE void setPassData(T* data) noexcept { _passData = (void*)data; }
458 : //! Reset work-data to null.
459 : ASMJIT_INLINE void resetPassData() noexcept { _passData = nullptr; }
460 :
461 : // --------------------------------------------------------------------------
462 : // [Members]
463 : // --------------------------------------------------------------------------
464 :
465 : CBNode* _prev; //!< Previous node.
466 : CBNode* _next; //!< Next node.
467 :
468 : uint8_t _type; //!< Node type, see \ref NodeType.
469 : uint8_t _opCount; //!< Count of operands or zero.
470 : uint16_t _flags; //!< Flags, different meaning for every type of the node.
471 : uint32_t _position; //!< Flow index.
472 :
473 : const char* _inlineComment; //!< Inline comment or null if not used.
474 : void* _passData; //!< Data used exclusively by the current `CBPass`.
475 : };
476 :
477 : // ============================================================================
478 : // [asmjit::CBInst]
479 : // ============================================================================
480 :
481 : //! Instruction (CodeBuilder).
482 : //!
483 : //! Wraps an instruction with its options and operands.
484 : class CBInst : public CBNode {
485 : public:
486 : ASMJIT_NONCOPYABLE(CBInst)
487 :
488 : // --------------------------------------------------------------------------
489 : // [Construction / Destruction]
490 : // --------------------------------------------------------------------------
491 :
492 : //! Create a new `CBInst` instance.
493 : ASMJIT_INLINE CBInst(CodeBuilder* cb, uint32_t instId, uint32_t options, Operand* opArray, uint32_t opCount) noexcept
494 48254 : : CBNode(cb, kNodeInst) {
495 :
496 : orFlags(kFlagIsRemovable);
497 48254 : _instDetail.instId = static_cast<uint16_t>(instId);
498 48254 : _instDetail.options = options;
499 :
500 48254 : _opCount = static_cast<uint8_t>(opCount);
501 48254 : _opArray = opArray;
502 :
503 : _updateMemOp();
504 : }
505 :
506 : //! Destroy the `CBInst` instance (NEVER CALLED).
507 : ASMJIT_INLINE ~CBInst() noexcept {}
508 :
509 : // --------------------------------------------------------------------------
510 : // [Accessors]
511 : // --------------------------------------------------------------------------
512 :
513 0 : ASMJIT_INLINE Inst::Detail& getInstDetail() noexcept { return _instDetail; }
514 0 : ASMJIT_INLINE const Inst::Detail& getInstDetail() const noexcept { return _instDetail; }
515 :
516 : //! Get the instruction id, see \ref Inst::Id.
517 79360 : ASMJIT_INLINE uint32_t getInstId() const noexcept { return _instDetail.instId; }
518 : //! Set the instruction id to `instId`, see \ref Inst::Id.
519 : ASMJIT_INLINE void setInstId(uint32_t instId) noexcept { _instDetail.instId = instId; }
520 :
521 : //! Whether the instruction is either a jump or a conditional jump likely to be taken.
522 : ASMJIT_INLINE bool isTaken() const noexcept { return hasFlag(kFlagIsTaken); }
523 :
524 : //! Get emit options.
525 79118 : ASMJIT_INLINE uint32_t getOptions() const noexcept { return _instDetail.options; }
526 : //! Set emit options.
527 0 : ASMJIT_INLINE void setOptions(uint32_t options) noexcept { _instDetail.options = options; }
528 : //! Add emit options.
529 : ASMJIT_INLINE void addOptions(uint32_t options) noexcept { _instDetail.options |= options; }
530 : //! Mask emit options.
531 : ASMJIT_INLINE void andOptions(uint32_t options) noexcept { _instDetail.options &= options; }
532 : //! Clear emit options.
533 0 : ASMJIT_INLINE void delOptions(uint32_t options) noexcept { _instDetail.options &= ~options; }
534 :
535 : //! Get if the node has an extra register operand.
536 : ASMJIT_INLINE bool hasExtraReg() const noexcept { return _instDetail.hasExtraReg(); }
537 : //! Get extra register operand.
538 : ASMJIT_INLINE RegOnly& getExtraReg() noexcept { return _instDetail.extraReg; }
539 : //! \overload
540 : ASMJIT_INLINE const RegOnly& getExtraReg() const noexcept { return _instDetail.extraReg; }
541 : //! Set extra register operand to `reg`.
542 : ASMJIT_INLINE void setExtraReg(const Reg& reg) noexcept { _instDetail.extraReg.init(reg); }
543 : //! Set extra register operand to `reg`.
544 : ASMJIT_INLINE void setExtraReg(const RegOnly& reg) noexcept { _instDetail.extraReg.init(reg); }
545 : //! Reset extra register operand.
546 : ASMJIT_INLINE void resetExtraReg() noexcept { _instDetail.extraReg.reset(); }
547 :
548 : //! Get operands count.
549 48254 : ASMJIT_INLINE uint32_t getOpCount() const noexcept { return _opCount; }
550 : //! Get operands list.
551 112102 : ASMJIT_INLINE Operand* getOpArray() noexcept { return _opArray; }
552 : //! \overload
553 0 : ASMJIT_INLINE const Operand* getOpArray() const noexcept { return _opArray; }
554 :
555 : //! Get whether the instruction contains a memory operand.
556 40846 : ASMJIT_INLINE bool hasMemOp() const noexcept { return _memOpIndex != 0xFF; }
557 : //! Get memory operand.
558 : //!
559 : //! NOTE: Can only be called if the instruction has such operand,
560 : //! see `hasMemOp()`.
561 : ASMJIT_INLINE Mem* getMemOp() const noexcept {
562 : ASMJIT_ASSERT(hasMemOp());
563 : return static_cast<Mem*>(&_opArray[_memOpIndex]);
564 : }
565 : //! \overload
566 : template<typename T>
567 : ASMJIT_INLINE T* getMemOp() const noexcept {
568 : ASMJIT_ASSERT(hasMemOp());
569 14496 : return static_cast<T*>(&_opArray[_memOpIndex]);
570 : }
571 :
572 : //! Set memory operand index, `0xFF` means no memory operand.
573 54322 : ASMJIT_INLINE void setMemOpIndex(uint32_t index) noexcept { _memOpIndex = static_cast<uint8_t>(index); }
574 : //! Reset memory operand index to `0xFF` (no operand).
575 : ASMJIT_INLINE void resetMemOpIndex() noexcept { _memOpIndex = 0xFF; }
576 :
577 : // --------------------------------------------------------------------------
578 : // [Utils]
579 : // --------------------------------------------------------------------------
580 :
581 : ASMJIT_INLINE void _updateMemOp() noexcept {
582 : Operand* opArray = getOpArray();
583 : uint32_t opCount = getOpCount();
584 :
585 : uint32_t i;
586 118400 : for (i = 0; i < opCount; i++)
587 84642 : if (opArray[i].isMem())
588 14496 : goto Update;
589 : i = 0xFF;
590 :
591 48254 : Update:
592 : setMemOpIndex(i);
593 : }
594 :
595 : // --------------------------------------------------------------------------
596 : // [Members]
597 : // --------------------------------------------------------------------------
598 :
599 : Inst::Detail _instDetail; //!< Instruction id, options, and extra register.
600 : uint8_t _memOpIndex; //!< \internal
601 : uint8_t _reserved[7]; //!< \internal
602 : Operand* _opArray; //!< Instruction operands.
603 : };
604 :
605 : // ============================================================================
606 : // [asmjit::CBInstEx]
607 : // ============================================================================
608 :
609 : struct CBInstEx : public CBInst {
610 : Operand _op4;
611 : Operand _op5;
612 : };
613 :
614 : // ============================================================================
615 : // [asmjit::CBJump]
616 : // ============================================================================
617 :
618 : //! Asm jump (conditional or direct).
619 : //!
620 : //! Extension of `CBInst` node, which stores more information about the jump.
621 : class CBJump : public CBInst {
622 : public:
623 : ASMJIT_NONCOPYABLE(CBJump)
624 :
625 : // --------------------------------------------------------------------------
626 : // [Construction / Destruction]
627 : // --------------------------------------------------------------------------
628 :
629 : ASMJIT_INLINE CBJump(CodeBuilder* cb, uint32_t instId, uint32_t options, Operand* opArray, uint32_t opCount) noexcept
630 0 : : CBInst(cb, instId, options, opArray, opCount),
631 0 : _target(nullptr),
632 0 : _jumpNext(nullptr) {}
633 : ASMJIT_INLINE ~CBJump() noexcept {}
634 :
635 : // --------------------------------------------------------------------------
636 : // [Accessors]
637 : // --------------------------------------------------------------------------
638 :
639 0 : ASMJIT_INLINE CBLabel* getTarget() const noexcept { return _target; }
640 0 : ASMJIT_INLINE CBJump* getJumpNext() const noexcept { return _jumpNext; }
641 :
642 : // --------------------------------------------------------------------------
643 : // [Members]
644 : // --------------------------------------------------------------------------
645 :
646 : CBLabel* _target; //!< Target node.
647 : CBJump* _jumpNext; //!< Next jump to the same target in a single linked-list.
648 : };
649 :
650 : // ============================================================================
651 : // [asmjit::CBData]
652 : // ============================================================================
653 :
654 : //! Asm data (CodeBuilder).
655 : //!
656 : //! Wraps `.data` directive. The node contains data that will be placed at the
657 : //! node's position in the assembler stream. The data is considered to be RAW;
658 : //! no analysis nor byte-order conversion is performed on RAW data.
659 : class CBData : public CBNode {
660 : public:
661 : ASMJIT_NONCOPYABLE(CBData)
662 : enum { kInlineBufferSize = static_cast<int>(64 - sizeof(CBNode) - 4) };
663 :
664 : // --------------------------------------------------------------------------
665 : // [Construction / Destruction]
666 : // --------------------------------------------------------------------------
667 :
668 : //! Create a new `CBData` instance.
669 0 : ASMJIT_INLINE CBData(CodeBuilder* cb, void* data, uint32_t size) noexcept : CBNode(cb, kNodeData) {
670 0 : if (size <= kInlineBufferSize) {
671 0 : if (data) ::memcpy(_buf, data, size);
672 : }
673 : else {
674 0 : _externalPtr = static_cast<uint8_t*>(data);
675 : }
676 0 : _size = size;
677 : }
678 :
679 : //! Destroy the `CBData` instance (NEVER CALLED).
680 : ASMJIT_INLINE ~CBData() noexcept {}
681 :
682 : // --------------------------------------------------------------------------
683 : // [Accessors]
684 : // --------------------------------------------------------------------------
685 :
686 : //! Get size of the data.
687 0 : uint32_t getSize() const noexcept { return _size; }
688 : //! Get pointer to the data.
689 0 : uint8_t* getData() const noexcept { return _size <= kInlineBufferSize ? const_cast<uint8_t*>(_buf) : _externalPtr; }
690 :
691 : // --------------------------------------------------------------------------
692 : // [Members]
693 : // --------------------------------------------------------------------------
694 :
695 : union {
696 : struct {
697 : uint8_t _buf[kInlineBufferSize]; //!< Embedded data buffer.
698 : uint32_t _size; //!< Size of the data.
699 : };
700 : struct {
701 : uint8_t* _externalPtr; //!< Pointer to external data.
702 : };
703 : };
704 : };
705 :
706 : // ============================================================================
707 : // [asmjit::CBAlign]
708 : // ============================================================================
709 :
710 : //! Align directive (CodeBuilder).
711 : //!
712 : //! Wraps `.align` directive.
713 : class CBAlign : public CBNode {
714 : public:
715 : ASMJIT_NONCOPYABLE(CBAlign)
716 :
717 : // --------------------------------------------------------------------------
718 : // [Construction / Destruction]
719 : // --------------------------------------------------------------------------
720 :
721 : //! Create a new `CBAlign` instance.
722 : ASMJIT_INLINE CBAlign(CodeBuilder* cb, uint32_t mode, uint32_t alignment) noexcept
723 0 : : CBNode(cb, kNodeAlign),
724 0 : _mode(mode),
725 0 : _alignment(alignment) {}
726 : //! Destroy the `CBAlign` instance (NEVER CALLED).
727 : ASMJIT_INLINE ~CBAlign() noexcept {}
728 :
729 : // --------------------------------------------------------------------------
730 : // [Accessors]
731 : // --------------------------------------------------------------------------
732 :
733 : //! Get align mode.
734 0 : ASMJIT_INLINE uint32_t getMode() const noexcept { return _mode; }
735 : //! Set align mode.
736 : ASMJIT_INLINE void setMode(uint32_t mode) noexcept { _mode = mode; }
737 :
738 : //! Get align offset in bytes.
739 0 : ASMJIT_INLINE uint32_t getAlignment() const noexcept { return _alignment; }
740 : //! Set align offset in bytes to `offset`.
741 : ASMJIT_INLINE void setAlignment(uint32_t alignment) noexcept { _alignment = alignment; }
742 :
743 : // --------------------------------------------------------------------------
744 : // [Members]
745 : // --------------------------------------------------------------------------
746 :
747 : uint32_t _mode; //!< Align mode, see \ref AlignMode.
748 : uint32_t _alignment; //!< Alignment (in bytes).
749 : };
750 :
751 : // ============================================================================
752 : // [asmjit::CBLabel]
753 : // ============================================================================
754 :
755 : //! Label (CodeBuilder).
756 : class CBLabel : public CBNode {
757 : public:
758 : ASMJIT_NONCOPYABLE(CBLabel)
759 :
760 : // --------------------------------------------------------------------------
761 : // [Construction / Destruction]
762 : // --------------------------------------------------------------------------
763 :
764 : //! Create a new `CBLabel` instance.
765 : ASMJIT_INLINE CBLabel(CodeBuilder* cb, uint32_t id = kInvalidValue) noexcept
766 3888 : : CBNode(cb, kNodeLabel),
767 3888 : _id(id),
768 3888 : _numRefs(0),
769 3888 : _from(nullptr) {}
770 : //! Destroy the `CBLabel` instance (NEVER CALLED).
771 : ASMJIT_INLINE ~CBLabel() noexcept {}
772 :
773 : // --------------------------------------------------------------------------
774 : // [Accessors]
775 : // --------------------------------------------------------------------------
776 :
777 : //! Get the label id.
778 0 : ASMJIT_INLINE uint32_t getId() const noexcept { return _id; }
779 : //! Get the label as `Label` operand.
780 3888 : ASMJIT_INLINE Label getLabel() const noexcept { return Label(_id); }
781 :
782 : //! Get first jmp instruction.
783 0 : ASMJIT_INLINE CBJump* getFrom() const noexcept { return _from; }
784 :
785 : //! Get number of jumps to this target.
786 0 : ASMJIT_INLINE uint32_t getNumRefs() const noexcept { return _numRefs; }
787 : //! Set number of jumps to this target.
788 : ASMJIT_INLINE void setNumRefs(uint32_t i) noexcept { _numRefs = i; }
789 :
790 : //! Add number of jumps to this target.
791 0 : ASMJIT_INLINE void addNumRefs(uint32_t i = 1) noexcept { _numRefs += i; }
792 : //! Subtract number of jumps to this target.
793 0 : ASMJIT_INLINE void subNumRefs(uint32_t i = 1) noexcept { _numRefs -= i; }
794 :
795 : // --------------------------------------------------------------------------
796 : // [Members]
797 : // --------------------------------------------------------------------------
798 :
799 : uint32_t _id; //!< Label id.
800 : uint32_t _numRefs; //!< Count of jumps here.
801 : CBJump* _from; //!< Linked-list of nodes that can jump here.
802 : };
803 :
804 : // ============================================================================
805 : // [asmjit::CBLabelData]
806 : // ============================================================================
807 :
808 : class CBLabelData : public CBNode {
809 : public:
810 : ASMJIT_NONCOPYABLE(CBLabelData)
811 :
812 : // --------------------------------------------------------------------------
813 : // [Construction / Destruction]
814 : // --------------------------------------------------------------------------
815 :
816 : //! Create a new `CBLabelData` instance.
817 : ASMJIT_INLINE CBLabelData(CodeBuilder* cb, uint32_t id = kInvalidValue) noexcept
818 0 : : CBNode(cb, kNodeLabelData),
819 0 : _id(id) {}
820 :
821 : //! Destroy the `CBLabelData` instance (NEVER CALLED).
822 : ASMJIT_INLINE ~CBLabelData() noexcept {}
823 :
824 : // --------------------------------------------------------------------------
825 : // [Interface]
826 : // --------------------------------------------------------------------------
827 :
828 : //! Get the label id.
829 : ASMJIT_INLINE uint32_t getId() const noexcept { return _id; }
830 : //! Get the label as `Label` operand.
831 0 : ASMJIT_INLINE Label getLabel() const noexcept { return Label(_id); }
832 :
833 : // --------------------------------------------------------------------------
834 : // [Members]
835 : // --------------------------------------------------------------------------
836 :
837 : uint32_t _id;
838 : };
839 :
840 : // ============================================================================
841 : // [asmjit::CBConstPool]
842 : // ============================================================================
843 :
844 : class CBConstPool : public CBLabel {
845 : public:
846 : ASMJIT_NONCOPYABLE(CBConstPool)
847 :
848 : // --------------------------------------------------------------------------
849 : // [Construction / Destruction]
850 : // --------------------------------------------------------------------------
851 :
852 : //! Create a new `CBConstPool` instance.
853 : ASMJIT_INLINE CBConstPool(CodeBuilder* cb, uint32_t id = kInvalidValue) noexcept
854 0 : : CBLabel(cb, id),
855 0 : _constPool(&cb->_cbBaseZone) { _type = kNodeConstPool; }
856 :
857 : //! Destroy the `CBConstPool` instance (NEVER CALLED).
858 : ASMJIT_INLINE ~CBConstPool() noexcept {}
859 :
860 : // --------------------------------------------------------------------------
861 : // [Interface]
862 : // --------------------------------------------------------------------------
863 :
864 0 : ASMJIT_INLINE ConstPool& getConstPool() noexcept { return _constPool; }
865 : ASMJIT_INLINE const ConstPool& getConstPool() const noexcept { return _constPool; }
866 :
867 : //! Get whether the constant-pool is empty.
868 : ASMJIT_INLINE bool isEmpty() const noexcept { return _constPool.isEmpty(); }
869 : //! Get the size of the constant-pool in bytes.
870 : ASMJIT_INLINE size_t getSize() const noexcept { return _constPool.getSize(); }
871 : //! Get minimum alignment.
872 : ASMJIT_INLINE size_t getAlignment() const noexcept { return _constPool.getAlignment(); }
873 :
874 : //! See \ref ConstPool::add().
875 : ASMJIT_INLINE Error add(const void* data, size_t size, size_t& dstOffset) noexcept {
876 0 : return _constPool.add(data, size, dstOffset);
877 : }
878 :
879 : // --------------------------------------------------------------------------
880 : // [Members]
881 : // --------------------------------------------------------------------------
882 :
883 : ConstPool _constPool;
884 : };
885 :
886 : // ============================================================================
887 : // [asmjit::CBComment]
888 : // ============================================================================
889 :
890 : //! Comment (CodeBuilder).
891 : class CBComment : public CBNode {
892 : public:
893 : ASMJIT_NONCOPYABLE(CBComment)
894 :
895 : // --------------------------------------------------------------------------
896 : // [Construction / Destruction]
897 : // --------------------------------------------------------------------------
898 :
899 : //! Create a new `CBComment` instance.
900 : ASMJIT_INLINE CBComment(CodeBuilder* cb, const char* comment) noexcept : CBNode(cb, kNodeComment) {
901 : orFlags(kFlagIsRemovable | kFlagIsInformative);
902 0 : _inlineComment = comment;
903 : }
904 :
905 : //! Destroy the `CBComment` instance (NEVER CALLED).
906 : ASMJIT_INLINE ~CBComment() noexcept {}
907 : };
908 :
909 : // ============================================================================
910 : // [asmjit::CBSentinel]
911 : // ============================================================================
912 :
913 : //! Sentinel (CodeBuilder).
914 : //!
915 : //! Sentinel is a marker that is completely ignored by the code builder. It's
916 : //! used to remember a position in a code as it never gets removed by any pass.
917 : class CBSentinel : public CBNode {
918 : public:
919 : ASMJIT_NONCOPYABLE(CBSentinel)
920 :
921 : // --------------------------------------------------------------------------
922 : // [Construction / Destruction]
923 : // --------------------------------------------------------------------------
924 :
925 : //! Create a new `CBSentinel` instance.
926 : ASMJIT_INLINE CBSentinel(CodeBuilder* cb) noexcept : CBNode(cb, kNodeSentinel) {}
927 : //! Destroy the `CBSentinel` instance (NEVER CALLED).
928 : ASMJIT_INLINE ~CBSentinel() noexcept {}
929 : };
930 :
931 : //! \}
932 :
933 : } // asmjit namespace
934 : } // namespace PLMD
935 :
936 : // [Api-End]
937 : #include "./asmjit_apiend.h"
938 :
939 : // [Guard]
940 : #endif // !ASMJIT_DISABLE_BUILDER
941 : #endif // _ASMJIT_BASE_CODEBUILDER_H
942 : #pragma GCC diagnostic pop
943 : #endif // __PLUMED_HAS_ASMJIT
944 : #endif
|