1 // AsmJit - Machine code generation for C++
2 //
3 // * Official AsmJit Home Page: https://asmjit.com
4 // * Official Github Repository: https://github.com/asmjit/asmjit
5 //
6 // Copyright (c) 2008-2020 The AsmJit Authors
7 //
8 // This software is provided 'as-is', without any express or implied
9 // warranty. In no event will the authors be held liable for any damages
10 // arising from the use of this software.
11 //
12 // Permission is granted to anyone to use this software for any purpose,
13 // including commercial applications, and to alter it and redistribute it
14 // freely, subject to the following restrictions:
15 //
16 // 1. The origin of this software must not be misrepresented; you must not
17 // claim that you wrote the original software. If you use this software
18 // in a product, an acknowledgment in the product documentation would be
19 // appreciated but is not required.
20 // 2. Altered source versions must be plainly marked as such, and must not be
21 // misrepresented as being the original software.
22 // 3. This notice may not be removed or altered from any source distribution.
23
24 #include "../core/api-build_p.h"
25 #include "../core/assembler.h"
26 #include "../core/emitterutils_p.h"
27 #include "../core/formatter.h"
28 #include "../core/logger.h"
29 #include "../core/support.h"
30
31 ASMJIT_BEGIN_NAMESPACE
32
33 // ============================================================================
34 // [asmjit::EmitterUtils]
35 // ============================================================================
36
37 namespace EmitterUtils {
38
39 #ifndef ASMJIT_NO_LOGGING
40
formatLine(String & sb,const uint8_t * binData,size_t binSize,size_t dispSize,size_t immSize,const char * comment)41 Error formatLine(String& sb, const uint8_t* binData, size_t binSize, size_t dispSize, size_t immSize, const char* comment) noexcept {
42 size_t currentSize = sb.size();
43 size_t commentSize = comment ? Support::strLen(comment, Globals::kMaxCommentSize) : 0;
44
45 ASMJIT_ASSERT(binSize >= dispSize);
46 const size_t kNoBinSize = SIZE_MAX;
47
48 if ((binSize != 0 && binSize != kNoBinSize) || commentSize) {
49 size_t align = kMaxInstLineSize;
50 char sep = ';';
51
52 for (size_t i = (binSize == kNoBinSize); i < 2; i++) {
53 size_t begin = sb.size();
54 ASMJIT_PROPAGATE(sb.padEnd(align));
55
56 if (sep) {
57 ASMJIT_PROPAGATE(sb.append(sep));
58 ASMJIT_PROPAGATE(sb.append(' '));
59 }
60
61 // Append binary data or comment.
62 if (i == 0) {
63 ASMJIT_PROPAGATE(sb.appendHex(binData, binSize - dispSize - immSize));
64 ASMJIT_PROPAGATE(sb.appendChars('.', dispSize * 2));
65 ASMJIT_PROPAGATE(sb.appendHex(binData + binSize - immSize, immSize));
66 if (commentSize == 0) break;
67 }
68 else {
69 ASMJIT_PROPAGATE(sb.append(comment, commentSize));
70 }
71
72 currentSize += sb.size() - begin;
73 align += kMaxBinarySize;
74 sep = '|';
75 }
76 }
77
78 return sb.append('\n');
79 }
80
logLabelBound(BaseAssembler * self,const Label & label)81 void logLabelBound(BaseAssembler* self, const Label& label) noexcept {
82 Logger* logger = self->logger();
83
84 StringTmp<512> sb;
85 size_t binSize = logger->hasFlag(FormatOptions::kFlagMachineCode) ? size_t(0) : SIZE_MAX;
86
87 sb.appendChars(' ', logger->indentation(FormatOptions::kIndentationLabel));
88 Formatter::formatLabel(sb, logger->flags(), self, label.id());
89 sb.append(':');
90 EmitterUtils::formatLine(sb, nullptr, binSize, 0, 0, self->_inlineComment);
91 logger->log(sb.data(), sb.size());
92 }
93
logInstructionEmitted(BaseAssembler * self,uint32_t instId,uint32_t options,const Operand_ & o0,const Operand_ & o1,const Operand_ & o2,const Operand_ * opExt,uint32_t relSize,uint32_t immSize,uint8_t * afterCursor)94 void logInstructionEmitted(
95 BaseAssembler* self,
96 uint32_t instId, uint32_t options, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt,
97 uint32_t relSize, uint32_t immSize, uint8_t* afterCursor) {
98
99 Logger* logger = self->logger();
100 ASMJIT_ASSERT(logger != nullptr);
101
102 StringTmp<256> sb;
103 uint32_t flags = logger->flags();
104
105 uint8_t* beforeCursor = self->bufferPtr();
106 intptr_t emittedSize = (intptr_t)(afterCursor - beforeCursor);
107
108 Operand_ opArray[Globals::kMaxOpCount];
109 EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt);
110
111 sb.appendChars(' ', logger->indentation(FormatOptions::kIndentationCode));
112 Formatter::formatInstruction(sb, flags, self, self->arch(), BaseInst(instId, options, self->extraReg()), opArray, Globals::kMaxOpCount);
113
114 if ((flags & FormatOptions::kFlagMachineCode) != 0)
115 EmitterUtils::formatLine(sb, self->bufferPtr(), size_t(emittedSize), relSize, immSize, self->inlineComment());
116 else
117 EmitterUtils::formatLine(sb, nullptr, SIZE_MAX, 0, 0, self->inlineComment());
118 logger->log(sb);
119 }
120
logInstructionFailed(BaseAssembler * self,Error err,uint32_t instId,uint32_t options,const Operand_ & o0,const Operand_ & o1,const Operand_ & o2,const Operand_ * opExt)121 Error logInstructionFailed(
122 BaseAssembler* self,
123 Error err,
124 uint32_t instId, uint32_t options, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) {
125
126 StringTmp<256> sb;
127 sb.append(DebugUtils::errorAsString(err));
128 sb.append(": ");
129
130 Operand_ opArray[Globals::kMaxOpCount];
131 EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt);
132
133 Formatter::formatInstruction(sb, 0, self, self->arch(), BaseInst(instId, options, self->extraReg()), opArray, Globals::kMaxOpCount);
134
135 if (self->inlineComment()) {
136 sb.append(" ; ");
137 sb.append(self->inlineComment());
138 }
139
140 self->resetInstOptions();
141 self->resetExtraReg();
142 self->resetInlineComment();
143 return self->reportError(err, sb.data());
144 }
145
146 #endif
147
148 } // {EmitterUtils}
149
150 ASMJIT_END_NAMESPACE
151