blob: 75ae456c03b36e23c774d5274b2ac2ab556d57ac [file] [log] [blame]
buzbee67bf8852011-08-17 17:51:35 -07001/*
2 * Copyright (C) 2011 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 "ArmLIR.h"
buzbee67bc2362011-10-11 18:08:40 -070019#include "../Ralloc.h"
buzbee67bf8852011-08-17 17:51:35 -070020
Elliott Hughes3b6baaa2011-10-14 19:13:56 -070021#include <string>
22
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080023namespace art {
24
buzbee67bf8852011-08-17 17:51:35 -070025static const char* coreRegNames[16] = {
26 "r0",
27 "r1",
28 "r2",
29 "r3",
30 "r4",
31 "r5",
32 "r6",
33 "r7",
34 "r8",
35 "rSELF",
36 "r10",
37 "r11",
38 "r12",
39 "sp",
40 "lr",
41 "pc",
42};
43
44
45static const char* shiftNames[4] = {
46 "lsl",
47 "lsr",
48 "asr",
49 "ror"};
50
51/* Decode and print a ARM register name */
buzbeeed3e9302011-09-23 17:34:19 -070052STATIC char* decodeRegList(ArmOpcode opcode, int vector, char* buf)
buzbee67bf8852011-08-17 17:51:35 -070053{
54 int i;
55 bool printed = false;
56 buf[0] = 0;
57 for (i = 0; i < 16; i++, vector >>= 1) {
58 if (vector & 0x1) {
59 int regId = i;
60 if (opcode == kThumbPush && i == 8) {
61 regId = r14lr;
62 } else if (opcode == kThumbPop && i == 8) {
63 regId = r15pc;
64 }
65 if (printed) {
66 sprintf(buf + strlen(buf), ", r%d", regId);
67 } else {
68 printed = true;
69 sprintf(buf, "r%d", regId);
70 }
71 }
72 }
73 return buf;
74}
75
buzbeeed3e9302011-09-23 17:34:19 -070076STATIC char* decodeFPCSRegList(int count, int base, char* buf)
buzbee67bf8852011-08-17 17:51:35 -070077{
78 sprintf(buf, "s%d", base);
79 for (int i = 1; i < count; i++) {
80 sprintf(buf + strlen(buf), ", s%d",base + i);
81 }
82 return buf;
83}
84
buzbeeed3e9302011-09-23 17:34:19 -070085STATIC int expandImmediate(int value)
buzbee67bf8852011-08-17 17:51:35 -070086{
87 int mode = (value & 0xf00) >> 8;
88 u4 bits = value & 0xff;
89 switch(mode) {
90 case 0:
91 return bits;
92 case 1:
93 return (bits << 16) | bits;
94 case 2:
95 return (bits << 24) | (bits << 8);
96 case 3:
97 return (bits << 24) | (bits << 16) | (bits << 8) | bits;
98 default:
99 break;
100 }
101 bits = (bits | 0x80) << 24;
102 return bits >> (((value & 0xf80) >> 7) - 8);
103}
104
105const char* ccNames[] = {"eq","ne","cs","cc","mi","pl","vs","vc",
106 "hi","ls","ge","lt","gt","le","al","nv"};
107/*
108 * Interpret a format string and build a string no longer than size
109 * See format key in Assemble.c.
110 */
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700111STATIC std::string buildInsnString(const char* fmt, ArmLIR* lir, unsigned char* baseAddr)
buzbee67bf8852011-08-17 17:51:35 -0700112{
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700113 std::string buf;
buzbee67bf8852011-08-17 17:51:35 -0700114 int i;
buzbee67bf8852011-08-17 17:51:35 -0700115 const char* fmtEnd = &fmt[strlen(fmt)];
116 char tbuf[256];
117 const char* name;
118 char nc;
119 while (fmt < fmtEnd) {
120 int operand;
121 if (*fmt == '!') {
122 fmt++;
buzbeeed3e9302011-09-23 17:34:19 -0700123 DCHECK_LT(fmt, fmtEnd);
buzbee67bf8852011-08-17 17:51:35 -0700124 nc = *fmt++;
125 if (nc=='!') {
126 strcpy(tbuf, "!");
127 } else {
buzbeeed3e9302011-09-23 17:34:19 -0700128 DCHECK_LT(fmt, fmtEnd);
Elliott Hughesf5a7a472011-10-07 14:31:02 -0700129 DCHECK_LT((unsigned)(nc-'0'), 4U);
buzbee67bf8852011-08-17 17:51:35 -0700130 operand = lir->operands[nc-'0'];
131 switch(*fmt++) {
132 case 'H':
133 if (operand != 0) {
134 sprintf(tbuf, ", %s %d",shiftNames[operand & 0x3],
135 operand >> 2);
136 } else {
137 strcpy(tbuf,"");
138 }
139 break;
140 case 'B':
141 switch (operand) {
142 case kSY:
143 name = "sy";
144 break;
145 case kST:
146 name = "st";
147 break;
148 case kISH:
149 name = "ish";
150 break;
151 case kISHST:
152 name = "ishst";
153 break;
154 case kNSH:
155 name = "nsh";
156 break;
157 case kNSHST:
158 name = "shst";
159 break;
160 default:
161 name = "DecodeError2";
162 break;
163 }
164 strcpy(tbuf, name);
165 break;
166 case 'b':
167 strcpy(tbuf,"0000");
168 for (i=3; i>= 0; i--) {
169 tbuf[i] += operand & 1;
170 operand >>= 1;
171 }
172 break;
173 case 'n':
174 operand = ~expandImmediate(operand);
175 sprintf(tbuf,"%d [%#x]", operand, operand);
176 break;
177 case 'm':
178 operand = expandImmediate(operand);
179 sprintf(tbuf,"%d [%#x]", operand, operand);
180 break;
181 case 's':
182 sprintf(tbuf,"s%d",operand & FP_REG_MASK);
183 break;
184 case 'S':
185 sprintf(tbuf,"d%d",(operand & FP_REG_MASK) >> 1);
186 break;
187 case 'h':
188 sprintf(tbuf,"%04x", operand);
189 break;
190 case 'M':
191 case 'd':
192 sprintf(tbuf,"%d", operand);
193 break;
194 case 'C':
195 sprintf(tbuf,"%s",coreRegNames[operand]);
196 break;
197 case 'E':
198 sprintf(tbuf,"%d", operand*4);
199 break;
200 case 'F':
201 sprintf(tbuf,"%d", operand*2);
202 break;
203 case 'c':
204 strcpy(tbuf, ccNames[operand]);
205 break;
206 case 't':
207 sprintf(tbuf,"0x%08x (L%p)",
208 (int) baseAddr + lir->generic.offset + 4 +
209 (operand << 1),
210 lir->generic.target);
211 break;
212 case 'u': {
213 int offset_1 = lir->operands[0];
214 int offset_2 = NEXT_LIR(lir)->operands[0];
215 intptr_t target =
216 ((((intptr_t) baseAddr + lir->generic.offset + 4) &
217 ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
218 0xfffffffc;
219 sprintf(tbuf, "%p", (void *) target);
220 break;
221 }
222
223 /* Nothing to print for BLX_2 */
224 case 'v':
225 strcpy(tbuf, "see above");
226 break;
227 case 'R':
228 decodeRegList(lir->opcode, operand, tbuf);
229 break;
230 case 'P':
231 decodeFPCSRegList(operand, 16, tbuf);
232 break;
233 case 'Q':
234 decodeFPCSRegList(operand, 0, tbuf);
235 break;
236 default:
237 strcpy(tbuf,"DecodeError1");
238 break;
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700239 }
240 buf += tbuf;
buzbee67bf8852011-08-17 17:51:35 -0700241 }
242 } else {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700243 buf += *fmt++;
buzbee67bf8852011-08-17 17:51:35 -0700244 }
buzbee67bf8852011-08-17 17:51:35 -0700245 }
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700246 return buf;
buzbee67bf8852011-08-17 17:51:35 -0700247}
248
249void oatDumpResourceMask(LIR* lir, u8 mask, const char* prefix)
250{
251 char buf[256];
252 buf[0] = 0;
253 ArmLIR* armLIR = (ArmLIR*) lir;
254
255 if (mask == ENCODE_ALL) {
256 strcpy(buf, "all");
257 } else {
258 char num[8];
259 int i;
260
261 for (i = 0; i < kRegEnd; i++) {
262 if (mask & (1ULL << i)) {
263 sprintf(num, "%d ", i);
264 strcat(buf, num);
265 }
266 }
267
268 if (mask & ENCODE_CCODE) {
269 strcat(buf, "cc ");
270 }
271 if (mask & ENCODE_FP_STATUS) {
272 strcat(buf, "fpcc ");
273 }
274
275 /* Memory bits */
276 if (armLIR && (mask & ENCODE_DALVIK_REG)) {
277 sprintf(buf + strlen(buf), "dr%d%s", armLIR->aliasInfo & 0xffff,
278 (armLIR->aliasInfo & 0x80000000) ? "(+1)" : "");
279 }
280 if (mask & ENCODE_LITERAL) {
281 strcat(buf, "lit ");
282 }
283
284 if (mask & ENCODE_HEAP_REF) {
285 strcat(buf, "heap ");
286 }
287 if (mask & ENCODE_MUST_NOT_ALIAS) {
288 strcat(buf, "noalias ");
289 }
290 }
291 if (buf[0]) {
292 LOG(INFO) << prefix << ": " << buf;
293 }
294}
295
296/*
297 * Debugging macros
298 */
299#define DUMP_RESOURCE_MASK(X)
300#define DUMP_SSA_REP(X)
301
302/* Pretty-print a LIR instruction */
303void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr)
304{
305 ArmLIR* lir = (ArmLIR*) arg;
buzbee67bf8852011-08-17 17:51:35 -0700306 int offset = lir->generic.offset;
307 int dest = lir->operands[0];
308 const bool dumpNop = false;
309
310 /* Handle pseudo-ops individually, and all regular insns as a group */
311 switch(lir->opcode) {
312 case kArmPseudoMethodEntry:
313 LOG(INFO) << "-------- method entry " <<
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800314 PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
buzbee67bf8852011-08-17 17:51:35 -0700315 break;
316 case kArmPseudoMethodExit:
317 LOG(INFO) << "-------- Method_Exit";
318 break;
319 case kArmPseudoBarrier:
320 LOG(INFO) << "-------- BARRIER";
321 break;
322 case kArmPseudoExtended:
323 LOG(INFO) << "-------- " << (char* ) dest;
324 break;
325 case kArmPseudoSSARep:
326 DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " << (char* ) dest);
327 break;
328 case kArmPseudoEntryBlock:
329 LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
330 break;
331 case kArmPseudoDalvikByteCodeBoundary:
332 LOG(INFO) << "-------- dalvik offset: 0x" << std::hex <<
333 lir->generic.dalvikOffset << " @ " << (char* )lir->operands[0];
334 break;
335 case kArmPseudoExitBlock:
336 LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
337 break;
338 case kArmPseudoPseudoAlign4:
339 LOG(INFO) << (intptr_t)baseAddr + offset << " (0x" << std::hex <<
340 offset << "): .align4";
341 break;
342 case kArmPseudoEHBlockLabel:
343 LOG(INFO) << "Exception_Handling:";
344 break;
345 case kArmPseudoTargetLabel:
346 case kArmPseudoNormalBlockLabel:
347 LOG(INFO) << "L" << (intptr_t)lir << ":";
348 break;
buzbee5ade1d22011-09-09 14:44:52 -0700349 case kArmPseudoThrowTarget:
350 LOG(INFO) << "LT" << (intptr_t)lir << ":";
351 break;
buzbeec1f45042011-09-21 16:03:19 -0700352 case kArmPseudoSuspendTarget:
353 LOG(INFO) << "LS" << (intptr_t)lir << ":";
354 break;
buzbee67bf8852011-08-17 17:51:35 -0700355 case kArmPseudoCaseLabel:
356 LOG(INFO) << "LC" << (intptr_t)lir << ": Case target 0x" <<
357 std::hex << lir->operands[0] << "|" << std::dec <<
358 lir->operands[0];
359 break;
360 default:
361 if (lir->flags.isNop && !dumpNop) {
362 break;
buzbee3ea4ec52011-08-22 17:37:19 -0700363 } else {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700364 std::string op_name(buildInsnString(EncodingMap[lir->opcode].name, lir, baseAddr));
365 std::string op_operands(buildInsnString(EncodingMap[lir->opcode].fmt, lir, baseAddr));
buzbeee3acd072012-02-25 17:03:10 -0800366 LOG(INFO) << StringPrintf("%p (%04x): %-9s%s%s", baseAddr + offset, offset,
367 op_name.c_str(), op_operands.c_str(), lir->flags.isNop ? "(nop)" : "");
buzbee67bf8852011-08-17 17:51:35 -0700368 }
buzbee67bf8852011-08-17 17:51:35 -0700369 break;
370 }
371
372 if (lir->useMask && (!lir->flags.isNop || dumpNop)) {
373 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir,
374 lir->useMask, "use"));
375 }
376 if (lir->defMask && (!lir->flags.isNop || dumpNop)) {
377 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir,
378 lir->defMask, "def"));
379 }
380}
381
buzbee67bc2362011-10-11 18:08:40 -0700382void oatDumpPromotionMap(CompilationUnit *cUnit)
383{
Ian Rogersa3760aa2011-11-14 14:32:37 -0800384 for (int i = 0; i < cUnit->numDalvikRegisters; i++) {
buzbee67bc2362011-10-11 18:08:40 -0700385 PromotionMap vRegMap = cUnit->promotionMap[i];
386 char buf[100];
387 if (vRegMap.fpLocation == kLocPhysReg) {
388 snprintf(buf, 100, " : s%d", vRegMap.fpReg & FP_REG_MASK);
389 } else {
390 buf[0] = 0;
391 }
392 char buf2[100];
393 snprintf(buf2, 100, "V[%02d] -> %s%d%s", i,
394 vRegMap.coreLocation == kLocPhysReg ?
395 "r" : "SP+", vRegMap.coreLocation == kLocPhysReg ?
396 vRegMap.coreReg : oatSRegOffset(cUnit, i), buf);
397 LOG(INFO) << buf2;
398 }
399}
400
401void oatDumpFullPromotionMap(CompilationUnit *cUnit)
402{
Ian Rogersa3760aa2011-11-14 14:32:37 -0800403 for (int i = 0; i < cUnit->numDalvikRegisters; i++) {
buzbee67bc2362011-10-11 18:08:40 -0700404 PromotionMap vRegMap = cUnit->promotionMap[i];
405 LOG(INFO) << i << " -> " << "CL:" << (int)vRegMap.coreLocation <<
406 ", CR:" << (int)vRegMap.coreReg << ", FL:" <<
407 (int)vRegMap.fpLocation << ", FR:" << (int)vRegMap.fpReg <<
408 ", - " << (int)vRegMap.firstInPair;
409 }
410}
411
buzbee67bf8852011-08-17 17:51:35 -0700412/* Dump instructions and constant pool contents */
413void oatCodegenDump(CompilationUnit* cUnit)
414{
buzbee67bf8852011-08-17 17:51:35 -0700415 LOG(INFO) << "/*";
Ian Rogersa3760aa2011-11-14 14:32:37 -0800416 LOG(INFO) << "Dumping LIR insns for "
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800417 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
buzbee67bf8852011-08-17 17:51:35 -0700418 LIR* lirInsn;
419 ArmLIR* armLIR;
420 int insnsSize = cUnit->insnsSize;
421
422 LOG(INFO) << "Regs (excluding ins) : " << cUnit->numRegs;
423 LOG(INFO) << "Ins : " << cUnit->numIns;
424 LOG(INFO) << "Outs : " << cUnit->numOuts;
buzbeebbaf8942011-10-02 13:08:29 -0700425 LOG(INFO) << "CoreSpills : " << cUnit->numCoreSpills;
426 LOG(INFO) << "FPSpills : " << cUnit->numFPSpills;
buzbee67bf8852011-08-17 17:51:35 -0700427 LOG(INFO) << "Padding : " << cUnit->numPadding;
428 LOG(INFO) << "Frame size : " << cUnit->frameSize;
429 LOG(INFO) << "Start of ins : " << cUnit->insOffset;
430 LOG(INFO) << "Start of regs : " << cUnit->regsOffset;
431 LOG(INFO) << "code size is " << cUnit->totalSize <<
432 " bytes, Dalvik size is " << insnsSize * 2;
433 LOG(INFO) << "expansion factor: " <<
434 (float)cUnit->totalSize / (float)(insnsSize * 2);
buzbee67bc2362011-10-11 18:08:40 -0700435 oatDumpPromotionMap(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700436 for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
buzbeec143c552011-08-20 17:38:58 -0700437 oatDumpLIRInsn(cUnit, lirInsn, 0);
buzbee67bf8852011-08-17 17:51:35 -0700438 }
439 for (lirInsn = cUnit->classPointerList; lirInsn; lirInsn = lirInsn->next) {
440 armLIR = (ArmLIR*) lirInsn;
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700441 LOG(INFO) << StringPrintf("%x (%04x): .class (%s)",
442 armLIR->generic.offset, armLIR->generic.offset,
443 ((CallsiteInfo *) armLIR->operands[0])->classDescriptor);
buzbee67bf8852011-08-17 17:51:35 -0700444 }
445 for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
446 armLIR = (ArmLIR*) lirInsn;
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700447 LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)",
448 armLIR->generic.offset, armLIR->generic.offset, armLIR->operands[0]);
buzbee67bf8852011-08-17 17:51:35 -0700449 }
450
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800451 const DexFile::MethodId& method_id =
Ian Rogersa3760aa2011-11-14 14:32:37 -0800452 cUnit->dex_file->GetMethodId(cUnit->method_idx);
Elliott Hughes95572412011-12-13 18:14:20 -0800453 std::string signature(cUnit->dex_file->GetMethodSignature(method_id));
454 std::string name(cUnit->dex_file->GetMethodName(method_id));
455 std::string descriptor(cUnit->dex_file->GetMethodDeclaringClassDescriptor(method_id));
buzbeec143c552011-08-20 17:38:58 -0700456
buzbee67bf8852011-08-17 17:51:35 -0700457 // Dump mapping table
buzbee4ef76522011-09-08 10:00:32 -0700458 if (cUnit->mappingTable.size() > 0) {
Shih-wei Liaoc44c8222012-01-14 10:22:14 -0800459 std::string line(StringPrintf("\n MappingTable %s%s_%s_mappingTable[%zu] = {",
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700460 descriptor.c_str(), name.c_str(), signature.c_str(), cUnit->mappingTable.size()));
461 std::replace(line.begin(), line.end(), ';', '_');
462 LOG(INFO) << line;
buzbee4ef76522011-09-08 10:00:32 -0700463 for (uint32_t i = 0; i < cUnit->mappingTable.size(); i+=2) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700464 line = StringPrintf(" {0x%08x, 0x%04x},",
buzbee4ef76522011-09-08 10:00:32 -0700465 cUnit->mappingTable[i], cUnit->mappingTable[i+1]);
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700466 LOG(INFO) << line;
buzbee67bf8852011-08-17 17:51:35 -0700467 }
468 LOG(INFO) <<" };\n\n";
469 }
buzbee67bf8852011-08-17 17:51:35 -0700470}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800471
472} // namespace art