diff options
author | kobalicek <kobalicek.petr@gmail.com> | 2021-01-26 16:27:57 +0300 |
---|---|---|
committer | kobalicek <kobalicek.petr@gmail.com> | 2021-01-26 16:28:48 +0300 |
commit | 71fb24cb11801bd462fb5e83bf7a10ab49aa482c (patch) | |
tree | 2a08a433ff43327b72f58e818eea859b3201162f | |
parent | 66781437728ae31001ccafe3baf88bf0342814f6 (diff) |
BaseEmitter::commentf() shouldn't format string, which will be discarded by the emitter (fixes #306)
-rw-r--r-- | src/asmjit/core.h | 2 | ||||
-rw-r--r-- | src/asmjit/core/assembler.cpp | 21 | ||||
-rw-r--r-- | src/asmjit/core/emitter.cpp | 66 | ||||
-rw-r--r-- | src/asmjit/core/emitter.h | 4 |
4 files changed, 61 insertions, 32 deletions
diff --git a/src/asmjit/core.h b/src/asmjit/core.h index 3b50c65..52540ab 100644 --- a/src/asmjit/core.h +++ b/src/asmjit/core.h @@ -1307,7 +1307,7 @@ namespace asmjit { //! invoking functions. At the moment it's the easiest way of generating code //! in AsmJit as most architecture and OS specifics is properly abstracted and //! handled by AsmJit automatically. However, abstractions also mean restrictions, -//! which means that \ref BaseCompiler has more limitations that \ref BaseAssembler +//! which means that \ref BaseCompiler has more limitations than \ref BaseAssembler //! or \ref BaseBuilder. //! //! Since \ref BaseCompiler provides register allocation it also establishes the diff --git a/src/asmjit/core/assembler.cpp b/src/asmjit/core/assembler.cpp index 4cf706f..c0cbf0f 100644 --- a/src/asmjit/core/assembler.cpp +++ b/src/asmjit/core/assembler.cpp @@ -366,20 +366,23 @@ Error BaseAssembler::embedLabelDelta(const Label& label, const Label& base, size // ============================================================================ Error BaseAssembler::comment(const char* data, size_t size) { - if (ASMJIT_UNLIKELY(!_code)) - return reportError(DebugUtils::errored(kErrorNotInitialized)); - -#ifndef ASMJIT_NO_LOGGING - if (_logger) { - _logger->log(data, size); - _logger->log("\n", 1); + if (!hasEmitterFlag(kFlagLogComments)) { + if (!hasEmitterFlag(kFlagAttached)) + return reportError(DebugUtils::errored(kErrorNotInitialized)); return kErrorOk; } + +#ifndef ASMJIT_NO_LOGGING + // Logger cannot be NULL if `kFlagLogComments` is set. + ASMJIT_ASSERT(_logger != nullptr); + + _logger->log(data, size); + _logger->log("\n", 1); + return kErrorOk; #else DebugUtils::unused(data, size); -#endif - return kErrorOk; +#endif } // ============================================================================ diff --git a/src/asmjit/core/emitter.cpp b/src/asmjit/core/emitter.cpp index 23ac3b3..f684140 100644 --- a/src/asmjit/core/emitter.cpp +++ b/src/asmjit/core/emitter.cpp @@ -66,22 +66,35 @@ Error BaseEmitter::finalize() { // [asmjit::BaseEmitter - Internals] // ============================================================================ -static constexpr uint32_t kEmitterPreservedFlags = - BaseEmitter::kFlagOwnLogger | - BaseEmitter::kFlagOwnErrorHandler ; +static constexpr uint32_t kEmitterPreservedFlags = BaseEmitter::kFlagOwnLogger | BaseEmitter::kFlagOwnErrorHandler; static ASMJIT_NOINLINE void BaseEmitter_updateForcedOptions(BaseEmitter* self) noexcept { - bool hasLogger = self->_logger != nullptr; - bool hasValidationOptions; + bool emitComments = false; + bool hasValidationOptions = false; - if (self->emitterType() == BaseEmitter::kTypeAssembler) + if (self->emitterType() == BaseEmitter::kTypeAssembler) { + // Assembler: Don't emit comments if logger is not attached. + emitComments = self->_code != nullptr && self->_logger != nullptr; hasValidationOptions = self->hasValidationOption(BaseEmitter::kValidationOptionAssembler); - else + } + else { + // Builder/Compiler: Always emit comments, we cannot assume they won't be used. + emitComments = self->_code != nullptr; hasValidationOptions = self->hasValidationOption(BaseEmitter::kValidationOptionIntermediate); + } - self->_forcedInstOptions &= ~BaseInst::kOptionReserved; - if (hasLogger || hasValidationOptions) + if (emitComments) + self->_addEmitterFlags(BaseEmitter::kFlagLogComments); + else + self->_clearEmitterFlags(BaseEmitter::kFlagLogComments); + + // 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 || hasValidationOptions) self->_forcedInstOptions |= BaseInst::kOptionReserved; + else + self->_forcedInstOptions &= ~BaseInst::kOptionReserved; } // ============================================================================ @@ -306,15 +319,22 @@ ASMJIT_FAVOR_SIZE Error BaseEmitter::emitArgsAssignment(const FuncFrame& frame, // ============================================================================ Error BaseEmitter::commentf(const char* fmt, ...) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); + if (!hasEmitterFlag(kFlagLogComments)) { + if (!hasEmitterFlag(kFlagAttached)) + 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; @@ -322,16 +342,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(kFlagLogComments)) { + if (!hasEmitterFlag(kFlagAttached)) + 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); @@ -346,6 +367,7 @@ Error BaseEmitter::commentv(const char* fmt, va_list ap) { Error BaseEmitter::onAttach(CodeHolder* code) noexcept { _code = code; _environment = code->environment(); + _addEmitterFlags(kFlagAttached); const ArchTraits& archTraits = ArchTraits::byArch(code->arch()); uint32_t nativeRegType = Environment::is32Bit(code->arch()) ? BaseReg::kTypeGp32 : BaseReg::kTypeGp64; @@ -358,16 +380,16 @@ 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); + _forcedInstOptions = BaseInst::kOptionReserved; + _privateData = 0; + _environment.reset(); _gpRegInfo.reset(); diff --git a/src/asmjit/core/emitter.h b/src/asmjit/core/emitter.h index 51651fd..fcb9bb5 100644 --- a/src/asmjit/core/emitter.h +++ b/src/asmjit/core/emitter.h @@ -109,6 +109,10 @@ public: //! Emitter flags. enum EmitterFlags : uint32_t { + //! Emitter is attached to CodeHolder. + kFlagAttached = 0x01u, + //! The emitter must emit comments. + kFlagLogComments = 0x08u, //! The emitter has its own \ref Logger (not propagated from \ref CodeHolder). kFlagOwnLogger = 0x10u, //! The emitter has its own \ref ErrorHandler (not propagated from \ref CodeHolder). |