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