codegen_util.cc revision cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8
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
170c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers#include "gc_map.h"
180c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers#include "verifier/dex_gc_map.h"
190c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers#include "verifier/method_verifier.h"
20eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee#include "codegen_util.h"
210c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
22e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbeenamespace art {
23e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
24cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee/* Convert an instruction to a NOP */
25cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbeevoid oatNopLIR( LIR* lir)
26cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee{
27cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  lir->flags.isNop = true;
28cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee}
29cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee
3031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid setMemRefType(LIR* lir, bool isLoad, int memType)
3131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
32eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee  uint64_t *maskPtr;
33eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee  uint64_t mask = ENCODE_MEM;;
34a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  DCHECK(EncodingMap[lir->opcode].flags & (IS_LOAD | IS_STORE));
35a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (isLoad) {
36a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    maskPtr = &lir->useMask;
37a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
38a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    maskPtr = &lir->defMask;
39a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
40a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Clear out the memref flags */
41a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  *maskPtr &= ~mask;
42a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* ..and then add back the one we need */
43a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (memType) {
44a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kLiteral:
45a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK(isLoad);
46a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      *maskPtr |= ENCODE_LITERAL;
47a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
48a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kDalvikReg:
49a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      *maskPtr |= ENCODE_DALVIK_REG;
50a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
51a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kHeapRef:
52a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      *maskPtr |= ENCODE_HEAP_REF;
53a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
54a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kMustNotAlias:
55a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      /* Currently only loads can be marked as kMustNotAlias */
56a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK(!(EncodingMap[lir->opcode].flags & IS_STORE));
57a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      *maskPtr |= ENCODE_MUST_NOT_ALIAS;
58a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
59a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
60a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(FATAL) << "Oat: invalid memref kind - " << memType;
61a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
6231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
6331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
6431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
65b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers * Mark load/store instructions that access Dalvik registers through the stack.
6631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
67b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogersvoid annotateDalvikRegAccess(LIR* lir, int regId, bool isLoad, bool is64bit)
6831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
69a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  setMemRefType(lir, isLoad, kDalvikReg);
7031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
71a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /*
72a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Store the Dalvik register id in aliasInfo. Mark the MSB if it is a 64-bit
73a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * access.
74a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   */
75ec13743da80a80c1817cf6660c28917fc28846bcbuzbee  lir->aliasInfo = ENCODE_ALIAS_INFO(regId, is64bit);
7631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
7731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
78eaf09bc65f9a10d12befcdb239156938c9bceef2buzbeeuint64_t oatGetRegMaskCommon(CompilationUnit* cUnit, int reg)
79b046e16d8b8da318d6055f9308950131f1255e08buzbee{
80b046e16d8b8da318d6055f9308950131f1255e08buzbee  return getRegMaskCommon(cUnit, reg);
81b046e16d8b8da318d6055f9308950131f1255e08buzbee}
82b046e16d8b8da318d6055f9308950131f1255e08buzbee
8331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
8431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Mark the corresponding bit(s).
8531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
86eaf09bc65f9a10d12befcdb239156938c9bceef2buzbeeinline void setupRegMask(CompilationUnit* cUnit, uint64_t* mask, int reg)
87b046e16d8b8da318d6055f9308950131f1255e08buzbee{
88b046e16d8b8da318d6055f9308950131f1255e08buzbee  *mask |= getRegMaskCommon(cUnit, reg);
89b046e16d8b8da318d6055f9308950131f1255e08buzbee}
90b046e16d8b8da318d6055f9308950131f1255e08buzbee
91b046e16d8b8da318d6055f9308950131f1255e08buzbee/* Exported version of setupRegMask */
92eaf09bc65f9a10d12befcdb239156938c9bceef2buzbeevoid oatSetupRegMask(CompilationUnit* cUnit, uint64_t* mask, int reg)
9331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
94b046e16d8b8da318d6055f9308950131f1255e08buzbee  setupRegMask(cUnit, mask, reg);
9531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
9631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
9731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
9831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Set up the proper fields in the resource mask
9931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
100b046e16d8b8da318d6055f9308950131f1255e08buzbeevoid setupResourceMasks(CompilationUnit* cUnit, LIR* lir)
10131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
102a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int opcode = lir->opcode;
10331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
104a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (opcode <= 0) {
105a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    lir->useMask = lir->defMask = 0;
106a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    return;
107a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
10831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
109ec13743da80a80c1817cf6660c28917fc28846bcbuzbee  uint64_t flags = EncodingMap[opcode].flags;
11031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
111a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (flags & NEEDS_FIXUP) {
112a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    lir->flags.pcRelFixup = true;
113a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
11431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
115a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Get the starting size of the instruction's template */
116a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  lir->flags.size = oatGetInsnSize(lir);
117e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
118a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Set up the mask for resources that are updated */
119a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (flags & (IS_LOAD | IS_STORE)) {
120a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    /* Default to heap - will catch specialized classes later */
121a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    setMemRefType(lir, flags & IS_LOAD, kHeapRef);
122a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
12331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
124a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /*
125a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Conservatively assume the branch here will call out a function that in
126a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * turn will trash everything.
127a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   */
128a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (flags & IS_BRANCH) {
129a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    lir->defMask = lir->useMask = ENCODE_ALL;
130a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    return;
131a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
13231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
133a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (flags & REG_DEF0) {
134b046e16d8b8da318d6055f9308950131f1255e08buzbee    setupRegMask(cUnit, &lir->defMask, lir->operands[0]);
135a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
13631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
137a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (flags & REG_DEF1) {
138b046e16d8b8da318d6055f9308950131f1255e08buzbee    setupRegMask(cUnit, &lir->defMask, lir->operands[1]);
139a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
14031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
14131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
142a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (flags & SETS_CCODES) {
143a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    lir->defMask |= ENCODE_CCODE;
144a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
14531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
146a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) {
147a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    int i;
14831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
149a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    for (i = 0; i < 4; i++) {
150a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      if (flags & (1 << (kRegUse0 + i))) {
151b046e16d8b8da318d6055f9308950131f1255e08buzbee        setupRegMask(cUnit, &lir->useMask, lir->operands[i]);
152a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
15331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
154a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
15531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
156a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (flags & USES_CCODES) {
157a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    lir->useMask |= ENCODE_CCODE;
158a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
15931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
160b046e16d8b8da318d6055f9308950131f1255e08buzbee  // Handle target-specific actions
161b046e16d8b8da318d6055f9308950131f1255e08buzbee  setupTargetResourceMasks(cUnit, lir);
16231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
16331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
16431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
1655de3494e4297c0d480409da3fecee39173f1d4e1buzbee * Debugging macros
1665de3494e4297c0d480409da3fecee39173f1d4e1buzbee */
1675de3494e4297c0d480409da3fecee39173f1d4e1buzbee#define DUMP_RESOURCE_MASK(X)
1685de3494e4297c0d480409da3fecee39173f1d4e1buzbee#define DUMP_SSA_REP(X)
1695de3494e4297c0d480409da3fecee39173f1d4e1buzbee
1705de3494e4297c0d480409da3fecee39173f1d4e1buzbee/* Pretty-print a LIR instruction */
171cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbeevoid oatDumpLIRInsn(CompilationUnit* cUnit, LIR* lir, unsigned char* baseAddr)
1725de3494e4297c0d480409da3fecee39173f1d4e1buzbee{
173a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int offset = lir->offset;
174a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int dest = lir->operands[0];
175a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  const bool dumpNop = (cUnit->enableDebug & (1 << kDebugShowNops));
176a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee
177a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Handle pseudo-ops individually, and all regular insns as a group */
178a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (lir->opcode) {
179a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoMethodEntry:
180a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "-------- method entry "
181a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
182a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
183a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoMethodExit:
184a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "-------- Method_Exit";
185a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
186a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoBarrier:
187a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "-------- BARRIER";
188a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
189a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoExtended:
190cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(INFO) << "-------- " << reinterpret_cast<char*>(dest);
191a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
192a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoSSARep:
193cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " <<  reinterpret_cast<char*>(dest));
194a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
195a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoEntryBlock:
196a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
197a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
198a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoDalvikByteCodeBoundary:
199a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "-------- dalvik offset: 0x" << std::hex
200cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee                << lir->dalvikOffset << " @ " << reinterpret_cast<char*>(lir->operands[0]);
201a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
202a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoExitBlock:
203a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
204a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
205a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoPseudoAlign4:
206cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(INFO) << reinterpret_cast<uintptr_t>(baseAddr) + offset << " (0x" << std::hex
207a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                << offset << "): .align4";
208a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
209a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoEHBlockLabel:
210a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "Exception_Handling:";
211a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
212a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoTargetLabel:
213a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoNormalBlockLabel:
214cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(INFO) << "L" << reinterpret_cast<void*>(lir) << ":";
215a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
216a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoThrowTarget:
217cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(INFO) << "LT" << reinterpret_cast<void*>(lir) << ":";
218a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
219a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoIntrinsicRetry:
220cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(INFO) << "IR" << reinterpret_cast<void*>(lir) << ":";
221a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
222a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoSuspendTarget:
223cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(INFO) << "LS" << reinterpret_cast<void*>(lir) << ":";
224a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
2258320f3867c02bae9bef6cdab267820cb7b412781buzbee    case kPseudoSafepointPC:
2268320f3867c02bae9bef6cdab267820cb7b412781buzbee      LOG(INFO) << "LsafepointPC_0x" << std::hex << lir->offset << "_" << lir->dalvikOffset << ":";
2278320f3867c02bae9bef6cdab267820cb7b412781buzbee      break;
228a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    case kPseudoExportedPC:
229a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee      LOG(INFO) << "LexportedPC_0x" << std::hex << lir->offset << "_" << lir->dalvikOffset << ":";
230a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee      break;
231a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kPseudoCaseLabel:
232cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(INFO) << "LC" << reinterpret_cast<void*>(lir) << ": Case target 0x"
233a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                << std::hex << lir->operands[0] << "|" << std::dec <<
234a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        lir->operands[0];
235a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
236a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
237a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      if (lir->flags.isNop && !dumpNop) {
238a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        break;
239a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      } else {
240a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        std::string op_name(buildInsnString(EncodingMap[lir->opcode].name,
241a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                                            lir, baseAddr));
242a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        std::string op_operands(buildInsnString(EncodingMap[lir->opcode].fmt
243a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                                              , lir, baseAddr));
244a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        LOG(INFO) << StringPrintf("%05x: %-9s%s%s",
245cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee                                  reinterpret_cast<unsigned int>(baseAddr + offset),
246a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                                  op_name.c_str(), op_operands.c_str(),
247a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                                  lir->flags.isNop ? "(nop)" : "");
248a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
249a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
250a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
251a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee
252a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (lir->useMask && (!lir->flags.isNop || dumpNop)) {
253a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->useMask, "use"));
254a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
255a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (lir->defMask && (!lir->flags.isNop || dumpNop)) {
256a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->defMask, "def"));
257a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
2585de3494e4297c0d480409da3fecee39173f1d4e1buzbee}
2595de3494e4297c0d480409da3fecee39173f1d4e1buzbee
2605de3494e4297c0d480409da3fecee39173f1d4e1buzbeevoid oatDumpPromotionMap(CompilationUnit *cUnit)
2615de3494e4297c0d480409da3fecee39173f1d4e1buzbee{
262a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int numRegs = cUnit->numDalvikRegisters + cUnit->numCompilerTemps + 1;
263a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  for (int i = 0; i < numRegs; i++) {
264a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    PromotionMap vRegMap = cUnit->promotionMap[i];
265a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    std::string buf;
266a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    if (vRegMap.fpLocation == kLocPhysReg) {
267f0504cdc5b6400edd4b39eea64ac280465042d5bbuzbee      StringAppendF(&buf, " : s%d", vRegMap.fpReg & fpRegMask());
268a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    }
2699c044ce5f76e9bfa17c4c1979e9f8c99ae100695buzbee
270a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    std::string buf3;
271a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    if (i < cUnit->numDalvikRegisters) {
272a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      StringAppendF(&buf3, "%02d", i);
273a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else if (i == cUnit->methodSReg) {
274a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      buf3 = "Method*";
275a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else {
276a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      StringAppendF(&buf3, "ct%d", i - cUnit->numDalvikRegisters);
2775de3494e4297c0d480409da3fecee39173f1d4e1buzbee    }
278a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee
279a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    LOG(INFO) << StringPrintf("V[%s] -> %s%d%s", buf3.c_str(),
280a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                              vRegMap.coreLocation == kLocPhysReg ?
281a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                              "r" : "SP+", vRegMap.coreLocation == kLocPhysReg ?
282a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                              vRegMap.coreReg : oatSRegOffset(cUnit, i),
283a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                              buf.c_str());
284a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
2855de3494e4297c0d480409da3fecee39173f1d4e1buzbee}
2865de3494e4297c0d480409da3fecee39173f1d4e1buzbee
287a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee/* Dump a mapping table */
288a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbeevoid dumpMappingTable(const char* table_name, const std::string& descriptor,
289a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee                      const std::string& name, const std::string& signature,
290a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee                      const std::vector<uint32_t>& v) {
291a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee  if (v.size() > 0) {
292a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    std::string line(StringPrintf("\n  %s %s%s_%s_table[%zu] = {", table_name,
293a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee                     descriptor.c_str(), name.c_str(), signature.c_str(), v.size()));
294a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    std::replace(line.begin(), line.end(), ';', '_');
295a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    LOG(INFO) << line;
296a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    for (uint32_t i = 0; i < v.size(); i+=2) {
297a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee      line = StringPrintf("    {0x%05x, 0x%04x},", v[i], v[i+1]);
298a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee      LOG(INFO) << line;
299a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    }
300a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    LOG(INFO) <<"  };\n\n";
301a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee  }
302a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee}
303a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee
3045de3494e4297c0d480409da3fecee39173f1d4e1buzbee/* Dump instructions and constant pool contents */
3055de3494e4297c0d480409da3fecee39173f1d4e1buzbeevoid oatCodegenDump(CompilationUnit* cUnit)
3065de3494e4297c0d480409da3fecee39173f1d4e1buzbee{
307a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LOG(INFO) << "Dumping LIR insns for "
308a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee            << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
309a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LIR* lirInsn;
310a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int insnsSize = cUnit->insnsSize;
311a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee
312a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LOG(INFO) << "Regs (excluding ins) : " << cUnit->numRegs;
313a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LOG(INFO) << "Ins          : " << cUnit->numIns;
314a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LOG(INFO) << "Outs         : " << cUnit->numOuts;
315a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LOG(INFO) << "CoreSpills       : " << cUnit->numCoreSpills;
316a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LOG(INFO) << "FPSpills       : " << cUnit->numFPSpills;
317a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LOG(INFO) << "CompilerTemps    : " << cUnit->numCompilerTemps;
318a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LOG(INFO) << "Frame size       : " << cUnit->frameSize;
319a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LOG(INFO) << "code size is " << cUnit->totalSize <<
320a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    " bytes, Dalvik size is " << insnsSize * 2;
321a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LOG(INFO) << "expansion factor: "
322cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee            << static_cast<float>(cUnit->totalSize) / static_cast<float>(insnsSize * 2);
323a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  oatDumpPromotionMap(cUnit);
324a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
325a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    oatDumpLIRInsn(cUnit, lirInsn, 0);
326a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
327a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
328cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee    LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)", lirInsn->offset, lirInsn->offset,
329cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee                              lirInsn->operands[0]);
330a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
331a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee
332a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  const DexFile::MethodId& method_id =
333a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      cUnit->dex_file->GetMethodId(cUnit->method_idx);
334a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  std::string signature(cUnit->dex_file->GetMethodSignature(method_id));
335a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  std::string name(cUnit->dex_file->GetMethodName(method_id));
336a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  std::string descriptor(cUnit->dex_file->GetMethodDeclaringClassDescriptor(method_id));
337a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee
338a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee  // Dump mapping tables
339a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee  dumpMappingTable("PC2Dex_MappingTable", descriptor, name, signature, cUnit->pc2dexMappingTable);
340a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee  dumpMappingTable("Dex2PC_MappingTable", descriptor, name, signature, cUnit->dex2pcMappingTable);
3415de3494e4297c0d480409da3fecee39173f1d4e1buzbee}
3425de3494e4297c0d480409da3fecee39173f1d4e1buzbee
343a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee
344a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbeeLIR* rawLIR(CompilationUnit* cUnit, int dalvikOffset, int opcode, int op0,
345a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      int op1, int op2, int op3, int op4, LIR* target)
346a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
347cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  LIR* insn = static_cast<LIR*>(oatNew(cUnit, sizeof(LIR), true, kAllocLIR));
348a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  insn->dalvikOffset = dalvikOffset;
349a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  insn->opcode = opcode;
350a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  insn->operands[0] = op0;
351a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  insn->operands[1] = op1;
352a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  insn->operands[2] = op2;
353a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  insn->operands[3] = op3;
354a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  insn->operands[4] = op4;
355a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  insn->target = target;
356b046e16d8b8da318d6055f9308950131f1255e08buzbee  oatSetupResourceMasks(cUnit, insn);
357a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee  if ((opcode == kPseudoTargetLabel) || (opcode == kPseudoSafepointPC) ||
358a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee      (opcode == kPseudoExportedPC)) {
359a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    // Always make labels scheduling barriers
3608320f3867c02bae9bef6cdab267820cb7b412781buzbee    insn->useMask = insn->defMask = ENCODE_ALL;
361a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
362a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return insn;
363a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee}
364a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee
365a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee/*
366a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee * The following are building blocks to construct low-level IRs with 0 - 4
367a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee * operands.
368a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee */
369a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbeeLIR* newLIR0(CompilationUnit* cUnit, int opcode)
370a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee{
371a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND))
372cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      << EncodingMap[opcode].name << " " << opcode << " "
373a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
374a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      << cUnit->currentDalvikOffset;
375a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode);
376cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  oatAppendLIR(cUnit, insn);
377a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return insn;
37831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
37931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
3805de3494e4297c0d480409da3fecee39173f1d4e1buzbeeLIR* newLIR1(CompilationUnit* cUnit, int opcode,
381a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee               int dest)
38231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
383a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_UNARY_OP))
384cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      << EncodingMap[opcode].name << " " << opcode << " "
385a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
386a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      << cUnit->currentDalvikOffset;
387a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest);
388cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  oatAppendLIR(cUnit, insn);
389a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return insn;
39031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
39131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
3925de3494e4297c0d480409da3fecee39173f1d4e1buzbeeLIR* newLIR2(CompilationUnit* cUnit, int opcode,
393a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee               int dest, int src1)
39431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
395a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_BINARY_OP))
396cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      << EncodingMap[opcode].name << " " << opcode << " "
397a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
398a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      << cUnit->currentDalvikOffset;
399a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1);
400cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  oatAppendLIR(cUnit, insn);
401a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return insn;
40231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
40331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
4045de3494e4297c0d480409da3fecee39173f1d4e1buzbeeLIR* newLIR3(CompilationUnit* cUnit, int opcode,
405a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee               int dest, int src1, int src2)
40631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
407a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_TERTIARY_OP))
408cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      << EncodingMap[opcode].name << " " << opcode << " "
409a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
410a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      << cUnit->currentDalvikOffset;
411cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1, src2);
412cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  oatAppendLIR(cUnit, insn);
413a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return insn;
41431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
41531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
4165de3494e4297c0d480409da3fecee39173f1d4e1buzbeeLIR* newLIR4(CompilationUnit* cUnit, int opcode,
417a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      int dest, int src1, int src2, int info)
41831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
419a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUAD_OP))
420cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      << EncodingMap[opcode].name << " " << opcode << " "
421a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
422a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      << cUnit->currentDalvikOffset;
423cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1, src2, info);
424cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  oatAppendLIR(cUnit, insn);
425a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return insn;
42631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
42731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
428b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian RogersLIR* newLIR5(CompilationUnit* cUnit, int opcode,
429a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee       int dest, int src1, int src2, int info1, int info2)
430b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers{
431a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUIN_OP))
432cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      << EncodingMap[opcode].name << " " << opcode << " "
433a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
434a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      << cUnit->currentDalvikOffset;
435cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1, src2, info1, info2);
436cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  oatAppendLIR(cUnit, insn);
437a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return insn;
438b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers}
439b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers
44031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
44131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Search the existing constants in the literal pool for an exact or close match
44231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * within specified delta (greater or equal to 0).
44331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
44431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeLIR* scanLiteralPool(LIR* dataTarget, int value, unsigned int delta)
44531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
446a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (dataTarget) {
447cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee    if ((static_cast<unsigned>(value - dataTarget->operands[0])) <= delta)
448cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      return dataTarget;
449a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    dataTarget = dataTarget->next;
450a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
451a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return NULL;
45231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
45331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
45431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* Search the existing constants in the literal pool for an exact wide match */
45531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeLIR* scanLiteralPoolWide(LIR* dataTarget, int valLo, int valHi)
45631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
457a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  bool loMatch = false;
458a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LIR* loTarget = NULL;
459a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (dataTarget) {
460cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee    if (loMatch && (dataTarget->operands[0] == valHi)) {
461cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      return loTarget;
46231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
463a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    loMatch = false;
464cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee    if (dataTarget->operands[0] == valLo) {
465a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      loMatch = true;
466a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      loTarget = dataTarget;
467a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    }
468a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    dataTarget = dataTarget->next;
469a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
470a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return NULL;
47131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
47231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
47331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
47431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * The following are building blocks to insert constants into the pool or
47531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * instruction streams.
47631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
47731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
4785de3494e4297c0d480409da3fecee39173f1d4e1buzbee/* Add a 32-bit constant either in the constant pool */
4793fa13791c51985d9956d01bc465de6d36c3390d3Ian RogersLIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP, int value)
48031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
481a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Add the constant to the literal pool */
482a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (constantListP) {
483cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee    LIR* newValue = static_cast<LIR*>(oatNew(cUnit, sizeof(LIR), true, kAllocData));
484a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    newValue->operands[0] = value;
485a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    newValue->next = *constantListP;
486cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee    *constantListP = newValue;
487a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    return newValue;
488a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
489a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return NULL;
49031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
49131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
49231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* Add a 64-bit constant to the constant pool or mixed with code */
49331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeLIR* addWideData(CompilationUnit* cUnit, LIR* *constantListP,
494a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee               int valLo, int valHi)
49531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
496a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  addWordData(cUnit, constantListP, valHi);
497a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return addWordData(cUnit, constantListP, valLo);
49831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
49931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
500ab058bb04d11ed086116d95f2d55bf6b35e8cc35Ian Rogersvoid pushWord(std::vector<uint8_t>&buf, int data) {
501a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  buf.push_back( data & 0xff);
502a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  buf.push_back( (data >> 8) & 0xff);
503a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  buf.push_back( (data >> 16) & 0xff);
504a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  buf.push_back( (data >> 24) & 0xff);
505e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
506e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
507ab058bb04d11ed086116d95f2d55bf6b35e8cc35Ian Rogersvoid alignBuffer(std::vector<uint8_t>&buf, size_t offset) {
508a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (buf.size() < offset) {
509a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    buf.push_back(0);
510a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
511e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
512e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
513f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrombool IsDirect(int invokeType) {
514f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom  InvokeType type = static_cast<InvokeType>(invokeType);
515f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom  return type == kStatic || type == kDirect;
516f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom}
517f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom
518e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Write the literal pool to the output stream */
51931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid installLiteralPools(CompilationUnit* cUnit)
520e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
521a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  alignBuffer(cUnit->codeBuffer, cUnit->dataOffset);
522a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LIR* dataLIR = cUnit->literalList;
523a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (dataLIR != NULL) {
524a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    pushWord(cUnit->codeBuffer, dataLIR->operands[0]);
525a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    dataLIR = NEXT_LIR(dataLIR);
526a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
527a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  // Push code and method literals, record offsets for the compiler to patch.
528a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  dataLIR = cUnit->codeLiteralList;
529137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers  while (dataLIR != NULL) {
530137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    uint32_t target = dataLIR->operands[0];
531137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    cUnit->compiler->AddCodePatch(cUnit->dex_file,
532137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers                                  cUnit->method_idx,
533137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers                                  cUnit->invoke_type,
534137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers                                  target,
535137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers                                  static_cast<InvokeType>(dataLIR->operands[1]),
536137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers                                  cUnit->codeBuffer.size());
537137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target);
538137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    // unique based on target to ensure code deduplication works
539137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
540137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    pushWord(cUnit->codeBuffer, unique_patch_value);
541137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    dataLIR = NEXT_LIR(dataLIR);
542137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers  }
543137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers  dataLIR = cUnit->methodLiteralList;
544137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers  while (dataLIR != NULL) {
545137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    uint32_t target = dataLIR->operands[0];
546137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    cUnit->compiler->AddMethodPatch(cUnit->dex_file,
547a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                                    cUnit->method_idx,
54808f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers                                    cUnit->invoke_type,
549a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                                    target,
55008f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers                                    static_cast<InvokeType>(dataLIR->operands[1]),
551a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                                    cUnit->codeBuffer.size());
552137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target);
553137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    // unique based on target to ensure code deduplication works
554137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
555137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    pushWord(cUnit->codeBuffer, unique_patch_value);
556137e88f798857321f4007631fdf052d2830ec2c4Ian Rogers    dataLIR = NEXT_LIR(dataLIR);
557a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
558e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
559e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
560e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Write the switch tables to the output stream */
56131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid installSwitchTables(CompilationUnit* cUnit)
562e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
563a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  GrowableListIterator iterator;
564a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
565a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (true) {
566cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee    SwitchTable* tabRec = reinterpret_cast<SwitchTable*>(oatGrowableListIteratorNext( &iterator));
567a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    if (tabRec == NULL) break;
568a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    alignBuffer(cUnit->codeBuffer, tabRec->offset);
569a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    /*
570a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee     * For Arm, our reference point is the address of the bx
571a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee     * instruction that does the launch, so we have to subtract
572a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee     * the auto pc-advance.  For other targets the reference point
573a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee     * is a label, so we can use the offset as-is.
574a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee     */
575b046e16d8b8da318d6055f9308950131f1255e08buzbee    int bxOffset = INVALID_OFFSET;
576b046e16d8b8da318d6055f9308950131f1255e08buzbee    switch (cUnit->instructionSet) {
577b046e16d8b8da318d6055f9308950131f1255e08buzbee      case kThumb2:
578b046e16d8b8da318d6055f9308950131f1255e08buzbee        bxOffset = tabRec->anchor->offset + 4;
579b046e16d8b8da318d6055f9308950131f1255e08buzbee        break;
580b046e16d8b8da318d6055f9308950131f1255e08buzbee      case kX86:
581b046e16d8b8da318d6055f9308950131f1255e08buzbee        bxOffset = 0;
582b046e16d8b8da318d6055f9308950131f1255e08buzbee        break;
583b046e16d8b8da318d6055f9308950131f1255e08buzbee      case kMips:
584b046e16d8b8da318d6055f9308950131f1255e08buzbee        bxOffset = tabRec->anchor->offset;
585b046e16d8b8da318d6055f9308950131f1255e08buzbee        break;
586b046e16d8b8da318d6055f9308950131f1255e08buzbee      default: LOG(FATAL) << "Unexpected instruction set: " << cUnit->instructionSet;
587b046e16d8b8da318d6055f9308950131f1255e08buzbee    }
588a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    if (cUnit->printMe) {
589a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(INFO) << "Switch table for offset 0x" << std::hex << bxOffset;
590a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    }
591a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
592cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      const int* keys = reinterpret_cast<const int*>(&(tabRec->table[2]));
593a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      for (int elems = 0; elems < tabRec->table[1]; elems++) {
594a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        int disp = tabRec->targets[elems]->offset - bxOffset;
595e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        if (cUnit->printMe) {
596a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee          LOG(INFO) << "  Case[" << elems << "] key: 0x"
597a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                    << std::hex << keys[elems] << ", disp: 0x"
598a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                    << std::hex << disp;
599e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        }
600a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        pushWord(cUnit->codeBuffer, keys[elems]);
601a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        pushWord(cUnit->codeBuffer,
602a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee          tabRec->targets[elems]->offset - bxOffset);
603a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
604a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else {
605a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(static_cast<int>(tabRec->table[0]),
606a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                static_cast<int>(Instruction::kPackedSwitchSignature));
607a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      for (int elems = 0; elems < tabRec->table[1]; elems++) {
608a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        int disp = tabRec->targets[elems]->offset - bxOffset;
609a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        if (cUnit->printMe) {
610a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee          LOG(INFO) << "  Case[" << elems << "] disp: 0x"
611a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                    << std::hex << disp;
612e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        }
613a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        pushWord(cUnit->codeBuffer, tabRec->targets[elems]->offset - bxOffset);
614a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
615e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
616a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
617e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
618e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
619e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Write the fill array dta to the output stream */
62031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid installFillArrayData(CompilationUnit* cUnit)
621e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
622a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  GrowableListIterator iterator;
623a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
624a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (true) {
625cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee    FillArrayData *tabRec =
626cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee        reinterpret_cast<FillArrayData*>(oatGrowableListIteratorNext( &iterator));
627a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    if (tabRec == NULL) break;
628a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    alignBuffer(cUnit->codeBuffer, tabRec->offset);
629a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    for (int i = 0; i < (tabRec->size + 1) / 2; i++) {
630a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      cUnit->codeBuffer.push_back( tabRec->table[i] & 0xFF);
631a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      cUnit->codeBuffer.push_back( (tabRec->table[i] >> 8) & 0xFF);
632e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
633a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
634e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
635e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
63631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeint assignLiteralOffsetCommon(LIR* lir, int offset)
637e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
638a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  for (;lir != NULL; lir = lir->next) {
639a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    lir->offset = offset;
640a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    offset += 4;
641a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
642a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return offset;
643e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
644e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
6456459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee// Make sure we have a code address for every declared catch entry
6466459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbeebool verifyCatchEntries(CompilationUnit* cUnit)
6476459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee{
6486459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  bool success = true;
6496459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  for (std::set<uint32_t>::const_iterator it = cUnit->catches.begin(); it != cUnit->catches.end(); ++it) {
6506459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    uint32_t dexPc = *it;
6516459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    bool found = false;
6526459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    for (size_t i = 0; i < cUnit->dex2pcMappingTable.size(); i += 2) {
6536459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee      if (dexPc == cUnit->dex2pcMappingTable[i+1]) {
6546459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee        found = true;
6556459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee        break;
6566459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee      }
6576459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    }
6586459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    if (!found) {
6596459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee      LOG(INFO) << "Missing native PC for catch entry @ 0x" << std::hex << dexPc;
6606459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee      success = false;
6616459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    }
6626459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  }
6636459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  // Now, try in the other direction
6646459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  for (size_t i = 0; i < cUnit->dex2pcMappingTable.size(); i += 2) {
6656459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    uint32_t dexPc = cUnit->dex2pcMappingTable[i+1];
6666459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    if (cUnit->catches.find(dexPc) == cUnit->catches.end()) {
6676459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee      LOG(INFO) << "Unexpected catch entry @ dex pc 0x" << std::hex << dexPc;
6686459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee      success = false;
6696459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    }
6706459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  }
6716459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  if (!success) {
6726459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    LOG(INFO) << "Bad dex2pcMapping table in " << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
6736459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee    LOG(INFO) << "Entries @ decode: " << cUnit->catches.size() << ", Entries in table: "
6746459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee              << cUnit->dex2pcMappingTable.size()/2;
6756459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  }
6766459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  return success;
6776459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee}
6786459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee
679a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbeevoid createMappingTables(CompilationUnit* cUnit)
680e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
681cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  for (LIR* tgtLIR = cUnit->firstLIRInsn; tgtLIR != NULL; tgtLIR = NEXT_LIR(tgtLIR)) {
6828320f3867c02bae9bef6cdab267820cb7b412781buzbee    if (!tgtLIR->flags.isNop && (tgtLIR->opcode == kPseudoSafepointPC)) {
683a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee      cUnit->pc2dexMappingTable.push_back(tgtLIR->offset);
684a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee      cUnit->pc2dexMappingTable.push_back(tgtLIR->dalvikOffset);
685a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    }
686a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    if (!tgtLIR->flags.isNop && (tgtLIR->opcode == kPseudoExportedPC)) {
687a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee      cUnit->dex2pcMappingTable.push_back(tgtLIR->offset);
688a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee      cUnit->dex2pcMappingTable.push_back(tgtLIR->dalvikOffset);
689e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
690a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
6916459e7cb35ca83ffc2f266dddeb83673bc07ecd4buzbee  DCHECK(verifyCatchEntries(cUnit));
692a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee  cUnit->combinedMappingTable.push_back(cUnit->pc2dexMappingTable.size() +
693a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee                                        cUnit->dex2pcMappingTable.size());
694a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee  cUnit->combinedMappingTable.push_back(cUnit->pc2dexMappingTable.size());
695a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee  cUnit->combinedMappingTable.insert(cUnit->combinedMappingTable.end(),
696a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee                                     cUnit->pc2dexMappingTable.begin(),
697a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee                                     cUnit->pc2dexMappingTable.end());
698a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee  cUnit->combinedMappingTable.insert(cUnit->combinedMappingTable.end(),
699a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee                                     cUnit->dex2pcMappingTable.begin(),
700a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee                                     cUnit->dex2pcMappingTable.end());
701e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
702e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
7030c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogersclass NativePcToReferenceMapBuilder {
7040c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers public:
7050c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  NativePcToReferenceMapBuilder(std::vector<uint8_t>* table,
7060c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers                                size_t entries, uint32_t max_native_offset,
7070c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers                                size_t references_width) : entries_(entries),
7080c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers                                references_width_(references_width), in_use_(entries),
7090c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers                                table_(table) {
7100c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    // Compute width in bytes needed to hold max_native_offset.
7110c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    native_offset_width_ = 0;
7120c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    while (max_native_offset != 0) {
7130c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers      native_offset_width_++;
7140c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers      max_native_offset >>= 8;
7150c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    }
7160c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    // Resize table and set up header.
7170c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    table->resize((EntryWidth() * entries) + sizeof(uint32_t));
718000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers    CHECK_LT(native_offset_width_, 1U << 3);
719000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers    (*table)[0] = native_offset_width_ & 7;
720000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers    CHECK_LT(references_width_, 1U << 13);
721000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers    (*table)[0] |= (references_width_ << 3) & 0xFF;
722000d724207b4ff32fcbc9744da76d2f594675eedIan Rogers    (*table)[1] = (references_width_ >> 5) & 0xFF;
7230c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    CHECK_LT(entries, 1U << 16);
7240c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    (*table)[2] = entries & 0xFF;
7250c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    (*table)[3] = (entries >> 8) & 0xFF;
7260c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
7270c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
7280c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  void AddEntry(uint32_t native_offset, const uint8_t* references) {
7290c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    size_t table_index = TableIndex(native_offset);
7300c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    while (in_use_[table_index]) {
7310c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers      table_index = (table_index + 1) % entries_;
7320c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    }
7330c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    in_use_[table_index] = true;
7340c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    SetNativeOffset(table_index, native_offset);
7350c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    DCHECK_EQ(native_offset, GetNativeOffset(table_index));
7360c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    SetReferences(table_index, references);
7370c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
7380c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
7390c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers private:
7400c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  size_t TableIndex(uint32_t native_offset) {
7410c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    return NativePcOffsetToReferenceMap::Hash(native_offset) % entries_;
7420c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
7430c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
7440c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  uint32_t GetNativeOffset(size_t table_index) {
7450c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    uint32_t native_offset = 0;
7460c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
7470c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    for (size_t i = 0; i < native_offset_width_; i++) {
7480c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers      native_offset |= (*table_)[table_offset + i] << (i * 8);
7490c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    }
7500c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    return native_offset;
7510c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
7520c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
7530c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  void SetNativeOffset(size_t table_index, uint32_t native_offset) {
7540c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
7550c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    for (size_t i = 0; i < native_offset_width_; i++) {
7560c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers      (*table_)[table_offset + i] = (native_offset >> (i * 8)) & 0xFF;
7570c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    }
7580c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
7590c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
7600c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  void SetReferences(size_t table_index, const uint8_t* references) {
7610c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
7620c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    memcpy(&(*table_)[table_offset + native_offset_width_], references, references_width_);
7630c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
7640c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
7650c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  size_t EntryWidth() const {
7660c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    return native_offset_width_ + references_width_;
7670c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
7680c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
7690c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // Number of entries in the table.
7700c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  const size_t entries_;
7710c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // Number of bytes used to encode the reference bitmap.
7720c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  const size_t references_width_;
7730c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // Number of bytes used to encode a native offset.
7740c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  size_t native_offset_width_;
7750c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // Entries that are in use.
7760c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  std::vector<bool> in_use_;
7770c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // The table we're building.
7780c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  std::vector<uint8_t>* const table_;
7790c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers};
7800c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
7810c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogersstatic void createNativeGcMap(CompilationUnit* cUnit) {
782a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee  const std::vector<uint32_t>& mapping_table = cUnit->pc2dexMappingTable;
7830c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  uint32_t max_native_offset = 0;
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    if (native_offset > max_native_offset) {
7870c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers      max_native_offset = native_offset;
7880c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    }
7890c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
7900c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  Compiler::MethodReference method_ref(cUnit->dex_file, cUnit->method_idx);
7910c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  const std::vector<uint8_t>* gc_map_raw = verifier::MethodVerifier::GetDexGcMap(method_ref);
7920c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  verifier::DexPcToReferenceMap dex_gc_map(&(*gc_map_raw)[4], gc_map_raw->size() - 4);
7930c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // Compute native offset to references size.
7940c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  NativePcToReferenceMapBuilder native_gc_map_builder(&cUnit->nativeGcMap,
7950c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers                                                      mapping_table.size() / 2, max_native_offset,
7960c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers                                                      dex_gc_map.RegWidth());
7970c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
7980c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  for (size_t i = 0; i < mapping_table.size(); i += 2) {
7990c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    uint32_t native_offset = mapping_table[i + 0];
8000c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    uint32_t dex_pc = mapping_table[i + 1];
8010c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    const uint8_t* references = dex_gc_map.FindBitMap(dex_pc, false);
802a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    CHECK(references != NULL) << "Missing ref for dex pc 0x" << std::hex << dex_pc;
803a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee    native_gc_map_builder.AddEntry(native_offset, references);
8040c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  }
8050c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers}
8060c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
807e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Determine the offset of each literal field */
80831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeint assignLiteralOffset(CompilationUnit* cUnit, int offset)
809e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
810a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  offset = assignLiteralOffsetCommon(cUnit->literalList, offset);
811a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  offset = assignLiteralOffsetCommon(cUnit->codeLiteralList, offset);
812a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  offset = assignLiteralOffsetCommon(cUnit->methodLiteralList, offset);
813a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return offset;
814e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
815e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
81631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeint assignSwitchTablesOffset(CompilationUnit* cUnit, int offset)
817e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
818a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  GrowableListIterator iterator;
819a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
820a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (true) {
821cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee    SwitchTable *tabRec = reinterpret_cast<SwitchTable*>(oatGrowableListIteratorNext(&iterator));
822a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    if (tabRec == NULL) break;
823a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    tabRec->offset = offset;
824a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
825a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      offset += tabRec->table[1] * (sizeof(int) * 2);
826a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else {
827a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(static_cast<int>(tabRec->table[0]),
828a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                static_cast<int>(Instruction::kPackedSwitchSignature));
829a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      offset += tabRec->table[1] * sizeof(int);
830e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
831a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
832a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return offset;
833e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
834e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
83531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeint assignFillArrayDataOffset(CompilationUnit* cUnit, int offset)
836e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
837a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  GrowableListIterator iterator;
838a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
839a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (true) {
840cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee    FillArrayData *tabRec =
841cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee        reinterpret_cast<FillArrayData*>(oatGrowableListIteratorNext(&iterator));
842a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    if (tabRec == NULL) break;
843a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    tabRec->offset = offset;
844a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    offset += tabRec->size;
845a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    // word align
846a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    offset = (offset + 3) & ~3;
847a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    }
848a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return offset;
849e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
850e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
851e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/*
852e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Walk the compilation unit and assign offsets to instructions
853e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * and literals and compute the total size of the compiled unit.
854e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee */
855e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbeevoid oatAssignOffsets(CompilationUnit* cUnit)
856e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
857a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int offset = oatAssignInsnOffsets(cUnit);
858e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
859a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Const values have to be word aligned */
860a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  offset = (offset + 3) & ~3;
861e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
862a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Set up offsets for literals */
863a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  cUnit->dataOffset = offset;
864e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
865a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  offset = assignLiteralOffset(cUnit, offset);
866e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
867a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  offset = assignSwitchTablesOffset(cUnit, offset);
868e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
869a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  offset = assignFillArrayDataOffset(cUnit, offset);
870e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
871a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  cUnit->totalSize = offset;
872e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
873e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
874e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/*
875e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Go over each instruction in the list and calculate the offset from the top
876e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * before sending them off to the assembler. If out-of-range branch distance is
877e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * seen rearrange the instructions a bit to correct it.
878e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee */
879e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbeevoid oatAssembleLIR(CompilationUnit* cUnit)
880e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
881a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  oatAssignOffsets(cUnit);
882a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /*
883a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Assemble here.  Note that we generate code with optimistic assumptions
884a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * and if found now to work, we'll have to redo the sequence and retry.
885a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   */
886e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
887a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (true) {
888a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    AssemblerStatus res = oatAssembleInstructions(cUnit, 0);
889a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    if (res == kSuccess) {
890a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
891a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else {
892a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      cUnit->assemblerRetries++;
893a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      if (cUnit->assemblerRetries > MAX_ASSEMBLER_RETRIES) {
894a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        oatCodegenDump(cUnit);
895a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        LOG(FATAL) << "Assembler error - too many retries";
896a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
897a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      // Redo offsets and try again
898a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      oatAssignOffsets(cUnit);
899a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      cUnit->codeBuffer.clear();
900e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
901a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
902e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
903a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  // Install literals
904a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  installLiteralPools(cUnit);
905e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
906a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  // Install switch tables
907a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  installSwitchTables(cUnit);
908e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
909a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  // Install fill array data
910a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  installFillArrayData(cUnit);
911e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
9120c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  // Create the mapping table and native offset to reference map.
913a5b3024aed77a8204d5fb48ba7f763fb8c60fa76Bill Buzbee  createMappingTables(cUnit);
9140c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers
9150c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers  createNativeGcMap(cUnit);
916e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
917e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
91831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
91931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Insert a kPseudoCaseLabel at the beginning of the Dalvik
92031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * offset vaddr.  This label will be used to fix up the case
92131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * branch table during the assembly phase.  Be sure to set
92231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * all resource flags on this to prevent code motion across
92331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * target boundaries.  KeyVal is just there for debugging.
92431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
92531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeLIR* insertCaseLabel(CompilationUnit* cUnit, int vaddr, int keyVal)
92631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
927a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  SafeMap<unsigned int, LIR*>::iterator it;
928a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  it = cUnit->boundaryMap.find(vaddr);
929a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (it == cUnit->boundaryMap.end()) {
930a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr;
931a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
932cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  LIR* newLabel = static_cast<LIR*>(oatNew(cUnit, sizeof(LIR), true, kAllocLIR));
933a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  newLabel->dalvikOffset = vaddr;
934a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  newLabel->opcode = kPseudoCaseLabel;
935a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  newLabel->operands[0] = keyVal;
936cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  oatInsertLIRAfter(it->second, newLabel);
937a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return newLabel;
93831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
93931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
94031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid markPackedCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
94131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
942eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee  const uint16_t* table = tabRec->table;
943a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int baseVaddr = tabRec->vaddr;
944cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  const int *targets = reinterpret_cast<const int*>(&table[4]);
945a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int entries = table[1];
946a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int lowKey = s4FromSwitchData(&table[2]);
947a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  for (int i = 0; i < entries; i++) {
948cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee    tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i], i + lowKey);
949a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
95031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
95131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
95231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid markSparseCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
95331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
954eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee  const uint16_t* table = tabRec->table;
955a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int baseVaddr = tabRec->vaddr;
956a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int entries = table[1];
957cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  const int* keys = reinterpret_cast<const int*>(&table[2]);
958cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  const int* targets = &keys[entries];
959a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  for (int i = 0; i < entries; i++) {
960cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee    tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i], keys[i]);
961a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
96231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
96331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
96431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid oatProcessSwitchTables(CompilationUnit* cUnit)
96531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
966a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  GrowableListIterator iterator;
967a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
968a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  while (true) {
969a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    SwitchTable *tabRec =
970cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee        reinterpret_cast<SwitchTable*>(oatGrowableListIteratorNext(&iterator));
971a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    if (tabRec == NULL) break;
972a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    if (tabRec->table[0] == Instruction::kPackedSwitchSignature) {
973a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      markPackedCaseLabels(cUnit, tabRec);
974a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
975a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      markSparseCaseLabels(cUnit, tabRec);
976a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else {
977a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LOG(FATAL) << "Invalid switch table";
97831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
979a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
98031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
98131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
982eaf09bc65f9a10d12befcdb239156938c9bceef2buzbeevoid dumpSparseSwitchTable(const uint16_t* table)
983a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /*
984a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Sparse switch data format:
985a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  ushort ident = 0x0200   magic value
986a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  ushort size       number of entries in the table; > 0
987a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  int keys[size]      keys, sorted low-to-high; 32-bit aligned
988a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  int targets[size]     branch targets, relative to switch opcode
989a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *
990a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Total size is (2+size*4) 16-bit code units.
991a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   */
992a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
993eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee  uint16_t ident = table[0];
994a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int entries = table[1];
995cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  const int* keys = reinterpret_cast<const int*>(&table[2]);
996cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  const int* targets = &keys[entries];
997a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LOG(INFO) <<  "Sparse switch table - ident:0x" << std::hex << ident
998a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee            << ", entries: " << std::dec << entries;
999a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  for (int i = 0; i < entries; i++) {
1000a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    LOG(INFO) << "  Key[" << keys[i] << "] -> 0x" << std::hex << targets[i];
1001a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
100231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
100331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
1004eaf09bc65f9a10d12befcdb239156938c9bceef2buzbeevoid dumpPackedSwitchTable(const uint16_t* table)
1005a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /*
1006a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Packed switch data format:
1007a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  ushort ident = 0x0100   magic value
1008a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  ushort size       number of entries in the table
1009a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  int first_key       first (and lowest) switch case value
1010a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *  int targets[size]     branch targets, relative to switch opcode
1011a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   *
1012a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   * Total size is (4+size*2) 16-bit code units.
1013a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee   */
1014a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
1015eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee  uint16_t ident = table[0];
1016cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  const int* targets = reinterpret_cast<const int*>(&table[4]);
1017a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int entries = table[1];
1018a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int lowKey = s4FromSwitchData(&table[2]);
1019a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident
1020a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee            << ", entries: " << std::dec << entries << ", lowKey: " << lowKey;
1021a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  for (int i = 0; i < entries; i++) {
1022a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    LOG(INFO) << "  Key[" << (i + lowKey) << "] -> 0x" << std::hex
1023a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee              << targets[i];
1024a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
102531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
1026e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
1027d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee/*
1028d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee * Set up special LIR to mark a Dalvik byte-code instruction start and
1029d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee * record it in the boundaryMap.  NOTE: in cases such as kMirOpCheck in
1030d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee * which we split a single Dalvik instruction, only the first MIR op
1031d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee * associated with a Dalvik PC should be entered into the map.
1032d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee */
1033d1643e41ef242ae656f667bf3c8b0324635cefd3buzbeeLIR* markBoundary(CompilationUnit* cUnit, int offset, const char* instStr)
1034d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee{
1035cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  LIR* res = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary, reinterpret_cast<uintptr_t>(instStr));
1036d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee  if (cUnit->boundaryMap.find(offset) == cUnit->boundaryMap.end()) {
1037d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee    cUnit->boundaryMap.Put(offset, res);
1038d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee  }
1039d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee  return res;
1040d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee}
1041e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
1042d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee}
1043d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee // namespace art
1044