blob: 3041d0b4274927f293b622814b2921e3cd138698 [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 */
buzbee07131ca2012-11-07 16:13:14 -080068 lir->aliasInfo = ENCODE_ALIAS_INFO(regId, is64bit);
buzbee31a4a6f2012-02-28 15:36:15 -080069}
70
buzbeeb046e162012-10-30 15:48:42 -070071u8 oatGetRegMaskCommon(CompilationUnit* cUnit, int reg)
72{
73 return getRegMaskCommon(cUnit, reg);
74}
75
buzbee31a4a6f2012-02-28 15:36:15 -080076/*
77 * Mark the corresponding bit(s).
78 */
buzbeeb046e162012-10-30 15:48:42 -070079inline void setupRegMask(CompilationUnit* cUnit, u8* mask, int reg)
buzbee31a4a6f2012-02-28 15:36:15 -080080{
buzbeeb046e162012-10-30 15:48:42 -070081 *mask |= getRegMaskCommon(cUnit, reg);
82}
83
84/* Exported version of setupRegMask */
85void oatSetupRegMask(CompilationUnit* cUnit, u8* mask, int reg)
86{
87 setupRegMask(cUnit, mask, reg);
buzbee31a4a6f2012-02-28 15:36:15 -080088}
89
90/*
91 * Set up the proper fields in the resource mask
92 */
buzbeeb046e162012-10-30 15:48:42 -070093void setupResourceMasks(CompilationUnit* cUnit, LIR* lir)
buzbee31a4a6f2012-02-28 15:36:15 -080094{
Bill Buzbeea114add2012-05-03 15:00:40 -070095 int opcode = lir->opcode;
96 int flags;
buzbee31a4a6f2012-02-28 15:36:15 -080097
Bill Buzbeea114add2012-05-03 15:00:40 -070098 if (opcode <= 0) {
99 lir->useMask = lir->defMask = 0;
100 return;
101 }
buzbee31a4a6f2012-02-28 15:36:15 -0800102
buzbeeb046e162012-10-30 15:48:42 -0700103 flags = EncodingMap[opcode].flags;
buzbee31a4a6f2012-02-28 15:36:15 -0800104
Bill Buzbeea114add2012-05-03 15:00:40 -0700105 if (flags & NEEDS_FIXUP) {
106 lir->flags.pcRelFixup = true;
107 }
buzbee31a4a6f2012-02-28 15:36:15 -0800108
Bill Buzbeea114add2012-05-03 15:00:40 -0700109 /* Get the starting size of the instruction's template */
110 lir->flags.size = oatGetInsnSize(lir);
buzbeee88dfbf2012-03-05 11:19:57 -0800111
Bill Buzbeea114add2012-05-03 15:00:40 -0700112 /* Set up the mask for resources that are updated */
113 if (flags & (IS_LOAD | IS_STORE)) {
114 /* Default to heap - will catch specialized classes later */
115 setMemRefType(lir, flags & IS_LOAD, kHeapRef);
116 }
buzbee31a4a6f2012-02-28 15:36:15 -0800117
Bill Buzbeea114add2012-05-03 15:00:40 -0700118 /*
119 * Conservatively assume the branch here will call out a function that in
120 * turn will trash everything.
121 */
122 if (flags & IS_BRANCH) {
123 lir->defMask = lir->useMask = ENCODE_ALL;
124 return;
125 }
buzbee31a4a6f2012-02-28 15:36:15 -0800126
Bill Buzbeea114add2012-05-03 15:00:40 -0700127 if (flags & REG_DEF0) {
buzbeeb046e162012-10-30 15:48:42 -0700128 setupRegMask(cUnit, &lir->defMask, lir->operands[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700129 }
buzbee31a4a6f2012-02-28 15:36:15 -0800130
Bill Buzbeea114add2012-05-03 15:00:40 -0700131 if (flags & REG_DEF1) {
buzbeeb046e162012-10-30 15:48:42 -0700132 setupRegMask(cUnit, &lir->defMask, lir->operands[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700133 }
buzbee31a4a6f2012-02-28 15:36:15 -0800134
buzbee31a4a6f2012-02-28 15:36:15 -0800135
Bill Buzbeea114add2012-05-03 15:00:40 -0700136 if (flags & SETS_CCODES) {
137 lir->defMask |= ENCODE_CCODE;
138 }
buzbee31a4a6f2012-02-28 15:36:15 -0800139
Bill Buzbeea114add2012-05-03 15:00:40 -0700140 if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) {
141 int i;
buzbee31a4a6f2012-02-28 15:36:15 -0800142
Bill Buzbeea114add2012-05-03 15:00:40 -0700143 for (i = 0; i < 4; i++) {
144 if (flags & (1 << (kRegUse0 + i))) {
buzbeeb046e162012-10-30 15:48:42 -0700145 setupRegMask(cUnit, &lir->useMask, lir->operands[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700146 }
buzbee31a4a6f2012-02-28 15:36:15 -0800147 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700148 }
buzbee31a4a6f2012-02-28 15:36:15 -0800149
Bill Buzbeea114add2012-05-03 15:00:40 -0700150 if (flags & USES_CCODES) {
151 lir->useMask |= ENCODE_CCODE;
152 }
buzbee31a4a6f2012-02-28 15:36:15 -0800153
buzbeeb046e162012-10-30 15:48:42 -0700154 // Handle target-specific actions
155 setupTargetResourceMasks(cUnit, lir);
buzbee31a4a6f2012-02-28 15:36:15 -0800156}
157
158/*
buzbee5de34942012-03-01 14:51:57 -0800159 * Debugging macros
160 */
161#define DUMP_RESOURCE_MASK(X)
162#define DUMP_SSA_REP(X)
163
164/* Pretty-print a LIR instruction */
165void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr)
166{
Bill Buzbeea114add2012-05-03 15:00:40 -0700167 LIR* lir = (LIR*) arg;
168 int offset = lir->offset;
169 int dest = lir->operands[0];
170 const bool dumpNop = (cUnit->enableDebug & (1 << kDebugShowNops));
buzbee5de34942012-03-01 14:51:57 -0800171
Bill Buzbeea114add2012-05-03 15:00:40 -0700172 /* Handle pseudo-ops individually, and all regular insns as a group */
173 switch (lir->opcode) {
174 case kPseudoMethodEntry:
175 LOG(INFO) << "-------- method entry "
176 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
177 break;
178 case kPseudoMethodExit:
179 LOG(INFO) << "-------- Method_Exit";
180 break;
181 case kPseudoBarrier:
182 LOG(INFO) << "-------- BARRIER";
183 break;
184 case kPseudoExtended:
185 LOG(INFO) << "-------- " << (char* ) dest;
186 break;
187 case kPseudoSSARep:
188 DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " << (char* ) dest);
189 break;
190 case kPseudoEntryBlock:
191 LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
192 break;
193 case kPseudoDalvikByteCodeBoundary:
194 LOG(INFO) << "-------- dalvik offset: 0x" << std::hex
195 << lir->dalvikOffset << " @ " << (char* )lir->operands[0];
196 break;
197 case kPseudoExitBlock:
198 LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
199 break;
200 case kPseudoPseudoAlign4:
201 LOG(INFO) << (intptr_t)baseAddr + offset << " (0x" << std::hex
202 << offset << "): .align4";
203 break;
204 case kPseudoEHBlockLabel:
205 LOG(INFO) << "Exception_Handling:";
206 break;
207 case kPseudoTargetLabel:
208 case kPseudoNormalBlockLabel:
209 LOG(INFO) << "L" << (void*)lir << ":";
210 break;
211 case kPseudoThrowTarget:
212 LOG(INFO) << "LT" << (void*)lir << ":";
213 break;
214 case kPseudoIntrinsicRetry:
215 LOG(INFO) << "IR" << (void*)lir << ":";
216 break;
217 case kPseudoSuspendTarget:
218 LOG(INFO) << "LS" << (void*)lir << ":";
219 break;
buzbee8320f382012-09-11 16:29:42 -0700220 case kPseudoSafepointPC:
221 LOG(INFO) << "LsafepointPC_0x" << std::hex << lir->offset << "_" << lir->dalvikOffset << ":";
222 break;
Bill Buzbeea5b30242012-09-28 07:19:44 -0700223 case kPseudoExportedPC:
224 LOG(INFO) << "LexportedPC_0x" << std::hex << lir->offset << "_" << lir->dalvikOffset << ":";
225 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700226 case kPseudoCaseLabel:
227 LOG(INFO) << "LC" << (void*)lir << ": Case target 0x"
228 << std::hex << lir->operands[0] << "|" << std::dec <<
229 lir->operands[0];
230 break;
231 default:
232 if (lir->flags.isNop && !dumpNop) {
233 break;
234 } else {
235 std::string op_name(buildInsnString(EncodingMap[lir->opcode].name,
236 lir, baseAddr));
237 std::string op_operands(buildInsnString(EncodingMap[lir->opcode].fmt
238 , lir, baseAddr));
239 LOG(INFO) << StringPrintf("%05x: %-9s%s%s",
240 (unsigned int)(baseAddr + offset),
241 op_name.c_str(), op_operands.c_str(),
242 lir->flags.isNop ? "(nop)" : "");
243 }
244 break;
245 }
buzbee5de34942012-03-01 14:51:57 -0800246
Bill Buzbeea114add2012-05-03 15:00:40 -0700247 if (lir->useMask && (!lir->flags.isNop || dumpNop)) {
248 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->useMask, "use"));
249 }
250 if (lir->defMask && (!lir->flags.isNop || dumpNop)) {
251 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->defMask, "def"));
252 }
buzbee5de34942012-03-01 14:51:57 -0800253}
254
255void oatDumpPromotionMap(CompilationUnit *cUnit)
256{
Bill Buzbeea114add2012-05-03 15:00:40 -0700257 int numRegs = cUnit->numDalvikRegisters + cUnit->numCompilerTemps + 1;
258 for (int i = 0; i < numRegs; i++) {
259 PromotionMap vRegMap = cUnit->promotionMap[i];
260 std::string buf;
261 if (vRegMap.fpLocation == kLocPhysReg) {
262 StringAppendF(&buf, " : s%d", vRegMap.fpReg & FP_REG_MASK);
buzbee5de34942012-03-01 14:51:57 -0800263 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700264
265 std::string buf3;
266 if (i < cUnit->numDalvikRegisters) {
267 StringAppendF(&buf3, "%02d", i);
268 } else if (i == cUnit->methodSReg) {
269 buf3 = "Method*";
270 } else {
271 StringAppendF(&buf3, "ct%d", i - cUnit->numDalvikRegisters);
272 }
273
274 LOG(INFO) << StringPrintf("V[%s] -> %s%d%s", buf3.c_str(),
275 vRegMap.coreLocation == kLocPhysReg ?
276 "r" : "SP+", vRegMap.coreLocation == kLocPhysReg ?
277 vRegMap.coreReg : oatSRegOffset(cUnit, i),
278 buf.c_str());
279 }
buzbee5de34942012-03-01 14:51:57 -0800280}
281
Bill Buzbeea5b30242012-09-28 07:19:44 -0700282/* Dump a mapping table */
283void dumpMappingTable(const char* table_name, const std::string& descriptor,
284 const std::string& name, const std::string& signature,
285 const std::vector<uint32_t>& v) {
286 if (v.size() > 0) {
287 std::string line(StringPrintf("\n %s %s%s_%s_table[%zu] = {", table_name,
288 descriptor.c_str(), name.c_str(), signature.c_str(), v.size()));
289 std::replace(line.begin(), line.end(), ';', '_');
290 LOG(INFO) << line;
291 for (uint32_t i = 0; i < v.size(); i+=2) {
292 line = StringPrintf(" {0x%05x, 0x%04x},", v[i], v[i+1]);
293 LOG(INFO) << line;
294 }
295 LOG(INFO) <<" };\n\n";
296 }
297}
298
buzbee5de34942012-03-01 14:51:57 -0800299/* Dump instructions and constant pool contents */
300void oatCodegenDump(CompilationUnit* cUnit)
301{
Bill Buzbeea114add2012-05-03 15:00:40 -0700302 LOG(INFO) << "Dumping LIR insns for "
303 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
304 LIR* lirInsn;
305 LIR* thisLIR;
306 int insnsSize = cUnit->insnsSize;
buzbee5de34942012-03-01 14:51:57 -0800307
Bill Buzbeea114add2012-05-03 15:00:40 -0700308 LOG(INFO) << "Regs (excluding ins) : " << cUnit->numRegs;
309 LOG(INFO) << "Ins : " << cUnit->numIns;
310 LOG(INFO) << "Outs : " << cUnit->numOuts;
311 LOG(INFO) << "CoreSpills : " << cUnit->numCoreSpills;
312 LOG(INFO) << "FPSpills : " << cUnit->numFPSpills;
313 LOG(INFO) << "CompilerTemps : " << cUnit->numCompilerTemps;
314 LOG(INFO) << "Frame size : " << cUnit->frameSize;
315 LOG(INFO) << "code size is " << cUnit->totalSize <<
316 " bytes, Dalvik size is " << insnsSize * 2;
317 LOG(INFO) << "expansion factor: "
318 << (float)cUnit->totalSize / (float)(insnsSize * 2);
319 oatDumpPromotionMap(cUnit);
320 for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
321 oatDumpLIRInsn(cUnit, lirInsn, 0);
322 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700323 for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
324 thisLIR = (LIR*) lirInsn;
325 LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)",
326 thisLIR->offset, thisLIR->offset,
327 thisLIR->operands[0]);
328 }
buzbee5de34942012-03-01 14:51:57 -0800329
Bill Buzbeea114add2012-05-03 15:00:40 -0700330 const DexFile::MethodId& method_id =
331 cUnit->dex_file->GetMethodId(cUnit->method_idx);
332 std::string signature(cUnit->dex_file->GetMethodSignature(method_id));
333 std::string name(cUnit->dex_file->GetMethodName(method_id));
334 std::string descriptor(cUnit->dex_file->GetMethodDeclaringClassDescriptor(method_id));
buzbee5de34942012-03-01 14:51:57 -0800335
Bill Buzbeea5b30242012-09-28 07:19:44 -0700336 // Dump mapping tables
337 dumpMappingTable("PC2Dex_MappingTable", descriptor, name, signature, cUnit->pc2dexMappingTable);
338 dumpMappingTable("Dex2PC_MappingTable", descriptor, name, signature, cUnit->dex2pcMappingTable);
buzbee5de34942012-03-01 14:51:57 -0800339}
340
buzbeea2ebdd72012-03-04 14:57:06 -0800341
342LIR* rawLIR(CompilationUnit* cUnit, int dalvikOffset, int opcode, int op0,
Bill Buzbeea114add2012-05-03 15:00:40 -0700343 int op1, int op2, int op3, int op4, LIR* target)
buzbeea2ebdd72012-03-04 14:57:06 -0800344{
Bill Buzbeea114add2012-05-03 15:00:40 -0700345 LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
346 insn->dalvikOffset = dalvikOffset;
347 insn->opcode = opcode;
348 insn->operands[0] = op0;
349 insn->operands[1] = op1;
350 insn->operands[2] = op2;
351 insn->operands[3] = op3;
352 insn->operands[4] = op4;
353 insn->target = target;
buzbeeb046e162012-10-30 15:48:42 -0700354 oatSetupResourceMasks(cUnit, insn);
Bill Buzbeea5b30242012-09-28 07:19:44 -0700355 if ((opcode == kPseudoTargetLabel) || (opcode == kPseudoSafepointPC) ||
356 (opcode == kPseudoExportedPC)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700357 // Always make labels scheduling barriers
buzbee8320f382012-09-11 16:29:42 -0700358 insn->useMask = insn->defMask = ENCODE_ALL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700359 }
360 return insn;
buzbeea2ebdd72012-03-04 14:57:06 -0800361}
362
buzbee5de34942012-03-01 14:51:57 -0800363/*
buzbee31a4a6f2012-02-28 15:36:15 -0800364 * The following are building blocks to construct low-level IRs with 0 - 4
365 * operands.
366 */
buzbee5de34942012-03-01 14:51:57 -0800367LIR* newLIR0(CompilationUnit* cUnit, int opcode)
buzbee31a4a6f2012-02-28 15:36:15 -0800368{
Bill Buzbeea114add2012-05-03 15:00:40 -0700369 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND))
370 << EncodingMap[opcode].name << " " << (int)opcode << " "
371 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
372 << cUnit->currentDalvikOffset;
373 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode);
374 oatAppendLIR(cUnit, (LIR*) insn);
375 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800376}
377
buzbee5de34942012-03-01 14:51:57 -0800378LIR* newLIR1(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700379 int dest)
buzbee31a4a6f2012-02-28 15:36:15 -0800380{
Bill Buzbeea114add2012-05-03 15:00:40 -0700381 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_UNARY_OP))
382 << EncodingMap[opcode].name << " " << (int)opcode << " "
383 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
384 << cUnit->currentDalvikOffset;
385 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest);
386 oatAppendLIR(cUnit, (LIR*) insn);
387 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800388}
389
buzbee5de34942012-03-01 14:51:57 -0800390LIR* newLIR2(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700391 int dest, int src1)
buzbee31a4a6f2012-02-28 15:36:15 -0800392{
Bill Buzbeea114add2012-05-03 15:00:40 -0700393 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_BINARY_OP))
394 << EncodingMap[opcode].name << " " << (int)opcode << " "
395 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
396 << cUnit->currentDalvikOffset;
397 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1);
398 oatAppendLIR(cUnit, (LIR*) insn);
399 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800400}
401
buzbee5de34942012-03-01 14:51:57 -0800402LIR* newLIR3(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700403 int dest, int src1, int src2)
buzbee31a4a6f2012-02-28 15:36:15 -0800404{
Bill Buzbeea114add2012-05-03 15:00:40 -0700405 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_TERTIARY_OP))
406 << EncodingMap[opcode].name << " " << (int)opcode << " "
407 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
408 << cUnit->currentDalvikOffset;
409 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
410 src2);
411 oatAppendLIR(cUnit, (LIR*) insn);
412 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800413}
414
buzbee5de34942012-03-01 14:51:57 -0800415LIR* newLIR4(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700416 int dest, int src1, int src2, int info)
buzbee31a4a6f2012-02-28 15:36:15 -0800417{
Bill Buzbeea114add2012-05-03 15:00:40 -0700418 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUAD_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, src1,
423 src2, info);
424 oatAppendLIR(cUnit, (LIR*) insn);
425 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800426}
buzbee31a4a6f2012-02-28 15:36:15 -0800427
Ian Rogersb5d09b22012-03-06 22:14:17 -0800428LIR* newLIR5(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700429 int dest, int src1, int src2, int info1, int info2)
Ian Rogersb5d09b22012-03-06 22:14:17 -0800430{
Bill Buzbeea114add2012-05-03 15:00:40 -0700431 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUIN_OP))
432 << EncodingMap[opcode].name << " " << (int)opcode << " "
433 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
434 << cUnit->currentDalvikOffset;
435 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
436 src2, info1, info2);
437 oatAppendLIR(cUnit, (LIR*) insn);
438 return insn;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800439}
440
buzbee31a4a6f2012-02-28 15:36:15 -0800441/*
442 * Search the existing constants in the literal pool for an exact or close match
443 * within specified delta (greater or equal to 0).
444 */
445LIR* scanLiteralPool(LIR* dataTarget, int value, unsigned int delta)
446{
Bill Buzbeea114add2012-05-03 15:00:40 -0700447 while (dataTarget) {
448 if (((unsigned) (value - ((LIR* ) dataTarget)->operands[0])) <= delta)
449 return (LIR* ) dataTarget;
450 dataTarget = dataTarget->next;
451 }
452 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800453}
454
455/* Search the existing constants in the literal pool for an exact wide match */
456LIR* scanLiteralPoolWide(LIR* dataTarget, int valLo, int valHi)
457{
Bill Buzbeea114add2012-05-03 15:00:40 -0700458 bool loMatch = false;
459 LIR* loTarget = NULL;
460 while (dataTarget) {
461 if (loMatch && (((LIR*)dataTarget)->operands[0] == valHi)) {
462 return (LIR*)loTarget;
buzbee31a4a6f2012-02-28 15:36:15 -0800463 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700464 loMatch = false;
465 if (((LIR*)dataTarget)->operands[0] == valLo) {
466 loMatch = true;
467 loTarget = dataTarget;
468 }
469 dataTarget = dataTarget->next;
470 }
471 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800472}
473
474/*
475 * The following are building blocks to insert constants into the pool or
476 * instruction streams.
477 */
478
buzbee5de34942012-03-01 14:51:57 -0800479/* Add a 32-bit constant either in the constant pool */
Ian Rogers3fa13792012-03-18 15:53:45 -0700480LIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP, int value)
buzbee31a4a6f2012-02-28 15:36:15 -0800481{
Bill Buzbeea114add2012-05-03 15:00:40 -0700482 /* Add the constant to the literal pool */
483 if (constantListP) {
484 LIR* newValue = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocData);
485 newValue->operands[0] = value;
486 newValue->next = *constantListP;
487 *constantListP = (LIR*) newValue;
488 return newValue;
489 }
490 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800491}
492
493/* Add a 64-bit constant to the constant pool or mixed with code */
494LIR* addWideData(CompilationUnit* cUnit, LIR* *constantListP,
Bill Buzbeea114add2012-05-03 15:00:40 -0700495 int valLo, int valHi)
buzbee31a4a6f2012-02-28 15:36:15 -0800496{
Bill Buzbeea114add2012-05-03 15:00:40 -0700497 //FIXME: hard-coded little endian, need BE variant
498 // Insert high word into list first
499 addWordData(cUnit, constantListP, valHi);
500 return addWordData(cUnit, constantListP, valLo);
buzbee31a4a6f2012-02-28 15:36:15 -0800501}
502
Ian Rogersab058bb2012-03-11 22:19:38 -0700503void pushWord(std::vector<uint8_t>&buf, int data) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700504 buf.push_back( data & 0xff);
505 buf.push_back( (data >> 8) & 0xff);
506 buf.push_back( (data >> 16) & 0xff);
507 buf.push_back( (data >> 24) & 0xff);
buzbeee3acd072012-02-25 17:03:10 -0800508}
509
Ian Rogersab058bb2012-03-11 22:19:38 -0700510void alignBuffer(std::vector<uint8_t>&buf, size_t offset) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700511 while (buf.size() < offset) {
512 buf.push_back(0);
513 }
buzbeee3acd072012-02-25 17:03:10 -0800514}
515
Brian Carlstromf5822582012-03-19 22:34:31 -0700516bool IsDirect(int invokeType) {
517 InvokeType type = static_cast<InvokeType>(invokeType);
518 return type == kStatic || type == kDirect;
519}
520
buzbeee3acd072012-02-25 17:03:10 -0800521/* Write the literal pool to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800522void installLiteralPools(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800523{
Bill Buzbeea114add2012-05-03 15:00:40 -0700524 alignBuffer(cUnit->codeBuffer, cUnit->dataOffset);
525 LIR* dataLIR = cUnit->literalList;
526 while (dataLIR != NULL) {
527 pushWord(cUnit->codeBuffer, dataLIR->operands[0]);
528 dataLIR = NEXT_LIR(dataLIR);
529 }
530 // Push code and method literals, record offsets for the compiler to patch.
531 dataLIR = cUnit->codeLiteralList;
Ian Rogers137e88f2012-10-08 17:46:47 -0700532 while (dataLIR != NULL) {
533 uint32_t target = dataLIR->operands[0];
534 cUnit->compiler->AddCodePatch(cUnit->dex_file,
535 cUnit->method_idx,
536 cUnit->invoke_type,
537 target,
538 static_cast<InvokeType>(dataLIR->operands[1]),
539 cUnit->codeBuffer.size());
540 const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target);
541 // unique based on target to ensure code deduplication works
542 uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
543 pushWord(cUnit->codeBuffer, unique_patch_value);
544 dataLIR = NEXT_LIR(dataLIR);
545 }
546 dataLIR = cUnit->methodLiteralList;
547 while (dataLIR != NULL) {
548 uint32_t target = dataLIR->operands[0];
549 cUnit->compiler->AddMethodPatch(cUnit->dex_file,
Bill Buzbeea114add2012-05-03 15:00:40 -0700550 cUnit->method_idx,
Ian Rogers08f753d2012-08-24 14:35:25 -0700551 cUnit->invoke_type,
Bill Buzbeea114add2012-05-03 15:00:40 -0700552 target,
Ian Rogers08f753d2012-08-24 14:35:25 -0700553 static_cast<InvokeType>(dataLIR->operands[1]),
Bill Buzbeea114add2012-05-03 15:00:40 -0700554 cUnit->codeBuffer.size());
Ian Rogers137e88f2012-10-08 17:46:47 -0700555 const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target);
556 // unique based on target to ensure code deduplication works
557 uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
558 pushWord(cUnit->codeBuffer, unique_patch_value);
559 dataLIR = NEXT_LIR(dataLIR);
Bill Buzbeea114add2012-05-03 15:00:40 -0700560 }
buzbeee3acd072012-02-25 17:03:10 -0800561}
562
563/* Write the switch tables to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800564void installSwitchTables(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800565{
Bill Buzbeea114add2012-05-03 15:00:40 -0700566 GrowableListIterator iterator;
567 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
568 while (true) {
569 SwitchTable* tabRec = (SwitchTable *) oatGrowableListIteratorNext(
570 &iterator);
571 if (tabRec == NULL) break;
572 alignBuffer(cUnit->codeBuffer, tabRec->offset);
573 /*
574 * For Arm, our reference point is the address of the bx
575 * instruction that does the launch, so we have to subtract
576 * the auto pc-advance. For other targets the reference point
577 * is a label, so we can use the offset as-is.
578 */
buzbeeb046e162012-10-30 15:48:42 -0700579 int bxOffset = INVALID_OFFSET;
580 switch (cUnit->instructionSet) {
581 case kThumb2:
582 bxOffset = tabRec->anchor->offset + 4;
583 break;
584 case kX86:
585 bxOffset = 0;
586 break;
587 case kMips:
588 bxOffset = tabRec->anchor->offset;
589 break;
590 default: LOG(FATAL) << "Unexpected instruction set: " << cUnit->instructionSet;
591 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700592 if (cUnit->printMe) {
593 LOG(INFO) << "Switch table for offset 0x" << std::hex << bxOffset;
buzbeee3acd072012-02-25 17:03:10 -0800594 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700595 if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
596 int* keys = (int*)&(tabRec->table[2]);
597 for (int elems = 0; elems < tabRec->table[1]; elems++) {
598 int disp = tabRec->targets[elems]->offset - bxOffset;
599 if (cUnit->printMe) {
600 LOG(INFO) << " Case[" << elems << "] key: 0x"
601 << std::hex << keys[elems] << ", disp: 0x"
602 << std::hex << disp;
603 }
604 pushWord(cUnit->codeBuffer, keys[elems]);
605 pushWord(cUnit->codeBuffer,
606 tabRec->targets[elems]->offset - bxOffset);
607 }
608 } else {
609 DCHECK_EQ(static_cast<int>(tabRec->table[0]),
610 static_cast<int>(Instruction::kPackedSwitchSignature));
611 for (int elems = 0; elems < tabRec->table[1]; elems++) {
612 int disp = tabRec->targets[elems]->offset - bxOffset;
613 if (cUnit->printMe) {
614 LOG(INFO) << " Case[" << elems << "] disp: 0x"
615 << std::hex << disp;
616 }
617 pushWord(cUnit->codeBuffer, tabRec->targets[elems]->offset - bxOffset);
618 }
619 }
620 }
buzbeee3acd072012-02-25 17:03:10 -0800621}
622
623/* Write the fill array dta to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800624void installFillArrayData(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800625{
Bill Buzbeea114add2012-05-03 15:00:40 -0700626 GrowableListIterator iterator;
627 oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
628 while (true) {
629 FillArrayData *tabRec = (FillArrayData *) oatGrowableListIteratorNext(
630 &iterator);
631 if (tabRec == NULL) break;
632 alignBuffer(cUnit->codeBuffer, tabRec->offset);
633 for (int i = 0; i < (tabRec->size + 1) / 2; i++) {
634 cUnit->codeBuffer.push_back( tabRec->table[i] & 0xFF);
635 cUnit->codeBuffer.push_back( (tabRec->table[i] >> 8) & 0xFF);
buzbeee3acd072012-02-25 17:03:10 -0800636 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700637 }
buzbeee3acd072012-02-25 17:03:10 -0800638}
639
buzbee31a4a6f2012-02-28 15:36:15 -0800640int assignLiteralOffsetCommon(LIR* lir, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800641{
Bill Buzbeea114add2012-05-03 15:00:40 -0700642 for (;lir != NULL; lir = lir->next) {
643 lir->offset = offset;
644 offset += 4;
645 }
646 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800647}
648
buzbee6459e7c2012-10-02 14:42:41 -0700649// Make sure we have a code address for every declared catch entry
650bool verifyCatchEntries(CompilationUnit* cUnit)
651{
652 bool success = true;
653 for (std::set<uint32_t>::const_iterator it = cUnit->catches.begin(); it != cUnit->catches.end(); ++it) {
654 uint32_t dexPc = *it;
655 bool found = false;
656 for (size_t i = 0; i < cUnit->dex2pcMappingTable.size(); i += 2) {
657 if (dexPc == cUnit->dex2pcMappingTable[i+1]) {
658 found = true;
659 break;
660 }
661 }
662 if (!found) {
663 LOG(INFO) << "Missing native PC for catch entry @ 0x" << std::hex << dexPc;
664 success = false;
665 }
666 }
667 // Now, try in the other direction
668 for (size_t i = 0; i < cUnit->dex2pcMappingTable.size(); i += 2) {
669 uint32_t dexPc = cUnit->dex2pcMappingTable[i+1];
670 if (cUnit->catches.find(dexPc) == cUnit->catches.end()) {
671 LOG(INFO) << "Unexpected catch entry @ dex pc 0x" << std::hex << dexPc;
672 success = false;
673 }
674 }
675 if (!success) {
676 LOG(INFO) << "Bad dex2pcMapping table in " << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
677 LOG(INFO) << "Entries @ decode: " << cUnit->catches.size() << ", Entries in table: "
678 << cUnit->dex2pcMappingTable.size()/2;
679 }
680 return success;
681}
682
Bill Buzbeea5b30242012-09-28 07:19:44 -0700683void createMappingTables(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800684{
buzbee8320f382012-09-11 16:29:42 -0700685 for (LIR* tgtLIR = (LIR *) cUnit->firstLIRInsn; tgtLIR != NULL; tgtLIR = NEXT_LIR(tgtLIR)) {
686 if (!tgtLIR->flags.isNop && (tgtLIR->opcode == kPseudoSafepointPC)) {
Bill Buzbeea5b30242012-09-28 07:19:44 -0700687 cUnit->pc2dexMappingTable.push_back(tgtLIR->offset);
688 cUnit->pc2dexMappingTable.push_back(tgtLIR->dalvikOffset);
689 }
690 if (!tgtLIR->flags.isNop && (tgtLIR->opcode == kPseudoExportedPC)) {
691 cUnit->dex2pcMappingTable.push_back(tgtLIR->offset);
692 cUnit->dex2pcMappingTable.push_back(tgtLIR->dalvikOffset);
buzbeee3acd072012-02-25 17:03:10 -0800693 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700694 }
buzbee6459e7c2012-10-02 14:42:41 -0700695 DCHECK(verifyCatchEntries(cUnit));
Bill Buzbeea5b30242012-09-28 07:19:44 -0700696 cUnit->combinedMappingTable.push_back(cUnit->pc2dexMappingTable.size() +
697 cUnit->dex2pcMappingTable.size());
698 cUnit->combinedMappingTable.push_back(cUnit->pc2dexMappingTable.size());
699 cUnit->combinedMappingTable.insert(cUnit->combinedMappingTable.end(),
700 cUnit->pc2dexMappingTable.begin(),
701 cUnit->pc2dexMappingTable.end());
702 cUnit->combinedMappingTable.insert(cUnit->combinedMappingTable.end(),
703 cUnit->dex2pcMappingTable.begin(),
704 cUnit->dex2pcMappingTable.end());
buzbeee3acd072012-02-25 17:03:10 -0800705}
706
Ian Rogers0c7abda2012-09-19 13:33:42 -0700707class NativePcToReferenceMapBuilder {
708 public:
709 NativePcToReferenceMapBuilder(std::vector<uint8_t>* table,
710 size_t entries, uint32_t max_native_offset,
711 size_t references_width) : entries_(entries),
712 references_width_(references_width), in_use_(entries),
713 table_(table) {
714 // Compute width in bytes needed to hold max_native_offset.
715 native_offset_width_ = 0;
716 while (max_native_offset != 0) {
717 native_offset_width_++;
718 max_native_offset >>= 8;
719 }
720 // Resize table and set up header.
721 table->resize((EntryWidth() * entries) + sizeof(uint32_t));
Ian Rogers000d7242012-09-21 16:07:36 -0700722 CHECK_LT(native_offset_width_, 1U << 3);
723 (*table)[0] = native_offset_width_ & 7;
724 CHECK_LT(references_width_, 1U << 13);
725 (*table)[0] |= (references_width_ << 3) & 0xFF;
726 (*table)[1] = (references_width_ >> 5) & 0xFF;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700727 CHECK_LT(entries, 1U << 16);
728 (*table)[2] = entries & 0xFF;
729 (*table)[3] = (entries >> 8) & 0xFF;
730 }
731
732 void AddEntry(uint32_t native_offset, const uint8_t* references) {
733 size_t table_index = TableIndex(native_offset);
734 while (in_use_[table_index]) {
735 table_index = (table_index + 1) % entries_;
736 }
737 in_use_[table_index] = true;
738 SetNativeOffset(table_index, native_offset);
739 DCHECK_EQ(native_offset, GetNativeOffset(table_index));
740 SetReferences(table_index, references);
741 }
742
743 private:
744 size_t TableIndex(uint32_t native_offset) {
745 return NativePcOffsetToReferenceMap::Hash(native_offset) % entries_;
746 }
747
748 uint32_t GetNativeOffset(size_t table_index) {
749 uint32_t native_offset = 0;
750 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
751 for (size_t i = 0; i < native_offset_width_; i++) {
752 native_offset |= (*table_)[table_offset + i] << (i * 8);
753 }
754 return native_offset;
755 }
756
757 void SetNativeOffset(size_t table_index, uint32_t native_offset) {
758 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
759 for (size_t i = 0; i < native_offset_width_; i++) {
760 (*table_)[table_offset + i] = (native_offset >> (i * 8)) & 0xFF;
761 }
762 }
763
764 void SetReferences(size_t table_index, const uint8_t* references) {
765 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
766 memcpy(&(*table_)[table_offset + native_offset_width_], references, references_width_);
767 }
768
769 size_t EntryWidth() const {
770 return native_offset_width_ + references_width_;
771 }
772
773 // Number of entries in the table.
774 const size_t entries_;
775 // Number of bytes used to encode the reference bitmap.
776 const size_t references_width_;
777 // Number of bytes used to encode a native offset.
778 size_t native_offset_width_;
779 // Entries that are in use.
780 std::vector<bool> in_use_;
781 // The table we're building.
782 std::vector<uint8_t>* const table_;
783};
784
785static void createNativeGcMap(CompilationUnit* cUnit) {
Bill Buzbeea5b30242012-09-28 07:19:44 -0700786 const std::vector<uint32_t>& mapping_table = cUnit->pc2dexMappingTable;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700787 uint32_t max_native_offset = 0;
788 for (size_t i = 0; i < mapping_table.size(); i += 2) {
789 uint32_t native_offset = mapping_table[i + 0];
790 if (native_offset > max_native_offset) {
791 max_native_offset = native_offset;
792 }
793 }
794 Compiler::MethodReference method_ref(cUnit->dex_file, cUnit->method_idx);
795 const std::vector<uint8_t>* gc_map_raw = verifier::MethodVerifier::GetDexGcMap(method_ref);
796 verifier::DexPcToReferenceMap dex_gc_map(&(*gc_map_raw)[4], gc_map_raw->size() - 4);
797 // Compute native offset to references size.
798 NativePcToReferenceMapBuilder native_gc_map_builder(&cUnit->nativeGcMap,
799 mapping_table.size() / 2, max_native_offset,
800 dex_gc_map.RegWidth());
801
802 for (size_t i = 0; i < mapping_table.size(); i += 2) {
803 uint32_t native_offset = mapping_table[i + 0];
804 uint32_t dex_pc = mapping_table[i + 1];
805 const uint8_t* references = dex_gc_map.FindBitMap(dex_pc, false);
Bill Buzbeea5b30242012-09-28 07:19:44 -0700806 CHECK(references != NULL) << "Missing ref for dex pc 0x" << std::hex << dex_pc;
807 native_gc_map_builder.AddEntry(native_offset, references);
Ian Rogers0c7abda2012-09-19 13:33:42 -0700808 }
809}
810
buzbeee3acd072012-02-25 17:03:10 -0800811/* Determine the offset of each literal field */
buzbee31a4a6f2012-02-28 15:36:15 -0800812int assignLiteralOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800813{
Bill Buzbeea114add2012-05-03 15:00:40 -0700814 offset = assignLiteralOffsetCommon(cUnit->literalList, offset);
815 offset = assignLiteralOffsetCommon(cUnit->codeLiteralList, offset);
816 offset = assignLiteralOffsetCommon(cUnit->methodLiteralList, offset);
817 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800818}
819
buzbee31a4a6f2012-02-28 15:36:15 -0800820int assignSwitchTablesOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800821{
Bill Buzbeea114add2012-05-03 15:00:40 -0700822 GrowableListIterator iterator;
823 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
824 while (true) {
825 SwitchTable *tabRec = (SwitchTable *) oatGrowableListIteratorNext(
826 &iterator);
827 if (tabRec == NULL) break;
828 tabRec->offset = offset;
829 if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
830 offset += tabRec->table[1] * (sizeof(int) * 2);
831 } else {
832 DCHECK_EQ(static_cast<int>(tabRec->table[0]),
833 static_cast<int>(Instruction::kPackedSwitchSignature));
834 offset += tabRec->table[1] * sizeof(int);
buzbeee3acd072012-02-25 17:03:10 -0800835 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700836 }
837 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800838}
839
buzbee31a4a6f2012-02-28 15:36:15 -0800840int assignFillArrayDataOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800841{
Bill Buzbeea114add2012-05-03 15:00:40 -0700842 GrowableListIterator iterator;
843 oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
844 while (true) {
845 FillArrayData *tabRec = (FillArrayData *) oatGrowableListIteratorNext(
846 &iterator);
847 if (tabRec == NULL) break;
848 tabRec->offset = offset;
849 offset += tabRec->size;
850 // word align
851 offset = (offset + 3) & ~3;
852 }
853 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800854}
855
856/*
857 * Walk the compilation unit and assign offsets to instructions
858 * and literals and compute the total size of the compiled unit.
859 */
860void oatAssignOffsets(CompilationUnit* cUnit)
861{
Bill Buzbeea114add2012-05-03 15:00:40 -0700862 int offset = oatAssignInsnOffsets(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800863
Bill Buzbeea114add2012-05-03 15:00:40 -0700864 /* Const values have to be word aligned */
865 offset = (offset + 3) & ~3;
buzbeee3acd072012-02-25 17:03:10 -0800866
Bill Buzbeea114add2012-05-03 15:00:40 -0700867 /* Set up offsets for literals */
868 cUnit->dataOffset = offset;
buzbeee3acd072012-02-25 17:03:10 -0800869
Bill Buzbeea114add2012-05-03 15:00:40 -0700870 offset = assignLiteralOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800871
Bill Buzbeea114add2012-05-03 15:00:40 -0700872 offset = assignSwitchTablesOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800873
Bill Buzbeea114add2012-05-03 15:00:40 -0700874 offset = assignFillArrayDataOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800875
Bill Buzbeea114add2012-05-03 15:00:40 -0700876 cUnit->totalSize = offset;
buzbeee3acd072012-02-25 17:03:10 -0800877}
878
879/*
880 * Go over each instruction in the list and calculate the offset from the top
881 * before sending them off to the assembler. If out-of-range branch distance is
882 * seen rearrange the instructions a bit to correct it.
883 */
884void oatAssembleLIR(CompilationUnit* cUnit)
885{
Bill Buzbeea114add2012-05-03 15:00:40 -0700886 oatAssignOffsets(cUnit);
887 /*
888 * Assemble here. Note that we generate code with optimistic assumptions
889 * and if found now to work, we'll have to redo the sequence and retry.
890 */
buzbeee3acd072012-02-25 17:03:10 -0800891
Bill Buzbeea114add2012-05-03 15:00:40 -0700892 while (true) {
893 AssemblerStatus res = oatAssembleInstructions(cUnit, 0);
894 if (res == kSuccess) {
895 break;
896 } else {
897 cUnit->assemblerRetries++;
898 if (cUnit->assemblerRetries > MAX_ASSEMBLER_RETRIES) {
899 oatCodegenDump(cUnit);
900 LOG(FATAL) << "Assembler error - too many retries";
901 }
902 // Redo offsets and try again
903 oatAssignOffsets(cUnit);
904 cUnit->codeBuffer.clear();
buzbeee3acd072012-02-25 17:03:10 -0800905 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700906 }
buzbeee3acd072012-02-25 17:03:10 -0800907
Bill Buzbeea114add2012-05-03 15:00:40 -0700908 // Install literals
909 installLiteralPools(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800910
Bill Buzbeea114add2012-05-03 15:00:40 -0700911 // Install switch tables
912 installSwitchTables(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800913
Bill Buzbeea114add2012-05-03 15:00:40 -0700914 // Install fill array data
915 installFillArrayData(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800916
Ian Rogers0c7abda2012-09-19 13:33:42 -0700917 // Create the mapping table and native offset to reference map.
Bill Buzbeea5b30242012-09-28 07:19:44 -0700918 createMappingTables(cUnit);
Ian Rogers0c7abda2012-09-19 13:33:42 -0700919
920 createNativeGcMap(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800921}
922
buzbee31a4a6f2012-02-28 15:36:15 -0800923/*
924 * Insert a kPseudoCaseLabel at the beginning of the Dalvik
925 * offset vaddr. This label will be used to fix up the case
926 * branch table during the assembly phase. Be sure to set
927 * all resource flags on this to prevent code motion across
928 * target boundaries. KeyVal is just there for debugging.
929 */
930LIR* insertCaseLabel(CompilationUnit* cUnit, int vaddr, int keyVal)
931{
Bill Buzbeea114add2012-05-03 15:00:40 -0700932 SafeMap<unsigned int, LIR*>::iterator it;
933 it = cUnit->boundaryMap.find(vaddr);
934 if (it == cUnit->boundaryMap.end()) {
935 LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr;
936 }
937 LIR* newLabel = (LIR*)oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
938 newLabel->dalvikOffset = vaddr;
939 newLabel->opcode = kPseudoCaseLabel;
940 newLabel->operands[0] = keyVal;
941 oatInsertLIRAfter(it->second, (LIR*)newLabel);
942 return newLabel;
buzbee31a4a6f2012-02-28 15:36:15 -0800943}
944
945void markPackedCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
946{
Bill Buzbeea114add2012-05-03 15:00:40 -0700947 const u2* table = tabRec->table;
948 int baseVaddr = tabRec->vaddr;
949 int *targets = (int*)&table[4];
950 int entries = table[1];
951 int lowKey = s4FromSwitchData(&table[2]);
952 for (int i = 0; i < entries; i++) {
953 tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
954 i + lowKey);
955 }
buzbee31a4a6f2012-02-28 15:36:15 -0800956}
957
958void markSparseCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
959{
Bill Buzbeea114add2012-05-03 15:00:40 -0700960 const u2* table = tabRec->table;
961 int baseVaddr = tabRec->vaddr;
962 int entries = table[1];
963 int* keys = (int*)&table[2];
964 int* targets = &keys[entries];
965 for (int i = 0; i < entries; i++) {
966 tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
967 keys[i]);
968 }
buzbee31a4a6f2012-02-28 15:36:15 -0800969}
970
971void oatProcessSwitchTables(CompilationUnit* cUnit)
972{
Bill Buzbeea114add2012-05-03 15:00:40 -0700973 GrowableListIterator iterator;
974 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
975 while (true) {
976 SwitchTable *tabRec =
977 (SwitchTable *) oatGrowableListIteratorNext(&iterator);
978 if (tabRec == NULL) break;
979 if (tabRec->table[0] == Instruction::kPackedSwitchSignature) {
980 markPackedCaseLabels(cUnit, tabRec);
981 } else if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
982 markSparseCaseLabels(cUnit, tabRec);
983 } else {
984 LOG(FATAL) << "Invalid switch table";
buzbee31a4a6f2012-02-28 15:36:15 -0800985 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700986 }
buzbee31a4a6f2012-02-28 15:36:15 -0800987}
988
989//FIXME: Do we have endian issues here?
990
991void dumpSparseSwitchTable(const u2* table)
Bill Buzbeea114add2012-05-03 15:00:40 -0700992 /*
993 * Sparse switch data format:
994 * ushort ident = 0x0200 magic value
995 * ushort size number of entries in the table; > 0
996 * int keys[size] keys, sorted low-to-high; 32-bit aligned
997 * int targets[size] branch targets, relative to switch opcode
998 *
999 * Total size is (2+size*4) 16-bit code units.
1000 */
buzbee31a4a6f2012-02-28 15:36:15 -08001001{
Bill Buzbeea114add2012-05-03 15:00:40 -07001002 u2 ident = table[0];
1003 int entries = table[1];
1004 int* keys = (int*)&table[2];
1005 int* targets = &keys[entries];
1006 LOG(INFO) << "Sparse switch table - ident:0x" << std::hex << ident
1007 << ", entries: " << std::dec << entries;
1008 for (int i = 0; i < entries; i++) {
1009 LOG(INFO) << " Key[" << keys[i] << "] -> 0x" << std::hex << targets[i];
1010 }
buzbee31a4a6f2012-02-28 15:36:15 -08001011}
1012
1013void dumpPackedSwitchTable(const u2* table)
Bill Buzbeea114add2012-05-03 15:00:40 -07001014 /*
1015 * Packed switch data format:
1016 * ushort ident = 0x0100 magic value
1017 * ushort size number of entries in the table
1018 * int first_key first (and lowest) switch case value
1019 * int targets[size] branch targets, relative to switch opcode
1020 *
1021 * Total size is (4+size*2) 16-bit code units.
1022 */
buzbee31a4a6f2012-02-28 15:36:15 -08001023{
Bill Buzbeea114add2012-05-03 15:00:40 -07001024 u2 ident = table[0];
1025 int* targets = (int*)&table[4];
1026 int entries = table[1];
1027 int lowKey = s4FromSwitchData(&table[2]);
1028 LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident
1029 << ", entries: " << std::dec << entries << ", lowKey: " << lowKey;
1030 for (int i = 0; i < entries; i++) {
1031 LOG(INFO) << " Key[" << (i + lowKey) << "] -> 0x" << std::hex
1032 << targets[i];
1033 }
buzbee31a4a6f2012-02-28 15:36:15 -08001034}
buzbeee3acd072012-02-25 17:03:10 -08001035
buzbeed1643e42012-09-05 14:06:51 -07001036/*
1037 * Set up special LIR to mark a Dalvik byte-code instruction start and
1038 * record it in the boundaryMap. NOTE: in cases such as kMirOpCheck in
1039 * which we split a single Dalvik instruction, only the first MIR op
1040 * associated with a Dalvik PC should be entered into the map.
1041 */
1042LIR* markBoundary(CompilationUnit* cUnit, int offset, const char* instStr)
1043{
1044 LIR* res = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary, (intptr_t) instStr);
1045 if (cUnit->boundaryMap.find(offset) == cUnit->boundaryMap.end()) {
1046 cUnit->boundaryMap.Put(offset, res);
1047 }
1048 return res;
1049}
buzbeee3acd072012-02-25 17:03:10 -08001050
buzbeed1643e42012-09-05 14:06:51 -07001051}
1052 // namespace art