odin-blend2d

Odin bindings to Blend2D
Log | Files | Refs | README | LICENSE

a64compiler.h (12219B)


      1 // This file is part of AsmJit project <https://asmjit.com>
      2 //
      3 // See <asmjit/core.h> or LICENSE.md for license and copyright information
      4 // SPDX-License-Identifier: Zlib
      5 
      6 #ifndef ASMJIT_ARM_A64COMPILER_H_INCLUDED
      7 #define ASMJIT_ARM_A64COMPILER_H_INCLUDED
      8 
      9 #include "../core/api-config.h"
     10 #ifndef ASMJIT_NO_COMPILER
     11 
     12 #include "../core/compiler.h"
     13 #include "../core/type.h"
     14 #include "../arm/a64emitter.h"
     15 
     16 ASMJIT_BEGIN_SUB_NAMESPACE(a64)
     17 
     18 //! \addtogroup asmjit_a64
     19 //! \{
     20 
     21 //! AArch64 compiler implementation.
     22 class ASMJIT_VIRTAPI Compiler
     23   : public BaseCompiler,
     24     public EmitterExplicitT<Compiler> {
     25 public:
     26   ASMJIT_NONCOPYABLE(Compiler)
     27   using Base = BaseCompiler;
     28 
     29   //! \name Construction & Destruction
     30   //! \{
     31 
     32   ASMJIT_API explicit Compiler(CodeHolder* code = nullptr) noexcept;
     33   ASMJIT_API ~Compiler() noexcept override;
     34 
     35   //! \}
     36 
     37   //! \name Virtual Registers
     38   //! \{
     39 
     40   //! Creates a new general-purpose register with `type_id` type and optional name passed via `args`.
     41   //!
     42   //! \note Using \ref TypeId is too generic. In general it's recommended to use \ref new_gp32(),
     43   //! \ref new_gp64(), and \ref new_gpz() or \ref new_gp_ptr().
     44   template<typename... Args>
     45   ASMJIT_INLINE_NODEBUG Gp new_gp(TypeId type_id, Args&&... args) { return new_reg<Gp>(type_id, std::forward<Args>(args)...); }
     46 
     47   //! Creates a new vector register with `type_id` type and optional name passed via `args`.
     48   //!
     49   //! \note Using \ref TypeId is too generic. In general it's recommended to use \ref new_vec128(),
     50   //! \ref new_vec_s(), \ref new_vec_d(), \ref new_vec_q(), ...
     51   template<typename... Args>
     52   ASMJIT_INLINE_NODEBUG Vec new_vec(TypeId type_id, Args&&... args) { return new_reg<Vec>(type_id, std::forward<Args>(args)...); }
     53 
     54   //! Creates a new 32-bit general purpose register mapped to low 32 bits of a full register (on 64-bit targets).
     55   template<typename... Args>
     56   ASMJIT_INLINE_NODEBUG Gp new_gp32(Args&&... args) { return new_reg<Gp>(TypeId::kUInt32, std::forward<Args>(args)...); }
     57 
     58   //! Creates a new 64-bit general purpose register.
     59   template<typename... Args>
     60   ASMJIT_INLINE_NODEBUG Gp new_gp64(Args&&... args) { return new_reg<Gp>(TypeId::kUInt64, std::forward<Args>(args)...); }
     61 
     62   //! Creates a new 32-bit general purpose register.
     63   //!
     64   //! \note This is a convenience function alias of \ref new_gp32().
     65   template<typename... Args>
     66   ASMJIT_INLINE_NODEBUG Gp new_gpw(Args&&... args) { return new_reg<Gp>(TypeId::kUIntPtr, std::forward<Args>(args)...); }
     67 
     68   //! Creates a new 64-bit general purpose register.
     69   //!
     70   //! \note This is a convenience function alias of \ref new_gp64().
     71   template<typename... Args>
     72   ASMJIT_INLINE_NODEBUG Gp new_gpx(Args&&... args) { return new_reg<Gp>(TypeId::kUIntPtr, std::forward<Args>(args)...); }
     73 
     74   //! Creates a new 32-bit or 64-bit general purpose register depending on the target register width.
     75   //!
     76   //! \note This is a convenience function, on aarch64 target it always creates a 64-bit general-purpose register.
     77   template<typename... Args>
     78   ASMJIT_INLINE_NODEBUG Gp new_gpz(Args&&... args) { return new_reg<Gp>(TypeId::kUIntPtr, std::forward<Args>(args)...); }
     79 
     80   //! Creates a new 32-bit or 64-bit general purpose register depending on the target register width.
     81   //!
     82   //! \note This is a convenience function, on aarch64 target it always creates a 64-bit general-purpose register.
     83   template<typename... Args>
     84   ASMJIT_INLINE_NODEBUG Gp new_gp_ptr(Args&&... args) { return new_reg<Gp>(TypeId::kUIntPtr, std::forward<Args>(args)...); }
     85 
     86   //! Creates a new 128-bit vector register.
     87   template<typename... Args>
     88   ASMJIT_INLINE_NODEBUG Vec new_vec128(Args&&... args) { return new_reg<Vec>(TypeId::kInt32x4, std::forward<Args>(args)...); }
     89 
     90   //! Creates a new 128-bit vector register that will be used for scalar 32-bit floating point operation.
     91   template<typename... Args>
     92   ASMJIT_INLINE_NODEBUG Vec new_vec128_f32x1(Args&&... args) { return new_reg<Vec>(TypeId::kFloat32x1, std::forward<Args>(args)...); }
     93 
     94   //! Creates a new 128-bit vector register that will be used for scalar 64-bit floating point operation.
     95   template<typename... Args>
     96   ASMJIT_INLINE_NODEBUG Vec new_vec128_f64x1(Args&&... args) { return new_reg<Vec>(TypeId::kFloat64x1, std::forward<Args>(args)...); }
     97 
     98   //! Creates a new 128-bit vector register that will be used for packed 32-bit floating point operation.
     99   template<typename... Args>
    100   ASMJIT_INLINE_NODEBUG Vec new_vec128_f32x4(Args&&... args) { return new_reg<Vec>(TypeId::kFloat32x4, std::forward<Args>(args)...); }
    101 
    102   //! Creates a new 128-bit vector register that will be used for packed 64-bit floating point operation.
    103   template<typename... Args>
    104   ASMJIT_INLINE_NODEBUG Vec new_vec128_f64x2(Args&&... args) { return new_reg<Vec>(TypeId::kFloat64x2, std::forward<Args>(args)...); }
    105 
    106   //! Creates a new 32-bit vector register (S).
    107   //!
    108   //! \note This may look like an alias of \ref new_vec128_f32x1(), but it's not. This really creates a 32-bit
    109   //! register, which has a type \ref RegType::kVec32, whereas \ref new_vec128_f32x1() creates a register,
    110   //! which has a type \ref RegType::kVec64
    111   template<typename... Args>
    112   ASMJIT_INLINE_NODEBUG Vec new_vec_s(Args&&... args) { return new_reg<Vec>(TypeId::kFloat32, std::forward<Args>(args)...); }
    113 
    114   //! Alias of \ref new_vec128_f64x1() that matches aarch64 architecture terminology.
    115   template<typename... Args>
    116   ASMJIT_INLINE_NODEBUG Vec new_vec_d(Args&&... args) { return new_reg<Vec>(TypeId::kFloat64, std::forward<Args>(args)...); }
    117 
    118   //! Alias of \ref new_vec128() that matches aarch64 architecture terminology.
    119   template<typename... Args>
    120   ASMJIT_INLINE_NODEBUG Vec new_vec_q(Args&&... args) { return new_reg<Vec>(TypeId::kInt32x4, std::forward<Args>(args)...); }
    121 
    122   //! \}
    123 
    124   //! \name Stack
    125   //! \{
    126 
    127   //! Creates a new stack and returns a \ref Mem operand that can be used to address it.
    128   ASMJIT_INLINE_NODEBUG Mem new_stack(uint32_t size, uint32_t alignment, const char* name = nullptr) {
    129     Mem m(Globals::NoInit);
    130     _new_stack(Out<BaseMem>(m), size, alignment, name);
    131     return m;
    132   }
    133 
    134   //! \}
    135 
    136   //! \name Constants
    137   //! \{
    138 
    139   //! Put data to a constant-pool and get a memory reference to it.
    140   ASMJIT_INLINE_NODEBUG Mem new_const(ConstPoolScope scope, const void* data, size_t size) {
    141     Mem m(Globals::NoInit);
    142     _new_const(Out<BaseMem>(m), scope, data, size);
    143     return m;
    144   }
    145 
    146   //! Put a BYTE `val` to a constant-pool (8 bits).
    147   ASMJIT_INLINE_NODEBUG Mem new_byte_const(ConstPoolScope scope, uint8_t val) noexcept { return new_const(scope, &val, 1); }
    148   //! Put a HWORD `val` to a constant-pool (16 bits).
    149   ASMJIT_INLINE_NODEBUG Mem new_half_const(ConstPoolScope scope, uint16_t val) noexcept { return new_const(scope, &val, 2); }
    150   //! Put a WORD `val` to a constant-pool (32 bits).
    151   ASMJIT_INLINE_NODEBUG Mem new_word_const(ConstPoolScope scope, uint32_t val) noexcept { return new_const(scope, &val, 4); }
    152   //! Put a DWORD `val` to a constant-pool (64 bits).
    153   ASMJIT_INLINE_NODEBUG Mem new_dword_const(ConstPoolScope scope, uint64_t val) noexcept { return new_const(scope, &val, 8); }
    154 
    155   //! Put a WORD `val` to a constant-pool.
    156   ASMJIT_INLINE_NODEBUG Mem new_int16_const(ConstPoolScope scope, int16_t val) noexcept { return new_const(scope, &val, 2); }
    157   //! Put a WORD `val` to a constant-pool.
    158   ASMJIT_INLINE_NODEBUG Mem new_uint16_const(ConstPoolScope scope, uint16_t val) noexcept { return new_const(scope, &val, 2); }
    159   //! Put a DWORD `val` to a constant-pool.
    160   ASMJIT_INLINE_NODEBUG Mem new_int32_const(ConstPoolScope scope, int32_t val) noexcept { return new_const(scope, &val, 4); }
    161   //! Put a DWORD `val` to a constant-pool.
    162   ASMJIT_INLINE_NODEBUG Mem new_uint32_const(ConstPoolScope scope, uint32_t val) noexcept { return new_const(scope, &val, 4); }
    163   //! Put a QWORD `val` to a constant-pool.
    164   ASMJIT_INLINE_NODEBUG Mem new_int64_const(ConstPoolScope scope, int64_t val) noexcept { return new_const(scope, &val, 8); }
    165   //! Put a QWORD `val` to a constant-pool.
    166   ASMJIT_INLINE_NODEBUG Mem new_uint64_const(ConstPoolScope scope, uint64_t val) noexcept { return new_const(scope, &val, 8); }
    167 
    168   //! Put a SP-FP `val` to a constant-pool.
    169   ASMJIT_INLINE_NODEBUG Mem new_float_const(ConstPoolScope scope, float val) noexcept { return new_const(scope, &val, 4); }
    170   //! Put a DP-FP `val` to a constant-pool.
    171   ASMJIT_INLINE_NODEBUG Mem new_double_const(ConstPoolScope scope, double val) noexcept { return new_const(scope, &val, 8); }
    172 
    173   //! \}
    174 
    175   //! \name Instruction Options
    176   //! \{
    177 
    178   //! Force the compiler to not follow the conditional or unconditional jump.
    179   ASMJIT_INLINE_NODEBUG Compiler& unfollow() noexcept { _inst_options |= InstOptions::kUnfollow; return *this; }
    180 
    181   //! \}
    182 
    183   //! \name Compiler specific
    184   //! \{
    185 
    186   //! Special pseudo-instruction that can be used to load a memory address into `o0` GP register.
    187   //!
    188   //! \note At the moment this instruction is only useful to load a stack allocated address into a GP register
    189   //! for further use. It makes very little sense to use it for anything else. The semantics of this instruction
    190   //! is the same as X86 `LEA` (load effective address) instruction.
    191   ASMJIT_INLINE_NODEBUG Error load_address_of(const Gp& o0, const Mem& o1) { return _emitter()->_emitI(Inst::kIdAdr, o0, o1); }
    192 
    193   //! \}
    194 
    195   //! \name Function Call & Ret Intrinsics
    196   //! \{
    197 
    198   //! Invoke a function call without `target` type enforcement.
    199   ASMJIT_INLINE_NODEBUG Error invoke_(Out<InvokeNode*> out, const Operand_& target, const FuncSignature& signature) {
    200     return add_invoke_node(out, Inst::kIdBlr, target, signature);
    201   }
    202 
    203   //! Invoke a function call of the given `target` and `signature` and store the added node to `out`.
    204   //!
    205   //! Creates a new \ref InvokeNode, initializes all the necessary members to match the given function `signature`,
    206   //! adds the node to the compiler, and stores its pointer to `out`. The operation is atomic, if anything fails
    207   //! nullptr is stored in `out` and error code is returned.
    208   ASMJIT_INLINE_NODEBUG Error invoke(Out<InvokeNode*> out, const Gp& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
    209   //! \overload
    210   ASMJIT_INLINE_NODEBUG Error invoke(Out<InvokeNode*> out, const Mem& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
    211   //! \overload
    212   ASMJIT_INLINE_NODEBUG Error invoke(Out<InvokeNode*> out, const Label& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
    213   //! \overload
    214   ASMJIT_INLINE_NODEBUG Error invoke(Out<InvokeNode*> out, const Imm& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
    215   //! \overload
    216   ASMJIT_INLINE_NODEBUG Error invoke(Out<InvokeNode*> out, uint64_t target, const FuncSignature& signature) { return invoke_(out, Imm(int64_t(target)), signature); }
    217 
    218   //! Return from function.
    219   //!
    220   //! \note This doesn't end the function - it just emits a return.
    221   ASMJIT_INLINE_NODEBUG Error ret() { return add_ret(Operand(), Operand()); }
    222 
    223   //! Return from function - one value.
    224   //!
    225   //! \note This doesn't end the function - it just emits a return.
    226   ASMJIT_INLINE_NODEBUG Error ret(const Reg& o0) { return add_ret(o0, Operand()); }
    227 
    228   //! Return from function - two values / register pair.
    229   //!
    230   //! \note This doesn't end the function - it just emits a return.
    231   ASMJIT_INLINE_NODEBUG Error ret(const Reg& o0, const Reg& o1) { return add_ret(o0, o1); }
    232 
    233   //! \}
    234 
    235   //! \name Jump Tables Support
    236   //! \{
    237 
    238   using EmitterExplicitT<Compiler>::br;
    239 
    240   //! Adds a jump to the given `target` with the provided jump `annotation`.
    241   ASMJIT_INLINE_NODEBUG Error br(const Reg& target, JumpAnnotation* annotation) { return emit_annotated_jump(Inst::kIdBr, target, annotation); }
    242 
    243   //! \}
    244 
    245   //! \name Events
    246   //! \{
    247 
    248   ASMJIT_API Error on_attach(CodeHolder& code) noexcept override;
    249   ASMJIT_API Error on_detach(CodeHolder& code) noexcept override;
    250   ASMJIT_API Error on_reinit(CodeHolder& code) noexcept override;
    251 
    252   //! \}
    253 
    254   //! \name Finalize
    255   //! \{
    256 
    257   ASMJIT_API Error finalize() override;
    258 
    259   //! \}
    260 };
    261 
    262 //! \}
    263 
    264 ASMJIT_END_SUB_NAMESPACE
    265 
    266 #endif // !ASMJIT_NO_COMPILER
    267 #endif // ASMJIT_ARM_A64COMPILER_H_INCLUDED