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 : #ifndef ASMJIT_NO_LOGGING
9 :
10 : #include "archtraits.h"
11 : #include "builder.h"
12 : #include "codeholder.h"
13 : #include "compiler.h"
14 : #include "emitter.h"
15 : #include "formatter_p.h"
16 : #include "moved_string.h"
17 : #include "support.h"
18 : #include "type.h"
19 :
20 : #if !defined(ASMJIT_NO_X86)
21 : #include "x86formatter_p.h"
22 : #endif
23 :
24 : #if !defined(ASMJIT_NO_AARCH64)
25 : #include "a64formatter_p.h"
26 : #endif
27 :
28 : ASMJIT_BEGIN_NAMESPACE
29 :
30 : #if defined(ASMJIT_NO_COMPILER)
31 : class VirtReg;
32 : #endif
33 :
34 : namespace Formatter {
35 :
36 : static const char wordNameTable[][8] = {
37 : "db",
38 : "dw",
39 : "dd",
40 : "dq",
41 : "byte",
42 : "half",
43 : "word",
44 : "hword",
45 : "dword",
46 : "qword",
47 : "xword",
48 : "short",
49 : "long",
50 : "quad"
51 : };
52 :
53 :
54 0 : Error formatTypeId(String& sb, TypeId typeId) noexcept {
55 0 : if (typeId == TypeId::kVoid)
56 0 : return sb.append("void");
57 :
58 : if (!TypeUtils::isValid(typeId))
59 0 : return sb.append("unknown");
60 :
61 : const char* typeName = "unknown";
62 : uint32_t typeSize = TypeUtils::sizeOf(typeId);
63 : TypeId scalarType = TypeUtils::scalarOf(typeId);
64 :
65 0 : switch (scalarType) {
66 : case TypeId::kIntPtr : typeName = "intptr" ; break;
67 0 : case TypeId::kUIntPtr: typeName = "uintptr"; break;
68 0 : case TypeId::kInt8 : typeName = "int8" ; break;
69 0 : case TypeId::kUInt8 : typeName = "uint8" ; break;
70 0 : case TypeId::kInt16 : typeName = "int16" ; break;
71 0 : case TypeId::kUInt16 : typeName = "uint16" ; break;
72 0 : case TypeId::kInt32 : typeName = "int32" ; break;
73 0 : case TypeId::kUInt32 : typeName = "uint32" ; break;
74 0 : case TypeId::kInt64 : typeName = "int64" ; break;
75 0 : case TypeId::kUInt64 : typeName = "uint64" ; break;
76 0 : case TypeId::kFloat32: typeName = "float32"; break;
77 0 : case TypeId::kFloat64: typeName = "float64"; break;
78 0 : case TypeId::kFloat80: typeName = "float80"; break;
79 0 : case TypeId::kMask8 : typeName = "mask8" ; break;
80 0 : case TypeId::kMask16 : typeName = "mask16" ; break;
81 0 : case TypeId::kMask32 : typeName = "mask32" ; break;
82 0 : case TypeId::kMask64 : typeName = "mask64" ; break;
83 0 : case TypeId::kMmx32 : typeName = "mmx32" ; break;
84 0 : case TypeId::kMmx64 : typeName = "mmx64" ; break;
85 :
86 0 : default:
87 : typeName = "unknown";
88 0 : break;
89 : }
90 :
91 : uint32_t baseSize = TypeUtils::sizeOf(scalarType);
92 0 : if (typeSize > baseSize) {
93 0 : uint32_t count = typeSize / baseSize;
94 : return sb.appendFormat("%sx%u", typeName, unsigned(count));
95 : }
96 : else {
97 0 : return sb.append(typeName);
98 : }
99 : }
100 :
101 0 : Error formatFeature(
102 : String& sb,
103 : Arch arch,
104 : uint32_t featureId) noexcept {
105 :
106 : #if !defined(ASMJIT_NO_X86)
107 0 : if (Environment::isFamilyX86(arch))
108 0 : return x86::FormatterInternal::formatFeature(sb, featureId);
109 : #endif
110 :
111 : #if !defined(ASMJIT_NO_AARCH32) && !defined(ASMJIT_NO_AARCH64)
112 0 : if (Environment::isFamilyARM(arch))
113 0 : return arm::FormatterInternal::formatFeature(sb, featureId);
114 : #endif
115 :
116 : return kErrorInvalidArch;
117 : }
118 :
119 0 : Error formatLabel(
120 : String& sb,
121 : FormatFlags formatFlags,
122 : const BaseEmitter* emitter,
123 : uint32_t labelId) noexcept {
124 :
125 : DebugUtils::unused(formatFlags);
126 :
127 : const LabelEntry* le = emitter->code()->labelEntry(labelId);
128 0 : if (ASMJIT_UNLIKELY(!le))
129 0 : return sb.appendFormat("<InvalidLabel:%u>", labelId);
130 :
131 0 : if (le->hasName()) {
132 0 : if (le->hasParent()) {
133 : uint32_t parentId = le->parentId();
134 : const LabelEntry* pe = emitter->code()->labelEntry(parentId);
135 :
136 0 : if (ASMJIT_UNLIKELY(!pe))
137 0 : ASMJIT_PROPAGATE(sb.appendFormat("<InvalidLabel:%u>", labelId));
138 0 : else if (ASMJIT_UNLIKELY(!pe->hasName()))
139 0 : ASMJIT_PROPAGATE(sb.appendFormat("L%u", parentId));
140 : else
141 0 : ASMJIT_PROPAGATE(sb.append(pe->name()));
142 :
143 0 : ASMJIT_PROPAGATE(sb.append('.'));
144 : }
145 :
146 0 : if (le->type() == LabelType::kAnonymous)
147 0 : ASMJIT_PROPAGATE(sb.appendFormat("L%u@", labelId));
148 0 : return sb.append(le->name());
149 : }
150 : else {
151 0 : return sb.appendFormat("L%u", labelId);
152 : }
153 : }
154 :
155 0 : Error formatRegister(
156 : String& sb,
157 : FormatFlags formatFlags,
158 : const BaseEmitter* emitter,
159 : Arch arch,
160 : RegType regType,
161 : uint32_t regId) noexcept {
162 :
163 : #if !defined(ASMJIT_NO_X86)
164 0 : if (Environment::isFamilyX86(arch))
165 0 : return x86::FormatterInternal::formatRegister(sb, formatFlags, emitter, arch, regType, regId);
166 : #endif
167 :
168 : #if !defined(ASMJIT_NO_AARCH64)
169 0 : if (Environment::isFamilyAArch64(arch))
170 0 : return a64::FormatterInternal::formatRegister(sb, formatFlags, emitter, arch, regType, regId);
171 : #endif
172 :
173 : return kErrorInvalidArch;
174 : }
175 :
176 0 : Error formatOperand(
177 : String& sb,
178 : FormatFlags formatFlags,
179 : const BaseEmitter* emitter,
180 : Arch arch,
181 : const Operand_& op) noexcept {
182 :
183 : #if !defined(ASMJIT_NO_X86)
184 0 : if (Environment::isFamilyX86(arch))
185 0 : return x86::FormatterInternal::formatOperand(sb, formatFlags, emitter, arch, op);
186 : #endif
187 :
188 : #if !defined(ASMJIT_NO_AARCH64)
189 0 : if (Environment::isFamilyAArch64(arch))
190 0 : return a64::FormatterInternal::formatOperand(sb, formatFlags, emitter, arch, op);
191 : #endif
192 :
193 : return kErrorInvalidArch;
194 : }
195 :
196 0 : ASMJIT_API Error formatDataType(
197 : String& sb,
198 : FormatFlags formatFlags,
199 : Arch arch,
200 : TypeId typeId) noexcept
201 : {
202 : DebugUtils::unused(formatFlags);
203 :
204 0 : if (ASMJIT_UNLIKELY(uint32_t(arch) > uint32_t(Arch::kMaxValue)))
205 : return DebugUtils::errored(kErrorInvalidArch);
206 :
207 : uint32_t typeSize = TypeUtils::sizeOf(typeId);
208 0 : if (typeSize == 0 || typeSize > 8)
209 : return DebugUtils::errored(kErrorInvalidState);
210 :
211 : uint32_t typeSizeLog2 = Support::ctz(typeSize);
212 0 : return sb.append(wordNameTable[size_t(ArchTraits::byArch(arch).typeNameIdByIndex(typeSizeLog2))]);
213 : }
214 :
215 0 : static Error formatDataHelper(String& sb, const char* typeName, uint32_t typeSize, const uint8_t* data, size_t itemCount) noexcept {
216 : sb.append('.');
217 : sb.append(typeName);
218 : sb.append(' ');
219 :
220 0 : for (size_t i = 0; i < itemCount; i++) {
221 : uint64_t v = 0;
222 :
223 0 : if (i != 0)
224 0 : ASMJIT_PROPAGATE(sb.append(", ", 2));
225 :
226 0 : switch (typeSize) {
227 0 : case 1: v = data[0]; break;
228 0 : case 2: v = Support::readU16u(data); break;
229 0 : case 4: v = Support::readU32u(data); break;
230 0 : case 8: v = Support::readU64u(data); break;
231 : }
232 :
233 0 : ASMJIT_PROPAGATE(sb.appendUInt(v, 16, typeSize * 2, StringFormatFlags::kAlternate));
234 0 : data += typeSize;
235 : }
236 :
237 : return kErrorOk;
238 : }
239 :
240 0 : Error formatData(
241 : String& sb,
242 : FormatFlags formatFlags,
243 : Arch arch,
244 : TypeId typeId, const void* data, size_t itemCount, size_t repeatCount) noexcept
245 : {
246 : DebugUtils::unused(formatFlags);
247 :
248 0 : if (ASMJIT_UNLIKELY(!Environment::isDefinedArch(arch)))
249 : return DebugUtils::errored(kErrorInvalidArch);
250 :
251 : uint32_t typeSize = TypeUtils::sizeOf(typeId);
252 0 : if (typeSize == 0)
253 : return DebugUtils::errored(kErrorInvalidState);
254 :
255 : if (!Support::isPowerOf2(typeSize)) {
256 0 : itemCount *= typeSize;
257 : typeSize = 1;
258 : }
259 :
260 0 : while (typeSize > 8u) {
261 0 : typeSize >>= 1;
262 0 : itemCount <<= 1;
263 : }
264 :
265 : uint32_t typeSizeLog2 = Support::ctz(typeSize);
266 0 : const char* wordName = wordNameTable[size_t(ArchTraits::byArch(arch).typeNameIdByIndex(typeSizeLog2))];
267 :
268 0 : if (repeatCount > 1)
269 0 : ASMJIT_PROPAGATE(sb.appendFormat(".repeat %zu ", repeatCount));
270 :
271 0 : return formatDataHelper(sb, wordName, typeSize, static_cast<const uint8_t*>(data), itemCount);
272 : }
273 :
274 0 : Error formatInstruction(
275 : String& sb,
276 : FormatFlags formatFlags,
277 : const BaseEmitter* emitter,
278 : Arch arch,
279 : const BaseInst& inst, const Operand_* operands, size_t opCount) noexcept {
280 :
281 : #if !defined(ASMJIT_NO_X86)
282 0 : if (Environment::isFamilyX86(arch))
283 0 : return x86::FormatterInternal::formatInstruction(sb, formatFlags, emitter, arch, inst, operands, opCount);
284 : #endif
285 :
286 : #if !defined(ASMJIT_NO_AARCH64)
287 0 : if (Environment::isFamilyARM(arch))
288 0 : return a64::FormatterInternal::formatInstruction(sb, formatFlags, emitter, arch, inst, operands, opCount);
289 : #endif
290 :
291 : return kErrorInvalidArch;
292 : }
293 :
294 : #ifndef ASMJIT_NO_BUILDER
295 :
296 : #ifndef ASMJIT_NO_COMPILER
297 0 : static Error formatFuncValue(String& sb, FormatFlags formatFlags, const BaseEmitter* emitter, FuncValue value) noexcept {
298 : TypeId typeId = value.typeId();
299 0 : ASMJIT_PROPAGATE(formatTypeId(sb, typeId));
300 :
301 0 : if (value.isAssigned()) {
302 0 : ASMJIT_PROPAGATE(sb.append('@'));
303 :
304 0 : if (value.isIndirect())
305 0 : ASMJIT_PROPAGATE(sb.append('['));
306 :
307 : // NOTE: It should be either reg or stack, but never both. We
308 : // use two IFs on purpose so if the FuncValue is both it would
309 : // show in logs.
310 0 : if (value.isReg()) {
311 0 : ASMJIT_PROPAGATE(formatRegister(sb, formatFlags, emitter, emitter->arch(), value.regType(), value.regId()));
312 : }
313 :
314 0 : if (value.isStack()) {
315 0 : ASMJIT_PROPAGATE(sb.appendFormat("[%d]", int(value.stackOffset())));
316 : }
317 :
318 0 : if (value.isIndirect())
319 0 : ASMJIT_PROPAGATE(sb.append(']'));
320 : }
321 :
322 : return kErrorOk;
323 : }
324 :
325 0 : static Error formatFuncValuePack(
326 : String& sb,
327 : FormatFlags formatFlags,
328 : const BaseCompiler* cc,
329 : const FuncValuePack& pack,
330 : const RegOnly* vRegs) noexcept {
331 :
332 0 : size_t count = pack.count();
333 0 : if (!count)
334 0 : return sb.append("void");
335 :
336 0 : if (count > 1)
337 : sb.append('[');
338 :
339 0 : for (uint32_t valueIndex = 0; valueIndex < count; valueIndex++) {
340 0 : const FuncValue& value = pack[valueIndex];
341 0 : if (!value)
342 : break;
343 :
344 0 : if (valueIndex)
345 0 : ASMJIT_PROPAGATE(sb.append(", "));
346 :
347 0 : ASMJIT_PROPAGATE(formatFuncValue(sb, formatFlags, cc, value));
348 :
349 0 : if (vRegs) {
350 : const VirtReg* virtReg = nullptr;
351 : static const char nullReg[] = "<none>";
352 :
353 0 : if (vRegs[valueIndex].isReg() && cc->isVirtIdValid(vRegs[valueIndex].id()))
354 : virtReg = cc->virtRegById(vRegs[valueIndex].id());
355 :
356 0 : ASMJIT_PROPAGATE(sb.appendFormat(" %s", virtReg ? virtReg->name() : nullReg));
357 : }
358 : }
359 :
360 0 : if (count > 1)
361 : sb.append(']');
362 :
363 : return kErrorOk;
364 : }
365 :
366 0 : static Error formatFuncRets(
367 : String& sb,
368 : FormatFlags formatFlags,
369 : const BaseCompiler* cc,
370 : const FuncDetail& fd) noexcept {
371 :
372 0 : return formatFuncValuePack(sb, formatFlags, cc, fd.retPack(), nullptr);
373 : }
374 :
375 0 : static Error formatFuncArgs(
376 : String& sb,
377 : FormatFlags formatFlags,
378 : const BaseCompiler* cc,
379 : const FuncDetail& fd,
380 : const FuncNode::ArgPack* argPacks) noexcept {
381 :
382 : uint32_t argCount = fd.argCount();
383 0 : if (!argCount)
384 0 : return sb.append("void");
385 :
386 0 : for (uint32_t argIndex = 0; argIndex < argCount; argIndex++) {
387 0 : if (argIndex)
388 0 : ASMJIT_PROPAGATE(sb.append(", "));
389 :
390 0 : ASMJIT_PROPAGATE(formatFuncValuePack(sb, formatFlags, cc, fd.argPack(argIndex), argPacks[argIndex]._data));
391 : }
392 :
393 : return kErrorOk;
394 : }
395 : #endif
396 :
397 0 : Error formatNode(
398 : String& sb,
399 : const FormatOptions& formatOptions,
400 : const BaseBuilder* builder,
401 : const BaseNode* node) noexcept {
402 :
403 0 : if (node->hasPosition() && formatOptions.hasFlag(FormatFlags::kPositions))
404 0 : ASMJIT_PROPAGATE(sb.appendFormat("<%05u> ", node->position()));
405 :
406 : size_t startLineIndex = sb.size();
407 :
408 0 : switch (node->type()) {
409 : case NodeType::kInst:
410 : case NodeType::kJump: {
411 : const InstNode* instNode = node->as<InstNode>();
412 0 : ASMJIT_PROPAGATE(builder->_funcs.formatInstruction(sb, formatOptions.flags(), builder,
413 : builder->arch(),
414 : instNode->baseInst(), instNode->operands(), instNode->opCount()));
415 : break;
416 : }
417 :
418 : case NodeType::kSection: {
419 : const SectionNode* sectionNode = node->as<SectionNode>();
420 0 : if (builder->_code->isSectionValid(sectionNode->id())) {
421 : const Section* section = builder->_code->sectionById(sectionNode->id());
422 0 : ASMJIT_PROPAGATE(sb.appendFormat(".section %s", section->name()));
423 : }
424 : break;
425 : }
426 :
427 : case NodeType::kLabel: {
428 : const LabelNode* labelNode = node->as<LabelNode>();
429 0 : ASMJIT_PROPAGATE(formatLabel(sb, formatOptions.flags(), builder, labelNode->labelId()));
430 0 : ASMJIT_PROPAGATE(sb.append(":"));
431 : break;
432 : }
433 :
434 : case NodeType::kAlign: {
435 : const AlignNode* alignNode = node->as<AlignNode>();
436 0 : ASMJIT_PROPAGATE(sb.appendFormat(".align %u (%s)",
437 : alignNode->alignment(),
438 : alignNode->alignMode() == AlignMode::kCode ? "code" : "data"));
439 : break;
440 : }
441 :
442 : case NodeType::kEmbedData: {
443 : const EmbedDataNode* embedNode = node->as<EmbedDataNode>();
444 0 : ASMJIT_PROPAGATE(sb.append('.'));
445 0 : ASMJIT_PROPAGATE(formatDataType(sb, formatOptions.flags(), builder->arch(), embedNode->typeId()));
446 0 : ASMJIT_PROPAGATE(sb.appendFormat(" {Count=%zu Repeat=%zu TotalSize=%zu}", embedNode->itemCount(), embedNode->repeatCount(), embedNode->dataSize()));
447 : break;
448 : }
449 :
450 : case NodeType::kEmbedLabel: {
451 : const EmbedLabelNode* embedNode = node->as<EmbedLabelNode>();
452 0 : ASMJIT_PROPAGATE(sb.append(".label "));
453 0 : ASMJIT_PROPAGATE(formatLabel(sb, formatOptions.flags(), builder, embedNode->labelId()));
454 : break;
455 : }
456 :
457 : case NodeType::kEmbedLabelDelta: {
458 : const EmbedLabelDeltaNode* embedNode = node->as<EmbedLabelDeltaNode>();
459 0 : ASMJIT_PROPAGATE(sb.append(".label ("));
460 0 : ASMJIT_PROPAGATE(formatLabel(sb, formatOptions.flags(), builder, embedNode->labelId()));
461 0 : ASMJIT_PROPAGATE(sb.append(" - "));
462 0 : ASMJIT_PROPAGATE(formatLabel(sb, formatOptions.flags(), builder, embedNode->baseLabelId()));
463 0 : ASMJIT_PROPAGATE(sb.append(")"));
464 : break;
465 : }
466 :
467 : case NodeType::kConstPool: {
468 : const ConstPoolNode* constPoolNode = node->as<ConstPoolNode>();
469 0 : ASMJIT_PROPAGATE(sb.appendFormat("[ConstPool Size=%zu Alignment=%zu]", constPoolNode->size(), constPoolNode->alignment()));
470 : break;
471 : };
472 :
473 : case NodeType::kComment: {
474 : const CommentNode* commentNode = node->as<CommentNode>();
475 0 : ASMJIT_PROPAGATE(sb.appendFormat("; %s", commentNode->inlineComment()));
476 : break;
477 : }
478 :
479 : case NodeType::kSentinel: {
480 : const SentinelNode* sentinelNode = node->as<SentinelNode>();
481 : const char* sentinelName = nullptr;
482 :
483 0 : switch (sentinelNode->sentinelType()) {
484 : case SentinelType::kFuncEnd:
485 : sentinelName = "[FuncEnd]";
486 : break;
487 :
488 0 : default:
489 : sentinelName = "[Sentinel]";
490 0 : break;
491 : }
492 :
493 0 : ASMJIT_PROPAGATE(sb.append(sentinelName));
494 : break;
495 : }
496 :
497 : #ifndef ASMJIT_NO_COMPILER
498 : case NodeType::kFunc: {
499 : const FuncNode* funcNode = node->as<FuncNode>();
500 :
501 0 : if (builder->isCompiler()) {
502 0 : ASMJIT_PROPAGATE(formatLabel(sb, formatOptions.flags(), builder, funcNode->labelId()));
503 0 : ASMJIT_PROPAGATE(sb.append(": "));
504 :
505 0 : ASMJIT_PROPAGATE(formatFuncRets(sb, formatOptions.flags(), static_cast<const BaseCompiler*>(builder), funcNode->detail()));
506 0 : ASMJIT_PROPAGATE(sb.append(" Func("));
507 0 : ASMJIT_PROPAGATE(formatFuncArgs(sb, formatOptions.flags(), static_cast<const BaseCompiler*>(builder), funcNode->detail(), funcNode->argPacks()));
508 0 : ASMJIT_PROPAGATE(sb.append(")"));
509 : }
510 : break;
511 : }
512 :
513 : case NodeType::kFuncRet: {
514 : const FuncRetNode* retNode = node->as<FuncRetNode>();
515 0 : ASMJIT_PROPAGATE(sb.append("[FuncRet]"));
516 :
517 0 : for (uint32_t i = 0; i < 2; i++) {
518 0 : const Operand_& op = retNode->_opArray[i];
519 0 : if (!op.isNone()) {
520 0 : ASMJIT_PROPAGATE(sb.append(i == 0 ? " " : ", "));
521 0 : ASMJIT_PROPAGATE(formatOperand(sb, formatOptions.flags(), builder, builder->arch(), op));
522 : }
523 : }
524 : break;
525 : }
526 :
527 : case NodeType::kInvoke: {
528 : const InvokeNode* invokeNode = node->as<InvokeNode>();
529 0 : ASMJIT_PROPAGATE(builder->_funcs.formatInstruction(sb, formatOptions.flags(), builder,
530 : builder->arch(),
531 : invokeNode->baseInst(), invokeNode->operands(), invokeNode->opCount()));
532 : break;
533 : }
534 : #endif
535 :
536 : default: {
537 0 : ASMJIT_PROPAGATE(sb.appendFormat("[UserNode:%u]", node->type()));
538 : break;
539 : }
540 : }
541 :
542 0 : if (node->hasInlineComment()) {
543 : size_t requiredPadding = paddingFromOptions(formatOptions, FormatPaddingGroup::kRegularLine);
544 0 : size_t currentPadding = sb.size() - startLineIndex;
545 :
546 0 : if (currentPadding < requiredPadding)
547 0 : ASMJIT_PROPAGATE(sb.appendChars(' ', requiredPadding - currentPadding));
548 :
549 0 : ASMJIT_PROPAGATE(sb.append("; "));
550 0 : ASMJIT_PROPAGATE(sb.append(node->inlineComment()));
551 : }
552 :
553 : return kErrorOk;
554 : }
555 :
556 0 : Error formatNodeList(
557 : String& sb,
558 : const FormatOptions& formatOptions,
559 : const BaseBuilder* builder) noexcept {
560 :
561 0 : return formatNodeList(sb, formatOptions, builder, builder->firstNode(), nullptr);
562 : }
563 :
564 0 : Error formatNodeList(
565 : String& sb,
566 : const FormatOptions& formatOptions,
567 : const BaseBuilder* builder,
568 : const BaseNode* begin,
569 : const BaseNode* end) noexcept {
570 :
571 : const BaseNode* node = begin;
572 0 : while (node != end) {
573 0 : ASMJIT_PROPAGATE(formatNode(sb, formatOptions, builder, node));
574 0 : ASMJIT_PROPAGATE(sb.append('\n'));
575 : node = node->next();
576 : }
577 : return kErrorOk;
578 : }
579 : #endif
580 :
581 : } // {Formatter}
582 :
583 : ASMJIT_END_NAMESPACE
584 :
585 : #endif
586 :
587 : #endif // __PLUMED_HAS_ASMJIT
|