blob: 91422eab775ca546aeb52e3ce7d98bdb6bbaf2f7 [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{
buzbee1fd33462013-03-25 13:40:45 -0700368 LIR* insn = static_cast<LIR*>(NewMem(cu_, sizeof(LIR), true, 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) {
buzbee1fd33462013-03-25 13:40:45 -0700502 LIR* new_value = static_cast<LIR*>(NewMem(cu_, sizeof(LIR), true, 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{
Bill Buzbeea114add2012-05-03 15:00:40 -0700576 GrowableListIterator iterator;
buzbee1fd33462013-03-25 13:40:45 -0700577 GrowableListIteratorInit(&switch_tables_, &iterator);
Bill Buzbeea114add2012-05-03 15:00:40 -0700578 while (true) {
buzbee1fd33462013-03-25 13:40:45 -0700579 Mir2Lir::SwitchTable* tab_rec =
580 reinterpret_cast<Mir2Lir::SwitchTable*>(GrowableListIteratorNext( &iterator));
buzbeefa57c472012-11-21 12:06:18 -0800581 if (tab_rec == NULL) break;
buzbee1fd33462013-03-25 13:40:45 -0700582 AlignBuffer(code_buffer_, tab_rec->offset);
Bill Buzbeea114add2012-05-03 15:00:40 -0700583 /*
584 * For Arm, our reference point is the address of the bx
585 * instruction that does the launch, so we have to subtract
586 * the auto pc-advance. For other targets the reference point
587 * is a label, so we can use the offset as-is.
588 */
buzbeefa57c472012-11-21 12:06:18 -0800589 int bx_offset = INVALID_OFFSET;
buzbee1fd33462013-03-25 13:40:45 -0700590 switch (cu_->instruction_set) {
buzbeeb046e162012-10-30 15:48:42 -0700591 case kThumb2:
buzbeefa57c472012-11-21 12:06:18 -0800592 bx_offset = tab_rec->anchor->offset + 4;
buzbeeb046e162012-10-30 15:48:42 -0700593 break;
594 case kX86:
buzbeefa57c472012-11-21 12:06:18 -0800595 bx_offset = 0;
buzbeeb046e162012-10-30 15:48:42 -0700596 break;
597 case kMips:
buzbeefa57c472012-11-21 12:06:18 -0800598 bx_offset = tab_rec->anchor->offset;
buzbeeb046e162012-10-30 15:48:42 -0700599 break;
buzbee1fd33462013-03-25 13:40:45 -0700600 default: LOG(FATAL) << "Unexpected instruction set: " << cu_->instruction_set;
buzbeeb046e162012-10-30 15:48:42 -0700601 }
buzbee1fd33462013-03-25 13:40:45 -0700602 if (cu_->verbose) {
buzbeefa57c472012-11-21 12:06:18 -0800603 LOG(INFO) << "Switch table for offset 0x" << std::hex << bx_offset;
buzbeee3acd072012-02-25 17:03:10 -0800604 }
buzbeefa57c472012-11-21 12:06:18 -0800605 if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) {
606 const int* keys = reinterpret_cast<const int*>(&(tab_rec->table[2]));
607 for (int elems = 0; elems < tab_rec->table[1]; elems++) {
608 int disp = tab_rec->targets[elems]->offset - bx_offset;
buzbee1fd33462013-03-25 13:40:45 -0700609 if (cu_->verbose) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700610 LOG(INFO) << " Case[" << elems << "] key: 0x"
611 << std::hex << keys[elems] << ", disp: 0x"
612 << std::hex << disp;
613 }
buzbee1fd33462013-03-25 13:40:45 -0700614 PushWord(code_buffer_, keys[elems]);
615 PushWord(code_buffer_,
buzbeefa57c472012-11-21 12:06:18 -0800616 tab_rec->targets[elems]->offset - bx_offset);
Bill Buzbeea114add2012-05-03 15:00:40 -0700617 }
618 } else {
buzbeefa57c472012-11-21 12:06:18 -0800619 DCHECK_EQ(static_cast<int>(tab_rec->table[0]),
Bill Buzbeea114add2012-05-03 15:00:40 -0700620 static_cast<int>(Instruction::kPackedSwitchSignature));
buzbeefa57c472012-11-21 12:06:18 -0800621 for (int elems = 0; elems < tab_rec->table[1]; elems++) {
622 int disp = tab_rec->targets[elems]->offset - bx_offset;
buzbee1fd33462013-03-25 13:40:45 -0700623 if (cu_->verbose) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700624 LOG(INFO) << " Case[" << elems << "] disp: 0x"
625 << std::hex << disp;
626 }
buzbee1fd33462013-03-25 13:40:45 -0700627 PushWord(code_buffer_, tab_rec->targets[elems]->offset - bx_offset);
Bill Buzbeea114add2012-05-03 15:00:40 -0700628 }
629 }
630 }
buzbeee3acd072012-02-25 17:03:10 -0800631}
632
633/* Write the fill array dta to the output stream */
buzbee1fd33462013-03-25 13:40:45 -0700634void Mir2Lir::InstallFillArrayData()
buzbeee3acd072012-02-25 17:03:10 -0800635{
Bill Buzbeea114add2012-05-03 15:00:40 -0700636 GrowableListIterator iterator;
buzbee1fd33462013-03-25 13:40:45 -0700637 GrowableListIteratorInit(&fill_array_data_, &iterator);
Bill Buzbeea114add2012-05-03 15:00:40 -0700638 while (true) {
buzbee1fd33462013-03-25 13:40:45 -0700639 Mir2Lir::FillArrayData *tab_rec =
640 reinterpret_cast<Mir2Lir::FillArrayData*>(GrowableListIteratorNext( &iterator));
buzbeefa57c472012-11-21 12:06:18 -0800641 if (tab_rec == NULL) break;
buzbee1fd33462013-03-25 13:40:45 -0700642 AlignBuffer(code_buffer_, tab_rec->offset);
buzbeefa57c472012-11-21 12:06:18 -0800643 for (int i = 0; i < (tab_rec->size + 1) / 2; i++) {
buzbee1fd33462013-03-25 13:40:45 -0700644 code_buffer_.push_back( tab_rec->table[i] & 0xFF);
645 code_buffer_.push_back( (tab_rec->table[i] >> 8) & 0xFF);
buzbeee3acd072012-02-25 17:03:10 -0800646 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700647 }
buzbeee3acd072012-02-25 17:03:10 -0800648}
649
buzbeeaad94382012-11-21 07:40:50 -0800650static int AssignLiteralOffsetCommon(LIR* lir, int offset)
buzbeee3acd072012-02-25 17:03:10 -0800651{
Bill Buzbeea114add2012-05-03 15:00:40 -0700652 for (;lir != NULL; lir = lir->next) {
653 lir->offset = offset;
654 offset += 4;
655 }
656 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800657}
658
buzbee6459e7c2012-10-02 14:42:41 -0700659// Make sure we have a code address for every declared catch entry
buzbee1fd33462013-03-25 13:40:45 -0700660bool Mir2Lir::VerifyCatchEntries()
buzbee6459e7c2012-10-02 14:42:41 -0700661{
662 bool success = true;
buzbee1fd33462013-03-25 13:40:45 -0700663 for (std::set<uint32_t>::const_iterator it = mir_graph_->catches_.begin();
664 it != mir_graph_->catches_.end(); ++it) {
buzbeefa57c472012-11-21 12:06:18 -0800665 uint32_t dex_pc = *it;
buzbee6459e7c2012-10-02 14:42:41 -0700666 bool found = false;
buzbee1fd33462013-03-25 13:40:45 -0700667 for (size_t i = 0; i < dex2pc_mapping_table_.size(); i += 2) {
668 if (dex_pc == dex2pc_mapping_table_[i+1]) {
buzbee6459e7c2012-10-02 14:42:41 -0700669 found = true;
670 break;
671 }
672 }
673 if (!found) {
buzbeefa57c472012-11-21 12:06:18 -0800674 LOG(INFO) << "Missing native PC for catch entry @ 0x" << std::hex << dex_pc;
buzbee6459e7c2012-10-02 14:42:41 -0700675 success = false;
676 }
677 }
678 // Now, try in the other direction
buzbee1fd33462013-03-25 13:40:45 -0700679 for (size_t i = 0; i < dex2pc_mapping_table_.size(); i += 2) {
680 uint32_t dex_pc = dex2pc_mapping_table_[i+1];
681 if (mir_graph_->catches_.find(dex_pc) == mir_graph_->catches_.end()) {
buzbeefa57c472012-11-21 12:06:18 -0800682 LOG(INFO) << "Unexpected catch entry @ dex pc 0x" << std::hex << dex_pc;
buzbee6459e7c2012-10-02 14:42:41 -0700683 success = false;
684 }
685 }
686 if (!success) {
buzbee1fd33462013-03-25 13:40:45 -0700687 LOG(INFO) << "Bad dex2pcMapping table in " << PrettyMethod(cu_->method_idx, *cu_->dex_file);
688 LOG(INFO) << "Entries @ decode: " << mir_graph_->catches_.size() << ", Entries in table: "
689 << dex2pc_mapping_table_.size()/2;
buzbee6459e7c2012-10-02 14:42:41 -0700690 }
691 return success;
692}
693
buzbee311ca162013-02-28 15:56:43 -0800694
buzbee1fd33462013-03-25 13:40:45 -0700695void Mir2Lir::CreateMappingTables()
buzbeee3acd072012-02-25 17:03:10 -0800696{
buzbee1fd33462013-03-25 13:40:45 -0700697 for (LIR* tgt_lir = first_lir_insn_; tgt_lir != NULL; tgt_lir = NEXT_LIR(tgt_lir)) {
buzbeefa57c472012-11-21 12:06:18 -0800698 if (!tgt_lir->flags.is_nop && (tgt_lir->opcode == kPseudoSafepointPC)) {
buzbee1fd33462013-03-25 13:40:45 -0700699 pc2dex_mapping_table_.push_back(tgt_lir->offset);
700 pc2dex_mapping_table_.push_back(tgt_lir->dalvik_offset);
Bill Buzbeea5b30242012-09-28 07:19:44 -0700701 }
buzbeefa57c472012-11-21 12:06:18 -0800702 if (!tgt_lir->flags.is_nop && (tgt_lir->opcode == kPseudoExportedPC)) {
buzbee1fd33462013-03-25 13:40:45 -0700703 dex2pc_mapping_table_.push_back(tgt_lir->offset);
704 dex2pc_mapping_table_.push_back(tgt_lir->dalvik_offset);
buzbeee3acd072012-02-25 17:03:10 -0800705 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700706 }
buzbee311ca162013-02-28 15:56:43 -0800707 if (kIsDebugBuild) {
buzbee1fd33462013-03-25 13:40:45 -0700708 DCHECK(VerifyCatchEntries());
buzbee311ca162013-02-28 15:56:43 -0800709 }
buzbee1fd33462013-03-25 13:40:45 -0700710 combined_mapping_table_.push_back(pc2dex_mapping_table_.size() +
711 dex2pc_mapping_table_.size());
712 combined_mapping_table_.push_back(pc2dex_mapping_table_.size());
713 combined_mapping_table_.insert(combined_mapping_table_.end(), pc2dex_mapping_table_.begin(),
714 pc2dex_mapping_table_.end());
715 combined_mapping_table_.insert(combined_mapping_table_.end(), dex2pc_mapping_table_.begin(),
716 dex2pc_mapping_table_.end());
buzbeee3acd072012-02-25 17:03:10 -0800717}
718
Ian Rogers0c7abda2012-09-19 13:33:42 -0700719class NativePcToReferenceMapBuilder {
720 public:
721 NativePcToReferenceMapBuilder(std::vector<uint8_t>* table,
722 size_t entries, uint32_t max_native_offset,
723 size_t references_width) : entries_(entries),
724 references_width_(references_width), in_use_(entries),
725 table_(table) {
726 // Compute width in bytes needed to hold max_native_offset.
727 native_offset_width_ = 0;
728 while (max_native_offset != 0) {
729 native_offset_width_++;
730 max_native_offset >>= 8;
731 }
732 // Resize table and set up header.
733 table->resize((EntryWidth() * entries) + sizeof(uint32_t));
Ian Rogers000d7242012-09-21 16:07:36 -0700734 CHECK_LT(native_offset_width_, 1U << 3);
735 (*table)[0] = native_offset_width_ & 7;
736 CHECK_LT(references_width_, 1U << 13);
737 (*table)[0] |= (references_width_ << 3) & 0xFF;
738 (*table)[1] = (references_width_ >> 5) & 0xFF;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700739 CHECK_LT(entries, 1U << 16);
740 (*table)[2] = entries & 0xFF;
741 (*table)[3] = (entries >> 8) & 0xFF;
742 }
743
744 void AddEntry(uint32_t native_offset, const uint8_t* references) {
745 size_t table_index = TableIndex(native_offset);
746 while (in_use_[table_index]) {
747 table_index = (table_index + 1) % entries_;
748 }
749 in_use_[table_index] = true;
750 SetNativeOffset(table_index, native_offset);
751 DCHECK_EQ(native_offset, GetNativeOffset(table_index));
752 SetReferences(table_index, references);
753 }
754
755 private:
756 size_t TableIndex(uint32_t native_offset) {
757 return NativePcOffsetToReferenceMap::Hash(native_offset) % entries_;
758 }
759
760 uint32_t GetNativeOffset(size_t table_index) {
761 uint32_t native_offset = 0;
762 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
763 for (size_t i = 0; i < native_offset_width_; i++) {
764 native_offset |= (*table_)[table_offset + i] << (i * 8);
765 }
766 return native_offset;
767 }
768
769 void SetNativeOffset(size_t table_index, uint32_t native_offset) {
770 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
771 for (size_t i = 0; i < native_offset_width_; i++) {
772 (*table_)[table_offset + i] = (native_offset >> (i * 8)) & 0xFF;
773 }
774 }
775
776 void SetReferences(size_t table_index, const uint8_t* references) {
777 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
778 memcpy(&(*table_)[table_offset + native_offset_width_], references, references_width_);
779 }
780
781 size_t EntryWidth() const {
782 return native_offset_width_ + references_width_;
783 }
784
785 // Number of entries in the table.
786 const size_t entries_;
787 // Number of bytes used to encode the reference bitmap.
788 const size_t references_width_;
789 // Number of bytes used to encode a native offset.
790 size_t native_offset_width_;
791 // Entries that are in use.
792 std::vector<bool> in_use_;
793 // The table we're building.
794 std::vector<uint8_t>* const table_;
795};
796
buzbee1fd33462013-03-25 13:40:45 -0700797void Mir2Lir::CreateNativeGcMap() {
798 const std::vector<uint32_t>& mapping_table = pc2dex_mapping_table_;
Ian Rogers0c7abda2012-09-19 13:33:42 -0700799 uint32_t max_native_offset = 0;
800 for (size_t i = 0; i < mapping_table.size(); i += 2) {
801 uint32_t native_offset = mapping_table[i + 0];
802 if (native_offset > max_native_offset) {
803 max_native_offset = native_offset;
804 }
805 }
buzbee1fd33462013-03-25 13:40:45 -0700806 CompilerDriver::MethodReference method_ref(cu_->dex_file, cu_->method_idx);
Ian Rogers0c7abda2012-09-19 13:33:42 -0700807 const std::vector<uint8_t>* gc_map_raw = verifier::MethodVerifier::GetDexGcMap(method_ref);
808 verifier::DexPcToReferenceMap dex_gc_map(&(*gc_map_raw)[4], gc_map_raw->size() - 4);
809 // Compute native offset to references size.
buzbee1fd33462013-03-25 13:40:45 -0700810 NativePcToReferenceMapBuilder native_gc_map_builder(&native_gc_map_,
Ian Rogers0c7abda2012-09-19 13:33:42 -0700811 mapping_table.size() / 2, max_native_offset,
812 dex_gc_map.RegWidth());
813
814 for (size_t i = 0; i < mapping_table.size(); i += 2) {
815 uint32_t native_offset = mapping_table[i + 0];
816 uint32_t dex_pc = mapping_table[i + 1];
817 const uint8_t* references = dex_gc_map.FindBitMap(dex_pc, false);
Bill Buzbeea5b30242012-09-28 07:19:44 -0700818 CHECK(references != NULL) << "Missing ref for dex pc 0x" << std::hex << dex_pc;
819 native_gc_map_builder.AddEntry(native_offset, references);
Ian Rogers0c7abda2012-09-19 13:33:42 -0700820 }
821}
822
buzbeee3acd072012-02-25 17:03:10 -0800823/* Determine the offset of each literal field */
buzbee1fd33462013-03-25 13:40:45 -0700824int Mir2Lir::AssignLiteralOffset(int offset)
buzbeee3acd072012-02-25 17:03:10 -0800825{
buzbee1fd33462013-03-25 13:40:45 -0700826 offset = AssignLiteralOffsetCommon(literal_list_, offset);
827 offset = AssignLiteralOffsetCommon(code_literal_list_, offset);
828 offset = AssignLiteralOffsetCommon(method_literal_list_, offset);
Bill Buzbeea114add2012-05-03 15:00:40 -0700829 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800830}
831
buzbee1fd33462013-03-25 13:40:45 -0700832int Mir2Lir::AssignSwitchTablesOffset(int offset)
buzbeee3acd072012-02-25 17:03:10 -0800833{
Bill Buzbeea114add2012-05-03 15:00:40 -0700834 GrowableListIterator iterator;
buzbee1fd33462013-03-25 13:40:45 -0700835 GrowableListIteratorInit(&switch_tables_, &iterator);
Bill Buzbeea114add2012-05-03 15:00:40 -0700836 while (true) {
buzbee1fd33462013-03-25 13:40:45 -0700837 Mir2Lir::SwitchTable *tab_rec =
838 reinterpret_cast<Mir2Lir::SwitchTable*>(GrowableListIteratorNext(&iterator));
buzbeefa57c472012-11-21 12:06:18 -0800839 if (tab_rec == NULL) break;
840 tab_rec->offset = offset;
841 if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) {
842 offset += tab_rec->table[1] * (sizeof(int) * 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700843 } else {
buzbeefa57c472012-11-21 12:06:18 -0800844 DCHECK_EQ(static_cast<int>(tab_rec->table[0]),
Bill Buzbeea114add2012-05-03 15:00:40 -0700845 static_cast<int>(Instruction::kPackedSwitchSignature));
buzbeefa57c472012-11-21 12:06:18 -0800846 offset += tab_rec->table[1] * sizeof(int);
buzbeee3acd072012-02-25 17:03:10 -0800847 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700848 }
849 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800850}
851
buzbee1fd33462013-03-25 13:40:45 -0700852int Mir2Lir::AssignFillArrayDataOffset(int offset)
buzbeee3acd072012-02-25 17:03:10 -0800853{
Bill Buzbeea114add2012-05-03 15:00:40 -0700854 GrowableListIterator iterator;
buzbee1fd33462013-03-25 13:40:45 -0700855 GrowableListIteratorInit(&fill_array_data_, &iterator);
Bill Buzbeea114add2012-05-03 15:00:40 -0700856 while (true) {
buzbee1fd33462013-03-25 13:40:45 -0700857 Mir2Lir::FillArrayData *tab_rec =
858 reinterpret_cast<Mir2Lir::FillArrayData*>(GrowableListIteratorNext(&iterator));
buzbeefa57c472012-11-21 12:06:18 -0800859 if (tab_rec == NULL) break;
860 tab_rec->offset = offset;
861 offset += tab_rec->size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700862 // word align
863 offset = (offset + 3) & ~3;
864 }
865 return offset;
buzbeee3acd072012-02-25 17:03:10 -0800866}
867
buzbeea3a82b22012-11-27 16:09:55 -0800868// LIR offset assignment.
buzbee1fd33462013-03-25 13:40:45 -0700869int Mir2Lir::AssignInsnOffsets()
buzbeea3a82b22012-11-27 16:09:55 -0800870{
871 LIR* lir;
872 int offset = 0;
873
buzbee1fd33462013-03-25 13:40:45 -0700874 for (lir = first_lir_insn_; lir != NULL; lir = NEXT_LIR(lir)) {
buzbeea3a82b22012-11-27 16:09:55 -0800875 lir->offset = offset;
876 if (lir->opcode >= 0) {
877 if (!lir->flags.is_nop) {
878 offset += lir->flags.size;
879 }
880 } else if (lir->opcode == kPseudoPseudoAlign4) {
881 if (offset & 0x2) {
882 offset += 2;
883 lir->operands[0] = 1;
884 } else {
885 lir->operands[0] = 0;
886 }
887 }
888 /* Pseudo opcodes don't consume space */
889 }
890
891 return offset;
892}
893
buzbeee3acd072012-02-25 17:03:10 -0800894/*
895 * Walk the compilation unit and assign offsets to instructions
896 * and literals and compute the total size of the compiled unit.
897 */
buzbee1fd33462013-03-25 13:40:45 -0700898void Mir2Lir::AssignOffsets()
buzbeee3acd072012-02-25 17:03:10 -0800899{
buzbee1fd33462013-03-25 13:40:45 -0700900 int offset = AssignInsnOffsets();
buzbeee3acd072012-02-25 17:03:10 -0800901
Bill Buzbeea114add2012-05-03 15:00:40 -0700902 /* Const values have to be word aligned */
903 offset = (offset + 3) & ~3;
buzbeee3acd072012-02-25 17:03:10 -0800904
Bill Buzbeea114add2012-05-03 15:00:40 -0700905 /* Set up offsets for literals */
buzbee1fd33462013-03-25 13:40:45 -0700906 data_offset_ = offset;
buzbeee3acd072012-02-25 17:03:10 -0800907
buzbee1fd33462013-03-25 13:40:45 -0700908 offset = AssignLiteralOffset(offset);
buzbeee3acd072012-02-25 17:03:10 -0800909
buzbee1fd33462013-03-25 13:40:45 -0700910 offset = AssignSwitchTablesOffset(offset);
buzbeee3acd072012-02-25 17:03:10 -0800911
buzbee1fd33462013-03-25 13:40:45 -0700912 offset = AssignFillArrayDataOffset(offset);
buzbeee3acd072012-02-25 17:03:10 -0800913
buzbee1fd33462013-03-25 13:40:45 -0700914 total_size_ = offset;
buzbeee3acd072012-02-25 17:03:10 -0800915}
916
917/*
918 * Go over each instruction in the list and calculate the offset from the top
919 * before sending them off to the assembler. If out-of-range branch distance is
920 * seen rearrange the instructions a bit to correct it.
921 */
buzbee1fd33462013-03-25 13:40:45 -0700922void Mir2Lir::AssembleLIR()
buzbeee3acd072012-02-25 17:03:10 -0800923{
buzbee1fd33462013-03-25 13:40:45 -0700924 AssignOffsets();
buzbee311ca162013-02-28 15:56:43 -0800925 int assembler_retries = 0;
Bill Buzbeea114add2012-05-03 15:00:40 -0700926 /*
927 * Assemble here. Note that we generate code with optimistic assumptions
928 * and if found now to work, we'll have to redo the sequence and retry.
929 */
buzbeee3acd072012-02-25 17:03:10 -0800930
Bill Buzbeea114add2012-05-03 15:00:40 -0700931 while (true) {
buzbee1fd33462013-03-25 13:40:45 -0700932 AssemblerStatus res = AssembleInstructions(0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700933 if (res == kSuccess) {
934 break;
935 } else {
buzbee311ca162013-02-28 15:56:43 -0800936 assembler_retries++;
937 if (assembler_retries > MAX_ASSEMBLER_RETRIES) {
buzbee1fd33462013-03-25 13:40:45 -0700938 CodegenDump();
Bill Buzbeea114add2012-05-03 15:00:40 -0700939 LOG(FATAL) << "Assembler error - too many retries";
940 }
941 // Redo offsets and try again
buzbee1fd33462013-03-25 13:40:45 -0700942 AssignOffsets();
943 code_buffer_.clear();
buzbeee3acd072012-02-25 17:03:10 -0800944 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700945 }
buzbeee3acd072012-02-25 17:03:10 -0800946
Bill Buzbeea114add2012-05-03 15:00:40 -0700947 // Install literals
buzbee1fd33462013-03-25 13:40:45 -0700948 InstallLiteralPools();
buzbeee3acd072012-02-25 17:03:10 -0800949
Bill Buzbeea114add2012-05-03 15:00:40 -0700950 // Install switch tables
buzbee1fd33462013-03-25 13:40:45 -0700951 InstallSwitchTables();
buzbeee3acd072012-02-25 17:03:10 -0800952
Bill Buzbeea114add2012-05-03 15:00:40 -0700953 // Install fill array data
buzbee1fd33462013-03-25 13:40:45 -0700954 InstallFillArrayData();
buzbeee3acd072012-02-25 17:03:10 -0800955
Ian Rogers0c7abda2012-09-19 13:33:42 -0700956 // Create the mapping table and native offset to reference map.
buzbee1fd33462013-03-25 13:40:45 -0700957 CreateMappingTables();
Ian Rogers0c7abda2012-09-19 13:33:42 -0700958
buzbee1fd33462013-03-25 13:40:45 -0700959 CreateNativeGcMap();
buzbeee3acd072012-02-25 17:03:10 -0800960}
961
buzbee31a4a6f2012-02-28 15:36:15 -0800962/*
963 * Insert a kPseudoCaseLabel at the beginning of the Dalvik
964 * offset vaddr. This label will be used to fix up the case
965 * branch table during the assembly phase. Be sure to set
966 * all resource flags on this to prevent code motion across
967 * target boundaries. KeyVal is just there for debugging.
968 */
buzbee1fd33462013-03-25 13:40:45 -0700969LIR* Mir2Lir::InsertCaseLabel(int vaddr, int keyVal)
buzbee31a4a6f2012-02-28 15:36:15 -0800970{
Bill Buzbeea114add2012-05-03 15:00:40 -0700971 SafeMap<unsigned int, LIR*>::iterator it;
buzbee1fd33462013-03-25 13:40:45 -0700972 it = boundary_map_.find(vaddr);
973 if (it == boundary_map_.end()) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700974 LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr;
975 }
buzbee1fd33462013-03-25 13:40:45 -0700976 LIR* new_label = static_cast<LIR*>(NewMem(cu_, sizeof(LIR), true, kAllocLIR));
buzbeefa57c472012-11-21 12:06:18 -0800977 new_label->dalvik_offset = vaddr;
978 new_label->opcode = kPseudoCaseLabel;
979 new_label->operands[0] = keyVal;
980 InsertLIRAfter(it->second, new_label);
981 return new_label;
buzbee31a4a6f2012-02-28 15:36:15 -0800982}
983
buzbee1fd33462013-03-25 13:40:45 -0700984void Mir2Lir::MarkPackedCaseLabels(Mir2Lir::SwitchTable *tab_rec)
buzbee31a4a6f2012-02-28 15:36:15 -0800985{
buzbeefa57c472012-11-21 12:06:18 -0800986 const uint16_t* table = tab_rec->table;
987 int base_vaddr = tab_rec->vaddr;
buzbeecbd6d442012-11-17 14:11:25 -0800988 const int *targets = reinterpret_cast<const int*>(&table[4]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700989 int entries = table[1];
buzbeefa57c472012-11-21 12:06:18 -0800990 int low_key = s4FromSwitchData(&table[2]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700991 for (int i = 0; i < entries; i++) {
buzbee1fd33462013-03-25 13:40:45 -0700992 tab_rec->targets[i] = InsertCaseLabel(base_vaddr + targets[i], i + low_key);
Bill Buzbeea114add2012-05-03 15:00:40 -0700993 }
buzbee31a4a6f2012-02-28 15:36:15 -0800994}
995
buzbee1fd33462013-03-25 13:40:45 -0700996void Mir2Lir::MarkSparseCaseLabels(Mir2Lir::SwitchTable *tab_rec)
buzbee31a4a6f2012-02-28 15:36:15 -0800997{
buzbeefa57c472012-11-21 12:06:18 -0800998 const uint16_t* table = tab_rec->table;
999 int base_vaddr = tab_rec->vaddr;
Bill Buzbeea114add2012-05-03 15:00:40 -07001000 int entries = table[1];
buzbeecbd6d442012-11-17 14:11:25 -08001001 const int* keys = reinterpret_cast<const int*>(&table[2]);
1002 const int* targets = &keys[entries];
Bill Buzbeea114add2012-05-03 15:00:40 -07001003 for (int i = 0; i < entries; i++) {
buzbee1fd33462013-03-25 13:40:45 -07001004 tab_rec->targets[i] = InsertCaseLabel(base_vaddr + targets[i], keys[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -07001005 }
buzbee31a4a6f2012-02-28 15:36:15 -08001006}
1007
buzbee1fd33462013-03-25 13:40:45 -07001008void Mir2Lir::ProcessSwitchTables()
buzbee31a4a6f2012-02-28 15:36:15 -08001009{
Bill Buzbeea114add2012-05-03 15:00:40 -07001010 GrowableListIterator iterator;
buzbee1fd33462013-03-25 13:40:45 -07001011 GrowableListIteratorInit(&switch_tables_, &iterator);
Bill Buzbeea114add2012-05-03 15:00:40 -07001012 while (true) {
buzbee1fd33462013-03-25 13:40:45 -07001013 Mir2Lir::SwitchTable *tab_rec =
1014 reinterpret_cast<Mir2Lir::SwitchTable*>(GrowableListIteratorNext(&iterator));
buzbeefa57c472012-11-21 12:06:18 -08001015 if (tab_rec == NULL) break;
1016 if (tab_rec->table[0] == Instruction::kPackedSwitchSignature) {
buzbee1fd33462013-03-25 13:40:45 -07001017 MarkPackedCaseLabels(tab_rec);
buzbeefa57c472012-11-21 12:06:18 -08001018 } else if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) {
buzbee1fd33462013-03-25 13:40:45 -07001019 MarkSparseCaseLabels(tab_rec);
Bill Buzbeea114add2012-05-03 15:00:40 -07001020 } else {
1021 LOG(FATAL) << "Invalid switch table";
buzbee31a4a6f2012-02-28 15:36:15 -08001022 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001023 }
buzbee31a4a6f2012-02-28 15:36:15 -08001024}
1025
buzbee1fd33462013-03-25 13:40:45 -07001026void Mir2Lir::DumpSparseSwitchTable(const uint16_t* table)
Bill Buzbeea114add2012-05-03 15:00:40 -07001027 /*
1028 * Sparse switch data format:
1029 * ushort ident = 0x0200 magic value
1030 * ushort size number of entries in the table; > 0
1031 * int keys[size] keys, sorted low-to-high; 32-bit aligned
1032 * int targets[size] branch targets, relative to switch opcode
1033 *
1034 * Total size is (2+size*4) 16-bit code units.
1035 */
buzbee31a4a6f2012-02-28 15:36:15 -08001036{
buzbeeeaf09bc2012-11-15 14:51:41 -08001037 uint16_t ident = table[0];
Bill Buzbeea114add2012-05-03 15:00:40 -07001038 int entries = table[1];
buzbeecbd6d442012-11-17 14:11:25 -08001039 const int* keys = reinterpret_cast<const int*>(&table[2]);
1040 const int* targets = &keys[entries];
Bill Buzbeea114add2012-05-03 15:00:40 -07001041 LOG(INFO) << "Sparse switch table - ident:0x" << std::hex << ident
1042 << ", entries: " << std::dec << entries;
1043 for (int i = 0; i < entries; i++) {
1044 LOG(INFO) << " Key[" << keys[i] << "] -> 0x" << std::hex << targets[i];
1045 }
buzbee31a4a6f2012-02-28 15:36:15 -08001046}
1047
buzbee1fd33462013-03-25 13:40:45 -07001048void Mir2Lir::DumpPackedSwitchTable(const uint16_t* table)
Bill Buzbeea114add2012-05-03 15:00:40 -07001049 /*
1050 * Packed switch data format:
1051 * ushort ident = 0x0100 magic value
1052 * ushort size number of entries in the table
1053 * int first_key first (and lowest) switch case value
1054 * int targets[size] branch targets, relative to switch opcode
1055 *
1056 * Total size is (4+size*2) 16-bit code units.
1057 */
buzbee31a4a6f2012-02-28 15:36:15 -08001058{
buzbeeeaf09bc2012-11-15 14:51:41 -08001059 uint16_t ident = table[0];
buzbeecbd6d442012-11-17 14:11:25 -08001060 const int* targets = reinterpret_cast<const int*>(&table[4]);
Bill Buzbeea114add2012-05-03 15:00:40 -07001061 int entries = table[1];
buzbeefa57c472012-11-21 12:06:18 -08001062 int low_key = s4FromSwitchData(&table[2]);
Bill Buzbeea114add2012-05-03 15:00:40 -07001063 LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident
buzbeefa57c472012-11-21 12:06:18 -08001064 << ", entries: " << std::dec << entries << ", low_key: " << low_key;
Bill Buzbeea114add2012-05-03 15:00:40 -07001065 for (int i = 0; i < entries; i++) {
buzbeefa57c472012-11-21 12:06:18 -08001066 LOG(INFO) << " Key[" << (i + low_key) << "] -> 0x" << std::hex
Bill Buzbeea114add2012-05-03 15:00:40 -07001067 << targets[i];
1068 }
buzbee31a4a6f2012-02-28 15:36:15 -08001069}
buzbeee3acd072012-02-25 17:03:10 -08001070
buzbeed1643e42012-09-05 14:06:51 -07001071/*
1072 * Set up special LIR to mark a Dalvik byte-code instruction start and
buzbeefa57c472012-11-21 12:06:18 -08001073 * record it in the boundary_map. NOTE: in cases such as kMirOpCheck in
buzbeed1643e42012-09-05 14:06:51 -07001074 * which we split a single Dalvik instruction, only the first MIR op
1075 * associated with a Dalvik PC should be entered into the map.
1076 */
buzbee1fd33462013-03-25 13:40:45 -07001077LIR* Mir2Lir::MarkBoundary(int offset, const char* inst_str)
buzbeed1643e42012-09-05 14:06:51 -07001078{
buzbee1fd33462013-03-25 13:40:45 -07001079 LIR* res = NewLIR1(kPseudoDalvikByteCodeBoundary, reinterpret_cast<uintptr_t>(inst_str));
1080 if (boundary_map_.find(offset) == boundary_map_.end()) {
1081 boundary_map_.Put(offset, res);
buzbeed1643e42012-09-05 14:06:51 -07001082 }
1083 return res;
1084}
buzbeee3acd072012-02-25 17:03:10 -08001085
buzbee1fd33462013-03-25 13:40:45 -07001086bool Mir2Lir::EvaluateBranch(Instruction::Code opcode, int32_t src1, int32_t src2)
buzbeee6285f92012-12-06 15:57:46 -08001087{
1088 bool is_taken;
1089 switch (opcode) {
1090 case Instruction::IF_EQ: is_taken = (src1 == src2); break;
1091 case Instruction::IF_NE: is_taken = (src1 != src2); break;
1092 case Instruction::IF_LT: is_taken = (src1 < src2); break;
1093 case Instruction::IF_GE: is_taken = (src1 >= src2); break;
1094 case Instruction::IF_GT: is_taken = (src1 > src2); break;
1095 case Instruction::IF_LE: is_taken = (src1 <= src2); break;
1096 case Instruction::IF_EQZ: is_taken = (src1 == 0); break;
1097 case Instruction::IF_NEZ: is_taken = (src1 != 0); break;
1098 case Instruction::IF_LTZ: is_taken = (src1 < 0); break;
1099 case Instruction::IF_GEZ: is_taken = (src1 >= 0); break;
1100 case Instruction::IF_GTZ: is_taken = (src1 > 0); break;
1101 case Instruction::IF_LEZ: is_taken = (src1 <= 0); break;
1102 default:
1103 LOG(FATAL) << "Unexpected opcode " << opcode;
1104 is_taken = false;
1105 }
1106 return is_taken;
1107}
1108
buzbee4ef3e452012-12-14 13:35:28 -08001109// Convert relation of src1/src2 to src2/src1
buzbee1fd33462013-03-25 13:40:45 -07001110ConditionCode Mir2Lir::FlipComparisonOrder(ConditionCode before) {
buzbee4ef3e452012-12-14 13:35:28 -08001111 ConditionCode res;
1112 switch (before) {
1113 case kCondEq: res = kCondEq; break;
1114 case kCondNe: res = kCondNe; break;
1115 case kCondLt: res = kCondGt; break;
1116 case kCondGt: res = kCondLt; break;
1117 case kCondLe: res = kCondGe; break;
1118 case kCondGe: res = kCondLe; break;
1119 default:
1120 res = static_cast<ConditionCode>(0);
1121 LOG(FATAL) << "Unexpected ccode " << before;
1122 }
1123 return res;
1124}
1125
buzbee1fd33462013-03-25 13:40:45 -07001126Mir2Lir::Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph)
1127 : literal_list_(NULL),
1128 method_literal_list_(NULL),
1129 code_literal_list_(NULL),
1130 cu_(cu),
1131 mir_graph_(mir_graph),
1132 data_offset_(0),
1133 total_size_(0),
1134 block_label_list_(NULL),
1135 live_sreg_(0),
1136 num_core_spills_(0),
1137 num_fp_spills_(0),
1138 frame_size_(0),
1139 core_spill_mask_(0),
1140 fp_spill_mask_(0),
1141 first_lir_insn_(NULL),
1142 last_lir_insn_(NULL)
1143 {
1144
1145 CompilerInitGrowableList(cu_, &switch_tables_, 4, kListSwitchTables);
1146 CompilerInitGrowableList(cu_, &fill_array_data_, 4, kListFillArrayData);
1147 CompilerInitGrowableList(cu_, &throw_launchpads_, 2048, kListThrowLaunchPads);
1148 CompilerInitGrowableList(cu_, &intrinsic_launchpads_, 4, kListMisc);
1149 CompilerInitGrowableList(cu_, &suspend_launchpads_, 2048, kListSuspendLaunchPads);
1150 promotion_map_ = static_cast<PromotionMap*>
1151 (NewMem(cu_, (cu_->num_dalvik_registers + cu_->num_compiler_temps + 1) *
1152 sizeof(promotion_map_[0]), true, kAllocRegAlloc));
1153}
1154
1155void Mir2Lir::Materialize() {
1156 CompilerInitializeRegAlloc(); // Needs to happen after SSA naming
1157
1158 /* Allocate Registers using simple local allocation scheme */
1159 SimpleRegAlloc();
1160
1161 //FIXME: re-enable by retrieving from mir_graph
1162 SpecialCaseHandler special_case = kNoHandler;
1163
1164 if (special_case != kNoHandler) {
1165 /*
1166 * Custom codegen for special cases. If for any reason the
1167 * special codegen doesn't succeed, first_lir_insn_ will
1168 * set to NULL;
1169 */
1170 SpecialMIR2LIR(special_case);
1171 }
1172
1173 /* Convert MIR to LIR, etc. */
1174 if (first_lir_insn_ == NULL) {
1175 MethodMIR2LIR();
1176 }
1177
1178 /* Method is not empty */
1179 if (first_lir_insn_) {
1180
1181 // mark the targets of switch statement case labels
1182 ProcessSwitchTables();
1183
1184 /* Convert LIR into machine code. */
1185 AssembleLIR();
1186
1187 if (cu_->verbose) {
1188 CodegenDump();
1189 }
1190
1191 }
1192
1193}
1194
1195CompiledMethod* Mir2Lir::GetCompiledMethod() {
1196 // Combine vmap tables - core regs, then fp regs - into vmap_table
1197 std::vector<uint16_t> vmap_table;
1198 // Core regs may have been inserted out of order - sort first
1199 std::sort(core_vmap_table_.begin(), core_vmap_table_.end());
1200 for (size_t i = 0 ; i < core_vmap_table_.size(); i++) {
1201 // Copy, stripping out the phys register sort key
1202 vmap_table.push_back(~(-1 << VREG_NUM_WIDTH) & core_vmap_table_[i]);
1203 }
1204 // If we have a frame, push a marker to take place of lr
1205 if (frame_size_ > 0) {
1206 vmap_table.push_back(INVALID_VREG);
1207 } else {
1208 DCHECK_EQ(__builtin_popcount(core_spill_mask_), 0);
1209 DCHECK_EQ(__builtin_popcount(fp_spill_mask_), 0);
1210 }
1211 // Combine vmap tables - core regs, then fp regs. fp regs already sorted
1212 for (uint32_t i = 0; i < fp_vmap_table_.size(); i++) {
1213 vmap_table.push_back(fp_vmap_table_[i]);
1214 }
1215 CompiledMethod* result =
1216 new CompiledMethod(cu_->instruction_set, code_buffer_,
1217 frame_size_, core_spill_mask_, fp_spill_mask_,
1218 combined_mapping_table_, vmap_table, native_gc_map_);
1219 return result;
1220}
1221
1222int Mir2Lir::ComputeFrameSize() {
1223 /* Figure out the frame size */
1224 static const uint32_t kAlignMask = kStackAlignment - 1;
1225 uint32_t size = (num_core_spills_ + num_fp_spills_ +
1226 1 /* filler word */ + cu_->num_regs + cu_->num_outs +
1227 cu_->num_compiler_temps + 1 /* cur_method* */)
1228 * sizeof(uint32_t);
1229 /* Align and set */
1230 return (size + kAlignMask) & ~(kAlignMask);
1231}
1232
1233/*
1234 * Append an LIR instruction to the LIR list maintained by a compilation
1235 * unit
1236 */
1237void Mir2Lir::AppendLIR(LIR* lir)
1238{
1239 if (first_lir_insn_ == NULL) {
1240 DCHECK(last_lir_insn_ == NULL);
1241 last_lir_insn_ = first_lir_insn_ = lir;
1242 lir->prev = lir->next = NULL;
1243 } else {
1244 last_lir_insn_->next = lir;
1245 lir->prev = last_lir_insn_;
1246 lir->next = NULL;
1247 last_lir_insn_ = lir;
1248 }
1249}
1250
1251/*
1252 * Insert an LIR instruction before the current instruction, which cannot be the
1253 * first instruction.
1254 *
1255 * prev_lir <-> new_lir <-> current_lir
1256 */
1257void Mir2Lir::InsertLIRBefore(LIR* current_lir, LIR* new_lir)
1258{
1259 DCHECK(current_lir->prev != NULL);
1260 LIR *prev_lir = current_lir->prev;
1261
1262 prev_lir->next = new_lir;
1263 new_lir->prev = prev_lir;
1264 new_lir->next = current_lir;
1265 current_lir->prev = new_lir;
1266}
1267
1268/*
1269 * Insert an LIR instruction after the current instruction, which cannot be the
1270 * first instruction.
1271 *
1272 * current_lir -> new_lir -> old_next
1273 */
1274void Mir2Lir::InsertLIRAfter(LIR* current_lir, LIR* new_lir)
1275{
1276 new_lir->prev = current_lir;
1277 new_lir->next = current_lir->next;
1278 current_lir->next = new_lir;
1279 new_lir->next->prev = new_lir;
1280}
1281
1282
buzbeea3a82b22012-11-27 16:09:55 -08001283} // namespace art