BaseEmitter::commentf() shouldn't format string, which will be discarded by the emitter (fixes #306)

This commit is contained in:
kobalicek
2021-01-26 14:27:57 +01:00
parent 6678143772
commit 71fb24cb11
4 changed files with 61 additions and 32 deletions

View File

@@ -1307,7 +1307,7 @@ namespace asmjit {
//! invoking functions. At the moment it's the easiest way of generating code //! 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 //! in AsmJit as most architecture and OS specifics is properly abstracted and
//! handled by AsmJit automatically. However, abstractions also mean restrictions, //! 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. //! or \ref BaseBuilder.
//! //!
//! Since \ref BaseCompiler provides register allocation it also establishes the //! Since \ref BaseCompiler provides register allocation it also establishes the

View File

@@ -366,20 +366,23 @@ Error BaseAssembler::embedLabelDelta(const Label& label, const Label& base, size
// ============================================================================ // ============================================================================
Error BaseAssembler::comment(const char* data, size_t size) { Error BaseAssembler::comment(const char* data, size_t size) {
if (ASMJIT_UNLIKELY(!_code)) if (!hasEmitterFlag(kFlagLogComments)) {
return reportError(DebugUtils::errored(kErrorNotInitialized)); if (!hasEmitterFlag(kFlagAttached))
return reportError(DebugUtils::errored(kErrorNotInitialized));
#ifndef ASMJIT_NO_LOGGING
if (_logger) {
_logger->log(data, size);
_logger->log("\n", 1);
return kErrorOk; 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 #else
DebugUtils::unused(data, size); DebugUtils::unused(data, size);
#endif
return kErrorOk; return kErrorOk;
#endif
} }
// ============================================================================ // ============================================================================

View File

@@ -66,22 +66,35 @@ Error BaseEmitter::finalize() {
// [asmjit::BaseEmitter - Internals] // [asmjit::BaseEmitter - Internals]
// ============================================================================ // ============================================================================
static constexpr uint32_t kEmitterPreservedFlags = static constexpr uint32_t kEmitterPreservedFlags = BaseEmitter::kFlagOwnLogger | BaseEmitter::kFlagOwnErrorHandler;
BaseEmitter::kFlagOwnLogger |
BaseEmitter::kFlagOwnErrorHandler ;
static ASMJIT_NOINLINE void BaseEmitter_updateForcedOptions(BaseEmitter* self) noexcept { static ASMJIT_NOINLINE void BaseEmitter_updateForcedOptions(BaseEmitter* self) noexcept {
bool hasLogger = self->_logger != nullptr; bool emitComments = false;
bool hasValidationOptions; 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); 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); hasValidationOptions = self->hasValidationOption(BaseEmitter::kValidationOptionIntermediate);
}
self->_forcedInstOptions &= ~BaseInst::kOptionReserved; if (emitComments)
if (hasLogger || hasValidationOptions) 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; 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, ...) { Error BaseEmitter::commentf(const char* fmt, ...) {
if (ASMJIT_UNLIKELY(!_code)) if (!hasEmitterFlag(kFlagLogComments)) {
return DebugUtils::errored(kErrorNotInitialized); if (!hasEmitterFlag(kFlagAttached))
return reportError(DebugUtils::errored(kErrorNotInitialized));
return kErrorOk;
}
#ifndef ASMJIT_NO_LOGGING #ifndef ASMJIT_NO_LOGGING
StringTmp<1024> sb;
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
Error err = commentv(fmt, ap); Error err = sb.appendVFormat(fmt, ap);
va_end(ap); va_end(ap);
return err;
ASMJIT_PROPAGATE(err);
return comment(sb.data(), sb.size());
#else #else
DebugUtils::unused(fmt); DebugUtils::unused(fmt);
return kErrorOk; return kErrorOk;
@@ -322,16 +342,17 @@ Error BaseEmitter::commentf(const char* fmt, ...) {
} }
Error BaseEmitter::commentv(const char* fmt, va_list ap) { Error BaseEmitter::commentv(const char* fmt, va_list ap) {
if (ASMJIT_UNLIKELY(!_code)) if (!hasEmitterFlag(kFlagLogComments)) {
return DebugUtils::errored(kErrorNotInitialized); if (!hasEmitterFlag(kFlagAttached))
return reportError(DebugUtils::errored(kErrorNotInitialized));
return kErrorOk;
}
#ifndef ASMJIT_NO_LOGGING #ifndef ASMJIT_NO_LOGGING
StringTmp<1024> sb; StringTmp<1024> sb;
Error err = sb.appendVFormat(fmt, ap); Error err = sb.appendVFormat(fmt, ap);
if (ASMJIT_UNLIKELY(err)) ASMJIT_PROPAGATE(err);
return err;
return comment(sb.data(), sb.size()); return comment(sb.data(), sb.size());
#else #else
DebugUtils::unused(fmt, ap); DebugUtils::unused(fmt, ap);
@@ -346,6 +367,7 @@ Error BaseEmitter::commentv(const char* fmt, va_list ap) {
Error BaseEmitter::onAttach(CodeHolder* code) noexcept { Error BaseEmitter::onAttach(CodeHolder* code) noexcept {
_code = code; _code = code;
_environment = code->environment(); _environment = code->environment();
_addEmitterFlags(kFlagAttached);
const ArchTraits& archTraits = ArchTraits::byArch(code->arch()); const ArchTraits& archTraits = ArchTraits::byArch(code->arch());
uint32_t nativeRegType = Environment::is32Bit(code->arch()) ? BaseReg::kTypeGp32 : BaseReg::kTypeGp64; 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 { Error BaseEmitter::onDetach(CodeHolder* code) noexcept {
DebugUtils::unused(code); DebugUtils::unused(code);
_clearEmitterFlags(~kEmitterPreservedFlags);
_forcedInstOptions = BaseInst::kOptionReserved;
_privateData = 0;
if (!hasOwnLogger()) if (!hasOwnLogger())
_logger = nullptr; _logger = nullptr;
if (!hasOwnErrorHandler()) if (!hasOwnErrorHandler())
_errorHandler = nullptr; _errorHandler = nullptr;
_clearEmitterFlags(~kEmitterPreservedFlags);
_forcedInstOptions = BaseInst::kOptionReserved;
_privateData = 0;
_environment.reset(); _environment.reset();
_gpRegInfo.reset(); _gpRegInfo.reset();

View File

@@ -109,6 +109,10 @@ public:
//! Emitter flags. //! Emitter flags.
enum EmitterFlags : uint32_t { 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). //! The emitter has its own \ref Logger (not propagated from \ref CodeHolder).
kFlagOwnLogger = 0x10u, kFlagOwnLogger = 0x10u,
//! The emitter has its own \ref ErrorHandler (not propagated from \ref CodeHolder). //! The emitter has its own \ref ErrorHandler (not propagated from \ref CodeHolder).