codegen_util.cc revision 311ca169f4727d46a55bdc8dfa0059719fa72b65
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
17395116cae130c983498c0a2f42b89e42f75bb9d0buzbee#include "compiler/dex/compiler_internals.h"
184f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h"
190c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers#include "gc_map.h"
200c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers#include "verifier/dex_gc_map.h"
210c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers#include "verifier/method_verifier.h"
221bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee#include "ralloc_util.h"
23eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee#include "codegen_util.h"
240c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
25e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbeenamespace art {
26e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
274ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbeebool IsInexpensiveConstant(CompilationUnit* cu, RegLocation rl_src)
284ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee{
294ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  bool res = false;
304ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (rl_src.is_const) {
314ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if (rl_src.wide) {
324ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (rl_src.fp) {
33311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee         res = cu->cg->InexpensiveConstantDouble(cu->mir_graph->ConstantValueWide(rl_src));
344ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else {
35311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee         res = cu->cg->InexpensiveConstantLong(cu->mir_graph->ConstantValueWide(rl_src));
364ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
374ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    } else {
384ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (rl_src.fp) {
39311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee         res = cu->cg->InexpensiveConstantFloat(cu->mir_graph->ConstantValue(rl_src));
404ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else {
41311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee         res = cu->cg->InexpensiveConstantInt(cu->mir_graph->ConstantValue(rl_src));
424ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
434ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
444ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
454ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  return res;
464ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
474ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
4802031b185b4653e6c72e21f7a51238b903f6d638buzbeevoid MarkSafepointPC(CompilationUnit* cu, LIR* inst)
4902031b185b4653e6c72e21f7a51238b903f6d638buzbee{
5002031b185b4653e6c72e21f7a51238b903f6d638buzbee  inst->def_mask = ENCODE_ALL;
5102031b185b4653e6c72e21f7a51238b903f6d638buzbee  LIR* safepoint_pc = NewLIR0(cu, kPseudoSafepointPC);
5202031b185b4653e6c72e21f7a51238b903f6d638buzbee  DCHECK_EQ(safepoint_pc->def_mask, ENCODE_ALL);
5302031b185b4653e6c72e21f7a51238b903f6d638buzbee}
5402031b185b4653e6c72e21f7a51238b903f6d638buzbee
5502031b185b4653e6c72e21f7a51238b903f6d638buzbeebool FastInstance(CompilationUnit* cu,  uint32_t field_idx,
5602031b185b4653e6c72e21f7a51238b903f6d638buzbee                  int& field_offset, bool& is_volatile, bool is_put)
5702031b185b4653e6c72e21f7a51238b903f6d638buzbee{
58311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  return cu->compiler_driver->ComputeInstanceFieldInfo(
59311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      field_idx, cu->mir_graph->GetCurrentDexCompilationUnit(), field_offset, is_volatile, is_put);
6002031b185b4653e6c72e21f7a51238b903f6d638buzbee}
6102031b185b4653e6c72e21f7a51238b903f6d638buzbee
62cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee/* Convert an instruction to a NOP */
6352a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbeevoid NopLIR( LIR* lir)
64cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee{
65fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  lir->flags.is_nop = true;
66cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee}
67cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee
6802031b185b4653e6c72e21f7a51238b903f6d638buzbeevoid SetMemRefType(CompilationUnit* cu, LIR* lir, bool is_load, int mem_type)
6931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
70fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  uint64_t *mask_ptr;
71eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee  uint64_t mask = ENCODE_MEM;;
7202031b185b4653e6c72e21f7a51238b903f6d638buzbee  Codegen* cg = cu->cg.get();
7302031b185b4653e6c72e21f7a51238b903f6d638buzbee  DCHECK(cg->GetTargetInstFlags(lir->opcode) & (IS_LOAD | IS_STORE));
74fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (is_load) {
75fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    mask_ptr = &lir->use_mask;
76a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
77fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    mask_ptr = &lir->def_mask;
78a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
79a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Clear out the memref flags */
80fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  *mask_ptr &= ~mask;
81a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* ..and then add back the one we need */
82fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  switch (mem_type) {
83a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kLiteral:
84fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      DCHECK(is_load);
85fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      *mask_ptr |= ENCODE_LITERAL;
86a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
87a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kDalvikReg:
88fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      *mask_ptr |= ENCODE_DALVIK_REG;
89a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
90a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kHeapRef:
91fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      *mask_ptr |= ENCODE_HEAP_REF;
92a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
93a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kMustNotAlias:
94a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      /* Currently only loads can be marked as kMustNotAlias */
9502031b185b4653e6c72e21f7a51238b903f6d638buzbee      DCHECK(!(cg->GetTargetInstFlags(lir->opcode) & IS_STORE));
96fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      *mask_ptr |= ENCODE_MUST_NOT_ALIAS;
97a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
98a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
99fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      LOG(FATAL) << "Oat: invalid memref kind - " << mem_type;
100a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
10131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
10231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
10331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
104b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers * Mark load/store instructions that access Dalvik registers through the stack.
10531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
10602031b185b4653e6c72e21f7a51238b903f6d638buzbeevoid AnnotateDalvikRegAccess(CompilationUnit* cu, LIR* lir, int reg_id, bool is_load, bool is64bit)
10731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
10802031b185b4653e6c72e21f7a51238b903f6d638buzbee  SetMemRefType(cu, lir, is_load, kDalvikReg);
10931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
110a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /*
111fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee   * Store the Dalvik register id in alias_info. Mark the MSB if it is a 64-bit
112a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * access.
113a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   */
114fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  lir->alias_info = ENCODE_ALIAS_INFO(reg_id, is64bit);
11531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
11631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
11731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
11831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Mark the corresponding bit(s).
11931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
120fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeevoid SetupRegMask(CompilationUnit* cu, uint64_t* mask, int reg)
12131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
12202031b185b4653e6c72e21f7a51238b903f6d638buzbee  Codegen* cg = cu->cg.get();
12302031b185b4653e6c72e21f7a51238b903f6d638buzbee  *mask |= cg->GetRegMaskCommon(cu, reg);
12431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
12531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
12631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
12731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Set up the proper fields in the resource mask
12831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
129fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeevoid SetupResourceMasks(CompilationUnit* cu, LIR* lir)
13031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
131a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int opcode = lir->opcode;
13202031b185b4653e6c72e21f7a51238b903f6d638buzbee  Codegen* cg = cu->cg.get();
13331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
134a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (opcode <= 0) {
135fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    lir->use_mask = lir->def_mask = 0;
136a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    return;
137a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
13831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
13902031b185b4653e6c72e21f7a51238b903f6d638buzbee  uint64_t flags = cg->GetTargetInstFlags(opcode);
14031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
141a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (flags & NEEDS_FIXUP) {
142a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    lir->flags.pcRelFixup = true;
143a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
14431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
145a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Get the starting size of the instruction's template */
14602031b185b4653e6c72e21f7a51238b903f6d638buzbee  lir->flags.size = cg->GetInsnSize(lir);
147e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
148a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Set up the mask for resources that are updated */
149a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (flags & (IS_LOAD | IS_STORE)) {
150a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    /* Default to heap - will catch specialized classes later */
15102031b185b4653e6c72e21f7a51238b903f6d638buzbee    SetMemRefType(cu, lir, flags & IS_LOAD, kHeapRef);
152a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
15331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
154a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /*
155a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Conservatively assume the branch here will call out a function that in
156a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * turn will trash everything.
157a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   */
158a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (flags & IS_BRANCH) {
159fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    lir->def_mask = lir->use_mask = ENCODE_ALL;
160a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    return;
161a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
16231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
163a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (flags & REG_DEF0) {
164fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    SetupRegMask(cu, &lir->def_mask, lir->operands[0]);
165a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
16631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
167a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (flags & REG_DEF1) {
168fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    SetupRegMask(cu, &lir->def_mask, lir->operands[1]);
169a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
17031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
17131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
172a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (flags & SETS_CCODES) {
173fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    lir->def_mask |= ENCODE_CCODE;
174a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
17531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
176a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) {
177a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    int i;
17831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
179a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    for (i = 0; i < 4; i++) {
180a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      if (flags & (1 << (kRegUse0 + i))) {
181fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        SetupRegMask(cu, &lir->use_mask, lir->operands[i]);
182a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
18331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
184a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
18531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
186a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (flags & USES_CCODES) {
187fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    lir->use_mask |= ENCODE_CCODE;
188a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
18931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
190b046e16d8b8da318d6055f9308950131f1255e08buzbee  // Handle target-specific actions
19102031b185b4653e6c72e21f7a51238b903f6d638buzbee  cg->SetupTargetResourceMasks(cu, lir);
19231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
19331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
19431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
1955de3494e4297c0d480409da3fecee39173f1d4e1buzbee * Debugging macros
1965de3494e4297c0d480409da3fecee39173f1d4e1buzbee */
1975de3494e4297c0d480409da3fecee39173f1d4e1buzbee#define DUMP_RESOURCE_MASK(X)
1985de3494e4297c0d480409da3fecee39173f1d4e1buzbee
1995de3494e4297c0d480409da3fecee39173f1d4e1buzbee/* Pretty-print a LIR instruction */
200fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeevoid DumpLIRInsn(CompilationUnit* cu, LIR* lir, unsigned char* base_addr)
2015de3494e4297c0d480409da3fecee39173f1d4e1buzbee{
202a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int offset = lir->offset;
203a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int dest = lir->operands[0];
204fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  const bool dump_nop = (cu->enable_debug & (1 << kDebugShowNops));
20502031b185b4653e6c72e21f7a51238b903f6d638buzbee  Codegen* cg = cu->cg.get();
206a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee
207a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Handle pseudo-ops individually, and all regular insns as a group */
208a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (lir->opcode) {
209a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoMethodEntry:
210a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "-------- method entry "
211fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                << PrettyMethod(cu->method_idx, *cu->dex_file);
212a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
213a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoMethodExit:
214a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "-------- Method_Exit";
215a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
216a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoBarrier:
217a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "-------- BARRIER";
218a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
219a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoEntryBlock:
220a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
221a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
222a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoDalvikByteCodeBoundary:
2234ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (lir->operands[0] == 0) {
2244ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee         lir->operands[0] = reinterpret_cast<uintptr_t>("No instruction string");
2254ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
226a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "-------- dalvik offset: 0x" << std::hex
227fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                << lir->dalvik_offset << " @ " << reinterpret_cast<char*>(lir->operands[0]);
228a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
229a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoExitBlock:
230a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
231a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
232a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoPseudoAlign4:
233fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      LOG(INFO) << reinterpret_cast<uintptr_t>(base_addr) + offset << " (0x" << std::hex
234a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                << offset << "): .align4";
235a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
236a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoEHBlockLabel:
237a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "Exception_Handling:";
238a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
239a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoTargetLabel:
240a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoNormalBlockLabel:
241cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(INFO) << "L" << reinterpret_cast<void*>(lir) << ":";
242a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
243a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoThrowTarget:
244cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(INFO) << "LT" << reinterpret_cast<void*>(lir) << ":";
245a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
246a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoIntrinsicRetry:
247cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(INFO) << "IR" << reinterpret_cast<void*>(lir) << ":";
248a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
249a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoSuspendTarget:
250cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(INFO) << "LS" << reinterpret_cast<void*>(lir) << ":";
251a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
2528320f3867c02bae9bef6cdab267820cb7b412781buzbee    case kPseudoSafepointPC:
253fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      LOG(INFO) << "LsafepointPC_0x" << std::hex << lir->offset << "_" << lir->dalvik_offset << ":";
2548320f3867c02bae9bef6cdab267820cb7b412781buzbee      break;
255a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    case kPseudoExportedPC:
256fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      LOG(INFO) << "LexportedPC_0x" << std::hex << lir->offset << "_" << lir->dalvik_offset << ":";
257a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee      break;
258a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoCaseLabel:
259cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(INFO) << "LC" << reinterpret_cast<void*>(lir) << ": Case target 0x"
260a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                << std::hex << lir->operands[0] << "|" << std::dec <<
261a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        lir->operands[0];
262a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
263a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
264fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (lir->flags.is_nop && !dump_nop) {
265a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        break;
266a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      } else {
26702031b185b4653e6c72e21f7a51238b903f6d638buzbee        std::string op_name(cg->BuildInsnString(cg->GetTargetInstName(lir->opcode),
26802031b185b4653e6c72e21f7a51238b903f6d638buzbee                                               lir, base_addr));
26902031b185b4653e6c72e21f7a51238b903f6d638buzbee        std::string op_operands(cg->BuildInsnString(cg->GetTargetInstFmt(lir->opcode),
27002031b185b4653e6c72e21f7a51238b903f6d638buzbee                                                    lir, base_addr));
271a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        LOG(INFO) << StringPrintf("%05x: %-9s%s%s",
272fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                  reinterpret_cast<unsigned int>(base_addr + offset),
273a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                                  op_name.c_str(), op_operands.c_str(),
274fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                  lir->flags.is_nop ? "(nop)" : "");
275a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
276a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
277a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
278a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee
279fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (lir->use_mask && (!lir->flags.is_nop || dump_nop)) {
280fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    DUMP_RESOURCE_MASK(DumpResourceMask((LIR* ) lir, lir->use_mask, "use"));
281a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
282fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (lir->def_mask && (!lir->flags.is_nop || dump_nop)) {
283fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    DUMP_RESOURCE_MASK(DumpResourceMask((LIR* ) lir, lir->def_mask, "def"));
284a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
2855de3494e4297c0d480409da3fecee39173f1d4e1buzbee}
2865de3494e4297c0d480409da3fecee39173f1d4e1buzbee
287fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeevoid DumpPromotionMap(CompilationUnit *cu)
2885de3494e4297c0d480409da3fecee39173f1d4e1buzbee{
28902031b185b4653e6c72e21f7a51238b903f6d638buzbee  Codegen* cg = cu->cg.get();
290fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int num_regs = cu->num_dalvik_registers + cu->num_compiler_temps + 1;
291fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  for (int i = 0; i < num_regs; i++) {
292fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    PromotionMap v_reg_map = cu->promotion_map[i];
293a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    std::string buf;
294fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (v_reg_map.fp_location == kLocPhysReg) {
29502031b185b4653e6c72e21f7a51238b903f6d638buzbee      StringAppendF(&buf, " : s%d", v_reg_map.FpReg & cg->FpRegMask());
296a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    }
2979c044ce5f76e9bfa17c4c1979e9f8c99ae100695buzbee
298a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    std::string buf3;
299fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (i < cu->num_dalvik_registers) {
300a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      StringAppendF(&buf3, "%02d", i);
301fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    } else if (i == cu->method_sreg) {
302a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      buf3 = "Method*";
303a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else {
304fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      StringAppendF(&buf3, "ct%d", i - cu->num_dalvik_registers);
3055de3494e4297c0d480409da3fecee39173f1d4e1buzbee    }
306a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee
307a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    LOG(INFO) << StringPrintf("V[%s] -> %s%d%s", buf3.c_str(),
308fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                              v_reg_map.core_location == kLocPhysReg ?
309fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                              "r" : "SP+", v_reg_map.core_location == kLocPhysReg ?
310fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                              v_reg_map.core_reg : SRegOffset(cu, i),
311a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                              buf.c_str());
312a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
3135de3494e4297c0d480409da3fecee39173f1d4e1buzbee}
3145de3494e4297c0d480409da3fecee39173f1d4e1buzbee
315a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee/* Dump a mapping table */
316aad94383fc41e8f8770f0b2144f766a2ffa772e7buzbeestatic void DumpMappingTable(const char* table_name, const std::string& descriptor,
317aad94383fc41e8f8770f0b2144f766a2ffa772e7buzbee                             const std::string& name, const std::string& signature,
318aad94383fc41e8f8770f0b2144f766a2ffa772e7buzbee                             const std::vector<uint32_t>& v) {
319a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee  if (v.size() > 0) {
320a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    std::string line(StringPrintf("\n  %s %s%s_%s_table[%zu] = {", table_name,
321a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee                     descriptor.c_str(), name.c_str(), signature.c_str(), v.size()));
322a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    std::replace(line.begin(), line.end(), ';', '_');
323a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    LOG(INFO) << line;
324a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    for (uint32_t i = 0; i < v.size(); i+=2) {
325a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee      line = StringPrintf("    {0x%05x, 0x%04x},", v[i], v[i+1]);
326a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee      LOG(INFO) << line;
327a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    }
328a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    LOG(INFO) <<"  };\n\n";
329a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee  }
330a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee}
331a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee
3325de3494e4297c0d480409da3fecee39173f1d4e1buzbee/* Dump instructions and constant pool contents */
333fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeevoid CodegenDump(CompilationUnit* cu)
3345de3494e4297c0d480409da3fecee39173f1d4e1buzbee{
335a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LOG(INFO) << "Dumping LIR insns for "
336fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee            << PrettyMethod(cu->method_idx, *cu->dex_file);
337fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* lir_insn;
338311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  int insns_size = cu->code_item->insns_size_in_code_units_;
339fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee
340fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LOG(INFO) << "Regs (excluding ins) : " << cu->num_regs;
341fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LOG(INFO) << "Ins          : " << cu->num_ins;
342fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LOG(INFO) << "Outs         : " << cu->num_outs;
343fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LOG(INFO) << "CoreSpills       : " << cu->num_core_spills;
344fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LOG(INFO) << "FPSpills       : " << cu->num_fp_spills;
345fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LOG(INFO) << "CompilerTemps    : " << cu->num_compiler_temps;
346fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LOG(INFO) << "Frame size       : " << cu->frame_size;
347fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LOG(INFO) << "code size is " << cu->total_size <<
348fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    " bytes, Dalvik size is " << insns_size * 2;
349a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LOG(INFO) << "expansion factor: "
350fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee            << static_cast<float>(cu->total_size) / static_cast<float>(insns_size * 2);
351fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DumpPromotionMap(cu);
35228c9a83398a6e48eefb9b79a390920629bbb8519buzbee  for (lir_insn = cu->first_lir_insn; lir_insn != NULL; lir_insn = lir_insn->next) {
353fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    DumpLIRInsn(cu, lir_insn, 0);
354a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
35528c9a83398a6e48eefb9b79a390920629bbb8519buzbee  for (lir_insn = cu->literal_list; lir_insn != NULL; lir_insn = lir_insn->next) {
356fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)", lir_insn->offset, lir_insn->offset,
357fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                              lir_insn->operands[0]);
358a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
359a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee
360a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  const DexFile::MethodId& method_id =
361fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      cu->dex_file->GetMethodId(cu->method_idx);
362fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  std::string signature(cu->dex_file->GetMethodSignature(method_id));
363fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  std::string name(cu->dex_file->GetMethodName(method_id));
364fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  std::string descriptor(cu->dex_file->GetMethodDeclaringClassDescriptor(method_id));
365a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee
366a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee  // Dump mapping tables
367fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DumpMappingTable("PC2Dex_MappingTable", descriptor, name, signature, cu->pc2dexMappingTable);
368fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DumpMappingTable("Dex2PC_MappingTable", descriptor, name, signature, cu->dex2pcMappingTable);
3695de3494e4297c0d480409da3fecee39173f1d4e1buzbee}
3705de3494e4297c0d480409da3fecee39173f1d4e1buzbee
371a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee
372fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* RawLIR(CompilationUnit* cu, int dalvik_offset, int opcode, int op0,
373a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      int op1, int op2, int op3, int op4, LIR* target)
374a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
375fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* insn = static_cast<LIR*>(NewMem(cu, sizeof(LIR), true, kAllocLIR));
376fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  insn->dalvik_offset = dalvik_offset;
377a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  insn->opcode = opcode;
378a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  insn->operands[0] = op0;
379a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  insn->operands[1] = op1;
380a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  insn->operands[2] = op2;
381a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  insn->operands[3] = op3;
382a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  insn->operands[4] = op4;
383a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  insn->target = target;
384fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  SetupResourceMasks(cu, insn);
385a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee  if ((opcode == kPseudoTargetLabel) || (opcode == kPseudoSafepointPC) ||
386a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee      (opcode == kPseudoExportedPC)) {
387a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    // Always make labels scheduling barriers
388fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    insn->use_mask = insn->def_mask = ENCODE_ALL;
389a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
390a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return insn;
391a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee}
392a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee
393a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee/*
394a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee * The following are building blocks to construct low-level IRs with 0 - 4
395a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee * operands.
396a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee */
397fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* NewLIR0(CompilationUnit* cu, int opcode)
398a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee{
39902031b185b4653e6c72e21f7a51238b903f6d638buzbee  Codegen* cg = cu->cg.get();
40002031b185b4653e6c72e21f7a51238b903f6d638buzbee  DCHECK(is_pseudo_opcode(opcode) || (cg->GetTargetInstFlags(opcode) & NO_OPERAND))
40102031b185b4653e6c72e21f7a51238b903f6d638buzbee      << cg->GetTargetInstName(opcode) << " " << opcode << " "
402fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      << PrettyMethod(cu->method_idx, *cu->dex_file) << " "
403fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      << cu->current_dalvik_offset;
404fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* insn = RawLIR(cu, cu->current_dalvik_offset, opcode);
405fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  AppendLIR(cu, insn);
406a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return insn;
40731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
40831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
409fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* NewLIR1(CompilationUnit* cu, int opcode,
410a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee               int dest)
41131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
41202031b185b4653e6c72e21f7a51238b903f6d638buzbee  Codegen* cg = cu->cg.get();
41302031b185b4653e6c72e21f7a51238b903f6d638buzbee  DCHECK(is_pseudo_opcode(opcode) || (cg->GetTargetInstFlags(opcode) & IS_UNARY_OP))
41402031b185b4653e6c72e21f7a51238b903f6d638buzbee      << cg->GetTargetInstName(opcode) << " " << opcode << " "
415fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      << PrettyMethod(cu->method_idx, *cu->dex_file) << " "
416fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      << cu->current_dalvik_offset;
417fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* insn = RawLIR(cu, cu->current_dalvik_offset, opcode, dest);
418fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  AppendLIR(cu, insn);
419a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return insn;
42031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
42131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
422fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* NewLIR2(CompilationUnit* cu, int opcode,
423a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee               int dest, int src1)
42431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
42502031b185b4653e6c72e21f7a51238b903f6d638buzbee  Codegen* cg = cu->cg.get();
42602031b185b4653e6c72e21f7a51238b903f6d638buzbee  DCHECK(is_pseudo_opcode(opcode) || (cg->GetTargetInstFlags(opcode) & IS_BINARY_OP))
42702031b185b4653e6c72e21f7a51238b903f6d638buzbee      << cg->GetTargetInstName(opcode) << " " << opcode << " "
428fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      << PrettyMethod(cu->method_idx, *cu->dex_file) << " "
429fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      << cu->current_dalvik_offset;
430fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* insn = RawLIR(cu, cu->current_dalvik_offset, opcode, dest, src1);
431fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  AppendLIR(cu, insn);
432a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return insn;
43331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
43431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
435fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* NewLIR3(CompilationUnit* cu, int opcode,
436a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee               int dest, int src1, int src2)
43731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
43802031b185b4653e6c72e21f7a51238b903f6d638buzbee  Codegen* cg = cu->cg.get();
43902031b185b4653e6c72e21f7a51238b903f6d638buzbee  DCHECK(is_pseudo_opcode(opcode) || (cg->GetTargetInstFlags(opcode) & IS_TERTIARY_OP))
44002031b185b4653e6c72e21f7a51238b903f6d638buzbee      << cg->GetTargetInstName(opcode) << " " << opcode << " "
441fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      << PrettyMethod(cu->method_idx, *cu->dex_file) << " "
442fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      << cu->current_dalvik_offset;
443fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* insn = RawLIR(cu, cu->current_dalvik_offset, opcode, dest, src1, src2);
444fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  AppendLIR(cu, insn);
445a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return insn;
44631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
44731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
448fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* NewLIR4(CompilationUnit* cu, int opcode,
449a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      int dest, int src1, int src2, int info)
45031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
45102031b185b4653e6c72e21f7a51238b903f6d638buzbee  Codegen* cg = cu->cg.get();
45202031b185b4653e6c72e21f7a51238b903f6d638buzbee  DCHECK(is_pseudo_opcode(opcode) || (cg->GetTargetInstFlags(opcode) & IS_QUAD_OP))
45302031b185b4653e6c72e21f7a51238b903f6d638buzbee      << cg->GetTargetInstName(opcode) << " " << opcode << " "
454fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      << PrettyMethod(cu->method_idx, *cu->dex_file) << " "
455fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      << cu->current_dalvik_offset;
456fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* insn = RawLIR(cu, cu->current_dalvik_offset, opcode, dest, src1, src2, info);
457fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  AppendLIR(cu, insn);
458a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return insn;
45931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
46031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
461fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* NewLIR5(CompilationUnit* cu, int opcode,
462a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee       int dest, int src1, int src2, int info1, int info2)
463b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers{
46402031b185b4653e6c72e21f7a51238b903f6d638buzbee  Codegen* cg = cu->cg.get();
46502031b185b4653e6c72e21f7a51238b903f6d638buzbee  DCHECK(is_pseudo_opcode(opcode) || (cg->GetTargetInstFlags(opcode) & IS_QUIN_OP))
46602031b185b4653e6c72e21f7a51238b903f6d638buzbee      << cg->GetTargetInstName(opcode) << " " << opcode << " "
467fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      << PrettyMethod(cu->method_idx, *cu->dex_file) << " "
468fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      << cu->current_dalvik_offset;
469fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* insn = RawLIR(cu, cu->current_dalvik_offset, opcode, dest, src1, src2, info1, info2);
470fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  AppendLIR(cu, insn);
471a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return insn;
472b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers}
473b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers
47431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
47531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Search the existing constants in the literal pool for an exact or close match
47631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * within specified delta (greater or equal to 0).
47731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
478fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* ScanLiteralPool(LIR* data_target, int value, unsigned int delta)
47931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
480fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  while (data_target) {
481fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if ((static_cast<unsigned>(value - data_target->operands[0])) <= delta)
482fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      return data_target;
483fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    data_target = data_target->next;
484a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
485a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return NULL;
48631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
48731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
48831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* Search the existing constants in the literal pool for an exact wide match */
489fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* ScanLiteralPoolWide(LIR* data_target, int val_lo, int val_hi)
49031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
491fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool lo_match = false;
492fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* lo_target = NULL;
493fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  while (data_target) {
494fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (lo_match && (data_target->operands[0] == val_hi)) {
4954ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      // Record high word in case we need to expand this later.
4964ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      lo_target->operands[1] = val_hi;
497fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      return lo_target;
49831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
499fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    lo_match = false;
500fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (data_target->operands[0] == val_lo) {
501fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      lo_match = true;
502fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      lo_target = data_target;
503a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    }
504fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    data_target = data_target->next;
505a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
506a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return NULL;
50731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
50831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
50931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
51031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * The following are building blocks to insert constants into the pool or
51131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * instruction streams.
51231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
51331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
5144ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee/* Add a 32-bit constant to the constant pool */
515fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* AddWordData(CompilationUnit* cu, LIR* *constant_list_p, int value)
51631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
517a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Add the constant to the literal pool */
518fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (constant_list_p) {
519fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    LIR* new_value = static_cast<LIR*>(NewMem(cu, sizeof(LIR), true, kAllocData));
520fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    new_value->operands[0] = value;
521fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    new_value->next = *constant_list_p;
522fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    *constant_list_p = new_value;
523fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    return new_value;
524a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
525a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return NULL;
52631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
52731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
52831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* Add a 64-bit constant to the constant pool or mixed with code */
529fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* AddWideData(CompilationUnit* cu, LIR* *constant_list_p,
530fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee               int val_lo, int val_hi)
53131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
532fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  AddWordData(cu, constant_list_p, val_hi);
533fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  return AddWordData(cu, constant_list_p, val_lo);
53431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
53531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
536aad94383fc41e8f8770f0b2144f766a2ffa772e7buzbeestatic void PushWord(std::vector<uint8_t>&buf, int data) {
537a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  buf.push_back( data & 0xff);
538a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  buf.push_back( (data >> 8) & 0xff);
539a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  buf.push_back( (data >> 16) & 0xff);
540a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  buf.push_back( (data >> 24) & 0xff);
541e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
542e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
543aad94383fc41e8f8770f0b2144f766a2ffa772e7buzbeestatic void AlignBuffer(std::vector<uint8_t>&buf, size_t offset) {
544a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (buf.size() < offset) {
545a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    buf.push_back(0);
546a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
547e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
548e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
549e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Write the literal pool to the output stream */
550fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic void InstallLiteralPools(CompilationUnit* cu)
551e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
552fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  AlignBuffer(cu->code_buffer, cu->data_offset);
553fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* data_lir = cu->literal_list;
554fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  while (data_lir != NULL) {
555fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    PushWord(cu->code_buffer, data_lir->operands[0]);
556fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    data_lir = NEXT_LIR(data_lir);
557a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
558a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  // Push code and method literals, record offsets for the compiler to patch.
559fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  data_lir = cu->code_literal_list;
560fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  while (data_lir != NULL) {
561fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    uint32_t target = data_lir->operands[0];
5621212a022fa5f8ef9585d765b1809521812af882cIan Rogers    cu->compiler_driver->AddCodePatch(cu->dex_file,
5631212a022fa5f8ef9585d765b1809521812af882cIan Rogers                                      cu->method_idx,
5641212a022fa5f8ef9585d765b1809521812af882cIan Rogers                                      cu->invoke_type,
5651212a022fa5f8ef9585d765b1809521812af882cIan Rogers                                      target,
5661212a022fa5f8ef9585d765b1809521812af882cIan Rogers                                      static_cast<InvokeType>(data_lir->operands[1]),
5671212a022fa5f8ef9585d765b1809521812af882cIan Rogers                                      cu->code_buffer.size());
568fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    const DexFile::MethodId& id = cu->dex_file->GetMethodId(target);
569137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    // unique based on target to ensure code deduplication works
570137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
571fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    PushWord(cu->code_buffer, unique_patch_value);
572fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    data_lir = NEXT_LIR(data_lir);
573137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers  }
574fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  data_lir = cu->method_literal_list;
575fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  while (data_lir != NULL) {
576fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    uint32_t target = data_lir->operands[0];
5771212a022fa5f8ef9585d765b1809521812af882cIan Rogers    cu->compiler_driver->AddMethodPatch(cu->dex_file,
5781212a022fa5f8ef9585d765b1809521812af882cIan Rogers                                        cu->method_idx,
5791212a022fa5f8ef9585d765b1809521812af882cIan Rogers                                        cu->invoke_type,
5801212a022fa5f8ef9585d765b1809521812af882cIan Rogers                                        target,
5811212a022fa5f8ef9585d765b1809521812af882cIan Rogers                                        static_cast<InvokeType>(data_lir->operands[1]),
5821212a022fa5f8ef9585d765b1809521812af882cIan Rogers                                        cu->code_buffer.size());
583fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    const DexFile::MethodId& id = cu->dex_file->GetMethodId(target);
584137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    // unique based on target to ensure code deduplication works
585137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
586fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    PushWord(cu->code_buffer, unique_patch_value);
587fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    data_lir = NEXT_LIR(data_lir);
588a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
589e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
590e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
591e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Write the switch tables to the output stream */
592fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic void InstallSwitchTables(CompilationUnit* cu)
593e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
594a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  GrowableListIterator iterator;
595fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  GrowableListIteratorInit(&cu->switch_tables, &iterator);
596a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (true) {
597311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    Codegen::SwitchTable* tab_rec =
598311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      reinterpret_cast<Codegen::SwitchTable*>(GrowableListIteratorNext( &iterator));
599fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (tab_rec == NULL) break;
600fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    AlignBuffer(cu->code_buffer, tab_rec->offset);
601a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    /*
602a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee     * For Arm, our reference point is the address of the bx
603a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee     * instruction that does the launch, so we have to subtract
604a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee     * the auto pc-advance.  For other targets the reference point
605a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee     * is a label, so we can use the offset as-is.
606a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee     */
607fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    int bx_offset = INVALID_OFFSET;
608fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    switch (cu->instruction_set) {
609b046e16d8b8da318d6055f9308950131f1255e08buzbee      case kThumb2:
610fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        bx_offset = tab_rec->anchor->offset + 4;
611b046e16d8b8da318d6055f9308950131f1255e08buzbee        break;
612b046e16d8b8da318d6055f9308950131f1255e08buzbee      case kX86:
613fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        bx_offset = 0;
614b046e16d8b8da318d6055f9308950131f1255e08buzbee        break;
615b046e16d8b8da318d6055f9308950131f1255e08buzbee      case kMips:
616fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        bx_offset = tab_rec->anchor->offset;
617b046e16d8b8da318d6055f9308950131f1255e08buzbee        break;
618fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      default: LOG(FATAL) << "Unexpected instruction set: " << cu->instruction_set;
619b046e16d8b8da318d6055f9308950131f1255e08buzbee    }
620fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (cu->verbose) {
621fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      LOG(INFO) << "Switch table for offset 0x" << std::hex << bx_offset;
622a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    }
623fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) {
624fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      const int* keys = reinterpret_cast<const int*>(&(tab_rec->table[2]));
625fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      for (int elems = 0; elems < tab_rec->table[1]; elems++) {
626fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        int disp = tab_rec->targets[elems]->offset - bx_offset;
627fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        if (cu->verbose) {
628a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee          LOG(INFO) << "  Case[" << elems << "] key: 0x"
629a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                    << std::hex << keys[elems] << ", disp: 0x"
630a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                    << std::hex << disp;
631e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        }
632fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        PushWord(cu->code_buffer, keys[elems]);
633fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        PushWord(cu->code_buffer,
634fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          tab_rec->targets[elems]->offset - bx_offset);
635a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
636a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else {
637fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      DCHECK_EQ(static_cast<int>(tab_rec->table[0]),
638a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                static_cast<int>(Instruction::kPackedSwitchSignature));
639fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      for (int elems = 0; elems < tab_rec->table[1]; elems++) {
640fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        int disp = tab_rec->targets[elems]->offset - bx_offset;
641fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        if (cu->verbose) {
642a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee          LOG(INFO) << "  Case[" << elems << "] disp: 0x"
643a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                    << std::hex << disp;
644e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        }
645fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        PushWord(cu->code_buffer, tab_rec->targets[elems]->offset - bx_offset);
646a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
647e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
648a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
649e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
650e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
651e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Write the fill array dta to the output stream */
652fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic void InstallFillArrayData(CompilationUnit* cu)
653e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
654a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  GrowableListIterator iterator;
655fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  GrowableListIteratorInit(&cu->fill_array_data, &iterator);
656a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (true) {
657311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    Codegen::FillArrayData *tab_rec =
658311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        reinterpret_cast<Codegen::FillArrayData*>(GrowableListIteratorNext( &iterator));
659fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (tab_rec == NULL) break;
660fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    AlignBuffer(cu->code_buffer, tab_rec->offset);
661fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    for (int i = 0; i < (tab_rec->size + 1) / 2; i++) {
662fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      cu->code_buffer.push_back( tab_rec->table[i] & 0xFF);
663fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      cu->code_buffer.push_back( (tab_rec->table[i] >> 8) & 0xFF);
664e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
665a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
666e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
667e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
668aad94383fc41e8f8770f0b2144f766a2ffa772e7buzbeestatic int AssignLiteralOffsetCommon(LIR* lir, int offset)
669e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
670a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  for (;lir != NULL; lir = lir->next) {
671a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    lir->offset = offset;
672a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    offset += 4;
673a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
674a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return offset;
675e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
676e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
6776459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee// Make sure we have a code address for every declared catch entry
678fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic bool VerifyCatchEntries(CompilationUnit* cu)
6796459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee{
6806459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  bool success = true;
681311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  for (std::set<uint32_t>::const_iterator it = cu->mir_graph->catches_.begin();
682311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee       it != cu->mir_graph->catches_.end(); ++it) {
683fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    uint32_t dex_pc = *it;
6846459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    bool found = false;
685fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    for (size_t i = 0; i < cu->dex2pcMappingTable.size(); i += 2) {
686fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (dex_pc == cu->dex2pcMappingTable[i+1]) {
6876459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee        found = true;
6886459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee        break;
6896459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee      }
6906459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    }
6916459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    if (!found) {
692fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      LOG(INFO) << "Missing native PC for catch entry @ 0x" << std::hex << dex_pc;
6936459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee      success = false;
6946459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    }
6956459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  }
6966459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  // Now, try in the other direction
697fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  for (size_t i = 0; i < cu->dex2pcMappingTable.size(); i += 2) {
698fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    uint32_t dex_pc = cu->dex2pcMappingTable[i+1];
699311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    if (cu->mir_graph->catches_.find(dex_pc) == cu->mir_graph->catches_.end()) {
700fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      LOG(INFO) << "Unexpected catch entry @ dex pc 0x" << std::hex << dex_pc;
7016459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee      success = false;
7026459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    }
7036459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  }
7046459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  if (!success) {
705fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    LOG(INFO) << "Bad dex2pcMapping table in " << PrettyMethod(cu->method_idx, *cu->dex_file);
706311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    LOG(INFO) << "Entries @ decode: " << cu->mir_graph->catches_.size() << ", Entries in table: "
707fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee              << cu->dex2pcMappingTable.size()/2;
7086459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  }
7096459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  return success;
7106459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee}
7116459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee
712311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
713fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic void CreateMappingTables(CompilationUnit* cu)
714e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
715fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  for (LIR* tgt_lir = cu->first_lir_insn; tgt_lir != NULL; tgt_lir = NEXT_LIR(tgt_lir)) {
716fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (!tgt_lir->flags.is_nop && (tgt_lir->opcode == kPseudoSafepointPC)) {
717fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      cu->pc2dexMappingTable.push_back(tgt_lir->offset);
718fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      cu->pc2dexMappingTable.push_back(tgt_lir->dalvik_offset);
719a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    }
720fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (!tgt_lir->flags.is_nop && (tgt_lir->opcode == kPseudoExportedPC)) {
721fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      cu->dex2pcMappingTable.push_back(tgt_lir->offset);
722fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      cu->dex2pcMappingTable.push_back(tgt_lir->dalvik_offset);
723e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
724a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
725311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  if (kIsDebugBuild) {
726311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    DCHECK(VerifyCatchEntries(cu));
727311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
728fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  cu->combined_mapping_table.push_back(cu->pc2dexMappingTable.size() +
729fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                        cu->dex2pcMappingTable.size());
730fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  cu->combined_mapping_table.push_back(cu->pc2dexMappingTable.size());
731fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  cu->combined_mapping_table.insert(cu->combined_mapping_table.end(),
732fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                     cu->pc2dexMappingTable.begin(),
733fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                     cu->pc2dexMappingTable.end());
734fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  cu->combined_mapping_table.insert(cu->combined_mapping_table.end(),
735fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                     cu->dex2pcMappingTable.begin(),
736fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                     cu->dex2pcMappingTable.end());
737e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
738e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
7390c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogersclass NativePcToReferenceMapBuilder {
7400c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers public:
7410c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  NativePcToReferenceMapBuilder(std::vector<uint8_t>* table,
7420c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers                                size_t entries, uint32_t max_native_offset,
7430c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers                                size_t references_width) : entries_(entries),
7440c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers                                references_width_(references_width), in_use_(entries),
7450c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers                                table_(table) {
7460c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    // Compute width in bytes needed to hold max_native_offset.
7470c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    native_offset_width_ = 0;
7480c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    while (max_native_offset != 0) {
7490c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers      native_offset_width_++;
7500c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers      max_native_offset >>= 8;
7510c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    }
7520c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    // Resize table and set up header.
7530c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    table->resize((EntryWidth() * entries) + sizeof(uint32_t));
754000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers    CHECK_LT(native_offset_width_, 1U << 3);
755000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers    (*table)[0] = native_offset_width_ & 7;
756000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers    CHECK_LT(references_width_, 1U << 13);
757000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers    (*table)[0] |= (references_width_ << 3) & 0xFF;
758000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers    (*table)[1] = (references_width_ >> 5) & 0xFF;
7590c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    CHECK_LT(entries, 1U << 16);
7600c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    (*table)[2] = entries & 0xFF;
7610c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    (*table)[3] = (entries >> 8) & 0xFF;
7620c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
7630c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
7640c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  void AddEntry(uint32_t native_offset, const uint8_t* references) {
7650c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    size_t table_index = TableIndex(native_offset);
7660c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    while (in_use_[table_index]) {
7670c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers      table_index = (table_index + 1) % entries_;
7680c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    }
7690c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    in_use_[table_index] = true;
7700c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    SetNativeOffset(table_index, native_offset);
7710c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    DCHECK_EQ(native_offset, GetNativeOffset(table_index));
7720c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    SetReferences(table_index, references);
7730c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
7740c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
7750c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers private:
7760c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  size_t TableIndex(uint32_t native_offset) {
7770c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    return NativePcOffsetToReferenceMap::Hash(native_offset) % entries_;
7780c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
7790c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
7800c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  uint32_t GetNativeOffset(size_t table_index) {
7810c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    uint32_t native_offset = 0;
7820c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
7830c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    for (size_t i = 0; i < native_offset_width_; i++) {
7840c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers      native_offset |= (*table_)[table_offset + i] << (i * 8);
7850c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    }
7860c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    return native_offset;
7870c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
7880c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
7890c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  void SetNativeOffset(size_t table_index, uint32_t native_offset) {
7900c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
7910c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    for (size_t i = 0; i < native_offset_width_; i++) {
7920c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers      (*table_)[table_offset + i] = (native_offset >> (i * 8)) & 0xFF;
7930c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    }
7940c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
7950c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
7960c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  void SetReferences(size_t table_index, const uint8_t* references) {
7970c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
7980c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    memcpy(&(*table_)[table_offset + native_offset_width_], references, references_width_);
7990c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
8000c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
8010c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  size_t EntryWidth() const {
8020c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    return native_offset_width_ + references_width_;
8030c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
8040c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
8050c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // Number of entries in the table.
8060c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  const size_t entries_;
8070c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // Number of bytes used to encode the reference bitmap.
8080c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  const size_t references_width_;
8090c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // Number of bytes used to encode a native offset.
8100c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  size_t native_offset_width_;
8110c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // Entries that are in use.
8120c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  std::vector<bool> in_use_;
8130c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // The table we're building.
8140c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  std::vector<uint8_t>* const table_;
8150c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers};
8160c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
817fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic void CreateNativeGcMap(CompilationUnit* cu) {
818fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  const std::vector<uint32_t>& mapping_table = cu->pc2dexMappingTable;
8190c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  uint32_t max_native_offset = 0;
8200c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  for (size_t i = 0; i < mapping_table.size(); i += 2) {
8210c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    uint32_t native_offset = mapping_table[i + 0];
8220c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    if (native_offset > max_native_offset) {
8230c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers      max_native_offset = native_offset;
8240c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    }
8250c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
8261212a022fa5f8ef9585d765b1809521812af882cIan Rogers  CompilerDriver::MethodReference method_ref(cu->dex_file, cu->method_idx);
8270c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  const std::vector<uint8_t>* gc_map_raw = verifier::MethodVerifier::GetDexGcMap(method_ref);
8280c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  verifier::DexPcToReferenceMap dex_gc_map(&(*gc_map_raw)[4], gc_map_raw->size() - 4);
8290c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // Compute native offset to references size.
830fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  NativePcToReferenceMapBuilder native_gc_map_builder(&cu->native_gc_map,
8310c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers                                                      mapping_table.size() / 2, max_native_offset,
8320c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers                                                      dex_gc_map.RegWidth());
8330c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
8340c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  for (size_t i = 0; i < mapping_table.size(); i += 2) {
8350c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    uint32_t native_offset = mapping_table[i + 0];
8360c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    uint32_t dex_pc = mapping_table[i + 1];
8370c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    const uint8_t* references = dex_gc_map.FindBitMap(dex_pc, false);
838a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    CHECK(references != NULL) << "Missing ref for dex pc 0x" << std::hex << dex_pc;
839a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    native_gc_map_builder.AddEntry(native_offset, references);
8400c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
8410c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers}
8420c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
843e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Determine the offset of each literal field */
844fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic int AssignLiteralOffset(CompilationUnit* cu, int offset)
845e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
846fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  offset = AssignLiteralOffsetCommon(cu->literal_list, offset);
847fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  offset = AssignLiteralOffsetCommon(cu->code_literal_list, offset);
848fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  offset = AssignLiteralOffsetCommon(cu->method_literal_list, offset);
849a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return offset;
850e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
851e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
852fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic int AssignSwitchTablesOffset(CompilationUnit* cu, int offset)
853e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
854a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  GrowableListIterator iterator;
855fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  GrowableListIteratorInit(&cu->switch_tables, &iterator);
856a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (true) {
857311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    Codegen::SwitchTable *tab_rec =
858311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        reinterpret_cast<Codegen::SwitchTable*>(GrowableListIteratorNext(&iterator));
859fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (tab_rec == NULL) break;
860fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    tab_rec->offset = offset;
861fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) {
862fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      offset += tab_rec->table[1] * (sizeof(int) * 2);
863a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else {
864fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      DCHECK_EQ(static_cast<int>(tab_rec->table[0]),
865a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                static_cast<int>(Instruction::kPackedSwitchSignature));
866fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      offset += tab_rec->table[1] * sizeof(int);
867e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
868a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
869a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return offset;
870e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
871e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
872fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic int AssignFillArrayDataOffset(CompilationUnit* cu, int offset)
873e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
874a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  GrowableListIterator iterator;
875fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  GrowableListIteratorInit(&cu->fill_array_data, &iterator);
876a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (true) {
877311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    Codegen::FillArrayData *tab_rec =
878311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        reinterpret_cast<Codegen::FillArrayData*>(GrowableListIteratorNext(&iterator));
879fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (tab_rec == NULL) break;
880fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    tab_rec->offset = offset;
881fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    offset += tab_rec->size;
882a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    // word align
883a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    offset = (offset + 3) & ~3;
884a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    }
885a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return offset;
886e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
887e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
888a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee// LIR offset assignment.
889a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbeestatic int AssignInsnOffsets(CompilationUnit* cu)
890a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee{
891a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee  LIR* lir;
892a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee  int offset = 0;
893a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee
894a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee  for (lir = cu->first_lir_insn; lir != NULL; lir = NEXT_LIR(lir)) {
895a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee    lir->offset = offset;
896a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee    if (lir->opcode >= 0) {
897a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee      if (!lir->flags.is_nop) {
898a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee        offset += lir->flags.size;
899a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee      }
900a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee    } else if (lir->opcode == kPseudoPseudoAlign4) {
901a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee      if (offset & 0x2) {
902a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee        offset += 2;
903a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee        lir->operands[0] = 1;
904a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee      } else {
905a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee        lir->operands[0] = 0;
906a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee      }
907a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee    }
908a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee    /* Pseudo opcodes don't consume space */
909a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee  }
910a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee
911a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee  return offset;
912a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee}
913a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee
914e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/*
915e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Walk the compilation unit and assign offsets to instructions
916e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * and literals and compute the total size of the compiled unit.
917e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee */
918fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic void AssignOffsets(CompilationUnit* cu)
919e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
920a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee  int offset = AssignInsnOffsets(cu);
921e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
922a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Const values have to be word aligned */
923a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  offset = (offset + 3) & ~3;
924e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
925a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Set up offsets for literals */
926fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  cu->data_offset = offset;
927e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
928fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  offset = AssignLiteralOffset(cu, offset);
929e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
930fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  offset = AssignSwitchTablesOffset(cu, offset);
931e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
932fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  offset = AssignFillArrayDataOffset(cu, offset);
933e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
934fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  cu->total_size = offset;
935e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
936e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
937e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/*
938e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Go over each instruction in the list and calculate the offset from the top
939e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * before sending them off to the assembler. If out-of-range branch distance is
940e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * seen rearrange the instructions a bit to correct it.
941e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee */
942fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeevoid AssembleLIR(CompilationUnit* cu)
943e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
94402031b185b4653e6c72e21f7a51238b903f6d638buzbee  Codegen* cg = cu->cg.get();
945fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  AssignOffsets(cu);
946311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  int assembler_retries = 0;
947a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /*
948a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Assemble here.  Note that we generate code with optimistic assumptions
949a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * and if found now to work, we'll have to redo the sequence and retry.
950a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   */
951e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
952a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (true) {
95302031b185b4653e6c72e21f7a51238b903f6d638buzbee    AssemblerStatus res = cg->AssembleInstructions(cu, 0);
954a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    if (res == kSuccess) {
955a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
956a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else {
957311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      assembler_retries++;
958311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      if (assembler_retries > MAX_ASSEMBLER_RETRIES) {
959fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        CodegenDump(cu);
960a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        LOG(FATAL) << "Assembler error - too many retries";
961a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
962a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      // Redo offsets and try again
963fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      AssignOffsets(cu);
964fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      cu->code_buffer.clear();
965e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
966a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
967e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
968a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  // Install literals
969fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  InstallLiteralPools(cu);
970e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
971a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  // Install switch tables
972fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  InstallSwitchTables(cu);
973e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
974a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  // Install fill array data
975fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  InstallFillArrayData(cu);
976e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
9770c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // Create the mapping table and native offset to reference map.
978fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  CreateMappingTables(cu);
9790c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
980fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  CreateNativeGcMap(cu);
981e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
982e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
98331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
98431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Insert a kPseudoCaseLabel at the beginning of the Dalvik
98531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * offset vaddr.  This label will be used to fix up the case
98631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * branch table during the assembly phase.  Be sure to set
98731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * all resource flags on this to prevent code motion across
98831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * target boundaries.  KeyVal is just there for debugging.
98931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
990fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic LIR* InsertCaseLabel(CompilationUnit* cu, int vaddr, int keyVal)
99131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
992a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  SafeMap<unsigned int, LIR*>::iterator it;
993fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  it = cu->boundary_map.find(vaddr);
994fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (it == cu->boundary_map.end()) {
995a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr;
996a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
997fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* new_label = static_cast<LIR*>(NewMem(cu, sizeof(LIR), true, kAllocLIR));
998fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  new_label->dalvik_offset = vaddr;
999fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  new_label->opcode = kPseudoCaseLabel;
1000fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  new_label->operands[0] = keyVal;
1001fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  InsertLIRAfter(it->second, new_label);
1002fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  return new_label;
100331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
100431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
1005311ca169f4727d46a55bdc8dfa0059719fa72b65buzbeestatic void MarkPackedCaseLabels(CompilationUnit* cu, Codegen::SwitchTable *tab_rec)
100631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
1007fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  const uint16_t* table = tab_rec->table;
1008fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int base_vaddr = tab_rec->vaddr;
1009cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  const int *targets = reinterpret_cast<const int*>(&table[4]);
1010a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int entries = table[1];
1011fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int low_key = s4FromSwitchData(&table[2]);
1012a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  for (int i = 0; i < entries; i++) {
1013fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    tab_rec->targets[i] = InsertCaseLabel(cu, base_vaddr + targets[i], i + low_key);
1014a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
101531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
101631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
1017311ca169f4727d46a55bdc8dfa0059719fa72b65buzbeestatic void MarkSparseCaseLabels(CompilationUnit* cu, Codegen::SwitchTable *tab_rec)
101831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
1019fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  const uint16_t* table = tab_rec->table;
1020fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int base_vaddr = tab_rec->vaddr;
1021a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int entries = table[1];
1022cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  const int* keys = reinterpret_cast<const int*>(&table[2]);
1023cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  const int* targets = &keys[entries];
1024a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  for (int i = 0; i < entries; i++) {
1025fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    tab_rec->targets[i] = InsertCaseLabel(cu, base_vaddr + targets[i], keys[i]);
1026a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
102731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
102831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
1029fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeevoid ProcessSwitchTables(CompilationUnit* cu)
103031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
1031a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  GrowableListIterator iterator;
1032fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  GrowableListIteratorInit(&cu->switch_tables, &iterator);
1033a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (true) {
1034311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    Codegen::SwitchTable *tab_rec =
1035311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        reinterpret_cast<Codegen::SwitchTable*>(GrowableListIteratorNext(&iterator));
1036fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (tab_rec == NULL) break;
1037fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (tab_rec->table[0] == Instruction::kPackedSwitchSignature) {
1038fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      MarkPackedCaseLabels(cu, tab_rec);
1039fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    } else if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) {
1040fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      MarkSparseCaseLabels(cu, tab_rec);
1041a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else {
1042a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(FATAL) << "Invalid switch table";
104331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
1044a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
104531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
104631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
104752a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbeevoid DumpSparseSwitchTable(const uint16_t* table)
1048a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /*
1049a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Sparse switch data format:
1050a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  ushort ident = 0x0200   magic value
1051a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  ushort size       number of entries in the table; > 0
1052a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  int keys[size]      keys, sorted low-to-high; 32-bit aligned
1053a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  int targets[size]     branch targets, relative to switch opcode
1054a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *
1055a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Total size is (2+size*4) 16-bit code units.
1056a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   */
1057a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
1058eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee  uint16_t ident = table[0];
1059a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int entries = table[1];
1060cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  const int* keys = reinterpret_cast<const int*>(&table[2]);
1061cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  const int* targets = &keys[entries];
1062a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LOG(INFO) <<  "Sparse switch table - ident:0x" << std::hex << ident
1063a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee            << ", entries: " << std::dec << entries;
1064a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  for (int i = 0; i < entries; i++) {
1065a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    LOG(INFO) << "  Key[" << keys[i] << "] -> 0x" << std::hex << targets[i];
1066a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
106731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
106831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
106952a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbeevoid DumpPackedSwitchTable(const uint16_t* table)
1070a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /*
1071a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Packed switch data format:
1072a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  ushort ident = 0x0100   magic value
1073a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  ushort size       number of entries in the table
1074a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  int first_key       first (and lowest) switch case value
1075a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  int targets[size]     branch targets, relative to switch opcode
1076a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *
1077a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Total size is (4+size*2) 16-bit code units.
1078a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   */
1079a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
1080eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee  uint16_t ident = table[0];
1081cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  const int* targets = reinterpret_cast<const int*>(&table[4]);
1082a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int entries = table[1];
1083fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int low_key = s4FromSwitchData(&table[2]);
1084a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident
1085fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee            << ", entries: " << std::dec << entries << ", low_key: " << low_key;
1086a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  for (int i = 0; i < entries; i++) {
1087fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    LOG(INFO) << "  Key[" << (i + low_key) << "] -> 0x" << std::hex
1088a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee              << targets[i];
1089a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
109031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
1091e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
1092d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee/*
1093d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee * Set up special LIR to mark a Dalvik byte-code instruction start and
1094fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * record it in the boundary_map.  NOTE: in cases such as kMirOpCheck in
1095d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee * which we split a single Dalvik instruction, only the first MIR op
1096d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee * associated with a Dalvik PC should be entered into the map.
1097d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee */
1098fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* MarkBoundary(CompilationUnit* cu, int offset, const char* inst_str)
1099d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee{
1100fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* res = NewLIR1(cu, kPseudoDalvikByteCodeBoundary, reinterpret_cast<uintptr_t>(inst_str));
1101fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (cu->boundary_map.find(offset) == cu->boundary_map.end()) {
1102fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    cu->boundary_map.Put(offset, res);
1103d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee  }
1104d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee  return res;
1105d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee}
1106e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
1107e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbeebool EvaluateBranch(Instruction::Code opcode, int32_t src1, int32_t src2)
1108e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee{
1109e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  bool is_taken;
1110e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  switch (opcode) {
1111e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    case Instruction::IF_EQ: is_taken = (src1 == src2); break;
1112e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    case Instruction::IF_NE: is_taken = (src1 != src2); break;
1113e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    case Instruction::IF_LT: is_taken = (src1 < src2); break;
1114e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    case Instruction::IF_GE: is_taken = (src1 >= src2); break;
1115e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    case Instruction::IF_GT: is_taken = (src1 > src2); break;
1116e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    case Instruction::IF_LE: is_taken = (src1 <= src2); break;
1117e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    case Instruction::IF_EQZ: is_taken = (src1 == 0); break;
1118e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    case Instruction::IF_NEZ: is_taken = (src1 != 0); break;
1119e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    case Instruction::IF_LTZ: is_taken = (src1 < 0); break;
1120e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    case Instruction::IF_GEZ: is_taken = (src1 >= 0); break;
1121e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    case Instruction::IF_GTZ: is_taken = (src1 > 0); break;
1122e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    case Instruction::IF_LEZ: is_taken = (src1 <= 0); break;
1123e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    default:
1124e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee      LOG(FATAL) << "Unexpected opcode " << opcode;
1125e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee      is_taken = false;
1126e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  }
1127e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  return is_taken;
1128e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee}
1129e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
11304ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee// Convert relation of src1/src2 to src2/src1
11314ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbeeConditionCode FlipComparisonOrder(ConditionCode before) {
11324ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  ConditionCode res;
11334ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  switch (before) {
11344ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondEq: res = kCondEq; break;
11354ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondNe: res = kCondNe; break;
11364ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondLt: res = kCondGt; break;
11374ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondGt: res = kCondLt; break;
11384ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondLe: res = kCondGe; break;
11394ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondGe: res = kCondLe; break;
11404ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    default:
11414ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      res = static_cast<ConditionCode>(0);
11424ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      LOG(FATAL) << "Unexpected ccode " << before;
11434ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
11444ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  return res;
11454ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
11464ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
1147a3a82b219531effb53aef13f48e50db9bf0f9fb5buzbee} // namespace art
1148