160 lines
4.2 KiB
C++
160 lines
4.2 KiB
C++
#include "emitter.h"
|
|
|
|
ASMJIT_BEGIN_NAMESPACE
|
|
|
|
// BaseEmitter - Construction & Destruction
|
|
// ========================================
|
|
|
|
BaseEmitter::BaseEmitter(EmitterType emitterType) noexcept
|
|
: _emitterType(emitterType) {}
|
|
|
|
BaseEmitter::~BaseEmitter() noexcept {
|
|
if (_code) {
|
|
_addEmitterFlags(EmitterFlags::kDestroyed);
|
|
_code->detach(this);
|
|
}
|
|
}
|
|
|
|
// BaseEmitter - Finalize
|
|
// ======================
|
|
|
|
Error BaseEmitter::finalize() {
|
|
// Does nothing by default, overridden by `BaseBuilder` and `BaseCompiler`.
|
|
return kErrorOk;
|
|
}
|
|
|
|
// BaseEmitter - Internals
|
|
// =======================
|
|
|
|
static constexpr EmitterFlags kEmitterPreservedFlags = EmitterFlags::kOwnLogger | EmitterFlags::kOwnErrorHandler;
|
|
|
|
static ASMJIT_NOINLINE void BaseEmitter_updateForcedOptions(BaseEmitter* self) noexcept {
|
|
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 (emitComments)
|
|
self->_addEmitterFlags(EmitterFlags::kLogComments);
|
|
else
|
|
self->_clearEmitterFlags(EmitterFlags::kLogComments);
|
|
|
|
// 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;
|
|
}
|
|
|
|
|
|
// BaseEmitter - Logging
|
|
// =====================
|
|
|
|
void BaseEmitter::setLogger(Logger* logger) noexcept {
|
|
#ifndef ASMJIT_NO_LOGGING
|
|
if (logger) {
|
|
_logger = logger;
|
|
_addEmitterFlags(EmitterFlags::kOwnLogger);
|
|
}
|
|
else {
|
|
_logger = nullptr;
|
|
_clearEmitterFlags(EmitterFlags::kOwnLogger);
|
|
if (_code)
|
|
_logger = _code->logger();
|
|
}
|
|
BaseEmitter_updateForcedOptions(this);
|
|
#else
|
|
DebugUtils::unused(logger);
|
|
#endif
|
|
}
|
|
|
|
// BaseEmitter - Error Handling
|
|
// ============================
|
|
|
|
void BaseEmitter::setErrorHandler(ErrorHandler* errorHandler) noexcept {
|
|
if (errorHandler) {
|
|
_errorHandler = errorHandler;
|
|
_addEmitterFlags(EmitterFlags::kOwnErrorHandler);
|
|
}
|
|
else {
|
|
_errorHandler = nullptr;
|
|
_clearEmitterFlags(EmitterFlags::kOwnErrorHandler);
|
|
if (_code)
|
|
_errorHandler = _code->errorHandler();
|
|
}
|
|
}
|
|
|
|
Error BaseEmitter::reportError(Error err, const char* message) {
|
|
ErrorHandler* eh = _errorHandler;
|
|
if (eh) {
|
|
if (!message)
|
|
message = DebugUtils::errorAsString(err);
|
|
eh->handleError(err, message, this);
|
|
}
|
|
return err;
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
Error BaseEmitter::onDetach(CodeHolder* code) noexcept {
|
|
DebugUtils::unused(code);
|
|
|
|
if (!hasOwnLogger())
|
|
_logger = nullptr;
|
|
|
|
if (!hasOwnErrorHandler())
|
|
_errorHandler = nullptr;
|
|
|
|
_clearEmitterFlags(~kEmitterPreservedFlags);
|
|
_forcedInstOptions = InstOptions::kReserved;
|
|
_privateData = 0;
|
|
|
|
_environment.reset();
|
|
//_gpSignature.reset();
|
|
|
|
//_instOptions = InstOptions::kNone;
|
|
//_extraReg.reset();
|
|
//_inlineComment = nullptr;
|
|
|
|
return kErrorOk;
|
|
}
|
|
|
|
void BaseEmitter::onSettingsUpdated() noexcept {
|
|
// Only called when attached to CodeHolder by CodeHolder.
|
|
ASMJIT_ASSERT(_code != nullptr);
|
|
|
|
if (!hasOwnLogger())
|
|
_logger = _code->logger();
|
|
|
|
if (!hasOwnErrorHandler())
|
|
_errorHandler = _code->errorHandler();
|
|
|
|
BaseEmitter_updateForcedOptions(this);
|
|
}
|
|
|
|
ASMJIT_END_NAMESPACE
|