summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/asmjit/src/asmjit/core/emitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/asmjit/src/asmjit/core/emitter.cpp')
-rw-r--r--3rdparty/asmjit/src/asmjit/core/emitter.cpp339
1 files changed, 181 insertions, 158 deletions
diff --git a/3rdparty/asmjit/src/asmjit/core/emitter.cpp b/3rdparty/asmjit/src/asmjit/core/emitter.cpp
index b6ecc3d3cca..4c855ea5688 100644
--- a/3rdparty/asmjit/src/asmjit/core/emitter.cpp
+++ b/3rdparty/asmjit/src/asmjit/core/emitter.cpp
@@ -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
#include "../core/api-build_p.h"
#include "../core/emitterutils_p.h"
@@ -27,104 +9,87 @@
#include "../core/logger.h"
#include "../core/support.h"
-#ifdef ASMJIT_BUILD_X86
- #include "../x86/x86internal_p.h"
- #include "../x86/x86instdb_p.h"
-#endif // ASMJIT_BUILD_X86
-
-#ifdef ASMJIT_BUILD_ARM
- #include "../arm/arminternal_p.h"
- #include "../arm/arminstdb.h"
-#endif // ASMJIT_BUILD_ARM
-
ASMJIT_BEGIN_NAMESPACE
-// ============================================================================
-// [asmjit::BaseEmitter - Construction / Destruction]
-// ============================================================================
-
-BaseEmitter::BaseEmitter(uint32_t emitterType) noexcept
- : _emitterType(uint8_t(emitterType)),
- _emitterFlags(0),
- _validationFlags(0),
- _validationOptions(0),
- _encodingOptions(0),
- _forcedInstOptions(BaseInst::kOptionReserved),
- _privateData(0),
- _code(nullptr),
- _logger(nullptr),
- _errorHandler(nullptr),
- _environment(),
- _gpRegInfo(),
- _instOptions(0),
- _extraReg(),
- _inlineComment(nullptr) {}
+// BaseEmitter - Construction & Destruction
+// ========================================
+
+BaseEmitter::BaseEmitter(EmitterType emitterType) noexcept
+ : _emitterType(emitterType) {}
BaseEmitter::~BaseEmitter() noexcept {
if (_code) {
- _addEmitterFlags(kFlagDestroyed);
+ _addEmitterFlags(EmitterFlags::kDestroyed);
_code->detach(this);
}
}
-// ============================================================================
-// [asmjit::BaseEmitter - Finalize]
-// ============================================================================
+// BaseEmitter - Finalize
+// ======================
Error BaseEmitter::finalize() {
// Does nothing by default, overridden by `BaseBuilder` and `BaseCompiler`.
return kErrorOk;
}
-// ============================================================================
-// [asmjit::BaseEmitter - Internals]
-// ============================================================================
+// BaseEmitter - Internals
+// =======================
-static constexpr uint32_t kEmitterPreservedFlags =
- BaseEmitter::kFlagOwnLogger |
- BaseEmitter::kFlagOwnErrorHandler ;
+static constexpr EmitterFlags kEmitterPreservedFlags = EmitterFlags::kOwnLogger | EmitterFlags::kOwnErrorHandler;
static ASMJIT_NOINLINE void BaseEmitter_updateForcedOptions(BaseEmitter* self) noexcept {
- bool hasLogger = self->_logger != nullptr;
- bool hasValidationOptions;
+ bool emitComments = false;
+ bool hasDiagnosticOptions = false;
+
+ if (self->emitterType() == EmitterType::kAssembler) {
+ // Assembler: Don't emit comments if logger is not attached.
+ emitComments = self->_code != nullptr && self->_logger != nullptr;
+ hasDiagnosticOptions = self->hasDiagnosticOption(DiagnosticOptions::kValidateAssembler);
+ }
+ else {
+ // Builder/Compiler: Always emit comments, we cannot assume they won't be used.
+ emitComments = self->_code != nullptr;
+ hasDiagnosticOptions = self->hasDiagnosticOption(DiagnosticOptions::kValidateIntermediate);
+ }
- if (self->emitterType() == BaseEmitter::kTypeAssembler)
- hasValidationOptions = self->hasValidationOption(BaseEmitter::kValidationOptionAssembler);
+ if (emitComments)
+ self->_addEmitterFlags(EmitterFlags::kLogComments);
else
- hasValidationOptions = self->hasValidationOption(BaseEmitter::kValidationOptionIntermediate);
+ self->_clearEmitterFlags(EmitterFlags::kLogComments);
- self->_forcedInstOptions &= ~BaseInst::kOptionReserved;
- if (hasLogger || hasValidationOptions)
- self->_forcedInstOptions |= BaseInst::kOptionReserved;
+ // The reserved option tells emitter (Assembler/Builder/Compiler) that there may be either a border
+ // case (CodeHolder not attached, for example) or that logging or validation is required.
+ if (self->_code == nullptr || self->_logger || hasDiagnosticOptions)
+ self->_forcedInstOptions |= InstOptions::kReserved;
+ else
+ self->_forcedInstOptions &= ~InstOptions::kReserved;
}
-// ============================================================================
-// [asmjit::BaseEmitter - Validation Options]
-// ============================================================================
+// BaseEmitter - Diagnostic Options
+// ================================
-void BaseEmitter::addValidationOptions(uint32_t options) noexcept {
- _validationOptions = uint8_t(_validationOptions | options);
+void BaseEmitter::addDiagnosticOptions(DiagnosticOptions options) noexcept {
+ _diagnosticOptions |= options;
BaseEmitter_updateForcedOptions(this);
}
-void BaseEmitter::clearValidationOptions(uint32_t options) noexcept {
- _validationOptions = uint8_t(_validationOptions | options);
+void BaseEmitter::clearDiagnosticOptions(DiagnosticOptions options) noexcept {
+ _diagnosticOptions &= ~options;
BaseEmitter_updateForcedOptions(this);
}
-// ============================================================================
-// [asmjit::BaseEmitter - Logging]
-// ============================================================================
+// BaseEmitter - Logging
+// =====================
void BaseEmitter::setLogger(Logger* logger) noexcept {
#ifndef ASMJIT_NO_LOGGING
if (logger) {
_logger = logger;
- _addEmitterFlags(kFlagOwnLogger);
+ _addEmitterFlags(EmitterFlags::kOwnLogger);
}
else {
_logger = nullptr;
- _clearEmitterFlags(kFlagOwnLogger);
+ _clearEmitterFlags(EmitterFlags::kOwnLogger);
if (_code)
_logger = _code->logger();
}
@@ -134,18 +99,17 @@ void BaseEmitter::setLogger(Logger* logger) noexcept {
#endif
}
-// ============================================================================
-// [asmjit::BaseEmitter - Error Handling]
-// ============================================================================
+// BaseEmitter - Error Handling
+// ============================
void BaseEmitter::setErrorHandler(ErrorHandler* errorHandler) noexcept {
if (errorHandler) {
_errorHandler = errorHandler;
- _addEmitterFlags(kFlagOwnErrorHandler);
+ _addEmitterFlags(EmitterFlags::kOwnErrorHandler);
}
else {
_errorHandler = nullptr;
- _clearEmitterFlags(kFlagOwnErrorHandler);
+ _clearEmitterFlags(EmitterFlags::kOwnErrorHandler);
if (_code)
_errorHandler = _code->errorHandler();
}
@@ -161,58 +125,87 @@ Error BaseEmitter::reportError(Error err, const char* message) {
return err;
}
-// ============================================================================
-// [asmjit::BaseEmitter - Labels]
-// ============================================================================
+// BaseEmitter - Sections
+// ======================
+
+// [[pure virtual]]
+Error BaseEmitter::section(Section* section) {
+ DebugUtils::unused(section);
+ return DebugUtils::errored(kErrorInvalidState);
+}
+
+// BaseEmitter - Labels
+// ====================
+
+// [[pure virtual]]
+Label BaseEmitter::newLabel() {
+ return Label(Globals::kInvalidId);
+}
+
+// [[pure virtual]]
+Label BaseEmitter::newNamedLabel(const char* name, size_t nameSize, LabelType type, uint32_t parentId) {
+ DebugUtils::unused(name, nameSize, type, parentId);
+ return Label(Globals::kInvalidId);
+}
Label BaseEmitter::labelByName(const char* name, size_t nameSize, uint32_t parentId) noexcept {
- return Label(_code ? _code->labelIdByName(name, nameSize, parentId) : uint32_t(Globals::kInvalidId));
+ return Label(_code ? _code->labelIdByName(name, nameSize, parentId) : Globals::kInvalidId);
+}
+
+// [[pure virtual]]
+Error BaseEmitter::bind(const Label& label) {
+ DebugUtils::unused(label);
+ return DebugUtils::errored(kErrorInvalidState);
}
bool BaseEmitter::isLabelValid(uint32_t labelId) const noexcept {
return _code && labelId < _code->labelCount();
}
-// ============================================================================
-// [asmjit::BaseEmitter - Emit (Low-Level)]
-// ============================================================================
+// BaseEmitter - Emit (Low-Level)
+// ==============================
using EmitterUtils::noExt;
-Error BaseEmitter::_emitI(uint32_t instId) {
+Error BaseEmitter::_emitI(InstId instId) {
return _emit(instId, noExt[0], noExt[1], noExt[2], noExt);
}
-Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0) {
+Error BaseEmitter::_emitI(InstId instId, const Operand_& o0) {
return _emit(instId, o0, noExt[1], noExt[2], noExt);
}
-Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1) {
+Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1) {
return _emit(instId, o0, o1, noExt[2], noExt);
}
-Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2) {
+Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2) {
return _emit(instId, o0, o1, o2, noExt);
}
-Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) {
+Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) {
Operand_ opExt[3] = { o3 };
return _emit(instId, o0, o1, o2, opExt);
}
-Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4) {
+Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4) {
Operand_ opExt[3] = { o3, o4 };
return _emit(instId, o0, o1, o2, opExt);
}
-Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, const Operand_& o5) {
+Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, const Operand_& o5) {
Operand_ opExt[3] = { o3, o4, o5 };
return _emit(instId, o0, o1, o2, opExt);
}
-Error BaseEmitter::_emitOpArray(uint32_t instId, const Operand_* operands, size_t opCount) {
- const Operand_* op = operands;
+// [[pure virtual]]
+Error BaseEmitter::_emit(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* oExt) {
+ DebugUtils::unused(instId, o0, o1, o2, oExt);
+ return DebugUtils::errored(kErrorInvalidState);
+}
+Error BaseEmitter::_emitOpArray(InstId instId, const Operand_* operands, size_t opCount) {
+ const Operand_* op = operands;
Operand_ opExt[3];
switch (opCount) {
@@ -248,75 +241,98 @@ Error BaseEmitter::_emitOpArray(uint32_t instId, const Operand_* operands, size_
}
}
-// ============================================================================
-// [asmjit::BaseEmitter - Emit (High-Level)]
-// ============================================================================
+// BaseEmitter - Emit Utilities
+// ============================
-ASMJIT_FAVOR_SIZE Error BaseEmitter::emitProlog(const FuncFrame& frame) {
+Error BaseEmitter::emitProlog(const FuncFrame& frame) {
if (ASMJIT_UNLIKELY(!_code))
return DebugUtils::errored(kErrorNotInitialized);
-#ifdef ASMJIT_BUILD_X86
- if (environment().isFamilyX86())
- return x86::X86Internal::emitProlog(as<x86::Emitter>(), frame);
-#endif
+ return _funcs.emitProlog(this, frame);
+}
-#ifdef ASMJIT_BUILD_ARM
- if (environment().isFamilyARM())
- return arm::ArmInternal::emitProlog(as<arm::Emitter>(), frame);
-#endif
+Error BaseEmitter::emitEpilog(const FuncFrame& frame) {
+ if (ASMJIT_UNLIKELY(!_code))
+ return DebugUtils::errored(kErrorNotInitialized);
- return DebugUtils::errored(kErrorInvalidArch);
+ return _funcs.emitEpilog(this, frame);
}
-ASMJIT_FAVOR_SIZE Error BaseEmitter::emitEpilog(const FuncFrame& frame) {
+Error BaseEmitter::emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args) {
if (ASMJIT_UNLIKELY(!_code))
return DebugUtils::errored(kErrorNotInitialized);
-#ifdef ASMJIT_BUILD_X86
- if (environment().isFamilyX86())
- return x86::X86Internal::emitEpilog(as<x86::Emitter>(), frame);
-#endif
+ return _funcs.emitArgsAssignment(this, frame, args);
+}
-#ifdef ASMJIT_BUILD_ARM
- if (environment().isFamilyARM())
- return arm::ArmInternal::emitEpilog(as<arm::Emitter>(), frame);
-#endif
+// BaseEmitter - Align
+// ===================
- return DebugUtils::errored(kErrorInvalidArch);
+// [[pure virtual]]
+Error BaseEmitter::align(AlignMode alignMode, uint32_t alignment) {
+ DebugUtils::unused(alignMode, alignment);
+ return DebugUtils::errored(kErrorInvalidState);
}
-ASMJIT_FAVOR_SIZE Error BaseEmitter::emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args) {
- if (ASMJIT_UNLIKELY(!_code))
- return DebugUtils::errored(kErrorNotInitialized);
+// BaseEmitter - Embed
+// ===================
-#ifdef ASMJIT_BUILD_X86
- if (environment().isFamilyX86())
- return x86::X86Internal::emitArgsAssignment(as<x86::Emitter>(), frame, args);
-#endif
+// [[pure virtual]]
+Error BaseEmitter::embed(const void* data, size_t dataSize) {
+ DebugUtils::unused(data, dataSize);
+ return DebugUtils::errored(kErrorInvalidState);
+}
-#ifdef ASMJIT_BUILD_ARM
- if (environment().isFamilyARM())
- return arm::ArmInternal::emitArgsAssignment(as<arm::Emitter>(), frame, args);
-#endif
+// [[pure virtual]]
+Error BaseEmitter::embedDataArray(TypeId typeId, const void* data, size_t itemCount, size_t repeatCount) {
+ DebugUtils::unused(typeId, data, itemCount, repeatCount);
+ return DebugUtils::errored(kErrorInvalidState);
+}
+
+// [[pure virtual]]
+Error BaseEmitter::embedConstPool(const Label& label, const ConstPool& pool) {
+ DebugUtils::unused(label, pool);
+ return DebugUtils::errored(kErrorInvalidState);
+}
- return DebugUtils::errored(kErrorInvalidArch);
+// [[pure virtual]]
+Error BaseEmitter::embedLabel(const Label& label, size_t dataSize) {
+ DebugUtils::unused(label, dataSize);
+ return DebugUtils::errored(kErrorInvalidState);
}
-// ============================================================================
-// [asmjit::BaseEmitter - Comment]
-// ============================================================================
+// [[pure virtual]]
+Error BaseEmitter::embedLabelDelta(const Label& label, const Label& base, size_t dataSize) {
+ DebugUtils::unused(label, base, dataSize);
+ return DebugUtils::errored(kErrorInvalidState);
+}
+
+// BaseEmitter - Comment
+// =====================
+
+// [[pure virtual]]
+Error BaseEmitter::comment(const char* data, size_t size) {
+ DebugUtils::unused(data, size);
+ return DebugUtils::errored(kErrorInvalidState);
+}
Error BaseEmitter::commentf(const char* fmt, ...) {
- if (ASMJIT_UNLIKELY(!_code))
- return DebugUtils::errored(kErrorNotInitialized);
+ if (!hasEmitterFlag(EmitterFlags::kLogComments)) {
+ if (!hasEmitterFlag(EmitterFlags::kAttached))
+ return reportError(DebugUtils::errored(kErrorNotInitialized));
+ return kErrorOk;
+ }
#ifndef ASMJIT_NO_LOGGING
+ StringTmp<1024> sb;
+
va_list ap;
va_start(ap, fmt);
- Error err = commentv(fmt, ap);
+ Error err = sb.appendVFormat(fmt, ap);
va_end(ap);
- return err;
+
+ ASMJIT_PROPAGATE(err);
+ return comment(sb.data(), sb.size());
#else
DebugUtils::unused(fmt);
return kErrorOk;
@@ -324,16 +340,17 @@ Error BaseEmitter::commentf(const char* fmt, ...) {
}
Error BaseEmitter::commentv(const char* fmt, va_list ap) {
- if (ASMJIT_UNLIKELY(!_code))
- return DebugUtils::errored(kErrorNotInitialized);
+ if (!hasEmitterFlag(EmitterFlags::kLogComments)) {
+ if (!hasEmitterFlag(EmitterFlags::kAttached))
+ return reportError(DebugUtils::errored(kErrorNotInitialized));
+ return kErrorOk;
+ }
#ifndef ASMJIT_NO_LOGGING
StringTmp<1024> sb;
Error err = sb.appendVFormat(fmt, ap);
- if (ASMJIT_UNLIKELY(err))
- return err;
-
+ ASMJIT_PROPAGATE(err);
return comment(sb.data(), sb.size());
#else
DebugUtils::unused(fmt, ap);
@@ -341,13 +358,17 @@ Error BaseEmitter::commentv(const char* fmt, va_list ap) {
#endif
}
-// ============================================================================
-// [asmjit::BaseEmitter - Events]
-// ============================================================================
+// BaseEmitter - Events
+// ====================
Error BaseEmitter::onAttach(CodeHolder* code) noexcept {
_code = code;
_environment = code->environment();
+ _addEmitterFlags(EmitterFlags::kAttached);
+
+ const ArchTraits& archTraits = ArchTraits::byArch(code->arch());
+ RegType nativeRegType = Environment::is32Bit(code->arch()) ? RegType::kGp32 : RegType::kGp64;
+ _gpSignature = archTraits.regTypeToSignature(nativeRegType);
onSettingsUpdated();
return kErrorOk;
@@ -356,22 +377,24 @@ Error BaseEmitter::onAttach(CodeHolder* code) noexcept {
Error BaseEmitter::onDetach(CodeHolder* code) noexcept {
DebugUtils::unused(code);
- _clearEmitterFlags(~kEmitterPreservedFlags);
- _forcedInstOptions = BaseInst::kOptionReserved;
- _privateData = 0;
-
if (!hasOwnLogger())
_logger = nullptr;
if (!hasOwnErrorHandler())
_errorHandler = nullptr;
+ _clearEmitterFlags(~kEmitterPreservedFlags);
+ _instructionAlignment = uint8_t(0);
+ _forcedInstOptions = InstOptions::kReserved;
+ _privateData = 0;
+
_environment.reset();
- _gpRegInfo.reset();
+ _gpSignature.reset();
- _instOptions = 0;
+ _instOptions = InstOptions::kNone;
_extraReg.reset();
_inlineComment = nullptr;
+ _funcs.reset();
return kErrorOk;
}