blob: 428b4432f20379b8265bb8f480fc7aea8198ba39 [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
jeffhaoe2962482012-06-28 11:29:57 -070079#if defined(TARGET_X86)
80 /*
81 * Double registers in x86 are just a single FP register
82 */
83 seed = 1;
84#else
Bill Buzbeea114add2012-05-03 15:00:40 -070085 /*
86 * Each double register is equal to a pair of single-precision FP registers
87 */
88 seed = DOUBLEREG(reg) ? 3 : 1;
jeffhaoe2962482012-06-28 11:29:57 -070089#endif
Bill Buzbeea114add2012-05-03 15:00:40 -070090 /* FP register starts at bit position 16 */
91 shift = FPREG(reg) ? kFPReg0 : 0;
92 /* Expand the double register id into single offset */
93 shift += regId;
94 return (seed << shift);
buzbee31a4a6f2012-02-28 15:36:15 -080095}
96
97/*
98 * Mark the corresponding bit(s).
99 */
100inline void setupRegMask(u8* mask, int reg)
101{
Bill Buzbeea114add2012-05-03 15:00:40 -0700102 *mask |= getRegMaskCommon(reg);
buzbee31a4a6f2012-02-28 15:36:15 -0800103}
104
105/*
106 * Set up the proper fields in the resource mask
107 */
108void setupResourceMasks(LIR* lir)
109{
Bill Buzbeea114add2012-05-03 15:00:40 -0700110 int opcode = lir->opcode;
111 int flags;
buzbee31a4a6f2012-02-28 15:36:15 -0800112
Bill Buzbeea114add2012-05-03 15:00:40 -0700113 if (opcode <= 0) {
114 lir->useMask = lir->defMask = 0;
115 return;
116 }
buzbee31a4a6f2012-02-28 15:36:15 -0800117
Bill Buzbeea114add2012-05-03 15:00:40 -0700118 flags = EncodingMap[lir->opcode].flags;
buzbee31a4a6f2012-02-28 15:36:15 -0800119
Bill Buzbeea114add2012-05-03 15:00:40 -0700120 if (flags & NEEDS_FIXUP) {
121 lir->flags.pcRelFixup = true;
122 }
buzbee31a4a6f2012-02-28 15:36:15 -0800123
Bill Buzbeea114add2012-05-03 15:00:40 -0700124 /* Get the starting size of the instruction's template */
125 lir->flags.size = oatGetInsnSize(lir);
buzbeee88dfbf2012-03-05 11:19:57 -0800126
Bill Buzbeea114add2012-05-03 15:00:40 -0700127 /* Set up the mask for resources that are updated */
128 if (flags & (IS_LOAD | IS_STORE)) {
129 /* Default to heap - will catch specialized classes later */
130 setMemRefType(lir, flags & IS_LOAD, kHeapRef);
131 }
buzbee31a4a6f2012-02-28 15:36:15 -0800132
Bill Buzbeea114add2012-05-03 15:00:40 -0700133 /*
134 * Conservatively assume the branch here will call out a function that in
135 * turn will trash everything.
136 */
137 if (flags & IS_BRANCH) {
138 lir->defMask = lir->useMask = ENCODE_ALL;
139 return;
140 }
buzbee31a4a6f2012-02-28 15:36:15 -0800141
Bill Buzbeea114add2012-05-03 15:00:40 -0700142 if (flags & REG_DEF0) {
143 setupRegMask(&lir->defMask, lir->operands[0]);
144 }
buzbee31a4a6f2012-02-28 15:36:15 -0800145
Bill Buzbeea114add2012-05-03 15:00:40 -0700146 if (flags & REG_DEF1) {
147 setupRegMask(&lir->defMask, lir->operands[1]);
148 }
buzbee31a4a6f2012-02-28 15:36:15 -0800149
jeffhaoe2962482012-06-28 11:29:57 -0700150#if defined(TARGET_X86)
151 if (flags & REG_DEFA) {
152 setupRegMask(&lir->defMask, rAX);
153 }
154
155 if (flags & REG_DEFD) {
156 setupRegMask(&lir->defMask, rDX);
157 }
158#endif
159
Bill Buzbeea114add2012-05-03 15:00:40 -0700160 if (flags & REG_DEF_SP) {
161 lir->defMask |= ENCODE_REG_SP;
162 }
buzbee31a4a6f2012-02-28 15:36:15 -0800163
buzbeea7678db2012-03-05 15:35:46 -0800164#if !defined(TARGET_X86)
Bill Buzbeea114add2012-05-03 15:00:40 -0700165 if (flags & REG_DEF_LR) {
166 lir->defMask |= ENCODE_REG_LR;
167 }
buzbeea7678db2012-03-05 15:35:46 -0800168#endif
buzbee31a4a6f2012-02-28 15:36:15 -0800169
jeffhaoe2962482012-06-28 11:29:57 -0700170#if defined(TARGET_ARM)
Bill Buzbeea114add2012-05-03 15:00:40 -0700171 if (flags & REG_DEF_LIST0) {
172 lir->defMask |= ENCODE_REG_LIST(lir->operands[0]);
173 }
buzbee31a4a6f2012-02-28 15:36:15 -0800174
Bill Buzbeea114add2012-05-03 15:00:40 -0700175 if (flags & REG_DEF_LIST1) {
176 lir->defMask |= ENCODE_REG_LIST(lir->operands[1]);
177 }
buzbee31a4a6f2012-02-28 15:36:15 -0800178
Bill Buzbeea114add2012-05-03 15:00:40 -0700179 if (flags & REG_DEF_FPCS_LIST0) {
180 lir->defMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]);
181 }
buzbee31a4a6f2012-02-28 15:36:15 -0800182
Bill Buzbeea114add2012-05-03 15:00:40 -0700183 if (flags & REG_DEF_FPCS_LIST2) {
184 for (int i = 0; i < lir->operands[2]; i++) {
185 setupRegMask(&lir->defMask, lir->operands[1] + i);
buzbee31a4a6f2012-02-28 15:36:15 -0800186 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700187 }
buzbee5de34942012-03-01 14:51:57 -0800188#endif
buzbee31a4a6f2012-02-28 15:36:15 -0800189
Bill Buzbeea114add2012-05-03 15:00:40 -0700190 if (flags & SETS_CCODES) {
191 lir->defMask |= ENCODE_CCODE;
192 }
buzbee31a4a6f2012-02-28 15:36:15 -0800193
194#if defined(TARGET_ARM)
Bill Buzbeea114add2012-05-03 15:00:40 -0700195 /* Conservatively treat the IT block */
196 if (flags & IS_IT) {
197 lir->defMask = ENCODE_ALL;
198 }
buzbee31a4a6f2012-02-28 15:36:15 -0800199#endif
200
Bill Buzbeea114add2012-05-03 15:00:40 -0700201 if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) {
202 int i;
buzbee31a4a6f2012-02-28 15:36:15 -0800203
Bill Buzbeea114add2012-05-03 15:00:40 -0700204 for (i = 0; i < 4; i++) {
205 if (flags & (1 << (kRegUse0 + i))) {
206 setupRegMask(&lir->useMask, lir->operands[i]);
207 }
buzbee31a4a6f2012-02-28 15:36:15 -0800208 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700209 }
buzbee31a4a6f2012-02-28 15:36:15 -0800210
jeffhaoe2962482012-06-28 11:29:57 -0700211#if defined(TARGET_X86)
212 if (flags & REG_USEA) {
213 setupRegMask(&lir->useMask, rAX);
214 }
215
216 if (flags & REG_USEC) {
217 setupRegMask(&lir->useMask, rCX);
218 }
219
220 if (flags & REG_USED) {
221 setupRegMask(&lir->useMask, rDX);
222 }
223#endif
224
buzbeea7678db2012-03-05 15:35:46 -0800225#if defined(TARGET_ARM)
Bill Buzbeea114add2012-05-03 15:00:40 -0700226 if (flags & REG_USE_PC) {
227 lir->useMask |= ENCODE_REG_PC;
228 }
buzbeea7678db2012-03-05 15:35:46 -0800229#endif
buzbee31a4a6f2012-02-28 15:36:15 -0800230
Bill Buzbeea114add2012-05-03 15:00:40 -0700231 if (flags & REG_USE_SP) {
232 lir->useMask |= ENCODE_REG_SP;
233 }
buzbee31a4a6f2012-02-28 15:36:15 -0800234
jeffhaoe2962482012-06-28 11:29:57 -0700235#if defined(TARGET_ARM)
Bill Buzbeea114add2012-05-03 15:00:40 -0700236 if (flags & REG_USE_LIST0) {
237 lir->useMask |= ENCODE_REG_LIST(lir->operands[0]);
238 }
buzbee31a4a6f2012-02-28 15:36:15 -0800239
Bill Buzbeea114add2012-05-03 15:00:40 -0700240 if (flags & REG_USE_LIST1) {
241 lir->useMask |= ENCODE_REG_LIST(lir->operands[1]);
242 }
buzbee31a4a6f2012-02-28 15:36:15 -0800243
Bill Buzbeea114add2012-05-03 15:00:40 -0700244 if (flags & REG_USE_FPCS_LIST0) {
245 lir->useMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]);
246 }
buzbee31a4a6f2012-02-28 15:36:15 -0800247
Bill Buzbeea114add2012-05-03 15:00:40 -0700248 if (flags & REG_USE_FPCS_LIST2) {
249 for (int i = 0; i < lir->operands[2]; i++) {
250 setupRegMask(&lir->useMask, lir->operands[1] + i);
buzbee31a4a6f2012-02-28 15:36:15 -0800251 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700252 }
buzbee5de34942012-03-01 14:51:57 -0800253#endif
buzbee31a4a6f2012-02-28 15:36:15 -0800254
Bill Buzbeea114add2012-05-03 15:00:40 -0700255 if (flags & USES_CCODES) {
256 lir->useMask |= ENCODE_CCODE;
257 }
buzbee31a4a6f2012-02-28 15:36:15 -0800258
259#if defined(TARGET_ARM)
Bill Buzbeea114add2012-05-03 15:00:40 -0700260 /* Fixup for kThumbPush/lr and kThumbPop/pc */
261 if (opcode == kThumbPush || opcode == kThumbPop) {
262 u8 r8Mask = getRegMaskCommon(r8);
263 if ((opcode == kThumbPush) && (lir->useMask & r8Mask)) {
264 lir->useMask &= ~r8Mask;
265 lir->useMask |= ENCODE_REG_LR;
266 } else if ((opcode == kThumbPop) && (lir->defMask & r8Mask)) {
267 lir->defMask &= ~r8Mask;
268 lir->defMask |= ENCODE_REG_PC;
buzbee31a4a6f2012-02-28 15:36:15 -0800269 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700270 }
buzbee31a4a6f2012-02-28 15:36:15 -0800271#endif
272}
273
274/*
buzbee5de34942012-03-01 14:51:57 -0800275 * Debugging macros
276 */
277#define DUMP_RESOURCE_MASK(X)
278#define DUMP_SSA_REP(X)
279
280/* Pretty-print a LIR instruction */
281void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr)
282{
Bill Buzbeea114add2012-05-03 15:00:40 -0700283 LIR* lir = (LIR*) arg;
284 int offset = lir->offset;
285 int dest = lir->operands[0];
286 const bool dumpNop = (cUnit->enableDebug & (1 << kDebugShowNops));
buzbee5de34942012-03-01 14:51:57 -0800287
Bill Buzbeea114add2012-05-03 15:00:40 -0700288 /* Handle pseudo-ops individually, and all regular insns as a group */
289 switch (lir->opcode) {
290 case kPseudoMethodEntry:
291 LOG(INFO) << "-------- method entry "
292 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
293 break;
294 case kPseudoMethodExit:
295 LOG(INFO) << "-------- Method_Exit";
296 break;
297 case kPseudoBarrier:
298 LOG(INFO) << "-------- BARRIER";
299 break;
300 case kPseudoExtended:
301 LOG(INFO) << "-------- " << (char* ) dest;
302 break;
303 case kPseudoSSARep:
304 DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " << (char* ) dest);
305 break;
306 case kPseudoEntryBlock:
307 LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
308 break;
309 case kPseudoDalvikByteCodeBoundary:
310 LOG(INFO) << "-------- dalvik offset: 0x" << std::hex
311 << lir->dalvikOffset << " @ " << (char* )lir->operands[0];
312 break;
313 case kPseudoExitBlock:
314 LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
315 break;
316 case kPseudoPseudoAlign4:
317 LOG(INFO) << (intptr_t)baseAddr + offset << " (0x" << std::hex
318 << offset << "): .align4";
319 break;
320 case kPseudoEHBlockLabel:
321 LOG(INFO) << "Exception_Handling:";
322 break;
323 case kPseudoTargetLabel:
324 case kPseudoNormalBlockLabel:
325 LOG(INFO) << "L" << (void*)lir << ":";
326 break;
327 case kPseudoThrowTarget:
328 LOG(INFO) << "LT" << (void*)lir << ":";
329 break;
330 case kPseudoIntrinsicRetry:
331 LOG(INFO) << "IR" << (void*)lir << ":";
332 break;
333 case kPseudoSuspendTarget:
334 LOG(INFO) << "LS" << (void*)lir << ":";
335 break;
336 case kPseudoCaseLabel:
337 LOG(INFO) << "LC" << (void*)lir << ": Case target 0x"
338 << std::hex << lir->operands[0] << "|" << std::dec <<
339 lir->operands[0];
340 break;
341 default:
342 if (lir->flags.isNop && !dumpNop) {
343 break;
344 } else {
345 std::string op_name(buildInsnString(EncodingMap[lir->opcode].name,
346 lir, baseAddr));
347 std::string op_operands(buildInsnString(EncodingMap[lir->opcode].fmt
348 , lir, baseAddr));
349 LOG(INFO) << StringPrintf("%05x: %-9s%s%s",
350 (unsigned int)(baseAddr + offset),
351 op_name.c_str(), op_operands.c_str(),
352 lir->flags.isNop ? "(nop)" : "");
353 }
354 break;
355 }
buzbee5de34942012-03-01 14:51:57 -0800356
Bill Buzbeea114add2012-05-03 15:00:40 -0700357 if (lir->useMask && (!lir->flags.isNop || dumpNop)) {
358 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->useMask, "use"));
359 }
360 if (lir->defMask && (!lir->flags.isNop || dumpNop)) {
361 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->defMask, "def"));
362 }
buzbee5de34942012-03-01 14:51:57 -0800363}
364
365void oatDumpPromotionMap(CompilationUnit *cUnit)
366{
Bill Buzbeea114add2012-05-03 15:00:40 -0700367 int numRegs = cUnit->numDalvikRegisters + cUnit->numCompilerTemps + 1;
368 for (int i = 0; i < numRegs; i++) {
369 PromotionMap vRegMap = cUnit->promotionMap[i];
370 std::string buf;
371 if (vRegMap.fpLocation == kLocPhysReg) {
372 StringAppendF(&buf, " : s%d", vRegMap.fpReg & FP_REG_MASK);
buzbee5de34942012-03-01 14:51:57 -0800373 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700374
375 std::string buf3;
376 if (i < cUnit->numDalvikRegisters) {
377 StringAppendF(&buf3, "%02d", i);
378 } else if (i == cUnit->methodSReg) {
379 buf3 = "Method*";
380 } else {
381 StringAppendF(&buf3, "ct%d", i - cUnit->numDalvikRegisters);
382 }
383
384 LOG(INFO) << StringPrintf("V[%s] -> %s%d%s", buf3.c_str(),
385 vRegMap.coreLocation == kLocPhysReg ?
386 "r" : "SP+", vRegMap.coreLocation == kLocPhysReg ?
387 vRegMap.coreReg : oatSRegOffset(cUnit, i),
388 buf.c_str());
389 }
buzbee5de34942012-03-01 14:51:57 -0800390}
391
buzbee5de34942012-03-01 14:51:57 -0800392/* Dump instructions and constant pool contents */
393void oatCodegenDump(CompilationUnit* cUnit)
394{
Bill Buzbeea114add2012-05-03 15:00:40 -0700395 LOG(INFO) << "Dumping LIR insns for "
396 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
397 LIR* lirInsn;
398 LIR* thisLIR;
399 int insnsSize = cUnit->insnsSize;
buzbee5de34942012-03-01 14:51:57 -0800400
Bill Buzbeea114add2012-05-03 15:00:40 -0700401 LOG(INFO) << "Regs (excluding ins) : " << cUnit->numRegs;
402 LOG(INFO) << "Ins : " << cUnit->numIns;
403 LOG(INFO) << "Outs : " << cUnit->numOuts;
404 LOG(INFO) << "CoreSpills : " << cUnit->numCoreSpills;
405 LOG(INFO) << "FPSpills : " << cUnit->numFPSpills;
406 LOG(INFO) << "CompilerTemps : " << cUnit->numCompilerTemps;
407 LOG(INFO) << "Frame size : " << cUnit->frameSize;
408 LOG(INFO) << "code size is " << cUnit->totalSize <<
409 " bytes, Dalvik size is " << insnsSize * 2;
410 LOG(INFO) << "expansion factor: "
411 << (float)cUnit->totalSize / (float)(insnsSize * 2);
412 oatDumpPromotionMap(cUnit);
413 for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
414 oatDumpLIRInsn(cUnit, lirInsn, 0);
415 }
416 for (lirInsn = cUnit->classPointerList; lirInsn; lirInsn = lirInsn->next) {
417 thisLIR = (LIR*) lirInsn;
418 LOG(INFO) << StringPrintf("%x (%04x): .class (%s)",
419 thisLIR->offset, thisLIR->offset,
420 ((CallsiteInfo *)
421 thisLIR->operands[0])->classDescriptor);
422 }
423 for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
424 thisLIR = (LIR*) lirInsn;
425 LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)",
426 thisLIR->offset, thisLIR->offset,
427 thisLIR->operands[0]);
428 }
buzbee5de34942012-03-01 14:51:57 -0800429
Bill Buzbeea114add2012-05-03 15:00:40 -0700430 const DexFile::MethodId& method_id =
431 cUnit->dex_file->GetMethodId(cUnit->method_idx);
432 std::string signature(cUnit->dex_file->GetMethodSignature(method_id));
433 std::string name(cUnit->dex_file->GetMethodName(method_id));
434 std::string descriptor(cUnit->dex_file->GetMethodDeclaringClassDescriptor(method_id));
buzbee5de34942012-03-01 14:51:57 -0800435
Bill Buzbeea114add2012-05-03 15:00:40 -0700436 // Dump mapping table
437 if (cUnit->mappingTable.size() > 0) {
438 std::string
439 line(StringPrintf("\n MappingTable %s%s_%s_mappingTable[%zu] = {",
440 descriptor.c_str(), name.c_str(), signature.c_str(),
441 cUnit->mappingTable.size()));
442 std::replace(line.begin(), line.end(), ';', '_');
443 LOG(INFO) << line;
444 for (uint32_t i = 0; i < cUnit->mappingTable.size(); i+=2) {
445 line = StringPrintf(" {0x%05x, 0x%04x},",
446 cUnit->mappingTable[i], cUnit->mappingTable[i+1]);
447 LOG(INFO) << line;
buzbee5de34942012-03-01 14:51:57 -0800448 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700449 LOG(INFO) <<" };\n\n";
450 }
buzbee5de34942012-03-01 14:51:57 -0800451}
452
buzbeea2ebdd72012-03-04 14:57:06 -0800453
454LIR* rawLIR(CompilationUnit* cUnit, int dalvikOffset, int opcode, int op0,
Bill Buzbeea114add2012-05-03 15:00:40 -0700455 int op1, int op2, int op3, int op4, LIR* target)
buzbeea2ebdd72012-03-04 14:57:06 -0800456{
Bill Buzbeea114add2012-05-03 15:00:40 -0700457 LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
458 insn->dalvikOffset = dalvikOffset;
459 insn->opcode = opcode;
460 insn->operands[0] = op0;
461 insn->operands[1] = op1;
462 insn->operands[2] = op2;
463 insn->operands[3] = op3;
464 insn->operands[4] = op4;
465 insn->target = target;
466 oatSetupResourceMasks(insn);
467 if (opcode == kPseudoTargetLabel) {
468 // Always make labels scheduling barriers
469 insn->defMask = ENCODE_ALL;
470 }
471 return insn;
buzbeea2ebdd72012-03-04 14:57:06 -0800472}
473
buzbee5de34942012-03-01 14:51:57 -0800474/*
buzbee31a4a6f2012-02-28 15:36:15 -0800475 * The following are building blocks to construct low-level IRs with 0 - 4
476 * operands.
477 */
buzbee5de34942012-03-01 14:51:57 -0800478LIR* newLIR0(CompilationUnit* cUnit, int opcode)
buzbee31a4a6f2012-02-28 15:36:15 -0800479{
Bill Buzbeea114add2012-05-03 15:00:40 -0700480 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND))
481 << EncodingMap[opcode].name << " " << (int)opcode << " "
482 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
483 << cUnit->currentDalvikOffset;
484 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode);
485 oatAppendLIR(cUnit, (LIR*) insn);
486 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800487}
488
buzbee5de34942012-03-01 14:51:57 -0800489LIR* newLIR1(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700490 int dest)
buzbee31a4a6f2012-02-28 15:36:15 -0800491{
Bill Buzbeea114add2012-05-03 15:00:40 -0700492 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_UNARY_OP))
493 << EncodingMap[opcode].name << " " << (int)opcode << " "
494 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
495 << cUnit->currentDalvikOffset;
496 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest);
497 oatAppendLIR(cUnit, (LIR*) insn);
498 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800499}
500
buzbee5de34942012-03-01 14:51:57 -0800501LIR* newLIR2(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700502 int dest, int src1)
buzbee31a4a6f2012-02-28 15:36:15 -0800503{
Bill Buzbeea114add2012-05-03 15:00:40 -0700504 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_BINARY_OP))
505 << EncodingMap[opcode].name << " " << (int)opcode << " "
506 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
507 << cUnit->currentDalvikOffset;
508 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1);
509 oatAppendLIR(cUnit, (LIR*) insn);
510 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800511}
512
buzbee5de34942012-03-01 14:51:57 -0800513LIR* newLIR3(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700514 int dest, int src1, int src2)
buzbee31a4a6f2012-02-28 15:36:15 -0800515{
Bill Buzbeea114add2012-05-03 15:00:40 -0700516 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_TERTIARY_OP))
517 << EncodingMap[opcode].name << " " << (int)opcode << " "
518 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
519 << cUnit->currentDalvikOffset;
520 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
521 src2);
522 oatAppendLIR(cUnit, (LIR*) insn);
523 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800524}
525
buzbee5de34942012-03-01 14:51:57 -0800526LIR* newLIR4(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700527 int dest, int src1, int src2, int info)
buzbee31a4a6f2012-02-28 15:36:15 -0800528{
Bill Buzbeea114add2012-05-03 15:00:40 -0700529 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUAD_OP))
530 << EncodingMap[opcode].name << " " << (int)opcode << " "
531 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
532 << cUnit->currentDalvikOffset;
533 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
534 src2, info);
535 oatAppendLIR(cUnit, (LIR*) insn);
536 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800537}
buzbee31a4a6f2012-02-28 15:36:15 -0800538
Ian Rogersb5d09b22012-03-06 22:14:17 -0800539LIR* newLIR5(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700540 int dest, int src1, int src2, int info1, int info2)
Ian Rogersb5d09b22012-03-06 22:14:17 -0800541{
Bill Buzbeea114add2012-05-03 15:00:40 -0700542 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUIN_OP))
543 << EncodingMap[opcode].name << " " << (int)opcode << " "
544 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
545 << cUnit->currentDalvikOffset;
546 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
547 src2, info1, info2);
548 oatAppendLIR(cUnit, (LIR*) insn);
549 return insn;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800550}
551
buzbee31a4a6f2012-02-28 15:36:15 -0800552/*
553 * Search the existing constants in the literal pool for an exact or close match
554 * within specified delta (greater or equal to 0).
555 */
556LIR* scanLiteralPool(LIR* dataTarget, int value, unsigned int delta)
557{
Bill Buzbeea114add2012-05-03 15:00:40 -0700558 while (dataTarget) {
559 if (((unsigned) (value - ((LIR* ) dataTarget)->operands[0])) <= delta)
560 return (LIR* ) dataTarget;
561 dataTarget = dataTarget->next;
562 }
563 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800564}
565
566/* Search the existing constants in the literal pool for an exact wide match */
567LIR* scanLiteralPoolWide(LIR* dataTarget, int valLo, int valHi)
568{
Bill Buzbeea114add2012-05-03 15:00:40 -0700569 bool loMatch = false;
570 LIR* loTarget = NULL;
571 while (dataTarget) {
572 if (loMatch && (((LIR*)dataTarget)->operands[0] == valHi)) {
573 return (LIR*)loTarget;
buzbee31a4a6f2012-02-28 15:36:15 -0800574 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700575 loMatch = false;
576 if (((LIR*)dataTarget)->operands[0] == valLo) {
577 loMatch = true;
578 loTarget = dataTarget;
579 }
580 dataTarget = dataTarget->next;
581 }
582 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800583}
584
585/*
586 * The following are building blocks to insert constants into the pool or
587 * instruction streams.
588 */
589
buzbee5de34942012-03-01 14:51:57 -0800590/* Add a 32-bit constant either in the constant pool */
Ian Rogers3fa13792012-03-18 15:53:45 -0700591LIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP, int value)
buzbee31a4a6f2012-02-28 15:36:15 -0800592{
Bill Buzbeea114add2012-05-03 15:00:40 -0700593 /* Add the constant to the literal pool */
594 if (constantListP) {
595 LIR* newValue = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocData);
596 newValue->operands[0] = value;
597 newValue->next = *constantListP;
598 *constantListP = (LIR*) newValue;
599 return newValue;
600 }
601 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800602}
603
604/* Add a 64-bit constant to the constant pool or mixed with code */
605LIR* addWideData(CompilationUnit* cUnit, LIR* *constantListP,
Bill Buzbeea114add2012-05-03 15:00:40 -0700606 int valLo, int valHi)
buzbee31a4a6f2012-02-28 15:36:15 -0800607{
Bill Buzbeea114add2012-05-03 15:00:40 -0700608 //FIXME: hard-coded little endian, need BE variant
609 // Insert high word into list first
610 addWordData(cUnit, constantListP, valHi);
611 return addWordData(cUnit, constantListP, valLo);
buzbee31a4a6f2012-02-28 15:36:15 -0800612}
613
Ian Rogersab058bb2012-03-11 22:19:38 -0700614void pushWord(std::vector<uint8_t>&buf, int data) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700615 buf.push_back( data & 0xff);
616 buf.push_back( (data >> 8) & 0xff);
617 buf.push_back( (data >> 16) & 0xff);
618 buf.push_back( (data >> 24) & 0xff);
buzbeee3acd072012-02-25 17:03:10 -0800619}
620
Ian Rogersab058bb2012-03-11 22:19:38 -0700621void alignBuffer(std::vector<uint8_t>&buf, size_t offset) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700622 while (buf.size() < offset) {
623 buf.push_back(0);
624 }
buzbeee3acd072012-02-25 17:03:10 -0800625}
626
Brian Carlstromf5822582012-03-19 22:34:31 -0700627bool IsDirect(int invokeType) {
628 InvokeType type = static_cast<InvokeType>(invokeType);
629 return type == kStatic || type == kDirect;
630}
631
buzbeee3acd072012-02-25 17:03:10 -0800632/* Write the literal pool to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800633void installLiteralPools(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800634{
Bill Buzbeea114add2012-05-03 15:00:40 -0700635 alignBuffer(cUnit->codeBuffer, cUnit->dataOffset);
636 LIR* dataLIR = cUnit->literalList;
637 while (dataLIR != NULL) {
638 pushWord(cUnit->codeBuffer, dataLIR->operands[0]);
639 dataLIR = NEXT_LIR(dataLIR);
640 }
641 // Push code and method literals, record offsets for the compiler to patch.
642 dataLIR = cUnit->codeLiteralList;
643 if (dataLIR != NULL) {
buzbeee3acd072012-02-25 17:03:10 -0800644 while (dataLIR != NULL) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700645 uint32_t target = dataLIR->operands[0];
646 cUnit->compiler->AddCodePatch(cUnit->dex_cache, cUnit->dex_file,
647 cUnit->method_idx,
648 cUnit->access_flags,
649 target,
650 IsDirect(dataLIR->operands[1]),
651 cUnit->codeBuffer.size());
652 const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target);
653 // unique based on target to ensure code deduplication works
654 uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
655 pushWord(cUnit->codeBuffer, unique_patch_value);
656 dataLIR = NEXT_LIR(dataLIR);
buzbeee3acd072012-02-25 17:03:10 -0800657 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700658 dataLIR = cUnit->methodLiteralList;
659 while (dataLIR != NULL) {
660 uint32_t target = dataLIR->operands[0];
661 cUnit->compiler->AddMethodPatch(cUnit->dex_cache, cUnit->dex_file,
662 cUnit->method_idx,
663 cUnit->access_flags,
664 target,
665 IsDirect(dataLIR->operands[1]),
666 cUnit->codeBuffer.size());
667 const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target);
668 // unique based on target to ensure code deduplication works
669 uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
670 pushWord(cUnit->codeBuffer, unique_patch_value);
671 dataLIR = NEXT_LIR(dataLIR);
Ian Rogers3fa13792012-03-18 15:53:45 -0700672 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700673 }
Ian Rogers3fa13792012-03-18 15:53:45 -0700674
buzbeee3acd072012-02-25 17:03:10 -0800675}
676
677/* Write the switch tables to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800678void installSwitchTables(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800679{
Bill Buzbeea114add2012-05-03 15:00:40 -0700680 GrowableListIterator iterator;
681 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
682 while (true) {
683 SwitchTable* tabRec = (SwitchTable *) oatGrowableListIteratorNext(
684 &iterator);
685 if (tabRec == NULL) break;
686 alignBuffer(cUnit->codeBuffer, tabRec->offset);
687 /*
688 * For Arm, our reference point is the address of the bx
689 * instruction that does the launch, so we have to subtract
690 * the auto pc-advance. For other targets the reference point
691 * is a label, so we can use the offset as-is.
692 */
buzbeec5159d52012-03-03 11:48:39 -0800693#if defined(TARGET_ARM)
Bill Buzbeea114add2012-05-03 15:00:40 -0700694 int bxOffset = tabRec->anchor->offset + 4;
Ian Rogers7caad772012-03-30 01:07:54 -0700695#elif defined(TARGET_X86)
Bill Buzbeea114add2012-05-03 15:00:40 -0700696 int bxOffset = 0;
buzbeec5159d52012-03-03 11:48:39 -0800697#else
Bill Buzbeea114add2012-05-03 15:00:40 -0700698 int bxOffset = tabRec->anchor->offset;
buzbeec5159d52012-03-03 11:48:39 -0800699#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700700 if (cUnit->printMe) {
701 LOG(INFO) << "Switch table for offset 0x" << std::hex << bxOffset;
buzbeee3acd072012-02-25 17:03:10 -0800702 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700703 if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
704 int* keys = (int*)&(tabRec->table[2]);
705 for (int elems = 0; elems < tabRec->table[1]; elems++) {
706 int disp = tabRec->targets[elems]->offset - bxOffset;
707 if (cUnit->printMe) {
708 LOG(INFO) << " Case[" << elems << "] key: 0x"
709 << std::hex << keys[elems] << ", disp: 0x"
710 << std::hex << disp;
711 }
712 pushWord(cUnit->codeBuffer, keys[elems]);
713 pushWord(cUnit->codeBuffer,
714 tabRec->targets[elems]->offset - bxOffset);
715 }
716 } else {
717 DCHECK_EQ(static_cast<int>(tabRec->table[0]),
718 static_cast<int>(Instruction::kPackedSwitchSignature));
719 for (int elems = 0; elems < tabRec->table[1]; elems++) {
720 int disp = tabRec->targets[elems]->offset - bxOffset;
721 if (cUnit->printMe) {
722 LOG(INFO) << " Case[" << elems << "] disp: 0x"
723 << std::hex << disp;
724 }
725 pushWord(cUnit->codeBuffer, tabRec->targets[elems]->offset - bxOffset);
726 }
727 }
728 }
buzbeee3acd072012-02-25 17:03:10 -0800729}
730
731/* Write the fill array dta to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800732void installFillArrayData(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800733{
Bill Buzbeea114add2012-05-03 15:00:40 -0700734 GrowableListIterator iterator;
735 oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
736 while (true) {
737 FillArrayData *tabRec = (FillArrayData *) oatGrowableListIteratorNext(
738 &iterator);
739 if (tabRec == NULL) break;
740 alignBuffer(cUnit->codeBuffer, tabRec->offset);
741 for (int i = 0; i < (tabRec->size + 1) / 2; i++) {
742 cUnit->codeBuffer.push_back( tabRec->table[i] & 0xFF);
743 cUnit->codeBuffer.push_back( (tabRec->table[i] >> 8) & 0xFF);
buzbeee3acd072012-02-25 17:03:10 -0800744 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700745 }
buzbeee3acd072012-02-25 17:03:10 -0800746}
747
buzbee31a4a6f2012-02-28 15:36:15 -0800748int assignLiteralOffsetCommon(LIR* lir, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800749{
Bill Buzbeea114add2012-05-03 15:00:40 -0700750 for (;lir != NULL; lir = lir->next) {
751 lir->offset = offset;
752 offset += 4;
753 }
754 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800755}
756
buzbee31a4a6f2012-02-28 15:36:15 -0800757void createMappingTable(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800758{
Bill Buzbeea114add2012-05-03 15:00:40 -0700759 LIR* tgtLIR;
760 int currentDalvikOffset = -1;
buzbeee3acd072012-02-25 17:03:10 -0800761
Bill Buzbeea114add2012-05-03 15:00:40 -0700762 for (tgtLIR = (LIR *) cUnit->firstLIRInsn;
763 tgtLIR;
764 tgtLIR = NEXT_LIR(tgtLIR)) {
765 if ((tgtLIR->opcode >= 0) && !tgtLIR->flags.isNop &&
766 (currentDalvikOffset != tgtLIR->dalvikOffset)) {
767 // Changed - need to emit a record
768 cUnit->mappingTable.push_back(tgtLIR->offset);
769 cUnit->mappingTable.push_back(tgtLIR->dalvikOffset);
770 currentDalvikOffset = tgtLIR->dalvikOffset;
buzbeee3acd072012-02-25 17:03:10 -0800771 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700772 }
buzbeee3acd072012-02-25 17:03:10 -0800773}
774
775/* Determine the offset of each literal field */
buzbee31a4a6f2012-02-28 15:36:15 -0800776int assignLiteralOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800777{
Bill Buzbeea114add2012-05-03 15:00:40 -0700778 offset = assignLiteralOffsetCommon(cUnit->literalList, offset);
779 offset = assignLiteralOffsetCommon(cUnit->codeLiteralList, offset);
780 offset = assignLiteralOffsetCommon(cUnit->methodLiteralList, offset);
781 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800782}
783
buzbee31a4a6f2012-02-28 15:36:15 -0800784int assignSwitchTablesOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800785{
Bill Buzbeea114add2012-05-03 15:00:40 -0700786 GrowableListIterator iterator;
787 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
788 while (true) {
789 SwitchTable *tabRec = (SwitchTable *) oatGrowableListIteratorNext(
790 &iterator);
791 if (tabRec == NULL) break;
792 tabRec->offset = offset;
793 if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
794 offset += tabRec->table[1] * (sizeof(int) * 2);
795 } else {
796 DCHECK_EQ(static_cast<int>(tabRec->table[0]),
797 static_cast<int>(Instruction::kPackedSwitchSignature));
798 offset += tabRec->table[1] * sizeof(int);
buzbeee3acd072012-02-25 17:03:10 -0800799 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700800 }
801 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800802}
803
buzbee31a4a6f2012-02-28 15:36:15 -0800804int assignFillArrayDataOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800805{
Bill Buzbeea114add2012-05-03 15:00:40 -0700806 GrowableListIterator iterator;
807 oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
808 while (true) {
809 FillArrayData *tabRec = (FillArrayData *) oatGrowableListIteratorNext(
810 &iterator);
811 if (tabRec == NULL) break;
812 tabRec->offset = offset;
813 offset += tabRec->size;
814 // word align
815 offset = (offset + 3) & ~3;
816 }
817 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800818}
819
820/*
821 * Walk the compilation unit and assign offsets to instructions
822 * and literals and compute the total size of the compiled unit.
823 */
824void oatAssignOffsets(CompilationUnit* cUnit)
825{
Bill Buzbeea114add2012-05-03 15:00:40 -0700826 int offset = oatAssignInsnOffsets(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800827
Bill Buzbeea114add2012-05-03 15:00:40 -0700828 /* Const values have to be word aligned */
829 offset = (offset + 3) & ~3;
buzbeee3acd072012-02-25 17:03:10 -0800830
Bill Buzbeea114add2012-05-03 15:00:40 -0700831 /* Set up offsets for literals */
832 cUnit->dataOffset = offset;
buzbeee3acd072012-02-25 17:03:10 -0800833
Bill Buzbeea114add2012-05-03 15:00:40 -0700834 offset = assignLiteralOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800835
Bill Buzbeea114add2012-05-03 15:00:40 -0700836 offset = assignSwitchTablesOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800837
Bill Buzbeea114add2012-05-03 15:00:40 -0700838 offset = assignFillArrayDataOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800839
Bill Buzbeea114add2012-05-03 15:00:40 -0700840 cUnit->totalSize = offset;
buzbeee3acd072012-02-25 17:03:10 -0800841}
842
843/*
844 * Go over each instruction in the list and calculate the offset from the top
845 * before sending them off to the assembler. If out-of-range branch distance is
846 * seen rearrange the instructions a bit to correct it.
847 */
848void oatAssembleLIR(CompilationUnit* cUnit)
849{
Bill Buzbeea114add2012-05-03 15:00:40 -0700850 oatAssignOffsets(cUnit);
851 /*
852 * Assemble here. Note that we generate code with optimistic assumptions
853 * and if found now to work, we'll have to redo the sequence and retry.
854 */
buzbeee3acd072012-02-25 17:03:10 -0800855
Bill Buzbeea114add2012-05-03 15:00:40 -0700856 while (true) {
857 AssemblerStatus res = oatAssembleInstructions(cUnit, 0);
858 if (res == kSuccess) {
859 break;
860 } else {
861 cUnit->assemblerRetries++;
862 if (cUnit->assemblerRetries > MAX_ASSEMBLER_RETRIES) {
863 oatCodegenDump(cUnit);
864 LOG(FATAL) << "Assembler error - too many retries";
865 }
866 // Redo offsets and try again
867 oatAssignOffsets(cUnit);
868 cUnit->codeBuffer.clear();
buzbeee3acd072012-02-25 17:03:10 -0800869 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700870 }
buzbeee3acd072012-02-25 17:03:10 -0800871
Bill Buzbeea114add2012-05-03 15:00:40 -0700872 // Install literals
873 installLiteralPools(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800874
Bill Buzbeea114add2012-05-03 15:00:40 -0700875 // Install switch tables
876 installSwitchTables(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800877
Bill Buzbeea114add2012-05-03 15:00:40 -0700878 // Install fill array data
879 installFillArrayData(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800880
Bill Buzbeea114add2012-05-03 15:00:40 -0700881 /*
882 * Create the mapping table
883 */
884 createMappingTable(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800885}
886
buzbee31a4a6f2012-02-28 15:36:15 -0800887/*
888 * Insert a kPseudoCaseLabel at the beginning of the Dalvik
889 * offset vaddr. This label will be used to fix up the case
890 * branch table during the assembly phase. Be sure to set
891 * all resource flags on this to prevent code motion across
892 * target boundaries. KeyVal is just there for debugging.
893 */
894LIR* insertCaseLabel(CompilationUnit* cUnit, int vaddr, int keyVal)
895{
Bill Buzbeea114add2012-05-03 15:00:40 -0700896 SafeMap<unsigned int, LIR*>::iterator it;
897 it = cUnit->boundaryMap.find(vaddr);
898 if (it == cUnit->boundaryMap.end()) {
899 LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr;
900 }
901 LIR* newLabel = (LIR*)oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
902 newLabel->dalvikOffset = vaddr;
903 newLabel->opcode = kPseudoCaseLabel;
904 newLabel->operands[0] = keyVal;
905 oatInsertLIRAfter(it->second, (LIR*)newLabel);
906 return newLabel;
buzbee31a4a6f2012-02-28 15:36:15 -0800907}
908
909void markPackedCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
910{
Bill Buzbeea114add2012-05-03 15:00:40 -0700911 const u2* table = tabRec->table;
912 int baseVaddr = tabRec->vaddr;
913 int *targets = (int*)&table[4];
914 int entries = table[1];
915 int lowKey = s4FromSwitchData(&table[2]);
916 for (int i = 0; i < entries; i++) {
917 tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
918 i + lowKey);
919 }
buzbee31a4a6f2012-02-28 15:36:15 -0800920}
921
922void markSparseCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
923{
Bill Buzbeea114add2012-05-03 15:00:40 -0700924 const u2* table = tabRec->table;
925 int baseVaddr = tabRec->vaddr;
926 int entries = table[1];
927 int* keys = (int*)&table[2];
928 int* targets = &keys[entries];
929 for (int i = 0; i < entries; i++) {
930 tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
931 keys[i]);
932 }
buzbee31a4a6f2012-02-28 15:36:15 -0800933}
934
935void oatProcessSwitchTables(CompilationUnit* cUnit)
936{
Bill Buzbeea114add2012-05-03 15:00:40 -0700937 GrowableListIterator iterator;
938 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
939 while (true) {
940 SwitchTable *tabRec =
941 (SwitchTable *) oatGrowableListIteratorNext(&iterator);
942 if (tabRec == NULL) break;
943 if (tabRec->table[0] == Instruction::kPackedSwitchSignature) {
944 markPackedCaseLabels(cUnit, tabRec);
945 } else if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
946 markSparseCaseLabels(cUnit, tabRec);
947 } else {
948 LOG(FATAL) << "Invalid switch table";
buzbee31a4a6f2012-02-28 15:36:15 -0800949 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700950 }
buzbee31a4a6f2012-02-28 15:36:15 -0800951}
952
953//FIXME: Do we have endian issues here?
954
955void dumpSparseSwitchTable(const u2* table)
Bill Buzbeea114add2012-05-03 15:00:40 -0700956 /*
957 * Sparse switch data format:
958 * ushort ident = 0x0200 magic value
959 * ushort size number of entries in the table; > 0
960 * int keys[size] keys, sorted low-to-high; 32-bit aligned
961 * int targets[size] branch targets, relative to switch opcode
962 *
963 * Total size is (2+size*4) 16-bit code units.
964 */
buzbee31a4a6f2012-02-28 15:36:15 -0800965{
Bill Buzbeea114add2012-05-03 15:00:40 -0700966 u2 ident = table[0];
967 int entries = table[1];
968 int* keys = (int*)&table[2];
969 int* targets = &keys[entries];
970 LOG(INFO) << "Sparse switch table - ident:0x" << std::hex << ident
971 << ", entries: " << std::dec << entries;
972 for (int i = 0; i < entries; i++) {
973 LOG(INFO) << " Key[" << keys[i] << "] -> 0x" << std::hex << targets[i];
974 }
buzbee31a4a6f2012-02-28 15:36:15 -0800975}
976
977void dumpPackedSwitchTable(const u2* table)
Bill Buzbeea114add2012-05-03 15:00:40 -0700978 /*
979 * Packed switch data format:
980 * ushort ident = 0x0100 magic value
981 * ushort size number of entries in the table
982 * int first_key first (and lowest) switch case value
983 * int targets[size] branch targets, relative to switch opcode
984 *
985 * Total size is (4+size*2) 16-bit code units.
986 */
buzbee31a4a6f2012-02-28 15:36:15 -0800987{
Bill Buzbeea114add2012-05-03 15:00:40 -0700988 u2 ident = table[0];
989 int* targets = (int*)&table[4];
990 int entries = table[1];
991 int lowKey = s4FromSwitchData(&table[2]);
992 LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident
993 << ", entries: " << std::dec << entries << ", lowKey: " << lowKey;
994 for (int i = 0; i < entries; i++) {
995 LOG(INFO) << " Key[" << (i + lowKey) << "] -> 0x" << std::hex
996 << targets[i];
997 }
buzbee31a4a6f2012-02-28 15:36:15 -0800998}
buzbeee3acd072012-02-25 17:03:10 -0800999
1000
1001} // namespace art