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