blob: 11982ba3ed74a545e430b78dca00210e853368cf [file] [log] [blame]
buzbeee3acd072012-02-25 17:03:10 -08001/*
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
17namespace art {
18
buzbee31a4a6f2012-02-28 15:36:15 -080019void setMemRefType(LIR* lir, bool isLoad, int memType)
20{
Bill Buzbeea114add2012-05-03 15:00:40 -070021 u8 *maskPtr;
22 u8 mask = ENCODE_MEM;;
23 DCHECK(EncodingMap[lir->opcode].flags & (IS_LOAD | IS_STORE));
24 if (isLoad) {
25 maskPtr = &lir->useMask;
26 } else {
27 maskPtr = &lir->defMask;
28 }
29 /* Clear out the memref flags */
30 *maskPtr &= ~mask;
31 /* ..and then add back the one we need */
32 switch (memType) {
33 case kLiteral:
34 DCHECK(isLoad);
35 *maskPtr |= ENCODE_LITERAL;
36 break;
37 case kDalvikReg:
38 *maskPtr |= ENCODE_DALVIK_REG;
39 break;
40 case kHeapRef:
41 *maskPtr |= ENCODE_HEAP_REF;
42 break;
43 case kMustNotAlias:
44 /* Currently only loads can be marked as kMustNotAlias */
45 DCHECK(!(EncodingMap[lir->opcode].flags & IS_STORE));
46 *maskPtr |= ENCODE_MUST_NOT_ALIAS;
47 break;
48 default:
49 LOG(FATAL) << "Oat: invalid memref kind - " << memType;
50 }
buzbee31a4a6f2012-02-28 15:36:15 -080051}
52
53/*
Ian Rogersb5d09b22012-03-06 22:14:17 -080054 * Mark load/store instructions that access Dalvik registers through the stack.
buzbee31a4a6f2012-02-28 15:36:15 -080055 */
Ian Rogersb5d09b22012-03-06 22:14:17 -080056void annotateDalvikRegAccess(LIR* lir, int regId, bool isLoad, bool is64bit)
buzbee31a4a6f2012-02-28 15:36:15 -080057{
Bill Buzbeea114add2012-05-03 15:00:40 -070058 setMemRefType(lir, isLoad, kDalvikReg);
buzbee31a4a6f2012-02-28 15:36:15 -080059
Bill Buzbeea114add2012-05-03 15:00:40 -070060 /*
61 * Store the Dalvik register id in aliasInfo. Mark the MSB if it is a 64-bit
62 * access.
63 */
64 lir->aliasInfo = regId;
65 if (is64bit) {
66 lir->aliasInfo |= 0x80000000;
67 }
buzbee31a4a6f2012-02-28 15:36:15 -080068}
69
70/*
71 * Decode the register id.
72 */
73inline u8 getRegMaskCommon(int reg)
74{
Bill Buzbeea114add2012-05-03 15:00:40 -070075 u8 seed;
76 int shift;
77 int regId = reg & 0x1f;
buzbee31a4a6f2012-02-28 15:36:15 -080078
Bill Buzbeea114add2012-05-03 15:00:40 -070079 /*
80 * Each double register is equal to a pair of single-precision FP registers
81 */
82 seed = DOUBLEREG(reg) ? 3 : 1;
83 /* FP register starts at bit position 16 */
84 shift = FPREG(reg) ? kFPReg0 : 0;
85 /* Expand the double register id into single offset */
86 shift += regId;
87 return (seed << shift);
buzbee31a4a6f2012-02-28 15:36:15 -080088}
89
90/*
91 * Mark the corresponding bit(s).
92 */
93inline void setupRegMask(u8* mask, int reg)
94{
Bill Buzbeea114add2012-05-03 15:00:40 -070095 *mask |= getRegMaskCommon(reg);
buzbee31a4a6f2012-02-28 15:36:15 -080096}
97
98/*
99 * Set up the proper fields in the resource mask
100 */
101void setupResourceMasks(LIR* lir)
102{
Bill Buzbeea114add2012-05-03 15:00:40 -0700103 int opcode = lir->opcode;
104 int flags;
buzbee31a4a6f2012-02-28 15:36:15 -0800105
Bill Buzbeea114add2012-05-03 15:00:40 -0700106 if (opcode <= 0) {
107 lir->useMask = lir->defMask = 0;
108 return;
109 }
buzbee31a4a6f2012-02-28 15:36:15 -0800110
Bill Buzbeea114add2012-05-03 15:00:40 -0700111 flags = EncodingMap[lir->opcode].flags;
buzbee31a4a6f2012-02-28 15:36:15 -0800112
Bill Buzbeea114add2012-05-03 15:00:40 -0700113 if (flags & NEEDS_FIXUP) {
114 lir->flags.pcRelFixup = true;
115 }
buzbee31a4a6f2012-02-28 15:36:15 -0800116
Bill Buzbeea114add2012-05-03 15:00:40 -0700117 /* Get the starting size of the instruction's template */
118 lir->flags.size = oatGetInsnSize(lir);
buzbeee88dfbf2012-03-05 11:19:57 -0800119
Bill Buzbeea114add2012-05-03 15:00:40 -0700120 /* Set up the mask for resources that are updated */
121 if (flags & (IS_LOAD | IS_STORE)) {
122 /* Default to heap - will catch specialized classes later */
123 setMemRefType(lir, flags & IS_LOAD, kHeapRef);
124 }
buzbee31a4a6f2012-02-28 15:36:15 -0800125
Bill Buzbeea114add2012-05-03 15:00:40 -0700126 /*
127 * Conservatively assume the branch here will call out a function that in
128 * turn will trash everything.
129 */
130 if (flags & IS_BRANCH) {
131 lir->defMask = lir->useMask = ENCODE_ALL;
132 return;
133 }
buzbee31a4a6f2012-02-28 15:36:15 -0800134
Bill Buzbeea114add2012-05-03 15:00:40 -0700135 if (flags & REG_DEF0) {
136 setupRegMask(&lir->defMask, lir->operands[0]);
137 }
buzbee31a4a6f2012-02-28 15:36:15 -0800138
Bill Buzbeea114add2012-05-03 15:00:40 -0700139 if (flags & REG_DEF1) {
140 setupRegMask(&lir->defMask, lir->operands[1]);
141 }
buzbee31a4a6f2012-02-28 15:36:15 -0800142
Bill Buzbeea114add2012-05-03 15:00:40 -0700143 if (flags & REG_DEF_SP) {
144 lir->defMask |= ENCODE_REG_SP;
145 }
buzbee31a4a6f2012-02-28 15:36:15 -0800146
buzbeea7678db2012-03-05 15:35:46 -0800147#if !defined(TARGET_X86)
Bill Buzbeea114add2012-05-03 15:00:40 -0700148 if (flags & REG_DEF_LR) {
149 lir->defMask |= ENCODE_REG_LR;
150 }
buzbeea7678db2012-03-05 15:35:46 -0800151#endif
buzbee31a4a6f2012-02-28 15:36:15 -0800152
Bill Buzbeea114add2012-05-03 15:00:40 -0700153 if (flags & REG_DEF_LIST0) {
154 lir->defMask |= ENCODE_REG_LIST(lir->operands[0]);
155 }
buzbee31a4a6f2012-02-28 15:36:15 -0800156
Bill Buzbeea114add2012-05-03 15:00:40 -0700157 if (flags & REG_DEF_LIST1) {
158 lir->defMask |= ENCODE_REG_LIST(lir->operands[1]);
159 }
buzbee31a4a6f2012-02-28 15:36:15 -0800160
buzbee5de34942012-03-01 14:51:57 -0800161#if defined(TARGET_ARM)
Bill Buzbeea114add2012-05-03 15:00:40 -0700162 if (flags & REG_DEF_FPCS_LIST0) {
163 lir->defMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]);
164 }
buzbee31a4a6f2012-02-28 15:36:15 -0800165
Bill Buzbeea114add2012-05-03 15:00:40 -0700166 if (flags & REG_DEF_FPCS_LIST2) {
167 for (int i = 0; i < lir->operands[2]; i++) {
168 setupRegMask(&lir->defMask, lir->operands[1] + i);
buzbee31a4a6f2012-02-28 15:36:15 -0800169 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700170 }
buzbee5de34942012-03-01 14:51:57 -0800171#endif
buzbee31a4a6f2012-02-28 15:36:15 -0800172
Bill Buzbeea114add2012-05-03 15:00:40 -0700173 if (flags & SETS_CCODES) {
174 lir->defMask |= ENCODE_CCODE;
175 }
buzbee31a4a6f2012-02-28 15:36:15 -0800176
177#if defined(TARGET_ARM)
Bill Buzbeea114add2012-05-03 15:00:40 -0700178 /* Conservatively treat the IT block */
179 if (flags & IS_IT) {
180 lir->defMask = ENCODE_ALL;
181 }
buzbee31a4a6f2012-02-28 15:36:15 -0800182#endif
183
Bill Buzbeea114add2012-05-03 15:00:40 -0700184 if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) {
185 int i;
buzbee31a4a6f2012-02-28 15:36:15 -0800186
Bill Buzbeea114add2012-05-03 15:00:40 -0700187 for (i = 0; i < 4; i++) {
188 if (flags & (1 << (kRegUse0 + i))) {
189 setupRegMask(&lir->useMask, lir->operands[i]);
190 }
buzbee31a4a6f2012-02-28 15:36:15 -0800191 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700192 }
buzbee31a4a6f2012-02-28 15:36:15 -0800193
buzbeea7678db2012-03-05 15:35:46 -0800194#if defined(TARGET_ARM)
Bill Buzbeea114add2012-05-03 15:00:40 -0700195 if (flags & REG_USE_PC) {
196 lir->useMask |= ENCODE_REG_PC;
197 }
buzbeea7678db2012-03-05 15:35:46 -0800198#endif
buzbee31a4a6f2012-02-28 15:36:15 -0800199
Bill Buzbeea114add2012-05-03 15:00:40 -0700200 if (flags & REG_USE_SP) {
201 lir->useMask |= ENCODE_REG_SP;
202 }
buzbee31a4a6f2012-02-28 15:36:15 -0800203
Bill Buzbeea114add2012-05-03 15:00:40 -0700204 if (flags & REG_USE_LIST0) {
205 lir->useMask |= ENCODE_REG_LIST(lir->operands[0]);
206 }
buzbee31a4a6f2012-02-28 15:36:15 -0800207
Bill Buzbeea114add2012-05-03 15:00:40 -0700208 if (flags & REG_USE_LIST1) {
209 lir->useMask |= ENCODE_REG_LIST(lir->operands[1]);
210 }
buzbee31a4a6f2012-02-28 15:36:15 -0800211
buzbee5de34942012-03-01 14:51:57 -0800212#if defined(TARGET_ARM)
Bill Buzbeea114add2012-05-03 15:00:40 -0700213 if (flags & REG_USE_FPCS_LIST0) {
214 lir->useMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]);
215 }
buzbee31a4a6f2012-02-28 15:36:15 -0800216
Bill Buzbeea114add2012-05-03 15:00:40 -0700217 if (flags & REG_USE_FPCS_LIST2) {
218 for (int i = 0; i < lir->operands[2]; i++) {
219 setupRegMask(&lir->useMask, lir->operands[1] + i);
buzbee31a4a6f2012-02-28 15:36:15 -0800220 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700221 }
buzbee5de34942012-03-01 14:51:57 -0800222#endif
buzbee31a4a6f2012-02-28 15:36:15 -0800223
Bill Buzbeea114add2012-05-03 15:00:40 -0700224 if (flags & USES_CCODES) {
225 lir->useMask |= ENCODE_CCODE;
226 }
buzbee31a4a6f2012-02-28 15:36:15 -0800227
228#if defined(TARGET_ARM)
Bill Buzbeea114add2012-05-03 15:00:40 -0700229 /* Fixup for kThumbPush/lr and kThumbPop/pc */
230 if (opcode == kThumbPush || opcode == kThumbPop) {
231 u8 r8Mask = getRegMaskCommon(r8);
232 if ((opcode == kThumbPush) && (lir->useMask & r8Mask)) {
233 lir->useMask &= ~r8Mask;
234 lir->useMask |= ENCODE_REG_LR;
235 } else if ((opcode == kThumbPop) && (lir->defMask & r8Mask)) {
236 lir->defMask &= ~r8Mask;
237 lir->defMask |= ENCODE_REG_PC;
buzbee31a4a6f2012-02-28 15:36:15 -0800238 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700239 }
buzbee31a4a6f2012-02-28 15:36:15 -0800240#endif
241}
242
243/*
buzbee5de34942012-03-01 14:51:57 -0800244 * Debugging macros
245 */
246#define DUMP_RESOURCE_MASK(X)
247#define DUMP_SSA_REP(X)
248
249/* Pretty-print a LIR instruction */
250void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr)
251{
Bill Buzbeea114add2012-05-03 15:00:40 -0700252 LIR* lir = (LIR*) arg;
253 int offset = lir->offset;
254 int dest = lir->operands[0];
255 const bool dumpNop = (cUnit->enableDebug & (1 << kDebugShowNops));
buzbee5de34942012-03-01 14:51:57 -0800256
Bill Buzbeea114add2012-05-03 15:00:40 -0700257 /* Handle pseudo-ops individually, and all regular insns as a group */
258 switch (lir->opcode) {
259 case kPseudoMethodEntry:
260 LOG(INFO) << "-------- method entry "
261 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
262 break;
263 case kPseudoMethodExit:
264 LOG(INFO) << "-------- Method_Exit";
265 break;
266 case kPseudoBarrier:
267 LOG(INFO) << "-------- BARRIER";
268 break;
269 case kPseudoExtended:
270 LOG(INFO) << "-------- " << (char* ) dest;
271 break;
272 case kPseudoSSARep:
273 DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " << (char* ) dest);
274 break;
275 case kPseudoEntryBlock:
276 LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
277 break;
278 case kPseudoDalvikByteCodeBoundary:
279 LOG(INFO) << "-------- dalvik offset: 0x" << std::hex
280 << lir->dalvikOffset << " @ " << (char* )lir->operands[0];
281 break;
282 case kPseudoExitBlock:
283 LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
284 break;
285 case kPseudoPseudoAlign4:
286 LOG(INFO) << (intptr_t)baseAddr + offset << " (0x" << std::hex
287 << offset << "): .align4";
288 break;
289 case kPseudoEHBlockLabel:
290 LOG(INFO) << "Exception_Handling:";
291 break;
292 case kPseudoTargetLabel:
293 case kPseudoNormalBlockLabel:
294 LOG(INFO) << "L" << (void*)lir << ":";
295 break;
296 case kPseudoThrowTarget:
297 LOG(INFO) << "LT" << (void*)lir << ":";
298 break;
299 case kPseudoIntrinsicRetry:
300 LOG(INFO) << "IR" << (void*)lir << ":";
301 break;
302 case kPseudoSuspendTarget:
303 LOG(INFO) << "LS" << (void*)lir << ":";
304 break;
305 case kPseudoCaseLabel:
306 LOG(INFO) << "LC" << (void*)lir << ": Case target 0x"
307 << std::hex << lir->operands[0] << "|" << std::dec <<
308 lir->operands[0];
309 break;
310 default:
311 if (lir->flags.isNop && !dumpNop) {
312 break;
313 } else {
314 std::string op_name(buildInsnString(EncodingMap[lir->opcode].name,
315 lir, baseAddr));
316 std::string op_operands(buildInsnString(EncodingMap[lir->opcode].fmt
317 , lir, baseAddr));
318 LOG(INFO) << StringPrintf("%05x: %-9s%s%s",
319 (unsigned int)(baseAddr + offset),
320 op_name.c_str(), op_operands.c_str(),
321 lir->flags.isNop ? "(nop)" : "");
322 }
323 break;
324 }
buzbee5de34942012-03-01 14:51:57 -0800325
Bill Buzbeea114add2012-05-03 15:00:40 -0700326 if (lir->useMask && (!lir->flags.isNop || dumpNop)) {
327 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->useMask, "use"));
328 }
329 if (lir->defMask && (!lir->flags.isNop || dumpNop)) {
330 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->defMask, "def"));
331 }
buzbee5de34942012-03-01 14:51:57 -0800332}
333
334void oatDumpPromotionMap(CompilationUnit *cUnit)
335{
Bill Buzbeea114add2012-05-03 15:00:40 -0700336 int numRegs = cUnit->numDalvikRegisters + cUnit->numCompilerTemps + 1;
337 for (int i = 0; i < numRegs; i++) {
338 PromotionMap vRegMap = cUnit->promotionMap[i];
339 std::string buf;
340 if (vRegMap.fpLocation == kLocPhysReg) {
341 StringAppendF(&buf, " : s%d", vRegMap.fpReg & FP_REG_MASK);
buzbee5de34942012-03-01 14:51:57 -0800342 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700343
344 std::string buf3;
345 if (i < cUnit->numDalvikRegisters) {
346 StringAppendF(&buf3, "%02d", i);
347 } else if (i == cUnit->methodSReg) {
348 buf3 = "Method*";
349 } else {
350 StringAppendF(&buf3, "ct%d", i - cUnit->numDalvikRegisters);
351 }
352
353 LOG(INFO) << StringPrintf("V[%s] -> %s%d%s", buf3.c_str(),
354 vRegMap.coreLocation == kLocPhysReg ?
355 "r" : "SP+", vRegMap.coreLocation == kLocPhysReg ?
356 vRegMap.coreReg : oatSRegOffset(cUnit, i),
357 buf.c_str());
358 }
buzbee5de34942012-03-01 14:51:57 -0800359}
360
buzbee5de34942012-03-01 14:51:57 -0800361/* Dump instructions and constant pool contents */
362void oatCodegenDump(CompilationUnit* cUnit)
363{
Bill Buzbeea114add2012-05-03 15:00:40 -0700364 LOG(INFO) << "/*";
365 LOG(INFO) << "Dumping LIR insns for "
366 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
367 LIR* lirInsn;
368 LIR* thisLIR;
369 int insnsSize = cUnit->insnsSize;
buzbee5de34942012-03-01 14:51:57 -0800370
Bill Buzbeea114add2012-05-03 15:00:40 -0700371 LOG(INFO) << "Regs (excluding ins) : " << cUnit->numRegs;
372 LOG(INFO) << "Ins : " << cUnit->numIns;
373 LOG(INFO) << "Outs : " << cUnit->numOuts;
374 LOG(INFO) << "CoreSpills : " << cUnit->numCoreSpills;
375 LOG(INFO) << "FPSpills : " << cUnit->numFPSpills;
376 LOG(INFO) << "CompilerTemps : " << cUnit->numCompilerTemps;
377 LOG(INFO) << "Frame size : " << cUnit->frameSize;
378 LOG(INFO) << "code size is " << cUnit->totalSize <<
379 " bytes, Dalvik size is " << insnsSize * 2;
380 LOG(INFO) << "expansion factor: "
381 << (float)cUnit->totalSize / (float)(insnsSize * 2);
382 oatDumpPromotionMap(cUnit);
383 for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
384 oatDumpLIRInsn(cUnit, lirInsn, 0);
385 }
386 for (lirInsn = cUnit->classPointerList; lirInsn; lirInsn = lirInsn->next) {
387 thisLIR = (LIR*) lirInsn;
388 LOG(INFO) << StringPrintf("%x (%04x): .class (%s)",
389 thisLIR->offset, thisLIR->offset,
390 ((CallsiteInfo *)
391 thisLIR->operands[0])->classDescriptor);
392 }
393 for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
394 thisLIR = (LIR*) lirInsn;
395 LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)",
396 thisLIR->offset, thisLIR->offset,
397 thisLIR->operands[0]);
398 }
buzbee5de34942012-03-01 14:51:57 -0800399
Bill Buzbeea114add2012-05-03 15:00:40 -0700400 const DexFile::MethodId& method_id =
401 cUnit->dex_file->GetMethodId(cUnit->method_idx);
402 std::string signature(cUnit->dex_file->GetMethodSignature(method_id));
403 std::string name(cUnit->dex_file->GetMethodName(method_id));
404 std::string descriptor(cUnit->dex_file->GetMethodDeclaringClassDescriptor(method_id));
buzbee5de34942012-03-01 14:51:57 -0800405
Bill Buzbeea114add2012-05-03 15:00:40 -0700406 // Dump mapping table
407 if (cUnit->mappingTable.size() > 0) {
408 std::string
409 line(StringPrintf("\n MappingTable %s%s_%s_mappingTable[%zu] = {",
410 descriptor.c_str(), name.c_str(), signature.c_str(),
411 cUnit->mappingTable.size()));
412 std::replace(line.begin(), line.end(), ';', '_');
413 LOG(INFO) << line;
414 for (uint32_t i = 0; i < cUnit->mappingTable.size(); i+=2) {
415 line = StringPrintf(" {0x%05x, 0x%04x},",
416 cUnit->mappingTable[i], cUnit->mappingTable[i+1]);
417 LOG(INFO) << line;
buzbee5de34942012-03-01 14:51:57 -0800418 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700419 LOG(INFO) <<" };\n\n";
420 }
buzbee5de34942012-03-01 14:51:57 -0800421}
422
buzbeea2ebdd72012-03-04 14:57:06 -0800423
424LIR* rawLIR(CompilationUnit* cUnit, int dalvikOffset, int opcode, int op0,
Bill Buzbeea114add2012-05-03 15:00:40 -0700425 int op1, int op2, int op3, int op4, LIR* target)
buzbeea2ebdd72012-03-04 14:57:06 -0800426{
Bill Buzbeea114add2012-05-03 15:00:40 -0700427 LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
428 insn->dalvikOffset = dalvikOffset;
429 insn->opcode = opcode;
430 insn->operands[0] = op0;
431 insn->operands[1] = op1;
432 insn->operands[2] = op2;
433 insn->operands[3] = op3;
434 insn->operands[4] = op4;
435 insn->target = target;
436 oatSetupResourceMasks(insn);
437 if (opcode == kPseudoTargetLabel) {
438 // Always make labels scheduling barriers
439 insn->defMask = ENCODE_ALL;
440 }
441 return insn;
buzbeea2ebdd72012-03-04 14:57:06 -0800442}
443
buzbee5de34942012-03-01 14:51:57 -0800444/*
buzbee31a4a6f2012-02-28 15:36:15 -0800445 * The following are building blocks to construct low-level IRs with 0 - 4
446 * operands.
447 */
buzbee5de34942012-03-01 14:51:57 -0800448LIR* newLIR0(CompilationUnit* cUnit, int opcode)
buzbee31a4a6f2012-02-28 15:36:15 -0800449{
Bill Buzbeea114add2012-05-03 15:00:40 -0700450 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND))
451 << EncodingMap[opcode].name << " " << (int)opcode << " "
452 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
453 << cUnit->currentDalvikOffset;
454 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode);
455 oatAppendLIR(cUnit, (LIR*) insn);
456 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800457}
458
buzbee5de34942012-03-01 14:51:57 -0800459LIR* newLIR1(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700460 int dest)
buzbee31a4a6f2012-02-28 15:36:15 -0800461{
Bill Buzbeea114add2012-05-03 15:00:40 -0700462 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_UNARY_OP))
463 << EncodingMap[opcode].name << " " << (int)opcode << " "
464 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
465 << cUnit->currentDalvikOffset;
466 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest);
467 oatAppendLIR(cUnit, (LIR*) insn);
468 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800469}
470
buzbee5de34942012-03-01 14:51:57 -0800471LIR* newLIR2(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700472 int dest, int src1)
buzbee31a4a6f2012-02-28 15:36:15 -0800473{
Bill Buzbeea114add2012-05-03 15:00:40 -0700474 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_BINARY_OP))
475 << EncodingMap[opcode].name << " " << (int)opcode << " "
476 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
477 << cUnit->currentDalvikOffset;
478 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1);
479 oatAppendLIR(cUnit, (LIR*) insn);
480 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800481}
482
buzbee5de34942012-03-01 14:51:57 -0800483LIR* newLIR3(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700484 int dest, int src1, int src2)
buzbee31a4a6f2012-02-28 15:36:15 -0800485{
Bill Buzbeea114add2012-05-03 15:00:40 -0700486 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_TERTIARY_OP))
487 << EncodingMap[opcode].name << " " << (int)opcode << " "
488 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
489 << cUnit->currentDalvikOffset;
490 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
491 src2);
492 oatAppendLIR(cUnit, (LIR*) insn);
493 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800494}
495
buzbee5de34942012-03-01 14:51:57 -0800496LIR* newLIR4(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700497 int dest, int src1, int src2, int info)
buzbee31a4a6f2012-02-28 15:36:15 -0800498{
Bill Buzbeea114add2012-05-03 15:00:40 -0700499 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUAD_OP))
500 << EncodingMap[opcode].name << " " << (int)opcode << " "
501 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
502 << cUnit->currentDalvikOffset;
503 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
504 src2, info);
505 oatAppendLIR(cUnit, (LIR*) insn);
506 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800507}
buzbee31a4a6f2012-02-28 15:36:15 -0800508
Ian Rogersb5d09b22012-03-06 22:14:17 -0800509LIR* newLIR5(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700510 int dest, int src1, int src2, int info1, int info2)
Ian Rogersb5d09b22012-03-06 22:14:17 -0800511{
Bill Buzbeea114add2012-05-03 15:00:40 -0700512 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUIN_OP))
513 << EncodingMap[opcode].name << " " << (int)opcode << " "
514 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
515 << cUnit->currentDalvikOffset;
516 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
517 src2, info1, info2);
518 oatAppendLIR(cUnit, (LIR*) insn);
519 return insn;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800520}
521
buzbee31a4a6f2012-02-28 15:36:15 -0800522/*
523 * Search the existing constants in the literal pool for an exact or close match
524 * within specified delta (greater or equal to 0).
525 */
526LIR* scanLiteralPool(LIR* dataTarget, int value, unsigned int delta)
527{
Bill Buzbeea114add2012-05-03 15:00:40 -0700528 while (dataTarget) {
529 if (((unsigned) (value - ((LIR* ) dataTarget)->operands[0])) <= delta)
530 return (LIR* ) dataTarget;
531 dataTarget = dataTarget->next;
532 }
533 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800534}
535
536/* Search the existing constants in the literal pool for an exact wide match */
537LIR* scanLiteralPoolWide(LIR* dataTarget, int valLo, int valHi)
538{
Bill Buzbeea114add2012-05-03 15:00:40 -0700539 bool loMatch = false;
540 LIR* loTarget = NULL;
541 while (dataTarget) {
542 if (loMatch && (((LIR*)dataTarget)->operands[0] == valHi)) {
543 return (LIR*)loTarget;
buzbee31a4a6f2012-02-28 15:36:15 -0800544 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700545 loMatch = false;
546 if (((LIR*)dataTarget)->operands[0] == valLo) {
547 loMatch = true;
548 loTarget = dataTarget;
549 }
550 dataTarget = dataTarget->next;
551 }
552 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800553}
554
555/*
556 * The following are building blocks to insert constants into the pool or
557 * instruction streams.
558 */
559
buzbee5de34942012-03-01 14:51:57 -0800560/* Add a 32-bit constant either in the constant pool */
Ian Rogers3fa13792012-03-18 15:53:45 -0700561LIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP, int value)
buzbee31a4a6f2012-02-28 15:36:15 -0800562{
Bill Buzbeea114add2012-05-03 15:00:40 -0700563 /* Add the constant to the literal pool */
564 if (constantListP) {
565 LIR* newValue = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocData);
566 newValue->operands[0] = value;
567 newValue->next = *constantListP;
568 *constantListP = (LIR*) newValue;
569 return newValue;
570 }
571 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800572}
573
574/* Add a 64-bit constant to the constant pool or mixed with code */
575LIR* addWideData(CompilationUnit* cUnit, LIR* *constantListP,
Bill Buzbeea114add2012-05-03 15:00:40 -0700576 int valLo, int valHi)
buzbee31a4a6f2012-02-28 15:36:15 -0800577{
Bill Buzbeea114add2012-05-03 15:00:40 -0700578 //FIXME: hard-coded little endian, need BE variant
579 // Insert high word into list first
580 addWordData(cUnit, constantListP, valHi);
581 return addWordData(cUnit, constantListP, valLo);
buzbee31a4a6f2012-02-28 15:36:15 -0800582}
583
Ian Rogersab058bb2012-03-11 22:19:38 -0700584void pushWord(std::vector<uint8_t>&buf, int data) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700585 buf.push_back( data & 0xff);
586 buf.push_back( (data >> 8) & 0xff);
587 buf.push_back( (data >> 16) & 0xff);
588 buf.push_back( (data >> 24) & 0xff);
buzbeee3acd072012-02-25 17:03:10 -0800589}
590
Ian Rogersab058bb2012-03-11 22:19:38 -0700591void alignBuffer(std::vector<uint8_t>&buf, size_t offset) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700592 while (buf.size() < offset) {
593 buf.push_back(0);
594 }
buzbeee3acd072012-02-25 17:03:10 -0800595}
596
Brian Carlstromf5822582012-03-19 22:34:31 -0700597bool IsDirect(int invokeType) {
598 InvokeType type = static_cast<InvokeType>(invokeType);
599 return type == kStatic || type == kDirect;
600}
601
buzbeee3acd072012-02-25 17:03:10 -0800602/* Write the literal pool to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800603void installLiteralPools(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800604{
Bill Buzbeea114add2012-05-03 15:00:40 -0700605 alignBuffer(cUnit->codeBuffer, cUnit->dataOffset);
606 LIR* dataLIR = cUnit->literalList;
607 while (dataLIR != NULL) {
608 pushWord(cUnit->codeBuffer, dataLIR->operands[0]);
609 dataLIR = NEXT_LIR(dataLIR);
610 }
611 // Push code and method literals, record offsets for the compiler to patch.
612 dataLIR = cUnit->codeLiteralList;
613 if (dataLIR != NULL) {
buzbeee3acd072012-02-25 17:03:10 -0800614 while (dataLIR != NULL) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700615 uint32_t target = dataLIR->operands[0];
616 cUnit->compiler->AddCodePatch(cUnit->dex_cache, cUnit->dex_file,
617 cUnit->method_idx,
618 cUnit->access_flags,
619 target,
620 IsDirect(dataLIR->operands[1]),
621 cUnit->codeBuffer.size());
622 const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target);
623 // unique based on target to ensure code deduplication works
624 uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
625 pushWord(cUnit->codeBuffer, unique_patch_value);
626 dataLIR = NEXT_LIR(dataLIR);
buzbeee3acd072012-02-25 17:03:10 -0800627 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700628 dataLIR = cUnit->methodLiteralList;
629 while (dataLIR != NULL) {
630 uint32_t target = dataLIR->operands[0];
631 cUnit->compiler->AddMethodPatch(cUnit->dex_cache, cUnit->dex_file,
632 cUnit->method_idx,
633 cUnit->access_flags,
634 target,
635 IsDirect(dataLIR->operands[1]),
636 cUnit->codeBuffer.size());
637 const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target);
638 // unique based on target to ensure code deduplication works
639 uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
640 pushWord(cUnit->codeBuffer, unique_patch_value);
641 dataLIR = NEXT_LIR(dataLIR);
Ian Rogers3fa13792012-03-18 15:53:45 -0700642 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700643 }
Ian Rogers3fa13792012-03-18 15:53:45 -0700644
buzbeee3acd072012-02-25 17:03:10 -0800645}
646
647/* Write the switch tables to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800648void installSwitchTables(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800649{
Bill Buzbeea114add2012-05-03 15:00:40 -0700650 GrowableListIterator iterator;
651 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
652 while (true) {
653 SwitchTable* tabRec = (SwitchTable *) oatGrowableListIteratorNext(
654 &iterator);
655 if (tabRec == NULL) break;
656 alignBuffer(cUnit->codeBuffer, tabRec->offset);
657 /*
658 * For Arm, our reference point is the address of the bx
659 * instruction that does the launch, so we have to subtract
660 * the auto pc-advance. For other targets the reference point
661 * is a label, so we can use the offset as-is.
662 */
buzbeec5159d52012-03-03 11:48:39 -0800663#if defined(TARGET_ARM)
Bill Buzbeea114add2012-05-03 15:00:40 -0700664 int bxOffset = tabRec->anchor->offset + 4;
Ian Rogers7caad772012-03-30 01:07:54 -0700665#elif defined(TARGET_X86)
Bill Buzbeea114add2012-05-03 15:00:40 -0700666 int bxOffset = 0;
buzbeec5159d52012-03-03 11:48:39 -0800667#else
Bill Buzbeea114add2012-05-03 15:00:40 -0700668 int bxOffset = tabRec->anchor->offset;
buzbeec5159d52012-03-03 11:48:39 -0800669#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700670 if (cUnit->printMe) {
671 LOG(INFO) << "Switch table for offset 0x" << std::hex << bxOffset;
buzbeee3acd072012-02-25 17:03:10 -0800672 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700673 if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
674 int* keys = (int*)&(tabRec->table[2]);
675 for (int elems = 0; elems < tabRec->table[1]; elems++) {
676 int disp = tabRec->targets[elems]->offset - bxOffset;
677 if (cUnit->printMe) {
678 LOG(INFO) << " Case[" << elems << "] key: 0x"
679 << std::hex << keys[elems] << ", disp: 0x"
680 << std::hex << disp;
681 }
682 pushWord(cUnit->codeBuffer, keys[elems]);
683 pushWord(cUnit->codeBuffer,
684 tabRec->targets[elems]->offset - bxOffset);
685 }
686 } else {
687 DCHECK_EQ(static_cast<int>(tabRec->table[0]),
688 static_cast<int>(Instruction::kPackedSwitchSignature));
689 for (int elems = 0; elems < tabRec->table[1]; elems++) {
690 int disp = tabRec->targets[elems]->offset - bxOffset;
691 if (cUnit->printMe) {
692 LOG(INFO) << " Case[" << elems << "] disp: 0x"
693 << std::hex << disp;
694 }
695 pushWord(cUnit->codeBuffer, tabRec->targets[elems]->offset - bxOffset);
696 }
697 }
698 }
buzbeee3acd072012-02-25 17:03:10 -0800699}
700
701/* Write the fill array dta to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800702void installFillArrayData(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800703{
Bill Buzbeea114add2012-05-03 15:00:40 -0700704 GrowableListIterator iterator;
705 oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
706 while (true) {
707 FillArrayData *tabRec = (FillArrayData *) oatGrowableListIteratorNext(
708 &iterator);
709 if (tabRec == NULL) break;
710 alignBuffer(cUnit->codeBuffer, tabRec->offset);
711 for (int i = 0; i < (tabRec->size + 1) / 2; i++) {
712 cUnit->codeBuffer.push_back( tabRec->table[i] & 0xFF);
713 cUnit->codeBuffer.push_back( (tabRec->table[i] >> 8) & 0xFF);
buzbeee3acd072012-02-25 17:03:10 -0800714 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700715 }
buzbeee3acd072012-02-25 17:03:10 -0800716}
717
buzbee31a4a6f2012-02-28 15:36:15 -0800718int assignLiteralOffsetCommon(LIR* lir, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800719{
Bill Buzbeea114add2012-05-03 15:00:40 -0700720 for (;lir != NULL; lir = lir->next) {
721 lir->offset = offset;
722 offset += 4;
723 }
724 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800725}
726
buzbee31a4a6f2012-02-28 15:36:15 -0800727void createMappingTable(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800728{
Bill Buzbeea114add2012-05-03 15:00:40 -0700729 LIR* tgtLIR;
730 int currentDalvikOffset = -1;
buzbeee3acd072012-02-25 17:03:10 -0800731
Bill Buzbeea114add2012-05-03 15:00:40 -0700732 for (tgtLIR = (LIR *) cUnit->firstLIRInsn;
733 tgtLIR;
734 tgtLIR = NEXT_LIR(tgtLIR)) {
735 if ((tgtLIR->opcode >= 0) && !tgtLIR->flags.isNop &&
736 (currentDalvikOffset != tgtLIR->dalvikOffset)) {
737 // Changed - need to emit a record
738 cUnit->mappingTable.push_back(tgtLIR->offset);
739 cUnit->mappingTable.push_back(tgtLIR->dalvikOffset);
740 currentDalvikOffset = tgtLIR->dalvikOffset;
buzbeee3acd072012-02-25 17:03:10 -0800741 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700742 }
buzbeee3acd072012-02-25 17:03:10 -0800743}
744
745/* Determine the offset of each literal field */
buzbee31a4a6f2012-02-28 15:36:15 -0800746int assignLiteralOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800747{
Bill Buzbeea114add2012-05-03 15:00:40 -0700748 offset = assignLiteralOffsetCommon(cUnit->literalList, offset);
749 offset = assignLiteralOffsetCommon(cUnit->codeLiteralList, offset);
750 offset = assignLiteralOffsetCommon(cUnit->methodLiteralList, offset);
751 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800752}
753
buzbee31a4a6f2012-02-28 15:36:15 -0800754int assignSwitchTablesOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800755{
Bill Buzbeea114add2012-05-03 15:00:40 -0700756 GrowableListIterator iterator;
757 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
758 while (true) {
759 SwitchTable *tabRec = (SwitchTable *) oatGrowableListIteratorNext(
760 &iterator);
761 if (tabRec == NULL) break;
762 tabRec->offset = offset;
763 if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
764 offset += tabRec->table[1] * (sizeof(int) * 2);
765 } else {
766 DCHECK_EQ(static_cast<int>(tabRec->table[0]),
767 static_cast<int>(Instruction::kPackedSwitchSignature));
768 offset += tabRec->table[1] * sizeof(int);
buzbeee3acd072012-02-25 17:03:10 -0800769 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700770 }
771 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800772}
773
buzbee31a4a6f2012-02-28 15:36:15 -0800774int assignFillArrayDataOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800775{
Bill Buzbeea114add2012-05-03 15:00:40 -0700776 GrowableListIterator iterator;
777 oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
778 while (true) {
779 FillArrayData *tabRec = (FillArrayData *) oatGrowableListIteratorNext(
780 &iterator);
781 if (tabRec == NULL) break;
782 tabRec->offset = offset;
783 offset += tabRec->size;
784 // word align
785 offset = (offset + 3) & ~3;
786 }
787 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800788}
789
790/*
791 * Walk the compilation unit and assign offsets to instructions
792 * and literals and compute the total size of the compiled unit.
793 */
794void oatAssignOffsets(CompilationUnit* cUnit)
795{
Bill Buzbeea114add2012-05-03 15:00:40 -0700796 int offset = oatAssignInsnOffsets(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800797
Bill Buzbeea114add2012-05-03 15:00:40 -0700798 /* Const values have to be word aligned */
799 offset = (offset + 3) & ~3;
buzbeee3acd072012-02-25 17:03:10 -0800800
Bill Buzbeea114add2012-05-03 15:00:40 -0700801 /* Set up offsets for literals */
802 cUnit->dataOffset = offset;
buzbeee3acd072012-02-25 17:03:10 -0800803
Bill Buzbeea114add2012-05-03 15:00:40 -0700804 offset = assignLiteralOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800805
Bill Buzbeea114add2012-05-03 15:00:40 -0700806 offset = assignSwitchTablesOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800807
Bill Buzbeea114add2012-05-03 15:00:40 -0700808 offset = assignFillArrayDataOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800809
Bill Buzbeea114add2012-05-03 15:00:40 -0700810 cUnit->totalSize = offset;
buzbeee3acd072012-02-25 17:03:10 -0800811}
812
813/*
814 * Go over each instruction in the list and calculate the offset from the top
815 * before sending them off to the assembler. If out-of-range branch distance is
816 * seen rearrange the instructions a bit to correct it.
817 */
818void oatAssembleLIR(CompilationUnit* cUnit)
819{
Bill Buzbeea114add2012-05-03 15:00:40 -0700820 oatAssignOffsets(cUnit);
821 /*
822 * Assemble here. Note that we generate code with optimistic assumptions
823 * and if found now to work, we'll have to redo the sequence and retry.
824 */
buzbeee3acd072012-02-25 17:03:10 -0800825
Bill Buzbeea114add2012-05-03 15:00:40 -0700826 while (true) {
827 AssemblerStatus res = oatAssembleInstructions(cUnit, 0);
828 if (res == kSuccess) {
829 break;
830 } else {
831 cUnit->assemblerRetries++;
832 if (cUnit->assemblerRetries > MAX_ASSEMBLER_RETRIES) {
833 oatCodegenDump(cUnit);
834 LOG(FATAL) << "Assembler error - too many retries";
835 }
836 // Redo offsets and try again
837 oatAssignOffsets(cUnit);
838 cUnit->codeBuffer.clear();
buzbeee3acd072012-02-25 17:03:10 -0800839 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700840 }
buzbeee3acd072012-02-25 17:03:10 -0800841
Bill Buzbeea114add2012-05-03 15:00:40 -0700842 // Install literals
843 installLiteralPools(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800844
Bill Buzbeea114add2012-05-03 15:00:40 -0700845 // Install switch tables
846 installSwitchTables(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800847
Bill Buzbeea114add2012-05-03 15:00:40 -0700848 // Install fill array data
849 installFillArrayData(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800850
Bill Buzbeea114add2012-05-03 15:00:40 -0700851 /*
852 * Create the mapping table
853 */
854 createMappingTable(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800855}
856
buzbee31a4a6f2012-02-28 15:36:15 -0800857/*
858 * Insert a kPseudoCaseLabel at the beginning of the Dalvik
859 * offset vaddr. This label will be used to fix up the case
860 * branch table during the assembly phase. Be sure to set
861 * all resource flags on this to prevent code motion across
862 * target boundaries. KeyVal is just there for debugging.
863 */
864LIR* insertCaseLabel(CompilationUnit* cUnit, int vaddr, int keyVal)
865{
Bill Buzbeea114add2012-05-03 15:00:40 -0700866 SafeMap<unsigned int, LIR*>::iterator it;
867 it = cUnit->boundaryMap.find(vaddr);
868 if (it == cUnit->boundaryMap.end()) {
869 LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr;
870 }
871 LIR* newLabel = (LIR*)oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
872 newLabel->dalvikOffset = vaddr;
873 newLabel->opcode = kPseudoCaseLabel;
874 newLabel->operands[0] = keyVal;
875 oatInsertLIRAfter(it->second, (LIR*)newLabel);
876 return newLabel;
buzbee31a4a6f2012-02-28 15:36:15 -0800877}
878
879void markPackedCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
880{
Bill Buzbeea114add2012-05-03 15:00:40 -0700881 const u2* table = tabRec->table;
882 int baseVaddr = tabRec->vaddr;
883 int *targets = (int*)&table[4];
884 int entries = table[1];
885 int lowKey = s4FromSwitchData(&table[2]);
886 for (int i = 0; i < entries; i++) {
887 tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
888 i + lowKey);
889 }
buzbee31a4a6f2012-02-28 15:36:15 -0800890}
891
892void markSparseCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
893{
Bill Buzbeea114add2012-05-03 15:00:40 -0700894 const u2* table = tabRec->table;
895 int baseVaddr = tabRec->vaddr;
896 int entries = table[1];
897 int* keys = (int*)&table[2];
898 int* targets = &keys[entries];
899 for (int i = 0; i < entries; i++) {
900 tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
901 keys[i]);
902 }
buzbee31a4a6f2012-02-28 15:36:15 -0800903}
904
905void oatProcessSwitchTables(CompilationUnit* cUnit)
906{
Bill Buzbeea114add2012-05-03 15:00:40 -0700907 GrowableListIterator iterator;
908 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
909 while (true) {
910 SwitchTable *tabRec =
911 (SwitchTable *) oatGrowableListIteratorNext(&iterator);
912 if (tabRec == NULL) break;
913 if (tabRec->table[0] == Instruction::kPackedSwitchSignature) {
914 markPackedCaseLabels(cUnit, tabRec);
915 } else if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
916 markSparseCaseLabels(cUnit, tabRec);
917 } else {
918 LOG(FATAL) << "Invalid switch table";
buzbee31a4a6f2012-02-28 15:36:15 -0800919 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700920 }
buzbee31a4a6f2012-02-28 15:36:15 -0800921}
922
923//FIXME: Do we have endian issues here?
924
925void dumpSparseSwitchTable(const u2* table)
Bill Buzbeea114add2012-05-03 15:00:40 -0700926 /*
927 * Sparse switch data format:
928 * ushort ident = 0x0200 magic value
929 * ushort size number of entries in the table; > 0
930 * int keys[size] keys, sorted low-to-high; 32-bit aligned
931 * int targets[size] branch targets, relative to switch opcode
932 *
933 * Total size is (2+size*4) 16-bit code units.
934 */
buzbee31a4a6f2012-02-28 15:36:15 -0800935{
Bill Buzbeea114add2012-05-03 15:00:40 -0700936 u2 ident = table[0];
937 int entries = table[1];
938 int* keys = (int*)&table[2];
939 int* targets = &keys[entries];
940 LOG(INFO) << "Sparse switch table - ident:0x" << std::hex << ident
941 << ", entries: " << std::dec << entries;
942 for (int i = 0; i < entries; i++) {
943 LOG(INFO) << " Key[" << keys[i] << "] -> 0x" << std::hex << targets[i];
944 }
buzbee31a4a6f2012-02-28 15:36:15 -0800945}
946
947void dumpPackedSwitchTable(const u2* table)
Bill Buzbeea114add2012-05-03 15:00:40 -0700948 /*
949 * Packed switch data format:
950 * ushort ident = 0x0100 magic value
951 * ushort size number of entries in the table
952 * int first_key first (and lowest) switch case value
953 * int targets[size] branch targets, relative to switch opcode
954 *
955 * Total size is (4+size*2) 16-bit code units.
956 */
buzbee31a4a6f2012-02-28 15:36:15 -0800957{
Bill Buzbeea114add2012-05-03 15:00:40 -0700958 u2 ident = table[0];
959 int* targets = (int*)&table[4];
960 int entries = table[1];
961 int lowKey = s4FromSwitchData(&table[2]);
962 LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident
963 << ", entries: " << std::dec << entries << ", lowKey: " << lowKey;
964 for (int i = 0; i < entries; i++) {
965 LOG(INFO) << " Key[" << (i + lowKey) << "] -> 0x" << std::hex
966 << targets[i];
967 }
buzbee31a4a6f2012-02-28 15:36:15 -0800968}
buzbeee3acd072012-02-25 17:03:10 -0800969
970
971} // namespace art