blob: f21843614291f3312b66033bd6197d8cd5328d24 [file] [log] [blame]
buzbeee3acd072012-02-25 17:03:10 -08001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "../../CompilerInternals.h"
18#include "MipsLIR.h"
19#include "../Ralloc.h"
20
21#include <string>
22
23namespace art {
24
25/* For dumping instructions */
26#define MIPS_REG_COUNT 32
27static const char *mipsRegName[MIPS_REG_COUNT] = {
28 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
29 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
30 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
31 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
32};
33
34/*
35 * Interpret a format string and build a string no longer than size
36 * See format key in Assemble.c.
37 */
38STATIC std::string buildInsnString(const char *fmt, MipsLIR *lir, unsigned char* baseAddr)
39{
40 std::string buf;
41 int i;
42 const char *fmtEnd = &fmt[strlen(fmt)];
43 char tbuf[256];
44 char nc;
45 while (fmt < fmtEnd) {
46 int operand;
47 if (*fmt == '!') {
48 fmt++;
49 DCHECK_LT(fmt, fmtEnd);
50 nc = *fmt++;
51 if (nc=='!') {
52 strcpy(tbuf, "!");
53 } else {
54 DCHECK_LT(fmt, fmtEnd);
55 DCHECK_LT((unsigned)(nc-'0'), 4u);
56 operand = lir->operands[nc-'0'];
57 switch(*fmt++) {
58 case 'b':
59 strcpy(tbuf,"0000");
60 for (i=3; i>= 0; i--) {
61 tbuf[i] += operand & 1;
62 operand >>= 1;
63 }
64 break;
65 case 's':
66 sprintf(tbuf,"$f%d",operand & FP_REG_MASK);
67 break;
68 case 'S':
69 DCHECK_EQ(((operand & FP_REG_MASK) & 1), 0);
70 sprintf(tbuf,"$f%d",operand & FP_REG_MASK);
71 break;
72 case 'h':
73 sprintf(tbuf,"%04x", operand);
74 break;
75 case 'M':
76 case 'd':
77 sprintf(tbuf,"%d", operand);
78 break;
79 case 'D':
80 sprintf(tbuf,"%d", operand+1);
81 break;
82 case 'E':
83 sprintf(tbuf,"%d", operand*4);
84 break;
85 case 'F':
86 sprintf(tbuf,"%d", operand*2);
87 break;
88 case 'c':
89 switch (operand) {
90 case kMipsCondEq:
91 strcpy(tbuf, "eq");
92 break;
93 case kMipsCondNe:
94 strcpy(tbuf, "ne");
95 break;
96 case kMipsCondLt:
97 strcpy(tbuf, "lt");
98 break;
99 case kMipsCondGe:
100 strcpy(tbuf, "ge");
101 break;
102 case kMipsCondGt:
103 strcpy(tbuf, "gt");
104 break;
105 case kMipsCondLe:
106 strcpy(tbuf, "le");
107 break;
108 case kMipsCondCs:
109 strcpy(tbuf, "cs");
110 break;
111 case kMipsCondMi:
112 strcpy(tbuf, "mi");
113 break;
114 default:
115 strcpy(tbuf, "");
116 break;
117 }
118 break;
119 case 't':
120 sprintf(tbuf,"0x%08x (L%p)",
121 (int) baseAddr + lir->generic.offset + 4 +
122 (operand << 2),
123 lir->generic.target);
124 break;
125 case 'T':
126 sprintf(tbuf,"0x%08x",
127 (int) (operand << 2));
128 break;
129 case 'u': {
130 int offset_1 = lir->operands[0];
131 int offset_2 = NEXT_LIR(lir)->operands[0];
132 intptr_t target =
133 ((((intptr_t) baseAddr + lir->generic.offset + 4) &
134 ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
135 0xfffffffc;
136 sprintf(tbuf, "%p", (void *) target);
137 break;
138 }
139
140 /* Nothing to print for BLX_2 */
141 case 'v':
142 strcpy(tbuf, "see above");
143 break;
144 case 'r':
145 DCHECK(operand >= 0 && operand < MIPS_REG_COUNT);
146 strcpy(tbuf, mipsRegName[operand]);
147 break;
148 default:
149 strcpy(tbuf,"DecodeError");
150 break;
151 }
152 buf += tbuf;
153 }
154 } else {
155 buf += *fmt++;
156 }
157 }
158 return buf;
159}
160
161// FIXME: need to redo resourse maps for MIPS - fix this at that time
162void oatDumpResourceMask(LIR *lir, u8 mask, const char *prefix)
163{
164 char buf[256];
165 buf[0] = 0;
166 MipsLIR *mipsLIR = (MipsLIR *) lir;
167
168 if (mask == ENCODE_ALL) {
169 strcpy(buf, "all");
170 } else {
171 char num[8];
172 int i;
173
174 for (i = 0; i < kRegEnd; i++) {
175 if (mask & (1ULL << i)) {
176 sprintf(num, "%d ", i);
177 strcat(buf, num);
178 }
179 }
180
181 if (mask & ENCODE_CCODE) {
182 strcat(buf, "cc ");
183 }
184 if (mask & ENCODE_FP_STATUS) {
185 strcat(buf, "fpcc ");
186 }
187 /* Memory bits */
188 if (mipsLIR && (mask & ENCODE_DALVIK_REG)) {
189 sprintf(buf + strlen(buf), "dr%d%s", mipsLIR->aliasInfo & 0xffff,
190 (mipsLIR->aliasInfo & 0x80000000) ? "(+1)" : "");
191 }
192 if (mask & ENCODE_LITERAL) {
193 strcat(buf, "lit ");
194 }
195
196 if (mask & ENCODE_HEAP_REF) {
197 strcat(buf, "heap ");
198 }
199 if (mask & ENCODE_MUST_NOT_ALIAS) {
200 strcat(buf, "noalias ");
201 }
202 }
203 if (buf[0]) {
204 LOG(INFO) << prefix << ": " << buf;
205 }
206}
207
208/*
209 * Debugging macros
210 */
211#define DUMP_RESOURCE_MASK(X)
212#define DUMP_SSA_REP(X)
213
214/* Pretty-print a LIR instruction */
215void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr)
216{
217 MipsLIR* lir = (MipsLIR*) arg;
218 int offset = lir->generic.offset;
219 int dest = lir->operands[0];
220 const bool dumpNop = false;
221
222 /* Handle pseudo-ops individually, and all regular insns as a group */
223 switch(lir->opcode) {
224 case kMipsPseudoMethodEntry:
225 LOG(INFO) << "-------- method entry " <<
226 PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
227 break;
228 case kMipsPseudoMethodExit:
229 LOG(INFO) << "-------- Method_Exit";
230 break;
231 case kMipsPseudoBarrier:
232 LOG(INFO) << "-------- BARRIER";
233 break;
234 case kMipsPseudoExtended:
235 LOG(INFO) << "-------- " << (char* ) dest;
236 break;
237 case kMipsPseudoSSARep:
238 DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " << (char* ) dest);
239 break;
240 case kMipsPseudoEntryBlock:
241 LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
242 break;
243 case kMipsPseudoDalvikByteCodeBoundary:
244 LOG(INFO) << "-------- dalvik offset: 0x" << std::hex <<
245 lir->generic.dalvikOffset << " @ " << (char* )lir->operands[0];
246 break;
247 case kMipsPseudoExitBlock:
248 LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
249 break;
250 case kMipsPseudoPseudoAlign4:
251 LOG(INFO) << (intptr_t)baseAddr + offset << " (0x" << std::hex <<
252 offset << "): .align4";
253 break;
254 case kMipsPseudoEHBlockLabel:
255 LOG(INFO) << "Exception_Handling:";
256 break;
257 case kMipsPseudoTargetLabel:
258 case kMipsPseudoNormalBlockLabel:
259 LOG(INFO) << "L" << (intptr_t)lir << ":";
260 break;
261 case kMipsPseudoThrowTarget:
262 LOG(INFO) << "LT" << (intptr_t)lir << ":";
263 break;
264 case kMipsPseudoSuspendTarget:
265 LOG(INFO) << "LS" << (intptr_t)lir << ":";
266 break;
267 case kMipsPseudoCaseLabel:
268 LOG(INFO) << "LC" << (intptr_t)lir << ": Case target 0x" <<
269 std::hex << lir->operands[0] << "|" << std::dec <<
270 lir->operands[0];
271 break;
272 default:
273 if (lir->flags.isNop && !dumpNop) {
274 break;
275 } else {
276 std::string op_name(buildInsnString(EncodingMap[lir->opcode].name, lir, baseAddr));
277 std::string op_operands(buildInsnString(EncodingMap[lir->opcode].fmt, lir, baseAddr));
278 LOG(INFO) << StringPrintf("%p (%04x): %-9s%s%s", baseAddr + offset, offset,
279 op_name.c_str(), op_operands.c_str(), lir->flags.isNop ? "(nop)" : "");
280 }
281 break;
282 }
283
284 if (lir->useMask && (!lir->flags.isNop || dumpNop)) {
285 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir,
286 lir->useMask, "use"));
287 }
288 if (lir->defMask && (!lir->flags.isNop || dumpNop)) {
289 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir,
290 lir->defMask, "def"));
291 }
292}
293
294void oatDumpPromotionMap(CompilationUnit *cUnit)
295{
296 for (int i = 0; i < cUnit->numDalvikRegisters; i++) {
297 PromotionMap vRegMap = cUnit->promotionMap[i];
298 char buf[100];
299 if (vRegMap.fpLocation == kLocPhysReg) {
300 snprintf(buf, 100, " : s%d", vRegMap.fpReg & FP_REG_MASK);
301 } else {
302 buf[0] = 0;
303 }
304 char buf2[100];
305 snprintf(buf2, 100, "V[%02d] -> %s%d%s", i,
306 vRegMap.coreLocation == kLocPhysReg ?
307 "r" : "SP+", vRegMap.coreLocation == kLocPhysReg ?
308 vRegMap.coreReg : oatSRegOffset(cUnit, i), buf);
309 LOG(INFO) << buf2;
310 }
311}
312
313void oatDumpFullPromotionMap(CompilationUnit *cUnit)
314{
315 for (int i = 0; i < cUnit->numDalvikRegisters; i++) {
316 PromotionMap vRegMap = cUnit->promotionMap[i];
317 LOG(INFO) << i << " -> " << "CL:" << (int)vRegMap.coreLocation <<
318 ", CR:" << (int)vRegMap.coreReg << ", FL:" <<
319 (int)vRegMap.fpLocation << ", FR:" << (int)vRegMap.fpReg <<
320 ", - " << (int)vRegMap.firstInPair;
321 }
322}
323
324/* Dump instructions and constant pool contents */
325void oatCodegenDump(CompilationUnit* cUnit)
326{
327 LOG(INFO) << "/*";
328 LOG(INFO) << "Dumping LIR insns for "
329 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
330 LIR* lirInsn;
331 MipsLIR* mipsLIR;
332 int insnsSize = cUnit->insnsSize;
333
334 LOG(INFO) << "Regs (excluding ins) : " << cUnit->numRegs;
335 LOG(INFO) << "Ins : " << cUnit->numIns;
336 LOG(INFO) << "Outs : " << cUnit->numOuts;
337 LOG(INFO) << "CoreSpills : " << cUnit->numCoreSpills;
338 LOG(INFO) << "FPSpills : " << cUnit->numFPSpills;
339 LOG(INFO) << "Padding : " << cUnit->numPadding;
340 LOG(INFO) << "Frame size : " << cUnit->frameSize;
341 LOG(INFO) << "Start of ins : " << cUnit->insOffset;
342 LOG(INFO) << "Start of regs : " << cUnit->regsOffset;
343 LOG(INFO) << "code size is " << cUnit->totalSize <<
344 " bytes, Dalvik size is " << insnsSize * 2;
345 LOG(INFO) << "expansion factor: " <<
346 (float)cUnit->totalSize / (float)(insnsSize * 2);
347 oatDumpPromotionMap(cUnit);
348 for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
349 oatDumpLIRInsn(cUnit, lirInsn, 0);
350 }
351 for (lirInsn = cUnit->classPointerList; lirInsn; lirInsn = lirInsn->next) {
352 mipsLIR = (MipsLIR*) lirInsn;
353 LOG(INFO) << StringPrintf("%x (%04x): .class (%s)",
354 mipsLIR->generic.offset, mipsLIR->generic.offset,
355 ((CallsiteInfo *) mipsLIR->operands[0])->classDescriptor);
356 }
357 for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
358 mipsLIR = (MipsLIR*) lirInsn;
359 LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)",
360 mipsLIR->generic.offset, mipsLIR->generic.offset, mipsLIR->operands[0]);
361 }
362
363 const DexFile::MethodId& method_id =
364 cUnit->dex_file->GetMethodId(cUnit->method_idx);
365 std::string signature(cUnit->dex_file->GetMethodSignature(method_id));
366 std::string name(cUnit->dex_file->GetMethodName(method_id));
367 std::string descriptor(cUnit->dex_file->GetMethodDeclaringClassDescriptor(method_id));
368
369 // Dump mapping table
370 if (cUnit->mappingTable.size() > 0) {
371 std::string line(StringPrintf("\n MappingTable %s%s_%s_mappingTable[%zu] = {",
372 descriptor.c_str(), name.c_str(), signature.c_str(), cUnit->mappingTable.size()));
373 std::replace(line.begin(), line.end(), ';', '_');
374 LOG(INFO) << line;
375 for (uint32_t i = 0; i < cUnit->mappingTable.size(); i+=2) {
376 line = StringPrintf(" {0x%08x, 0x%04x},",
377 cUnit->mappingTable[i], cUnit->mappingTable[i+1]);
378 LOG(INFO) << line;
379 }
380 LOG(INFO) <<" };\n\n";
381 }
382}
383
384} // namespace art