|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef ASMJIT_ARM_A64COMPILER_H_INCLUDED
|
|
|
#define ASMJIT_ARM_A64COMPILER_H_INCLUDED
|
|
|
|
|
|
#include "../core/api-config.h"
|
|
|
#ifndef ASMJIT_NO_COMPILER
|
|
|
|
|
|
#include "../core/compiler.h"
|
|
|
#include "../core/type.h"
|
|
|
#include "../arm/a64emitter.h"
|
|
|
|
|
|
ASMJIT_BEGIN_SUB_NAMESPACE(a64)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ASMJIT_VIRTAPI Compiler
|
|
|
: public BaseCompiler,
|
|
|
public EmitterExplicitT<Compiler> {
|
|
|
public:
|
|
|
ASMJIT_NONCOPYABLE(Compiler)
|
|
|
typedef BaseCompiler Base;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ASMJIT_API explicit Compiler(CodeHolder* code = nullptr) noexcept;
|
|
|
ASMJIT_API ~Compiler() noexcept override;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename RegT, typename Type>
|
|
|
ASMJIT_INLINE_NODEBUG RegT _newRegInternal(const Type& type) {
|
|
|
RegT reg(Globals::NoInit);
|
|
|
_newReg(®, type, nullptr);
|
|
|
return reg;
|
|
|
}
|
|
|
|
|
|
template<typename RegT, typename Type>
|
|
|
ASMJIT_INLINE_NODEBUG RegT _newRegInternal(const Type& type, const char* s) {
|
|
|
#ifndef ASMJIT_NO_LOGGING
|
|
|
RegT reg(Globals::NoInit);
|
|
|
_newReg(®, type, s);
|
|
|
return reg;
|
|
|
#else
|
|
|
DebugUtils::unused(s);
|
|
|
return _newRegInternal<RegT>(type);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
template<typename RegT, typename Type, typename... Args>
|
|
|
ASMJIT_INLINE_NODEBUG RegT _newRegInternal(const Type& type, const char* s, Args&&... args) {
|
|
|
#ifndef ASMJIT_NO_LOGGING
|
|
|
RegT reg(Globals::NoInit);
|
|
|
_newRegFmt(®, type, s, std::forward<Args>(args)...);
|
|
|
return reg;
|
|
|
#else
|
|
|
DebugUtils::unused(s, std::forward<Args>(args)...);
|
|
|
return _newRegInternal<RegT>(type);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
|
|
|
template<typename RegT, typename... Args>
|
|
|
ASMJIT_INLINE_NODEBUG RegT newSimilarReg(const RegT& ref, Args&&... args) {
|
|
|
return _newRegInternal<RegT>(ref, std::forward<Args>(args)...);
|
|
|
}
|
|
|
|
|
|
template<typename... Args>
|
|
|
ASMJIT_INLINE_NODEBUG Reg newReg(TypeId typeId, Args&&... args) { return _newRegInternal<Reg>(typeId, std::forward<Args>(args)...); }
|
|
|
|
|
|
template<typename... Args>
|
|
|
ASMJIT_INLINE_NODEBUG Gp newGp(TypeId typeId, Args&&... args) { return _newRegInternal<Gp>(typeId, std::forward<Args>(args)...); }
|
|
|
|
|
|
template<typename... Args>
|
|
|
ASMJIT_INLINE_NODEBUG Vec newVec(TypeId typeId, Args&&... args) { return _newRegInternal<Vec>(typeId, std::forward<Args>(args)...); }
|
|
|
|
|
|
template<typename... Args>
|
|
|
ASMJIT_INLINE_NODEBUG Gp newInt32(Args&&... args) { return _newRegInternal<Gp>(TypeId::kInt32, std::forward<Args>(args)...); }
|
|
|
template<typename... Args>
|
|
|
ASMJIT_INLINE_NODEBUG Gp newUInt32(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUInt32, std::forward<Args>(args)...); }
|
|
|
|
|
|
template<typename... Args>
|
|
|
ASMJIT_INLINE_NODEBUG Gp newInt64(Args&&... args) { return _newRegInternal<Gp>(TypeId::kInt64, std::forward<Args>(args)...); }
|
|
|
template<typename... Args>
|
|
|
ASMJIT_INLINE_NODEBUG Gp newUInt64(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUInt64, std::forward<Args>(args)...); }
|
|
|
|
|
|
template<typename... Args>
|
|
|
ASMJIT_INLINE_NODEBUG Gp newIntPtr(Args&&... args) { return _newRegInternal<Gp>(TypeId::kIntPtr, std::forward<Args>(args)...); }
|
|
|
template<typename... Args>
|
|
|
ASMJIT_INLINE_NODEBUG Gp newUIntPtr(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUIntPtr, std::forward<Args>(args)...); }
|
|
|
|
|
|
template<typename... Args>
|
|
|
ASMJIT_INLINE_NODEBUG Gp newGpw(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUInt32, std::forward<Args>(args)...); }
|
|
|
template<typename... Args>
|
|
|
ASMJIT_INLINE_NODEBUG Gp newGpx(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUInt64, std::forward<Args>(args)...); }
|
|
|
template<typename... Args>
|
|
|
ASMJIT_INLINE_NODEBUG Gp newGpz(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUIntPtr, std::forward<Args>(args)...); }
|
|
|
|
|
|
template<typename... Args>
|
|
|
ASMJIT_INLINE_NODEBUG Vec newVecS(Args&&... args) { return _newRegInternal<Vec>(TypeId::kFloat32, std::forward<Args>(args)...); }
|
|
|
|
|
|
template<typename... Args>
|
|
|
ASMJIT_INLINE_NODEBUG Vec newVecD(Args&&... args) { return _newRegInternal<Vec>(TypeId::kFloat64, std::forward<Args>(args)...); }
|
|
|
|
|
|
template<typename... Args>
|
|
|
ASMJIT_INLINE_NODEBUG Vec newVecQ(Args&&... args) { return _newRegInternal<Vec>(TypeId::kUInt8x16, std::forward<Args>(args)...); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Mem newStack(uint32_t size, uint32_t alignment, const char* name = nullptr) {
|
|
|
Mem m(Globals::NoInit);
|
|
|
_newStack(&m, size, alignment, name);
|
|
|
return m;
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Mem newConst(ConstPoolScope scope, const void* data, size_t size) {
|
|
|
Mem m(Globals::NoInit);
|
|
|
_newConst(&m, scope, data, size);
|
|
|
return m;
|
|
|
}
|
|
|
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Mem newByteConst(ConstPoolScope scope, uint8_t val) noexcept { return newConst(scope, &val, 1); }
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Mem newHWordConst(ConstPoolScope scope, uint16_t val) noexcept { return newConst(scope, &val, 2); }
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Mem newWordConst(ConstPoolScope scope, uint32_t val) noexcept { return newConst(scope, &val, 4); }
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Mem newDWordConst(ConstPoolScope scope, uint64_t val) noexcept { return newConst(scope, &val, 8); }
|
|
|
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Mem newInt16Const(ConstPoolScope scope, int16_t val) noexcept { return newConst(scope, &val, 2); }
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Mem newUInt16Const(ConstPoolScope scope, uint16_t val) noexcept { return newConst(scope, &val, 2); }
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Mem newInt32Const(ConstPoolScope scope, int32_t val) noexcept { return newConst(scope, &val, 4); }
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Mem newUInt32Const(ConstPoolScope scope, uint32_t val) noexcept { return newConst(scope, &val, 4); }
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Mem newInt64Const(ConstPoolScope scope, int64_t val) noexcept { return newConst(scope, &val, 8); }
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Mem newUInt64Const(ConstPoolScope scope, uint64_t val) noexcept { return newConst(scope, &val, 8); }
|
|
|
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Mem newFloatConst(ConstPoolScope scope, float val) noexcept { return newConst(scope, &val, 4); }
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Mem newDoubleConst(ConstPoolScope scope, double val) noexcept { return newConst(scope, &val, 8); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Compiler& unfollow() noexcept { _instOptions |= InstOptions::kUnfollow; return *this; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Error loadAddressOf(const Gp& o0, const Mem& o1) { return _emitter()->_emitI(Inst::kIdAdr, o0, o1); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Error invoke_(InvokeNode** out, const Operand_& target, const FuncSignature& signature) {
|
|
|
return addInvokeNode(out, Inst::kIdBlr, target, signature);
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, const Gp& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, const Mem& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, const Label& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, const Imm& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, uint64_t target, const FuncSignature& signature) { return invoke_(out, Imm(int64_t(target)), signature); }
|
|
|
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Error ret() { return addRet(Operand(), Operand()); }
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Error ret(const BaseReg& o0) { return addRet(o0, Operand()); }
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Error ret(const BaseReg& o0, const BaseReg& o1) { return addRet(o0, o1); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
using EmitterExplicitT<Compiler>::br;
|
|
|
|
|
|
|
|
|
ASMJIT_INLINE_NODEBUG Error br(const BaseReg& target, JumpAnnotation* annotation) { return emitAnnotatedJump(Inst::kIdBr, target, annotation); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ASMJIT_API Error onAttach(CodeHolder* code) noexcept override;
|
|
|
ASMJIT_API Error onDetach(CodeHolder* code) noexcept override;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ASMJIT_API Error finalize() override;
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
ASMJIT_END_SUB_NAMESPACE
|
|
|
|
|
|
#endif
|
|
|
#endif
|
|
|
|