blob: 517d1b5c03986b76c3917968f4b48256776dac4a [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
buzbee395116c2013-02-27 14:30:25 -080017#include "compiler/dex/compiler_internals.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070018#include "dex_file-inl.h"
Ian Rogers0c7abda2012-09-19 13:33:42 -070019#include "gc_map.h"
20#include "verifier/dex_gc_map.h"
21#include "verifier/method_verifier.h"
22
buzbeee3acd072012-02-25 17:03:10 -080023namespace art {
24
buzbee1fd33462013-03-25 13:40:45 -070025bool Mir2Lir::IsInexpensiveConstant(RegLocation rl_src)
buzbee4ef3e452012-12-14 13:35:28 -080026{
27 bool res = false;
28 if (rl_src.is_const) {
29 if (rl_src.wide) {
30 if (rl_src.fp) {
buzbee1fd33462013-03-25 13:40:45 -070031 res = InexpensiveConstantDouble(mir_graph_->ConstantValueWide(rl_src));
buzbee4ef3e452012-12-14 13:35:28 -080032 } else {
buzbee1fd33462013-03-25 13:40:45 -070033 res = InexpensiveConstantLong(mir_graph_->ConstantValueWide(rl_src));
buzbee4ef3e452012-12-14 13:35:28 -080034 }
35 } else {
36 if (rl_src.fp) {
buzbee1fd33462013-03-25 13:40:45 -070037 res = InexpensiveConstantFloat(mir_graph_->ConstantValue(rl_src));
buzbee4ef3e452012-12-14 13:35:28 -080038 } else {
buzbee1fd33462013-03-25 13:40:45 -070039 res = InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src));
buzbee4ef3e452012-12-14 13:35:28 -080040 }
41 }
42 }
43 return res;
44}
45
buzbee1fd33462013-03-25 13:40:45 -070046void Mir2Lir::MarkSafepointPC(LIR* inst)
buzbee02031b12012-11-23 09:41:35 -080047{
48 inst->def_mask = ENCODE_ALL;
buzbee1fd33462013-03-25 13:40:45 -070049 LIR* safepoint_pc = NewLIR0(kPseudoSafepointPC);
buzbee02031b12012-11-23 09:41:35 -080050 DCHECK_EQ(safepoint_pc->def_mask, ENCODE_ALL);
51}
52
buzbee1fd33462013-03-25 13:40:45 -070053bool Mir2Lir::FastInstance(uint32_t field_idx, int& field_offset, bool& is_volatile, bool is_put)
buzbee02031b12012-11-23 09:41:35 -080054{
buzbee1fd33462013-03-25 13:40:45 -070055 return cu_->compiler_driver->ComputeInstanceFieldInfo(
56 field_idx, mir_graph_->GetCurrentDexCompilationUnit(), field_offset, is_volatile, is_put);
buzbee02031b12012-11-23 09:41:35 -080057}
58
buzbeecbd6d442012-11-17 14:11:25 -080059/* Convert an instruction to a NOP */
buzbee1fd33462013-03-25 13:40:45 -070060void Mir2Lir::NopLIR( LIR* lir)
buzbeecbd6d442012-11-17 14:11:25 -080061{
buzbeefa57c472012-11-21 12:06:18 -080062 lir->flags.is_nop = true;
buzbeecbd6d442012-11-17 14:11:25 -080063}
64
buzbee1fd33462013-03-25 13:40:45 -070065void Mir2Lir::SetMemRefType(LIR* lir, bool is_load, int mem_type)
buzbee31a4a6f2012-02-28 15:36:15 -080066{
buzbeefa57c472012-11-21 12:06:18 -080067 uint64_t *mask_ptr;
buzbeeeaf09bc2012-11-15 14:51:41 -080068 uint64_t mask = ENCODE_MEM;;
buzbee1fd33462013-03-25 13:40:45 -070069 DCHECK(GetTargetInstFlags(lir->opcode) & (IS_LOAD | IS_STORE));
buzbeefa57c472012-11-21 12:06:18 -080070 if (is_load) {
71 mask_ptr = &lir->use_mask;
Bill Buzbeea114add2012-05-03 15:00:40 -070072 } else {
buzbeefa57c472012-11-21 12:06:18 -080073 mask_ptr = &lir->def_mask;
Bill Buzbeea114add2012-05-03 15:00:40 -070074 }
75 /* Clear out the memref flags */
buzbeefa57c472012-11-21 12:06:18 -080076 *mask_ptr &= ~mask;
Bill Buzbeea114add2012-05-03 15:00:40 -070077 /* ..and then add back the one we need */
buzbeefa57c472012-11-21 12:06:18 -080078 switch (mem_type) {
Bill Buzbeea114add2012-05-03 15:00:40 -070079 case kLiteral:
buzbeefa57c472012-11-21 12:06:18 -080080 DCHECK(is_load);
81 *mask_ptr |= ENCODE_LITERAL;
Bill Buzbeea114add2012-05-03 15:00:40 -070082 break;
83 case kDalvikReg:
buzbeefa57c472012-11-21 12:06:18 -080084 *mask_ptr |= ENCODE_DALVIK_REG;
Bill Buzbeea114add2012-05-03 15:00:40 -070085 break;
86 case kHeapRef:
buzbeefa57c472012-11-21 12:06:18 -080087 *mask_ptr |= ENCODE_HEAP_REF;
Bill Buzbeea114add2012-05-03 15:00:40 -070088 break;
89 case kMustNotAlias:
90 /* Currently only loads can be marked as kMustNotAlias */
buzbee1fd33462013-03-25 13:40:45 -070091 DCHECK(!(GetTargetInstFlags(lir->opcode) & IS_STORE));
buzbeefa57c472012-11-21 12:06:18 -080092 *mask_ptr |= ENCODE_MUST_NOT_ALIAS;
Bill Buzbeea114add2012-05-03 15:00:40 -070093 break;
94 default:
buzbeefa57c472012-11-21 12:06:18 -080095 LOG(FATAL) << "Oat: invalid memref kind - " << mem_type;
Bill Buzbeea114add2012-05-03 15:00:40 -070096 }
buzbee31a4a6f2012-02-28 15:36:15 -080097}
98
99/*
Ian Rogersb5d09b22012-03-06 22:14:17 -0800100 * Mark load/store instructions that access Dalvik registers through the stack.
buzbee31a4a6f2012-02-28 15:36:15 -0800101 */
buzbee1fd33462013-03-25 13:40:45 -0700102void Mir2Lir::AnnotateDalvikRegAccess(LIR* lir, int reg_id, bool is_load,
103 bool is64bit)
buzbee31a4a6f2012-02-28 15:36:15 -0800104{
buzbee1fd33462013-03-25 13:40:45 -0700105 SetMemRefType(lir, is_load, kDalvikReg);
buzbee31a4a6f2012-02-28 15:36:15 -0800106
Bill Buzbeea114add2012-05-03 15:00:40 -0700107 /*
buzbeefa57c472012-11-21 12:06:18 -0800108 * Store the Dalvik register id in alias_info. Mark the MSB if it is a 64-bit
Bill Buzbeea114add2012-05-03 15:00:40 -0700109 * access.
110 */
buzbeefa57c472012-11-21 12:06:18 -0800111 lir->alias_info = ENCODE_ALIAS_INFO(reg_id, is64bit);
buzbee31a4a6f2012-02-28 15:36:15 -0800112}
113
114/*
115 * Mark the corresponding bit(s).
116 */
buzbee1fd33462013-03-25 13:40:45 -0700117void Mir2Lir::SetupRegMask(uint64_t* mask, int reg)
buzbee31a4a6f2012-02-28 15:36:15 -0800118{
buzbee1fd33462013-03-25 13:40:45 -0700119 *mask |= GetRegMaskCommon(reg);
buzbee31a4a6f2012-02-28 15:36:15 -0800120}
121
122/*
123 * Set up the proper fields in the resource mask
124 */
buzbee1fd33462013-03-25 13:40:45 -0700125void Mir2Lir::SetupResourceMasks(LIR* lir)
buzbee31a4a6f2012-02-28 15:36:15 -0800126{
Bill Buzbeea114add2012-05-03 15:00:40 -0700127 int opcode = lir->opcode;
buzbee31a4a6f2012-02-28 15:36:15 -0800128
Bill Buzbeea114add2012-05-03 15:00:40 -0700129 if (opcode <= 0) {
buzbeefa57c472012-11-21 12:06:18 -0800130 lir->use_mask = lir->def_mask = 0;
Bill Buzbeea114add2012-05-03 15:00:40 -0700131 return;
132 }
buzbee31a4a6f2012-02-28 15:36:15 -0800133
buzbee1fd33462013-03-25 13:40:45 -0700134 uint64_t flags = GetTargetInstFlags(opcode);
buzbee31a4a6f2012-02-28 15:36:15 -0800135
Bill Buzbeea114add2012-05-03 15:00:40 -0700136 if (flags & NEEDS_FIXUP) {
137 lir->flags.pcRelFixup = true;
138 }
buzbee31a4a6f2012-02-28 15:36:15 -0800139
Bill Buzbeea114add2012-05-03 15:00:40 -0700140 /* Get the starting size of the instruction's template */
buzbee1fd33462013-03-25 13:40:45 -0700141 lir->flags.size = GetInsnSize(lir);
buzbeee88dfbf2012-03-05 11:19:57 -0800142
Bill Buzbeea114add2012-05-03 15:00:40 -0700143 /* Set up the mask for resources that are updated */
144 if (flags & (IS_LOAD | IS_STORE)) {
145 /* Default to heap - will catch specialized classes later */
buzbee1fd33462013-03-25 13:40:45 -0700146 SetMemRefType(lir, flags & IS_LOAD, kHeapRef);
Bill Buzbeea114add2012-05-03 15:00:40 -0700147 }
buzbee31a4a6f2012-02-28 15:36:15 -0800148
Bill Buzbeea114add2012-05-03 15:00:40 -0700149 /*
150 * Conservatively assume the branch here will call out a function that in
151 * turn will trash everything.
152 */
153 if (flags & IS_BRANCH) {
buzbeefa57c472012-11-21 12:06:18 -0800154 lir->def_mask = lir->use_mask = ENCODE_ALL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700155 return;
156 }
buzbee31a4a6f2012-02-28 15:36:15 -0800157
Bill Buzbeea114add2012-05-03 15:00:40 -0700158 if (flags & REG_DEF0) {
buzbee1fd33462013-03-25 13:40:45 -0700159 SetupRegMask(&lir->def_mask, lir->operands[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700160 }
buzbee31a4a6f2012-02-28 15:36:15 -0800161
Bill Buzbeea114add2012-05-03 15:00:40 -0700162 if (flags & REG_DEF1) {
buzbee1fd33462013-03-25 13:40:45 -0700163 SetupRegMask(&lir->def_mask, lir->operands[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700164 }
buzbee31a4a6f2012-02-28 15:36:15 -0800165
buzbee31a4a6f2012-02-28 15:36:15 -0800166
Bill Buzbeea114add2012-05-03 15:00:40 -0700167 if (flags & SETS_CCODES) {
buzbeefa57c472012-11-21 12:06:18 -0800168 lir->def_mask |= ENCODE_CCODE;
Bill Buzbeea114add2012-05-03 15:00:40 -0700169 }
buzbee31a4a6f2012-02-28 15:36:15 -0800170
Bill Buzbeea114add2012-05-03 15:00:40 -0700171 if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) {
172 int i;
buzbee31a4a6f2012-02-28 15:36:15 -0800173
Bill Buzbeea114add2012-05-03 15:00:40 -0700174 for (i = 0; i < 4; i++) {
175 if (flags & (1 << (kRegUse0 + i))) {
buzbee1fd33462013-03-25 13:40:45 -0700176 SetupRegMask(&lir->use_mask, lir->operands[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700177 }
buzbee31a4a6f2012-02-28 15:36:15 -0800178 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700179 }
buzbee31a4a6f2012-02-28 15:36:15 -0800180
Bill Buzbeea114add2012-05-03 15:00:40 -0700181 if (flags & USES_CCODES) {
buzbeefa57c472012-11-21 12:06:18 -0800182 lir->use_mask |= ENCODE_CCODE;
Bill Buzbeea114add2012-05-03 15:00:40 -0700183 }
buzbee31a4a6f2012-02-28 15:36:15 -0800184
buzbeeb046e162012-10-30 15:48:42 -0700185 // Handle target-specific actions
buzbee1fd33462013-03-25 13:40:45 -0700186 SetupTargetResourceMasks(lir);
buzbee31a4a6f2012-02-28 15:36:15 -0800187}
188
189/*
buzbee5de34942012-03-01 14:51:57 -0800190 * Debugging macros
191 */
192#define DUMP_RESOURCE_MASK(X)
buzbee5de34942012-03-01 14:51:57 -0800193
194/* Pretty-print a LIR instruction */
buzbee1fd33462013-03-25 13:40:45 -0700195void Mir2Lir::DumpLIRInsn(LIR* lir, unsigned char* base_addr)
buzbee5de34942012-03-01 14:51:57 -0800196{
Bill Buzbeea114add2012-05-03 15:00:40 -0700197 int offset = lir->offset;
198 int dest = lir->operands[0];
buzbee1fd33462013-03-25 13:40:45 -0700199 const bool dump_nop = (cu_->enable_debug & (1 << kDebugShowNops));
buzbee5de34942012-03-01 14:51:57 -0800200
Bill Buzbeea114add2012-05-03 15:00:40 -0700201 /* Handle pseudo-ops individually, and all regular insns as a group */
202 switch (lir->opcode) {
203 case kPseudoMethodEntry:
204 LOG(INFO) << "-------- method entry "
buzbee1fd33462013-03-25 13:40:45 -0700205 << PrettyMethod(cu_->method_idx, *cu_->dex_file);
Bill Buzbeea114add2012-05-03 15:00:40 -0700206 break;
207 case kPseudoMethodExit:
208 LOG(INFO) << "-------- Method_Exit";
209 break;
210 case kPseudoBarrier:
211 LOG(INFO) << "-------- BARRIER";
212 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700213 case kPseudoEntryBlock:
214 LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
215 break;
216 case kPseudoDalvikByteCodeBoundary:
buzbee4ef3e452012-12-14 13:35:28 -0800217 if (lir->operands[0] == 0) {
218 lir->operands[0] = reinterpret_cast<uintptr_t>("No instruction string");
219 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700220 LOG(INFO) << "-------- dalvik offset: 0x" << std::hex
buzbeefa57c472012-11-21 12:06:18 -0800221 << lir->dalvik_offset << " @ " << reinterpret_cast<char*>(lir->operands[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700222 break;
223 case kPseudoExitBlock:
224 LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
225 break;
226 case kPseudoPseudoAlign4:
buzbeefa57c472012-11-21 12:06:18 -0800227 LOG(INFO) << reinterpret_cast<uintptr_t>(base_addr) + offset << " (0x" << std::hex
Bill Buzbeea114add2012-05-03 15:00:40 -0700228 << offset << "): .align4";
229 break;
230 case kPseudoEHBlockLabel:
231 LOG(INFO) << "Exception_Handling:";
232 break;
233 case kPseudoTargetLabel:
234 case kPseudoNormalBlockLabel:
buzbeecbd6d442012-11-17 14:11:25 -0800235 LOG(INFO) << "L" << reinterpret_cast<void*>(lir) << ":";
Bill Buzbeea114add2012-05-03 15:00:40 -0700236 break;
237 case kPseudoThrowTarget:
buzbeecbd6d442012-11-17 14:11:25 -0800238 LOG(INFO) << "LT" << reinterpret_cast<void*>(lir) << ":";
Bill Buzbeea114add2012-05-03 15:00:40 -0700239 break;
240 case kPseudoIntrinsicRetry:
buzbeecbd6d442012-11-17 14:11:25 -0800241 LOG(INFO) << "IR" << reinterpret_cast<void*>(lir) << ":";
Bill Buzbeea114add2012-05-03 15:00:40 -0700242 break;
243 case kPseudoSuspendTarget:
buzbeecbd6d442012-11-17 14:11:25 -0800244 LOG(INFO) << "LS" << reinterpret_cast<void*>(lir) << ":";
Bill Buzbeea114add2012-05-03 15:00:40 -0700245 break;
buzbee8320f382012-09-11 16:29:42 -0700246 case kPseudoSafepointPC:
buzbeefa57c472012-11-21 12:06:18 -0800247 LOG(INFO) << "LsafepointPC_0x" << std::hex << lir->offset << "_" << lir->dalvik_offset << ":";
buzbee8320f382012-09-11 16:29:42 -0700248 break;
Bill Buzbeea5b30242012-09-28 07:19:44 -0700249 case kPseudoExportedPC:
buzbeefa57c472012-11-21 12:06:18 -0800250 LOG(INFO) << "LexportedPC_0x" << std::hex << lir->offset << "_" << lir->dalvik_offset << ":";
Bill Buzbeea5b30242012-09-28 07:19:44 -0700251 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700252 case kPseudoCaseLabel:
buzbeecbd6d442012-11-17 14:11:25 -0800253 LOG(INFO) << "LC" << reinterpret_cast<void*>(lir) << ": Case target 0x"
Bill Buzbeea114add2012-05-03 15:00:40 -0700254 << std::hex << lir->operands[0] << "|" << std::dec <<
255 lir->operands[0];
256 break;
257 default:
buzbeefa57c472012-11-21 12:06:18 -0800258 if (lir->flags.is_nop && !dump_nop) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700259 break;
260 } else {
buzbee1fd33462013-03-25 13:40:45 -0700261 std::string op_name(BuildInsnString(GetTargetInstName(lir->opcode),
buzbee02031b12012-11-23 09:41:35 -0800262 lir, base_addr));
buzbee1fd33462013-03-25 13:40:45 -0700263 std::string op_operands(BuildInsnString(GetTargetInstFmt(lir->opcode),
buzbee02031b12012-11-23 09:41:35 -0800264 lir, base_addr));
Bill Buzbeea114add2012-05-03 15:00:40 -0700265 LOG(INFO) << StringPrintf("%05x: %-9s%s%s",
buzbeefa57c472012-11-21 12:06:18 -0800266 reinterpret_cast<unsigned int>(base_addr + offset),
Bill Buzbeea114add2012-05-03 15:00:40 -0700267 op_name.c_str(), op_operands.c_str(),
buzbeefa57c472012-11-21 12:06:18 -0800268 lir->flags.is_nop ? "(nop)" : "");
Bill Buzbeea114add2012-05-03 15:00:40 -0700269 }
270 break;
271 }
buzbee5de34942012-03-01 14:51:57 -0800272
buzbeefa57c472012-11-21 12:06:18 -0800273 if (lir->use_mask && (!lir->flags.is_nop || dump_nop)) {
274 DUMP_RESOURCE_MASK(DumpResourceMask((LIR* ) lir, lir->use_mask, "use"));
Bill Buzbeea114add2012-05-03 15:00:40 -0700275 }
buzbeefa57c472012-11-21 12:06:18 -0800276 if (lir->def_mask && (!lir->flags.is_nop || dump_nop)) {
277 DUMP_RESOURCE_MASK(DumpResourceMask((LIR* ) lir, lir->def_mask, "def"));
Bill Buzbeea114add2012-05-03 15:00:40 -0700278 }
buzbee5de34942012-03-01 14:51:57 -0800279}
280
buzbee1fd33462013-03-25 13:40:45 -0700281void Mir2Lir::DumpPromotionMap()
buzbee5de34942012-03-01 14:51:57 -0800282{
buzbee1fd33462013-03-25 13:40:45 -0700283 int num_regs = cu_->num_dalvik_registers + cu_->num_compiler_temps + 1;
buzbeefa57c472012-11-21 12:06:18 -0800284 for (int i = 0; i < num_regs; i++) {
buzbee1fd33462013-03-25 13:40:45 -0700285 PromotionMap v_reg_map = promotion_map_[i];
Bill Buzbeea114add2012-05-03 15:00:40 -0700286 std::string buf;
buzbeefa57c472012-11-21 12:06:18 -0800287 if (v_reg_map.fp_location == kLocPhysReg) {
buzbee1fd33462013-03-25 13:40:45 -0700288 StringAppendF(&buf, " : s%d", v_reg_map.FpReg & FpRegMask());
buzbee5de34942012-03-01 14:51:57 -0800289 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700290
291 std::string buf3;
buzbee1fd33462013-03-25 13:40:45 -0700292 if (i < cu_->num_dalvik_registers) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700293 StringAppendF(&buf3, "%02d", i);
buzbee1fd33462013-03-25 13:40:45 -0700294 } else if (i == mir_graph_->GetMethodSReg()) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700295 buf3 = "Method*";
296 } else {
buzbee1fd33462013-03-25 13:40:45 -0700297 StringAppendF(&buf3, "ct%d", i - cu_->num_dalvik_registers);
Bill Buzbeea114add2012-05-03 15:00:40 -0700298 }
299
300 LOG(INFO) << StringPrintf("V[%s] -> %s%d%s", buf3.c_str(),
buzbeefa57c472012-11-21 12:06:18 -0800301 v_reg_map.core_location == kLocPhysReg ?
302 "r" : "SP+", v_reg_map.core_location == kLocPhysReg ?
buzbee1fd33462013-03-25 13:40:45 -0700303 v_reg_map.core_reg : SRegOffset(i),
Bill Buzbeea114add2012-05-03 15:00:40 -0700304 buf.c_str());
305 }
buzbee5de34942012-03-01 14:51:57 -0800306}
307
Bill Buzbeea5b30242012-09-28 07:19:44 -0700308/* Dump a mapping table */
buzbee1fd33462013-03-25 13:40:45 -0700309void Mir2Lir::DumpMappingTable(const char* table_name, const std::string& descriptor,
310 const std::string& name, const std::string& signature,
311 const std::vector<uint32_t>& v) {
Bill Buzbeea5b30242012-09-28 07:19:44 -0700312 if (v.size() > 0) {
313 std::string line(StringPrintf("\n %s %s%s_%s_table[%zu] = {", table_name,
314 descriptor.c_str(), name.c_str(), signature.c_str(), v.size()));
315 std::replace(line.begin(), line.end(), ';', '_');
316 LOG(INFO) << line;
317 for (uint32_t i = 0; i < v.size(); i+=2) {
318 line = StringPrintf(" {0x%05x, 0x%04x},", v[i], v[i+1]);
319 LOG(INFO) << line;
320 }
321 LOG(INFO) <<" };\n\n";
322 }
323}
324
buzbee5de34942012-03-01 14:51:57 -0800325/* Dump instructions and constant pool contents */
buzbee1fd33462013-03-25 13:40:45 -0700326void Mir2Lir::CodegenDump()
buzbee5de34942012-03-01 14:51:57 -0800327{
Bill Buzbeea114add2012-05-03 15:00:40 -0700328 LOG(INFO) << "Dumping LIR insns for "
buzbee1fd33462013-03-25 13:40:45 -0700329 << PrettyMethod(cu_->method_idx, *cu_->dex_file);
buzbeefa57c472012-11-21 12:06:18 -0800330 LIR* lir_insn;
buzbee1fd33462013-03-25 13:40:45 -0700331 int insns_size = cu_->code_item->insns_size_in_code_units_;
buzbee5de34942012-03-01 14:51:57 -0800332
buzbee1fd33462013-03-25 13:40:45 -0700333 LOG(INFO) << "Regs (excluding ins) : " << cu_->num_regs;
334 LOG(INFO) << "Ins : " << cu_->num_ins;
335 LOG(INFO) << "Outs : " << cu_->num_outs;
336 LOG(INFO) << "CoreSpills : " << num_core_spills_;
337 LOG(INFO) << "FPSpills : " << num_fp_spills_;
338 LOG(INFO) << "CompilerTemps : " << cu_->num_compiler_temps;
339 LOG(INFO) << "Frame size : " << frame_size_;
340 LOG(INFO) << "code size is " << total_size_ <<
buzbeefa57c472012-11-21 12:06:18 -0800341 " bytes, Dalvik size is " << insns_size * 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700342 LOG(INFO) << "expansion factor: "
buzbee1fd33462013-03-25 13:40:45 -0700343 << static_cast<float>(total_size_) / static_cast<float>(insns_size * 2);
344 DumpPromotionMap();
345 for (lir_insn = first_lir_insn_; lir_insn != NULL; lir_insn = lir_insn->next) {
346 DumpLIRInsn(lir_insn, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700347 }
buzbee1fd33462013-03-25 13:40:45 -0700348 for (lir_insn = literal_list_; lir_insn != NULL; lir_insn = lir_insn->next) {
buzbeefa57c472012-11-21 12:06:18 -0800349 LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)", lir_insn->offset, lir_insn->offset,
350 lir_insn->operands[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700351 }
buzbee5de34942012-03-01 14:51:57 -0800352
Bill Buzbeea114add2012-05-03 15:00:40 -0700353 const DexFile::MethodId& method_id =
buzbee1fd33462013-03-25 13:40:45 -0700354 cu_->dex_file->GetMethodId(cu_->method_idx);
355 std::string signature(cu_->dex_file->GetMethodSignature(method_id));
356 std::string name(cu_->dex_file->GetMethodName(method_id));
357 std::string descriptor(cu_->dex_file->GetMethodDeclaringClassDescriptor(method_id));
buzbee5de34942012-03-01 14:51:57 -0800358
Bill Buzbeea5b30242012-09-28 07:19:44 -0700359 // Dump mapping tables
buzbee1fd33462013-03-25 13:40:45 -0700360 DumpMappingTable("PC2Dex_MappingTable", descriptor, name, signature, pc2dex_mapping_table_);
361 DumpMappingTable("Dex2PC_MappingTable", descriptor, name, signature, dex2pc_mapping_table_);
buzbee5de34942012-03-01 14:51:57 -0800362}
363
buzbeea2ebdd72012-03-04 14:57:06 -0800364
buzbee1fd33462013-03-25 13:40:45 -0700365LIR* Mir2Lir::RawLIR(int dalvik_offset, int opcode, int op0,
366 int op1, int op2, int op3, int op4, LIR* target)
buzbeea2ebdd72012-03-04 14:57:06 -0800367{
buzbee862a7602013-04-05 10:58:54 -0700368 LIR* insn = static_cast<LIR*>(arena_->NewMem(sizeof(LIR), true, ArenaAllocator::kAllocLIR));
buzbeefa57c472012-11-21 12:06:18 -0800369 insn->dalvik_offset = dalvik_offset;
Bill Buzbeea114add2012-05-03 15:00:40 -0700370 insn->opcode = opcode;
371 insn->operands[0] = op0;
372 insn->operands[1] = op1;
373 insn->operands[2] = op2;
374 insn->operands[3] = op3;
375 insn->operands[4] = op4;
376 insn->target = target;
buzbee1fd33462013-03-25 13:40:45 -0700377 SetupResourceMasks(insn);
Bill Buzbeea5b30242012-09-28 07:19:44 -0700378 if ((opcode == kPseudoTargetLabel) || (opcode == kPseudoSafepointPC) ||
379 (opcode == kPseudoExportedPC)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700380 // Always make labels scheduling barriers
buzbeefa57c472012-11-21 12:06:18 -0800381 insn->use_mask = insn->def_mask = ENCODE_ALL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700382 }
383 return insn;
buzbeea2ebdd72012-03-04 14:57:06 -0800384}
385
buzbee5de34942012-03-01 14:51:57 -0800386/*
buzbee31a4a6f2012-02-28 15:36:15 -0800387 * The following are building blocks to construct low-level IRs with 0 - 4
388 * operands.
389 */
buzbee1fd33462013-03-25 13:40:45 -0700390LIR* Mir2Lir::NewLIR0(int opcode)
buzbee31a4a6f2012-02-28 15:36:15 -0800391{
buzbee1fd33462013-03-25 13:40:45 -0700392 DCHECK(is_pseudo_opcode(opcode) || (GetTargetInstFlags(opcode) & NO_OPERAND))
393 << GetTargetInstName(opcode) << " " << opcode << " "
394 << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " "
395 << current_dalvik_offset_;
396 LIR* insn = RawLIR(current_dalvik_offset_, opcode);
397 AppendLIR(insn);
Bill Buzbeea114add2012-05-03 15:00:40 -0700398 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800399}
400
buzbee1fd33462013-03-25 13:40:45 -0700401LIR* Mir2Lir::NewLIR1(int opcode, int dest)
buzbee31a4a6f2012-02-28 15:36:15 -0800402{
buzbee1fd33462013-03-25 13:40:45 -0700403 DCHECK(is_pseudo_opcode(opcode) || (GetTargetInstFlags(opcode) & IS_UNARY_OP))
404 << GetTargetInstName(opcode) << " " << opcode << " "
405 << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " "
406 << current_dalvik_offset_;
407 LIR* insn = RawLIR(current_dalvik_offset_, opcode, dest);
408 AppendLIR(insn);
Bill Buzbeea114add2012-05-03 15:00:40 -0700409 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800410}
411
buzbee1fd33462013-03-25 13:40:45 -0700412LIR* Mir2Lir::NewLIR2(int opcode, int dest, int src1)
buzbee31a4a6f2012-02-28 15:36:15 -0800413{
buzbee1fd33462013-03-25 13:40:45 -0700414 DCHECK(is_pseudo_opcode(opcode) || (GetTargetInstFlags(opcode) & IS_BINARY_OP))
415 << GetTargetInstName(opcode) << " " << opcode << " "
416 << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " "
417 << current_dalvik_offset_;
418 LIR* insn = RawLIR(current_dalvik_offset_, opcode, dest, src1);
419 AppendLIR(insn);
Bill Buzbeea114add2012-05-03 15:00:40 -0700420 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800421}
422
buzbee1fd33462013-03-25 13:40:45 -0700423LIR* Mir2Lir::NewLIR3(int opcode, int dest, int src1, int src2)
buzbee31a4a6f2012-02-28 15:36:15 -0800424{
buzbee1fd33462013-03-25 13:40:45 -0700425 DCHECK(is_pseudo_opcode(opcode) || (GetTargetInstFlags(opcode) & IS_TERTIARY_OP))
426 << GetTargetInstName(opcode) << " " << opcode << " "
427 << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " "
428 << current_dalvik_offset_;
429 LIR* insn = RawLIR(current_dalvik_offset_, opcode, dest, src1, src2);
430 AppendLIR(insn);
Bill Buzbeea114add2012-05-03 15:00:40 -0700431 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800432}
433
buzbee1fd33462013-03-25 13:40:45 -0700434LIR* Mir2Lir::NewLIR4(int opcode, int dest, int src1, int src2, int info)
buzbee31a4a6f2012-02-28 15:36:15 -0800435{
buzbee1fd33462013-03-25 13:40:45 -0700436 DCHECK(is_pseudo_opcode(opcode) || (GetTargetInstFlags(opcode) & IS_QUAD_OP))
437 << GetTargetInstName(opcode) << " " << opcode << " "
438 << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " "
439 << current_dalvik_offset_;
440 LIR* insn = RawLIR(current_dalvik_offset_, opcode, dest, src1, src2, info);
441 AppendLIR(insn);
Bill Buzbeea114add2012-05-03 15:00:40 -0700442 return insn;
buzbee31a4a6f2012-02-28 15:36:15 -0800443}
buzbee31a4a6f2012-02-28 15:36:15 -0800444
buzbee1fd33462013-03-25 13:40:45 -0700445LIR* Mir2Lir::NewLIR5(int opcode, int dest, int src1, int src2, int info1,
446 int info2)
Ian Rogersb5d09b22012-03-06 22:14:17 -0800447{
buzbee1fd33462013-03-25 13:40:45 -0700448 DCHECK(is_pseudo_opcode(opcode) || (GetTargetInstFlags(opcode) & IS_QUIN_OP))
449 << GetTargetInstName(opcode) << " " << opcode << " "
450 << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " "
451 << current_dalvik_offset_;
452 LIR* insn = RawLIR(current_dalvik_offset_, opcode, dest, src1, src2, info1, info2);
453 AppendLIR(insn);
Bill Buzbeea114add2012-05-03 15:00:40 -0700454 return insn;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800455}
456
buzbee31a4a6f2012-02-28 15:36:15 -0800457/*
458 * Search the existing constants in the literal pool for an exact or close match
459 * within specified delta (greater or equal to 0).
460 */
buzbee1fd33462013-03-25 13:40:45 -0700461LIR* Mir2Lir::ScanLiteralPool(LIR* data_target, int value, unsigned int delta)
buzbee31a4a6f2012-02-28 15:36:15 -0800462{
buzbeefa57c472012-11-21 12:06:18 -0800463 while (data_target) {
464 if ((static_cast<unsigned>(value - data_target->operands[0])) <= delta)
465 return data_target;
466 data_target = data_target->next;
Bill Buzbeea114add2012-05-03 15:00:40 -0700467 }
468 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800469}
470
471/* Search the existing constants in the literal pool for an exact wide match */
buzbee1fd33462013-03-25 13:40:45 -0700472LIR* Mir2Lir::ScanLiteralPoolWide(LIR* data_target, int val_lo, int val_hi)
buzbee31a4a6f2012-02-28 15:36:15 -0800473{
buzbeefa57c472012-11-21 12:06:18 -0800474 bool lo_match = false;
475 LIR* lo_target = NULL;
476 while (data_target) {
477 if (lo_match && (data_target->operands[0] == val_hi)) {
buzbee4ef3e452012-12-14 13:35:28 -0800478 // Record high word in case we need to expand this later.
479 lo_target->operands[1] = val_hi;
buzbeefa57c472012-11-21 12:06:18 -0800480 return lo_target;
buzbee31a4a6f2012-02-28 15:36:15 -0800481 }
buzbeefa57c472012-11-21 12:06:18 -0800482 lo_match = false;
483 if (data_target->operands[0] == val_lo) {
484 lo_match = true;
485 lo_target = data_target;
Bill Buzbeea114add2012-05-03 15:00:40 -0700486 }
buzbeefa57c472012-11-21 12:06:18 -0800487 data_target = data_target->next;
Bill Buzbeea114add2012-05-03 15:00:40 -0700488 }
489 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800490}
491
492/*
493 * The following are building blocks to insert constants into the pool or
494 * instruction streams.
495 */
496
buzbee4ef3e452012-12-14 13:35:28 -0800497/* Add a 32-bit constant to the constant pool */
buzbee1fd33462013-03-25 13:40:45 -0700498LIR* Mir2Lir::AddWordData(LIR* *constant_list_p, int value)
buzbee31a4a6f2012-02-28 15:36:15 -0800499{
Bill Buzbeea114add2012-05-03 15:00:40 -0700500 /* Add the constant to the literal pool */
buzbeefa57c472012-11-21 12:06:18 -0800501 if (constant_list_p) {
buzbee862a7602013-04-05 10:58:54 -0700502 LIR* new_value = static_cast<LIR*>(arena_->NewMem(sizeof(LIR), true, ArenaAllocator::kAllocData));
buzbeefa57c472012-11-21 12:06:18 -0800503 new_value->operands[0] = value;
504 new_value->next = *constant_list_p;
505 *constant_list_p = new_value;
506 return new_value;
Bill Buzbeea114add2012-05-03 15:00:40 -0700507 }
508 return NULL;
buzbee31a4a6f2012-02-28 15:36:15 -0800509}
510
511/* Add a 64-bit constant to the constant pool or mixed with code */
buzbee1fd33462013-03-25 13:40:45 -0700512LIR* Mir2Lir::AddWideData(LIR* *constant_list_p, int val_lo, int val_hi)
buzbee31a4a6f2012-02-28 15:36:15 -0800513{
buzbee1fd33462013-03-25 13:40:45 -0700514 AddWordData(constant_list_p, val_hi);
515 return AddWordData(constant_list_p, val_lo);
buzbee31a4a6f2012-02-28 15:36:15 -0800516}
517
buzbeeaad94382012-11-21 07:40:50 -0800518static void PushWord(std::vector<uint8_t>&buf, int data) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700519 buf.push_back( data & 0xff);
520 buf.push_back( (data >> 8) & 0xff);
521 buf.push_back( (data >> 16) & 0xff);
522 buf.push_back( (data >> 24) & 0xff);
buzbeee3acd072012-02-25 17:03:10 -0800523}
524
buzbeeaad94382012-11-21 07:40:50 -0800525static void AlignBuffer(std::vector<uint8_t>&buf, size_t offset) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700526 while (buf.size() < offset) {
527 buf.push_back(0);
528 }
buzbeee3acd072012-02-25 17:03:10 -0800529}
530
531/* Write the literal pool to the output stream */
buzbee1fd33462013-03-25 13:40:45 -0700532void Mir2Lir::InstallLiteralPools()
buzbeee3acd072012-02-25 17:03:10 -0800533{
buzbee1fd33462013-03-25 13:40:45 -0700534 AlignBuffer(code_buffer_, data_offset_);
535 LIR* data_lir = literal_list_;
buzbeefa57c472012-11-21 12:06:18 -0800536 while (data_lir != NULL) {
buzbee1fd33462013-03-25 13:40:45 -0700537 PushWord(code_buffer_, data_lir->operands[0]);
buzbeefa57c472012-11-21 12:06:18 -0800538 data_lir = NEXT_LIR(data_lir);
Bill Buzbeea114add2012-05-03 15:00:40 -0700539 }
540 // Push code and method literals, record offsets for the compiler to patch.
buzbee1fd33462013-03-25 13:40:45 -0700541 data_lir = code_literal_list_;
buzbeefa57c472012-11-21 12:06:18 -0800542 while (data_lir != NULL) {
543 uint32_t target = data_lir->operands[0];
buzbee1fd33462013-03-25 13:40:45 -0700544 cu_->compiler_driver->AddCodePatch(cu_->dex_file,
545 cu_->method_idx,
546 cu_->invoke_type,
Ian Rogers1212a022013-03-04 10:48:41 -0800547 target,
548 static_cast<InvokeType>(data_lir->operands[1]),
buzbee1fd33462013-03-25 13:40:45 -0700549 code_buffer_.size());
550 const DexFile::MethodId& id = cu_->dex_file->GetMethodId(target);
Ian Rogers137e88f2012-10-08 17:46:47 -0700551 // unique based on target to ensure code deduplication works
552 uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
buzbee1fd33462013-03-25 13:40:45 -0700553 PushWord(code_buffer_, unique_patch_value);
buzbeefa57c472012-11-21 12:06:18 -0800554 data_lir = NEXT_LIR(data_lir);
Ian Rogers137e88f2012-10-08 17:46:47 -0700555 }
buzbee1fd33462013-03-25 13:40:45 -0700556 data_lir = method_literal_list_;
buzbeefa57c472012-11-21 12:06:18 -0800557 while (data_lir != NULL) {
558 uint32_t target = data_lir->operands[0];
buzbee1fd33462013-03-25 13:40:45 -0700559 cu_->compiler_driver->AddMethodPatch(cu_->dex_file,
560 cu_->method_idx,
561 cu_->invoke_type,
Ian Rogers1212a022013-03-04 10:48:41 -0800562 target,
563 static_cast<InvokeType>(data_lir->operands[1]),
buzbee1fd33462013-03-25 13:40:45 -0700564 code_buffer_.size());
565 const DexFile::MethodId& id = cu_->dex_file->GetMethodId(target);
Ian Rogers137e88f2012-10-08 17:46:47 -0700566 // unique based on target to ensure code deduplication works
567 uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
buzbee1fd33462013-03-25 13:40:45 -0700568 PushWord(code_buffer_, unique_patch_value);
buzbeefa57c472012-11-21 12:06:18 -0800569 data_lir = NEXT_LIR(data_lir);
Bill Buzbeea114add2012-05-03 15:00:40 -0700570 }
buzbeee3acd072012-02-25 17:03:10 -0800571}
572
573/* Write the switch tables to the output stream */
buzbee1fd33462013-03-25 13:40:45 -0700574void Mir2Lir::InstallSwitchTables()
buzbeee3acd072012-02-25 17:03:10 -0800575{
buzbee862a7602013-04-05 10:58:54 -0700576 GrowableArray<SwitchTable*>::Iterator iterator(&switch_tables_);
Bill Buzbeea114add2012-05-03 15:00:40 -0700577 while (true) {
buzbee862a7602013-04-05 10:58:54 -0700578 Mir2Lir::SwitchTable* tab_rec = iterator.Next();
buzbeefa57c472012-11-21 12:06:18 -0800579 if (tab_rec == NULL) break;
buzbee1fd33462013-03-25 13:40:45 -0700580 AlignBuffer(code_buffer_, tab_rec->offset);
Bill Buzbeea114add2012-05-03 15:00:40 -0700581 /*
582 * For Arm, our reference point is the address of the bx
583 * instruction that does the launch, so we have to subtract
584 * the auto pc-advance. For other targets the reference point
585 * is a label, so we can use the offset as-is.
586 */
buzbeefa57c472012-11-21 12:06:18 -0800587 int bx_offset = INVALID_OFFSET;
buzbee1fd33462013-03-25 13:40:45 -0700588 switch (cu_->instruction_set) {
buzbeeb046e162012-10-30 15:48:42 -0700589 case kThumb2:
buzbeefa57c472012-11-21 12:06:18 -0800590 bx_offset = tab_rec->anchor->offset + 4;
buzbeeb046e162012-10-30 15:48:42 -0700591 break;
592 case kX86:
buzbeefa57c472012-11-21 12:06:18 -0800593 bx_offset = 0;
buzbeeb046e162012-10-30 15:48:42 -0700594 break;
595 case kMips:
buzbeefa57c472012-11-21 12:06:18 -0800596 bx_offset = tab_rec->anchor->offset;
buzbeeb046e162012-10-30 15:48:42 -0700597 break;
buzbee1fd33462013-03-25 13:40:45 -0700598 default: LOG(FATAL) << "Unexpected instruction set: " << cu_->instruction_set;
buzbeeb046e162012-10-30 15:48:42 -0700599 }
buzbee1fd33462013-03-25 13:40:45 -0700600 if (cu_->verbose) {
buzbeefa57c472012-11-21 12:06:18 -0800601 LOG(INFO) << "Switch table for offset 0x" << std::hex << bx_offset;
buzbeee3acd072012-02-25 17:03:10 -0800602 }
buzbeefa57c472012-11-21 12:06:18 -0800603 if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) {
604 const int* keys = reinterpret_cast<const int*>(&(tab_rec->table[2]));
605 for (int elems = 0; elems < tab_rec->table[1]; elems++) {
606 int disp = tab_rec->targets[elems]->offset - bx_offset;
buzbee1fd33462013-03-25 13:40:45 -0700607 if (cu_->verbose) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700608 LOG(INFO) << " Case[" << elems << "] key: 0x"
609 << std::hex << keys[elems] << ", disp: 0x"
610 << std::hex << disp;
611 }
buzbee1fd33462013-03-25 13:40:45 -0700612 PushWord(code_buffer_, keys[elems]);
613 PushWord(code_buffer_,
buzbeefa57c472012-11-21 12:06:18 -0800614 tab_rec->targets[elems]->offset - bx_offset);
Bill Buzbeea114add2012-05-03 15:00:40 -0700615 }
616 } else {
buzbeefa57c472012-11-21 12:06:18 -0800617 DCHECK_EQ(static_cast<int>(tab_rec->table[0]),
Bill Buzbeea114add2012-05-03 15:00:40 -0700618 static_cast<int>(Instruction::kPackedSwitchSignature));
buzbeefa57c472012-11-21 12:06:18 -0800619 for (int elems = 0; elems < tab_rec->table[1]; elems++) {
620 int disp = tab_rec->targets[elems]->offset - bx_offset;
buzbee1fd33462013-03-25 13:40:45 -0700621 if (cu_->verbose) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700622 LOG(INFO) << " Case[" << elems << "] disp: 0x"
623 << std::hex << disp;
624 }
buzbee1fd33462013-03-25 13:40:45 -0700625 PushWord(code_buffer_, tab_rec->targets[elems]->offset - bx_offset);
Bill Buzbeea114add2012-05-03 15:00:40 -0700626 }
627 }
628 }
buzbeee3acd072012-02-25 17:03:10 -0800629}
630
631/* Write the fill array dta to the output stream */
buzbee1fd33462013-03-25 13:40:45 -0700632void Mir2Lir::InstallFillArrayData()
buzbeee3acd072012-02-25 17:03:10 -0800633{
buzbee862a7602013-04-05 10:58:54 -0700634 GrowableArray<FillArrayData*>::Iterator iterator(&fill_array_data_);
Bill Buzbeea114add2012-05-03 15:00:40 -0700635 while (true) {
buzbee862a7602013-04-05 10:58:54 -0700636 Mir2Lir::FillArrayData *tab_rec = iterator.Next();
buzbeefa57c472012-11-21 12:06:18 -0800637 if (tab_rec == NULL) break;
buzbee1fd33462013-03-25 13:40:45 -0700638 AlignBuffer(code_buffer_, tab_rec->offset);
buzbeefa57c472012-11-21 12:06:18 -0800639 for (int i = 0; i < (tab_rec->size + 1) / 2; i++) {
buzbee1fd33462013-03-25 13:40:45 -0700640 code_buffer_.push_back( tab_rec->table[i] & 0xFF);
641 code_buffer_.push_back( (tab_rec->table[i] >> 8) & 0xFF);
buzbeee3acd072012-02-25 17:03:10 -0800642 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700643 }
buzbeee3acd072012-02-25 17:03:10 -0800644}
645
buzbeeaad94382012-11-21 07:40:50 -0800646static int AssignLiteralOffsetCommon(LIR* lir, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800647{
Bill Buzbeea114add2012-05-03 15:00:40 -0700648 for (;lir != NULL; lir = lir->next) {
649 lir->offset = offset;
650 offset += 4;
651 }
652 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800653}
654
buzbee6459e7c2012-10-02 14:42:41 -0700655// Make sure we have a code address for every declared catch entry
buzbee1fd33462013-03-25 13:40:45 -0700656bool Mir2Lir::VerifyCatchEntries()
buzbee6459e7c2012-10-02 14:42:41 -0700657{
658 bool success = true;
buzbee1fd33462013-03-25 13:40:45 -0700659 for (std::set<uint32_t>::const_iterator it = mir_graph_->catches_.begin();
660 it != mir_graph_->catches_.end(); ++it) {
buzbeefa57c472012-11-21 12:06:18 -0800661 uint32_t dex_pc = *it;
buzbee6459e7c2012-10-02 14:42:41 -0700662 bool found = false;
buzbee1fd33462013-03-25 13:40:45 -0700663 for (size_t i = 0; i < dex2pc_mapping_table_.size(); i += 2) {
664 if (dex_pc == dex2pc_mapping_table_[i+1]) {
buzbee6459e7c2012-10-02 14:42:41 -0700665 found = true;
666 break;
667 }
668 }
669 if (!found) {
buzbeefa57c472012-11-21 12:06:18 -0800670 LOG(INFO) << "Missing native PC for catch entry @ 0x" << std::hex << dex_pc;
buzbee6459e7c2012-10-02 14:42:41 -0700671 success = false;
672 }
673 }
674 // Now, try in the other direction
buzbee1fd33462013-03-25 13:40:45 -0700675 for (size_t i = 0; i < dex2pc_mapping_table_.size(); i += 2) {
676 uint32_t dex_pc = dex2pc_mapping_table_[i+1];
677 if (mir_graph_->catches_.find(dex_pc) == mir_graph_->catches_.end()) {
buzbeefa57c472012-11-21 12:06:18 -0800678 LOG(INFO) << "Unexpected catch entry @ dex pc 0x" << std::hex << dex_pc;
buzbee6459e7c2012-10-02 14:42:41 -0700679 success = false;
680 }
681 }
682 if (!success) {
buzbee1fd33462013-03-25 13:40:45 -0700683 LOG(INFO) << "Bad dex2pcMapping table in " << PrettyMethod(cu_->method_idx, *cu_->dex_file);
684 LOG(INFO) << "Entries @ decode: " << mir_graph_->catches_.size() << ", Entries in table: "
685 << dex2pc_mapping_table_.size()/2;
buzbee6459e7c2012-10-02 14:42:41 -0700686 }
687 return success;
688}
689
buzbee311ca162013-02-28 15:56:43 -0800690
buzbee1fd33462013-03-25 13:40:45 -0700691void Mir2Lir::CreateMappingTables()
buzbeee3acd072012-02-25 17:03:10 -0800692{
buzbee1fd33462013-03-25 13:40:45 -0700693 for (LIR* tgt_lir = first_lir_insn_; tgt_lir != NULL; tgt_lir = NEXT_LIR(tgt_lir)) {
buzbeefa57c472012-11-21 12:06:18 -0800694 if (!tgt_lir->flags.is_nop && (tgt_lir->opcode == kPseudoSafepointPC)) {
buzbee1fd33462013-03-25 13:40:45 -0700695 pc2dex_mapping_table_.push_back(tgt_lir->offset);
696 pc2dex_mapping_table_.push_back(tgt_lir->dalvik_offset);
Bill Buzbeea5b30242012-09-28 07:19:44 -0700697 }
buzbeefa57c472012-11-21 12:06:18 -0800698 if (!tgt_lir->flags.is_nop && (tgt_lir->opcode == kPseudoExportedPC)) {
buzbee1fd33462013-03-25 13:40:45 -0700699 dex2pc_mapping_table_.push_back(tgt_lir->offset);
700 dex2pc_mapping_table_.push_back(tgt_lir->dalvik_offset);
buzbeee3acd072012-02-25 17:03:10 -0800701 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700702 }
buzbee311ca162013-02-28 15:56:43 -0800703 if (kIsDebugBuild) {
buzbee1fd33462013-03-25 13:40:45 -0700704 DCHECK(VerifyCatchEntries());
buzbee311ca162013-02-28 15:56:43 -0800705 }
buzbee1fd33462013-03-25 13:40:45 -0700706 combined_mapping_table_.push_back(pc2dex_mapping_table_.size() +
707 dex2pc_mapping_table_.size());
708 combined_mapping_table_.push_back(pc2dex_mapping_table_.size());
709 combined_mapping_table_.insert(combined_mapping_table_.end(), pc2dex_mapping_table_.begin(),
710 pc2dex_mapping_table_.end());
711 combined_mapping_table_.insert(combined_mapping_table_.end(), dex2pc_mapping_table_.begin(),
712 dex2pc_mapping_table_.end());
buzbeee3acd072012-02-25 17:03:10 -0800713}
714
Ian Rogers0c7abda2012-09-19 13:33:42 -0700715class NativePcToReferenceMapBuilder {
716 public:
717 NativePcToReferenceMapBuilder(std::vector<uint8_t>* table,
718 size_t entries, uint32_t max_native_offset,
719 size_t references_width) : entries_(entries),
720 references_width_(references_width), in_use_(entries),
721 table_(table) {
722 // Compute width in bytes needed to hold max_native_offset.
723 native_offset_width_ = 0;
724 while (max_native_offset != 0) {
725 native_offset_width_++;
726 max_native_offset >>= 8;
727 }
728 // Resize table and set up header.
729 table->resize((EntryWidth() * entries) + sizeof(uint32_t));
Ian Rogers000d7242012-09-21 16:07:36 -0700730 CHECK_LT(native_offset_width_, 1U << 3);
731 (*table)[0] = native_offset_width_ & 7;
732 CHECK_LT(references_width_, 1U << 13);
733 (*table)[0] |= (references_width_ << 3) & 0xFF;
734 (*table)[1] = (references_width_ >> 5) & 0xFF;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700735 CHECK_LT(entries, 1U << 16);
736 (*table)[2] = entries & 0xFF;
737 (*table)[3] = (entries >> 8) & 0xFF;
738 }
739
740 void AddEntry(uint32_t native_offset, const uint8_t* references) {
741 size_t table_index = TableIndex(native_offset);
742 while (in_use_[table_index]) {
743 table_index = (table_index + 1) % entries_;
744 }
745 in_use_[table_index] = true;
746 SetNativeOffset(table_index, native_offset);
747 DCHECK_EQ(native_offset, GetNativeOffset(table_index));
748 SetReferences(table_index, references);
749 }
750
751 private:
752 size_t TableIndex(uint32_t native_offset) {
753 return NativePcOffsetToReferenceMap::Hash(native_offset) % entries_;
754 }
755
756 uint32_t GetNativeOffset(size_t table_index) {
757 uint32_t native_offset = 0;
758 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
759 for (size_t i = 0; i < native_offset_width_; i++) {
760 native_offset |= (*table_)[table_offset + i] << (i * 8);
761 }
762 return native_offset;
763 }
764
765 void SetNativeOffset(size_t table_index, uint32_t native_offset) {
766 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
767 for (size_t i = 0; i < native_offset_width_; i++) {
768 (*table_)[table_offset + i] = (native_offset >> (i * 8)) & 0xFF;
769 }
770 }
771
772 void SetReferences(size_t table_index, const uint8_t* references) {
773 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
774 memcpy(&(*table_)[table_offset + native_offset_width_], references, references_width_);
775 }
776
777 size_t EntryWidth() const {
778 return native_offset_width_ + references_width_;
779 }
780
781 // Number of entries in the table.
782 const size_t entries_;
783 // Number of bytes used to encode the reference bitmap.
784 const size_t references_width_;
785 // Number of bytes used to encode a native offset.
786 size_t native_offset_width_;
787 // Entries that are in use.
788 std::vector<bool> in_use_;
789 // The table we're building.
790 std::vector<uint8_t>* const table_;
791};
792
buzbee1fd33462013-03-25 13:40:45 -0700793void Mir2Lir::CreateNativeGcMap() {
794 const std::vector<uint32_t>& mapping_table = pc2dex_mapping_table_;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700795 uint32_t max_native_offset = 0;
796 for (size_t i = 0; i < mapping_table.size(); i += 2) {
797 uint32_t native_offset = mapping_table[i + 0];
798 if (native_offset > max_native_offset) {
799 max_native_offset = native_offset;
800 }
801 }
buzbee1fd33462013-03-25 13:40:45 -0700802 CompilerDriver::MethodReference method_ref(cu_->dex_file, cu_->method_idx);
Ian Rogers0c7abda2012-09-19 13:33:42 -0700803 const std::vector<uint8_t>* gc_map_raw = verifier::MethodVerifier::GetDexGcMap(method_ref);
804 verifier::DexPcToReferenceMap dex_gc_map(&(*gc_map_raw)[4], gc_map_raw->size() - 4);
805 // Compute native offset to references size.
buzbee1fd33462013-03-25 13:40:45 -0700806 NativePcToReferenceMapBuilder native_gc_map_builder(&native_gc_map_,
Ian Rogers0c7abda2012-09-19 13:33:42 -0700807 mapping_table.size() / 2, max_native_offset,
808 dex_gc_map.RegWidth());
809
810 for (size_t i = 0; i < mapping_table.size(); i += 2) {
811 uint32_t native_offset = mapping_table[i + 0];
812 uint32_t dex_pc = mapping_table[i + 1];
813 const uint8_t* references = dex_gc_map.FindBitMap(dex_pc, false);
Bill Buzbeea5b30242012-09-28 07:19:44 -0700814 CHECK(references != NULL) << "Missing ref for dex pc 0x" << std::hex << dex_pc;
815 native_gc_map_builder.AddEntry(native_offset, references);
Ian Rogers0c7abda2012-09-19 13:33:42 -0700816 }
817}
818
buzbeee3acd072012-02-25 17:03:10 -0800819/* Determine the offset of each literal field */
buzbee1fd33462013-03-25 13:40:45 -0700820int Mir2Lir::AssignLiteralOffset(int offset)
buzbeee3acd072012-02-25 17:03:10 -0800821{
buzbee1fd33462013-03-25 13:40:45 -0700822 offset = AssignLiteralOffsetCommon(literal_list_, offset);
823 offset = AssignLiteralOffsetCommon(code_literal_list_, offset);
824 offset = AssignLiteralOffsetCommon(method_literal_list_, offset);
Bill Buzbeea114add2012-05-03 15:00:40 -0700825 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800826}
827
buzbee1fd33462013-03-25 13:40:45 -0700828int Mir2Lir::AssignSwitchTablesOffset(int offset)
buzbeee3acd072012-02-25 17:03:10 -0800829{
buzbee862a7602013-04-05 10:58:54 -0700830 GrowableArray<SwitchTable*>::Iterator iterator(&switch_tables_);
Bill Buzbeea114add2012-05-03 15:00:40 -0700831 while (true) {
buzbee862a7602013-04-05 10:58:54 -0700832 Mir2Lir::SwitchTable *tab_rec = iterator.Next();
buzbeefa57c472012-11-21 12:06:18 -0800833 if (tab_rec == NULL) break;
834 tab_rec->offset = offset;
835 if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) {
836 offset += tab_rec->table[1] * (sizeof(int) * 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700837 } else {
buzbeefa57c472012-11-21 12:06:18 -0800838 DCHECK_EQ(static_cast<int>(tab_rec->table[0]),
Bill Buzbeea114add2012-05-03 15:00:40 -0700839 static_cast<int>(Instruction::kPackedSwitchSignature));
buzbeefa57c472012-11-21 12:06:18 -0800840 offset += tab_rec->table[1] * sizeof(int);
buzbeee3acd072012-02-25 17:03:10 -0800841 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700842 }
843 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800844}
845
buzbee1fd33462013-03-25 13:40:45 -0700846int Mir2Lir::AssignFillArrayDataOffset(int offset)
buzbeee3acd072012-02-25 17:03:10 -0800847{
buzbee862a7602013-04-05 10:58:54 -0700848 GrowableArray<FillArrayData*>::Iterator iterator(&fill_array_data_);
Bill Buzbeea114add2012-05-03 15:00:40 -0700849 while (true) {
buzbee862a7602013-04-05 10:58:54 -0700850 Mir2Lir::FillArrayData *tab_rec = iterator.Next();
buzbeefa57c472012-11-21 12:06:18 -0800851 if (tab_rec == NULL) break;
852 tab_rec->offset = offset;
853 offset += tab_rec->size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700854 // word align
855 offset = (offset + 3) & ~3;
856 }
857 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800858}
859
buzbeea3a82b22012-11-27 16:09:55 -0800860// LIR offset assignment.
buzbee1fd33462013-03-25 13:40:45 -0700861int Mir2Lir::AssignInsnOffsets()
buzbeea3a82b22012-11-27 16:09:55 -0800862{
863 LIR* lir;
864 int offset = 0;
865
buzbee1fd33462013-03-25 13:40:45 -0700866 for (lir = first_lir_insn_; lir != NULL; lir = NEXT_LIR(lir)) {
buzbeea3a82b22012-11-27 16:09:55 -0800867 lir->offset = offset;
868 if (lir->opcode >= 0) {
869 if (!lir->flags.is_nop) {
870 offset += lir->flags.size;
871 }
872 } else if (lir->opcode == kPseudoPseudoAlign4) {
873 if (offset & 0x2) {
874 offset += 2;
875 lir->operands[0] = 1;
876 } else {
877 lir->operands[0] = 0;
878 }
879 }
880 /* Pseudo opcodes don't consume space */
881 }
882
883 return offset;
884}
885
buzbeee3acd072012-02-25 17:03:10 -0800886/*
887 * Walk the compilation unit and assign offsets to instructions
888 * and literals and compute the total size of the compiled unit.
889 */
buzbee1fd33462013-03-25 13:40:45 -0700890void Mir2Lir::AssignOffsets()
buzbeee3acd072012-02-25 17:03:10 -0800891{
buzbee1fd33462013-03-25 13:40:45 -0700892 int offset = AssignInsnOffsets();
buzbeee3acd072012-02-25 17:03:10 -0800893
Bill Buzbeea114add2012-05-03 15:00:40 -0700894 /* Const values have to be word aligned */
895 offset = (offset + 3) & ~3;
buzbeee3acd072012-02-25 17:03:10 -0800896
Bill Buzbeea114add2012-05-03 15:00:40 -0700897 /* Set up offsets for literals */
buzbee1fd33462013-03-25 13:40:45 -0700898 data_offset_ = offset;
buzbeee3acd072012-02-25 17:03:10 -0800899
buzbee1fd33462013-03-25 13:40:45 -0700900 offset = AssignLiteralOffset(offset);
buzbeee3acd072012-02-25 17:03:10 -0800901
buzbee1fd33462013-03-25 13:40:45 -0700902 offset = AssignSwitchTablesOffset(offset);
buzbeee3acd072012-02-25 17:03:10 -0800903
buzbee1fd33462013-03-25 13:40:45 -0700904 offset = AssignFillArrayDataOffset(offset);
buzbeee3acd072012-02-25 17:03:10 -0800905
buzbee1fd33462013-03-25 13:40:45 -0700906 total_size_ = offset;
buzbeee3acd072012-02-25 17:03:10 -0800907}
908
909/*
910 * Go over each instruction in the list and calculate the offset from the top
911 * before sending them off to the assembler. If out-of-range branch distance is
912 * seen rearrange the instructions a bit to correct it.
913 */
buzbee1fd33462013-03-25 13:40:45 -0700914void Mir2Lir::AssembleLIR()
buzbeee3acd072012-02-25 17:03:10 -0800915{
buzbee1fd33462013-03-25 13:40:45 -0700916 AssignOffsets();
buzbee311ca162013-02-28 15:56:43 -0800917 int assembler_retries = 0;
Bill Buzbeea114add2012-05-03 15:00:40 -0700918 /*
919 * Assemble here. Note that we generate code with optimistic assumptions
920 * and if found now to work, we'll have to redo the sequence and retry.
921 */
buzbeee3acd072012-02-25 17:03:10 -0800922
Bill Buzbeea114add2012-05-03 15:00:40 -0700923 while (true) {
buzbee1fd33462013-03-25 13:40:45 -0700924 AssemblerStatus res = AssembleInstructions(0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700925 if (res == kSuccess) {
926 break;
927 } else {
buzbee311ca162013-02-28 15:56:43 -0800928 assembler_retries++;
929 if (assembler_retries > MAX_ASSEMBLER_RETRIES) {
buzbee1fd33462013-03-25 13:40:45 -0700930 CodegenDump();
Bill Buzbeea114add2012-05-03 15:00:40 -0700931 LOG(FATAL) << "Assembler error - too many retries";
932 }
933 // Redo offsets and try again
buzbee1fd33462013-03-25 13:40:45 -0700934 AssignOffsets();
935 code_buffer_.clear();
buzbeee3acd072012-02-25 17:03:10 -0800936 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700937 }
buzbeee3acd072012-02-25 17:03:10 -0800938
Bill Buzbeea114add2012-05-03 15:00:40 -0700939 // Install literals
buzbee1fd33462013-03-25 13:40:45 -0700940 InstallLiteralPools();
buzbeee3acd072012-02-25 17:03:10 -0800941
Bill Buzbeea114add2012-05-03 15:00:40 -0700942 // Install switch tables
buzbee1fd33462013-03-25 13:40:45 -0700943 InstallSwitchTables();
buzbeee3acd072012-02-25 17:03:10 -0800944
Bill Buzbeea114add2012-05-03 15:00:40 -0700945 // Install fill array data
buzbee1fd33462013-03-25 13:40:45 -0700946 InstallFillArrayData();
buzbeee3acd072012-02-25 17:03:10 -0800947
Ian Rogers0c7abda2012-09-19 13:33:42 -0700948 // Create the mapping table and native offset to reference map.
buzbee1fd33462013-03-25 13:40:45 -0700949 CreateMappingTables();
Ian Rogers0c7abda2012-09-19 13:33:42 -0700950
buzbee1fd33462013-03-25 13:40:45 -0700951 CreateNativeGcMap();
buzbeee3acd072012-02-25 17:03:10 -0800952}
953
buzbee31a4a6f2012-02-28 15:36:15 -0800954/*
955 * Insert a kPseudoCaseLabel at the beginning of the Dalvik
956 * offset vaddr. This label will be used to fix up the case
957 * branch table during the assembly phase. Be sure to set
958 * all resource flags on this to prevent code motion across
959 * target boundaries. KeyVal is just there for debugging.
960 */
buzbee1fd33462013-03-25 13:40:45 -0700961LIR* Mir2Lir::InsertCaseLabel(int vaddr, int keyVal)
buzbee31a4a6f2012-02-28 15:36:15 -0800962{
Bill Buzbeea114add2012-05-03 15:00:40 -0700963 SafeMap<unsigned int, LIR*>::iterator it;
buzbee1fd33462013-03-25 13:40:45 -0700964 it = boundary_map_.find(vaddr);
965 if (it == boundary_map_.end()) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700966 LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr;
967 }
buzbee862a7602013-04-05 10:58:54 -0700968 LIR* new_label = static_cast<LIR*>(arena_->NewMem(sizeof(LIR), true, ArenaAllocator::kAllocLIR));
buzbeefa57c472012-11-21 12:06:18 -0800969 new_label->dalvik_offset = vaddr;
970 new_label->opcode = kPseudoCaseLabel;
971 new_label->operands[0] = keyVal;
972 InsertLIRAfter(it->second, new_label);
973 return new_label;
buzbee31a4a6f2012-02-28 15:36:15 -0800974}
975
buzbee1fd33462013-03-25 13:40:45 -0700976void Mir2Lir::MarkPackedCaseLabels(Mir2Lir::SwitchTable *tab_rec)
buzbee31a4a6f2012-02-28 15:36:15 -0800977{
buzbeefa57c472012-11-21 12:06:18 -0800978 const uint16_t* table = tab_rec->table;
979 int base_vaddr = tab_rec->vaddr;
buzbeecbd6d442012-11-17 14:11:25 -0800980 const int *targets = reinterpret_cast<const int*>(&table[4]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700981 int entries = table[1];
buzbeefa57c472012-11-21 12:06:18 -0800982 int low_key = s4FromSwitchData(&table[2]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700983 for (int i = 0; i < entries; i++) {
buzbee1fd33462013-03-25 13:40:45 -0700984 tab_rec->targets[i] = InsertCaseLabel(base_vaddr + targets[i], i + low_key);
Bill Buzbeea114add2012-05-03 15:00:40 -0700985 }
buzbee31a4a6f2012-02-28 15:36:15 -0800986}
987
buzbee1fd33462013-03-25 13:40:45 -0700988void Mir2Lir::MarkSparseCaseLabels(Mir2Lir::SwitchTable *tab_rec)
buzbee31a4a6f2012-02-28 15:36:15 -0800989{
buzbeefa57c472012-11-21 12:06:18 -0800990 const uint16_t* table = tab_rec->table;
991 int base_vaddr = tab_rec->vaddr;
Bill Buzbeea114add2012-05-03 15:00:40 -0700992 int entries = table[1];
buzbeecbd6d442012-11-17 14:11:25 -0800993 const int* keys = reinterpret_cast<const int*>(&table[2]);
994 const int* targets = &keys[entries];
Bill Buzbeea114add2012-05-03 15:00:40 -0700995 for (int i = 0; i < entries; i++) {
buzbee1fd33462013-03-25 13:40:45 -0700996 tab_rec->targets[i] = InsertCaseLabel(base_vaddr + targets[i], keys[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700997 }
buzbee31a4a6f2012-02-28 15:36:15 -0800998}
999
buzbee1fd33462013-03-25 13:40:45 -07001000void Mir2Lir::ProcessSwitchTables()
buzbee31a4a6f2012-02-28 15:36:15 -08001001{
buzbee862a7602013-04-05 10:58:54 -07001002 GrowableArray<SwitchTable*>::Iterator iterator(&switch_tables_);
Bill Buzbeea114add2012-05-03 15:00:40 -07001003 while (true) {
buzbee862a7602013-04-05 10:58:54 -07001004 Mir2Lir::SwitchTable *tab_rec = iterator.Next();
buzbeefa57c472012-11-21 12:06:18 -08001005 if (tab_rec == NULL) break;
1006 if (tab_rec->table[0] == Instruction::kPackedSwitchSignature) {
buzbee1fd33462013-03-25 13:40:45 -07001007 MarkPackedCaseLabels(tab_rec);
buzbeefa57c472012-11-21 12:06:18 -08001008 } else if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) {
buzbee1fd33462013-03-25 13:40:45 -07001009 MarkSparseCaseLabels(tab_rec);
Bill Buzbeea114add2012-05-03 15:00:40 -07001010 } else {
1011 LOG(FATAL) << "Invalid switch table";
buzbee31a4a6f2012-02-28 15:36:15 -08001012 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001013 }
buzbee31a4a6f2012-02-28 15:36:15 -08001014}
1015
buzbee1fd33462013-03-25 13:40:45 -07001016void Mir2Lir::DumpSparseSwitchTable(const uint16_t* table)
Bill Buzbeea114add2012-05-03 15:00:40 -07001017 /*
1018 * Sparse switch data format:
1019 * ushort ident = 0x0200 magic value
1020 * ushort size number of entries in the table; > 0
1021 * int keys[size] keys, sorted low-to-high; 32-bit aligned
1022 * int targets[size] branch targets, relative to switch opcode
1023 *
1024 * Total size is (2+size*4) 16-bit code units.
1025 */
buzbee31a4a6f2012-02-28 15:36:15 -08001026{
buzbeeeaf09bc2012-11-15 14:51:41 -08001027 uint16_t ident = table[0];
Bill Buzbeea114add2012-05-03 15:00:40 -07001028 int entries = table[1];
buzbeecbd6d442012-11-17 14:11:25 -08001029 const int* keys = reinterpret_cast<const int*>(&table[2]);
1030 const int* targets = &keys[entries];
Bill Buzbeea114add2012-05-03 15:00:40 -07001031 LOG(INFO) << "Sparse switch table - ident:0x" << std::hex << ident
1032 << ", entries: " << std::dec << entries;
1033 for (int i = 0; i < entries; i++) {
1034 LOG(INFO) << " Key[" << keys[i] << "] -> 0x" << std::hex << targets[i];
1035 }
buzbee31a4a6f2012-02-28 15:36:15 -08001036}
1037
buzbee1fd33462013-03-25 13:40:45 -07001038void Mir2Lir::DumpPackedSwitchTable(const uint16_t* table)
Bill Buzbeea114add2012-05-03 15:00:40 -07001039 /*
1040 * Packed switch data format:
1041 * ushort ident = 0x0100 magic value
1042 * ushort size number of entries in the table
1043 * int first_key first (and lowest) switch case value
1044 * int targets[size] branch targets, relative to switch opcode
1045 *
1046 * Total size is (4+size*2) 16-bit code units.
1047 */
buzbee31a4a6f2012-02-28 15:36:15 -08001048{
buzbeeeaf09bc2012-11-15 14:51:41 -08001049 uint16_t ident = table[0];
buzbeecbd6d442012-11-17 14:11:25 -08001050 const int* targets = reinterpret_cast<const int*>(&table[4]);
Bill Buzbeea114add2012-05-03 15:00:40 -07001051 int entries = table[1];
buzbeefa57c472012-11-21 12:06:18 -08001052 int low_key = s4FromSwitchData(&table[2]);
Bill Buzbeea114add2012-05-03 15:00:40 -07001053 LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident
buzbeefa57c472012-11-21 12:06:18 -08001054 << ", entries: " << std::dec << entries << ", low_key: " << low_key;
Bill Buzbeea114add2012-05-03 15:00:40 -07001055 for (int i = 0; i < entries; i++) {
buzbeefa57c472012-11-21 12:06:18 -08001056 LOG(INFO) << " Key[" << (i + low_key) << "] -> 0x" << std::hex
Bill Buzbeea114add2012-05-03 15:00:40 -07001057 << targets[i];
1058 }
buzbee31a4a6f2012-02-28 15:36:15 -08001059}
buzbeee3acd072012-02-25 17:03:10 -08001060
buzbeed1643e42012-09-05 14:06:51 -07001061/*
1062 * Set up special LIR to mark a Dalvik byte-code instruction start and
buzbeefa57c472012-11-21 12:06:18 -08001063 * record it in the boundary_map. NOTE: in cases such as kMirOpCheck in
buzbeed1643e42012-09-05 14:06:51 -07001064 * which we split a single Dalvik instruction, only the first MIR op
1065 * associated with a Dalvik PC should be entered into the map.
1066 */
buzbee1fd33462013-03-25 13:40:45 -07001067LIR* Mir2Lir::MarkBoundary(int offset, const char* inst_str)
buzbeed1643e42012-09-05 14:06:51 -07001068{
buzbee1fd33462013-03-25 13:40:45 -07001069 LIR* res = NewLIR1(kPseudoDalvikByteCodeBoundary, reinterpret_cast<uintptr_t>(inst_str));
1070 if (boundary_map_.find(offset) == boundary_map_.end()) {
1071 boundary_map_.Put(offset, res);
buzbeed1643e42012-09-05 14:06:51 -07001072 }
1073 return res;
1074}
buzbeee3acd072012-02-25 17:03:10 -08001075
buzbee1fd33462013-03-25 13:40:45 -07001076bool Mir2Lir::EvaluateBranch(Instruction::Code opcode, int32_t src1, int32_t src2)
buzbeee6285f92012-12-06 15:57:46 -08001077{
1078 bool is_taken;
1079 switch (opcode) {
1080 case Instruction::IF_EQ: is_taken = (src1 == src2); break;
1081 case Instruction::IF_NE: is_taken = (src1 != src2); break;
1082 case Instruction::IF_LT: is_taken = (src1 < src2); break;
1083 case Instruction::IF_GE: is_taken = (src1 >= src2); break;
1084 case Instruction::IF_GT: is_taken = (src1 > src2); break;
1085 case Instruction::IF_LE: is_taken = (src1 <= src2); break;
1086 case Instruction::IF_EQZ: is_taken = (src1 == 0); break;
1087 case Instruction::IF_NEZ: is_taken = (src1 != 0); break;
1088 case Instruction::IF_LTZ: is_taken = (src1 < 0); break;
1089 case Instruction::IF_GEZ: is_taken = (src1 >= 0); break;
1090 case Instruction::IF_GTZ: is_taken = (src1 > 0); break;
1091 case Instruction::IF_LEZ: is_taken = (src1 <= 0); break;
1092 default:
1093 LOG(FATAL) << "Unexpected opcode " << opcode;
1094 is_taken = false;
1095 }
1096 return is_taken;
1097}
1098
buzbee4ef3e452012-12-14 13:35:28 -08001099// Convert relation of src1/src2 to src2/src1
buzbee1fd33462013-03-25 13:40:45 -07001100ConditionCode Mir2Lir::FlipComparisonOrder(ConditionCode before) {
buzbee4ef3e452012-12-14 13:35:28 -08001101 ConditionCode res;
1102 switch (before) {
1103 case kCondEq: res = kCondEq; break;
1104 case kCondNe: res = kCondNe; break;
1105 case kCondLt: res = kCondGt; break;
1106 case kCondGt: res = kCondLt; break;
1107 case kCondLe: res = kCondGe; break;
1108 case kCondGe: res = kCondLe; break;
1109 default:
1110 res = static_cast<ConditionCode>(0);
1111 LOG(FATAL) << "Unexpected ccode " << before;
1112 }
1113 return res;
1114}
1115
buzbee862a7602013-04-05 10:58:54 -07001116// TODO: move to mir_to_lir.cc
1117Mir2Lir::Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
Ian Rogers6282dc12013-04-18 15:54:02 -07001118 : Backend(arena),
1119 literal_list_(NULL),
buzbee1fd33462013-03-25 13:40:45 -07001120 method_literal_list_(NULL),
1121 code_literal_list_(NULL),
1122 cu_(cu),
1123 mir_graph_(mir_graph),
buzbee862a7602013-04-05 10:58:54 -07001124 switch_tables_(arena, 4, kGrowableArraySwitchTables),
1125 fill_array_data_(arena, 4, kGrowableArrayFillArrayData),
1126 throw_launchpads_(arena, 2048, kGrowableArrayThrowLaunchPads),
1127 suspend_launchpads_(arena, 4, kGrowableArraySuspendLaunchPads),
1128 intrinsic_launchpads_(arena, 2048, kGrowableArrayMisc),
buzbee1fd33462013-03-25 13:40:45 -07001129 data_offset_(0),
1130 total_size_(0),
1131 block_label_list_(NULL),
buzbee862a7602013-04-05 10:58:54 -07001132 current_dalvik_offset_(0),
1133 reg_pool_(NULL),
buzbee1fd33462013-03-25 13:40:45 -07001134 live_sreg_(0),
1135 num_core_spills_(0),
1136 num_fp_spills_(0),
1137 frame_size_(0),
1138 core_spill_mask_(0),
1139 fp_spill_mask_(0),
1140 first_lir_insn_(NULL),
1141 last_lir_insn_(NULL)
1142 {
buzbee1fd33462013-03-25 13:40:45 -07001143 promotion_map_ = static_cast<PromotionMap*>
buzbee862a7602013-04-05 10:58:54 -07001144 (arena_->NewMem((cu_->num_dalvik_registers + cu_->num_compiler_temps + 1) *
1145 sizeof(promotion_map_[0]), true, ArenaAllocator::kAllocRegAlloc));
buzbee1fd33462013-03-25 13:40:45 -07001146}
1147
1148void Mir2Lir::Materialize() {
1149 CompilerInitializeRegAlloc(); // Needs to happen after SSA naming
1150
1151 /* Allocate Registers using simple local allocation scheme */
1152 SimpleRegAlloc();
1153
1154 //FIXME: re-enable by retrieving from mir_graph
1155 SpecialCaseHandler special_case = kNoHandler;
1156
1157 if (special_case != kNoHandler) {
1158 /*
1159 * Custom codegen for special cases. If for any reason the
1160 * special codegen doesn't succeed, first_lir_insn_ will
1161 * set to NULL;
1162 */
1163 SpecialMIR2LIR(special_case);
1164 }
1165
1166 /* Convert MIR to LIR, etc. */
1167 if (first_lir_insn_ == NULL) {
1168 MethodMIR2LIR();
1169 }
1170
1171 /* Method is not empty */
1172 if (first_lir_insn_) {
1173
1174 // mark the targets of switch statement case labels
1175 ProcessSwitchTables();
1176
1177 /* Convert LIR into machine code. */
1178 AssembleLIR();
1179
1180 if (cu_->verbose) {
1181 CodegenDump();
1182 }
1183
1184 }
1185
1186}
1187
1188CompiledMethod* Mir2Lir::GetCompiledMethod() {
1189 // Combine vmap tables - core regs, then fp regs - into vmap_table
1190 std::vector<uint16_t> vmap_table;
1191 // Core regs may have been inserted out of order - sort first
1192 std::sort(core_vmap_table_.begin(), core_vmap_table_.end());
1193 for (size_t i = 0 ; i < core_vmap_table_.size(); i++) {
1194 // Copy, stripping out the phys register sort key
1195 vmap_table.push_back(~(-1 << VREG_NUM_WIDTH) & core_vmap_table_[i]);
1196 }
1197 // If we have a frame, push a marker to take place of lr
1198 if (frame_size_ > 0) {
1199 vmap_table.push_back(INVALID_VREG);
1200 } else {
1201 DCHECK_EQ(__builtin_popcount(core_spill_mask_), 0);
1202 DCHECK_EQ(__builtin_popcount(fp_spill_mask_), 0);
1203 }
1204 // Combine vmap tables - core regs, then fp regs. fp regs already sorted
1205 for (uint32_t i = 0; i < fp_vmap_table_.size(); i++) {
1206 vmap_table.push_back(fp_vmap_table_[i]);
1207 }
1208 CompiledMethod* result =
1209 new CompiledMethod(cu_->instruction_set, code_buffer_,
1210 frame_size_, core_spill_mask_, fp_spill_mask_,
1211 combined_mapping_table_, vmap_table, native_gc_map_);
1212 return result;
1213}
1214
1215int Mir2Lir::ComputeFrameSize() {
1216 /* Figure out the frame size */
1217 static const uint32_t kAlignMask = kStackAlignment - 1;
1218 uint32_t size = (num_core_spills_ + num_fp_spills_ +
1219 1 /* filler word */ + cu_->num_regs + cu_->num_outs +
1220 cu_->num_compiler_temps + 1 /* cur_method* */)
1221 * sizeof(uint32_t);
1222 /* Align and set */
1223 return (size + kAlignMask) & ~(kAlignMask);
1224}
1225
1226/*
1227 * Append an LIR instruction to the LIR list maintained by a compilation
1228 * unit
1229 */
1230void Mir2Lir::AppendLIR(LIR* lir)
1231{
1232 if (first_lir_insn_ == NULL) {
1233 DCHECK(last_lir_insn_ == NULL);
1234 last_lir_insn_ = first_lir_insn_ = lir;
1235 lir->prev = lir->next = NULL;
1236 } else {
1237 last_lir_insn_->next = lir;
1238 lir->prev = last_lir_insn_;
1239 lir->next = NULL;
1240 last_lir_insn_ = lir;
1241 }
1242}
1243
1244/*
1245 * Insert an LIR instruction before the current instruction, which cannot be the
1246 * first instruction.
1247 *
1248 * prev_lir <-> new_lir <-> current_lir
1249 */
1250void Mir2Lir::InsertLIRBefore(LIR* current_lir, LIR* new_lir)
1251{
1252 DCHECK(current_lir->prev != NULL);
1253 LIR *prev_lir = current_lir->prev;
1254
1255 prev_lir->next = new_lir;
1256 new_lir->prev = prev_lir;
1257 new_lir->next = current_lir;
1258 current_lir->prev = new_lir;
1259}
1260
1261/*
1262 * Insert an LIR instruction after the current instruction, which cannot be the
1263 * first instruction.
1264 *
1265 * current_lir -> new_lir -> old_next
1266 */
1267void Mir2Lir::InsertLIRAfter(LIR* current_lir, LIR* new_lir)
1268{
1269 new_lir->prev = current_lir;
1270 new_lir->next = current_lir->next;
1271 current_lir->next = new_lir;
1272 new_lir->next->prev = new_lir;
1273}
1274
1275
buzbeea3a82b22012-11-27 16:09:55 -08001276} // namespace art