Line data Source code
1 : #ifdef __PLUMED_HAS_ASMJIT
2 : // This file is part of AsmJit project <https://asmjit.com>
3 : //
4 : // See asmjit.h or LICENSE.md for license and copyright information
5 : // SPDX-License-Identifier: Zlib
6 :
7 : #include "api-build_p.h"
8 : #include "emitterutils_p.h"
9 : #include "errorhandler.h"
10 : #include "logger.h"
11 : #include "support.h"
12 :
13 : ASMJIT_BEGIN_NAMESPACE
14 :
15 : // BaseEmitter - Construction & Destruction
16 : // ========================================
17 :
18 54984 : BaseEmitter::BaseEmitter(EmitterType emitterType) noexcept
19 54984 : : _emitterType(emitterType) {}
20 :
21 54984 : BaseEmitter::~BaseEmitter() noexcept {
22 54984 : if (_code) {
23 : _addEmitterFlags(EmitterFlags::kDestroyed);
24 54984 : _code->detach(this);
25 : }
26 54984 : }
27 :
28 : // BaseEmitter - Finalize
29 : // ======================
30 :
31 0 : Error BaseEmitter::finalize() {
32 : // Does nothing by default, overridden by `BaseBuilder` and `BaseCompiler`.
33 0 : return kErrorOk;
34 : }
35 :
36 : // BaseEmitter - Internals
37 : // =======================
38 :
39 : static constexpr EmitterFlags kEmitterPreservedFlags = EmitterFlags::kOwnLogger | EmitterFlags::kOwnErrorHandler;
40 :
41 82476 : static ASMJIT_NOINLINE void BaseEmitter_updateForcedOptions(BaseEmitter* self) noexcept {
42 : bool emitComments = false;
43 : bool hasDiagnosticOptions = false;
44 :
45 82476 : if (self->emitterType() == EmitterType::kAssembler) {
46 : // Assembler: Don't emit comments if logger is not attached.
47 54984 : emitComments = self->_code != nullptr && self->_logger != nullptr;
48 : hasDiagnosticOptions = self->hasDiagnosticOption(DiagnosticOptions::kValidateAssembler);
49 : }
50 : else {
51 : // Builder/Compiler: Always emit comments, we cannot assume they won't be used.
52 27492 : emitComments = self->_code != nullptr;
53 : hasDiagnosticOptions = self->hasDiagnosticOption(DiagnosticOptions::kValidateIntermediate);
54 : }
55 :
56 82476 : if (emitComments)
57 : self->_addEmitterFlags(EmitterFlags::kLogComments);
58 : else
59 : self->_clearEmitterFlags(EmitterFlags::kLogComments);
60 :
61 : // The reserved option tells emitter (Assembler/Builder/Compiler) that there may be either a border
62 : // case (CodeHolder not attached, for example) or that logging or validation is required.
63 82476 : if (self->_code == nullptr || self->_logger || hasDiagnosticOptions)
64 : self->_forcedInstOptions |= InstOptions::kReserved;
65 : else
66 : self->_forcedInstOptions &= ~InstOptions::kReserved;
67 82476 : }
68 :
69 : // BaseEmitter - Diagnostic Options
70 : // ================================
71 :
72 27492 : void BaseEmitter::addDiagnosticOptions(DiagnosticOptions options) noexcept {
73 : _diagnosticOptions |= options;
74 27492 : BaseEmitter_updateForcedOptions(this);
75 27492 : }
76 :
77 0 : void BaseEmitter::clearDiagnosticOptions(DiagnosticOptions options) noexcept {
78 : _diagnosticOptions &= ~options;
79 0 : BaseEmitter_updateForcedOptions(this);
80 0 : }
81 :
82 : // BaseEmitter - Logging
83 : // =====================
84 :
85 0 : void BaseEmitter::setLogger(Logger* logger) noexcept {
86 : #ifndef ASMJIT_NO_LOGGING
87 0 : if (logger) {
88 0 : _logger = logger;
89 : _addEmitterFlags(EmitterFlags::kOwnLogger);
90 : }
91 : else {
92 0 : _logger = nullptr;
93 : _clearEmitterFlags(EmitterFlags::kOwnLogger);
94 0 : if (_code)
95 0 : _logger = _code->logger();
96 : }
97 0 : BaseEmitter_updateForcedOptions(this);
98 : #else
99 : DebugUtils::unused(logger);
100 : #endif
101 0 : }
102 :
103 : // BaseEmitter - Error Handling
104 : // ============================
105 :
106 54984 : void BaseEmitter::setErrorHandler(ErrorHandler* errorHandler) noexcept {
107 54984 : if (errorHandler) {
108 27492 : _errorHandler = errorHandler;
109 : _addEmitterFlags(EmitterFlags::kOwnErrorHandler);
110 : }
111 : else {
112 27492 : _errorHandler = nullptr;
113 : _clearEmitterFlags(EmitterFlags::kOwnErrorHandler);
114 27492 : if (_code)
115 27492 : _errorHandler = _code->errorHandler();
116 : }
117 54984 : }
118 :
119 0 : Error BaseEmitter::reportError(Error err, const char* message) {
120 0 : ErrorHandler* eh = _errorHandler;
121 0 : if (eh) {
122 0 : if (!message)
123 0 : message = DebugUtils::errorAsString(err);
124 0 : eh->handleError(err, message, this);
125 : }
126 0 : return err;
127 : }
128 :
129 : // BaseEmitter - Labels
130 : // ====================
131 :
132 0 : Label BaseEmitter::labelByName(const char* name, size_t nameSize, uint32_t parentId) noexcept {
133 0 : return Label(_code ? _code->labelIdByName(name, nameSize, parentId) : Globals::kInvalidId);
134 : }
135 :
136 0 : bool BaseEmitter::isLabelValid(uint32_t labelId) const noexcept {
137 0 : return _code && labelId < _code->labelCount();
138 : }
139 :
140 : // BaseEmitter - Emit (Low-Level)
141 : // ==============================
142 :
143 : using EmitterUtils::noExt;
144 :
145 27492 : Error BaseEmitter::_emitI(InstId instId) {
146 27492 : return _emit(instId, noExt[0], noExt[1], noExt[2], noExt);
147 : }
148 :
149 0 : Error BaseEmitter::_emitI(InstId instId, const Operand_& o0) {
150 0 : return _emit(instId, o0, noExt[1], noExt[2], noExt);
151 : }
152 :
153 219411 : Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1) {
154 219411 : return _emit(instId, o0, o1, noExt[2], noExt);
155 : }
156 :
157 133334 : Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2) {
158 133334 : return _emit(instId, o0, o1, o2, noExt);
159 : }
160 :
161 2133 : Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) {
162 2133 : Operand_ opExt[3] = { o3 };
163 2133 : return _emit(instId, o0, o1, o2, opExt);
164 : }
165 :
166 0 : Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4) {
167 0 : Operand_ opExt[3] = { o3, o4 };
168 0 : return _emit(instId, o0, o1, o2, opExt);
169 : }
170 :
171 0 : Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, const Operand_& o5) {
172 0 : Operand_ opExt[3] = { o3, o4, o5 };
173 0 : return _emit(instId, o0, o1, o2, opExt);
174 : }
175 :
176 0 : Error BaseEmitter::_emitOpArray(InstId instId, const Operand_* operands, size_t opCount) {
177 : const Operand_* op = operands;
178 : Operand_ opExt[3];
179 :
180 0 : switch (opCount) {
181 0 : case 0:
182 0 : return _emit(instId, noExt[0], noExt[1], noExt[2], noExt);
183 :
184 0 : case 1:
185 0 : return _emit(instId, op[0], noExt[1], noExt[2], noExt);
186 :
187 0 : case 2:
188 0 : return _emit(instId, op[0], op[1], noExt[2], noExt);
189 :
190 0 : case 3:
191 0 : return _emit(instId, op[0], op[1], op[2], noExt);
192 :
193 0 : case 4:
194 0 : opExt[0] = op[3];
195 : opExt[1].reset();
196 : opExt[2].reset();
197 0 : return _emit(instId, op[0], op[1], op[2], opExt);
198 :
199 0 : case 5:
200 0 : opExt[0] = op[3];
201 0 : opExt[1] = op[4];
202 : opExt[2].reset();
203 0 : return _emit(instId, op[0], op[1], op[2], opExt);
204 :
205 0 : case 6:
206 0 : return _emit(instId, op[0], op[1], op[2], op + 3);
207 :
208 : default:
209 : return DebugUtils::errored(kErrorInvalidArgument);
210 : }
211 : }
212 :
213 : // BaseEmitter - Emit Utilities
214 : // ============================
215 :
216 27492 : Error BaseEmitter::emitProlog(const FuncFrame& frame) {
217 27492 : if (ASMJIT_UNLIKELY(!_code))
218 : return DebugUtils::errored(kErrorNotInitialized);
219 :
220 27492 : return _funcs.emitProlog(this, frame);
221 : }
222 :
223 27492 : Error BaseEmitter::emitEpilog(const FuncFrame& frame) {
224 27492 : if (ASMJIT_UNLIKELY(!_code))
225 : return DebugUtils::errored(kErrorNotInitialized);
226 :
227 27492 : return _funcs.emitEpilog(this, frame);
228 : }
229 :
230 0 : Error BaseEmitter::emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args) {
231 0 : if (ASMJIT_UNLIKELY(!_code))
232 : return DebugUtils::errored(kErrorNotInitialized);
233 :
234 0 : return _funcs.emitArgsAssignment(this, frame, args);
235 : }
236 :
237 : // BaseEmitter - Comment
238 : // =====================
239 :
240 0 : Error BaseEmitter::commentf(const char* fmt, ...) {
241 0 : if (!hasEmitterFlag(EmitterFlags::kLogComments)) {
242 0 : if (!hasEmitterFlag(EmitterFlags::kAttached))
243 0 : return reportError(DebugUtils::errored(kErrorNotInitialized));
244 : return kErrorOk;
245 : }
246 :
247 : #ifndef ASMJIT_NO_LOGGING
248 : StringTmp<1024> sb;
249 :
250 : va_list ap;
251 0 : va_start(ap, fmt);
252 : Error err = sb.appendVFormat(fmt, ap);
253 0 : va_end(ap);
254 :
255 0 : ASMJIT_PROPAGATE(err);
256 0 : return comment(sb.data(), sb.size());
257 : #else
258 : DebugUtils::unused(fmt);
259 : return kErrorOk;
260 : #endif
261 : }
262 :
263 0 : Error BaseEmitter::commentv(const char* fmt, va_list ap) {
264 0 : if (!hasEmitterFlag(EmitterFlags::kLogComments)) {
265 0 : if (!hasEmitterFlag(EmitterFlags::kAttached))
266 0 : return reportError(DebugUtils::errored(kErrorNotInitialized));
267 : return kErrorOk;
268 : }
269 :
270 : #ifndef ASMJIT_NO_LOGGING
271 : StringTmp<1024> sb;
272 : Error err = sb.appendVFormat(fmt, ap);
273 :
274 0 : ASMJIT_PROPAGATE(err);
275 0 : return comment(sb.data(), sb.size());
276 : #else
277 : DebugUtils::unused(fmt, ap);
278 : return kErrorOk;
279 : #endif
280 : }
281 :
282 : // BaseEmitter - Events
283 : // ====================
284 :
285 54984 : Error BaseEmitter::onAttach(CodeHolder* code) noexcept {
286 54984 : _code = code;
287 54984 : _environment = code->environment();
288 : _addEmitterFlags(EmitterFlags::kAttached);
289 :
290 : const ArchTraits& archTraits = ArchTraits::byArch(code->arch());
291 54984 : RegType nativeRegType = Environment::is32Bit(code->arch()) ? RegType::kGp32 : RegType::kGp64;
292 54984 : _gpSignature = archTraits.regTypeToSignature(nativeRegType);
293 :
294 54984 : onSettingsUpdated();
295 54984 : return kErrorOk;
296 : }
297 :
298 0 : Error BaseEmitter::onDetach(CodeHolder* code) noexcept {
299 : DebugUtils::unused(code);
300 :
301 0 : if (!hasOwnLogger())
302 0 : _logger = nullptr;
303 :
304 0 : if (!hasOwnErrorHandler())
305 0 : _errorHandler = nullptr;
306 :
307 : _clearEmitterFlags(~kEmitterPreservedFlags);
308 0 : _forcedInstOptions = InstOptions::kReserved;
309 0 : _privateData = 0;
310 :
311 : _environment.reset();
312 : _gpSignature.reset();
313 :
314 0 : _instOptions = InstOptions::kNone;
315 : _extraReg.reset();
316 0 : _inlineComment = nullptr;
317 :
318 0 : return kErrorOk;
319 : }
320 :
321 54984 : void BaseEmitter::onSettingsUpdated() noexcept {
322 : // Only called when attached to CodeHolder by CodeHolder.
323 : ASMJIT_ASSERT(_code != nullptr);
324 :
325 54984 : if (!hasOwnLogger())
326 54984 : _logger = _code->logger();
327 :
328 54984 : if (!hasOwnErrorHandler())
329 54984 : _errorHandler = _code->errorHandler();
330 :
331 54984 : BaseEmitter_updateForcedOptions(this);
332 54984 : }
333 :
334 : ASMJIT_END_NAMESPACE
335 :
336 : #endif // __PLUMED_HAS_ASMJIT
|