codegen_util.cc revision fa57c47f1b72916371a9c2d5c1389219bce655b4
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
171bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee#include "../compiler_internals.h"
180c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers#include "gc_map.h"
190c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers#include "verifier/dex_gc_map.h"
200c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers#include "verifier/method_verifier.h"
211bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee#include "ralloc_util.h"
22eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee#include "codegen_util.h"
230c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
24e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbeenamespace art {
25e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
26cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee/* Convert an instruction to a NOP */
2752a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbeevoid NopLIR( LIR* lir)
28cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee{
29fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  lir->flags.is_nop = true;
30cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee}
31cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee
32fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeevoid SetMemRefType(LIR* lir, bool is_load, int mem_type)
3331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
34fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  uint64_t *mask_ptr;
35eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee  uint64_t mask = ENCODE_MEM;;
3652a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  DCHECK(GetTargetInstFlags(lir->opcode) & (IS_LOAD | IS_STORE));
37fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (is_load) {
38fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    mask_ptr = &lir->use_mask;
39a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
40fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    mask_ptr = &lir->def_mask;
41a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
42a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Clear out the memref flags */
43fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  *mask_ptr &= ~mask;
44a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* ..and then add back the one we need */
45fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  switch (mem_type) {
46a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kLiteral:
47fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      DCHECK(is_load);
48fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      *mask_ptr |= ENCODE_LITERAL;
49a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
50a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kDalvikReg:
51fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      *mask_ptr |= ENCODE_DALVIK_REG;
52a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
53a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kHeapRef:
54fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      *mask_ptr |= ENCODE_HEAP_REF;
55a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
56a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kMustNotAlias:
57a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      /* Currently only loads can be marked as kMustNotAlias */
5852a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      DCHECK(!(GetTargetInstFlags(lir->opcode) & IS_STORE));
59fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      *mask_ptr |= ENCODE_MUST_NOT_ALIAS;
60a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
61a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
62fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      LOG(FATAL) << "Oat: invalid memref kind - " << mem_type;
63a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
6431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
6531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
6631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
67b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers * Mark load/store instructions that access Dalvik registers through the stack.
6831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
69fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeevoid AnnotateDalvikRegAccess(LIR* lir, int reg_id, bool is_load, bool is64bit)
7031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
71fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  SetMemRefType(lir, is_load, kDalvikReg);
7231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
73a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /*
74fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee   * Store the Dalvik register id in alias_info. Mark the MSB if it is a 64-bit
75a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * access.
76a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   */
77fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  lir->alias_info = ENCODE_ALIAS_INFO(reg_id, is64bit);
7831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
7931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
8031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
8131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Mark the corresponding bit(s).
8231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
83fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeevoid SetupRegMask(CompilationUnit* cu, uint64_t* mask, int reg)
8431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
85fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  *mask |= GetRegMaskCommon(cu, reg);
8631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
8731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
8831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
8931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Set up the proper fields in the resource mask
9031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
91fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeevoid SetupResourceMasks(CompilationUnit* cu, LIR* lir)
9231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
93a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int opcode = lir->opcode;
9431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
95a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (opcode <= 0) {
96fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    lir->use_mask = lir->def_mask = 0;
97a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    return;
98a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
9931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
10052a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  uint64_t flags = GetTargetInstFlags(opcode);
10131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
102a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (flags & NEEDS_FIXUP) {
103a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    lir->flags.pcRelFixup = true;
104a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
10531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
106a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Get the starting size of the instruction's template */
10752a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  lir->flags.size = GetInsnSize(lir);
108e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
109a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Set up the mask for resources that are updated */
110a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (flags & (IS_LOAD | IS_STORE)) {
111a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    /* Default to heap - will catch specialized classes later */
11252a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee    SetMemRefType(lir, flags & IS_LOAD, kHeapRef);
113a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
11431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
115a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /*
116a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Conservatively assume the branch here will call out a function that in
117a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * turn will trash everything.
118a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   */
119a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (flags & IS_BRANCH) {
120fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    lir->def_mask = lir->use_mask = ENCODE_ALL;
121a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    return;
122a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
12331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
124a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (flags & REG_DEF0) {
125fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    SetupRegMask(cu, &lir->def_mask, lir->operands[0]);
126a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
12731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
128a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (flags & REG_DEF1) {
129fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    SetupRegMask(cu, &lir->def_mask, lir->operands[1]);
130a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
13131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
13231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
133a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (flags & SETS_CCODES) {
134fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    lir->def_mask |= ENCODE_CCODE;
135a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
13631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
137a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) {
138a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    int i;
13931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
140a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    for (i = 0; i < 4; i++) {
141a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      if (flags & (1 << (kRegUse0 + i))) {
142fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        SetupRegMask(cu, &lir->use_mask, lir->operands[i]);
143a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
14431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
145a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
14631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
147a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (flags & USES_CCODES) {
148fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    lir->use_mask |= ENCODE_CCODE;
149a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
15031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
151b046e16d8b8da318d6055f9308950131f1255e08buzbee  // Handle target-specific actions
152fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  SetupTargetResourceMasks(cu, lir);
15331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
15431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
15531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
1565de3494e4297c0d480409da3fecee39173f1d4e1buzbee * Debugging macros
1575de3494e4297c0d480409da3fecee39173f1d4e1buzbee */
1585de3494e4297c0d480409da3fecee39173f1d4e1buzbee#define DUMP_RESOURCE_MASK(X)
1595de3494e4297c0d480409da3fecee39173f1d4e1buzbee#define DUMP_SSA_REP(X)
1605de3494e4297c0d480409da3fecee39173f1d4e1buzbee
1615de3494e4297c0d480409da3fecee39173f1d4e1buzbee/* Pretty-print a LIR instruction */
162fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeevoid DumpLIRInsn(CompilationUnit* cu, LIR* lir, unsigned char* base_addr)
1635de3494e4297c0d480409da3fecee39173f1d4e1buzbee{
164a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int offset = lir->offset;
165a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int dest = lir->operands[0];
166fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  const bool dump_nop = (cu->enable_debug & (1 << kDebugShowNops));
167a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee
168a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Handle pseudo-ops individually, and all regular insns as a group */
169a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (lir->opcode) {
170a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoMethodEntry:
171a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "-------- method entry "
172fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                << PrettyMethod(cu->method_idx, *cu->dex_file);
173a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
174a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoMethodExit:
175a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "-------- Method_Exit";
176a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
177a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoBarrier:
178a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "-------- BARRIER";
179a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
180a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoExtended:
181cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(INFO) << "-------- " << reinterpret_cast<char*>(dest);
182a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
183a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoSSARep:
184cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " <<  reinterpret_cast<char*>(dest));
185a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
186a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoEntryBlock:
187a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
188a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
189a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoDalvikByteCodeBoundary:
190a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "-------- dalvik offset: 0x" << std::hex
191fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                << lir->dalvik_offset << " @ " << reinterpret_cast<char*>(lir->operands[0]);
192a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
193a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoExitBlock:
194a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
195a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
196a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoPseudoAlign4:
197fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      LOG(INFO) << reinterpret_cast<uintptr_t>(base_addr) + offset << " (0x" << std::hex
198a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                << offset << "): .align4";
199a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
200a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoEHBlockLabel:
201a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "Exception_Handling:";
202a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
203a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoTargetLabel:
204a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoNormalBlockLabel:
205cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(INFO) << "L" << reinterpret_cast<void*>(lir) << ":";
206a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
207a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoThrowTarget:
208cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(INFO) << "LT" << reinterpret_cast<void*>(lir) << ":";
209a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
210a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoIntrinsicRetry:
211cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(INFO) << "IR" << reinterpret_cast<void*>(lir) << ":";
212a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
213a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoSuspendTarget:
214cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(INFO) << "LS" << reinterpret_cast<void*>(lir) << ":";
215a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
2168320f3867c02bae9bef6cdab267820cb7b412781buzbee    case kPseudoSafepointPC:
217fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      LOG(INFO) << "LsafepointPC_0x" << std::hex << lir->offset << "_" << lir->dalvik_offset << ":";
2188320f3867c02bae9bef6cdab267820cb7b412781buzbee      break;
219a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    case kPseudoExportedPC:
220fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      LOG(INFO) << "LexportedPC_0x" << std::hex << lir->offset << "_" << lir->dalvik_offset << ":";
221a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee      break;
222a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoCaseLabel:
223cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(INFO) << "LC" << reinterpret_cast<void*>(lir) << ": Case target 0x"
224a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                << std::hex << lir->operands[0] << "|" << std::dec <<
225a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        lir->operands[0];
226a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
227a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
228fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (lir->flags.is_nop && !dump_nop) {
229a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        break;
230a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      } else {
23152a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee        std::string op_name(BuildInsnString(GetTargetInstName(lir->opcode),
232fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                            lir, base_addr));
23352a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee        std::string op_operands(BuildInsnString(GetTargetInstFmt(lir->opcode),
234fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                                lir, base_addr));
235a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        LOG(INFO) << StringPrintf("%05x: %-9s%s%s",
236fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                  reinterpret_cast<unsigned int>(base_addr + offset),
237a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                                  op_name.c_str(), op_operands.c_str(),
238fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                  lir->flags.is_nop ? "(nop)" : "");
239a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
240a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
241a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
242a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee
243fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (lir->use_mask && (!lir->flags.is_nop || dump_nop)) {
244fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    DUMP_RESOURCE_MASK(DumpResourceMask((LIR* ) lir, lir->use_mask, "use"));
245a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
246fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (lir->def_mask && (!lir->flags.is_nop || dump_nop)) {
247fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    DUMP_RESOURCE_MASK(DumpResourceMask((LIR* ) lir, lir->def_mask, "def"));
248a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
2495de3494e4297c0d480409da3fecee39173f1d4e1buzbee}
2505de3494e4297c0d480409da3fecee39173f1d4e1buzbee
251fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeevoid DumpPromotionMap(CompilationUnit *cu)
2525de3494e4297c0d480409da3fecee39173f1d4e1buzbee{
253fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int num_regs = cu->num_dalvik_registers + cu->num_compiler_temps + 1;
254fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  for (int i = 0; i < num_regs; i++) {
255fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    PromotionMap v_reg_map = cu->promotion_map[i];
256a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    std::string buf;
257fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (v_reg_map.fp_location == kLocPhysReg) {
258fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      StringAppendF(&buf, " : s%d", v_reg_map.FpReg & FpRegMask());
259a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    }
2609c044ce5f76e9bfa17c4c1979e9f8c99ae100695buzbee
261a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    std::string buf3;
262fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (i < cu->num_dalvik_registers) {
263a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      StringAppendF(&buf3, "%02d", i);
264fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    } else if (i == cu->method_sreg) {
265a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      buf3 = "Method*";
266a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else {
267fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      StringAppendF(&buf3, "ct%d", i - cu->num_dalvik_registers);
2685de3494e4297c0d480409da3fecee39173f1d4e1buzbee    }
269a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee
270a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    LOG(INFO) << StringPrintf("V[%s] -> %s%d%s", buf3.c_str(),
271fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                              v_reg_map.core_location == kLocPhysReg ?
272fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                              "r" : "SP+", v_reg_map.core_location == kLocPhysReg ?
273fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                              v_reg_map.core_reg : SRegOffset(cu, i),
274a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                              buf.c_str());
275a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
2765de3494e4297c0d480409da3fecee39173f1d4e1buzbee}
2775de3494e4297c0d480409da3fecee39173f1d4e1buzbee
278a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee/* Dump a mapping table */
279aad94383fc41e8f8770f0b2144f766a2ffa772e7buzbeestatic void DumpMappingTable(const char* table_name, const std::string& descriptor,
280aad94383fc41e8f8770f0b2144f766a2ffa772e7buzbee                             const std::string& name, const std::string& signature,
281aad94383fc41e8f8770f0b2144f766a2ffa772e7buzbee                             const std::vector<uint32_t>& v) {
282a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee  if (v.size() > 0) {
283a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    std::string line(StringPrintf("\n  %s %s%s_%s_table[%zu] = {", table_name,
284a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee                     descriptor.c_str(), name.c_str(), signature.c_str(), v.size()));
285a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    std::replace(line.begin(), line.end(), ';', '_');
286a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    LOG(INFO) << line;
287a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    for (uint32_t i = 0; i < v.size(); i+=2) {
288a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee      line = StringPrintf("    {0x%05x, 0x%04x},", v[i], v[i+1]);
289a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee      LOG(INFO) << line;
290a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    }
291a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    LOG(INFO) <<"  };\n\n";
292a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee  }
293a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee}
294a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee
2955de3494e4297c0d480409da3fecee39173f1d4e1buzbee/* Dump instructions and constant pool contents */
296fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeevoid CodegenDump(CompilationUnit* cu)
2975de3494e4297c0d480409da3fecee39173f1d4e1buzbee{
298a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LOG(INFO) << "Dumping LIR insns for "
299fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee            << PrettyMethod(cu->method_idx, *cu->dex_file);
300fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* lir_insn;
301fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int insns_size = cu->insns_size;
302fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee
303fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LOG(INFO) << "Regs (excluding ins) : " << cu->num_regs;
304fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LOG(INFO) << "Ins          : " << cu->num_ins;
305fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LOG(INFO) << "Outs         : " << cu->num_outs;
306fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LOG(INFO) << "CoreSpills       : " << cu->num_core_spills;
307fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LOG(INFO) << "FPSpills       : " << cu->num_fp_spills;
308fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LOG(INFO) << "CompilerTemps    : " << cu->num_compiler_temps;
309fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LOG(INFO) << "Frame size       : " << cu->frame_size;
310fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LOG(INFO) << "code size is " << cu->total_size <<
311fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    " bytes, Dalvik size is " << insns_size * 2;
312a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LOG(INFO) << "expansion factor: "
313fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee            << static_cast<float>(cu->total_size) / static_cast<float>(insns_size * 2);
314fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DumpPromotionMap(cu);
315fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  for (lir_insn = cu->first_lir_insn; lir_insn; lir_insn = lir_insn->next) {
316fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    DumpLIRInsn(cu, lir_insn, 0);
317a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
318fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  for (lir_insn = cu->literal_list; lir_insn; lir_insn = lir_insn->next) {
319fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)", lir_insn->offset, lir_insn->offset,
320fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                              lir_insn->operands[0]);
321a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
322a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee
323a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  const DexFile::MethodId& method_id =
324fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      cu->dex_file->GetMethodId(cu->method_idx);
325fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  std::string signature(cu->dex_file->GetMethodSignature(method_id));
326fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  std::string name(cu->dex_file->GetMethodName(method_id));
327fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  std::string descriptor(cu->dex_file->GetMethodDeclaringClassDescriptor(method_id));
328a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee
329a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee  // Dump mapping tables
330fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DumpMappingTable("PC2Dex_MappingTable", descriptor, name, signature, cu->pc2dexMappingTable);
331fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DumpMappingTable("Dex2PC_MappingTable", descriptor, name, signature, cu->dex2pcMappingTable);
3325de3494e4297c0d480409da3fecee39173f1d4e1buzbee}
3335de3494e4297c0d480409da3fecee39173f1d4e1buzbee
334a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee
335fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* RawLIR(CompilationUnit* cu, int dalvik_offset, int opcode, int op0,
336a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      int op1, int op2, int op3, int op4, LIR* target)
337a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
338fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* insn = static_cast<LIR*>(NewMem(cu, sizeof(LIR), true, kAllocLIR));
339fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  insn->dalvik_offset = dalvik_offset;
340a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  insn->opcode = opcode;
341a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  insn->operands[0] = op0;
342a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  insn->operands[1] = op1;
343a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  insn->operands[2] = op2;
344a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  insn->operands[3] = op3;
345a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  insn->operands[4] = op4;
346a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  insn->target = target;
347fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  SetupResourceMasks(cu, insn);
348a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee  if ((opcode == kPseudoTargetLabel) || (opcode == kPseudoSafepointPC) ||
349a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee      (opcode == kPseudoExportedPC)) {
350a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    // Always make labels scheduling barriers
351fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    insn->use_mask = insn->def_mask = ENCODE_ALL;
352a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
353a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return insn;
354a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee}
355a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee
356a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee/*
357a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee * The following are building blocks to construct low-level IRs with 0 - 4
358a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee * operands.
359a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee */
360fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* NewLIR0(CompilationUnit* cu, int opcode)
361a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee{
362fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(is_pseudo_opcode(opcode) || (GetTargetInstFlags(opcode) & NO_OPERAND))
36352a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      << GetTargetInstName(opcode) << " " << opcode << " "
364fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      << PrettyMethod(cu->method_idx, *cu->dex_file) << " "
365fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      << cu->current_dalvik_offset;
366fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* insn = RawLIR(cu, cu->current_dalvik_offset, opcode);
367fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  AppendLIR(cu, insn);
368a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return insn;
36931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
37031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
371fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* NewLIR1(CompilationUnit* cu, int opcode,
372a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee               int dest)
37331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
374fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(is_pseudo_opcode(opcode) || (GetTargetInstFlags(opcode) & IS_UNARY_OP))
37552a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      << GetTargetInstName(opcode) << " " << opcode << " "
376fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      << PrettyMethod(cu->method_idx, *cu->dex_file) << " "
377fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      << cu->current_dalvik_offset;
378fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* insn = RawLIR(cu, cu->current_dalvik_offset, opcode, dest);
379fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  AppendLIR(cu, insn);
380a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return insn;
38131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
38231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
383fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* NewLIR2(CompilationUnit* cu, int opcode,
384a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee               int dest, int src1)
38531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
386fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(is_pseudo_opcode(opcode) || (GetTargetInstFlags(opcode) & IS_BINARY_OP))
38752a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      << GetTargetInstName(opcode) << " " << opcode << " "
388fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      << PrettyMethod(cu->method_idx, *cu->dex_file) << " "
389fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      << cu->current_dalvik_offset;
390fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* insn = RawLIR(cu, cu->current_dalvik_offset, opcode, dest, src1);
391fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  AppendLIR(cu, insn);
392a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return insn;
39331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
39431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
395fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* NewLIR3(CompilationUnit* cu, int opcode,
396a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee               int dest, int src1, int src2)
39731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
398fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(is_pseudo_opcode(opcode) || (GetTargetInstFlags(opcode) & IS_TERTIARY_OP))
39952a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      << GetTargetInstName(opcode) << " " << opcode << " "
400fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      << PrettyMethod(cu->method_idx, *cu->dex_file) << " "
401fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      << cu->current_dalvik_offset;
402fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* insn = RawLIR(cu, cu->current_dalvik_offset, opcode, dest, src1, src2);
403fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  AppendLIR(cu, insn);
404a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return insn;
40531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
40631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
407fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* NewLIR4(CompilationUnit* cu, int opcode,
408a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      int dest, int src1, int src2, int info)
40931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
410fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(is_pseudo_opcode(opcode) || (GetTargetInstFlags(opcode) & IS_QUAD_OP))
41152a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      << GetTargetInstName(opcode) << " " << opcode << " "
412fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      << PrettyMethod(cu->method_idx, *cu->dex_file) << " "
413fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      << cu->current_dalvik_offset;
414fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* insn = RawLIR(cu, cu->current_dalvik_offset, opcode, dest, src1, src2, info);
415fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  AppendLIR(cu, insn);
416a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return insn;
41731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
41831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
419fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* NewLIR5(CompilationUnit* cu, int opcode,
420a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee       int dest, int src1, int src2, int info1, int info2)
421b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers{
422fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(is_pseudo_opcode(opcode) || (GetTargetInstFlags(opcode) & IS_QUIN_OP))
42352a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      << GetTargetInstName(opcode) << " " << opcode << " "
424fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      << PrettyMethod(cu->method_idx, *cu->dex_file) << " "
425fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      << cu->current_dalvik_offset;
426fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* insn = RawLIR(cu, cu->current_dalvik_offset, opcode, dest, src1, src2, info1, info2);
427fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  AppendLIR(cu, insn);
428a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return insn;
429b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers}
430b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers
43131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
43231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Search the existing constants in the literal pool for an exact or close match
43331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * within specified delta (greater or equal to 0).
43431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
435fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* ScanLiteralPool(LIR* data_target, int value, unsigned int delta)
43631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
437fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  while (data_target) {
438fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if ((static_cast<unsigned>(value - data_target->operands[0])) <= delta)
439fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      return data_target;
440fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    data_target = data_target->next;
441a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
442a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return NULL;
44331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
44431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
44531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* Search the existing constants in the literal pool for an exact wide match */
446fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* ScanLiteralPoolWide(LIR* data_target, int val_lo, int val_hi)
44731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
448fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool lo_match = false;
449fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* lo_target = NULL;
450fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  while (data_target) {
451fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (lo_match && (data_target->operands[0] == val_hi)) {
452fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      return lo_target;
45331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
454fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    lo_match = false;
455fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (data_target->operands[0] == val_lo) {
456fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      lo_match = true;
457fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      lo_target = data_target;
458a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    }
459fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    data_target = data_target->next;
460a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
461a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return NULL;
46231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
46331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
46431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
46531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * The following are building blocks to insert constants into the pool or
46631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * instruction streams.
46731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
46831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
4695de3494e4297c0d480409da3fecee39173f1d4e1buzbee/* Add a 32-bit constant either in the constant pool */
470fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* AddWordData(CompilationUnit* cu, LIR* *constant_list_p, int value)
47131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
472a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Add the constant to the literal pool */
473fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (constant_list_p) {
474fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    LIR* new_value = static_cast<LIR*>(NewMem(cu, sizeof(LIR), true, kAllocData));
475fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    new_value->operands[0] = value;
476fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    new_value->next = *constant_list_p;
477fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    *constant_list_p = new_value;
478fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    return new_value;
479a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
480a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return NULL;
48131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
48231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
48331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* Add a 64-bit constant to the constant pool or mixed with code */
484fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* AddWideData(CompilationUnit* cu, LIR* *constant_list_p,
485fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee               int val_lo, int val_hi)
48631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
487fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  AddWordData(cu, constant_list_p, val_hi);
488fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  return AddWordData(cu, constant_list_p, val_lo);
48931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
49031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
491aad94383fc41e8f8770f0b2144f766a2ffa772e7buzbeestatic void PushWord(std::vector<uint8_t>&buf, int data) {
492a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  buf.push_back( data & 0xff);
493a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  buf.push_back( (data >> 8) & 0xff);
494a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  buf.push_back( (data >> 16) & 0xff);
495a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  buf.push_back( (data >> 24) & 0xff);
496e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
497e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
498aad94383fc41e8f8770f0b2144f766a2ffa772e7buzbeestatic void AlignBuffer(std::vector<uint8_t>&buf, size_t offset) {
499a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (buf.size() < offset) {
500a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    buf.push_back(0);
501a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
502e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
503e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
504e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Write the literal pool to the output stream */
505fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic void InstallLiteralPools(CompilationUnit* cu)
506e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
507fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  AlignBuffer(cu->code_buffer, cu->data_offset);
508fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* data_lir = cu->literal_list;
509fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  while (data_lir != NULL) {
510fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    PushWord(cu->code_buffer, data_lir->operands[0]);
511fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    data_lir = NEXT_LIR(data_lir);
512a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
513a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  // Push code and method literals, record offsets for the compiler to patch.
514fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  data_lir = cu->code_literal_list;
515fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  while (data_lir != NULL) {
516fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    uint32_t target = data_lir->operands[0];
517fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    cu->compiler->AddCodePatch(cu->dex_file,
518fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                  cu->method_idx,
519fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                  cu->invoke_type,
520137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers                                  target,
521fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                  static_cast<InvokeType>(data_lir->operands[1]),
522fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                  cu->code_buffer.size());
523fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    const DexFile::MethodId& id = cu->dex_file->GetMethodId(target);
524137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    // unique based on target to ensure code deduplication works
525137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
526fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    PushWord(cu->code_buffer, unique_patch_value);
527fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    data_lir = NEXT_LIR(data_lir);
528137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers  }
529fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  data_lir = cu->method_literal_list;
530fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  while (data_lir != NULL) {
531fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    uint32_t target = data_lir->operands[0];
532fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    cu->compiler->AddMethodPatch(cu->dex_file,
533fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                    cu->method_idx,
534fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                    cu->invoke_type,
535a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                                    target,
536fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                    static_cast<InvokeType>(data_lir->operands[1]),
537fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                    cu->code_buffer.size());
538fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    const DexFile::MethodId& id = cu->dex_file->GetMethodId(target);
539137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    // unique based on target to ensure code deduplication works
540137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
541fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    PushWord(cu->code_buffer, unique_patch_value);
542fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    data_lir = NEXT_LIR(data_lir);
543a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
544e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
545e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
546e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Write the switch tables to the output stream */
547fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic void InstallSwitchTables(CompilationUnit* cu)
548e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
549a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  GrowableListIterator iterator;
550fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  GrowableListIteratorInit(&cu->switch_tables, &iterator);
551a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (true) {
552fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    SwitchTable* tab_rec = reinterpret_cast<SwitchTable*>(GrowableListIteratorNext( &iterator));
553fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (tab_rec == NULL) break;
554fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    AlignBuffer(cu->code_buffer, tab_rec->offset);
555a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    /*
556a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee     * For Arm, our reference point is the address of the bx
557a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee     * instruction that does the launch, so we have to subtract
558a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee     * the auto pc-advance.  For other targets the reference point
559a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee     * is a label, so we can use the offset as-is.
560a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee     */
561fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    int bx_offset = INVALID_OFFSET;
562fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    switch (cu->instruction_set) {
563b046e16d8b8da318d6055f9308950131f1255e08buzbee      case kThumb2:
564fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        bx_offset = tab_rec->anchor->offset + 4;
565b046e16d8b8da318d6055f9308950131f1255e08buzbee        break;
566b046e16d8b8da318d6055f9308950131f1255e08buzbee      case kX86:
567fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        bx_offset = 0;
568b046e16d8b8da318d6055f9308950131f1255e08buzbee        break;
569b046e16d8b8da318d6055f9308950131f1255e08buzbee      case kMips:
570fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        bx_offset = tab_rec->anchor->offset;
571b046e16d8b8da318d6055f9308950131f1255e08buzbee        break;
572fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      default: LOG(FATAL) << "Unexpected instruction set: " << cu->instruction_set;
573b046e16d8b8da318d6055f9308950131f1255e08buzbee    }
574fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (cu->verbose) {
575fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      LOG(INFO) << "Switch table for offset 0x" << std::hex << bx_offset;
576a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    }
577fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) {
578fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      const int* keys = reinterpret_cast<const int*>(&(tab_rec->table[2]));
579fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      for (int elems = 0; elems < tab_rec->table[1]; elems++) {
580fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        int disp = tab_rec->targets[elems]->offset - bx_offset;
581fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        if (cu->verbose) {
582a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee          LOG(INFO) << "  Case[" << elems << "] key: 0x"
583a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                    << std::hex << keys[elems] << ", disp: 0x"
584a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                    << std::hex << disp;
585e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        }
586fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        PushWord(cu->code_buffer, keys[elems]);
587fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        PushWord(cu->code_buffer,
588fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          tab_rec->targets[elems]->offset - bx_offset);
589a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
590a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else {
591fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      DCHECK_EQ(static_cast<int>(tab_rec->table[0]),
592a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                static_cast<int>(Instruction::kPackedSwitchSignature));
593fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      for (int elems = 0; elems < tab_rec->table[1]; elems++) {
594fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        int disp = tab_rec->targets[elems]->offset - bx_offset;
595fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        if (cu->verbose) {
596a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee          LOG(INFO) << "  Case[" << elems << "] disp: 0x"
597a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                    << std::hex << disp;
598e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        }
599fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        PushWord(cu->code_buffer, tab_rec->targets[elems]->offset - bx_offset);
600a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
601e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
602a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
603e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
604e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
605e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Write the fill array dta to the output stream */
606fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic void InstallFillArrayData(CompilationUnit* cu)
607e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
608a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  GrowableListIterator iterator;
609fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  GrowableListIteratorInit(&cu->fill_array_data, &iterator);
610a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (true) {
611fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    FillArrayData *tab_rec =
61252a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee        reinterpret_cast<FillArrayData*>(GrowableListIteratorNext( &iterator));
613fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (tab_rec == NULL) break;
614fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    AlignBuffer(cu->code_buffer, tab_rec->offset);
615fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    for (int i = 0; i < (tab_rec->size + 1) / 2; i++) {
616fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      cu->code_buffer.push_back( tab_rec->table[i] & 0xFF);
617fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      cu->code_buffer.push_back( (tab_rec->table[i] >> 8) & 0xFF);
618e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
619a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
620e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
621e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
622aad94383fc41e8f8770f0b2144f766a2ffa772e7buzbeestatic int AssignLiteralOffsetCommon(LIR* lir, int offset)
623e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
624a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  for (;lir != NULL; lir = lir->next) {
625a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    lir->offset = offset;
626a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    offset += 4;
627a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
628a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return offset;
629e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
630e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
6316459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee// Make sure we have a code address for every declared catch entry
632fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic bool VerifyCatchEntries(CompilationUnit* cu)
6336459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee{
6346459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  bool success = true;
635fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  for (std::set<uint32_t>::const_iterator it = cu->catches.begin(); it != cu->catches.end(); ++it) {
636fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    uint32_t dex_pc = *it;
6376459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    bool found = false;
638fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    for (size_t i = 0; i < cu->dex2pcMappingTable.size(); i += 2) {
639fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (dex_pc == cu->dex2pcMappingTable[i+1]) {
6406459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee        found = true;
6416459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee        break;
6426459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee      }
6436459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    }
6446459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    if (!found) {
645fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      LOG(INFO) << "Missing native PC for catch entry @ 0x" << std::hex << dex_pc;
6466459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee      success = false;
6476459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    }
6486459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  }
6496459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  // Now, try in the other direction
650fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  for (size_t i = 0; i < cu->dex2pcMappingTable.size(); i += 2) {
651fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    uint32_t dex_pc = cu->dex2pcMappingTable[i+1];
652fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (cu->catches.find(dex_pc) == cu->catches.end()) {
653fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      LOG(INFO) << "Unexpected catch entry @ dex pc 0x" << std::hex << dex_pc;
6546459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee      success = false;
6556459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    }
6566459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  }
6576459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  if (!success) {
658fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    LOG(INFO) << "Bad dex2pcMapping table in " << PrettyMethod(cu->method_idx, *cu->dex_file);
659fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    LOG(INFO) << "Entries @ decode: " << cu->catches.size() << ", Entries in table: "
660fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee              << cu->dex2pcMappingTable.size()/2;
6616459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  }
6626459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  return success;
6636459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee}
6646459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee
665fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic void CreateMappingTables(CompilationUnit* cu)
666e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
667fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  for (LIR* tgt_lir = cu->first_lir_insn; tgt_lir != NULL; tgt_lir = NEXT_LIR(tgt_lir)) {
668fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (!tgt_lir->flags.is_nop && (tgt_lir->opcode == kPseudoSafepointPC)) {
669fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      cu->pc2dexMappingTable.push_back(tgt_lir->offset);
670fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      cu->pc2dexMappingTable.push_back(tgt_lir->dalvik_offset);
671a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    }
672fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (!tgt_lir->flags.is_nop && (tgt_lir->opcode == kPseudoExportedPC)) {
673fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      cu->dex2pcMappingTable.push_back(tgt_lir->offset);
674fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      cu->dex2pcMappingTable.push_back(tgt_lir->dalvik_offset);
675e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
676a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
677fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(VerifyCatchEntries(cu));
678fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  cu->combined_mapping_table.push_back(cu->pc2dexMappingTable.size() +
679fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                        cu->dex2pcMappingTable.size());
680fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  cu->combined_mapping_table.push_back(cu->pc2dexMappingTable.size());
681fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  cu->combined_mapping_table.insert(cu->combined_mapping_table.end(),
682fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                     cu->pc2dexMappingTable.begin(),
683fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                     cu->pc2dexMappingTable.end());
684fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  cu->combined_mapping_table.insert(cu->combined_mapping_table.end(),
685fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                     cu->dex2pcMappingTable.begin(),
686fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                     cu->dex2pcMappingTable.end());
687e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
688e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
6890c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogersclass NativePcToReferenceMapBuilder {
6900c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers public:
6910c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  NativePcToReferenceMapBuilder(std::vector<uint8_t>* table,
6920c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers                                size_t entries, uint32_t max_native_offset,
6930c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers                                size_t references_width) : entries_(entries),
6940c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers                                references_width_(references_width), in_use_(entries),
6950c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers                                table_(table) {
6960c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    // Compute width in bytes needed to hold max_native_offset.
6970c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    native_offset_width_ = 0;
6980c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    while (max_native_offset != 0) {
6990c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers      native_offset_width_++;
7000c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers      max_native_offset >>= 8;
7010c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    }
7020c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    // Resize table and set up header.
7030c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    table->resize((EntryWidth() * entries) + sizeof(uint32_t));
704000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers    CHECK_LT(native_offset_width_, 1U << 3);
705000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers    (*table)[0] = native_offset_width_ & 7;
706000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers    CHECK_LT(references_width_, 1U << 13);
707000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers    (*table)[0] |= (references_width_ << 3) & 0xFF;
708000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers    (*table)[1] = (references_width_ >> 5) & 0xFF;
7090c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    CHECK_LT(entries, 1U << 16);
7100c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    (*table)[2] = entries & 0xFF;
7110c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    (*table)[3] = (entries >> 8) & 0xFF;
7120c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
7130c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
7140c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  void AddEntry(uint32_t native_offset, const uint8_t* references) {
7150c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    size_t table_index = TableIndex(native_offset);
7160c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    while (in_use_[table_index]) {
7170c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers      table_index = (table_index + 1) % entries_;
7180c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    }
7190c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    in_use_[table_index] = true;
7200c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    SetNativeOffset(table_index, native_offset);
7210c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    DCHECK_EQ(native_offset, GetNativeOffset(table_index));
7220c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    SetReferences(table_index, references);
7230c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
7240c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
7250c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers private:
7260c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  size_t TableIndex(uint32_t native_offset) {
7270c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    return NativePcOffsetToReferenceMap::Hash(native_offset) % entries_;
7280c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
7290c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
7300c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  uint32_t GetNativeOffset(size_t table_index) {
7310c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    uint32_t native_offset = 0;
7320c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
7330c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    for (size_t i = 0; i < native_offset_width_; i++) {
7340c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers      native_offset |= (*table_)[table_offset + i] << (i * 8);
7350c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    }
7360c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    return native_offset;
7370c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
7380c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
7390c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  void SetNativeOffset(size_t table_index, uint32_t native_offset) {
7400c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
7410c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    for (size_t i = 0; i < native_offset_width_; i++) {
7420c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers      (*table_)[table_offset + i] = (native_offset >> (i * 8)) & 0xFF;
7430c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    }
7440c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
7450c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
7460c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  void SetReferences(size_t table_index, const uint8_t* references) {
7470c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
7480c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    memcpy(&(*table_)[table_offset + native_offset_width_], references, references_width_);
7490c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
7500c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
7510c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  size_t EntryWidth() const {
7520c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    return native_offset_width_ + references_width_;
7530c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
7540c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
7550c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // Number of entries in the table.
7560c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  const size_t entries_;
7570c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // Number of bytes used to encode the reference bitmap.
7580c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  const size_t references_width_;
7590c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // Number of bytes used to encode a native offset.
7600c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  size_t native_offset_width_;
7610c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // Entries that are in use.
7620c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  std::vector<bool> in_use_;
7630c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // The table we're building.
7640c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  std::vector<uint8_t>* const table_;
7650c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers};
7660c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
767fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic void CreateNativeGcMap(CompilationUnit* cu) {
768fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  const std::vector<uint32_t>& mapping_table = cu->pc2dexMappingTable;
7690c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  uint32_t max_native_offset = 0;
7700c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  for (size_t i = 0; i < mapping_table.size(); i += 2) {
7710c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    uint32_t native_offset = mapping_table[i + 0];
7720c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    if (native_offset > max_native_offset) {
7730c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers      max_native_offset = native_offset;
7740c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    }
7750c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
776fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  Compiler::MethodReference method_ref(cu->dex_file, cu->method_idx);
7770c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  const std::vector<uint8_t>* gc_map_raw = verifier::MethodVerifier::GetDexGcMap(method_ref);
7780c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  verifier::DexPcToReferenceMap dex_gc_map(&(*gc_map_raw)[4], gc_map_raw->size() - 4);
7790c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // Compute native offset to references size.
780fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  NativePcToReferenceMapBuilder native_gc_map_builder(&cu->native_gc_map,
7810c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers                                                      mapping_table.size() / 2, max_native_offset,
7820c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers                                                      dex_gc_map.RegWidth());
7830c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
7840c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  for (size_t i = 0; i < mapping_table.size(); i += 2) {
7850c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    uint32_t native_offset = mapping_table[i + 0];
7860c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    uint32_t dex_pc = mapping_table[i + 1];
7870c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    const uint8_t* references = dex_gc_map.FindBitMap(dex_pc, false);
788a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    CHECK(references != NULL) << "Missing ref for dex pc 0x" << std::hex << dex_pc;
789a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    native_gc_map_builder.AddEntry(native_offset, references);
7900c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
7910c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers}
7920c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
793e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Determine the offset of each literal field */
794fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic int AssignLiteralOffset(CompilationUnit* cu, int offset)
795e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
796fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  offset = AssignLiteralOffsetCommon(cu->literal_list, offset);
797fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  offset = AssignLiteralOffsetCommon(cu->code_literal_list, offset);
798fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  offset = AssignLiteralOffsetCommon(cu->method_literal_list, offset);
799a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return offset;
800e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
801e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
802fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic int AssignSwitchTablesOffset(CompilationUnit* cu, int offset)
803e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
804a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  GrowableListIterator iterator;
805fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  GrowableListIteratorInit(&cu->switch_tables, &iterator);
806a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (true) {
807fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    SwitchTable *tab_rec = reinterpret_cast<SwitchTable*>(GrowableListIteratorNext(&iterator));
808fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (tab_rec == NULL) break;
809fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    tab_rec->offset = offset;
810fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) {
811fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      offset += tab_rec->table[1] * (sizeof(int) * 2);
812a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else {
813fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      DCHECK_EQ(static_cast<int>(tab_rec->table[0]),
814a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                static_cast<int>(Instruction::kPackedSwitchSignature));
815fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      offset += tab_rec->table[1] * sizeof(int);
816e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
817a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
818a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return offset;
819e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
820e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
821fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic int AssignFillArrayDataOffset(CompilationUnit* cu, int offset)
822e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
823a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  GrowableListIterator iterator;
824fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  GrowableListIteratorInit(&cu->fill_array_data, &iterator);
825a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (true) {
826fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    FillArrayData *tab_rec =
82752a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee        reinterpret_cast<FillArrayData*>(GrowableListIteratorNext(&iterator));
828fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (tab_rec == NULL) break;
829fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    tab_rec->offset = offset;
830fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    offset += tab_rec->size;
831a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    // word align
832a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    offset = (offset + 3) & ~3;
833a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    }
834a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return offset;
835e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
836e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
837e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/*
838e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Walk the compilation unit and assign offsets to instructions
839e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * and literals and compute the total size of the compiled unit.
840e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee */
841fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic void AssignOffsets(CompilationUnit* cu)
842e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
843fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int offset = AssignInsnOffsets(cu);
844e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
845a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Const values have to be word aligned */
846a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  offset = (offset + 3) & ~3;
847e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
848a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Set up offsets for literals */
849fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  cu->data_offset = offset;
850e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
851fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  offset = AssignLiteralOffset(cu, offset);
852e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
853fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  offset = AssignSwitchTablesOffset(cu, offset);
854e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
855fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  offset = AssignFillArrayDataOffset(cu, offset);
856e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
857fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  cu->total_size = offset;
858e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
859e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
860e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/*
861e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Go over each instruction in the list and calculate the offset from the top
862e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * before sending them off to the assembler. If out-of-range branch distance is
863e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * seen rearrange the instructions a bit to correct it.
864e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee */
865fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeevoid AssembleLIR(CompilationUnit* cu)
866e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
867fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  AssignOffsets(cu);
868a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /*
869a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Assemble here.  Note that we generate code with optimistic assumptions
870a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * and if found now to work, we'll have to redo the sequence and retry.
871a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   */
872e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
873a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (true) {
874fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    AssemblerStatus res = AssembleInstructions(cu, 0);
875a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    if (res == kSuccess) {
876a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
877a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else {
878fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      cu->assembler_retries++;
879fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (cu->assembler_retries > MAX_ASSEMBLER_RETRIES) {
880fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        CodegenDump(cu);
881a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        LOG(FATAL) << "Assembler error - too many retries";
882a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
883a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      // Redo offsets and try again
884fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      AssignOffsets(cu);
885fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      cu->code_buffer.clear();
886e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
887a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
888e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
889a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  // Install literals
890fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  InstallLiteralPools(cu);
891e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
892a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  // Install switch tables
893fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  InstallSwitchTables(cu);
894e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
895a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  // Install fill array data
896fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  InstallFillArrayData(cu);
897e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
8980c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // Create the mapping table and native offset to reference map.
899fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  CreateMappingTables(cu);
9000c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
901fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  CreateNativeGcMap(cu);
902e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
903e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
90431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
90531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Insert a kPseudoCaseLabel at the beginning of the Dalvik
90631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * offset vaddr.  This label will be used to fix up the case
90731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * branch table during the assembly phase.  Be sure to set
90831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * all resource flags on this to prevent code motion across
90931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * target boundaries.  KeyVal is just there for debugging.
91031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
911fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic LIR* InsertCaseLabel(CompilationUnit* cu, int vaddr, int keyVal)
91231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
913a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  SafeMap<unsigned int, LIR*>::iterator it;
914fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  it = cu->boundary_map.find(vaddr);
915fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (it == cu->boundary_map.end()) {
916a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr;
917a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
918fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* new_label = static_cast<LIR*>(NewMem(cu, sizeof(LIR), true, kAllocLIR));
919fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  new_label->dalvik_offset = vaddr;
920fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  new_label->opcode = kPseudoCaseLabel;
921fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  new_label->operands[0] = keyVal;
922fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  InsertLIRAfter(it->second, new_label);
923fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  return new_label;
92431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
92531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
926fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic void MarkPackedCaseLabels(CompilationUnit* cu, SwitchTable *tab_rec)
92731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
928fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  const uint16_t* table = tab_rec->table;
929fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int base_vaddr = tab_rec->vaddr;
930cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  const int *targets = reinterpret_cast<const int*>(&table[4]);
931a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int entries = table[1];
932fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int low_key = s4FromSwitchData(&table[2]);
933a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  for (int i = 0; i < entries; i++) {
934fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    tab_rec->targets[i] = InsertCaseLabel(cu, base_vaddr + targets[i], i + low_key);
935a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
93631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
93731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
938fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic void MarkSparseCaseLabels(CompilationUnit* cu, SwitchTable *tab_rec)
93931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
940fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  const uint16_t* table = tab_rec->table;
941fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int base_vaddr = tab_rec->vaddr;
942a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int entries = table[1];
943cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  const int* keys = reinterpret_cast<const int*>(&table[2]);
944cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  const int* targets = &keys[entries];
945a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  for (int i = 0; i < entries; i++) {
946fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    tab_rec->targets[i] = InsertCaseLabel(cu, base_vaddr + targets[i], keys[i]);
947a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
94831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
94931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
950fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeevoid ProcessSwitchTables(CompilationUnit* cu)
95131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
952a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  GrowableListIterator iterator;
953fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  GrowableListIteratorInit(&cu->switch_tables, &iterator);
954a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (true) {
955fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    SwitchTable *tab_rec =
95652a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee        reinterpret_cast<SwitchTable*>(GrowableListIteratorNext(&iterator));
957fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (tab_rec == NULL) break;
958fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (tab_rec->table[0] == Instruction::kPackedSwitchSignature) {
959fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      MarkPackedCaseLabels(cu, tab_rec);
960fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    } else if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) {
961fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      MarkSparseCaseLabels(cu, tab_rec);
962a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else {
963a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(FATAL) << "Invalid switch table";
96431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
965a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
96631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
96731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
96852a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbeevoid DumpSparseSwitchTable(const uint16_t* table)
969a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /*
970a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Sparse switch data format:
971a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  ushort ident = 0x0200   magic value
972a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  ushort size       number of entries in the table; > 0
973a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  int keys[size]      keys, sorted low-to-high; 32-bit aligned
974a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  int targets[size]     branch targets, relative to switch opcode
975a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *
976a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Total size is (2+size*4) 16-bit code units.
977a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   */
978a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
979eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee  uint16_t ident = table[0];
980a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int entries = table[1];
981cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  const int* keys = reinterpret_cast<const int*>(&table[2]);
982cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  const int* targets = &keys[entries];
983a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LOG(INFO) <<  "Sparse switch table - ident:0x" << std::hex << ident
984a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee            << ", entries: " << std::dec << entries;
985a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  for (int i = 0; i < entries; i++) {
986a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    LOG(INFO) << "  Key[" << keys[i] << "] -> 0x" << std::hex << targets[i];
987a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
98831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
98931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
99052a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbeevoid DumpPackedSwitchTable(const uint16_t* table)
991a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /*
992a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Packed switch data format:
993a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  ushort ident = 0x0100   magic value
994a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  ushort size       number of entries in the table
995a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  int first_key       first (and lowest) switch case value
996a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  int targets[size]     branch targets, relative to switch opcode
997a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *
998a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Total size is (4+size*2) 16-bit code units.
999a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   */
1000a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
1001eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee  uint16_t ident = table[0];
1002cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  const int* targets = reinterpret_cast<const int*>(&table[4]);
1003a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int entries = table[1];
1004fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int low_key = s4FromSwitchData(&table[2]);
1005a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident
1006fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee            << ", entries: " << std::dec << entries << ", low_key: " << low_key;
1007a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  for (int i = 0; i < entries; i++) {
1008fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    LOG(INFO) << "  Key[" << (i + low_key) << "] -> 0x" << std::hex
1009a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee              << targets[i];
1010a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
101131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
1012e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
1013d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee/*
1014d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee * Set up special LIR to mark a Dalvik byte-code instruction start and
1015fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * record it in the boundary_map.  NOTE: in cases such as kMirOpCheck in
1016d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee * which we split a single Dalvik instruction, only the first MIR op
1017d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee * associated with a Dalvik PC should be entered into the map.
1018d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee */
1019fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeeLIR* MarkBoundary(CompilationUnit* cu, int offset, const char* inst_str)
1020d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee{
1021fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* res = NewLIR1(cu, kPseudoDalvikByteCodeBoundary, reinterpret_cast<uintptr_t>(inst_str));
1022fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (cu->boundary_map.find(offset) == cu->boundary_map.end()) {
1023fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    cu->boundary_map.Put(offset, res);
1024d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee  }
1025d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee  return res;
1026d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee}
1027e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
1028d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee}
1029d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee // namespace art
1030