blob: dff30bee5ed607436b90b20c544a8fa9481031fa [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;
buzbee31a4a6f2012-02-28 15:36:15 -080077
jeffhaoe2962482012-06-28 11:29:57 -070078#if defined(TARGET_X86)
jeffhao854029c2012-07-23 17:31:30 -070079 int regId = reg & 0xf;
jeffhaoe2962482012-06-28 11:29:57 -070080 /*
81 * Double registers in x86 are just a single FP register
82 */
83 seed = 1;
84#else
jeffhao854029c2012-07-23 17:31:30 -070085 int regId = reg & 0x1f;
Bill Buzbeea114add2012-05-03 15:00:40 -070086 /*
87 * Each double register is equal to a pair of single-precision FP registers
88 */
89 seed = DOUBLEREG(reg) ? 3 : 1;
jeffhaoe2962482012-06-28 11:29:57 -070090#endif
Bill Buzbeea114add2012-05-03 15:00:40 -070091 /* FP register starts at bit position 16 */
92 shift = FPREG(reg) ? kFPReg0 : 0;
93 /* Expand the double register id into single offset */
94 shift += regId;
95 return (seed << shift);
buzbee31a4a6f2012-02-28 15:36:15 -080096}
97
98/*
99 * Mark the corresponding bit(s).
100 */
101inline void setupRegMask(u8* mask, int reg)
102{
Bill Buzbeea114add2012-05-03 15:00:40 -0700103 *mask |= getRegMaskCommon(reg);
buzbee31a4a6f2012-02-28 15:36:15 -0800104}
105
106/*
107 * Set up the proper fields in the resource mask
108 */
109void setupResourceMasks(LIR* lir)
110{
Bill Buzbeea114add2012-05-03 15:00:40 -0700111 int opcode = lir->opcode;
112 int flags;
buzbee31a4a6f2012-02-28 15:36:15 -0800113
Bill Buzbeea114add2012-05-03 15:00:40 -0700114 if (opcode <= 0) {
115 lir->useMask = lir->defMask = 0;
116 return;
117 }
buzbee31a4a6f2012-02-28 15:36:15 -0800118
Bill Buzbeea114add2012-05-03 15:00:40 -0700119 flags = EncodingMap[lir->opcode].flags;
buzbee31a4a6f2012-02-28 15:36:15 -0800120
Bill Buzbeea114add2012-05-03 15:00:40 -0700121 if (flags & NEEDS_FIXUP) {
122 lir->flags.pcRelFixup = true;
123 }
buzbee31a4a6f2012-02-28 15:36:15 -0800124
Bill Buzbeea114add2012-05-03 15:00:40 -0700125 /* Get the starting size of the instruction's template */
126 lir->flags.size = oatGetInsnSize(lir);
buzbeee88dfbf2012-03-05 11:19:57 -0800127
Bill Buzbeea114add2012-05-03 15:00:40 -0700128 /* Set up the mask for resources that are updated */
129 if (flags & (IS_LOAD | IS_STORE)) {
130 /* Default to heap - will catch specialized classes later */
131 setMemRefType(lir, flags & IS_LOAD, kHeapRef);
132 }
buzbee31a4a6f2012-02-28 15:36:15 -0800133
Bill Buzbeea114add2012-05-03 15:00:40 -0700134 /*
135 * Conservatively assume the branch here will call out a function that in
136 * turn will trash everything.
137 */
138 if (flags & IS_BRANCH) {
139 lir->defMask = lir->useMask = ENCODE_ALL;
140 return;
141 }
buzbee31a4a6f2012-02-28 15:36:15 -0800142
Bill Buzbeea114add2012-05-03 15:00:40 -0700143 if (flags & REG_DEF0) {
144 setupRegMask(&lir->defMask, lir->operands[0]);
145 }
buzbee31a4a6f2012-02-28 15:36:15 -0800146
Bill Buzbeea114add2012-05-03 15:00:40 -0700147 if (flags & REG_DEF1) {
148 setupRegMask(&lir->defMask, lir->operands[1]);
149 }
buzbee31a4a6f2012-02-28 15:36:15 -0800150
jeffhaoe2962482012-06-28 11:29:57 -0700151#if defined(TARGET_X86)
152 if (flags & REG_DEFA) {
153 setupRegMask(&lir->defMask, rAX);
154 }
155
156 if (flags & REG_DEFD) {
157 setupRegMask(&lir->defMask, rDX);
158 }
159#endif
160
Bill Buzbeea114add2012-05-03 15:00:40 -0700161 if (flags & REG_DEF_SP) {
162 lir->defMask |= ENCODE_REG_SP;
163 }
buzbee31a4a6f2012-02-28 15:36:15 -0800164
buzbeea7678db2012-03-05 15:35:46 -0800165#if !defined(TARGET_X86)
Bill Buzbeea114add2012-05-03 15:00:40 -0700166 if (flags & REG_DEF_LR) {
167 lir->defMask |= ENCODE_REG_LR;
168 }
buzbeea7678db2012-03-05 15:35:46 -0800169#endif
buzbee31a4a6f2012-02-28 15:36:15 -0800170
jeffhaoe2962482012-06-28 11:29:57 -0700171#if defined(TARGET_ARM)
Bill Buzbeea114add2012-05-03 15:00:40 -0700172 if (flags & REG_DEF_LIST0) {
173 lir->defMask |= ENCODE_REG_LIST(lir->operands[0]);
174 }
buzbee31a4a6f2012-02-28 15:36:15 -0800175
Bill Buzbeea114add2012-05-03 15:00:40 -0700176 if (flags & REG_DEF_LIST1) {
177 lir->defMask |= ENCODE_REG_LIST(lir->operands[1]);
178 }
buzbee31a4a6f2012-02-28 15:36:15 -0800179
Bill Buzbeea114add2012-05-03 15:00:40 -0700180 if (flags & REG_DEF_FPCS_LIST0) {
181 lir->defMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]);
182 }
buzbee31a4a6f2012-02-28 15:36:15 -0800183
Bill Buzbeea114add2012-05-03 15:00:40 -0700184 if (flags & REG_DEF_FPCS_LIST2) {
185 for (int i = 0; i < lir->operands[2]; i++) {
186 setupRegMask(&lir->defMask, lir->operands[1] + i);
buzbee31a4a6f2012-02-28 15:36:15 -0800187 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700188 }
buzbee5de34942012-03-01 14:51:57 -0800189#endif
buzbee31a4a6f2012-02-28 15:36:15 -0800190
Bill Buzbeea114add2012-05-03 15:00:40 -0700191 if (flags & SETS_CCODES) {
192 lir->defMask |= ENCODE_CCODE;
193 }
buzbee31a4a6f2012-02-28 15:36:15 -0800194
195#if defined(TARGET_ARM)
Bill Buzbeea114add2012-05-03 15:00:40 -0700196 /* Conservatively treat the IT block */
197 if (flags & IS_IT) {
198 lir->defMask = ENCODE_ALL;
199 }
buzbee31a4a6f2012-02-28 15:36:15 -0800200#endif
201
Bill Buzbeea114add2012-05-03 15:00:40 -0700202 if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) {
203 int i;
buzbee31a4a6f2012-02-28 15:36:15 -0800204
Bill Buzbeea114add2012-05-03 15:00:40 -0700205 for (i = 0; i < 4; i++) {
206 if (flags & (1 << (kRegUse0 + i))) {
207 setupRegMask(&lir->useMask, lir->operands[i]);
208 }
buzbee31a4a6f2012-02-28 15:36:15 -0800209 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700210 }
buzbee31a4a6f2012-02-28 15:36:15 -0800211
jeffhaoe2962482012-06-28 11:29:57 -0700212#if defined(TARGET_X86)
213 if (flags & REG_USEA) {
214 setupRegMask(&lir->useMask, rAX);
215 }
216
217 if (flags & REG_USEC) {
218 setupRegMask(&lir->useMask, rCX);
219 }
220
221 if (flags & REG_USED) {
222 setupRegMask(&lir->useMask, rDX);
223 }
224#endif
225
buzbeea7678db2012-03-05 15:35:46 -0800226#if defined(TARGET_ARM)
Bill Buzbeea114add2012-05-03 15:00:40 -0700227 if (flags & REG_USE_PC) {
228 lir->useMask |= ENCODE_REG_PC;
229 }
buzbeea7678db2012-03-05 15:35:46 -0800230#endif
buzbee31a4a6f2012-02-28 15:36:15 -0800231
Bill Buzbeea114add2012-05-03 15:00:40 -0700232 if (flags & REG_USE_SP) {
233 lir->useMask |= ENCODE_REG_SP;
234 }
buzbee31a4a6f2012-02-28 15:36:15 -0800235
jeffhaoe2962482012-06-28 11:29:57 -0700236#if defined(TARGET_ARM)
Bill Buzbeea114add2012-05-03 15:00:40 -0700237 if (flags & REG_USE_LIST0) {
238 lir->useMask |= ENCODE_REG_LIST(lir->operands[0]);
239 }
buzbee31a4a6f2012-02-28 15:36:15 -0800240
Bill Buzbeea114add2012-05-03 15:00:40 -0700241 if (flags & REG_USE_LIST1) {
242 lir->useMask |= ENCODE_REG_LIST(lir->operands[1]);
243 }
buzbee31a4a6f2012-02-28 15:36:15 -0800244
Bill Buzbeea114add2012-05-03 15:00:40 -0700245 if (flags & REG_USE_FPCS_LIST0) {
246 lir->useMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]);
247 }
buzbee31a4a6f2012-02-28 15:36:15 -0800248
Bill Buzbeea114add2012-05-03 15:00:40 -0700249 if (flags & REG_USE_FPCS_LIST2) {
250 for (int i = 0; i < lir->operands[2]; i++) {
251 setupRegMask(&lir->useMask, lir->operands[1] + i);
buzbee31a4a6f2012-02-28 15:36:15 -0800252 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700253 }
buzbee5de34942012-03-01 14:51:57 -0800254#endif
buzbee31a4a6f2012-02-28 15:36:15 -0800255
Bill Buzbeea114add2012-05-03 15:00:40 -0700256 if (flags & USES_CCODES) {
257 lir->useMask |= ENCODE_CCODE;
258 }
buzbee31a4a6f2012-02-28 15:36:15 -0800259
260#if defined(TARGET_ARM)
Bill Buzbeea114add2012-05-03 15:00:40 -0700261 /* Fixup for kThumbPush/lr and kThumbPop/pc */
262 if (opcode == kThumbPush || opcode == kThumbPop) {
263 u8 r8Mask = getRegMaskCommon(r8);
264 if ((opcode == kThumbPush) && (lir->useMask & r8Mask)) {
265 lir->useMask &= ~r8Mask;
266 lir->useMask |= ENCODE_REG_LR;
267 } else if ((opcode == kThumbPop) && (lir->defMask & r8Mask)) {
268 lir->defMask &= ~r8Mask;
269 lir->defMask |= ENCODE_REG_PC;
buzbee31a4a6f2012-02-28 15:36:15 -0800270 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700271 }
buzbee31a4a6f2012-02-28 15:36:15 -0800272#endif
273}
274
275/*
buzbee5de34942012-03-01 14:51:57 -0800276 * Debugging macros
277 */
278#define DUMP_RESOURCE_MASK(X)
279#define DUMP_SSA_REP(X)
280
281/* Pretty-print a LIR instruction */
282void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr)
283{
Bill Buzbeea114add2012-05-03 15:00:40 -0700284 LIR* lir = (LIR*) arg;
285 int offset = lir->offset;
286 int dest = lir->operands[0];
287 const bool dumpNop = (cUnit->enableDebug & (1 << kDebugShowNops));
buzbee5de34942012-03-01 14:51:57 -0800288
Bill Buzbeea114add2012-05-03 15:00:40 -0700289 /* Handle pseudo-ops individually, and all regular insns as a group */
290 switch (lir->opcode) {
291 case kPseudoMethodEntry:
292 LOG(INFO) << "-------- method entry "
293 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
294 break;
295 case kPseudoMethodExit:
296 LOG(INFO) << "-------- Method_Exit";
297 break;
298 case kPseudoBarrier:
299 LOG(INFO) << "-------- BARRIER";
300 break;
301 case kPseudoExtended:
302 LOG(INFO) << "-------- " << (char* ) dest;
303 break;
304 case kPseudoSSARep:
305 DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " << (char* ) dest);
306 break;
307 case kPseudoEntryBlock:
308 LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
309 break;
310 case kPseudoDalvikByteCodeBoundary:
311 LOG(INFO) << "-------- dalvik offset: 0x" << std::hex
312 << lir->dalvikOffset << " @ " << (char* )lir->operands[0];
313 break;
314 case kPseudoExitBlock:
315 LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
316 break;
317 case kPseudoPseudoAlign4:
318 LOG(INFO) << (intptr_t)baseAddr + offset << " (0x" << std::hex
319 << offset << "): .align4";
320 break;
321 case kPseudoEHBlockLabel:
322 LOG(INFO) << "Exception_Handling:";
323 break;
324 case kPseudoTargetLabel:
325 case kPseudoNormalBlockLabel:
326 LOG(INFO) << "L" << (void*)lir << ":";
327 break;
328 case kPseudoThrowTarget:
329 LOG(INFO) << "LT" << (void*)lir << ":";
330 break;
331 case kPseudoIntrinsicRetry:
332 LOG(INFO) << "IR" << (void*)lir << ":";
333 break;
334 case kPseudoSuspendTarget:
335 LOG(INFO) << "LS" << (void*)lir << ":";
336 break;
buzbee8320f382012-09-11 16:29:42 -0700337 case kPseudoSafepointPC:
338 LOG(INFO) << "LsafepointPC_0x" << std::hex << lir->offset << "_" << lir->dalvikOffset << ":";
339 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700340 case kPseudoCaseLabel:
341 LOG(INFO) << "LC" << (void*)lir << ": Case target 0x"
342 << std::hex << lir->operands[0] << "|" << std::dec <<
343 lir->operands[0];
344 break;
345 default:
346 if (lir->flags.isNop && !dumpNop) {
347 break;
348 } else {
349 std::string op_name(buildInsnString(EncodingMap[lir->opcode].name,
350 lir, baseAddr));
351 std::string op_operands(buildInsnString(EncodingMap[lir->opcode].fmt
352 , lir, baseAddr));
353 LOG(INFO) << StringPrintf("%05x: %-9s%s%s",
354 (unsigned int)(baseAddr + offset),
355 op_name.c_str(), op_operands.c_str(),
356 lir->flags.isNop ? "(nop)" : "");
357 }
358 break;
359 }
buzbee5de34942012-03-01 14:51:57 -0800360
Bill Buzbeea114add2012-05-03 15:00:40 -0700361 if (lir->useMask && (!lir->flags.isNop || dumpNop)) {
362 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->useMask, "use"));
363 }
364 if (lir->defMask && (!lir->flags.isNop || dumpNop)) {
365 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->defMask, "def"));
366 }
buzbee5de34942012-03-01 14:51:57 -0800367}
368
369void oatDumpPromotionMap(CompilationUnit *cUnit)
370{
Bill Buzbeea114add2012-05-03 15:00:40 -0700371 int numRegs = cUnit->numDalvikRegisters + cUnit->numCompilerTemps + 1;
372 for (int i = 0; i < numRegs; i++) {
373 PromotionMap vRegMap = cUnit->promotionMap[i];
374 std::string buf;
375 if (vRegMap.fpLocation == kLocPhysReg) {
376 StringAppendF(&buf, " : s%d", vRegMap.fpReg & FP_REG_MASK);
buzbee5de34942012-03-01 14:51:57 -0800377 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700378
379 std::string buf3;
380 if (i < cUnit->numDalvikRegisters) {
381 StringAppendF(&buf3, "%02d", i);
382 } else if (i == cUnit->methodSReg) {
383 buf3 = "Method*";
384 } else {
385 StringAppendF(&buf3, "ct%d", i - cUnit->numDalvikRegisters);
386 }
387
388 LOG(INFO) << StringPrintf("V[%s] -> %s%d%s", buf3.c_str(),
389 vRegMap.coreLocation == kLocPhysReg ?
390 "r" : "SP+", vRegMap.coreLocation == kLocPhysReg ?
391 vRegMap.coreReg : oatSRegOffset(cUnit, i),
392 buf.c_str());
393 }
buzbee5de34942012-03-01 14:51:57 -0800394}
395
buzbee5de34942012-03-01 14:51:57 -0800396/* Dump instructions and constant pool contents */
397void oatCodegenDump(CompilationUnit* cUnit)
398{
Bill Buzbeea114add2012-05-03 15:00:40 -0700399 LOG(INFO) << "Dumping LIR insns for "
400 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
401 LIR* lirInsn;
402 LIR* thisLIR;
403 int insnsSize = cUnit->insnsSize;
buzbee5de34942012-03-01 14:51:57 -0800404
Bill Buzbeea114add2012-05-03 15:00:40 -0700405 LOG(INFO) << "Regs (excluding ins) : " << cUnit->numRegs;
406 LOG(INFO) << "Ins : " << cUnit->numIns;
407 LOG(INFO) << "Outs : " << cUnit->numOuts;
408 LOG(INFO) << "CoreSpills : " << cUnit->numCoreSpills;
409 LOG(INFO) << "FPSpills : " << cUnit->numFPSpills;
410 LOG(INFO) << "CompilerTemps : " << cUnit->numCompilerTemps;
411 LOG(INFO) << "Frame size : " << cUnit->frameSize;
412 LOG(INFO) << "code size is " << cUnit->totalSize <<
413 " bytes, Dalvik size is " << insnsSize * 2;
414 LOG(INFO) << "expansion factor: "
415 << (float)cUnit->totalSize / (float)(insnsSize * 2);
416 oatDumpPromotionMap(cUnit);
417 for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
418 oatDumpLIRInsn(cUnit, lirInsn, 0);
419 }
420 for (lirInsn = cUnit->classPointerList; lirInsn; lirInsn = lirInsn->next) {
421 thisLIR = (LIR*) lirInsn;
422 LOG(INFO) << StringPrintf("%x (%04x): .class (%s)",
423 thisLIR->offset, thisLIR->offset,
424 ((CallsiteInfo *)
425 thisLIR->operands[0])->classDescriptor);
426 }
427 for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
428 thisLIR = (LIR*) lirInsn;
429 LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)",
430 thisLIR->offset, thisLIR->offset,
431 thisLIR->operands[0]);
432 }
buzbee5de34942012-03-01 14:51:57 -0800433
Bill Buzbeea114add2012-05-03 15:00:40 -0700434 const DexFile::MethodId& method_id =
435 cUnit->dex_file->GetMethodId(cUnit->method_idx);
436 std::string signature(cUnit->dex_file->GetMethodSignature(method_id));
437 std::string name(cUnit->dex_file->GetMethodName(method_id));
438 std::string descriptor(cUnit->dex_file->GetMethodDeclaringClassDescriptor(method_id));
buzbee5de34942012-03-01 14:51:57 -0800439
Bill Buzbeea114add2012-05-03 15:00:40 -0700440 // Dump mapping table
441 if (cUnit->mappingTable.size() > 0) {
442 std::string
443 line(StringPrintf("\n MappingTable %s%s_%s_mappingTable[%zu] = {",
444 descriptor.c_str(), name.c_str(), signature.c_str(),
445 cUnit->mappingTable.size()));
446 std::replace(line.begin(), line.end(), ';', '_');
447 LOG(INFO) << line;
448 for (uint32_t i = 0; i < cUnit->mappingTable.size(); i+=2) {
449 line = StringPrintf(" {0x%05x, 0x%04x},",
450 cUnit->mappingTable[i], cUnit->mappingTable[i+1]);
451 LOG(INFO) << line;
buzbee5de34942012-03-01 14:51:57 -0800452 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700453 LOG(INFO) <<" };\n\n";
454 }
buzbee5de34942012-03-01 14:51:57 -0800455}
456
buzbeea2ebdd72012-03-04 14:57:06 -0800457
458LIR* rawLIR(CompilationUnit* cUnit, int dalvikOffset, int opcode, int op0,
Bill Buzbeea114add2012-05-03 15:00:40 -0700459 int op1, int op2, int op3, int op4, LIR* target)
buzbeea2ebdd72012-03-04 14:57:06 -0800460{
Bill Buzbeea114add2012-05-03 15:00:40 -0700461 LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
462 insn->dalvikOffset = dalvikOffset;
463 insn->opcode = opcode;
464 insn->operands[0] = op0;
465 insn->operands[1] = op1;
466 insn->operands[2] = op2;
467 insn->operands[3] = op3;
468 insn->operands[4] = op4;
469 insn->target = target;
470 oatSetupResourceMasks(insn);
buzbee8320f382012-09-11 16:29:42 -0700471 if ((opcode == kPseudoTargetLabel) || (opcode == kPseudoSafepointPC)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700472 // Always make labels scheduling barriers
buzbee8320f382012-09-11 16:29:42 -0700473 insn->useMask = insn->defMask = ENCODE_ALL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700474 }
475 return insn;
buzbeea2ebdd72012-03-04 14:57:06 -0800476}
477
buzbee5de34942012-03-01 14:51:57 -0800478/*
buzbee31a4a6f2012-02-28 15:36:15 -0800479 * The following are building blocks to construct low-level IRs with 0 - 4
480 * operands.
481 */
buzbee5de34942012-03-01 14:51:57 -0800482LIR* newLIR0(CompilationUnit* cUnit, int opcode)
buzbee31a4a6f2012-02-28 15:36:15 -0800483{
Bill Buzbeea114add2012-05-03 15:00:40 -0700484 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND))
485 << EncodingMap[opcode].name << " " << (int)opcode << " "
486 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
487 << cUnit->currentDalvikOffset;
488 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode);
489 oatAppendLIR(cUnit, (LIR*) insn);
490 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800491}
492
buzbee5de34942012-03-01 14:51:57 -0800493LIR* newLIR1(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700494 int dest)
buzbee31a4a6f2012-02-28 15:36:15 -0800495{
Bill Buzbeea114add2012-05-03 15:00:40 -0700496 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_UNARY_OP))
497 << EncodingMap[opcode].name << " " << (int)opcode << " "
498 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
499 << cUnit->currentDalvikOffset;
500 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest);
501 oatAppendLIR(cUnit, (LIR*) insn);
502 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800503}
504
buzbee5de34942012-03-01 14:51:57 -0800505LIR* newLIR2(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700506 int dest, int src1)
buzbee31a4a6f2012-02-28 15:36:15 -0800507{
Bill Buzbeea114add2012-05-03 15:00:40 -0700508 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_BINARY_OP))
509 << EncodingMap[opcode].name << " " << (int)opcode << " "
510 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
511 << cUnit->currentDalvikOffset;
512 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1);
513 oatAppendLIR(cUnit, (LIR*) insn);
514 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800515}
516
buzbee5de34942012-03-01 14:51:57 -0800517LIR* newLIR3(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700518 int dest, int src1, int src2)
buzbee31a4a6f2012-02-28 15:36:15 -0800519{
Bill Buzbeea114add2012-05-03 15:00:40 -0700520 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_TERTIARY_OP))
521 << EncodingMap[opcode].name << " " << (int)opcode << " "
522 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
523 << cUnit->currentDalvikOffset;
524 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
525 src2);
526 oatAppendLIR(cUnit, (LIR*) insn);
527 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800528}
529
buzbee5de34942012-03-01 14:51:57 -0800530LIR* newLIR4(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700531 int dest, int src1, int src2, int info)
buzbee31a4a6f2012-02-28 15:36:15 -0800532{
Bill Buzbeea114add2012-05-03 15:00:40 -0700533 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUAD_OP))
534 << EncodingMap[opcode].name << " " << (int)opcode << " "
535 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
536 << cUnit->currentDalvikOffset;
537 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
538 src2, info);
539 oatAppendLIR(cUnit, (LIR*) insn);
540 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800541}
buzbee31a4a6f2012-02-28 15:36:15 -0800542
Ian Rogersb5d09b22012-03-06 22:14:17 -0800543LIR* newLIR5(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700544 int dest, int src1, int src2, int info1, int info2)
Ian Rogersb5d09b22012-03-06 22:14:17 -0800545{
Bill Buzbeea114add2012-05-03 15:00:40 -0700546 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUIN_OP))
547 << EncodingMap[opcode].name << " " << (int)opcode << " "
548 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
549 << cUnit->currentDalvikOffset;
550 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
551 src2, info1, info2);
552 oatAppendLIR(cUnit, (LIR*) insn);
553 return insn;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800554}
555
buzbee31a4a6f2012-02-28 15:36:15 -0800556/*
557 * Search the existing constants in the literal pool for an exact or close match
558 * within specified delta (greater or equal to 0).
559 */
560LIR* scanLiteralPool(LIR* dataTarget, int value, unsigned int delta)
561{
Bill Buzbeea114add2012-05-03 15:00:40 -0700562 while (dataTarget) {
563 if (((unsigned) (value - ((LIR* ) dataTarget)->operands[0])) <= delta)
564 return (LIR* ) dataTarget;
565 dataTarget = dataTarget->next;
566 }
567 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800568}
569
570/* Search the existing constants in the literal pool for an exact wide match */
571LIR* scanLiteralPoolWide(LIR* dataTarget, int valLo, int valHi)
572{
Bill Buzbeea114add2012-05-03 15:00:40 -0700573 bool loMatch = false;
574 LIR* loTarget = NULL;
575 while (dataTarget) {
576 if (loMatch && (((LIR*)dataTarget)->operands[0] == valHi)) {
577 return (LIR*)loTarget;
buzbee31a4a6f2012-02-28 15:36:15 -0800578 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700579 loMatch = false;
580 if (((LIR*)dataTarget)->operands[0] == valLo) {
581 loMatch = true;
582 loTarget = dataTarget;
583 }
584 dataTarget = dataTarget->next;
585 }
586 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800587}
588
589/*
590 * The following are building blocks to insert constants into the pool or
591 * instruction streams.
592 */
593
buzbee5de34942012-03-01 14:51:57 -0800594/* Add a 32-bit constant either in the constant pool */
Ian Rogers3fa13792012-03-18 15:53:45 -0700595LIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP, int value)
buzbee31a4a6f2012-02-28 15:36:15 -0800596{
Bill Buzbeea114add2012-05-03 15:00:40 -0700597 /* Add the constant to the literal pool */
598 if (constantListP) {
599 LIR* newValue = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocData);
600 newValue->operands[0] = value;
601 newValue->next = *constantListP;
602 *constantListP = (LIR*) newValue;
603 return newValue;
604 }
605 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800606}
607
608/* Add a 64-bit constant to the constant pool or mixed with code */
609LIR* addWideData(CompilationUnit* cUnit, LIR* *constantListP,
Bill Buzbeea114add2012-05-03 15:00:40 -0700610 int valLo, int valHi)
buzbee31a4a6f2012-02-28 15:36:15 -0800611{
Bill Buzbeea114add2012-05-03 15:00:40 -0700612 //FIXME: hard-coded little endian, need BE variant
613 // Insert high word into list first
614 addWordData(cUnit, constantListP, valHi);
615 return addWordData(cUnit, constantListP, valLo);
buzbee31a4a6f2012-02-28 15:36:15 -0800616}
617
Ian Rogersab058bb2012-03-11 22:19:38 -0700618void pushWord(std::vector<uint8_t>&buf, int data) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700619 buf.push_back( data & 0xff);
620 buf.push_back( (data >> 8) & 0xff);
621 buf.push_back( (data >> 16) & 0xff);
622 buf.push_back( (data >> 24) & 0xff);
buzbeee3acd072012-02-25 17:03:10 -0800623}
624
Ian Rogersab058bb2012-03-11 22:19:38 -0700625void alignBuffer(std::vector<uint8_t>&buf, size_t offset) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700626 while (buf.size() < offset) {
627 buf.push_back(0);
628 }
buzbeee3acd072012-02-25 17:03:10 -0800629}
630
Brian Carlstromf5822582012-03-19 22:34:31 -0700631bool IsDirect(int invokeType) {
632 InvokeType type = static_cast<InvokeType>(invokeType);
633 return type == kStatic || type == kDirect;
634}
635
buzbeee3acd072012-02-25 17:03:10 -0800636/* Write the literal pool to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800637void installLiteralPools(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800638{
Bill Buzbeea114add2012-05-03 15:00:40 -0700639 alignBuffer(cUnit->codeBuffer, cUnit->dataOffset);
640 LIR* dataLIR = cUnit->literalList;
641 while (dataLIR != NULL) {
642 pushWord(cUnit->codeBuffer, dataLIR->operands[0]);
643 dataLIR = NEXT_LIR(dataLIR);
644 }
645 // Push code and method literals, record offsets for the compiler to patch.
646 dataLIR = cUnit->codeLiteralList;
647 if (dataLIR != NULL) {
buzbeee3acd072012-02-25 17:03:10 -0800648 while (dataLIR != NULL) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700649 uint32_t target = dataLIR->operands[0];
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700650 cUnit->compiler->AddCodePatch(cUnit->dex_file,
Bill Buzbeea114add2012-05-03 15:00:40 -0700651 cUnit->method_idx,
Ian Rogers08f753d2012-08-24 14:35:25 -0700652 cUnit->invoke_type,
Bill Buzbeea114add2012-05-03 15:00:40 -0700653 target,
Ian Rogers08f753d2012-08-24 14:35:25 -0700654 static_cast<InvokeType>(dataLIR->operands[1]),
Bill Buzbeea114add2012-05-03 15:00:40 -0700655 cUnit->codeBuffer.size());
656 const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target);
657 // unique based on target to ensure code deduplication works
658 uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
659 pushWord(cUnit->codeBuffer, unique_patch_value);
660 dataLIR = NEXT_LIR(dataLIR);
buzbeee3acd072012-02-25 17:03:10 -0800661 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700662 dataLIR = cUnit->methodLiteralList;
663 while (dataLIR != NULL) {
664 uint32_t target = dataLIR->operands[0];
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700665 cUnit->compiler->AddMethodPatch(cUnit->dex_file,
Bill Buzbeea114add2012-05-03 15:00:40 -0700666 cUnit->method_idx,
Ian Rogers08f753d2012-08-24 14:35:25 -0700667 cUnit->invoke_type,
Bill Buzbeea114add2012-05-03 15:00:40 -0700668 target,
Ian Rogers08f753d2012-08-24 14:35:25 -0700669 static_cast<InvokeType>(dataLIR->operands[1]),
Bill Buzbeea114add2012-05-03 15:00:40 -0700670 cUnit->codeBuffer.size());
671 const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target);
672 // unique based on target to ensure code deduplication works
673 uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
674 pushWord(cUnit->codeBuffer, unique_patch_value);
675 dataLIR = NEXT_LIR(dataLIR);
Ian Rogers3fa13792012-03-18 15:53:45 -0700676 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700677 }
Ian Rogers3fa13792012-03-18 15:53:45 -0700678
buzbeee3acd072012-02-25 17:03:10 -0800679}
680
681/* Write the switch tables to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800682void installSwitchTables(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800683{
Bill Buzbeea114add2012-05-03 15:00:40 -0700684 GrowableListIterator iterator;
685 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
686 while (true) {
687 SwitchTable* tabRec = (SwitchTable *) oatGrowableListIteratorNext(
688 &iterator);
689 if (tabRec == NULL) break;
690 alignBuffer(cUnit->codeBuffer, tabRec->offset);
691 /*
692 * For Arm, our reference point is the address of the bx
693 * instruction that does the launch, so we have to subtract
694 * the auto pc-advance. For other targets the reference point
695 * is a label, so we can use the offset as-is.
696 */
buzbeec5159d52012-03-03 11:48:39 -0800697#if defined(TARGET_ARM)
Bill Buzbeea114add2012-05-03 15:00:40 -0700698 int bxOffset = tabRec->anchor->offset + 4;
Ian Rogers7caad772012-03-30 01:07:54 -0700699#elif defined(TARGET_X86)
Bill Buzbeea114add2012-05-03 15:00:40 -0700700 int bxOffset = 0;
buzbeec5159d52012-03-03 11:48:39 -0800701#else
Bill Buzbeea114add2012-05-03 15:00:40 -0700702 int bxOffset = tabRec->anchor->offset;
buzbeec5159d52012-03-03 11:48:39 -0800703#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700704 if (cUnit->printMe) {
705 LOG(INFO) << "Switch table for offset 0x" << std::hex << bxOffset;
buzbeee3acd072012-02-25 17:03:10 -0800706 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700707 if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
708 int* keys = (int*)&(tabRec->table[2]);
709 for (int elems = 0; elems < tabRec->table[1]; elems++) {
710 int disp = tabRec->targets[elems]->offset - bxOffset;
711 if (cUnit->printMe) {
712 LOG(INFO) << " Case[" << elems << "] key: 0x"
713 << std::hex << keys[elems] << ", disp: 0x"
714 << std::hex << disp;
715 }
716 pushWord(cUnit->codeBuffer, keys[elems]);
717 pushWord(cUnit->codeBuffer,
718 tabRec->targets[elems]->offset - bxOffset);
719 }
720 } else {
721 DCHECK_EQ(static_cast<int>(tabRec->table[0]),
722 static_cast<int>(Instruction::kPackedSwitchSignature));
723 for (int elems = 0; elems < tabRec->table[1]; elems++) {
724 int disp = tabRec->targets[elems]->offset - bxOffset;
725 if (cUnit->printMe) {
726 LOG(INFO) << " Case[" << elems << "] disp: 0x"
727 << std::hex << disp;
728 }
729 pushWord(cUnit->codeBuffer, tabRec->targets[elems]->offset - bxOffset);
730 }
731 }
732 }
buzbeee3acd072012-02-25 17:03:10 -0800733}
734
735/* Write the fill array dta to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800736void installFillArrayData(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800737{
Bill Buzbeea114add2012-05-03 15:00:40 -0700738 GrowableListIterator iterator;
739 oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
740 while (true) {
741 FillArrayData *tabRec = (FillArrayData *) oatGrowableListIteratorNext(
742 &iterator);
743 if (tabRec == NULL) break;
744 alignBuffer(cUnit->codeBuffer, tabRec->offset);
745 for (int i = 0; i < (tabRec->size + 1) / 2; i++) {
746 cUnit->codeBuffer.push_back( tabRec->table[i] & 0xFF);
747 cUnit->codeBuffer.push_back( (tabRec->table[i] >> 8) & 0xFF);
buzbeee3acd072012-02-25 17:03:10 -0800748 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700749 }
buzbeee3acd072012-02-25 17:03:10 -0800750}
751
buzbee31a4a6f2012-02-28 15:36:15 -0800752int assignLiteralOffsetCommon(LIR* lir, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800753{
Bill Buzbeea114add2012-05-03 15:00:40 -0700754 for (;lir != NULL; lir = lir->next) {
755 lir->offset = offset;
756 offset += 4;
757 }
758 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800759}
760
buzbee31a4a6f2012-02-28 15:36:15 -0800761void createMappingTable(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800762{
buzbee8320f382012-09-11 16:29:42 -0700763 for (LIR* tgtLIR = (LIR *) cUnit->firstLIRInsn; tgtLIR != NULL; tgtLIR = NEXT_LIR(tgtLIR)) {
764 if (!tgtLIR->flags.isNop && (tgtLIR->opcode == kPseudoSafepointPC)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700765 cUnit->mappingTable.push_back(tgtLIR->offset);
766 cUnit->mappingTable.push_back(tgtLIR->dalvikOffset);
buzbeee3acd072012-02-25 17:03:10 -0800767 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700768 }
buzbeee3acd072012-02-25 17:03:10 -0800769}
770
771/* Determine the offset of each literal field */
buzbee31a4a6f2012-02-28 15:36:15 -0800772int assignLiteralOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800773{
Bill Buzbeea114add2012-05-03 15:00:40 -0700774 offset = assignLiteralOffsetCommon(cUnit->literalList, offset);
775 offset = assignLiteralOffsetCommon(cUnit->codeLiteralList, offset);
776 offset = assignLiteralOffsetCommon(cUnit->methodLiteralList, offset);
777 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800778}
779
buzbee31a4a6f2012-02-28 15:36:15 -0800780int assignSwitchTablesOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800781{
Bill Buzbeea114add2012-05-03 15:00:40 -0700782 GrowableListIterator iterator;
783 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
784 while (true) {
785 SwitchTable *tabRec = (SwitchTable *) oatGrowableListIteratorNext(
786 &iterator);
787 if (tabRec == NULL) break;
788 tabRec->offset = offset;
789 if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
790 offset += tabRec->table[1] * (sizeof(int) * 2);
791 } else {
792 DCHECK_EQ(static_cast<int>(tabRec->table[0]),
793 static_cast<int>(Instruction::kPackedSwitchSignature));
794 offset += tabRec->table[1] * sizeof(int);
buzbeee3acd072012-02-25 17:03:10 -0800795 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700796 }
797 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800798}
799
buzbee31a4a6f2012-02-28 15:36:15 -0800800int assignFillArrayDataOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800801{
Bill Buzbeea114add2012-05-03 15:00:40 -0700802 GrowableListIterator iterator;
803 oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
804 while (true) {
805 FillArrayData *tabRec = (FillArrayData *) oatGrowableListIteratorNext(
806 &iterator);
807 if (tabRec == NULL) break;
808 tabRec->offset = offset;
809 offset += tabRec->size;
810 // word align
811 offset = (offset + 3) & ~3;
812 }
813 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800814}
815
816/*
817 * Walk the compilation unit and assign offsets to instructions
818 * and literals and compute the total size of the compiled unit.
819 */
820void oatAssignOffsets(CompilationUnit* cUnit)
821{
Bill Buzbeea114add2012-05-03 15:00:40 -0700822 int offset = oatAssignInsnOffsets(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800823
Bill Buzbeea114add2012-05-03 15:00:40 -0700824 /* Const values have to be word aligned */
825 offset = (offset + 3) & ~3;
buzbeee3acd072012-02-25 17:03:10 -0800826
Bill Buzbeea114add2012-05-03 15:00:40 -0700827 /* Set up offsets for literals */
828 cUnit->dataOffset = offset;
buzbeee3acd072012-02-25 17:03:10 -0800829
Bill Buzbeea114add2012-05-03 15:00:40 -0700830 offset = assignLiteralOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800831
Bill Buzbeea114add2012-05-03 15:00:40 -0700832 offset = assignSwitchTablesOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800833
Bill Buzbeea114add2012-05-03 15:00:40 -0700834 offset = assignFillArrayDataOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800835
Bill Buzbeea114add2012-05-03 15:00:40 -0700836 cUnit->totalSize = offset;
buzbeee3acd072012-02-25 17:03:10 -0800837}
838
839/*
840 * Go over each instruction in the list and calculate the offset from the top
841 * before sending them off to the assembler. If out-of-range branch distance is
842 * seen rearrange the instructions a bit to correct it.
843 */
844void oatAssembleLIR(CompilationUnit* cUnit)
845{
Bill Buzbeea114add2012-05-03 15:00:40 -0700846 oatAssignOffsets(cUnit);
847 /*
848 * Assemble here. Note that we generate code with optimistic assumptions
849 * and if found now to work, we'll have to redo the sequence and retry.
850 */
buzbeee3acd072012-02-25 17:03:10 -0800851
Bill Buzbeea114add2012-05-03 15:00:40 -0700852 while (true) {
853 AssemblerStatus res = oatAssembleInstructions(cUnit, 0);
854 if (res == kSuccess) {
855 break;
856 } else {
857 cUnit->assemblerRetries++;
858 if (cUnit->assemblerRetries > MAX_ASSEMBLER_RETRIES) {
859 oatCodegenDump(cUnit);
860 LOG(FATAL) << "Assembler error - too many retries";
861 }
862 // Redo offsets and try again
863 oatAssignOffsets(cUnit);
864 cUnit->codeBuffer.clear();
buzbeee3acd072012-02-25 17:03:10 -0800865 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700866 }
buzbeee3acd072012-02-25 17:03:10 -0800867
Bill Buzbeea114add2012-05-03 15:00:40 -0700868 // Install literals
869 installLiteralPools(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800870
Bill Buzbeea114add2012-05-03 15:00:40 -0700871 // Install switch tables
872 installSwitchTables(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800873
Bill Buzbeea114add2012-05-03 15:00:40 -0700874 // Install fill array data
875 installFillArrayData(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800876
Bill Buzbeea114add2012-05-03 15:00:40 -0700877 /*
878 * Create the mapping table
879 */
880 createMappingTable(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800881}
882
buzbee31a4a6f2012-02-28 15:36:15 -0800883/*
884 * Insert a kPseudoCaseLabel at the beginning of the Dalvik
885 * offset vaddr. This label will be used to fix up the case
886 * branch table during the assembly phase. Be sure to set
887 * all resource flags on this to prevent code motion across
888 * target boundaries. KeyVal is just there for debugging.
889 */
890LIR* insertCaseLabel(CompilationUnit* cUnit, int vaddr, int keyVal)
891{
Bill Buzbeea114add2012-05-03 15:00:40 -0700892 SafeMap<unsigned int, LIR*>::iterator it;
893 it = cUnit->boundaryMap.find(vaddr);
894 if (it == cUnit->boundaryMap.end()) {
895 LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr;
896 }
897 LIR* newLabel = (LIR*)oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
898 newLabel->dalvikOffset = vaddr;
899 newLabel->opcode = kPseudoCaseLabel;
900 newLabel->operands[0] = keyVal;
901 oatInsertLIRAfter(it->second, (LIR*)newLabel);
902 return newLabel;
buzbee31a4a6f2012-02-28 15:36:15 -0800903}
904
905void markPackedCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
906{
Bill Buzbeea114add2012-05-03 15:00:40 -0700907 const u2* table = tabRec->table;
908 int baseVaddr = tabRec->vaddr;
909 int *targets = (int*)&table[4];
910 int entries = table[1];
911 int lowKey = s4FromSwitchData(&table[2]);
912 for (int i = 0; i < entries; i++) {
913 tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
914 i + lowKey);
915 }
buzbee31a4a6f2012-02-28 15:36:15 -0800916}
917
918void markSparseCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
919{
Bill Buzbeea114add2012-05-03 15:00:40 -0700920 const u2* table = tabRec->table;
921 int baseVaddr = tabRec->vaddr;
922 int entries = table[1];
923 int* keys = (int*)&table[2];
924 int* targets = &keys[entries];
925 for (int i = 0; i < entries; i++) {
926 tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
927 keys[i]);
928 }
buzbee31a4a6f2012-02-28 15:36:15 -0800929}
930
931void oatProcessSwitchTables(CompilationUnit* cUnit)
932{
Bill Buzbeea114add2012-05-03 15:00:40 -0700933 GrowableListIterator iterator;
934 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
935 while (true) {
936 SwitchTable *tabRec =
937 (SwitchTable *) oatGrowableListIteratorNext(&iterator);
938 if (tabRec == NULL) break;
939 if (tabRec->table[0] == Instruction::kPackedSwitchSignature) {
940 markPackedCaseLabels(cUnit, tabRec);
941 } else if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
942 markSparseCaseLabels(cUnit, tabRec);
943 } else {
944 LOG(FATAL) << "Invalid switch table";
buzbee31a4a6f2012-02-28 15:36:15 -0800945 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700946 }
buzbee31a4a6f2012-02-28 15:36:15 -0800947}
948
949//FIXME: Do we have endian issues here?
950
951void dumpSparseSwitchTable(const u2* table)
Bill Buzbeea114add2012-05-03 15:00:40 -0700952 /*
953 * Sparse switch data format:
954 * ushort ident = 0x0200 magic value
955 * ushort size number of entries in the table; > 0
956 * int keys[size] keys, sorted low-to-high; 32-bit aligned
957 * int targets[size] branch targets, relative to switch opcode
958 *
959 * Total size is (2+size*4) 16-bit code units.
960 */
buzbee31a4a6f2012-02-28 15:36:15 -0800961{
Bill Buzbeea114add2012-05-03 15:00:40 -0700962 u2 ident = table[0];
963 int entries = table[1];
964 int* keys = (int*)&table[2];
965 int* targets = &keys[entries];
966 LOG(INFO) << "Sparse switch table - ident:0x" << std::hex << ident
967 << ", entries: " << std::dec << entries;
968 for (int i = 0; i < entries; i++) {
969 LOG(INFO) << " Key[" << keys[i] << "] -> 0x" << std::hex << targets[i];
970 }
buzbee31a4a6f2012-02-28 15:36:15 -0800971}
972
973void dumpPackedSwitchTable(const u2* table)
Bill Buzbeea114add2012-05-03 15:00:40 -0700974 /*
975 * Packed switch data format:
976 * ushort ident = 0x0100 magic value
977 * ushort size number of entries in the table
978 * int first_key first (and lowest) switch case value
979 * int targets[size] branch targets, relative to switch opcode
980 *
981 * Total size is (4+size*2) 16-bit code units.
982 */
buzbee31a4a6f2012-02-28 15:36:15 -0800983{
Bill Buzbeea114add2012-05-03 15:00:40 -0700984 u2 ident = table[0];
985 int* targets = (int*)&table[4];
986 int entries = table[1];
987 int lowKey = s4FromSwitchData(&table[2]);
988 LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident
989 << ", entries: " << std::dec << entries << ", lowKey: " << lowKey;
990 for (int i = 0; i < entries; i++) {
991 LOG(INFO) << " Key[" << (i + lowKey) << "] -> 0x" << std::hex
992 << targets[i];
993 }
buzbee31a4a6f2012-02-28 15:36:15 -0800994}
buzbeee3acd072012-02-25 17:03:10 -0800995
buzbeed1643e42012-09-05 14:06:51 -0700996/*
997 * Set up special LIR to mark a Dalvik byte-code instruction start and
998 * record it in the boundaryMap. NOTE: in cases such as kMirOpCheck in
999 * which we split a single Dalvik instruction, only the first MIR op
1000 * associated with a Dalvik PC should be entered into the map.
1001 */
1002LIR* markBoundary(CompilationUnit* cUnit, int offset, const char* instStr)
1003{
1004 LIR* res = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary, (intptr_t) instStr);
1005 if (cUnit->boundaryMap.find(offset) == cUnit->boundaryMap.end()) {
1006 cUnit->boundaryMap.Put(offset, res);
1007 }
1008 return res;
1009}
buzbeee3acd072012-02-25 17:03:10 -08001010
buzbeed1643e42012-09-05 14:06:51 -07001011}
1012 // namespace art