blob: 7ad2647f18b5affec6f27b33c63f84e5949aed87 [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
Ian Rogers0c7abda2012-09-19 13:33:42 -070017#include "gc_map.h"
18#include "verifier/dex_gc_map.h"
19#include "verifier/method_verifier.h"
20
buzbeee3acd072012-02-25 17:03:10 -080021namespace art {
22
buzbee31a4a6f2012-02-28 15:36:15 -080023void setMemRefType(LIR* lir, bool isLoad, int memType)
24{
Bill Buzbeea114add2012-05-03 15:00:40 -070025 u8 *maskPtr;
26 u8 mask = ENCODE_MEM;;
27 DCHECK(EncodingMap[lir->opcode].flags & (IS_LOAD | IS_STORE));
28 if (isLoad) {
29 maskPtr = &lir->useMask;
30 } else {
31 maskPtr = &lir->defMask;
32 }
33 /* Clear out the memref flags */
34 *maskPtr &= ~mask;
35 /* ..and then add back the one we need */
36 switch (memType) {
37 case kLiteral:
38 DCHECK(isLoad);
39 *maskPtr |= ENCODE_LITERAL;
40 break;
41 case kDalvikReg:
42 *maskPtr |= ENCODE_DALVIK_REG;
43 break;
44 case kHeapRef:
45 *maskPtr |= ENCODE_HEAP_REF;
46 break;
47 case kMustNotAlias:
48 /* Currently only loads can be marked as kMustNotAlias */
49 DCHECK(!(EncodingMap[lir->opcode].flags & IS_STORE));
50 *maskPtr |= ENCODE_MUST_NOT_ALIAS;
51 break;
52 default:
53 LOG(FATAL) << "Oat: invalid memref kind - " << memType;
54 }
buzbee31a4a6f2012-02-28 15:36:15 -080055}
56
57/*
Ian Rogersb5d09b22012-03-06 22:14:17 -080058 * Mark load/store instructions that access Dalvik registers through the stack.
buzbee31a4a6f2012-02-28 15:36:15 -080059 */
Ian Rogersb5d09b22012-03-06 22:14:17 -080060void annotateDalvikRegAccess(LIR* lir, int regId, bool isLoad, bool is64bit)
buzbee31a4a6f2012-02-28 15:36:15 -080061{
Bill Buzbeea114add2012-05-03 15:00:40 -070062 setMemRefType(lir, isLoad, kDalvikReg);
buzbee31a4a6f2012-02-28 15:36:15 -080063
Bill Buzbeea114add2012-05-03 15:00:40 -070064 /*
65 * Store the Dalvik register id in aliasInfo. Mark the MSB if it is a 64-bit
66 * access.
67 */
68 lir->aliasInfo = regId;
69 if (is64bit) {
70 lir->aliasInfo |= 0x80000000;
71 }
buzbee31a4a6f2012-02-28 15:36:15 -080072}
73
74/*
75 * Decode the register id.
76 */
buzbeeb046e162012-10-30 15:48:42 -070077inline u8 getRegMaskCommon(CompilationUnit* cUnit, int reg)
buzbee31a4a6f2012-02-28 15:36:15 -080078{
Bill Buzbeea114add2012-05-03 15:00:40 -070079 u8 seed;
80 int shift;
buzbeeb046e162012-10-30 15:48:42 -070081 int regId;
buzbee31a4a6f2012-02-28 15:36:15 -080082
buzbeeb046e162012-10-30 15:48:42 -070083
84 if (cUnit->instructionSet == kX86) {
85 regId = reg & 0xf;
86 /* Double registers in x86 are just a single FP register */
87 seed = 1;
88 } else {
89 regId = reg & 0x1f;
90 /* Each double register is equal to a pair of single-precision FP registers */
91 seed = DOUBLEREG(reg) ? 3 : 1;
92 }
Bill Buzbeea114add2012-05-03 15:00:40 -070093 /* FP register starts at bit position 16 */
94 shift = FPREG(reg) ? kFPReg0 : 0;
95 /* Expand the double register id into single offset */
96 shift += regId;
97 return (seed << shift);
buzbee31a4a6f2012-02-28 15:36:15 -080098}
99
buzbeeb046e162012-10-30 15:48:42 -0700100u8 oatGetRegMaskCommon(CompilationUnit* cUnit, int reg)
101{
102 return getRegMaskCommon(cUnit, reg);
103}
104
buzbee31a4a6f2012-02-28 15:36:15 -0800105/*
106 * Mark the corresponding bit(s).
107 */
buzbeeb046e162012-10-30 15:48:42 -0700108inline void setupRegMask(CompilationUnit* cUnit, u8* mask, int reg)
buzbee31a4a6f2012-02-28 15:36:15 -0800109{
buzbeeb046e162012-10-30 15:48:42 -0700110 *mask |= getRegMaskCommon(cUnit, reg);
111}
112
113/* Exported version of setupRegMask */
114void oatSetupRegMask(CompilationUnit* cUnit, u8* mask, int reg)
115{
116 setupRegMask(cUnit, mask, reg);
buzbee31a4a6f2012-02-28 15:36:15 -0800117}
118
119/*
120 * Set up the proper fields in the resource mask
121 */
buzbeeb046e162012-10-30 15:48:42 -0700122void setupResourceMasks(CompilationUnit* cUnit, LIR* lir)
buzbee31a4a6f2012-02-28 15:36:15 -0800123{
Bill Buzbeea114add2012-05-03 15:00:40 -0700124 int opcode = lir->opcode;
125 int flags;
buzbee31a4a6f2012-02-28 15:36:15 -0800126
Bill Buzbeea114add2012-05-03 15:00:40 -0700127 if (opcode <= 0) {
128 lir->useMask = lir->defMask = 0;
129 return;
130 }
buzbee31a4a6f2012-02-28 15:36:15 -0800131
buzbeeb046e162012-10-30 15:48:42 -0700132 flags = EncodingMap[opcode].flags;
buzbee31a4a6f2012-02-28 15:36:15 -0800133
Bill Buzbeea114add2012-05-03 15:00:40 -0700134 if (flags & NEEDS_FIXUP) {
135 lir->flags.pcRelFixup = true;
136 }
buzbee31a4a6f2012-02-28 15:36:15 -0800137
Bill Buzbeea114add2012-05-03 15:00:40 -0700138 /* Get the starting size of the instruction's template */
139 lir->flags.size = oatGetInsnSize(lir);
buzbeee88dfbf2012-03-05 11:19:57 -0800140
Bill Buzbeea114add2012-05-03 15:00:40 -0700141 /* Set up the mask for resources that are updated */
142 if (flags & (IS_LOAD | IS_STORE)) {
143 /* Default to heap - will catch specialized classes later */
144 setMemRefType(lir, flags & IS_LOAD, kHeapRef);
145 }
buzbee31a4a6f2012-02-28 15:36:15 -0800146
Bill Buzbeea114add2012-05-03 15:00:40 -0700147 /*
148 * Conservatively assume the branch here will call out a function that in
149 * turn will trash everything.
150 */
151 if (flags & IS_BRANCH) {
152 lir->defMask = lir->useMask = ENCODE_ALL;
153 return;
154 }
buzbee31a4a6f2012-02-28 15:36:15 -0800155
Bill Buzbeea114add2012-05-03 15:00:40 -0700156 if (flags & REG_DEF0) {
buzbeeb046e162012-10-30 15:48:42 -0700157 setupRegMask(cUnit, &lir->defMask, lir->operands[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700158 }
buzbee31a4a6f2012-02-28 15:36:15 -0800159
Bill Buzbeea114add2012-05-03 15:00:40 -0700160 if (flags & REG_DEF1) {
buzbeeb046e162012-10-30 15:48:42 -0700161 setupRegMask(cUnit, &lir->defMask, lir->operands[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700162 }
buzbee31a4a6f2012-02-28 15:36:15 -0800163
Bill Buzbeea114add2012-05-03 15:00:40 -0700164 if (flags & REG_DEF_SP) {
165 lir->defMask |= ENCODE_REG_SP;
166 }
buzbee31a4a6f2012-02-28 15:36:15 -0800167
buzbee31a4a6f2012-02-28 15:36:15 -0800168
Bill Buzbeea114add2012-05-03 15:00:40 -0700169 if (flags & SETS_CCODES) {
170 lir->defMask |= ENCODE_CCODE;
171 }
buzbee31a4a6f2012-02-28 15:36:15 -0800172
Bill Buzbeea114add2012-05-03 15:00:40 -0700173 if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) {
174 int i;
buzbee31a4a6f2012-02-28 15:36:15 -0800175
Bill Buzbeea114add2012-05-03 15:00:40 -0700176 for (i = 0; i < 4; i++) {
177 if (flags & (1 << (kRegUse0 + i))) {
buzbeeb046e162012-10-30 15:48:42 -0700178 setupRegMask(cUnit, &lir->useMask, lir->operands[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700179 }
buzbee31a4a6f2012-02-28 15:36:15 -0800180 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700181 }
buzbee31a4a6f2012-02-28 15:36:15 -0800182
Bill Buzbeea114add2012-05-03 15:00:40 -0700183 if (flags & REG_USE_SP) {
184 lir->useMask |= ENCODE_REG_SP;
185 }
buzbee31a4a6f2012-02-28 15:36:15 -0800186
Bill Buzbeea114add2012-05-03 15:00:40 -0700187 if (flags & USES_CCODES) {
188 lir->useMask |= ENCODE_CCODE;
189 }
buzbee31a4a6f2012-02-28 15:36:15 -0800190
buzbeeb046e162012-10-30 15:48:42 -0700191 // Handle target-specific actions
192 setupTargetResourceMasks(cUnit, lir);
buzbee31a4a6f2012-02-28 15:36:15 -0800193}
194
195/*
buzbee5de34942012-03-01 14:51:57 -0800196 * Debugging macros
197 */
198#define DUMP_RESOURCE_MASK(X)
199#define DUMP_SSA_REP(X)
200
201/* Pretty-print a LIR instruction */
202void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr)
203{
Bill Buzbeea114add2012-05-03 15:00:40 -0700204 LIR* lir = (LIR*) arg;
205 int offset = lir->offset;
206 int dest = lir->operands[0];
207 const bool dumpNop = (cUnit->enableDebug & (1 << kDebugShowNops));
buzbee5de34942012-03-01 14:51:57 -0800208
Bill Buzbeea114add2012-05-03 15:00:40 -0700209 /* Handle pseudo-ops individually, and all regular insns as a group */
210 switch (lir->opcode) {
211 case kPseudoMethodEntry:
212 LOG(INFO) << "-------- method entry "
213 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
214 break;
215 case kPseudoMethodExit:
216 LOG(INFO) << "-------- Method_Exit";
217 break;
218 case kPseudoBarrier:
219 LOG(INFO) << "-------- BARRIER";
220 break;
221 case kPseudoExtended:
222 LOG(INFO) << "-------- " << (char* ) dest;
223 break;
224 case kPseudoSSARep:
225 DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " << (char* ) dest);
226 break;
227 case kPseudoEntryBlock:
228 LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
229 break;
230 case kPseudoDalvikByteCodeBoundary:
231 LOG(INFO) << "-------- dalvik offset: 0x" << std::hex
232 << lir->dalvikOffset << " @ " << (char* )lir->operands[0];
233 break;
234 case kPseudoExitBlock:
235 LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
236 break;
237 case kPseudoPseudoAlign4:
238 LOG(INFO) << (intptr_t)baseAddr + offset << " (0x" << std::hex
239 << offset << "): .align4";
240 break;
241 case kPseudoEHBlockLabel:
242 LOG(INFO) << "Exception_Handling:";
243 break;
244 case kPseudoTargetLabel:
245 case kPseudoNormalBlockLabel:
246 LOG(INFO) << "L" << (void*)lir << ":";
247 break;
248 case kPseudoThrowTarget:
249 LOG(INFO) << "LT" << (void*)lir << ":";
250 break;
251 case kPseudoIntrinsicRetry:
252 LOG(INFO) << "IR" << (void*)lir << ":";
253 break;
254 case kPseudoSuspendTarget:
255 LOG(INFO) << "LS" << (void*)lir << ":";
256 break;
buzbee8320f382012-09-11 16:29:42 -0700257 case kPseudoSafepointPC:
258 LOG(INFO) << "LsafepointPC_0x" << std::hex << lir->offset << "_" << lir->dalvikOffset << ":";
259 break;
Bill Buzbeea5b30242012-09-28 07:19:44 -0700260 case kPseudoExportedPC:
261 LOG(INFO) << "LexportedPC_0x" << std::hex << lir->offset << "_" << lir->dalvikOffset << ":";
262 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700263 case kPseudoCaseLabel:
264 LOG(INFO) << "LC" << (void*)lir << ": Case target 0x"
265 << std::hex << lir->operands[0] << "|" << std::dec <<
266 lir->operands[0];
267 break;
268 default:
269 if (lir->flags.isNop && !dumpNop) {
270 break;
271 } else {
272 std::string op_name(buildInsnString(EncodingMap[lir->opcode].name,
273 lir, baseAddr));
274 std::string op_operands(buildInsnString(EncodingMap[lir->opcode].fmt
275 , lir, baseAddr));
276 LOG(INFO) << StringPrintf("%05x: %-9s%s%s",
277 (unsigned int)(baseAddr + offset),
278 op_name.c_str(), op_operands.c_str(),
279 lir->flags.isNop ? "(nop)" : "");
280 }
281 break;
282 }
buzbee5de34942012-03-01 14:51:57 -0800283
Bill Buzbeea114add2012-05-03 15:00:40 -0700284 if (lir->useMask && (!lir->flags.isNop || dumpNop)) {
285 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->useMask, "use"));
286 }
287 if (lir->defMask && (!lir->flags.isNop || dumpNop)) {
288 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->defMask, "def"));
289 }
buzbee5de34942012-03-01 14:51:57 -0800290}
291
292void oatDumpPromotionMap(CompilationUnit *cUnit)
293{
Bill Buzbeea114add2012-05-03 15:00:40 -0700294 int numRegs = cUnit->numDalvikRegisters + cUnit->numCompilerTemps + 1;
295 for (int i = 0; i < numRegs; i++) {
296 PromotionMap vRegMap = cUnit->promotionMap[i];
297 std::string buf;
298 if (vRegMap.fpLocation == kLocPhysReg) {
299 StringAppendF(&buf, " : s%d", vRegMap.fpReg & FP_REG_MASK);
buzbee5de34942012-03-01 14:51:57 -0800300 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700301
302 std::string buf3;
303 if (i < cUnit->numDalvikRegisters) {
304 StringAppendF(&buf3, "%02d", i);
305 } else if (i == cUnit->methodSReg) {
306 buf3 = "Method*";
307 } else {
308 StringAppendF(&buf3, "ct%d", i - cUnit->numDalvikRegisters);
309 }
310
311 LOG(INFO) << StringPrintf("V[%s] -> %s%d%s", buf3.c_str(),
312 vRegMap.coreLocation == kLocPhysReg ?
313 "r" : "SP+", vRegMap.coreLocation == kLocPhysReg ?
314 vRegMap.coreReg : oatSRegOffset(cUnit, i),
315 buf.c_str());
316 }
buzbee5de34942012-03-01 14:51:57 -0800317}
318
Bill Buzbeea5b30242012-09-28 07:19:44 -0700319/* Dump a mapping table */
320void dumpMappingTable(const char* table_name, const std::string& descriptor,
321 const std::string& name, const std::string& signature,
322 const std::vector<uint32_t>& v) {
323 if (v.size() > 0) {
324 std::string line(StringPrintf("\n %s %s%s_%s_table[%zu] = {", table_name,
325 descriptor.c_str(), name.c_str(), signature.c_str(), v.size()));
326 std::replace(line.begin(), line.end(), ';', '_');
327 LOG(INFO) << line;
328 for (uint32_t i = 0; i < v.size(); i+=2) {
329 line = StringPrintf(" {0x%05x, 0x%04x},", v[i], v[i+1]);
330 LOG(INFO) << line;
331 }
332 LOG(INFO) <<" };\n\n";
333 }
334}
335
buzbee5de34942012-03-01 14:51:57 -0800336/* Dump instructions and constant pool contents */
337void oatCodegenDump(CompilationUnit* cUnit)
338{
Bill Buzbeea114add2012-05-03 15:00:40 -0700339 LOG(INFO) << "Dumping LIR insns for "
340 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
341 LIR* lirInsn;
342 LIR* thisLIR;
343 int insnsSize = cUnit->insnsSize;
buzbee5de34942012-03-01 14:51:57 -0800344
Bill Buzbeea114add2012-05-03 15:00:40 -0700345 LOG(INFO) << "Regs (excluding ins) : " << cUnit->numRegs;
346 LOG(INFO) << "Ins : " << cUnit->numIns;
347 LOG(INFO) << "Outs : " << cUnit->numOuts;
348 LOG(INFO) << "CoreSpills : " << cUnit->numCoreSpills;
349 LOG(INFO) << "FPSpills : " << cUnit->numFPSpills;
350 LOG(INFO) << "CompilerTemps : " << cUnit->numCompilerTemps;
351 LOG(INFO) << "Frame size : " << cUnit->frameSize;
352 LOG(INFO) << "code size is " << cUnit->totalSize <<
353 " bytes, Dalvik size is " << insnsSize * 2;
354 LOG(INFO) << "expansion factor: "
355 << (float)cUnit->totalSize / (float)(insnsSize * 2);
356 oatDumpPromotionMap(cUnit);
357 for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
358 oatDumpLIRInsn(cUnit, lirInsn, 0);
359 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700360 for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
361 thisLIR = (LIR*) lirInsn;
362 LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)",
363 thisLIR->offset, thisLIR->offset,
364 thisLIR->operands[0]);
365 }
buzbee5de34942012-03-01 14:51:57 -0800366
Bill Buzbeea114add2012-05-03 15:00:40 -0700367 const DexFile::MethodId& method_id =
368 cUnit->dex_file->GetMethodId(cUnit->method_idx);
369 std::string signature(cUnit->dex_file->GetMethodSignature(method_id));
370 std::string name(cUnit->dex_file->GetMethodName(method_id));
371 std::string descriptor(cUnit->dex_file->GetMethodDeclaringClassDescriptor(method_id));
buzbee5de34942012-03-01 14:51:57 -0800372
Bill Buzbeea5b30242012-09-28 07:19:44 -0700373 // Dump mapping tables
374 dumpMappingTable("PC2Dex_MappingTable", descriptor, name, signature, cUnit->pc2dexMappingTable);
375 dumpMappingTable("Dex2PC_MappingTable", descriptor, name, signature, cUnit->dex2pcMappingTable);
buzbee5de34942012-03-01 14:51:57 -0800376}
377
buzbeea2ebdd72012-03-04 14:57:06 -0800378
379LIR* rawLIR(CompilationUnit* cUnit, int dalvikOffset, int opcode, int op0,
Bill Buzbeea114add2012-05-03 15:00:40 -0700380 int op1, int op2, int op3, int op4, LIR* target)
buzbeea2ebdd72012-03-04 14:57:06 -0800381{
Bill Buzbeea114add2012-05-03 15:00:40 -0700382 LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
383 insn->dalvikOffset = dalvikOffset;
384 insn->opcode = opcode;
385 insn->operands[0] = op0;
386 insn->operands[1] = op1;
387 insn->operands[2] = op2;
388 insn->operands[3] = op3;
389 insn->operands[4] = op4;
390 insn->target = target;
buzbeeb046e162012-10-30 15:48:42 -0700391 oatSetupResourceMasks(cUnit, insn);
Bill Buzbeea5b30242012-09-28 07:19:44 -0700392 if ((opcode == kPseudoTargetLabel) || (opcode == kPseudoSafepointPC) ||
393 (opcode == kPseudoExportedPC)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700394 // Always make labels scheduling barriers
buzbee8320f382012-09-11 16:29:42 -0700395 insn->useMask = insn->defMask = ENCODE_ALL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700396 }
397 return insn;
buzbeea2ebdd72012-03-04 14:57:06 -0800398}
399
buzbee5de34942012-03-01 14:51:57 -0800400/*
buzbee31a4a6f2012-02-28 15:36:15 -0800401 * The following are building blocks to construct low-level IRs with 0 - 4
402 * operands.
403 */
buzbee5de34942012-03-01 14:51:57 -0800404LIR* newLIR0(CompilationUnit* cUnit, int opcode)
buzbee31a4a6f2012-02-28 15:36:15 -0800405{
Bill Buzbeea114add2012-05-03 15:00:40 -0700406 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND))
407 << EncodingMap[opcode].name << " " << (int)opcode << " "
408 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
409 << cUnit->currentDalvikOffset;
410 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode);
411 oatAppendLIR(cUnit, (LIR*) insn);
412 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800413}
414
buzbee5de34942012-03-01 14:51:57 -0800415LIR* newLIR1(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700416 int dest)
buzbee31a4a6f2012-02-28 15:36:15 -0800417{
Bill Buzbeea114add2012-05-03 15:00:40 -0700418 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_UNARY_OP))
419 << EncodingMap[opcode].name << " " << (int)opcode << " "
420 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
421 << cUnit->currentDalvikOffset;
422 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest);
423 oatAppendLIR(cUnit, (LIR*) insn);
424 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800425}
426
buzbee5de34942012-03-01 14:51:57 -0800427LIR* newLIR2(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700428 int dest, int src1)
buzbee31a4a6f2012-02-28 15:36:15 -0800429{
Bill Buzbeea114add2012-05-03 15:00:40 -0700430 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_BINARY_OP))
431 << EncodingMap[opcode].name << " " << (int)opcode << " "
432 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
433 << cUnit->currentDalvikOffset;
434 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1);
435 oatAppendLIR(cUnit, (LIR*) insn);
436 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800437}
438
buzbee5de34942012-03-01 14:51:57 -0800439LIR* newLIR3(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700440 int dest, int src1, int src2)
buzbee31a4a6f2012-02-28 15:36:15 -0800441{
Bill Buzbeea114add2012-05-03 15:00:40 -0700442 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_TERTIARY_OP))
443 << EncodingMap[opcode].name << " " << (int)opcode << " "
444 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
445 << cUnit->currentDalvikOffset;
446 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
447 src2);
448 oatAppendLIR(cUnit, (LIR*) insn);
449 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800450}
451
buzbee5de34942012-03-01 14:51:57 -0800452LIR* newLIR4(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700453 int dest, int src1, int src2, int info)
buzbee31a4a6f2012-02-28 15:36:15 -0800454{
Bill Buzbeea114add2012-05-03 15:00:40 -0700455 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUAD_OP))
456 << EncodingMap[opcode].name << " " << (int)opcode << " "
457 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
458 << cUnit->currentDalvikOffset;
459 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
460 src2, info);
461 oatAppendLIR(cUnit, (LIR*) insn);
462 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800463}
buzbee31a4a6f2012-02-28 15:36:15 -0800464
Ian Rogersb5d09b22012-03-06 22:14:17 -0800465LIR* newLIR5(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700466 int dest, int src1, int src2, int info1, int info2)
Ian Rogersb5d09b22012-03-06 22:14:17 -0800467{
Bill Buzbeea114add2012-05-03 15:00:40 -0700468 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUIN_OP))
469 << EncodingMap[opcode].name << " " << (int)opcode << " "
470 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
471 << cUnit->currentDalvikOffset;
472 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
473 src2, info1, info2);
474 oatAppendLIR(cUnit, (LIR*) insn);
475 return insn;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800476}
477
buzbee31a4a6f2012-02-28 15:36:15 -0800478/*
479 * Search the existing constants in the literal pool for an exact or close match
480 * within specified delta (greater or equal to 0).
481 */
482LIR* scanLiteralPool(LIR* dataTarget, int value, unsigned int delta)
483{
Bill Buzbeea114add2012-05-03 15:00:40 -0700484 while (dataTarget) {
485 if (((unsigned) (value - ((LIR* ) dataTarget)->operands[0])) <= delta)
486 return (LIR* ) dataTarget;
487 dataTarget = dataTarget->next;
488 }
489 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800490}
491
492/* Search the existing constants in the literal pool for an exact wide match */
493LIR* scanLiteralPoolWide(LIR* dataTarget, int valLo, int valHi)
494{
Bill Buzbeea114add2012-05-03 15:00:40 -0700495 bool loMatch = false;
496 LIR* loTarget = NULL;
497 while (dataTarget) {
498 if (loMatch && (((LIR*)dataTarget)->operands[0] == valHi)) {
499 return (LIR*)loTarget;
buzbee31a4a6f2012-02-28 15:36:15 -0800500 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700501 loMatch = false;
502 if (((LIR*)dataTarget)->operands[0] == valLo) {
503 loMatch = true;
504 loTarget = dataTarget;
505 }
506 dataTarget = dataTarget->next;
507 }
508 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800509}
510
511/*
512 * The following are building blocks to insert constants into the pool or
513 * instruction streams.
514 */
515
buzbee5de34942012-03-01 14:51:57 -0800516/* Add a 32-bit constant either in the constant pool */
Ian Rogers3fa13792012-03-18 15:53:45 -0700517LIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP, int value)
buzbee31a4a6f2012-02-28 15:36:15 -0800518{
Bill Buzbeea114add2012-05-03 15:00:40 -0700519 /* Add the constant to the literal pool */
520 if (constantListP) {
521 LIR* newValue = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocData);
522 newValue->operands[0] = value;
523 newValue->next = *constantListP;
524 *constantListP = (LIR*) newValue;
525 return newValue;
526 }
527 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800528}
529
530/* Add a 64-bit constant to the constant pool or mixed with code */
531LIR* addWideData(CompilationUnit* cUnit, LIR* *constantListP,
Bill Buzbeea114add2012-05-03 15:00:40 -0700532 int valLo, int valHi)
buzbee31a4a6f2012-02-28 15:36:15 -0800533{
Bill Buzbeea114add2012-05-03 15:00:40 -0700534 //FIXME: hard-coded little endian, need BE variant
535 // Insert high word into list first
536 addWordData(cUnit, constantListP, valHi);
537 return addWordData(cUnit, constantListP, valLo);
buzbee31a4a6f2012-02-28 15:36:15 -0800538}
539
Ian Rogersab058bb2012-03-11 22:19:38 -0700540void pushWord(std::vector<uint8_t>&buf, int data) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700541 buf.push_back( data & 0xff);
542 buf.push_back( (data >> 8) & 0xff);
543 buf.push_back( (data >> 16) & 0xff);
544 buf.push_back( (data >> 24) & 0xff);
buzbeee3acd072012-02-25 17:03:10 -0800545}
546
Ian Rogersab058bb2012-03-11 22:19:38 -0700547void alignBuffer(std::vector<uint8_t>&buf, size_t offset) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700548 while (buf.size() < offset) {
549 buf.push_back(0);
550 }
buzbeee3acd072012-02-25 17:03:10 -0800551}
552
Brian Carlstromf5822582012-03-19 22:34:31 -0700553bool IsDirect(int invokeType) {
554 InvokeType type = static_cast<InvokeType>(invokeType);
555 return type == kStatic || type == kDirect;
556}
557
buzbeee3acd072012-02-25 17:03:10 -0800558/* Write the literal pool to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800559void installLiteralPools(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800560{
Bill Buzbeea114add2012-05-03 15:00:40 -0700561 alignBuffer(cUnit->codeBuffer, cUnit->dataOffset);
562 LIR* dataLIR = cUnit->literalList;
563 while (dataLIR != NULL) {
564 pushWord(cUnit->codeBuffer, dataLIR->operands[0]);
565 dataLIR = NEXT_LIR(dataLIR);
566 }
567 // Push code and method literals, record offsets for the compiler to patch.
568 dataLIR = cUnit->codeLiteralList;
Ian Rogers137e88f2012-10-08 17:46:47 -0700569 while (dataLIR != NULL) {
570 uint32_t target = dataLIR->operands[0];
571 cUnit->compiler->AddCodePatch(cUnit->dex_file,
572 cUnit->method_idx,
573 cUnit->invoke_type,
574 target,
575 static_cast<InvokeType>(dataLIR->operands[1]),
576 cUnit->codeBuffer.size());
577 const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target);
578 // unique based on target to ensure code deduplication works
579 uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
580 pushWord(cUnit->codeBuffer, unique_patch_value);
581 dataLIR = NEXT_LIR(dataLIR);
582 }
583 dataLIR = cUnit->methodLiteralList;
584 while (dataLIR != NULL) {
585 uint32_t target = dataLIR->operands[0];
586 cUnit->compiler->AddMethodPatch(cUnit->dex_file,
Bill Buzbeea114add2012-05-03 15:00:40 -0700587 cUnit->method_idx,
Ian Rogers08f753d2012-08-24 14:35:25 -0700588 cUnit->invoke_type,
Bill Buzbeea114add2012-05-03 15:00:40 -0700589 target,
Ian Rogers08f753d2012-08-24 14:35:25 -0700590 static_cast<InvokeType>(dataLIR->operands[1]),
Bill Buzbeea114add2012-05-03 15:00:40 -0700591 cUnit->codeBuffer.size());
Ian Rogers137e88f2012-10-08 17:46:47 -0700592 const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target);
593 // unique based on target to ensure code deduplication works
594 uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
595 pushWord(cUnit->codeBuffer, unique_patch_value);
596 dataLIR = NEXT_LIR(dataLIR);
Bill Buzbeea114add2012-05-03 15:00:40 -0700597 }
buzbeee3acd072012-02-25 17:03:10 -0800598}
599
600/* Write the switch tables to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800601void installSwitchTables(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800602{
Bill Buzbeea114add2012-05-03 15:00:40 -0700603 GrowableListIterator iterator;
604 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
605 while (true) {
606 SwitchTable* tabRec = (SwitchTable *) oatGrowableListIteratorNext(
607 &iterator);
608 if (tabRec == NULL) break;
609 alignBuffer(cUnit->codeBuffer, tabRec->offset);
610 /*
611 * For Arm, our reference point is the address of the bx
612 * instruction that does the launch, so we have to subtract
613 * the auto pc-advance. For other targets the reference point
614 * is a label, so we can use the offset as-is.
615 */
buzbeeb046e162012-10-30 15:48:42 -0700616 int bxOffset = INVALID_OFFSET;
617 switch (cUnit->instructionSet) {
618 case kThumb2:
619 bxOffset = tabRec->anchor->offset + 4;
620 break;
621 case kX86:
622 bxOffset = 0;
623 break;
624 case kMips:
625 bxOffset = tabRec->anchor->offset;
626 break;
627 default: LOG(FATAL) << "Unexpected instruction set: " << cUnit->instructionSet;
628 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700629 if (cUnit->printMe) {
630 LOG(INFO) << "Switch table for offset 0x" << std::hex << bxOffset;
buzbeee3acd072012-02-25 17:03:10 -0800631 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700632 if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
633 int* keys = (int*)&(tabRec->table[2]);
634 for (int elems = 0; elems < tabRec->table[1]; elems++) {
635 int disp = tabRec->targets[elems]->offset - bxOffset;
636 if (cUnit->printMe) {
637 LOG(INFO) << " Case[" << elems << "] key: 0x"
638 << std::hex << keys[elems] << ", disp: 0x"
639 << std::hex << disp;
640 }
641 pushWord(cUnit->codeBuffer, keys[elems]);
642 pushWord(cUnit->codeBuffer,
643 tabRec->targets[elems]->offset - bxOffset);
644 }
645 } else {
646 DCHECK_EQ(static_cast<int>(tabRec->table[0]),
647 static_cast<int>(Instruction::kPackedSwitchSignature));
648 for (int elems = 0; elems < tabRec->table[1]; elems++) {
649 int disp = tabRec->targets[elems]->offset - bxOffset;
650 if (cUnit->printMe) {
651 LOG(INFO) << " Case[" << elems << "] disp: 0x"
652 << std::hex << disp;
653 }
654 pushWord(cUnit->codeBuffer, tabRec->targets[elems]->offset - bxOffset);
655 }
656 }
657 }
buzbeee3acd072012-02-25 17:03:10 -0800658}
659
660/* Write the fill array dta to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800661void installFillArrayData(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800662{
Bill Buzbeea114add2012-05-03 15:00:40 -0700663 GrowableListIterator iterator;
664 oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
665 while (true) {
666 FillArrayData *tabRec = (FillArrayData *) oatGrowableListIteratorNext(
667 &iterator);
668 if (tabRec == NULL) break;
669 alignBuffer(cUnit->codeBuffer, tabRec->offset);
670 for (int i = 0; i < (tabRec->size + 1) / 2; i++) {
671 cUnit->codeBuffer.push_back( tabRec->table[i] & 0xFF);
672 cUnit->codeBuffer.push_back( (tabRec->table[i] >> 8) & 0xFF);
buzbeee3acd072012-02-25 17:03:10 -0800673 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700674 }
buzbeee3acd072012-02-25 17:03:10 -0800675}
676
buzbee31a4a6f2012-02-28 15:36:15 -0800677int assignLiteralOffsetCommon(LIR* lir, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800678{
Bill Buzbeea114add2012-05-03 15:00:40 -0700679 for (;lir != NULL; lir = lir->next) {
680 lir->offset = offset;
681 offset += 4;
682 }
683 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800684}
685
buzbee6459e7c2012-10-02 14:42:41 -0700686// Make sure we have a code address for every declared catch entry
687bool verifyCatchEntries(CompilationUnit* cUnit)
688{
689 bool success = true;
690 for (std::set<uint32_t>::const_iterator it = cUnit->catches.begin(); it != cUnit->catches.end(); ++it) {
691 uint32_t dexPc = *it;
692 bool found = false;
693 for (size_t i = 0; i < cUnit->dex2pcMappingTable.size(); i += 2) {
694 if (dexPc == cUnit->dex2pcMappingTable[i+1]) {
695 found = true;
696 break;
697 }
698 }
699 if (!found) {
700 LOG(INFO) << "Missing native PC for catch entry @ 0x" << std::hex << dexPc;
701 success = false;
702 }
703 }
704 // Now, try in the other direction
705 for (size_t i = 0; i < cUnit->dex2pcMappingTable.size(); i += 2) {
706 uint32_t dexPc = cUnit->dex2pcMappingTable[i+1];
707 if (cUnit->catches.find(dexPc) == cUnit->catches.end()) {
708 LOG(INFO) << "Unexpected catch entry @ dex pc 0x" << std::hex << dexPc;
709 success = false;
710 }
711 }
712 if (!success) {
713 LOG(INFO) << "Bad dex2pcMapping table in " << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
714 LOG(INFO) << "Entries @ decode: " << cUnit->catches.size() << ", Entries in table: "
715 << cUnit->dex2pcMappingTable.size()/2;
716 }
717 return success;
718}
719
Bill Buzbeea5b30242012-09-28 07:19:44 -0700720void createMappingTables(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800721{
buzbee8320f382012-09-11 16:29:42 -0700722 for (LIR* tgtLIR = (LIR *) cUnit->firstLIRInsn; tgtLIR != NULL; tgtLIR = NEXT_LIR(tgtLIR)) {
723 if (!tgtLIR->flags.isNop && (tgtLIR->opcode == kPseudoSafepointPC)) {
Bill Buzbeea5b30242012-09-28 07:19:44 -0700724 cUnit->pc2dexMappingTable.push_back(tgtLIR->offset);
725 cUnit->pc2dexMappingTable.push_back(tgtLIR->dalvikOffset);
726 }
727 if (!tgtLIR->flags.isNop && (tgtLIR->opcode == kPseudoExportedPC)) {
728 cUnit->dex2pcMappingTable.push_back(tgtLIR->offset);
729 cUnit->dex2pcMappingTable.push_back(tgtLIR->dalvikOffset);
buzbeee3acd072012-02-25 17:03:10 -0800730 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700731 }
buzbee6459e7c2012-10-02 14:42:41 -0700732 DCHECK(verifyCatchEntries(cUnit));
Bill Buzbeea5b30242012-09-28 07:19:44 -0700733 cUnit->combinedMappingTable.push_back(cUnit->pc2dexMappingTable.size() +
734 cUnit->dex2pcMappingTable.size());
735 cUnit->combinedMappingTable.push_back(cUnit->pc2dexMappingTable.size());
736 cUnit->combinedMappingTable.insert(cUnit->combinedMappingTable.end(),
737 cUnit->pc2dexMappingTable.begin(),
738 cUnit->pc2dexMappingTable.end());
739 cUnit->combinedMappingTable.insert(cUnit->combinedMappingTable.end(),
740 cUnit->dex2pcMappingTable.begin(),
741 cUnit->dex2pcMappingTable.end());
buzbeee3acd072012-02-25 17:03:10 -0800742}
743
Ian Rogers0c7abda2012-09-19 13:33:42 -0700744class NativePcToReferenceMapBuilder {
745 public:
746 NativePcToReferenceMapBuilder(std::vector<uint8_t>* table,
747 size_t entries, uint32_t max_native_offset,
748 size_t references_width) : entries_(entries),
749 references_width_(references_width), in_use_(entries),
750 table_(table) {
751 // Compute width in bytes needed to hold max_native_offset.
752 native_offset_width_ = 0;
753 while (max_native_offset != 0) {
754 native_offset_width_++;
755 max_native_offset >>= 8;
756 }
757 // Resize table and set up header.
758 table->resize((EntryWidth() * entries) + sizeof(uint32_t));
Ian Rogers000d7242012-09-21 16:07:36 -0700759 CHECK_LT(native_offset_width_, 1U << 3);
760 (*table)[0] = native_offset_width_ & 7;
761 CHECK_LT(references_width_, 1U << 13);
762 (*table)[0] |= (references_width_ << 3) & 0xFF;
763 (*table)[1] = (references_width_ >> 5) & 0xFF;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700764 CHECK_LT(entries, 1U << 16);
765 (*table)[2] = entries & 0xFF;
766 (*table)[3] = (entries >> 8) & 0xFF;
767 }
768
769 void AddEntry(uint32_t native_offset, const uint8_t* references) {
770 size_t table_index = TableIndex(native_offset);
771 while (in_use_[table_index]) {
772 table_index = (table_index + 1) % entries_;
773 }
774 in_use_[table_index] = true;
775 SetNativeOffset(table_index, native_offset);
776 DCHECK_EQ(native_offset, GetNativeOffset(table_index));
777 SetReferences(table_index, references);
778 }
779
780 private:
781 size_t TableIndex(uint32_t native_offset) {
782 return NativePcOffsetToReferenceMap::Hash(native_offset) % entries_;
783 }
784
785 uint32_t GetNativeOffset(size_t table_index) {
786 uint32_t native_offset = 0;
787 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
788 for (size_t i = 0; i < native_offset_width_; i++) {
789 native_offset |= (*table_)[table_offset + i] << (i * 8);
790 }
791 return native_offset;
792 }
793
794 void SetNativeOffset(size_t table_index, uint32_t native_offset) {
795 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
796 for (size_t i = 0; i < native_offset_width_; i++) {
797 (*table_)[table_offset + i] = (native_offset >> (i * 8)) & 0xFF;
798 }
799 }
800
801 void SetReferences(size_t table_index, const uint8_t* references) {
802 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
803 memcpy(&(*table_)[table_offset + native_offset_width_], references, references_width_);
804 }
805
806 size_t EntryWidth() const {
807 return native_offset_width_ + references_width_;
808 }
809
810 // Number of entries in the table.
811 const size_t entries_;
812 // Number of bytes used to encode the reference bitmap.
813 const size_t references_width_;
814 // Number of bytes used to encode a native offset.
815 size_t native_offset_width_;
816 // Entries that are in use.
817 std::vector<bool> in_use_;
818 // The table we're building.
819 std::vector<uint8_t>* const table_;
820};
821
822static void createNativeGcMap(CompilationUnit* cUnit) {
Bill Buzbeea5b30242012-09-28 07:19:44 -0700823 const std::vector<uint32_t>& mapping_table = cUnit->pc2dexMappingTable;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700824 uint32_t max_native_offset = 0;
825 for (size_t i = 0; i < mapping_table.size(); i += 2) {
826 uint32_t native_offset = mapping_table[i + 0];
827 if (native_offset > max_native_offset) {
828 max_native_offset = native_offset;
829 }
830 }
831 Compiler::MethodReference method_ref(cUnit->dex_file, cUnit->method_idx);
832 const std::vector<uint8_t>* gc_map_raw = verifier::MethodVerifier::GetDexGcMap(method_ref);
833 verifier::DexPcToReferenceMap dex_gc_map(&(*gc_map_raw)[4], gc_map_raw->size() - 4);
834 // Compute native offset to references size.
835 NativePcToReferenceMapBuilder native_gc_map_builder(&cUnit->nativeGcMap,
836 mapping_table.size() / 2, max_native_offset,
837 dex_gc_map.RegWidth());
838
839 for (size_t i = 0; i < mapping_table.size(); i += 2) {
840 uint32_t native_offset = mapping_table[i + 0];
841 uint32_t dex_pc = mapping_table[i + 1];
842 const uint8_t* references = dex_gc_map.FindBitMap(dex_pc, false);
Bill Buzbeea5b30242012-09-28 07:19:44 -0700843 CHECK(references != NULL) << "Missing ref for dex pc 0x" << std::hex << dex_pc;
844 native_gc_map_builder.AddEntry(native_offset, references);
Ian Rogers0c7abda2012-09-19 13:33:42 -0700845 }
846}
847
buzbeee3acd072012-02-25 17:03:10 -0800848/* Determine the offset of each literal field */
buzbee31a4a6f2012-02-28 15:36:15 -0800849int assignLiteralOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800850{
Bill Buzbeea114add2012-05-03 15:00:40 -0700851 offset = assignLiteralOffsetCommon(cUnit->literalList, offset);
852 offset = assignLiteralOffsetCommon(cUnit->codeLiteralList, offset);
853 offset = assignLiteralOffsetCommon(cUnit->methodLiteralList, offset);
854 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800855}
856
buzbee31a4a6f2012-02-28 15:36:15 -0800857int assignSwitchTablesOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800858{
Bill Buzbeea114add2012-05-03 15:00:40 -0700859 GrowableListIterator iterator;
860 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
861 while (true) {
862 SwitchTable *tabRec = (SwitchTable *) oatGrowableListIteratorNext(
863 &iterator);
864 if (tabRec == NULL) break;
865 tabRec->offset = offset;
866 if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
867 offset += tabRec->table[1] * (sizeof(int) * 2);
868 } else {
869 DCHECK_EQ(static_cast<int>(tabRec->table[0]),
870 static_cast<int>(Instruction::kPackedSwitchSignature));
871 offset += tabRec->table[1] * sizeof(int);
buzbeee3acd072012-02-25 17:03:10 -0800872 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700873 }
874 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800875}
876
buzbee31a4a6f2012-02-28 15:36:15 -0800877int assignFillArrayDataOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800878{
Bill Buzbeea114add2012-05-03 15:00:40 -0700879 GrowableListIterator iterator;
880 oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
881 while (true) {
882 FillArrayData *tabRec = (FillArrayData *) oatGrowableListIteratorNext(
883 &iterator);
884 if (tabRec == NULL) break;
885 tabRec->offset = offset;
886 offset += tabRec->size;
887 // word align
888 offset = (offset + 3) & ~3;
889 }
890 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800891}
892
893/*
894 * Walk the compilation unit and assign offsets to instructions
895 * and literals and compute the total size of the compiled unit.
896 */
897void oatAssignOffsets(CompilationUnit* cUnit)
898{
Bill Buzbeea114add2012-05-03 15:00:40 -0700899 int offset = oatAssignInsnOffsets(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800900
Bill Buzbeea114add2012-05-03 15:00:40 -0700901 /* Const values have to be word aligned */
902 offset = (offset + 3) & ~3;
buzbeee3acd072012-02-25 17:03:10 -0800903
Bill Buzbeea114add2012-05-03 15:00:40 -0700904 /* Set up offsets for literals */
905 cUnit->dataOffset = offset;
buzbeee3acd072012-02-25 17:03:10 -0800906
Bill Buzbeea114add2012-05-03 15:00:40 -0700907 offset = assignLiteralOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800908
Bill Buzbeea114add2012-05-03 15:00:40 -0700909 offset = assignSwitchTablesOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800910
Bill Buzbeea114add2012-05-03 15:00:40 -0700911 offset = assignFillArrayDataOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800912
Bill Buzbeea114add2012-05-03 15:00:40 -0700913 cUnit->totalSize = offset;
buzbeee3acd072012-02-25 17:03:10 -0800914}
915
916/*
917 * Go over each instruction in the list and calculate the offset from the top
918 * before sending them off to the assembler. If out-of-range branch distance is
919 * seen rearrange the instructions a bit to correct it.
920 */
921void oatAssembleLIR(CompilationUnit* cUnit)
922{
Bill Buzbeea114add2012-05-03 15:00:40 -0700923 oatAssignOffsets(cUnit);
924 /*
925 * Assemble here. Note that we generate code with optimistic assumptions
926 * and if found now to work, we'll have to redo the sequence and retry.
927 */
buzbeee3acd072012-02-25 17:03:10 -0800928
Bill Buzbeea114add2012-05-03 15:00:40 -0700929 while (true) {
930 AssemblerStatus res = oatAssembleInstructions(cUnit, 0);
931 if (res == kSuccess) {
932 break;
933 } else {
934 cUnit->assemblerRetries++;
935 if (cUnit->assemblerRetries > MAX_ASSEMBLER_RETRIES) {
936 oatCodegenDump(cUnit);
937 LOG(FATAL) << "Assembler error - too many retries";
938 }
939 // Redo offsets and try again
940 oatAssignOffsets(cUnit);
941 cUnit->codeBuffer.clear();
buzbeee3acd072012-02-25 17:03:10 -0800942 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700943 }
buzbeee3acd072012-02-25 17:03:10 -0800944
Bill Buzbeea114add2012-05-03 15:00:40 -0700945 // Install literals
946 installLiteralPools(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800947
Bill Buzbeea114add2012-05-03 15:00:40 -0700948 // Install switch tables
949 installSwitchTables(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800950
Bill Buzbeea114add2012-05-03 15:00:40 -0700951 // Install fill array data
952 installFillArrayData(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800953
Ian Rogers0c7abda2012-09-19 13:33:42 -0700954 // Create the mapping table and native offset to reference map.
Bill Buzbeea5b30242012-09-28 07:19:44 -0700955 createMappingTables(cUnit);
Ian Rogers0c7abda2012-09-19 13:33:42 -0700956
957 createNativeGcMap(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800958}
959
buzbee31a4a6f2012-02-28 15:36:15 -0800960/*
961 * Insert a kPseudoCaseLabel at the beginning of the Dalvik
962 * offset vaddr. This label will be used to fix up the case
963 * branch table during the assembly phase. Be sure to set
964 * all resource flags on this to prevent code motion across
965 * target boundaries. KeyVal is just there for debugging.
966 */
967LIR* insertCaseLabel(CompilationUnit* cUnit, int vaddr, int keyVal)
968{
Bill Buzbeea114add2012-05-03 15:00:40 -0700969 SafeMap<unsigned int, LIR*>::iterator it;
970 it = cUnit->boundaryMap.find(vaddr);
971 if (it == cUnit->boundaryMap.end()) {
972 LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr;
973 }
974 LIR* newLabel = (LIR*)oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
975 newLabel->dalvikOffset = vaddr;
976 newLabel->opcode = kPseudoCaseLabel;
977 newLabel->operands[0] = keyVal;
978 oatInsertLIRAfter(it->second, (LIR*)newLabel);
979 return newLabel;
buzbee31a4a6f2012-02-28 15:36:15 -0800980}
981
982void markPackedCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
983{
Bill Buzbeea114add2012-05-03 15:00:40 -0700984 const u2* table = tabRec->table;
985 int baseVaddr = tabRec->vaddr;
986 int *targets = (int*)&table[4];
987 int entries = table[1];
988 int lowKey = s4FromSwitchData(&table[2]);
989 for (int i = 0; i < entries; i++) {
990 tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
991 i + lowKey);
992 }
buzbee31a4a6f2012-02-28 15:36:15 -0800993}
994
995void markSparseCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
996{
Bill Buzbeea114add2012-05-03 15:00:40 -0700997 const u2* table = tabRec->table;
998 int baseVaddr = tabRec->vaddr;
999 int entries = table[1];
1000 int* keys = (int*)&table[2];
1001 int* targets = &keys[entries];
1002 for (int i = 0; i < entries; i++) {
1003 tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
1004 keys[i]);
1005 }
buzbee31a4a6f2012-02-28 15:36:15 -08001006}
1007
1008void oatProcessSwitchTables(CompilationUnit* cUnit)
1009{
Bill Buzbeea114add2012-05-03 15:00:40 -07001010 GrowableListIterator iterator;
1011 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
1012 while (true) {
1013 SwitchTable *tabRec =
1014 (SwitchTable *) oatGrowableListIteratorNext(&iterator);
1015 if (tabRec == NULL) break;
1016 if (tabRec->table[0] == Instruction::kPackedSwitchSignature) {
1017 markPackedCaseLabels(cUnit, tabRec);
1018 } else if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
1019 markSparseCaseLabels(cUnit, tabRec);
1020 } else {
1021 LOG(FATAL) << "Invalid switch table";
buzbee31a4a6f2012-02-28 15:36:15 -08001022 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001023 }
buzbee31a4a6f2012-02-28 15:36:15 -08001024}
1025
1026//FIXME: Do we have endian issues here?
1027
1028void dumpSparseSwitchTable(const u2* table)
Bill Buzbeea114add2012-05-03 15:00:40 -07001029 /*
1030 * Sparse switch data format:
1031 * ushort ident = 0x0200 magic value
1032 * ushort size number of entries in the table; > 0
1033 * int keys[size] keys, sorted low-to-high; 32-bit aligned
1034 * int targets[size] branch targets, relative to switch opcode
1035 *
1036 * Total size is (2+size*4) 16-bit code units.
1037 */
buzbee31a4a6f2012-02-28 15:36:15 -08001038{
Bill Buzbeea114add2012-05-03 15:00:40 -07001039 u2 ident = table[0];
1040 int entries = table[1];
1041 int* keys = (int*)&table[2];
1042 int* targets = &keys[entries];
1043 LOG(INFO) << "Sparse switch table - ident:0x" << std::hex << ident
1044 << ", entries: " << std::dec << entries;
1045 for (int i = 0; i < entries; i++) {
1046 LOG(INFO) << " Key[" << keys[i] << "] -> 0x" << std::hex << targets[i];
1047 }
buzbee31a4a6f2012-02-28 15:36:15 -08001048}
1049
1050void dumpPackedSwitchTable(const u2* table)
Bill Buzbeea114add2012-05-03 15:00:40 -07001051 /*
1052 * Packed switch data format:
1053 * ushort ident = 0x0100 magic value
1054 * ushort size number of entries in the table
1055 * int first_key first (and lowest) switch case value
1056 * int targets[size] branch targets, relative to switch opcode
1057 *
1058 * Total size is (4+size*2) 16-bit code units.
1059 */
buzbee31a4a6f2012-02-28 15:36:15 -08001060{
Bill Buzbeea114add2012-05-03 15:00:40 -07001061 u2 ident = table[0];
1062 int* targets = (int*)&table[4];
1063 int entries = table[1];
1064 int lowKey = s4FromSwitchData(&table[2]);
1065 LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident
1066 << ", entries: " << std::dec << entries << ", lowKey: " << lowKey;
1067 for (int i = 0; i < entries; i++) {
1068 LOG(INFO) << " Key[" << (i + lowKey) << "] -> 0x" << std::hex
1069 << targets[i];
1070 }
buzbee31a4a6f2012-02-28 15:36:15 -08001071}
buzbeee3acd072012-02-25 17:03:10 -08001072
buzbeed1643e42012-09-05 14:06:51 -07001073/*
1074 * Set up special LIR to mark a Dalvik byte-code instruction start and
1075 * record it in the boundaryMap. NOTE: in cases such as kMirOpCheck in
1076 * which we split a single Dalvik instruction, only the first MIR op
1077 * associated with a Dalvik PC should be entered into the map.
1078 */
1079LIR* markBoundary(CompilationUnit* cUnit, int offset, const char* instStr)
1080{
1081 LIR* res = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary, (intptr_t) instStr);
1082 if (cUnit->boundaryMap.find(offset) == cUnit->boundaryMap.end()) {
1083 cUnit->boundaryMap.Put(offset, res);
1084 }
1085 return res;
1086}
buzbeee3acd072012-02-25 17:03:10 -08001087
buzbeed1643e42012-09-05 14:06:51 -07001088}
1089 // namespace art