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 "assembler.h"
9 : #include "codewriter_p.h"
10 : #include "constpool.h"
11 : #include "emitterutils_p.h"
12 : #include "formatter.h"
13 : #include "logger.h"
14 : #include "support.h"
15 :
16 : ASMJIT_BEGIN_NAMESPACE
17 :
18 : // BaseAssembler - Construction & Destruction
19 : // ==========================================
20 :
21 27492 : BaseAssembler::BaseAssembler() noexcept
22 27492 : : BaseEmitter(EmitterType::kAssembler) {}
23 :
24 27492 : BaseAssembler::~BaseAssembler() noexcept {}
25 :
26 : // BaseAssembler - Buffer Management
27 : // =================================
28 :
29 0 : Error BaseAssembler::setOffset(size_t offset) {
30 0 : if (ASMJIT_UNLIKELY(!_code))
31 0 : return reportError(DebugUtils::errored(kErrorNotInitialized));
32 :
33 0 : size_t size = Support::max<size_t>(_section->bufferSize(), this->offset());
34 0 : if (ASMJIT_UNLIKELY(offset > size))
35 0 : return reportError(DebugUtils::errored(kErrorInvalidArgument));
36 :
37 0 : _bufferPtr = _bufferData + offset;
38 0 : return kErrorOk;
39 : }
40 :
41 : // BaseAssembler - Section Management
42 : // ==================================
43 :
44 54984 : static void BaseAssembler_initSection(BaseAssembler* self, Section* section) noexcept {
45 54984 : uint8_t* p = section->_buffer._data;
46 :
47 54984 : self->_section = section;
48 54984 : self->_bufferData = p;
49 54984 : self->_bufferPtr = p + section->_buffer._size;
50 54984 : self->_bufferEnd = p + section->_buffer._capacity;
51 54984 : }
52 :
53 27492 : Error BaseAssembler::section(Section* section) {
54 27492 : if (ASMJIT_UNLIKELY(!_code))
55 0 : return reportError(DebugUtils::errored(kErrorNotInitialized));
56 :
57 27492 : if (!_code->isSectionValid(section->id()) || _code->_sections[section->id()] != section)
58 0 : return reportError(DebugUtils::errored(kErrorInvalidSection));
59 :
60 : #ifndef ASMJIT_NO_LOGGING
61 27492 : if (_logger)
62 0 : _logger->logf(".section %s {#%u}\n", section->name(), section->id());
63 : #endif
64 :
65 27492 : BaseAssembler_initSection(this, section);
66 27492 : return kErrorOk;
67 : }
68 :
69 : // BaseAssembler - Label Management
70 : // ================================
71 :
72 0 : Label BaseAssembler::newLabel() {
73 : uint32_t labelId = Globals::kInvalidId;
74 0 : if (ASMJIT_LIKELY(_code)) {
75 : LabelEntry* le;
76 0 : Error err = _code->newLabelEntry(&le);
77 0 : if (ASMJIT_UNLIKELY(err))
78 0 : reportError(err);
79 : else
80 0 : labelId = le->id();
81 : }
82 0 : return Label(labelId);
83 : }
84 :
85 0 : Label BaseAssembler::newNamedLabel(const char* name, size_t nameSize, LabelType type, uint32_t parentId) {
86 : uint32_t labelId = Globals::kInvalidId;
87 0 : if (ASMJIT_LIKELY(_code)) {
88 : LabelEntry* le;
89 0 : Error err = _code->newNamedLabelEntry(&le, name, nameSize, type, parentId);
90 0 : if (ASMJIT_UNLIKELY(err))
91 0 : reportError(err);
92 : else
93 0 : labelId = le->id();
94 : }
95 0 : return Label(labelId);
96 : }
97 :
98 54984 : Error BaseAssembler::bind(const Label& label) {
99 54984 : if (ASMJIT_UNLIKELY(!_code))
100 0 : return reportError(DebugUtils::errored(kErrorNotInitialized));
101 :
102 54984 : Error err = _code->bindLabel(label, _section->id(), offset());
103 :
104 : #ifndef ASMJIT_NO_LOGGING
105 54984 : if (_logger)
106 0 : EmitterUtils::logLabelBound(this, label);
107 : #endif
108 :
109 : resetInlineComment();
110 54984 : if (err)
111 0 : return reportError(err);
112 :
113 : return kErrorOk;
114 : }
115 :
116 : // BaseAssembler - Embed
117 : // =====================
118 :
119 0 : Error BaseAssembler::embed(const void* data, size_t dataSize) {
120 0 : if (ASMJIT_UNLIKELY(!_code))
121 0 : return reportError(DebugUtils::errored(kErrorNotInitialized));
122 :
123 0 : if (dataSize == 0)
124 : return kErrorOk;
125 :
126 : CodeWriter writer(this);
127 0 : ASMJIT_PROPAGATE(writer.ensureSpace(this, dataSize));
128 :
129 : writer.emitData(data, dataSize);
130 : writer.done(this);
131 :
132 : #ifndef ASMJIT_NO_LOGGING
133 0 : if (_logger) {
134 : StringTmp<512> sb;
135 0 : Formatter::formatData(sb, _logger->flags(), arch(), TypeId::kUInt8, data, dataSize, 1);
136 : sb.append('\n');
137 0 : _logger->log(sb);
138 : }
139 : #endif
140 :
141 : return kErrorOk;
142 : }
143 :
144 0 : Error BaseAssembler::embedDataArray(TypeId typeId, const void* data, size_t itemCount, size_t repeatCount) {
145 : uint32_t deabstractDelta = TypeUtils::deabstractDeltaOfSize(registerSize());
146 : TypeId finalTypeId = TypeUtils::deabstract(typeId, deabstractDelta);
147 :
148 0 : if (ASMJIT_UNLIKELY(!TypeUtils::isValid(finalTypeId)))
149 0 : return reportError(DebugUtils::errored(kErrorInvalidArgument));
150 :
151 0 : if (itemCount == 0 || repeatCount == 0)
152 : return kErrorOk;
153 :
154 : uint32_t typeSize = TypeUtils::sizeOf(finalTypeId);
155 : Support::FastUInt8 of = 0;
156 :
157 : size_t dataSize = Support::mulOverflow(itemCount, size_t(typeSize), &of);
158 : size_t totalSize = Support::mulOverflow(dataSize, repeatCount, &of);
159 :
160 0 : if (ASMJIT_UNLIKELY(of))
161 0 : return reportError(DebugUtils::errored(kErrorOutOfMemory));
162 :
163 : CodeWriter writer(this);
164 0 : ASMJIT_PROPAGATE(writer.ensureSpace(this, totalSize));
165 :
166 0 : for (size_t i = 0; i < repeatCount; i++)
167 : writer.emitData(data, dataSize);
168 :
169 : writer.done(this);
170 :
171 : #ifndef ASMJIT_NO_LOGGING
172 0 : if (_logger) {
173 : StringTmp<512> sb;
174 0 : Formatter::formatData(sb, _logger->flags(), arch(), typeId, data, itemCount, repeatCount);
175 : sb.append('\n');
176 0 : _logger->log(sb);
177 : }
178 : #endif
179 :
180 : return kErrorOk;
181 : }
182 :
183 : #ifndef ASMJIT_NO_LOGGING
184 : static const TypeId dataTypeIdBySize[9] = {
185 : TypeId::kVoid, // [0] (invalid)
186 : TypeId::kUInt8, // [1] (uint8_t)
187 : TypeId::kUInt16, // [2] (uint16_t)
188 : TypeId::kVoid, // [3] (invalid)
189 : TypeId::kUInt32, // [4] (uint32_t)
190 : TypeId::kVoid, // [5] (invalid)
191 : TypeId::kVoid, // [6] (invalid)
192 : TypeId::kVoid, // [7] (invalid)
193 : TypeId::kUInt64 // [8] (uint64_t)
194 : };
195 : #endif
196 :
197 0 : Error BaseAssembler::embedConstPool(const Label& label, const ConstPool& pool) {
198 0 : if (ASMJIT_UNLIKELY(!_code))
199 0 : return reportError(DebugUtils::errored(kErrorNotInitialized));
200 :
201 0 : if (ASMJIT_UNLIKELY(!isLabelValid(label)))
202 0 : return reportError(DebugUtils::errored(kErrorInvalidLabel));
203 :
204 0 : ASMJIT_PROPAGATE(align(AlignMode::kData, uint32_t(pool.alignment())));
205 0 : ASMJIT_PROPAGATE(bind(label));
206 :
207 : size_t size = pool.size();
208 0 : if (!size)
209 : return kErrorOk;
210 :
211 : CodeWriter writer(this);
212 0 : ASMJIT_PROPAGATE(writer.ensureSpace(this, size));
213 :
214 : #ifndef ASMJIT_NO_LOGGING
215 : uint8_t* data = writer.cursor();
216 : #endif
217 :
218 0 : pool.fill(writer.cursor());
219 : writer.advance(size);
220 : writer.done(this);
221 :
222 : #ifndef ASMJIT_NO_LOGGING
223 0 : if (_logger) {
224 : uint32_t dataSizeLog2 = Support::min<uint32_t>(Support::ctz(pool.minItemSize()), 3);
225 0 : uint32_t dataSize = 1 << dataSizeLog2;
226 :
227 : StringTmp<512> sb;
228 0 : Formatter::formatData(sb, _logger->flags(), arch(), dataTypeIdBySize[dataSize], data, size >> dataSizeLog2);
229 : sb.append('\n');
230 0 : _logger->log(sb);
231 : }
232 : #endif
233 :
234 : return kErrorOk;
235 : }
236 :
237 0 : Error BaseAssembler::embedLabel(const Label& label, size_t dataSize) {
238 0 : if (ASMJIT_UNLIKELY(!_code))
239 0 : return reportError(DebugUtils::errored(kErrorNotInitialized));
240 :
241 : ASMJIT_ASSERT(_code != nullptr);
242 : RelocEntry* re;
243 : LabelEntry* le = _code->labelEntry(label);
244 :
245 0 : if (ASMJIT_UNLIKELY(!le))
246 0 : return reportError(DebugUtils::errored(kErrorInvalidLabel));
247 :
248 0 : if (dataSize == 0)
249 0 : dataSize = registerSize();
250 :
251 0 : if (ASMJIT_UNLIKELY(!Support::isPowerOf2(dataSize) || dataSize > 8))
252 0 : return reportError(DebugUtils::errored(kErrorInvalidOperandSize));
253 :
254 : CodeWriter writer(this);
255 0 : ASMJIT_PROPAGATE(writer.ensureSpace(this, dataSize));
256 :
257 : #ifndef ASMJIT_NO_LOGGING
258 0 : if (_logger) {
259 : StringTmp<256> sb;
260 : sb.append('.');
261 0 : Formatter::formatDataType(sb, _logger->flags(), arch(), dataTypeIdBySize[dataSize]);
262 : sb.append(' ');
263 0 : Formatter::formatLabel(sb, FormatFlags::kNone, this, label.id());
264 : sb.append('\n');
265 0 : _logger->log(sb);
266 : }
267 : #endif
268 :
269 0 : Error err = _code->newRelocEntry(&re, RelocType::kRelToAbs);
270 0 : if (ASMJIT_UNLIKELY(err))
271 0 : return reportError(err);
272 :
273 0 : re->_sourceSectionId = _section->id();
274 0 : re->_sourceOffset = offset();
275 : re->_format.resetToSimpleValue(OffsetType::kUnsignedOffset, dataSize);
276 :
277 0 : if (le->isBound()) {
278 0 : re->_targetSectionId = le->section()->id();
279 0 : re->_payload = le->offset();
280 : }
281 : else {
282 : OffsetFormat of;
283 : of.resetToSimpleValue(OffsetType::kUnsignedOffset, dataSize);
284 :
285 0 : LabelLink* link = _code->newLabelLink(le, _section->id(), offset(), 0, of);
286 0 : if (ASMJIT_UNLIKELY(!link))
287 0 : return reportError(DebugUtils::errored(kErrorOutOfMemory));
288 :
289 0 : link->relocId = re->id();
290 : }
291 :
292 : // Emit dummy DWORD/QWORD depending on the data size.
293 : writer.emitZeros(dataSize);
294 : writer.done(this);
295 :
296 0 : return kErrorOk;
297 : }
298 :
299 0 : Error BaseAssembler::embedLabelDelta(const Label& label, const Label& base, size_t dataSize) {
300 0 : if (ASMJIT_UNLIKELY(!_code))
301 0 : return reportError(DebugUtils::errored(kErrorNotInitialized));
302 :
303 : LabelEntry* labelEntry = _code->labelEntry(label);
304 : LabelEntry* baseEntry = _code->labelEntry(base);
305 :
306 0 : if (ASMJIT_UNLIKELY(!labelEntry || !baseEntry))
307 0 : return reportError(DebugUtils::errored(kErrorInvalidLabel));
308 :
309 0 : if (dataSize == 0)
310 0 : dataSize = registerSize();
311 :
312 0 : if (ASMJIT_UNLIKELY(!Support::isPowerOf2(dataSize) || dataSize > 8))
313 0 : return reportError(DebugUtils::errored(kErrorInvalidOperandSize));
314 :
315 : CodeWriter writer(this);
316 0 : ASMJIT_PROPAGATE(writer.ensureSpace(this, dataSize));
317 :
318 : #ifndef ASMJIT_NO_LOGGING
319 0 : if (_logger) {
320 : StringTmp<256> sb;
321 : sb.append('.');
322 0 : Formatter::formatDataType(sb, _logger->flags(), arch(), dataTypeIdBySize[dataSize]);
323 : sb.append(" (");
324 0 : Formatter::formatLabel(sb, FormatFlags::kNone, this, label.id());
325 : sb.append(" - ");
326 0 : Formatter::formatLabel(sb, FormatFlags::kNone, this, base.id());
327 : sb.append(")\n");
328 0 : _logger->log(sb);
329 : }
330 : #endif
331 :
332 : // If both labels are bound within the same section it means the delta can be calculated now.
333 0 : if (labelEntry->isBound() && baseEntry->isBound() && labelEntry->section() == baseEntry->section()) {
334 0 : uint64_t delta = labelEntry->offset() - baseEntry->offset();
335 : writer.emitValueLE(delta, dataSize);
336 : }
337 : else {
338 : RelocEntry* re;
339 0 : Error err = _code->newRelocEntry(&re, RelocType::kExpression);
340 0 : if (ASMJIT_UNLIKELY(err))
341 0 : return reportError(err);
342 :
343 0 : Expression* exp = _code->_zone.newT<Expression>();
344 0 : if (ASMJIT_UNLIKELY(!exp))
345 0 : return reportError(DebugUtils::errored(kErrorOutOfMemory));
346 :
347 0 : exp->reset();
348 0 : exp->opType = ExpressionOpType::kSub;
349 : exp->setValueAsLabel(0, labelEntry);
350 : exp->setValueAsLabel(1, baseEntry);
351 :
352 0 : re->_format.resetToSimpleValue(OffsetType::kSignedOffset, dataSize);
353 0 : re->_sourceSectionId = _section->id();
354 0 : re->_sourceOffset = offset();
355 0 : re->_payload = (uint64_t)(uintptr_t)exp;
356 :
357 : writer.emitZeros(dataSize);
358 : }
359 :
360 : writer.done(this);
361 0 : return kErrorOk;
362 : }
363 :
364 : // BaseAssembler - Comment
365 : // =======================
366 :
367 0 : Error BaseAssembler::comment(const char* data, size_t size) {
368 0 : if (!hasEmitterFlag(EmitterFlags::kLogComments)) {
369 0 : if (!hasEmitterFlag(EmitterFlags::kAttached))
370 0 : return reportError(DebugUtils::errored(kErrorNotInitialized));
371 : return kErrorOk;
372 : }
373 :
374 : #ifndef ASMJIT_NO_LOGGING
375 : // Logger cannot be NULL if `EmitterFlags::kLogComments` is set.
376 : ASMJIT_ASSERT(_logger != nullptr);
377 :
378 0 : _logger->log(data, size);
379 0 : _logger->log("\n", 1);
380 0 : return kErrorOk;
381 : #else
382 : DebugUtils::unused(data, size);
383 : return kErrorOk;
384 : #endif
385 : }
386 :
387 : // BaseAssembler - Events
388 : // ======================
389 :
390 27492 : Error BaseAssembler::onAttach(CodeHolder* code) noexcept {
391 27492 : ASMJIT_PROPAGATE(Base::onAttach(code));
392 :
393 : // Attach to the end of the .text section.
394 27492 : BaseAssembler_initSection(this, code->_sections[0]);
395 :
396 27492 : return kErrorOk;
397 : }
398 :
399 0 : Error BaseAssembler::onDetach(CodeHolder* code) noexcept {
400 0 : _section = nullptr;
401 0 : _bufferData = nullptr;
402 0 : _bufferEnd = nullptr;
403 0 : _bufferPtr = nullptr;
404 0 : return Base::onDetach(code);
405 : }
406 :
407 : ASMJIT_END_NAMESPACE
408 :
409 : #endif // __PLUMED_HAS_ASMJIT
|