blob: b0a1e4437c4b2c7131180a778a54ca1386432cd7 [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 */
buzbeeec137432012-11-13 12:13:16 -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;
buzbee31a4a6f2012-02-28 15:36:15 -080096
Bill Buzbeea114add2012-05-03 15:00:40 -070097 if (opcode <= 0) {
98 lir->useMask = lir->defMask = 0;
99 return;
100 }
buzbee31a4a6f2012-02-28 15:36:15 -0800101
buzbeeec137432012-11-13 12:13:16 -0800102 uint64_t flags = EncodingMap[opcode].flags;
buzbee31a4a6f2012-02-28 15:36:15 -0800103
Bill Buzbeea114add2012-05-03 15:00:40 -0700104 if (flags & NEEDS_FIXUP) {
105 lir->flags.pcRelFixup = true;
106 }
buzbee31a4a6f2012-02-28 15:36:15 -0800107
Bill Buzbeea114add2012-05-03 15:00:40 -0700108 /* Get the starting size of the instruction's template */
109 lir->flags.size = oatGetInsnSize(lir);
buzbeee88dfbf2012-03-05 11:19:57 -0800110
Bill Buzbeea114add2012-05-03 15:00:40 -0700111 /* Set up the mask for resources that are updated */
112 if (flags & (IS_LOAD | IS_STORE)) {
113 /* Default to heap - will catch specialized classes later */
114 setMemRefType(lir, flags & IS_LOAD, kHeapRef);
115 }
buzbee31a4a6f2012-02-28 15:36:15 -0800116
Bill Buzbeea114add2012-05-03 15:00:40 -0700117 /*
118 * Conservatively assume the branch here will call out a function that in
119 * turn will trash everything.
120 */
121 if (flags & IS_BRANCH) {
122 lir->defMask = lir->useMask = ENCODE_ALL;
123 return;
124 }
buzbee31a4a6f2012-02-28 15:36:15 -0800125
Bill Buzbeea114add2012-05-03 15:00:40 -0700126 if (flags & REG_DEF0) {
buzbeeb046e162012-10-30 15:48:42 -0700127 setupRegMask(cUnit, &lir->defMask, lir->operands[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700128 }
buzbee31a4a6f2012-02-28 15:36:15 -0800129
Bill Buzbeea114add2012-05-03 15:00:40 -0700130 if (flags & REG_DEF1) {
buzbeeb046e162012-10-30 15:48:42 -0700131 setupRegMask(cUnit, &lir->defMask, lir->operands[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700132 }
buzbee31a4a6f2012-02-28 15:36:15 -0800133
buzbee31a4a6f2012-02-28 15:36:15 -0800134
Bill Buzbeea114add2012-05-03 15:00:40 -0700135 if (flags & SETS_CCODES) {
136 lir->defMask |= ENCODE_CCODE;
137 }
buzbee31a4a6f2012-02-28 15:36:15 -0800138
Bill Buzbeea114add2012-05-03 15:00:40 -0700139 if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) {
140 int i;
buzbee31a4a6f2012-02-28 15:36:15 -0800141
Bill Buzbeea114add2012-05-03 15:00:40 -0700142 for (i = 0; i < 4; i++) {
143 if (flags & (1 << (kRegUse0 + i))) {
buzbeeb046e162012-10-30 15:48:42 -0700144 setupRegMask(cUnit, &lir->useMask, lir->operands[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700145 }
buzbee31a4a6f2012-02-28 15:36:15 -0800146 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700147 }
buzbee31a4a6f2012-02-28 15:36:15 -0800148
Bill Buzbeea114add2012-05-03 15:00:40 -0700149 if (flags & USES_CCODES) {
150 lir->useMask |= ENCODE_CCODE;
151 }
buzbee31a4a6f2012-02-28 15:36:15 -0800152
buzbeeb046e162012-10-30 15:48:42 -0700153 // Handle target-specific actions
154 setupTargetResourceMasks(cUnit, lir);
buzbee31a4a6f2012-02-28 15:36:15 -0800155}
156
157/*
buzbee5de34942012-03-01 14:51:57 -0800158 * Debugging macros
159 */
160#define DUMP_RESOURCE_MASK(X)
161#define DUMP_SSA_REP(X)
162
163/* Pretty-print a LIR instruction */
164void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr)
165{
Bill Buzbeea114add2012-05-03 15:00:40 -0700166 LIR* lir = (LIR*) arg;
167 int offset = lir->offset;
168 int dest = lir->operands[0];
169 const bool dumpNop = (cUnit->enableDebug & (1 << kDebugShowNops));
buzbee5de34942012-03-01 14:51:57 -0800170
Bill Buzbeea114add2012-05-03 15:00:40 -0700171 /* Handle pseudo-ops individually, and all regular insns as a group */
172 switch (lir->opcode) {
173 case kPseudoMethodEntry:
174 LOG(INFO) << "-------- method entry "
175 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
176 break;
177 case kPseudoMethodExit:
178 LOG(INFO) << "-------- Method_Exit";
179 break;
180 case kPseudoBarrier:
181 LOG(INFO) << "-------- BARRIER";
182 break;
183 case kPseudoExtended:
184 LOG(INFO) << "-------- " << (char* ) dest;
185 break;
186 case kPseudoSSARep:
187 DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " << (char* ) dest);
188 break;
189 case kPseudoEntryBlock:
190 LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
191 break;
192 case kPseudoDalvikByteCodeBoundary:
193 LOG(INFO) << "-------- dalvik offset: 0x" << std::hex
194 << lir->dalvikOffset << " @ " << (char* )lir->operands[0];
195 break;
196 case kPseudoExitBlock:
197 LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
198 break;
199 case kPseudoPseudoAlign4:
200 LOG(INFO) << (intptr_t)baseAddr + offset << " (0x" << std::hex
201 << offset << "): .align4";
202 break;
203 case kPseudoEHBlockLabel:
204 LOG(INFO) << "Exception_Handling:";
205 break;
206 case kPseudoTargetLabel:
207 case kPseudoNormalBlockLabel:
208 LOG(INFO) << "L" << (void*)lir << ":";
209 break;
210 case kPseudoThrowTarget:
211 LOG(INFO) << "LT" << (void*)lir << ":";
212 break;
213 case kPseudoIntrinsicRetry:
214 LOG(INFO) << "IR" << (void*)lir << ":";
215 break;
216 case kPseudoSuspendTarget:
217 LOG(INFO) << "LS" << (void*)lir << ":";
218 break;
buzbee8320f382012-09-11 16:29:42 -0700219 case kPseudoSafepointPC:
220 LOG(INFO) << "LsafepointPC_0x" << std::hex << lir->offset << "_" << lir->dalvikOffset << ":";
221 break;
Bill Buzbeea5b30242012-09-28 07:19:44 -0700222 case kPseudoExportedPC:
223 LOG(INFO) << "LexportedPC_0x" << std::hex << lir->offset << "_" << lir->dalvikOffset << ":";
224 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700225 case kPseudoCaseLabel:
226 LOG(INFO) << "LC" << (void*)lir << ": Case target 0x"
227 << std::hex << lir->operands[0] << "|" << std::dec <<
228 lir->operands[0];
229 break;
230 default:
231 if (lir->flags.isNop && !dumpNop) {
232 break;
233 } else {
234 std::string op_name(buildInsnString(EncodingMap[lir->opcode].name,
235 lir, baseAddr));
236 std::string op_operands(buildInsnString(EncodingMap[lir->opcode].fmt
237 , lir, baseAddr));
238 LOG(INFO) << StringPrintf("%05x: %-9s%s%s",
239 (unsigned int)(baseAddr + offset),
240 op_name.c_str(), op_operands.c_str(),
241 lir->flags.isNop ? "(nop)" : "");
242 }
243 break;
244 }
buzbee5de34942012-03-01 14:51:57 -0800245
Bill Buzbeea114add2012-05-03 15:00:40 -0700246 if (lir->useMask && (!lir->flags.isNop || dumpNop)) {
247 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->useMask, "use"));
248 }
249 if (lir->defMask && (!lir->flags.isNop || dumpNop)) {
250 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->defMask, "def"));
251 }
buzbee5de34942012-03-01 14:51:57 -0800252}
253
254void oatDumpPromotionMap(CompilationUnit *cUnit)
255{
Bill Buzbeea114add2012-05-03 15:00:40 -0700256 int numRegs = cUnit->numDalvikRegisters + cUnit->numCompilerTemps + 1;
257 for (int i = 0; i < numRegs; i++) {
258 PromotionMap vRegMap = cUnit->promotionMap[i];
259 std::string buf;
260 if (vRegMap.fpLocation == kLocPhysReg) {
buzbeef0504cd2012-11-13 16:31:10 -0800261 StringAppendF(&buf, " : s%d", vRegMap.fpReg & fpRegMask());
buzbee5de34942012-03-01 14:51:57 -0800262 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700263
264 std::string buf3;
265 if (i < cUnit->numDalvikRegisters) {
266 StringAppendF(&buf3, "%02d", i);
267 } else if (i == cUnit->methodSReg) {
268 buf3 = "Method*";
269 } else {
270 StringAppendF(&buf3, "ct%d", i - cUnit->numDalvikRegisters);
271 }
272
273 LOG(INFO) << StringPrintf("V[%s] -> %s%d%s", buf3.c_str(),
274 vRegMap.coreLocation == kLocPhysReg ?
275 "r" : "SP+", vRegMap.coreLocation == kLocPhysReg ?
276 vRegMap.coreReg : oatSRegOffset(cUnit, i),
277 buf.c_str());
278 }
buzbee5de34942012-03-01 14:51:57 -0800279}
280
Bill Buzbeea5b30242012-09-28 07:19:44 -0700281/* Dump a mapping table */
282void dumpMappingTable(const char* table_name, const std::string& descriptor,
283 const std::string& name, const std::string& signature,
284 const std::vector<uint32_t>& v) {
285 if (v.size() > 0) {
286 std::string line(StringPrintf("\n %s %s%s_%s_table[%zu] = {", table_name,
287 descriptor.c_str(), name.c_str(), signature.c_str(), v.size()));
288 std::replace(line.begin(), line.end(), ';', '_');
289 LOG(INFO) << line;
290 for (uint32_t i = 0; i < v.size(); i+=2) {
291 line = StringPrintf(" {0x%05x, 0x%04x},", v[i], v[i+1]);
292 LOG(INFO) << line;
293 }
294 LOG(INFO) <<" };\n\n";
295 }
296}
297
buzbee5de34942012-03-01 14:51:57 -0800298/* Dump instructions and constant pool contents */
299void oatCodegenDump(CompilationUnit* cUnit)
300{
Bill Buzbeea114add2012-05-03 15:00:40 -0700301 LOG(INFO) << "Dumping LIR insns for "
302 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
303 LIR* lirInsn;
304 LIR* thisLIR;
305 int insnsSize = cUnit->insnsSize;
buzbee5de34942012-03-01 14:51:57 -0800306
Bill Buzbeea114add2012-05-03 15:00:40 -0700307 LOG(INFO) << "Regs (excluding ins) : " << cUnit->numRegs;
308 LOG(INFO) << "Ins : " << cUnit->numIns;
309 LOG(INFO) << "Outs : " << cUnit->numOuts;
310 LOG(INFO) << "CoreSpills : " << cUnit->numCoreSpills;
311 LOG(INFO) << "FPSpills : " << cUnit->numFPSpills;
312 LOG(INFO) << "CompilerTemps : " << cUnit->numCompilerTemps;
313 LOG(INFO) << "Frame size : " << cUnit->frameSize;
314 LOG(INFO) << "code size is " << cUnit->totalSize <<
315 " bytes, Dalvik size is " << insnsSize * 2;
316 LOG(INFO) << "expansion factor: "
317 << (float)cUnit->totalSize / (float)(insnsSize * 2);
318 oatDumpPromotionMap(cUnit);
319 for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
320 oatDumpLIRInsn(cUnit, lirInsn, 0);
321 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700322 for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
323 thisLIR = (LIR*) lirInsn;
324 LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)",
325 thisLIR->offset, thisLIR->offset,
326 thisLIR->operands[0]);
327 }
buzbee5de34942012-03-01 14:51:57 -0800328
Bill Buzbeea114add2012-05-03 15:00:40 -0700329 const DexFile::MethodId& method_id =
330 cUnit->dex_file->GetMethodId(cUnit->method_idx);
331 std::string signature(cUnit->dex_file->GetMethodSignature(method_id));
332 std::string name(cUnit->dex_file->GetMethodName(method_id));
333 std::string descriptor(cUnit->dex_file->GetMethodDeclaringClassDescriptor(method_id));
buzbee5de34942012-03-01 14:51:57 -0800334
Bill Buzbeea5b30242012-09-28 07:19:44 -0700335 // Dump mapping tables
336 dumpMappingTable("PC2Dex_MappingTable", descriptor, name, signature, cUnit->pc2dexMappingTable);
337 dumpMappingTable("Dex2PC_MappingTable", descriptor, name, signature, cUnit->dex2pcMappingTable);
buzbee5de34942012-03-01 14:51:57 -0800338}
339
buzbeea2ebdd72012-03-04 14:57:06 -0800340
341LIR* rawLIR(CompilationUnit* cUnit, int dalvikOffset, int opcode, int op0,
Bill Buzbeea114add2012-05-03 15:00:40 -0700342 int op1, int op2, int op3, int op4, LIR* target)
buzbeea2ebdd72012-03-04 14:57:06 -0800343{
Bill Buzbeea114add2012-05-03 15:00:40 -0700344 LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
345 insn->dalvikOffset = dalvikOffset;
346 insn->opcode = opcode;
347 insn->operands[0] = op0;
348 insn->operands[1] = op1;
349 insn->operands[2] = op2;
350 insn->operands[3] = op3;
351 insn->operands[4] = op4;
352 insn->target = target;
buzbeeb046e162012-10-30 15:48:42 -0700353 oatSetupResourceMasks(cUnit, insn);
Bill Buzbeea5b30242012-09-28 07:19:44 -0700354 if ((opcode == kPseudoTargetLabel) || (opcode == kPseudoSafepointPC) ||
355 (opcode == kPseudoExportedPC)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700356 // Always make labels scheduling barriers
buzbee8320f382012-09-11 16:29:42 -0700357 insn->useMask = insn->defMask = ENCODE_ALL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700358 }
359 return insn;
buzbeea2ebdd72012-03-04 14:57:06 -0800360}
361
buzbee5de34942012-03-01 14:51:57 -0800362/*
buzbee31a4a6f2012-02-28 15:36:15 -0800363 * The following are building blocks to construct low-level IRs with 0 - 4
364 * operands.
365 */
buzbee5de34942012-03-01 14:51:57 -0800366LIR* newLIR0(CompilationUnit* cUnit, int opcode)
buzbee31a4a6f2012-02-28 15:36:15 -0800367{
Bill Buzbeea114add2012-05-03 15:00:40 -0700368 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND))
369 << EncodingMap[opcode].name << " " << (int)opcode << " "
370 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
371 << cUnit->currentDalvikOffset;
372 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode);
373 oatAppendLIR(cUnit, (LIR*) insn);
374 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800375}
376
buzbee5de34942012-03-01 14:51:57 -0800377LIR* newLIR1(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700378 int dest)
buzbee31a4a6f2012-02-28 15:36:15 -0800379{
Bill Buzbeea114add2012-05-03 15:00:40 -0700380 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_UNARY_OP))
381 << EncodingMap[opcode].name << " " << (int)opcode << " "
382 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
383 << cUnit->currentDalvikOffset;
384 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest);
385 oatAppendLIR(cUnit, (LIR*) insn);
386 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800387}
388
buzbee5de34942012-03-01 14:51:57 -0800389LIR* newLIR2(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700390 int dest, int src1)
buzbee31a4a6f2012-02-28 15:36:15 -0800391{
Bill Buzbeea114add2012-05-03 15:00:40 -0700392 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_BINARY_OP))
393 << EncodingMap[opcode].name << " " << (int)opcode << " "
394 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
395 << cUnit->currentDalvikOffset;
396 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1);
397 oatAppendLIR(cUnit, (LIR*) insn);
398 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800399}
400
buzbee5de34942012-03-01 14:51:57 -0800401LIR* newLIR3(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700402 int dest, int src1, int src2)
buzbee31a4a6f2012-02-28 15:36:15 -0800403{
Bill Buzbeea114add2012-05-03 15:00:40 -0700404 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_TERTIARY_OP))
405 << EncodingMap[opcode].name << " " << (int)opcode << " "
406 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
407 << cUnit->currentDalvikOffset;
408 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
409 src2);
410 oatAppendLIR(cUnit, (LIR*) insn);
411 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800412}
413
buzbee5de34942012-03-01 14:51:57 -0800414LIR* newLIR4(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700415 int dest, int src1, int src2, int info)
buzbee31a4a6f2012-02-28 15:36:15 -0800416{
Bill Buzbeea114add2012-05-03 15:00:40 -0700417 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUAD_OP))
418 << EncodingMap[opcode].name << " " << (int)opcode << " "
419 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
420 << cUnit->currentDalvikOffset;
421 LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
422 src2, info);
423 oatAppendLIR(cUnit, (LIR*) insn);
424 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800425}
buzbee31a4a6f2012-02-28 15:36:15 -0800426
Ian Rogersb5d09b22012-03-06 22:14:17 -0800427LIR* newLIR5(CompilationUnit* cUnit, int opcode,
Bill Buzbeea114add2012-05-03 15:00:40 -0700428 int dest, int src1, int src2, int info1, int info2)
Ian Rogersb5d09b22012-03-06 22:14:17 -0800429{
Bill Buzbeea114add2012-05-03 15:00:40 -0700430 DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUIN_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 src2, info1, info2);
436 oatAppendLIR(cUnit, (LIR*) insn);
437 return insn;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800438}
439
buzbee31a4a6f2012-02-28 15:36:15 -0800440/*
441 * Search the existing constants in the literal pool for an exact or close match
442 * within specified delta (greater or equal to 0).
443 */
444LIR* scanLiteralPool(LIR* dataTarget, int value, unsigned int delta)
445{
Bill Buzbeea114add2012-05-03 15:00:40 -0700446 while (dataTarget) {
447 if (((unsigned) (value - ((LIR* ) dataTarget)->operands[0])) <= delta)
448 return (LIR* ) dataTarget;
449 dataTarget = dataTarget->next;
450 }
451 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800452}
453
454/* Search the existing constants in the literal pool for an exact wide match */
455LIR* scanLiteralPoolWide(LIR* dataTarget, int valLo, int valHi)
456{
Bill Buzbeea114add2012-05-03 15:00:40 -0700457 bool loMatch = false;
458 LIR* loTarget = NULL;
459 while (dataTarget) {
460 if (loMatch && (((LIR*)dataTarget)->operands[0] == valHi)) {
461 return (LIR*)loTarget;
buzbee31a4a6f2012-02-28 15:36:15 -0800462 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700463 loMatch = false;
464 if (((LIR*)dataTarget)->operands[0] == valLo) {
465 loMatch = true;
466 loTarget = dataTarget;
467 }
468 dataTarget = dataTarget->next;
469 }
470 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800471}
472
473/*
474 * The following are building blocks to insert constants into the pool or
475 * instruction streams.
476 */
477
buzbee5de34942012-03-01 14:51:57 -0800478/* Add a 32-bit constant either in the constant pool */
Ian Rogers3fa13792012-03-18 15:53:45 -0700479LIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP, int value)
buzbee31a4a6f2012-02-28 15:36:15 -0800480{
Bill Buzbeea114add2012-05-03 15:00:40 -0700481 /* Add the constant to the literal pool */
482 if (constantListP) {
483 LIR* newValue = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocData);
484 newValue->operands[0] = value;
485 newValue->next = *constantListP;
486 *constantListP = (LIR*) newValue;
487 return newValue;
488 }
489 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800490}
491
492/* Add a 64-bit constant to the constant pool or mixed with code */
493LIR* addWideData(CompilationUnit* cUnit, LIR* *constantListP,
Bill Buzbeea114add2012-05-03 15:00:40 -0700494 int valLo, int valHi)
buzbee31a4a6f2012-02-28 15:36:15 -0800495{
Bill Buzbeea114add2012-05-03 15:00:40 -0700496 //FIXME: hard-coded little endian, need BE variant
497 // Insert high word into list first
498 addWordData(cUnit, constantListP, valHi);
499 return addWordData(cUnit, constantListP, valLo);
buzbee31a4a6f2012-02-28 15:36:15 -0800500}
501
Ian Rogersab058bb2012-03-11 22:19:38 -0700502void pushWord(std::vector<uint8_t>&buf, int data) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700503 buf.push_back( data & 0xff);
504 buf.push_back( (data >> 8) & 0xff);
505 buf.push_back( (data >> 16) & 0xff);
506 buf.push_back( (data >> 24) & 0xff);
buzbeee3acd072012-02-25 17:03:10 -0800507}
508
Ian Rogersab058bb2012-03-11 22:19:38 -0700509void alignBuffer(std::vector<uint8_t>&buf, size_t offset) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700510 while (buf.size() < offset) {
511 buf.push_back(0);
512 }
buzbeee3acd072012-02-25 17:03:10 -0800513}
514
Brian Carlstromf5822582012-03-19 22:34:31 -0700515bool IsDirect(int invokeType) {
516 InvokeType type = static_cast<InvokeType>(invokeType);
517 return type == kStatic || type == kDirect;
518}
519
buzbeee3acd072012-02-25 17:03:10 -0800520/* Write the literal pool to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800521void installLiteralPools(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800522{
Bill Buzbeea114add2012-05-03 15:00:40 -0700523 alignBuffer(cUnit->codeBuffer, cUnit->dataOffset);
524 LIR* dataLIR = cUnit->literalList;
525 while (dataLIR != NULL) {
526 pushWord(cUnit->codeBuffer, dataLIR->operands[0]);
527 dataLIR = NEXT_LIR(dataLIR);
528 }
529 // Push code and method literals, record offsets for the compiler to patch.
530 dataLIR = cUnit->codeLiteralList;
Ian Rogers137e88f2012-10-08 17:46:47 -0700531 while (dataLIR != NULL) {
532 uint32_t target = dataLIR->operands[0];
533 cUnit->compiler->AddCodePatch(cUnit->dex_file,
534 cUnit->method_idx,
535 cUnit->invoke_type,
536 target,
537 static_cast<InvokeType>(dataLIR->operands[1]),
538 cUnit->codeBuffer.size());
539 const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target);
540 // unique based on target to ensure code deduplication works
541 uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
542 pushWord(cUnit->codeBuffer, unique_patch_value);
543 dataLIR = NEXT_LIR(dataLIR);
544 }
545 dataLIR = cUnit->methodLiteralList;
546 while (dataLIR != NULL) {
547 uint32_t target = dataLIR->operands[0];
548 cUnit->compiler->AddMethodPatch(cUnit->dex_file,
Bill Buzbeea114add2012-05-03 15:00:40 -0700549 cUnit->method_idx,
Ian Rogers08f753d2012-08-24 14:35:25 -0700550 cUnit->invoke_type,
Bill Buzbeea114add2012-05-03 15:00:40 -0700551 target,
Ian Rogers08f753d2012-08-24 14:35:25 -0700552 static_cast<InvokeType>(dataLIR->operands[1]),
Bill Buzbeea114add2012-05-03 15:00:40 -0700553 cUnit->codeBuffer.size());
Ian Rogers137e88f2012-10-08 17:46:47 -0700554 const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target);
555 // unique based on target to ensure code deduplication works
556 uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
557 pushWord(cUnit->codeBuffer, unique_patch_value);
558 dataLIR = NEXT_LIR(dataLIR);
Bill Buzbeea114add2012-05-03 15:00:40 -0700559 }
buzbeee3acd072012-02-25 17:03:10 -0800560}
561
562/* Write the switch tables to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800563void installSwitchTables(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800564{
Bill Buzbeea114add2012-05-03 15:00:40 -0700565 GrowableListIterator iterator;
566 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
567 while (true) {
568 SwitchTable* tabRec = (SwitchTable *) oatGrowableListIteratorNext(
569 &iterator);
570 if (tabRec == NULL) break;
571 alignBuffer(cUnit->codeBuffer, tabRec->offset);
572 /*
573 * For Arm, our reference point is the address of the bx
574 * instruction that does the launch, so we have to subtract
575 * the auto pc-advance. For other targets the reference point
576 * is a label, so we can use the offset as-is.
577 */
buzbeeb046e162012-10-30 15:48:42 -0700578 int bxOffset = INVALID_OFFSET;
579 switch (cUnit->instructionSet) {
580 case kThumb2:
581 bxOffset = tabRec->anchor->offset + 4;
582 break;
583 case kX86:
584 bxOffset = 0;
585 break;
586 case kMips:
587 bxOffset = tabRec->anchor->offset;
588 break;
589 default: LOG(FATAL) << "Unexpected instruction set: " << cUnit->instructionSet;
590 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700591 if (cUnit->printMe) {
592 LOG(INFO) << "Switch table for offset 0x" << std::hex << bxOffset;
buzbeee3acd072012-02-25 17:03:10 -0800593 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700594 if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
595 int* keys = (int*)&(tabRec->table[2]);
596 for (int elems = 0; elems < tabRec->table[1]; elems++) {
597 int disp = tabRec->targets[elems]->offset - bxOffset;
598 if (cUnit->printMe) {
599 LOG(INFO) << " Case[" << elems << "] key: 0x"
600 << std::hex << keys[elems] << ", disp: 0x"
601 << std::hex << disp;
602 }
603 pushWord(cUnit->codeBuffer, keys[elems]);
604 pushWord(cUnit->codeBuffer,
605 tabRec->targets[elems]->offset - bxOffset);
606 }
607 } else {
608 DCHECK_EQ(static_cast<int>(tabRec->table[0]),
609 static_cast<int>(Instruction::kPackedSwitchSignature));
610 for (int elems = 0; elems < tabRec->table[1]; elems++) {
611 int disp = tabRec->targets[elems]->offset - bxOffset;
612 if (cUnit->printMe) {
613 LOG(INFO) << " Case[" << elems << "] disp: 0x"
614 << std::hex << disp;
615 }
616 pushWord(cUnit->codeBuffer, tabRec->targets[elems]->offset - bxOffset);
617 }
618 }
619 }
buzbeee3acd072012-02-25 17:03:10 -0800620}
621
622/* Write the fill array dta to the output stream */
buzbee31a4a6f2012-02-28 15:36:15 -0800623void installFillArrayData(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800624{
Bill Buzbeea114add2012-05-03 15:00:40 -0700625 GrowableListIterator iterator;
626 oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
627 while (true) {
628 FillArrayData *tabRec = (FillArrayData *) oatGrowableListIteratorNext(
629 &iterator);
630 if (tabRec == NULL) break;
631 alignBuffer(cUnit->codeBuffer, tabRec->offset);
632 for (int i = 0; i < (tabRec->size + 1) / 2; i++) {
633 cUnit->codeBuffer.push_back( tabRec->table[i] & 0xFF);
634 cUnit->codeBuffer.push_back( (tabRec->table[i] >> 8) & 0xFF);
buzbeee3acd072012-02-25 17:03:10 -0800635 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700636 }
buzbeee3acd072012-02-25 17:03:10 -0800637}
638
buzbee31a4a6f2012-02-28 15:36:15 -0800639int assignLiteralOffsetCommon(LIR* lir, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800640{
Bill Buzbeea114add2012-05-03 15:00:40 -0700641 for (;lir != NULL; lir = lir->next) {
642 lir->offset = offset;
643 offset += 4;
644 }
645 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800646}
647
buzbee6459e7c2012-10-02 14:42:41 -0700648// Make sure we have a code address for every declared catch entry
649bool verifyCatchEntries(CompilationUnit* cUnit)
650{
651 bool success = true;
652 for (std::set<uint32_t>::const_iterator it = cUnit->catches.begin(); it != cUnit->catches.end(); ++it) {
653 uint32_t dexPc = *it;
654 bool found = false;
655 for (size_t i = 0; i < cUnit->dex2pcMappingTable.size(); i += 2) {
656 if (dexPc == cUnit->dex2pcMappingTable[i+1]) {
657 found = true;
658 break;
659 }
660 }
661 if (!found) {
662 LOG(INFO) << "Missing native PC for catch entry @ 0x" << std::hex << dexPc;
663 success = false;
664 }
665 }
666 // Now, try in the other direction
667 for (size_t i = 0; i < cUnit->dex2pcMappingTable.size(); i += 2) {
668 uint32_t dexPc = cUnit->dex2pcMappingTable[i+1];
669 if (cUnit->catches.find(dexPc) == cUnit->catches.end()) {
670 LOG(INFO) << "Unexpected catch entry @ dex pc 0x" << std::hex << dexPc;
671 success = false;
672 }
673 }
674 if (!success) {
675 LOG(INFO) << "Bad dex2pcMapping table in " << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
676 LOG(INFO) << "Entries @ decode: " << cUnit->catches.size() << ", Entries in table: "
677 << cUnit->dex2pcMappingTable.size()/2;
678 }
679 return success;
680}
681
Bill Buzbeea5b30242012-09-28 07:19:44 -0700682void createMappingTables(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -0800683{
buzbee8320f382012-09-11 16:29:42 -0700684 for (LIR* tgtLIR = (LIR *) cUnit->firstLIRInsn; tgtLIR != NULL; tgtLIR = NEXT_LIR(tgtLIR)) {
685 if (!tgtLIR->flags.isNop && (tgtLIR->opcode == kPseudoSafepointPC)) {
Bill Buzbeea5b30242012-09-28 07:19:44 -0700686 cUnit->pc2dexMappingTable.push_back(tgtLIR->offset);
687 cUnit->pc2dexMappingTable.push_back(tgtLIR->dalvikOffset);
688 }
689 if (!tgtLIR->flags.isNop && (tgtLIR->opcode == kPseudoExportedPC)) {
690 cUnit->dex2pcMappingTable.push_back(tgtLIR->offset);
691 cUnit->dex2pcMappingTable.push_back(tgtLIR->dalvikOffset);
buzbeee3acd072012-02-25 17:03:10 -0800692 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700693 }
buzbee6459e7c2012-10-02 14:42:41 -0700694 DCHECK(verifyCatchEntries(cUnit));
Bill Buzbeea5b30242012-09-28 07:19:44 -0700695 cUnit->combinedMappingTable.push_back(cUnit->pc2dexMappingTable.size() +
696 cUnit->dex2pcMappingTable.size());
697 cUnit->combinedMappingTable.push_back(cUnit->pc2dexMappingTable.size());
698 cUnit->combinedMappingTable.insert(cUnit->combinedMappingTable.end(),
699 cUnit->pc2dexMappingTable.begin(),
700 cUnit->pc2dexMappingTable.end());
701 cUnit->combinedMappingTable.insert(cUnit->combinedMappingTable.end(),
702 cUnit->dex2pcMappingTable.begin(),
703 cUnit->dex2pcMappingTable.end());
buzbeee3acd072012-02-25 17:03:10 -0800704}
705
Ian Rogers0c7abda2012-09-19 13:33:42 -0700706class NativePcToReferenceMapBuilder {
707 public:
708 NativePcToReferenceMapBuilder(std::vector<uint8_t>* table,
709 size_t entries, uint32_t max_native_offset,
710 size_t references_width) : entries_(entries),
711 references_width_(references_width), in_use_(entries),
712 table_(table) {
713 // Compute width in bytes needed to hold max_native_offset.
714 native_offset_width_ = 0;
715 while (max_native_offset != 0) {
716 native_offset_width_++;
717 max_native_offset >>= 8;
718 }
719 // Resize table and set up header.
720 table->resize((EntryWidth() * entries) + sizeof(uint32_t));
Ian Rogers000d7242012-09-21 16:07:36 -0700721 CHECK_LT(native_offset_width_, 1U << 3);
722 (*table)[0] = native_offset_width_ & 7;
723 CHECK_LT(references_width_, 1U << 13);
724 (*table)[0] |= (references_width_ << 3) & 0xFF;
725 (*table)[1] = (references_width_ >> 5) & 0xFF;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700726 CHECK_LT(entries, 1U << 16);
727 (*table)[2] = entries & 0xFF;
728 (*table)[3] = (entries >> 8) & 0xFF;
729 }
730
731 void AddEntry(uint32_t native_offset, const uint8_t* references) {
732 size_t table_index = TableIndex(native_offset);
733 while (in_use_[table_index]) {
734 table_index = (table_index + 1) % entries_;
735 }
736 in_use_[table_index] = true;
737 SetNativeOffset(table_index, native_offset);
738 DCHECK_EQ(native_offset, GetNativeOffset(table_index));
739 SetReferences(table_index, references);
740 }
741
742 private:
743 size_t TableIndex(uint32_t native_offset) {
744 return NativePcOffsetToReferenceMap::Hash(native_offset) % entries_;
745 }
746
747 uint32_t GetNativeOffset(size_t table_index) {
748 uint32_t native_offset = 0;
749 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
750 for (size_t i = 0; i < native_offset_width_; i++) {
751 native_offset |= (*table_)[table_offset + i] << (i * 8);
752 }
753 return native_offset;
754 }
755
756 void SetNativeOffset(size_t table_index, uint32_t native_offset) {
757 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
758 for (size_t i = 0; i < native_offset_width_; i++) {
759 (*table_)[table_offset + i] = (native_offset >> (i * 8)) & 0xFF;
760 }
761 }
762
763 void SetReferences(size_t table_index, const uint8_t* references) {
764 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
765 memcpy(&(*table_)[table_offset + native_offset_width_], references, references_width_);
766 }
767
768 size_t EntryWidth() const {
769 return native_offset_width_ + references_width_;
770 }
771
772 // Number of entries in the table.
773 const size_t entries_;
774 // Number of bytes used to encode the reference bitmap.
775 const size_t references_width_;
776 // Number of bytes used to encode a native offset.
777 size_t native_offset_width_;
778 // Entries that are in use.
779 std::vector<bool> in_use_;
780 // The table we're building.
781 std::vector<uint8_t>* const table_;
782};
783
784static void createNativeGcMap(CompilationUnit* cUnit) {
Bill Buzbeea5b30242012-09-28 07:19:44 -0700785 const std::vector<uint32_t>& mapping_table = cUnit->pc2dexMappingTable;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700786 uint32_t max_native_offset = 0;
787 for (size_t i = 0; i < mapping_table.size(); i += 2) {
788 uint32_t native_offset = mapping_table[i + 0];
789 if (native_offset > max_native_offset) {
790 max_native_offset = native_offset;
791 }
792 }
793 Compiler::MethodReference method_ref(cUnit->dex_file, cUnit->method_idx);
794 const std::vector<uint8_t>* gc_map_raw = verifier::MethodVerifier::GetDexGcMap(method_ref);
795 verifier::DexPcToReferenceMap dex_gc_map(&(*gc_map_raw)[4], gc_map_raw->size() - 4);
796 // Compute native offset to references size.
797 NativePcToReferenceMapBuilder native_gc_map_builder(&cUnit->nativeGcMap,
798 mapping_table.size() / 2, max_native_offset,
799 dex_gc_map.RegWidth());
800
801 for (size_t i = 0; i < mapping_table.size(); i += 2) {
802 uint32_t native_offset = mapping_table[i + 0];
803 uint32_t dex_pc = mapping_table[i + 1];
804 const uint8_t* references = dex_gc_map.FindBitMap(dex_pc, false);
Bill Buzbeea5b30242012-09-28 07:19:44 -0700805 CHECK(references != NULL) << "Missing ref for dex pc 0x" << std::hex << dex_pc;
806 native_gc_map_builder.AddEntry(native_offset, references);
Ian Rogers0c7abda2012-09-19 13:33:42 -0700807 }
808}
809
buzbeee3acd072012-02-25 17:03:10 -0800810/* Determine the offset of each literal field */
buzbee31a4a6f2012-02-28 15:36:15 -0800811int assignLiteralOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800812{
Bill Buzbeea114add2012-05-03 15:00:40 -0700813 offset = assignLiteralOffsetCommon(cUnit->literalList, offset);
814 offset = assignLiteralOffsetCommon(cUnit->codeLiteralList, offset);
815 offset = assignLiteralOffsetCommon(cUnit->methodLiteralList, offset);
816 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800817}
818
buzbee31a4a6f2012-02-28 15:36:15 -0800819int assignSwitchTablesOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800820{
Bill Buzbeea114add2012-05-03 15:00:40 -0700821 GrowableListIterator iterator;
822 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
823 while (true) {
824 SwitchTable *tabRec = (SwitchTable *) oatGrowableListIteratorNext(
825 &iterator);
826 if (tabRec == NULL) break;
827 tabRec->offset = offset;
828 if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
829 offset += tabRec->table[1] * (sizeof(int) * 2);
830 } else {
831 DCHECK_EQ(static_cast<int>(tabRec->table[0]),
832 static_cast<int>(Instruction::kPackedSwitchSignature));
833 offset += tabRec->table[1] * sizeof(int);
buzbeee3acd072012-02-25 17:03:10 -0800834 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700835 }
836 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800837}
838
buzbee31a4a6f2012-02-28 15:36:15 -0800839int assignFillArrayDataOffset(CompilationUnit* cUnit, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800840{
Bill Buzbeea114add2012-05-03 15:00:40 -0700841 GrowableListIterator iterator;
842 oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
843 while (true) {
844 FillArrayData *tabRec = (FillArrayData *) oatGrowableListIteratorNext(
845 &iterator);
846 if (tabRec == NULL) break;
847 tabRec->offset = offset;
848 offset += tabRec->size;
849 // word align
850 offset = (offset + 3) & ~3;
851 }
852 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800853}
854
855/*
856 * Walk the compilation unit and assign offsets to instructions
857 * and literals and compute the total size of the compiled unit.
858 */
859void oatAssignOffsets(CompilationUnit* cUnit)
860{
Bill Buzbeea114add2012-05-03 15:00:40 -0700861 int offset = oatAssignInsnOffsets(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800862
Bill Buzbeea114add2012-05-03 15:00:40 -0700863 /* Const values have to be word aligned */
864 offset = (offset + 3) & ~3;
buzbeee3acd072012-02-25 17:03:10 -0800865
Bill Buzbeea114add2012-05-03 15:00:40 -0700866 /* Set up offsets for literals */
867 cUnit->dataOffset = offset;
buzbeee3acd072012-02-25 17:03:10 -0800868
Bill Buzbeea114add2012-05-03 15:00:40 -0700869 offset = assignLiteralOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800870
Bill Buzbeea114add2012-05-03 15:00:40 -0700871 offset = assignSwitchTablesOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800872
Bill Buzbeea114add2012-05-03 15:00:40 -0700873 offset = assignFillArrayDataOffset(cUnit, offset);
buzbeee3acd072012-02-25 17:03:10 -0800874
Bill Buzbeea114add2012-05-03 15:00:40 -0700875 cUnit->totalSize = offset;
buzbeee3acd072012-02-25 17:03:10 -0800876}
877
878/*
879 * Go over each instruction in the list and calculate the offset from the top
880 * before sending them off to the assembler. If out-of-range branch distance is
881 * seen rearrange the instructions a bit to correct it.
882 */
883void oatAssembleLIR(CompilationUnit* cUnit)
884{
Bill Buzbeea114add2012-05-03 15:00:40 -0700885 oatAssignOffsets(cUnit);
886 /*
887 * Assemble here. Note that we generate code with optimistic assumptions
888 * and if found now to work, we'll have to redo the sequence and retry.
889 */
buzbeee3acd072012-02-25 17:03:10 -0800890
Bill Buzbeea114add2012-05-03 15:00:40 -0700891 while (true) {
892 AssemblerStatus res = oatAssembleInstructions(cUnit, 0);
893 if (res == kSuccess) {
894 break;
895 } else {
896 cUnit->assemblerRetries++;
897 if (cUnit->assemblerRetries > MAX_ASSEMBLER_RETRIES) {
898 oatCodegenDump(cUnit);
899 LOG(FATAL) << "Assembler error - too many retries";
900 }
901 // Redo offsets and try again
902 oatAssignOffsets(cUnit);
903 cUnit->codeBuffer.clear();
buzbeee3acd072012-02-25 17:03:10 -0800904 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700905 }
buzbeee3acd072012-02-25 17:03:10 -0800906
Bill Buzbeea114add2012-05-03 15:00:40 -0700907 // Install literals
908 installLiteralPools(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800909
Bill Buzbeea114add2012-05-03 15:00:40 -0700910 // Install switch tables
911 installSwitchTables(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800912
Bill Buzbeea114add2012-05-03 15:00:40 -0700913 // Install fill array data
914 installFillArrayData(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800915
Ian Rogers0c7abda2012-09-19 13:33:42 -0700916 // Create the mapping table and native offset to reference map.
Bill Buzbeea5b30242012-09-28 07:19:44 -0700917 createMappingTables(cUnit);
Ian Rogers0c7abda2012-09-19 13:33:42 -0700918
919 createNativeGcMap(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800920}
921
buzbee31a4a6f2012-02-28 15:36:15 -0800922/*
923 * Insert a kPseudoCaseLabel at the beginning of the Dalvik
924 * offset vaddr. This label will be used to fix up the case
925 * branch table during the assembly phase. Be sure to set
926 * all resource flags on this to prevent code motion across
927 * target boundaries. KeyVal is just there for debugging.
928 */
929LIR* insertCaseLabel(CompilationUnit* cUnit, int vaddr, int keyVal)
930{
Bill Buzbeea114add2012-05-03 15:00:40 -0700931 SafeMap<unsigned int, LIR*>::iterator it;
932 it = cUnit->boundaryMap.find(vaddr);
933 if (it == cUnit->boundaryMap.end()) {
934 LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr;
935 }
936 LIR* newLabel = (LIR*)oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
937 newLabel->dalvikOffset = vaddr;
938 newLabel->opcode = kPseudoCaseLabel;
939 newLabel->operands[0] = keyVal;
940 oatInsertLIRAfter(it->second, (LIR*)newLabel);
941 return newLabel;
buzbee31a4a6f2012-02-28 15:36:15 -0800942}
943
944void markPackedCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
945{
Bill Buzbeea114add2012-05-03 15:00:40 -0700946 const u2* table = tabRec->table;
947 int baseVaddr = tabRec->vaddr;
948 int *targets = (int*)&table[4];
949 int entries = table[1];
950 int lowKey = s4FromSwitchData(&table[2]);
951 for (int i = 0; i < entries; i++) {
952 tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
953 i + lowKey);
954 }
buzbee31a4a6f2012-02-28 15:36:15 -0800955}
956
957void markSparseCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
958{
Bill Buzbeea114add2012-05-03 15:00:40 -0700959 const u2* table = tabRec->table;
960 int baseVaddr = tabRec->vaddr;
961 int entries = table[1];
962 int* keys = (int*)&table[2];
963 int* targets = &keys[entries];
964 for (int i = 0; i < entries; i++) {
965 tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
966 keys[i]);
967 }
buzbee31a4a6f2012-02-28 15:36:15 -0800968}
969
970void oatProcessSwitchTables(CompilationUnit* cUnit)
971{
Bill Buzbeea114add2012-05-03 15:00:40 -0700972 GrowableListIterator iterator;
973 oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
974 while (true) {
975 SwitchTable *tabRec =
976 (SwitchTable *) oatGrowableListIteratorNext(&iterator);
977 if (tabRec == NULL) break;
978 if (tabRec->table[0] == Instruction::kPackedSwitchSignature) {
979 markPackedCaseLabels(cUnit, tabRec);
980 } else if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
981 markSparseCaseLabels(cUnit, tabRec);
982 } else {
983 LOG(FATAL) << "Invalid switch table";
buzbee31a4a6f2012-02-28 15:36:15 -0800984 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700985 }
buzbee31a4a6f2012-02-28 15:36:15 -0800986}
987
988//FIXME: Do we have endian issues here?
989
990void dumpSparseSwitchTable(const u2* table)
Bill Buzbeea114add2012-05-03 15:00:40 -0700991 /*
992 * Sparse switch data format:
993 * ushort ident = 0x0200 magic value
994 * ushort size number of entries in the table; > 0
995 * int keys[size] keys, sorted low-to-high; 32-bit aligned
996 * int targets[size] branch targets, relative to switch opcode
997 *
998 * Total size is (2+size*4) 16-bit code units.
999 */
buzbee31a4a6f2012-02-28 15:36:15 -08001000{
Bill Buzbeea114add2012-05-03 15:00:40 -07001001 u2 ident = table[0];
1002 int entries = table[1];
1003 int* keys = (int*)&table[2];
1004 int* targets = &keys[entries];
1005 LOG(INFO) << "Sparse switch table - ident:0x" << std::hex << ident
1006 << ", entries: " << std::dec << entries;
1007 for (int i = 0; i < entries; i++) {
1008 LOG(INFO) << " Key[" << keys[i] << "] -> 0x" << std::hex << targets[i];
1009 }
buzbee31a4a6f2012-02-28 15:36:15 -08001010}
1011
1012void dumpPackedSwitchTable(const u2* table)
Bill Buzbeea114add2012-05-03 15:00:40 -07001013 /*
1014 * Packed switch data format:
1015 * ushort ident = 0x0100 magic value
1016 * ushort size number of entries in the table
1017 * int first_key first (and lowest) switch case value
1018 * int targets[size] branch targets, relative to switch opcode
1019 *
1020 * Total size is (4+size*2) 16-bit code units.
1021 */
buzbee31a4a6f2012-02-28 15:36:15 -08001022{
Bill Buzbeea114add2012-05-03 15:00:40 -07001023 u2 ident = table[0];
1024 int* targets = (int*)&table[4];
1025 int entries = table[1];
1026 int lowKey = s4FromSwitchData(&table[2]);
1027 LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident
1028 << ", entries: " << std::dec << entries << ", lowKey: " << lowKey;
1029 for (int i = 0; i < entries; i++) {
1030 LOG(INFO) << " Key[" << (i + lowKey) << "] -> 0x" << std::hex
1031 << targets[i];
1032 }
buzbee31a4a6f2012-02-28 15:36:15 -08001033}
buzbeee3acd072012-02-25 17:03:10 -08001034
buzbeed1643e42012-09-05 14:06:51 -07001035/*
1036 * Set up special LIR to mark a Dalvik byte-code instruction start and
1037 * record it in the boundaryMap. NOTE: in cases such as kMirOpCheck in
1038 * which we split a single Dalvik instruction, only the first MIR op
1039 * associated with a Dalvik PC should be entered into the map.
1040 */
1041LIR* markBoundary(CompilationUnit* cUnit, int offset, const char* instStr)
1042{
1043 LIR* res = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary, (intptr_t) instStr);
1044 if (cUnit->boundaryMap.find(offset) == cUnit->boundaryMap.end()) {
1045 cUnit->boundaryMap.Put(offset, res);
1046 }
1047 return res;
1048}
buzbeee3acd072012-02-25 17:03:10 -08001049
buzbeed1643e42012-09-05 14:06:51 -07001050}
1051 // namespace art