summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/asmjit/src/asmjit/x86/x86builder.h
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/asmjit/src/asmjit/x86/x86builder.h')
-rw-r--r--3rdparty/asmjit/src/asmjit/x86/x86builder.h139
1 files changed, 53 insertions, 86 deletions
diff --git a/3rdparty/asmjit/src/asmjit/x86/x86builder.h b/3rdparty/asmjit/src/asmjit/x86/x86builder.h
index 256bc9ecbec..194c1402f11 100644
--- a/3rdparty/asmjit/src/asmjit/x86/x86builder.h
+++ b/3rdparty/asmjit/src/asmjit/x86/x86builder.h
@@ -1,25 +1,7 @@
-// AsmJit - Machine code generation for C++
+// This file is part of AsmJit project <https://asmjit.com>
//
-// * Official AsmJit Home Page: https://asmjit.com
-// * Official Github Repository: https://github.com/asmjit/asmjit
-//
-// Copyright (c) 2008-2020 The AsmJit Authors
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-// claim that you wrote the original software. If you use this software
-// in a product, an acknowledgment in the product documentation would be
-// appreciated but is not required.
-// 2. Altered source versions must be plainly marked as such, and must not be
-// misrepresented as being the original software.
-// 3. This notice may not be removed or altered from any source distribution.
+// See asmjit.h or LICENSE.md for license and copyright information
+// SPDX-License-Identifier: Zlib
#ifndef ASMJIT_X86_X86BUILDER_H_INCLUDED
#define ASMJIT_X86_X86BUILDER_H_INCLUDED
@@ -28,7 +10,6 @@
#ifndef ASMJIT_NO_BUILDER
#include "../core/builder.h"
-#include "../core/datatypes.h"
#include "../x86/x86emitter.h"
ASMJIT_BEGIN_SUB_NAMESPACE(x86)
@@ -36,19 +17,13 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
//! \addtogroup asmjit_x86
//! \{
-// ============================================================================
-// [asmjit::x86::Builder]
-// ============================================================================
-
//! X86/X64 builder implementation.
//!
-//! The code representation used by \ref BaseBuilder is compatible with everything
-//! AsmJit provides. Each instruction is stored as \ref InstNode, which contains
-//! instruction id, options, and operands. Each instruction emitted will create
-//! a new \ref InstNode instance and add it to the current cursor in the double-linked
-//! list of nodes. Since the instruction stream used by \ref BaseBuilder can be
-//! manipulated, we can rewrite the SumInts example from \ref asmjit_assembler
-//! into the following:
+//! The code representation used by \ref BaseBuilder is compatible with everything AsmJit provides. Each instruction
+//! is stored as \ref InstNode, which contains instruction id, options, and operands. Each instruction emitted will
+//! create a new \ref InstNode instance and add it to the current cursor in the double-linked list of nodes. Since
+//! the instruction stream used by \ref BaseBuilder can be manipulated, we can rewrite the SumInts example from
+//! \ref asmjit_assembler into the following:
//!
//! ```
//! #include <asmjit/x86.h>
@@ -61,7 +36,9 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
//! // Small helper function to print the current content of `cb`.
//! static void dumpCode(BaseBuilder& builder, const char* phase) {
//! String sb;
-//! builder.dump(sb);
+//! formatOptions formatOptions {};
+//!
+//! Formatter::formatNodeList(sb, formatOptions, &builder);
//! printf("%s:\n%s\n", phase, sb.data());
//! }
//!
@@ -69,12 +46,12 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
//! JitRuntime rt; // Create JIT Runtime.
//! CodeHolder code; // Create a CodeHolder.
//!
-//! code.init(rt.environment()); // Initialize code to match the JIT environment.
+//! code.init(rt.environment(), // Initialize code to match the JIT environment.
+//! rt.cpuFeatures());
//! x86::Builder cb(&code); // Create and attach x86::Builder to `code`.
//!
-//! // Decide which registers will be mapped to function arguments. Try changing
-//! // registers of `dst`, `srcA`, and `srcB` and see what happens in function's
-//! // prolog and epilog.
+//! // Decide which registers will be mapped to function arguments. Try changing registers
+//! // of `dst`, `srcA`, and `srcB` and see what happens in function's prolog and epilog.
//! x86::Gp dst = cb.zax();
//! x86::Gp srcA = cb.zcx();
//! x86::Gp srcB = cb.zdx();
@@ -84,7 +61,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
//!
//! // Create and initialize `FuncDetail`.
//! FuncDetail func;
-//! func.init(FuncSignatureT<void, int*, const int*, const int*>(CallConv::kIdHost));
+//! func.init(FuncSignature::build<void, int*, const int*, const int*>());
//!
//! // Remember prolog insertion point.
//! BaseNode* prologInsertionPoint = cb.cursor();
@@ -106,8 +83,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
//! FuncFrame frame;
//! frame.init(func);
//!
-//! // Make XMM0 and XMM1 dirty; `kGroupVec` describes XMM|YMM|ZMM registers.
-//! frame.setDirtyRegs(x86::Reg::kGroupVec, IntUtils::mask(0, 1));
+//! // Make XMM0 and XMM1 dirty; RegGroup::kVec describes XMM|YMM|ZMM registers.
+//! frame.setDirtyRegs(RegGroup::kVec, IntUtils::mask(0, 1));
//!
//! FuncArgsAssignment args(&func); // Create arguments assignment context.
//! args.assignAll(dst, srcA, srcB); // Assign our registers to arguments.
@@ -148,8 +125,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
//! }
//! ```
//!
-//! When the example is executed it should output the following (this one using
-//! AMD64-SystemV ABI):
+//! When the example is executed it should output the following (this one using AMD64-SystemV ABI):
//!
//! ```
//! Raw Function:
@@ -170,23 +146,21 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
//! {5 8 4 9}
//! ```
//!
-//! The number of use-cases of \ref BaseBuilder is not limited and highly depends
-//! on your creativity and experience. The previous example can be easily improved
-//! to collect all dirty registers inside the function programmatically and to pass
-//! them to \ref FuncFrame::setDirtyRegs().
+//! The number of use-cases of \ref BaseBuilder is not limited and highly depends on your creativity and experience.
+//! The previous example can be easily improved to collect all dirty registers inside the function programmatically
+//! and to pass them to \ref FuncFrame::setDirtyRegs().
//!
//! ```
//! #include <asmjit/x86.h>
//!
//! using namespace asmjit;
//!
-//! // NOTE: This function doesn't cover all possible constructs. It ignores
-//! // instructions that write to implicit registers that are not part of the
-//! // operand list. It also counts read-only registers. Real implementation
-//! // would be a bit more complicated, but still relatively easy to implement.
+//! // NOTE: This function doesn't cover all possible constructs. It ignores instructions that write
+//! // to implicit registers that are not part of the operand list. It also counts read-only registers.
+//! // Real implementation would be a bit more complicated, but still relatively easy to implement.
//! static void collectDirtyRegs(const BaseNode* first,
//! const BaseNode* last,
-//! uint32_t regMask[BaseReg::kGroupVirt]) {
+//! Support::Array<RegMask, Globals::kNumVirtGroups>& regMask) {
//! const BaseNode* node = first;
//! while (node) {
//! if (node->actsAsInst()) {
@@ -197,7 +171,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
//! const Operand& op = opArray[i];
//! if (op.isReg()) {
//! const x86::Reg& reg = op.as<x86::Reg>();
-//! if (reg.group() < BaseReg::kGroupVirt) {
+//! if (reg.group() <= RegGroup::kMaxVirt) {
//! regMask[reg.group()] |= 1u << reg.id();
//! }
//! }
@@ -211,23 +185,21 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
//! }
//!
//! static void setDirtyRegsOfFuncFrame(const x86::Builder& builder, FuncFrame& frame) {
-//! uint32_t regMask[BaseReg::kGroupVirt] {};
+//! Support::Array<RegMask, Globals::kNumVirtGroups> regMask {};
//! collectDirtyRegs(builder.firstNode(), builder.lastNode(), regMask);
//!
//! // X86/X64 ABIs only require to save GP/XMM registers:
-//! frame.setDirtyRegs(x86::Reg::kGroupGp , regMask[x86::Reg::kGroupGp ]);
-//! frame.setDirtyRegs(x86::Reg::kGroupVec, regMask[x86::Reg::kGroupVec]);
+//! frame.setDirtyRegs(RegGroup::kGp, regMask[RegGroup::kGp]);
+//! frame.setDirtyRegs(RegGroup::kVec, regMask[RegGroup::kVec]);
//! }
//! ```
//!
//! ### Casting Between Various Emitters
//!
-//! Even when \ref BaseAssembler and \ref BaseBuilder provide the same interface
-//! as defined by \ref BaseEmitter their platform dependent variants like \ref
-//! x86::Assembler and \ref x86::Builder cannot be interchanged or casted
-//! to each other by using a C++ `static_cast<>`. The main reason is the
-//! inheritance graph of these classes is different and cast-incompatible, as
-//! illustrated below:
+//! Even when \ref BaseAssembler and \ref BaseBuilder provide the same interface as defined by \ref BaseEmitter their
+//! platform dependent variants like \ref x86::Assembler and \ref x86::Builder cannot be interchanged or casted to each
+//! other by using a C++ `static_cast<>`. The main reason is the inheritance graph of these classes is different and
+//! cast-incompatible, as illustrated below:
//!
//! ```
//! +--------------+ +=========================+
@@ -250,15 +222,12 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
//! (abstract) (final) (mixin)
//! ```
//!
-//! The graph basically shows that it's not possible to cast between \ref
-//! x86::Assembler and \ref x86::Builder. However, since both share the
-//! base interface (\ref BaseEmitter) it's possible to cast them to a class
-//! that cannot be instantiated, but defines the same interface - the class
-//! is called \ref x86::Emitter and was introduced to make it possible to
-//! write a function that can emit to both \ref x86::Assembler and \ref
-//! x86::Builder. Note that \ref x86::Emitter cannot be created, it's abstract
-//! and has private constructors and destructors; it was only designed to be
-//! casted to and used as an interface.
+//! The graph basically shows that it's not possible to cast between \ref x86::Assembler and \ref x86::Builder.
+//! However, since both share the base interface (\ref BaseEmitter) it's possible to cast them to a class that
+//! cannot be instantiated, but defines the same interface - the class is called \ref x86::Emitter and was
+//! introduced to make it possible to write a function that can emit to both \ref x86::Assembler and \ref
+//! x86::Builder. Note that \ref x86::Emitter cannot be created, it's abstract and has private constructors and
+//! destructors; it was only designed to be casted to and used as an interface.
//!
//! Each architecture-specific emitter implements a member function called
//! `as<arch::Emitter>()`, which casts the instance to the architecture
@@ -289,19 +258,16 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
//! }
//! ```
//!
-//! The example above shows how to create a function that can emit code to
-//! either \ref x86::Assembler or \ref x86::Builder through \ref x86::Emitter,
-//! which provides emitter-neutral functionality. \ref x86::Emitter, however,
-//! doesn't provide any emitter-specific functionality like `setCursor()`.
+//! The example above shows how to create a function that can emit code to either \ref x86::Assembler or \ref
+//! x86::Builder through \ref x86::Emitter, which provides emitter-neutral functionality. \ref x86::Emitter,
+//! however, doesn't provide any emitter-specific functionality like `setCursor()`.
//!
//! ### Code Injection and Manipulation
//!
-//! \ref BaseBuilder emitter stores its nodes in a double-linked list, which
-//! makes it easy to manipulate that list during the code generation or
-//! afterwards. Each node is always emitted next to the current cursor and the
-//! cursor is advanced to that newly emitted node. The cursor can be retrieved
-//! and changed by \ref BaseBuilder::cursor() and \ref BaseBuilder::setCursor(),
-//! respectively.
+//! \ref BaseBuilder emitter stores its nodes in a double-linked list, which makes it easy to manipulate that
+//! list during the code generation or afterwards. Each node is always emitted next to the current cursor and
+//! the cursor is advanced to that newly emitted node. The cursor can be retrieved and changed by \ref
+//! BaseBuilder::cursor() and \ref BaseBuilder::setCursor(), respectively.
//!
//! The example below demonstrates how to remember a node and inject something
//! next to it.
@@ -360,21 +326,22 @@ public:
//! \{
ASMJIT_API explicit Builder(CodeHolder* code = nullptr) noexcept;
- ASMJIT_API virtual ~Builder() noexcept;
+ ASMJIT_API ~Builder() noexcept override;
//! \}
- //! \name Finalize
+ //! \name Events
//! \{
- ASMJIT_API Error finalize() override;
+ ASMJIT_API Error onAttach(CodeHolder* code) noexcept override;
+ ASMJIT_API Error onDetach(CodeHolder* code) noexcept override;
//! \}
- //! \name Events
+ //! \name Finalize
//! \{
- ASMJIT_API Error onAttach(CodeHolder* code) noexcept override;
+ ASMJIT_API Error finalize() override;
//! \}
};