codegen_util.cc revision 7934ac288acfb2552bb0b06ec1f61e5820d924a4
1e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/*
2e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Copyright (C) 2011 The Android Open Source Project
3e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee *
4e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Licensed under the Apache License, Version 2.0 (the "License");
5e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * you may not use this file except in compliance with the License.
6e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * You may obtain a copy of the License at
7e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee *
8e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee *      http://www.apache.org/licenses/LICENSE-2.0
9e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee *
10e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Unless required by applicable law or agreed to in writing, software
11e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * distributed under the License is distributed on an "AS IS" BASIS,
12e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * See the License for the specific language governing permissions and
14e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * limitations under the License.
15e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee */
16e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
177940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/compiler_internals.h"
184f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h"
190c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers#include "gc_map.h"
208d3a117b374352a1853fae9b7306afeaaa9e3b91Ian Rogers#include "mir_to_lir-inl.h"
210c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers#include "verifier/dex_gc_map.h"
220c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers#include "verifier/method_verifier.h"
230c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
24e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbeenamespace art {
25e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
262ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool Mir2Lir::IsInexpensiveConstant(RegLocation rl_src) {
274ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  bool res = false;
284ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (rl_src.is_const) {
294ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if (rl_src.wide) {
304ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (rl_src.fp) {
311fd3346740dfb7f47be9922312b68a4227fada96buzbee         res = InexpensiveConstantDouble(mir_graph_->ConstantValueWide(rl_src));
324ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else {
331fd3346740dfb7f47be9922312b68a4227fada96buzbee         res = InexpensiveConstantLong(mir_graph_->ConstantValueWide(rl_src));
344ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
354ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    } else {
364ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (rl_src.fp) {
371fd3346740dfb7f47be9922312b68a4227fada96buzbee         res = InexpensiveConstantFloat(mir_graph_->ConstantValue(rl_src));
384ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else {
391fd3346740dfb7f47be9922312b68a4227fada96buzbee         res = InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src));
404ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
414ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
424ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
434ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  return res;
444ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
454ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
462ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::MarkSafepointPC(LIR* inst) {
4702031b185b4653e6c72e21f7a51238b903f6d638buzbee  inst->def_mask = ENCODE_ALL;
481fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* safepoint_pc = NewLIR0(kPseudoSafepointPC);
4902031b185b4653e6c72e21f7a51238b903f6d638buzbee  DCHECK_EQ(safepoint_pc->def_mask, ENCODE_ALL);
5002031b185b4653e6c72e21f7a51238b903f6d638buzbee}
5102031b185b4653e6c72e21f7a51238b903f6d638buzbee
522ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool Mir2Lir::FastInstance(uint32_t field_idx, int& field_offset, bool& is_volatile, bool is_put) {
531fd3346740dfb7f47be9922312b68a4227fada96buzbee  return cu_->compiler_driver->ComputeInstanceFieldInfo(
541fd3346740dfb7f47be9922312b68a4227fada96buzbee      field_idx, mir_graph_->GetCurrentDexCompilationUnit(), field_offset, is_volatile, is_put);
5502031b185b4653e6c72e21f7a51238b903f6d638buzbee}
5602031b185b4653e6c72e21f7a51238b903f6d638buzbee
57cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee/* Convert an instruction to a NOP */
58df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstromvoid Mir2Lir::NopLIR(LIR* lir) {
59fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  lir->flags.is_nop = true;
60cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee}
61cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee
622ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::SetMemRefType(LIR* lir, bool is_load, int mem_type) {
63fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  uint64_t *mask_ptr;
64f69863b3039fc621ff4250e262d2a024d5e79ec8Brian Carlstrom  uint64_t mask = ENCODE_MEM;
651fd3346740dfb7f47be9922312b68a4227fada96buzbee  DCHECK(GetTargetInstFlags(lir->opcode) & (IS_LOAD | IS_STORE));
66fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (is_load) {
67fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    mask_ptr = &lir->use_mask;
68a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
69fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    mask_ptr = &lir->def_mask;
70a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
71a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Clear out the memref flags */
72fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  *mask_ptr &= ~mask;
73a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* ..and then add back the one we need */
74fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  switch (mem_type) {
75a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kLiteral:
76fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      DCHECK(is_load);
77fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      *mask_ptr |= ENCODE_LITERAL;
78a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
79a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kDalvikReg:
80fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      *mask_ptr |= ENCODE_DALVIK_REG;
81a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
82a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kHeapRef:
83fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      *mask_ptr |= ENCODE_HEAP_REF;
84a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
85a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kMustNotAlias:
86a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      /* Currently only loads can be marked as kMustNotAlias */
871fd3346740dfb7f47be9922312b68a4227fada96buzbee      DCHECK(!(GetTargetInstFlags(lir->opcode) & IS_STORE));
88fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      *mask_ptr |= ENCODE_MUST_NOT_ALIAS;
89a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
90a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
91fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      LOG(FATAL) << "Oat: invalid memref kind - " << mem_type;
92a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
9331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
9431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
9531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
96b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers * Mark load/store instructions that access Dalvik registers through the stack.
9731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
981fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid Mir2Lir::AnnotateDalvikRegAccess(LIR* lir, int reg_id, bool is_load,
992ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                      bool is64bit) {
1001fd3346740dfb7f47be9922312b68a4227fada96buzbee  SetMemRefType(lir, is_load, kDalvikReg);
10131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
102a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /*
103fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee   * Store the Dalvik register id in alias_info. Mark the MSB if it is a 64-bit
104a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * access.
105a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   */
106fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  lir->alias_info = ENCODE_ALIAS_INFO(reg_id, is64bit);
10731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
10831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
10931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
1105de3494e4297c0d480409da3fecee39173f1d4e1buzbee * Debugging macros
1115de3494e4297c0d480409da3fecee39173f1d4e1buzbee */
1125de3494e4297c0d480409da3fecee39173f1d4e1buzbee#define DUMP_RESOURCE_MASK(X)
1135de3494e4297c0d480409da3fecee39173f1d4e1buzbee
1145de3494e4297c0d480409da3fecee39173f1d4e1buzbee/* Pretty-print a LIR instruction */
1152ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::DumpLIRInsn(LIR* lir, unsigned char* base_addr) {
116a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int offset = lir->offset;
117a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int dest = lir->operands[0];
1181fd3346740dfb7f47be9922312b68a4227fada96buzbee  const bool dump_nop = (cu_->enable_debug & (1 << kDebugShowNops));
119a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee
120a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Handle pseudo-ops individually, and all regular insns as a group */
121a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (lir->opcode) {
122a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoMethodEntry:
123a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "-------- method entry "
1241fd3346740dfb7f47be9922312b68a4227fada96buzbee                << PrettyMethod(cu_->method_idx, *cu_->dex_file);
125a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
126a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoMethodExit:
127a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "-------- Method_Exit";
128a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
129a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoBarrier:
130a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "-------- BARRIER";
131a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
132a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoEntryBlock:
133a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
134a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
135a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoDalvikByteCodeBoundary:
1364ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (lir->operands[0] == 0) {
1374ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee         lir->operands[0] = reinterpret_cast<uintptr_t>("No instruction string");
1384ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
139a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "-------- dalvik offset: 0x" << std::hex
140fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                << lir->dalvik_offset << " @ " << reinterpret_cast<char*>(lir->operands[0]);
141a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
142a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoExitBlock:
143a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
144a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
145a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoPseudoAlign4:
146fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      LOG(INFO) << reinterpret_cast<uintptr_t>(base_addr) + offset << " (0x" << std::hex
147a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                << offset << "): .align4";
148a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
149a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoEHBlockLabel:
150a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "Exception_Handling:";
151a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
152a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoTargetLabel:
153a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoNormalBlockLabel:
154cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(INFO) << "L" << reinterpret_cast<void*>(lir) << ":";
155a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
156a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoThrowTarget:
157cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(INFO) << "LT" << reinterpret_cast<void*>(lir) << ":";
158a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
159a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoIntrinsicRetry:
160cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(INFO) << "IR" << reinterpret_cast<void*>(lir) << ":";
161a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
162a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoSuspendTarget:
163cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(INFO) << "LS" << reinterpret_cast<void*>(lir) << ":";
164a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
1658320f3867c02bae9bef6cdab267820cb7b412781buzbee    case kPseudoSafepointPC:
166fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      LOG(INFO) << "LsafepointPC_0x" << std::hex << lir->offset << "_" << lir->dalvik_offset << ":";
1678320f3867c02bae9bef6cdab267820cb7b412781buzbee      break;
168a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    case kPseudoExportedPC:
169fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      LOG(INFO) << "LexportedPC_0x" << std::hex << lir->offset << "_" << lir->dalvik_offset << ":";
170a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee      break;
171a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoCaseLabel:
172cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(INFO) << "LC" << reinterpret_cast<void*>(lir) << ": Case target 0x"
173a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                << std::hex << lir->operands[0] << "|" << std::dec <<
174a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        lir->operands[0];
175a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
176a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
177fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (lir->flags.is_nop && !dump_nop) {
178a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        break;
179a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      } else {
1801fd3346740dfb7f47be9922312b68a4227fada96buzbee        std::string op_name(BuildInsnString(GetTargetInstName(lir->opcode),
18102031b185b4653e6c72e21f7a51238b903f6d638buzbee                                               lir, base_addr));
1821fd3346740dfb7f47be9922312b68a4227fada96buzbee        std::string op_operands(BuildInsnString(GetTargetInstFmt(lir->opcode),
18302031b185b4653e6c72e21f7a51238b903f6d638buzbee                                                    lir, base_addr));
184a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        LOG(INFO) << StringPrintf("%05x: %-9s%s%s",
185fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                  reinterpret_cast<unsigned int>(base_addr + offset),
186a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                                  op_name.c_str(), op_operands.c_str(),
187fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                  lir->flags.is_nop ? "(nop)" : "");
188a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
189a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
190a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
191a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee
192fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (lir->use_mask && (!lir->flags.is_nop || dump_nop)) {
1932d88862f0752a7a0e65145b088f49dabd49d4284Brian Carlstrom    DUMP_RESOURCE_MASK(DumpResourceMask(lir, lir->use_mask, "use"));
194a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
195fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (lir->def_mask && (!lir->flags.is_nop || dump_nop)) {
1962d88862f0752a7a0e65145b088f49dabd49d4284Brian Carlstrom    DUMP_RESOURCE_MASK(DumpResourceMask(lir, lir->def_mask, "def"));
197a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
1985de3494e4297c0d480409da3fecee39173f1d4e1buzbee}
1995de3494e4297c0d480409da3fecee39173f1d4e1buzbee
2002ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::DumpPromotionMap() {
2011fd3346740dfb7f47be9922312b68a4227fada96buzbee  int num_regs = cu_->num_dalvik_registers + cu_->num_compiler_temps + 1;
202fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  for (int i = 0; i < num_regs; i++) {
2031fd3346740dfb7f47be9922312b68a4227fada96buzbee    PromotionMap v_reg_map = promotion_map_[i];
204a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    std::string buf;
205fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (v_reg_map.fp_location == kLocPhysReg) {
2061fd3346740dfb7f47be9922312b68a4227fada96buzbee      StringAppendF(&buf, " : s%d", v_reg_map.FpReg & FpRegMask());
207a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    }
2089c044ce5f76e9bfa17c4c1979e9f8c99ae100695buzbee
209a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    std::string buf3;
2101fd3346740dfb7f47be9922312b68a4227fada96buzbee    if (i < cu_->num_dalvik_registers) {
211a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      StringAppendF(&buf3, "%02d", i);
2121fd3346740dfb7f47be9922312b68a4227fada96buzbee    } else if (i == mir_graph_->GetMethodSReg()) {
213a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      buf3 = "Method*";
214a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else {
2151fd3346740dfb7f47be9922312b68a4227fada96buzbee      StringAppendF(&buf3, "ct%d", i - cu_->num_dalvik_registers);
2165de3494e4297c0d480409da3fecee39173f1d4e1buzbee    }
217a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee
218a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    LOG(INFO) << StringPrintf("V[%s] -> %s%d%s", buf3.c_str(),
219fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                              v_reg_map.core_location == kLocPhysReg ?
220fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                              "r" : "SP+", v_reg_map.core_location == kLocPhysReg ?
2211fd3346740dfb7f47be9922312b68a4227fada96buzbee                              v_reg_map.core_reg : SRegOffset(i),
222a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                              buf.c_str());
223a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
2245de3494e4297c0d480409da3fecee39173f1d4e1buzbee}
2255de3494e4297c0d480409da3fecee39173f1d4e1buzbee
226a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee/* Dump a mapping table */
2271fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid Mir2Lir::DumpMappingTable(const char* table_name, const std::string& descriptor,
2281fd3346740dfb7f47be9922312b68a4227fada96buzbee                               const std::string& name, const std::string& signature,
2291fd3346740dfb7f47be9922312b68a4227fada96buzbee                               const std::vector<uint32_t>& v) {
230a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee  if (v.size() > 0) {
231a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    std::string line(StringPrintf("\n  %s %s%s_%s_table[%zu] = {", table_name,
232a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee                     descriptor.c_str(), name.c_str(), signature.c_str(), v.size()));
233a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    std::replace(line.begin(), line.end(), ';', '_');
234a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    LOG(INFO) << line;
235a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    for (uint32_t i = 0; i < v.size(); i+=2) {
236a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee      line = StringPrintf("    {0x%05x, 0x%04x},", v[i], v[i+1]);
237a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee      LOG(INFO) << line;
238a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    }
239a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    LOG(INFO) <<"  };\n\n";
240a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee  }
241a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee}
242a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee
2435de3494e4297c0d480409da3fecee39173f1d4e1buzbee/* Dump instructions and constant pool contents */
2442ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::CodegenDump() {
245a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LOG(INFO) << "Dumping LIR insns for "
2461fd3346740dfb7f47be9922312b68a4227fada96buzbee            << PrettyMethod(cu_->method_idx, *cu_->dex_file);
247fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* lir_insn;
2481fd3346740dfb7f47be9922312b68a4227fada96buzbee  int insns_size = cu_->code_item->insns_size_in_code_units_;
2491fd3346740dfb7f47be9922312b68a4227fada96buzbee
2501fd3346740dfb7f47be9922312b68a4227fada96buzbee  LOG(INFO) << "Regs (excluding ins) : " << cu_->num_regs;
2511fd3346740dfb7f47be9922312b68a4227fada96buzbee  LOG(INFO) << "Ins          : " << cu_->num_ins;
2521fd3346740dfb7f47be9922312b68a4227fada96buzbee  LOG(INFO) << "Outs         : " << cu_->num_outs;
2531fd3346740dfb7f47be9922312b68a4227fada96buzbee  LOG(INFO) << "CoreSpills       : " << num_core_spills_;
2541fd3346740dfb7f47be9922312b68a4227fada96buzbee  LOG(INFO) << "FPSpills       : " << num_fp_spills_;
2551fd3346740dfb7f47be9922312b68a4227fada96buzbee  LOG(INFO) << "CompilerTemps    : " << cu_->num_compiler_temps;
2561fd3346740dfb7f47be9922312b68a4227fada96buzbee  LOG(INFO) << "Frame size       : " << frame_size_;
2571fd3346740dfb7f47be9922312b68a4227fada96buzbee  LOG(INFO) << "code size is " << total_size_ <<
258fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    " bytes, Dalvik size is " << insns_size * 2;
259a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LOG(INFO) << "expansion factor: "
2601fd3346740dfb7f47be9922312b68a4227fada96buzbee            << static_cast<float>(total_size_) / static_cast<float>(insns_size * 2);
2611fd3346740dfb7f47be9922312b68a4227fada96buzbee  DumpPromotionMap();
2621fd3346740dfb7f47be9922312b68a4227fada96buzbee  for (lir_insn = first_lir_insn_; lir_insn != NULL; lir_insn = lir_insn->next) {
2631fd3346740dfb7f47be9922312b68a4227fada96buzbee    DumpLIRInsn(lir_insn, 0);
264a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
2651fd3346740dfb7f47be9922312b68a4227fada96buzbee  for (lir_insn = literal_list_; lir_insn != NULL; lir_insn = lir_insn->next) {
266fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)", lir_insn->offset, lir_insn->offset,
267fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                              lir_insn->operands[0]);
268a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
269a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee
270a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  const DexFile::MethodId& method_id =
2711fd3346740dfb7f47be9922312b68a4227fada96buzbee      cu_->dex_file->GetMethodId(cu_->method_idx);
2721fd3346740dfb7f47be9922312b68a4227fada96buzbee  std::string signature(cu_->dex_file->GetMethodSignature(method_id));
2731fd3346740dfb7f47be9922312b68a4227fada96buzbee  std::string name(cu_->dex_file->GetMethodName(method_id));
2741fd3346740dfb7f47be9922312b68a4227fada96buzbee  std::string descriptor(cu_->dex_file->GetMethodDeclaringClassDescriptor(method_id));
275a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee
276a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee  // Dump mapping tables
2771fd3346740dfb7f47be9922312b68a4227fada96buzbee  DumpMappingTable("PC2Dex_MappingTable", descriptor, name, signature, pc2dex_mapping_table_);
2781fd3346740dfb7f47be9922312b68a4227fada96buzbee  DumpMappingTable("Dex2PC_MappingTable", descriptor, name, signature, dex2pc_mapping_table_);
2795de3494e4297c0d480409da3fecee39173f1d4e1buzbee}
2805de3494e4297c0d480409da3fecee39173f1d4e1buzbee
28131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
28231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Search the existing constants in the literal pool for an exact or close match
28331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * within specified delta (greater or equal to 0).
28431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
2852ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* Mir2Lir::ScanLiteralPool(LIR* data_target, int value, unsigned int delta) {
286fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  while (data_target) {
287fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if ((static_cast<unsigned>(value - data_target->operands[0])) <= delta)
288fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      return data_target;
289fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    data_target = data_target->next;
290a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
291a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return NULL;
29231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
29331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
29431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* Search the existing constants in the literal pool for an exact wide match */
2952ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* Mir2Lir::ScanLiteralPoolWide(LIR* data_target, int val_lo, int val_hi) {
296fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool lo_match = false;
297fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* lo_target = NULL;
298fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  while (data_target) {
299fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (lo_match && (data_target->operands[0] == val_hi)) {
3004ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      // Record high word in case we need to expand this later.
3014ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      lo_target->operands[1] = val_hi;
302fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      return lo_target;
30331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
304fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    lo_match = false;
305fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (data_target->operands[0] == val_lo) {
306fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      lo_match = true;
307fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      lo_target = data_target;
308a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    }
309fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    data_target = data_target->next;
310a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
311a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return NULL;
31231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
31331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
31431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
31531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * The following are building blocks to insert constants into the pool or
31631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * instruction streams.
31731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
31831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
3194ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee/* Add a 32-bit constant to the constant pool */
3202ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* Mir2Lir::AddWordData(LIR* *constant_list_p, int value) {
321a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Add the constant to the literal pool */
322fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (constant_list_p) {
323862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee    LIR* new_value = static_cast<LIR*>(arena_->NewMem(sizeof(LIR), true, ArenaAllocator::kAllocData));
324fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    new_value->operands[0] = value;
325fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    new_value->next = *constant_list_p;
326fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    *constant_list_p = new_value;
327fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    return new_value;
328a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
329a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return NULL;
33031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
33131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
33231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* Add a 64-bit constant to the constant pool or mixed with code */
3332ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* Mir2Lir::AddWideData(LIR* *constant_list_p, int val_lo, int val_hi) {
3341fd3346740dfb7f47be9922312b68a4227fada96buzbee  AddWordData(constant_list_p, val_hi);
3351fd3346740dfb7f47be9922312b68a4227fada96buzbee  return AddWordData(constant_list_p, val_lo);
33631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
33731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
338aad94383fc41e8f8770f0b2144f766a2ffa772e7buzbeestatic void PushWord(std::vector<uint8_t>&buf, int data) {
339df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  buf.push_back(data & 0xff);
340df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  buf.push_back((data >> 8) & 0xff);
341df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  buf.push_back((data >> 16) & 0xff);
342df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  buf.push_back((data >> 24) & 0xff);
343e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
344e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
345aad94383fc41e8f8770f0b2144f766a2ffa772e7buzbeestatic void AlignBuffer(std::vector<uint8_t>&buf, size_t offset) {
346a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (buf.size() < offset) {
347a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    buf.push_back(0);
348a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
349e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
350e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
351e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Write the literal pool to the output stream */
3522ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::InstallLiteralPools() {
3531fd3346740dfb7f47be9922312b68a4227fada96buzbee  AlignBuffer(code_buffer_, data_offset_);
3541fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* data_lir = literal_list_;
355fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  while (data_lir != NULL) {
3561fd3346740dfb7f47be9922312b68a4227fada96buzbee    PushWord(code_buffer_, data_lir->operands[0]);
357fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    data_lir = NEXT_LIR(data_lir);
358a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
359a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  // Push code and method literals, record offsets for the compiler to patch.
3601fd3346740dfb7f47be9922312b68a4227fada96buzbee  data_lir = code_literal_list_;
361fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  while (data_lir != NULL) {
362fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    uint32_t target = data_lir->operands[0];
3631fd3346740dfb7f47be9922312b68a4227fada96buzbee    cu_->compiler_driver->AddCodePatch(cu_->dex_file,
3641fd3346740dfb7f47be9922312b68a4227fada96buzbee                                      cu_->method_idx,
3651fd3346740dfb7f47be9922312b68a4227fada96buzbee                                      cu_->invoke_type,
3661212a022fa5f8ef9585d765b1809521812af882cIan Rogers                                      target,
3671212a022fa5f8ef9585d765b1809521812af882cIan Rogers                                      static_cast<InvokeType>(data_lir->operands[1]),
3681fd3346740dfb7f47be9922312b68a4227fada96buzbee                                      code_buffer_.size());
3691fd3346740dfb7f47be9922312b68a4227fada96buzbee    const DexFile::MethodId& id = cu_->dex_file->GetMethodId(target);
370137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    // unique based on target to ensure code deduplication works
371137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
3721fd3346740dfb7f47be9922312b68a4227fada96buzbee    PushWord(code_buffer_, unique_patch_value);
373fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    data_lir = NEXT_LIR(data_lir);
374137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers  }
3751fd3346740dfb7f47be9922312b68a4227fada96buzbee  data_lir = method_literal_list_;
376fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  while (data_lir != NULL) {
377fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    uint32_t target = data_lir->operands[0];
3781fd3346740dfb7f47be9922312b68a4227fada96buzbee    cu_->compiler_driver->AddMethodPatch(cu_->dex_file,
3791fd3346740dfb7f47be9922312b68a4227fada96buzbee                                        cu_->method_idx,
3801fd3346740dfb7f47be9922312b68a4227fada96buzbee                                        cu_->invoke_type,
3811212a022fa5f8ef9585d765b1809521812af882cIan Rogers                                        target,
3821212a022fa5f8ef9585d765b1809521812af882cIan Rogers                                        static_cast<InvokeType>(data_lir->operands[1]),
3831fd3346740dfb7f47be9922312b68a4227fada96buzbee                                        code_buffer_.size());
3841fd3346740dfb7f47be9922312b68a4227fada96buzbee    const DexFile::MethodId& id = cu_->dex_file->GetMethodId(target);
385137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    // unique based on target to ensure code deduplication works
386137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
3871fd3346740dfb7f47be9922312b68a4227fada96buzbee    PushWord(code_buffer_, unique_patch_value);
388fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    data_lir = NEXT_LIR(data_lir);
389a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
390e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
391e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
392e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Write the switch tables to the output stream */
3932ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::InstallSwitchTables() {
394862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee  GrowableArray<SwitchTable*>::Iterator iterator(&switch_tables_);
395a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (true) {
396862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee    Mir2Lir::SwitchTable* tab_rec = iterator.Next();
397fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (tab_rec == NULL) break;
3981fd3346740dfb7f47be9922312b68a4227fada96buzbee    AlignBuffer(code_buffer_, tab_rec->offset);
399a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    /*
400a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee     * For Arm, our reference point is the address of the bx
401a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee     * instruction that does the launch, so we have to subtract
402a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee     * the auto pc-advance.  For other targets the reference point
403a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee     * is a label, so we can use the offset as-is.
404a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee     */
405fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    int bx_offset = INVALID_OFFSET;
4061fd3346740dfb7f47be9922312b68a4227fada96buzbee    switch (cu_->instruction_set) {
407b046e16d8b8da318d6055f9308950131f1255e08buzbee      case kThumb2:
408fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        bx_offset = tab_rec->anchor->offset + 4;
409b046e16d8b8da318d6055f9308950131f1255e08buzbee        break;
410b046e16d8b8da318d6055f9308950131f1255e08buzbee      case kX86:
411fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        bx_offset = 0;
412b046e16d8b8da318d6055f9308950131f1255e08buzbee        break;
413b046e16d8b8da318d6055f9308950131f1255e08buzbee      case kMips:
414fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        bx_offset = tab_rec->anchor->offset;
415b046e16d8b8da318d6055f9308950131f1255e08buzbee        break;
4161fd3346740dfb7f47be9922312b68a4227fada96buzbee      default: LOG(FATAL) << "Unexpected instruction set: " << cu_->instruction_set;
417b046e16d8b8da318d6055f9308950131f1255e08buzbee    }
4181fd3346740dfb7f47be9922312b68a4227fada96buzbee    if (cu_->verbose) {
419fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      LOG(INFO) << "Switch table for offset 0x" << std::hex << bx_offset;
420a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    }
421fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) {
422fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      const int* keys = reinterpret_cast<const int*>(&(tab_rec->table[2]));
423fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      for (int elems = 0; elems < tab_rec->table[1]; elems++) {
424fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        int disp = tab_rec->targets[elems]->offset - bx_offset;
4251fd3346740dfb7f47be9922312b68a4227fada96buzbee        if (cu_->verbose) {
426a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee          LOG(INFO) << "  Case[" << elems << "] key: 0x"
427a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                    << std::hex << keys[elems] << ", disp: 0x"
428a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                    << std::hex << disp;
429e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        }
4301fd3346740dfb7f47be9922312b68a4227fada96buzbee        PushWord(code_buffer_, keys[elems]);
4311fd3346740dfb7f47be9922312b68a4227fada96buzbee        PushWord(code_buffer_,
432fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          tab_rec->targets[elems]->offset - bx_offset);
433a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
434a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else {
435fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      DCHECK_EQ(static_cast<int>(tab_rec->table[0]),
436a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                static_cast<int>(Instruction::kPackedSwitchSignature));
437fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      for (int elems = 0; elems < tab_rec->table[1]; elems++) {
438fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        int disp = tab_rec->targets[elems]->offset - bx_offset;
4391fd3346740dfb7f47be9922312b68a4227fada96buzbee        if (cu_->verbose) {
440a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee          LOG(INFO) << "  Case[" << elems << "] disp: 0x"
441a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                    << std::hex << disp;
442e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        }
4431fd3346740dfb7f47be9922312b68a4227fada96buzbee        PushWord(code_buffer_, tab_rec->targets[elems]->offset - bx_offset);
444a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
445e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
446a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
447e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
448e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
449e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Write the fill array dta to the output stream */
4502ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::InstallFillArrayData() {
451862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee  GrowableArray<FillArrayData*>::Iterator iterator(&fill_array_data_);
452a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (true) {
453862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee    Mir2Lir::FillArrayData *tab_rec = iterator.Next();
454fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (tab_rec == NULL) break;
4551fd3346740dfb7f47be9922312b68a4227fada96buzbee    AlignBuffer(code_buffer_, tab_rec->offset);
456fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    for (int i = 0; i < (tab_rec->size + 1) / 2; i++) {
457df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom      code_buffer_.push_back(tab_rec->table[i] & 0xFF);
458df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom      code_buffer_.push_back((tab_rec->table[i] >> 8) & 0xFF);
459e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
460a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
461e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
462e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
4632ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromstatic int AssignLiteralOffsetCommon(LIR* lir, int offset) {
46402c8cc6d1312a2b55533f02f6369dc7c94672f90Brian Carlstrom  for (; lir != NULL; lir = lir->next) {
465a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    lir->offset = offset;
466a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    offset += 4;
467a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
468a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return offset;
469e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
470e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
4716459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee// Make sure we have a code address for every declared catch entry
4722ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool Mir2Lir::VerifyCatchEntries() {
4736459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  bool success = true;
4741fd3346740dfb7f47be9922312b68a4227fada96buzbee  for (std::set<uint32_t>::const_iterator it = mir_graph_->catches_.begin();
4751fd3346740dfb7f47be9922312b68a4227fada96buzbee       it != mir_graph_->catches_.end(); ++it) {
476fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    uint32_t dex_pc = *it;
4776459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    bool found = false;
4781fd3346740dfb7f47be9922312b68a4227fada96buzbee    for (size_t i = 0; i < dex2pc_mapping_table_.size(); i += 2) {
4791fd3346740dfb7f47be9922312b68a4227fada96buzbee      if (dex_pc == dex2pc_mapping_table_[i+1]) {
4806459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee        found = true;
4816459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee        break;
4826459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee      }
4836459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    }
4846459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    if (!found) {
485fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      LOG(INFO) << "Missing native PC for catch entry @ 0x" << std::hex << dex_pc;
4866459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee      success = false;
4876459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    }
4886459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  }
4896459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  // Now, try in the other direction
4901fd3346740dfb7f47be9922312b68a4227fada96buzbee  for (size_t i = 0; i < dex2pc_mapping_table_.size(); i += 2) {
4911fd3346740dfb7f47be9922312b68a4227fada96buzbee    uint32_t dex_pc = dex2pc_mapping_table_[i+1];
4921fd3346740dfb7f47be9922312b68a4227fada96buzbee    if (mir_graph_->catches_.find(dex_pc) == mir_graph_->catches_.end()) {
493fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      LOG(INFO) << "Unexpected catch entry @ dex pc 0x" << std::hex << dex_pc;
4946459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee      success = false;
4956459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    }
4966459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  }
4976459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  if (!success) {
4981fd3346740dfb7f47be9922312b68a4227fada96buzbee    LOG(INFO) << "Bad dex2pcMapping table in " << PrettyMethod(cu_->method_idx, *cu_->dex_file);
4991fd3346740dfb7f47be9922312b68a4227fada96buzbee    LOG(INFO) << "Entries @ decode: " << mir_graph_->catches_.size() << ", Entries in table: "
5001fd3346740dfb7f47be9922312b68a4227fada96buzbee              << dex2pc_mapping_table_.size()/2;
5016459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  }
5026459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  return success;
5036459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee}
5046459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee
505311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
5062ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::CreateMappingTables() {
5071fd3346740dfb7f47be9922312b68a4227fada96buzbee  for (LIR* tgt_lir = first_lir_insn_; tgt_lir != NULL; tgt_lir = NEXT_LIR(tgt_lir)) {
508fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (!tgt_lir->flags.is_nop && (tgt_lir->opcode == kPseudoSafepointPC)) {
5091fd3346740dfb7f47be9922312b68a4227fada96buzbee      pc2dex_mapping_table_.push_back(tgt_lir->offset);
5101fd3346740dfb7f47be9922312b68a4227fada96buzbee      pc2dex_mapping_table_.push_back(tgt_lir->dalvik_offset);
511a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    }
512fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (!tgt_lir->flags.is_nop && (tgt_lir->opcode == kPseudoExportedPC)) {
5131fd3346740dfb7f47be9922312b68a4227fada96buzbee      dex2pc_mapping_table_.push_back(tgt_lir->offset);
5141fd3346740dfb7f47be9922312b68a4227fada96buzbee      dex2pc_mapping_table_.push_back(tgt_lir->dalvik_offset);
515e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
516a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
517311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  if (kIsDebugBuild) {
5181fd3346740dfb7f47be9922312b68a4227fada96buzbee    DCHECK(VerifyCatchEntries());
519311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
5201fd3346740dfb7f47be9922312b68a4227fada96buzbee  combined_mapping_table_.push_back(pc2dex_mapping_table_.size() +
5211fd3346740dfb7f47be9922312b68a4227fada96buzbee                                        dex2pc_mapping_table_.size());
5221fd3346740dfb7f47be9922312b68a4227fada96buzbee  combined_mapping_table_.push_back(pc2dex_mapping_table_.size());
5231fd3346740dfb7f47be9922312b68a4227fada96buzbee  combined_mapping_table_.insert(combined_mapping_table_.end(), pc2dex_mapping_table_.begin(),
5241fd3346740dfb7f47be9922312b68a4227fada96buzbee                                 pc2dex_mapping_table_.end());
5251fd3346740dfb7f47be9922312b68a4227fada96buzbee  combined_mapping_table_.insert(combined_mapping_table_.end(), dex2pc_mapping_table_.begin(),
5261fd3346740dfb7f47be9922312b68a4227fada96buzbee                                 dex2pc_mapping_table_.end());
527e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
528e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
5290c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogersclass NativePcToReferenceMapBuilder {
5300c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers public:
5310c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  NativePcToReferenceMapBuilder(std::vector<uint8_t>* table,
5320c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers                                size_t entries, uint32_t max_native_offset,
5330c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers                                size_t references_width) : entries_(entries),
5340c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers                                references_width_(references_width), in_use_(entries),
5350c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers                                table_(table) {
5360c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    // Compute width in bytes needed to hold max_native_offset.
5370c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    native_offset_width_ = 0;
5380c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    while (max_native_offset != 0) {
5390c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers      native_offset_width_++;
5400c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers      max_native_offset >>= 8;
5410c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    }
5420c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    // Resize table and set up header.
5430c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    table->resize((EntryWidth() * entries) + sizeof(uint32_t));
544000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers    CHECK_LT(native_offset_width_, 1U << 3);
545000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers    (*table)[0] = native_offset_width_ & 7;
546000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers    CHECK_LT(references_width_, 1U << 13);
547000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers    (*table)[0] |= (references_width_ << 3) & 0xFF;
548000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers    (*table)[1] = (references_width_ >> 5) & 0xFF;
5490c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    CHECK_LT(entries, 1U << 16);
5500c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    (*table)[2] = entries & 0xFF;
5510c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    (*table)[3] = (entries >> 8) & 0xFF;
5520c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
5530c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
5540c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  void AddEntry(uint32_t native_offset, const uint8_t* references) {
5550c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    size_t table_index = TableIndex(native_offset);
5560c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    while (in_use_[table_index]) {
5570c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers      table_index = (table_index + 1) % entries_;
5580c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    }
5590c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    in_use_[table_index] = true;
5600c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    SetNativeOffset(table_index, native_offset);
5610c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    DCHECK_EQ(native_offset, GetNativeOffset(table_index));
5620c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    SetReferences(table_index, references);
5630c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
5640c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
5650c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers private:
5660c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  size_t TableIndex(uint32_t native_offset) {
5670c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    return NativePcOffsetToReferenceMap::Hash(native_offset) % entries_;
5680c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
5690c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
5700c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  uint32_t GetNativeOffset(size_t table_index) {
5710c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    uint32_t native_offset = 0;
5720c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
5730c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    for (size_t i = 0; i < native_offset_width_; i++) {
5740c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers      native_offset |= (*table_)[table_offset + i] << (i * 8);
5750c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    }
5760c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    return native_offset;
5770c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
5780c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
5790c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  void SetNativeOffset(size_t table_index, uint32_t native_offset) {
5800c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
5810c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    for (size_t i = 0; i < native_offset_width_; i++) {
5820c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers      (*table_)[table_offset + i] = (native_offset >> (i * 8)) & 0xFF;
5830c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    }
5840c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
5850c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
5860c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  void SetReferences(size_t table_index, const uint8_t* references) {
5870c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
5880c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    memcpy(&(*table_)[table_offset + native_offset_width_], references, references_width_);
5890c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
5900c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
5910c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  size_t EntryWidth() const {
5920c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    return native_offset_width_ + references_width_;
5930c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
5940c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
5950c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // Number of entries in the table.
5960c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  const size_t entries_;
5970c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // Number of bytes used to encode the reference bitmap.
5980c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  const size_t references_width_;
5990c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // Number of bytes used to encode a native offset.
6000c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  size_t native_offset_width_;
6010c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // Entries that are in use.
6020c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  std::vector<bool> in_use_;
6030c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // The table we're building.
6040c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  std::vector<uint8_t>* const table_;
6050c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers};
6060c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
6071fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid Mir2Lir::CreateNativeGcMap() {
6081fd3346740dfb7f47be9922312b68a4227fada96buzbee  const std::vector<uint32_t>& mapping_table = pc2dex_mapping_table_;
6090c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  uint32_t max_native_offset = 0;
6100c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  for (size_t i = 0; i < mapping_table.size(); i += 2) {
6110c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    uint32_t native_offset = mapping_table[i + 0];
6120c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    if (native_offset > max_native_offset) {
6130c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers      max_native_offset = native_offset;
6140c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    }
6150c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
61651c2467e8771b56e25ae4f17f66522f979f57a7eBrian Carlstrom  MethodReference method_ref(cu_->dex_file, cu_->method_idx);
6170c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  const std::vector<uint8_t>* gc_map_raw = verifier::MethodVerifier::GetDexGcMap(method_ref);
6180c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  verifier::DexPcToReferenceMap dex_gc_map(&(*gc_map_raw)[4], gc_map_raw->size() - 4);
6190c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // Compute native offset to references size.
6201fd3346740dfb7f47be9922312b68a4227fada96buzbee  NativePcToReferenceMapBuilder native_gc_map_builder(&native_gc_map_,
6210c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers                                                      mapping_table.size() / 2, max_native_offset,
6220c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers                                                      dex_gc_map.RegWidth());
6230c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
6240c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  for (size_t i = 0; i < mapping_table.size(); i += 2) {
6250c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    uint32_t native_offset = mapping_table[i + 0];
6260c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    uint32_t dex_pc = mapping_table[i + 1];
6270c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    const uint8_t* references = dex_gc_map.FindBitMap(dex_pc, false);
628a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    CHECK(references != NULL) << "Missing ref for dex pc 0x" << std::hex << dex_pc;
629a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    native_gc_map_builder.AddEntry(native_offset, references);
6300c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
6310c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers}
6320c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
633e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Determine the offset of each literal field */
6342ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromint Mir2Lir::AssignLiteralOffset(int offset) {
6351fd3346740dfb7f47be9922312b68a4227fada96buzbee  offset = AssignLiteralOffsetCommon(literal_list_, offset);
6361fd3346740dfb7f47be9922312b68a4227fada96buzbee  offset = AssignLiteralOffsetCommon(code_literal_list_, offset);
6371fd3346740dfb7f47be9922312b68a4227fada96buzbee  offset = AssignLiteralOffsetCommon(method_literal_list_, offset);
638a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return offset;
639e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
640e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
6412ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromint Mir2Lir::AssignSwitchTablesOffset(int offset) {
642862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee  GrowableArray<SwitchTable*>::Iterator iterator(&switch_tables_);
643a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (true) {
644862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee    Mir2Lir::SwitchTable *tab_rec = iterator.Next();
645fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (tab_rec == NULL) break;
646fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    tab_rec->offset = offset;
647fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) {
648fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      offset += tab_rec->table[1] * (sizeof(int) * 2);
649a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else {
650fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      DCHECK_EQ(static_cast<int>(tab_rec->table[0]),
651a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                static_cast<int>(Instruction::kPackedSwitchSignature));
652fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      offset += tab_rec->table[1] * sizeof(int);
653e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
654a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
655a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return offset;
656e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
657e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
6582ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromint Mir2Lir::AssignFillArrayDataOffset(int offset) {
659862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee  GrowableArray<FillArrayData*>::Iterator iterator(&fill_array_data_);
660a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (true) {
661862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee    Mir2Lir::FillArrayData *tab_rec = iterator.Next();
662fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (tab_rec == NULL) break;
663fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    tab_rec->offset = offset;
664fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    offset += tab_rec->size;
665a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    // word align
666a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    offset = (offset + 3) & ~3;
667a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    }
668a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return offset;
669e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
670e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
671a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee// LIR offset assignment.
6722ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromint Mir2Lir::AssignInsnOffsets() {
673a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee  LIR* lir;
674a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee  int offset = 0;
675a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee
6761fd3346740dfb7f47be9922312b68a4227fada96buzbee  for (lir = first_lir_insn_; lir != NULL; lir = NEXT_LIR(lir)) {
677a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee    lir->offset = offset;
678a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee    if (lir->opcode >= 0) {
679a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee      if (!lir->flags.is_nop) {
680a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee        offset += lir->flags.size;
681a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee      }
682a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee    } else if (lir->opcode == kPseudoPseudoAlign4) {
683a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee      if (offset & 0x2) {
684a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee        offset += 2;
685a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee        lir->operands[0] = 1;
686a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee      } else {
687a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee        lir->operands[0] = 0;
688a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee      }
689a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee    }
690a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee    /* Pseudo opcodes don't consume space */
691a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee  }
692a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee
693a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee  return offset;
694a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee}
695a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee
696e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/*
697e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Walk the compilation unit and assign offsets to instructions
698e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * and literals and compute the total size of the compiled unit.
699e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee */
7002ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::AssignOffsets() {
7011fd3346740dfb7f47be9922312b68a4227fada96buzbee  int offset = AssignInsnOffsets();
702e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
703a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Const values have to be word aligned */
704a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  offset = (offset + 3) & ~3;
705e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
706a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Set up offsets for literals */
7071fd3346740dfb7f47be9922312b68a4227fada96buzbee  data_offset_ = offset;
708e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
7091fd3346740dfb7f47be9922312b68a4227fada96buzbee  offset = AssignLiteralOffset(offset);
710e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
7111fd3346740dfb7f47be9922312b68a4227fada96buzbee  offset = AssignSwitchTablesOffset(offset);
712e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
7131fd3346740dfb7f47be9922312b68a4227fada96buzbee  offset = AssignFillArrayDataOffset(offset);
714e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
7151fd3346740dfb7f47be9922312b68a4227fada96buzbee  total_size_ = offset;
716e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
717e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
718e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/*
719e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Go over each instruction in the list and calculate the offset from the top
720e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * before sending them off to the assembler. If out-of-range branch distance is
721e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * seen rearrange the instructions a bit to correct it.
722e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee */
7232ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::AssembleLIR() {
7241fd3346740dfb7f47be9922312b68a4227fada96buzbee  AssignOffsets();
725311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  int assembler_retries = 0;
726a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /*
727a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Assemble here.  Note that we generate code with optimistic assumptions
728a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * and if found now to work, we'll have to redo the sequence and retry.
729a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   */
730e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
731a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (true) {
7321fd3346740dfb7f47be9922312b68a4227fada96buzbee    AssemblerStatus res = AssembleInstructions(0);
733a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    if (res == kSuccess) {
734a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
735a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else {
736311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      assembler_retries++;
737311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      if (assembler_retries > MAX_ASSEMBLER_RETRIES) {
7381fd3346740dfb7f47be9922312b68a4227fada96buzbee        CodegenDump();
739a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        LOG(FATAL) << "Assembler error - too many retries";
740a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
741a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      // Redo offsets and try again
7421fd3346740dfb7f47be9922312b68a4227fada96buzbee      AssignOffsets();
7431fd3346740dfb7f47be9922312b68a4227fada96buzbee      code_buffer_.clear();
744e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
745a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
746e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
747a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  // Install literals
7481fd3346740dfb7f47be9922312b68a4227fada96buzbee  InstallLiteralPools();
749e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
750a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  // Install switch tables
7511fd3346740dfb7f47be9922312b68a4227fada96buzbee  InstallSwitchTables();
752e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
753a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  // Install fill array data
7541fd3346740dfb7f47be9922312b68a4227fada96buzbee  InstallFillArrayData();
755e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
7560c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // Create the mapping table and native offset to reference map.
7571fd3346740dfb7f47be9922312b68a4227fada96buzbee  CreateMappingTables();
7580c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
7591fd3346740dfb7f47be9922312b68a4227fada96buzbee  CreateNativeGcMap();
760e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
761e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
76231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
76331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Insert a kPseudoCaseLabel at the beginning of the Dalvik
76431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * offset vaddr.  This label will be used to fix up the case
76531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * branch table during the assembly phase.  Be sure to set
76631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * all resource flags on this to prevent code motion across
76731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * target boundaries.  KeyVal is just there for debugging.
76831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
7692ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* Mir2Lir::InsertCaseLabel(int vaddr, int keyVal) {
770a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  SafeMap<unsigned int, LIR*>::iterator it;
7711fd3346740dfb7f47be9922312b68a4227fada96buzbee  it = boundary_map_.find(vaddr);
7721fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (it == boundary_map_.end()) {
773a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr;
774a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
775862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee  LIR* new_label = static_cast<LIR*>(arena_->NewMem(sizeof(LIR), true, ArenaAllocator::kAllocLIR));
776fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  new_label->dalvik_offset = vaddr;
777fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  new_label->opcode = kPseudoCaseLabel;
778fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  new_label->operands[0] = keyVal;
779fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  InsertLIRAfter(it->second, new_label);
780fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  return new_label;
78131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
78231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
7832ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::MarkPackedCaseLabels(Mir2Lir::SwitchTable *tab_rec) {
784fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  const uint16_t* table = tab_rec->table;
785fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int base_vaddr = tab_rec->vaddr;
786cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  const int *targets = reinterpret_cast<const int*>(&table[4]);
787a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int entries = table[1];
788fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int low_key = s4FromSwitchData(&table[2]);
789a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  for (int i = 0; i < entries; i++) {
7901fd3346740dfb7f47be9922312b68a4227fada96buzbee    tab_rec->targets[i] = InsertCaseLabel(base_vaddr + targets[i], i + low_key);
791a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
79231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
79331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
7942ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::MarkSparseCaseLabels(Mir2Lir::SwitchTable *tab_rec) {
795fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  const uint16_t* table = tab_rec->table;
796fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int base_vaddr = tab_rec->vaddr;
797a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int entries = table[1];
798cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  const int* keys = reinterpret_cast<const int*>(&table[2]);
799cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  const int* targets = &keys[entries];
800a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  for (int i = 0; i < entries; i++) {
8011fd3346740dfb7f47be9922312b68a4227fada96buzbee    tab_rec->targets[i] = InsertCaseLabel(base_vaddr + targets[i], keys[i]);
802a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
80331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
80431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
8052ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::ProcessSwitchTables() {
806862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee  GrowableArray<SwitchTable*>::Iterator iterator(&switch_tables_);
807a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (true) {
808862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee    Mir2Lir::SwitchTable *tab_rec = iterator.Next();
809fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (tab_rec == NULL) break;
810fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (tab_rec->table[0] == Instruction::kPackedSwitchSignature) {
8111fd3346740dfb7f47be9922312b68a4227fada96buzbee      MarkPackedCaseLabels(tab_rec);
812fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    } else if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) {
8131fd3346740dfb7f47be9922312b68a4227fada96buzbee      MarkSparseCaseLabels(tab_rec);
814a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else {
815a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(FATAL) << "Invalid switch table";
81631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
817a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
81831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
81931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
8202ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::DumpSparseSwitchTable(const uint16_t* table) {
821a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /*
822a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Sparse switch data format:
823a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  ushort ident = 0x0200   magic value
824a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  ushort size       number of entries in the table; > 0
825a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  int keys[size]      keys, sorted low-to-high; 32-bit aligned
826a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  int targets[size]     branch targets, relative to switch opcode
827a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *
828a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Total size is (2+size*4) 16-bit code units.
829a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   */
830eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee  uint16_t ident = table[0];
831a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int entries = table[1];
832cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  const int* keys = reinterpret_cast<const int*>(&table[2]);
833cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  const int* targets = &keys[entries];
834a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LOG(INFO) <<  "Sparse switch table - ident:0x" << std::hex << ident
835a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee            << ", entries: " << std::dec << entries;
836a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  for (int i = 0; i < entries; i++) {
837a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    LOG(INFO) << "  Key[" << keys[i] << "] -> 0x" << std::hex << targets[i];
838a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
83931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
84031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
8412ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::DumpPackedSwitchTable(const uint16_t* table) {
842a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /*
843a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Packed switch data format:
844a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  ushort ident = 0x0100   magic value
845a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  ushort size       number of entries in the table
846a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  int first_key       first (and lowest) switch case value
847a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  int targets[size]     branch targets, relative to switch opcode
848a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *
849a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Total size is (4+size*2) 16-bit code units.
850a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   */
851eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee  uint16_t ident = table[0];
852cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  const int* targets = reinterpret_cast<const int*>(&table[4]);
853a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int entries = table[1];
854fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int low_key = s4FromSwitchData(&table[2]);
855a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident
856fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee            << ", entries: " << std::dec << entries << ", low_key: " << low_key;
857a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  for (int i = 0; i < entries; i++) {
858fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    LOG(INFO) << "  Key[" << (i + low_key) << "] -> 0x" << std::hex
859a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee              << targets[i];
860a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
86131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
862e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
863d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee/*
864d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee * Set up special LIR to mark a Dalvik byte-code instruction start and
865fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * record it in the boundary_map.  NOTE: in cases such as kMirOpCheck in
866d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee * which we split a single Dalvik instruction, only the first MIR op
867d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee * associated with a Dalvik PC should be entered into the map.
868d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee */
8692ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* Mir2Lir::MarkBoundary(int offset, const char* inst_str) {
8701fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* res = NewLIR1(kPseudoDalvikByteCodeBoundary, reinterpret_cast<uintptr_t>(inst_str));
8711fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (boundary_map_.find(offset) == boundary_map_.end()) {
8721fd3346740dfb7f47be9922312b68a4227fada96buzbee    boundary_map_.Put(offset, res);
873d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee  }
874d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee  return res;
875d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee}
876e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
8772ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool Mir2Lir::EvaluateBranch(Instruction::Code opcode, int32_t src1, int32_t src2) {
878e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  bool is_taken;
879e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  switch (opcode) {
880e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    case Instruction::IF_EQ: is_taken = (src1 == src2); break;
881e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    case Instruction::IF_NE: is_taken = (src1 != src2); break;
882e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    case Instruction::IF_LT: is_taken = (src1 < src2); break;
883e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    case Instruction::IF_GE: is_taken = (src1 >= src2); break;
884e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    case Instruction::IF_GT: is_taken = (src1 > src2); break;
885e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    case Instruction::IF_LE: is_taken = (src1 <= src2); break;
886e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    case Instruction::IF_EQZ: is_taken = (src1 == 0); break;
887e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    case Instruction::IF_NEZ: is_taken = (src1 != 0); break;
888e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    case Instruction::IF_LTZ: is_taken = (src1 < 0); break;
889e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    case Instruction::IF_GEZ: is_taken = (src1 >= 0); break;
890e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    case Instruction::IF_GTZ: is_taken = (src1 > 0); break;
891e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    case Instruction::IF_LEZ: is_taken = (src1 <= 0); break;
892e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    default:
893e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee      LOG(FATAL) << "Unexpected opcode " << opcode;
894e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee      is_taken = false;
895e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  }
896e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  return is_taken;
897e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee}
898e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
8994ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee// Convert relation of src1/src2 to src2/src1
9001fd3346740dfb7f47be9922312b68a4227fada96buzbeeConditionCode Mir2Lir::FlipComparisonOrder(ConditionCode before) {
9014ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  ConditionCode res;
9024ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  switch (before) {
9034ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondEq: res = kCondEq; break;
9044ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondNe: res = kCondNe; break;
9054ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondLt: res = kCondGt; break;
9064ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondGt: res = kCondLt; break;
9074ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondLe: res = kCondGe; break;
9084ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondGe: res = kCondLe; break;
9094ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    default:
9104ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      res = static_cast<ConditionCode>(0);
9114ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      LOG(FATAL) << "Unexpected ccode " << before;
9124ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
9134ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  return res;
9144ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
9154ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
916862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee// TODO: move to mir_to_lir.cc
917862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbeeMir2Lir::Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
9186282dc12440a2072dc06a616160027ff21bd895eIan Rogers    : Backend(arena),
9196282dc12440a2072dc06a616160027ff21bd895eIan Rogers      literal_list_(NULL),
9201fd3346740dfb7f47be9922312b68a4227fada96buzbee      method_literal_list_(NULL),
9211fd3346740dfb7f47be9922312b68a4227fada96buzbee      code_literal_list_(NULL),
9221fd3346740dfb7f47be9922312b68a4227fada96buzbee      cu_(cu),
9231fd3346740dfb7f47be9922312b68a4227fada96buzbee      mir_graph_(mir_graph),
924862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee      switch_tables_(arena, 4, kGrowableArraySwitchTables),
925862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee      fill_array_data_(arena, 4, kGrowableArrayFillArrayData),
926862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee      throw_launchpads_(arena, 2048, kGrowableArrayThrowLaunchPads),
927862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee      suspend_launchpads_(arena, 4, kGrowableArraySuspendLaunchPads),
928862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee      intrinsic_launchpads_(arena, 2048, kGrowableArrayMisc),
9291fd3346740dfb7f47be9922312b68a4227fada96buzbee      data_offset_(0),
9301fd3346740dfb7f47be9922312b68a4227fada96buzbee      total_size_(0),
9311fd3346740dfb7f47be9922312b68a4227fada96buzbee      block_label_list_(NULL),
932862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee      current_dalvik_offset_(0),
933862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee      reg_pool_(NULL),
9341fd3346740dfb7f47be9922312b68a4227fada96buzbee      live_sreg_(0),
9351fd3346740dfb7f47be9922312b68a4227fada96buzbee      num_core_spills_(0),
9361fd3346740dfb7f47be9922312b68a4227fada96buzbee      num_fp_spills_(0),
9371fd3346740dfb7f47be9922312b68a4227fada96buzbee      frame_size_(0),
9381fd3346740dfb7f47be9922312b68a4227fada96buzbee      core_spill_mask_(0),
9391fd3346740dfb7f47be9922312b68a4227fada96buzbee      fp_spill_mask_(0),
9401fd3346740dfb7f47be9922312b68a4227fada96buzbee      first_lir_insn_(NULL),
9412ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom      last_lir_insn_(NULL) {
9421fd3346740dfb7f47be9922312b68a4227fada96buzbee  promotion_map_ = static_cast<PromotionMap*>
943862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee      (arena_->NewMem((cu_->num_dalvik_registers  + cu_->num_compiler_temps + 1) *
944862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee                      sizeof(promotion_map_[0]), true, ArenaAllocator::kAllocRegAlloc));
9451fd3346740dfb7f47be9922312b68a4227fada96buzbee}
9461fd3346740dfb7f47be9922312b68a4227fada96buzbee
9471fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid Mir2Lir::Materialize() {
9481fd3346740dfb7f47be9922312b68a4227fada96buzbee  CompilerInitializeRegAlloc();  // Needs to happen after SSA naming
9491fd3346740dfb7f47be9922312b68a4227fada96buzbee
9501fd3346740dfb7f47be9922312b68a4227fada96buzbee  /* Allocate Registers using simple local allocation scheme */
9511fd3346740dfb7f47be9922312b68a4227fada96buzbee  SimpleRegAlloc();
9521fd3346740dfb7f47be9922312b68a4227fada96buzbee
953479f83c196d5a95e36196eac548dc6019e70a5bebuzbee  if (mir_graph_->IsSpecialCase()) {
9541fd3346740dfb7f47be9922312b68a4227fada96buzbee      /*
9551fd3346740dfb7f47be9922312b68a4227fada96buzbee       * Custom codegen for special cases.  If for any reason the
9561fd3346740dfb7f47be9922312b68a4227fada96buzbee       * special codegen doesn't succeed, first_lir_insn_ will
9571fd3346740dfb7f47be9922312b68a4227fada96buzbee       * set to NULL;
9581fd3346740dfb7f47be9922312b68a4227fada96buzbee       */
959479f83c196d5a95e36196eac548dc6019e70a5bebuzbee      SpecialMIR2LIR(mir_graph_->GetSpecialCase());
9601fd3346740dfb7f47be9922312b68a4227fada96buzbee    }
9611fd3346740dfb7f47be9922312b68a4227fada96buzbee
9621fd3346740dfb7f47be9922312b68a4227fada96buzbee  /* Convert MIR to LIR, etc. */
9631fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (first_lir_insn_ == NULL) {
9641fd3346740dfb7f47be9922312b68a4227fada96buzbee    MethodMIR2LIR();
9651fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
9661fd3346740dfb7f47be9922312b68a4227fada96buzbee
9671fd3346740dfb7f47be9922312b68a4227fada96buzbee  /* Method is not empty */
9681fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (first_lir_insn_) {
9691fd3346740dfb7f47be9922312b68a4227fada96buzbee    // mark the targets of switch statement case labels
9701fd3346740dfb7f47be9922312b68a4227fada96buzbee    ProcessSwitchTables();
9711fd3346740dfb7f47be9922312b68a4227fada96buzbee
9721fd3346740dfb7f47be9922312b68a4227fada96buzbee    /* Convert LIR into machine code. */
9731fd3346740dfb7f47be9922312b68a4227fada96buzbee    AssembleLIR();
9741fd3346740dfb7f47be9922312b68a4227fada96buzbee
9751fd3346740dfb7f47be9922312b68a4227fada96buzbee    if (cu_->verbose) {
9761fd3346740dfb7f47be9922312b68a4227fada96buzbee      CodegenDump();
9771fd3346740dfb7f47be9922312b68a4227fada96buzbee    }
9781fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
9791fd3346740dfb7f47be9922312b68a4227fada96buzbee}
9801fd3346740dfb7f47be9922312b68a4227fada96buzbee
9811fd3346740dfb7f47be9922312b68a4227fada96buzbeeCompiledMethod* Mir2Lir::GetCompiledMethod() {
9821fd3346740dfb7f47be9922312b68a4227fada96buzbee  // Combine vmap tables - core regs, then fp regs - into vmap_table
9831fd3346740dfb7f47be9922312b68a4227fada96buzbee  std::vector<uint16_t> vmap_table;
9841fd3346740dfb7f47be9922312b68a4227fada96buzbee  // Core regs may have been inserted out of order - sort first
9851fd3346740dfb7f47be9922312b68a4227fada96buzbee  std::sort(core_vmap_table_.begin(), core_vmap_table_.end());
9861fd3346740dfb7f47be9922312b68a4227fada96buzbee  for (size_t i = 0 ; i < core_vmap_table_.size(); i++) {
9871fd3346740dfb7f47be9922312b68a4227fada96buzbee    // Copy, stripping out the phys register sort key
9881fd3346740dfb7f47be9922312b68a4227fada96buzbee    vmap_table.push_back(~(-1 << VREG_NUM_WIDTH) & core_vmap_table_[i]);
9891fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
9901fd3346740dfb7f47be9922312b68a4227fada96buzbee  // If we have a frame, push a marker to take place of lr
9911fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (frame_size_ > 0) {
9921fd3346740dfb7f47be9922312b68a4227fada96buzbee    vmap_table.push_back(INVALID_VREG);
9931fd3346740dfb7f47be9922312b68a4227fada96buzbee  } else {
9941fd3346740dfb7f47be9922312b68a4227fada96buzbee    DCHECK_EQ(__builtin_popcount(core_spill_mask_), 0);
9951fd3346740dfb7f47be9922312b68a4227fada96buzbee    DCHECK_EQ(__builtin_popcount(fp_spill_mask_), 0);
9961fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
9971fd3346740dfb7f47be9922312b68a4227fada96buzbee  // Combine vmap tables - core regs, then fp regs. fp regs already sorted
9981fd3346740dfb7f47be9922312b68a4227fada96buzbee  for (uint32_t i = 0; i < fp_vmap_table_.size(); i++) {
9991fd3346740dfb7f47be9922312b68a4227fada96buzbee    vmap_table.push_back(fp_vmap_table_[i]);
10001fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
10011fd3346740dfb7f47be9922312b68a4227fada96buzbee  CompiledMethod* result =
10021fd3346740dfb7f47be9922312b68a4227fada96buzbee      new CompiledMethod(cu_->instruction_set, code_buffer_,
10031fd3346740dfb7f47be9922312b68a4227fada96buzbee                         frame_size_, core_spill_mask_, fp_spill_mask_,
10041fd3346740dfb7f47be9922312b68a4227fada96buzbee                         combined_mapping_table_, vmap_table, native_gc_map_);
10051fd3346740dfb7f47be9922312b68a4227fada96buzbee  return result;
10061fd3346740dfb7f47be9922312b68a4227fada96buzbee}
10071fd3346740dfb7f47be9922312b68a4227fada96buzbee
10081fd3346740dfb7f47be9922312b68a4227fada96buzbeeint Mir2Lir::ComputeFrameSize() {
10091fd3346740dfb7f47be9922312b68a4227fada96buzbee  /* Figure out the frame size */
10101fd3346740dfb7f47be9922312b68a4227fada96buzbee  static const uint32_t kAlignMask = kStackAlignment - 1;
10111fd3346740dfb7f47be9922312b68a4227fada96buzbee  uint32_t size = (num_core_spills_ + num_fp_spills_ +
10121fd3346740dfb7f47be9922312b68a4227fada96buzbee                   1 /* filler word */ + cu_->num_regs + cu_->num_outs +
10131fd3346740dfb7f47be9922312b68a4227fada96buzbee                   cu_->num_compiler_temps + 1 /* cur_method* */)
10141fd3346740dfb7f47be9922312b68a4227fada96buzbee                   * sizeof(uint32_t);
10151fd3346740dfb7f47be9922312b68a4227fada96buzbee  /* Align and set */
10161fd3346740dfb7f47be9922312b68a4227fada96buzbee  return (size + kAlignMask) & ~(kAlignMask);
10171fd3346740dfb7f47be9922312b68a4227fada96buzbee}
10181fd3346740dfb7f47be9922312b68a4227fada96buzbee
10191fd3346740dfb7f47be9922312b68a4227fada96buzbee/*
10201fd3346740dfb7f47be9922312b68a4227fada96buzbee * Append an LIR instruction to the LIR list maintained by a compilation
10211fd3346740dfb7f47be9922312b68a4227fada96buzbee * unit
10221fd3346740dfb7f47be9922312b68a4227fada96buzbee */
10232ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::AppendLIR(LIR* lir) {
10241fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (first_lir_insn_ == NULL) {
10251fd3346740dfb7f47be9922312b68a4227fada96buzbee    DCHECK(last_lir_insn_ == NULL);
10261fd3346740dfb7f47be9922312b68a4227fada96buzbee    last_lir_insn_ = first_lir_insn_ = lir;
10271fd3346740dfb7f47be9922312b68a4227fada96buzbee    lir->prev = lir->next = NULL;
10281fd3346740dfb7f47be9922312b68a4227fada96buzbee  } else {
10291fd3346740dfb7f47be9922312b68a4227fada96buzbee    last_lir_insn_->next = lir;
10301fd3346740dfb7f47be9922312b68a4227fada96buzbee    lir->prev = last_lir_insn_;
10311fd3346740dfb7f47be9922312b68a4227fada96buzbee    lir->next = NULL;
10321fd3346740dfb7f47be9922312b68a4227fada96buzbee    last_lir_insn_ = lir;
10331fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
10341fd3346740dfb7f47be9922312b68a4227fada96buzbee}
10351fd3346740dfb7f47be9922312b68a4227fada96buzbee
10361fd3346740dfb7f47be9922312b68a4227fada96buzbee/*
10371fd3346740dfb7f47be9922312b68a4227fada96buzbee * Insert an LIR instruction before the current instruction, which cannot be the
10381fd3346740dfb7f47be9922312b68a4227fada96buzbee * first instruction.
10391fd3346740dfb7f47be9922312b68a4227fada96buzbee *
10401fd3346740dfb7f47be9922312b68a4227fada96buzbee * prev_lir <-> new_lir <-> current_lir
10411fd3346740dfb7f47be9922312b68a4227fada96buzbee */
10422ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::InsertLIRBefore(LIR* current_lir, LIR* new_lir) {
10431fd3346740dfb7f47be9922312b68a4227fada96buzbee  DCHECK(current_lir->prev != NULL);
10441fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR *prev_lir = current_lir->prev;
10451fd3346740dfb7f47be9922312b68a4227fada96buzbee
10461fd3346740dfb7f47be9922312b68a4227fada96buzbee  prev_lir->next = new_lir;
10471fd3346740dfb7f47be9922312b68a4227fada96buzbee  new_lir->prev = prev_lir;
10481fd3346740dfb7f47be9922312b68a4227fada96buzbee  new_lir->next = current_lir;
10491fd3346740dfb7f47be9922312b68a4227fada96buzbee  current_lir->prev = new_lir;
10501fd3346740dfb7f47be9922312b68a4227fada96buzbee}
10511fd3346740dfb7f47be9922312b68a4227fada96buzbee
10521fd3346740dfb7f47be9922312b68a4227fada96buzbee/*
10531fd3346740dfb7f47be9922312b68a4227fada96buzbee * Insert an LIR instruction after the current instruction, which cannot be the
10541fd3346740dfb7f47be9922312b68a4227fada96buzbee * first instruction.
10551fd3346740dfb7f47be9922312b68a4227fada96buzbee *
10561fd3346740dfb7f47be9922312b68a4227fada96buzbee * current_lir -> new_lir -> old_next
10571fd3346740dfb7f47be9922312b68a4227fada96buzbee */
10582ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid Mir2Lir::InsertLIRAfter(LIR* current_lir, LIR* new_lir) {
10591fd3346740dfb7f47be9922312b68a4227fada96buzbee  new_lir->prev = current_lir;
10601fd3346740dfb7f47be9922312b68a4227fada96buzbee  new_lir->next = current_lir->next;
10611fd3346740dfb7f47be9922312b68a4227fada96buzbee  current_lir->next = new_lir;
10621fd3346740dfb7f47be9922312b68a4227fada96buzbee  new_lir->next->prev = new_lir;
10631fd3346740dfb7f47be9922312b68a4227fada96buzbee}
10641fd3346740dfb7f47be9922312b68a4227fada96buzbee
10651fd3346740dfb7f47be9922312b68a4227fada96buzbee
10667934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom}  // namespace art
1067