diff options
Diffstat (limited to '3rdparty/asmjit/src/asmjit/core/emitter.cpp')
-rw-r--r-- | 3rdparty/asmjit/src/asmjit/core/emitter.cpp | 339 |
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; } |