Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2008-2017, Petr Kobalicek
3 :
4 : This software is provided 'as-is', without any express or implied
5 : warranty. In no event will the authors be held liable for any damages
6 : arising from the use of this software.
7 :
8 : Permission is granted to anyone to use this software for any purpose,
9 : including commercial applications, and to alter it and redistribute it
10 : freely, subject to the following restrictions:
11 :
12 : 1. The origin of this software must not be misrepresented; you must not
13 : claim that you wrote the original software. If you use this software
14 : in a product, an acknowledgment in the product documentation would be
15 : appreciated but is not required.
16 : 2. Altered source versions must be plainly marked as such, and must not be
17 : misrepresented as being the original software.
18 : 3. This notice may not be removed or altered from any source distribution.
19 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
20 : #ifdef __PLUMED_HAS_ASMJIT
21 : #pragma GCC diagnostic push
22 : #pragma GCC diagnostic ignored "-Wpedantic"
23 : // [AsmJit]
24 : // Complete x86/x64 JIT and Remote Assembler for C++.
25 : //
26 : // [License]
27 : // Zlib - See LICENSE.md file in the package.
28 :
29 : // [Export]
30 : #define ASMJIT_EXPORTS
31 :
32 : // [Guard]
33 : #include "./asmjit_build.h"
34 : #if !defined(ASMJIT_DISABLE_LOGGING)
35 :
36 : // [Dependencies]
37 : #include "./codeholder.h"
38 : #include "./codeemitter.h"
39 : #include "./logging.h"
40 : #include "./utils.h"
41 :
42 : #if !defined(ASMJIT_DISABLE_BUILDER)
43 : # include "./codebuilder.h"
44 : #endif // !ASMJIT_DISABLE_BUILDER
45 :
46 : #if !defined(ASMJIT_DISABLE_COMPILER)
47 : # include "./codecompiler.h"
48 : #else
49 : namespace PLMD {
50 : namespace asmjit { class VirtReg; }
51 : #endif // !ASMJIT_DISABLE_COMPILER
52 :
53 : #if defined(ASMJIT_BUILD_X86)
54 : # include "./x86logging_p.h"
55 : #endif // ASMJIT_BUILD_X86
56 :
57 : #if defined(ASMJIT_BUILD_ARM)
58 : # include "./armlogging_p.h"
59 : #endif // ASMJIT_BUILD_ARM
60 :
61 : // [Api-Begin]
62 : #include "./asmjit_apibegin.h"
63 :
64 : namespace PLMD {
65 : namespace asmjit {
66 :
67 : // ============================================================================
68 : // [asmjit::Logger - Construction / Destruction]
69 : // ============================================================================
70 :
71 0 : Logger::Logger() noexcept {
72 0 : _options = 0;
73 0 : ::memset(_indentation, 0, ASMJIT_ARRAY_SIZE(_indentation));
74 0 : }
75 0 : Logger::~Logger() noexcept {}
76 :
77 : // ============================================================================
78 : // [asmjit::Logger - Logging]
79 : // ============================================================================
80 :
81 0 : Error Logger::logf(const char* fmt, ...) noexcept {
82 : Error err;
83 :
84 : va_list ap;
85 0 : va_start(ap, fmt);
86 0 : err = logv(fmt, ap);
87 0 : va_end(ap);
88 :
89 0 : return err;
90 : }
91 :
92 0 : Error Logger::logv(const char* fmt, va_list ap) noexcept {
93 : char buf[1024];
94 0 : size_t len = vsnprintf(buf, sizeof(buf), fmt, ap);
95 :
96 : if (len >= sizeof(buf))
97 : len = sizeof(buf) - 1;
98 0 : return log(buf, len);
99 : }
100 :
101 0 : Error Logger::logBinary(const void* data, size_t size) noexcept {
102 : static const char prefix[] = ".data ";
103 : static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
104 :
105 : const uint8_t* s = static_cast<const uint8_t*>(data);
106 0 : size_t i = size;
107 :
108 : char buffer[128];
109 : ::memcpy(buffer, prefix, ASMJIT_ARRAY_SIZE(prefix) - 1);
110 :
111 0 : while (i) {
112 0 : uint32_t n = static_cast<uint32_t>(std::min<size_t>(i, 16));
113 : char* p = buffer + ASMJIT_ARRAY_SIZE(prefix) - 1;
114 :
115 0 : i -= n;
116 : do {
117 0 : uint32_t c = s[0];
118 :
119 0 : p[0] = hex[c >> 4];
120 0 : p[1] = hex[c & 15];
121 :
122 0 : p += 2;
123 0 : s += 1;
124 0 : } while (--n);
125 :
126 0 : *p++ = '\n';
127 0 : ASMJIT_PROPAGATE(log(buffer, (size_t)(p - buffer)));
128 : }
129 :
130 : return kErrorOk;
131 : }
132 :
133 : // ============================================================================
134 : // [asmjit::Logger - Indentation]
135 : // ============================================================================
136 :
137 0 : void Logger::setIndentation(const char* indentation) noexcept {
138 0 : ::memset(_indentation, 0, ASMJIT_ARRAY_SIZE(_indentation));
139 0 : if (!indentation)
140 : return;
141 :
142 : size_t length = Utils::strLen(indentation, ASMJIT_ARRAY_SIZE(_indentation) - 1);
143 : ::memcpy(_indentation, indentation, length);
144 : }
145 :
146 : // ============================================================================
147 : // [asmjit::FileLogger - Construction / Destruction]
148 : // ============================================================================
149 :
150 0 : FileLogger::FileLogger(FILE* stream) noexcept : _stream(nullptr) { setStream(stream); }
151 0 : FileLogger::~FileLogger() noexcept {}
152 :
153 : // ============================================================================
154 : // [asmjit::FileLogger - Logging]
155 : // ============================================================================
156 :
157 0 : Error FileLogger::_log(const char* buf, size_t len) noexcept {
158 0 : if (!_stream)
159 : return kErrorOk;
160 :
161 0 : if (len == Globals::kInvalidIndex)
162 0 : len = strlen(buf);
163 :
164 0 : fwrite(buf, 1, len, _stream);
165 0 : return kErrorOk;
166 : }
167 :
168 : // ============================================================================
169 : // [asmjit::StringLogger - Construction / Destruction]
170 : // ============================================================================
171 :
172 0 : StringLogger::StringLogger() noexcept {}
173 0 : StringLogger::~StringLogger() noexcept {}
174 :
175 : // ============================================================================
176 : // [asmjit::StringLogger - Logging]
177 : // ============================================================================
178 :
179 0 : Error StringLogger::_log(const char* buf, size_t len) noexcept {
180 0 : return _stringBuilder.appendString(buf, len);
181 : }
182 :
183 : // ============================================================================
184 : // [asmjit::Logging]
185 : // ============================================================================
186 :
187 0 : Error Logging::formatLabel(
188 : StringBuilder& sb,
189 : uint32_t logOptions,
190 : const CodeEmitter* emitter,
191 : uint32_t labelId) noexcept {
192 :
193 : const LabelEntry* le = emitter->getCode()->getLabelEntry(labelId);
194 0 : if (ASMJIT_UNLIKELY(!le))
195 0 : return sb.appendFormat("InvalidLabel[Id=%u]", static_cast<unsigned int>(labelId));
196 :
197 0 : if (le->hasName()) {
198 0 : if (le->hasParent()) {
199 : uint32_t parentId = le->getParentId();
200 : const LabelEntry* pe = emitter->getCode()->getLabelEntry(parentId);
201 :
202 0 : if (ASMJIT_UNLIKELY(!pe))
203 0 : ASMJIT_PROPAGATE(sb.appendFormat("InvalidLabel[Id=%u]", static_cast<unsigned int>(labelId)));
204 0 : else if (ASMJIT_UNLIKELY(!pe->hasName()))
205 0 : ASMJIT_PROPAGATE(sb.appendFormat("L%u", Operand::unpackId(parentId)));
206 : else
207 0 : ASMJIT_PROPAGATE(sb.appendString(pe->getName()));
208 :
209 0 : ASMJIT_PROPAGATE(sb.appendChar('.'));
210 : }
211 0 : return sb.appendString(le->getName());
212 : }
213 : else {
214 0 : return sb.appendFormat("L%u", Operand::unpackId(labelId));
215 : }
216 : }
217 :
218 0 : Error Logging::formatRegister(
219 : StringBuilder& sb,
220 : uint32_t logOptions,
221 : const CodeEmitter* emitter,
222 : uint32_t archType,
223 : uint32_t regType,
224 : uint32_t regId) noexcept {
225 :
226 : #if defined(ASMJIT_BUILD_X86)
227 0 : return X86Logging::formatRegister(sb, logOptions, emitter, archType, regType, regId);
228 : #endif // ASMJIT_BUILD_X86
229 :
230 : #if defined(ASMJIT_BUILD_ARM)
231 : return ArmLogging::formatRegister(sb, logOptions, emitter, archType, regType, regId);
232 : #endif // ASMJIT_BUILD_ARM
233 :
234 : return kErrorInvalidArch;
235 : }
236 :
237 0 : Error Logging::formatOperand(
238 : StringBuilder& sb,
239 : uint32_t logOptions,
240 : const CodeEmitter* emitter,
241 : uint32_t archType,
242 : const Operand_& op) noexcept {
243 :
244 : #if defined(ASMJIT_BUILD_X86)
245 0 : return X86Logging::formatOperand(sb, logOptions, emitter, archType, op);
246 : #endif // ASMJIT_BUILD_X86
247 :
248 : #if defined(ASMJIT_BUILD_ARM)
249 : return ArmLogging::formatOperand(sb, logOptions, emitter, archType, op);
250 : #endif // ASMJIT_BUILD_ARM
251 :
252 : return kErrorInvalidArch;
253 : }
254 :
255 0 : Error Logging::formatInstruction(
256 : StringBuilder& sb,
257 : uint32_t logOptions,
258 : const CodeEmitter* emitter,
259 : uint32_t archType,
260 : const Inst::Detail& detail, const Operand_* opArray, uint32_t opCount) noexcept {
261 :
262 : #if defined(ASMJIT_BUILD_X86)
263 0 : return X86Logging::formatInstruction(sb, logOptions, emitter, archType, detail, opArray, opCount);
264 : #endif // ASMJIT_BUILD_X86
265 :
266 : #if defined(ASMJIT_BUILD_ARM)
267 : return ArmLogging::formatInstruction(sb, logOptions, emitter, archType, detail, opArray, opCount);
268 : #endif // ASMJIT_BUILD_ARM
269 :
270 : return kErrorInvalidArch;
271 : }
272 :
273 : #if !defined(ASMJIT_DISABLE_BUILDER)
274 0 : static Error formatTypeId(StringBuilder& sb, uint32_t typeId) noexcept {
275 0 : if (typeId == TypeId::kVoid)
276 0 : return sb.appendString("void");
277 :
278 0 : if (!TypeId::isValid(typeId))
279 0 : return sb.appendString("unknown");
280 :
281 : const char* typeName = "unknown";
282 : uint32_t typeSize = TypeId::sizeOf(typeId);
283 :
284 : uint32_t elementId = TypeId::elementOf(typeId);
285 0 : switch (elementId) {
286 0 : case TypeId::kIntPtr : typeName = "intptr" ; break;
287 0 : case TypeId::kUIntPtr: typeName = "uintptr"; break;
288 0 : case TypeId::kI8 : typeName = "i8" ; break;
289 0 : case TypeId::kU8 : typeName = "u8" ; break;
290 0 : case TypeId::kI16 : typeName = "i16" ; break;
291 0 : case TypeId::kU16 : typeName = "u16" ; break;
292 0 : case TypeId::kI32 : typeName = "i32" ; break;
293 0 : case TypeId::kU32 : typeName = "u32" ; break;
294 0 : case TypeId::kI64 : typeName = "i64" ; break;
295 0 : case TypeId::kU64 : typeName = "u64" ; break;
296 0 : case TypeId::kF32 : typeName = "f32" ; break;
297 0 : case TypeId::kF64 : typeName = "f64" ; break;
298 0 : case TypeId::kF80 : typeName = "f80" ; break;
299 0 : case TypeId::kMask8 : typeName = "mask8" ; break;
300 0 : case TypeId::kMask16 : typeName = "mask16" ; break;
301 0 : case TypeId::kMask32 : typeName = "mask32" ; break;
302 0 : case TypeId::kMask64 : typeName = "mask64" ; break;
303 0 : case TypeId::kMmx32 : typeName = "mmx32" ; break;
304 0 : case TypeId::kMmx64 : typeName = "mmx64" ; break;
305 : }
306 :
307 : uint32_t elementSize = TypeId::sizeOf(elementId);
308 0 : if (typeSize > elementSize) {
309 0 : unsigned int numElements = typeSize / elementSize;
310 0 : return sb.appendFormat("%sx%u", typeName, numElements);
311 : }
312 : else {
313 0 : return sb.appendString(typeName);
314 : }
315 : }
316 :
317 0 : static Error formatFuncDetailValue(
318 : StringBuilder& sb,
319 : uint32_t logOptions,
320 : const CodeEmitter* emitter,
321 : FuncDetail::Value value) noexcept {
322 :
323 : uint32_t typeId = value.getTypeId();
324 0 : ASMJIT_PROPAGATE(formatTypeId(sb, typeId));
325 :
326 0 : if (value.byReg()) {
327 0 : ASMJIT_PROPAGATE(sb.appendChar(':'));
328 0 : ASMJIT_PROPAGATE(Logging::formatRegister(sb, logOptions, emitter, emitter->getArchType(), value.getRegType(), value.getRegId()));
329 : }
330 :
331 0 : if (value.byStack()) {
332 0 : ASMJIT_PROPAGATE(sb.appendFormat(":[%d]", static_cast<int>(value.getStackOffset())));
333 : }
334 :
335 : return kErrorOk;
336 : }
337 :
338 0 : static Error formatFuncRets(
339 : StringBuilder& sb,
340 : uint32_t logOptions,
341 : const CodeEmitter* emitter,
342 : const FuncDetail& fd,
343 : VirtReg* const* vRegs) noexcept {
344 :
345 0 : if (!fd.hasRet())
346 0 : return sb.appendString("void");
347 :
348 0 : for (uint32_t i = 0; i < fd.getRetCount(); i++) {
349 0 : if (i) ASMJIT_PROPAGATE(sb.appendString(", "));
350 0 : ASMJIT_PROPAGATE(formatFuncDetailValue(sb, logOptions, emitter, fd.getRet(i)));
351 :
352 : #if !defined(ASMJIT_DISABLE_COMPILER)
353 0 : if (vRegs)
354 0 : ASMJIT_PROPAGATE(sb.appendFormat(" {%s}", vRegs[i]->getName()));
355 : #endif // !ASMJIT_DISABLE_COMPILER
356 : }
357 :
358 : return kErrorOk;
359 : }
360 :
361 0 : static Error formatFuncArgs(
362 : StringBuilder& sb,
363 : uint32_t logOptions,
364 : const CodeEmitter* emitter,
365 : const FuncDetail& fd,
366 : VirtReg* const* vRegs) noexcept {
367 :
368 0 : for (uint32_t i = 0; i < fd.getArgCount(); i++) {
369 0 : if (i) ASMJIT_PROPAGATE(sb.appendString(", "));
370 0 : ASMJIT_PROPAGATE(formatFuncDetailValue(sb, logOptions, emitter, fd.getArg(i)));
371 :
372 : #if !defined(ASMJIT_DISABLE_COMPILER)
373 0 : if (vRegs)
374 0 : ASMJIT_PROPAGATE(sb.appendFormat(" {%s}", vRegs[i]->getName()));
375 : #endif // !ASMJIT_DISABLE_COMPILER
376 : }
377 :
378 : return kErrorOk;
379 : }
380 :
381 0 : Error Logging::formatNode(
382 : StringBuilder& sb,
383 : uint32_t logOptions,
384 : const CodeBuilder* cb,
385 : const CBNode* node_) noexcept {
386 :
387 0 : if (node_->hasPosition())
388 0 : ASMJIT_PROPAGATE(sb.appendFormat("<%04u> ", node_->getPosition()));
389 :
390 0 : switch (node_->getType()) {
391 : case CBNode::kNodeInst: {
392 : const CBInst* node = node_->as<CBInst>();
393 0 : ASMJIT_PROPAGATE(
394 : Logging::formatInstruction(sb, logOptions, cb,
395 : cb->getArchType(),
396 : node->getInstDetail(), node->getOpArray(), node->getOpCount()));
397 : break;
398 : }
399 :
400 : case CBNode::kNodeLabel: {
401 : const CBLabel* node = node_->as<CBLabel>();
402 0 : ASMJIT_PROPAGATE(sb.appendFormat("L%u:", Operand::unpackId(node->getId())));
403 : break;
404 : }
405 :
406 : case CBNode::kNodeData: {
407 : const CBData* node = node_->as<CBData>();
408 0 : ASMJIT_PROPAGATE(sb.appendFormat(".embed (%u bytes)", node->getSize()));
409 : break;
410 : }
411 :
412 : case CBNode::kNodeAlign: {
413 : const CBAlign* node = node_->as<CBAlign>();
414 0 : ASMJIT_PROPAGATE(
415 : sb.appendFormat(".align %u (%s)",
416 : node->getAlignment(),
417 : node->getMode() == kAlignCode ? "code" : "data"));
418 : break;
419 : }
420 :
421 : case CBNode::kNodeComment: {
422 : const CBComment* node = node_->as<CBComment>();
423 0 : ASMJIT_PROPAGATE(sb.appendFormat("; %s", node->getInlineComment()));
424 : break;
425 : }
426 :
427 : case CBNode::kNodeSentinel: {
428 0 : ASMJIT_PROPAGATE(sb.appendString("[sentinel]"));
429 : break;
430 : }
431 :
432 : #if !defined(ASMJIT_DISABLE_COMPILER)
433 : case CBNode::kNodeFunc: {
434 : const CCFunc* node = node_->as<CCFunc>();
435 0 : ASMJIT_PROPAGATE(formatLabel(sb, logOptions, cb, node->getId()));
436 :
437 0 : ASMJIT_PROPAGATE(sb.appendString(": ["));
438 0 : ASMJIT_PROPAGATE(formatFuncRets(sb, logOptions, cb, node->getDetail(), nullptr));
439 0 : ASMJIT_PROPAGATE(sb.appendString("]"));
440 :
441 0 : ASMJIT_PROPAGATE(sb.appendString("("));
442 0 : ASMJIT_PROPAGATE(formatFuncArgs(sb, logOptions, cb, node->getDetail(), node->getArgs()));
443 0 : ASMJIT_PROPAGATE(sb.appendString(")"));
444 : break;
445 : }
446 :
447 : case CBNode::kNodeFuncExit: {
448 0 : ASMJIT_PROPAGATE(sb.appendString("[ret]"));
449 : break;
450 : }
451 :
452 : case CBNode::kNodeFuncCall: {
453 : const CCFuncCall* node = node_->as<CCFuncCall>();
454 0 : ASMJIT_PROPAGATE(
455 : Logging::formatInstruction(sb, logOptions, cb,
456 : cb->getArchType(),
457 : node->getInstDetail(), node->getOpArray(), node->getOpCount()));
458 : break;
459 : }
460 : #endif // !ASMJIT_DISABLE_COMPILER
461 :
462 : default: {
463 0 : ASMJIT_PROPAGATE(sb.appendFormat("[unknown (type=%u)]", node_->getType()));
464 : break;
465 : }
466 : }
467 :
468 : return kErrorOk;
469 : }
470 : #endif // !ASMJIT_DISABLE_BUILDER
471 :
472 0 : Error Logging::formatLine(StringBuilder& sb, const uint8_t* binData, size_t binLen, size_t dispLen, size_t imLen, const char* comment) noexcept {
473 : size_t currentLen = sb.getLength();
474 0 : size_t commentLen = comment ? Utils::strLen(comment, kMaxCommentLength) : 0;
475 :
476 : ASMJIT_ASSERT(binLen >= dispLen);
477 :
478 0 : if ((binLen != 0 && binLen != Globals::kInvalidIndex) || commentLen) {
479 : size_t align = kMaxInstLength;
480 : char sep = ';';
481 :
482 0 : for (size_t i = (binLen == Globals::kInvalidIndex); i < 2; i++) {
483 : size_t begin = sb.getLength();
484 :
485 : // Append align.
486 0 : if (currentLen < align)
487 0 : ASMJIT_PROPAGATE(sb.appendChars(' ', align - currentLen));
488 :
489 : // Append separator.
490 : if (sep) {
491 0 : ASMJIT_PROPAGATE(sb.appendChar(sep));
492 0 : ASMJIT_PROPAGATE(sb.appendChar(' '));
493 : }
494 :
495 : // Append binary data or comment.
496 0 : if (i == 0) {
497 0 : ASMJIT_PROPAGATE(sb.appendHex(binData, binLen - dispLen - imLen));
498 0 : ASMJIT_PROPAGATE(sb.appendChars('.', dispLen * 2));
499 0 : ASMJIT_PROPAGATE(sb.appendHex(binData + binLen - imLen, imLen));
500 0 : if (commentLen == 0) break;
501 : }
502 : else {
503 0 : ASMJIT_PROPAGATE(sb.appendString(comment, commentLen));
504 : }
505 :
506 0 : currentLen += sb.getLength() - begin;
507 0 : align += kMaxBinaryLength;
508 : sep = '|';
509 : }
510 : }
511 :
512 0 : return sb.appendChar('\n');
513 : }
514 :
515 : } // asmjit namespace
516 : } // namespace PLMD
517 :
518 : // [Api-End]
519 : #include "./asmjit_apiend.h"
520 :
521 : // [Guard]
522 : #endif // !ASMJIT_DISABLE_LOGGING
523 : #pragma GCC diagnostic pop
524 : #endif // __PLUMED_HAS_ASMJIT
|