mir_to_lir-inl.h revision c32447bcc8c36ee8ff265ed678c7df86936a9ebe
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef ART_COMPILER_DEX_QUICK_MIR_TO_LIR_INL_H_ 18#define ART_COMPILER_DEX_QUICK_MIR_TO_LIR_INL_H_ 19 20#include "mir_to_lir.h" 21 22#include "dex/compiler_internals.h" 23 24namespace art { 25 26/* Mark a temp register as dead. Does not affect allocation state. */ 27inline void Mir2Lir::ClobberBody(RegisterInfo* p) { 28 DCHECK(p->IsTemp()); 29 if (p->SReg() != INVALID_SREG) { 30 DCHECK(!(p->IsLive() && p->IsDirty())) << "Live & dirty temp in clobber"; 31 p->MarkDead(); 32 if (p->IsWide()) { 33 p->SetIsWide(false); 34 if (p->GetReg().NotExactlyEquals(p->Partner())) { 35 // Register pair - deal with the other half. 36 p = GetRegInfo(p->Partner()); 37 p->SetIsWide(false); 38 p->MarkDead(); 39 } 40 } 41 } 42} 43 44inline LIR* Mir2Lir::RawLIR(DexOffset dalvik_offset, int opcode, int op0, 45 int op1, int op2, int op3, int op4, LIR* target) { 46 LIR* insn = static_cast<LIR*>(arena_->Alloc(sizeof(LIR), kArenaAllocLIR)); 47 insn->dalvik_offset = dalvik_offset; 48 insn->opcode = opcode; 49 insn->operands[0] = op0; 50 insn->operands[1] = op1; 51 insn->operands[2] = op2; 52 insn->operands[3] = op3; 53 insn->operands[4] = op4; 54 insn->target = target; 55 SetupResourceMasks(insn); 56 if ((opcode == kPseudoTargetLabel) || (opcode == kPseudoSafepointPC) || 57 (opcode == kPseudoExportedPC)) { 58 // Always make labels scheduling barriers 59 DCHECK(!insn->flags.use_def_invalid); 60 insn->u.m.use_mask = insn->u.m.def_mask = &kEncodeAll; 61 } 62 return insn; 63} 64 65/* 66 * The following are building blocks to construct low-level IRs with 0 - 4 67 * operands. 68 */ 69inline LIR* Mir2Lir::NewLIR0(int opcode) { 70 DCHECK(IsPseudoLirOp(opcode) || (GetTargetInstFlags(opcode) & NO_OPERAND)) 71 << GetTargetInstName(opcode) << " " << opcode << " " 72 << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " " 73 << current_dalvik_offset_; 74 LIR* insn = RawLIR(current_dalvik_offset_, opcode); 75 AppendLIR(insn); 76 return insn; 77} 78 79inline LIR* Mir2Lir::NewLIR1(int opcode, int dest) { 80 DCHECK(IsPseudoLirOp(opcode) || (GetTargetInstFlags(opcode) & IS_UNARY_OP)) 81 << GetTargetInstName(opcode) << " " << opcode << " " 82 << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " " 83 << current_dalvik_offset_; 84 LIR* insn = RawLIR(current_dalvik_offset_, opcode, dest); 85 AppendLIR(insn); 86 return insn; 87} 88 89inline LIR* Mir2Lir::NewLIR2(int opcode, int dest, int src1) { 90 DCHECK(IsPseudoLirOp(opcode) || (GetTargetInstFlags(opcode) & IS_BINARY_OP)) 91 << GetTargetInstName(opcode) << " " << opcode << " " 92 << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " " 93 << current_dalvik_offset_; 94 LIR* insn = RawLIR(current_dalvik_offset_, opcode, dest, src1); 95 AppendLIR(insn); 96 return insn; 97} 98 99inline LIR* Mir2Lir::NewLIR2NoDest(int opcode, int src, int info) { 100 DCHECK(IsPseudoLirOp(opcode) || (GetTargetInstFlags(opcode) & IS_UNARY_OP)) 101 << GetTargetInstName(opcode) << " " << opcode << " " 102 << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " " 103 << current_dalvik_offset_; 104 LIR* insn = RawLIR(current_dalvik_offset_, opcode, src, info); 105 AppendLIR(insn); 106 return insn; 107} 108 109inline LIR* Mir2Lir::NewLIR3(int opcode, int dest, int src1, int src2) { 110 DCHECK(IsPseudoLirOp(opcode) || (GetTargetInstFlags(opcode) & IS_TERTIARY_OP)) 111 << GetTargetInstName(opcode) << " " << opcode << " " 112 << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " " 113 << current_dalvik_offset_; 114 LIR* insn = RawLIR(current_dalvik_offset_, opcode, dest, src1, src2); 115 AppendLIR(insn); 116 return insn; 117} 118 119inline LIR* Mir2Lir::NewLIR4(int opcode, int dest, int src1, int src2, int info) { 120 DCHECK(IsPseudoLirOp(opcode) || (GetTargetInstFlags(opcode) & IS_QUAD_OP)) 121 << GetTargetInstName(opcode) << " " << opcode << " " 122 << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " " 123 << current_dalvik_offset_; 124 LIR* insn = RawLIR(current_dalvik_offset_, opcode, dest, src1, src2, info); 125 AppendLIR(insn); 126 return insn; 127} 128 129inline LIR* Mir2Lir::NewLIR5(int opcode, int dest, int src1, int src2, int info1, 130 int info2) { 131 DCHECK(IsPseudoLirOp(opcode) || (GetTargetInstFlags(opcode) & IS_QUIN_OP)) 132 << GetTargetInstName(opcode) << " " << opcode << " " 133 << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " " 134 << current_dalvik_offset_; 135 LIR* insn = RawLIR(current_dalvik_offset_, opcode, dest, src1, src2, info1, info2); 136 AppendLIR(insn); 137 return insn; 138} 139 140/* 141 * Mark the corresponding bit(s). 142 */ 143inline void Mir2Lir::SetupRegMask(ResourceMask* mask, int reg) { 144 DCHECK_EQ((reg & ~RegStorage::kRegValMask), 0); 145 DCHECK(reginfo_map_.Get(reg) != nullptr) << "No info for 0x" << reg; 146 *mask = mask->Union(reginfo_map_.Get(reg)->DefUseMask()); 147} 148 149/* 150 * Set up the proper fields in the resource mask 151 */ 152inline void Mir2Lir::SetupResourceMasks(LIR* lir) { 153 int opcode = lir->opcode; 154 155 if (IsPseudoLirOp(opcode)) { 156 lir->u.m.use_mask = lir->u.m.def_mask = &kEncodeNone; 157 if (opcode != kPseudoBarrier) { 158 lir->flags.fixup = kFixupLabel; 159 } 160 return; 161 } 162 163 uint64_t flags = GetTargetInstFlags(opcode); 164 165 if (flags & NEEDS_FIXUP) { 166 // Note: target-specific setup may specialize the fixup kind. 167 lir->flags.fixup = kFixupLabel; 168 } 169 170 /* Get the starting size of the instruction's template. */ 171 lir->flags.size = GetInsnSize(lir); 172 estimated_native_code_size_ += lir->flags.size; 173 174 /* Set up the mask for resources. */ 175 ResourceMask use_mask; 176 ResourceMask def_mask; 177 178 if (flags & (IS_LOAD | IS_STORE)) { 179 /* Set memory reference type (defaults to heap, overridden by ScopedMemRefType). */ 180 if (flags & IS_LOAD) { 181 use_mask.SetBit(mem_ref_type_); 182 } else { 183 /* Currently only loads can be marked as kMustNotAlias. */ 184 DCHECK(mem_ref_type_ != ResourceMask::kMustNotAlias); 185 } 186 if (flags & IS_STORE) { 187 /* Literals cannot be written to. */ 188 DCHECK(mem_ref_type_ != ResourceMask::kLiteral); 189 def_mask.SetBit(mem_ref_type_); 190 } 191 } 192 193 /* 194 * Conservatively assume the branch here will call out a function that in 195 * turn will trash everything. 196 */ 197 if (flags & IS_BRANCH) { 198 lir->u.m.def_mask = lir->u.m.use_mask = &kEncodeAll; 199 return; 200 } 201 202 if (flags & REG_DEF0) { 203 SetupRegMask(&def_mask, lir->operands[0]); 204 } 205 206 if (flags & REG_DEF1) { 207 SetupRegMask(&def_mask, lir->operands[1]); 208 } 209 210 if (flags & REG_DEF2) { 211 SetupRegMask(&def_mask, lir->operands[2]); 212 } 213 214 if (flags & REG_USE0) { 215 SetupRegMask(&use_mask, lir->operands[0]); 216 } 217 218 if (flags & REG_USE1) { 219 SetupRegMask(&use_mask, lir->operands[1]); 220 } 221 222 if (flags & REG_USE2) { 223 SetupRegMask(&use_mask, lir->operands[2]); 224 } 225 226 if (flags & REG_USE3) { 227 SetupRegMask(&use_mask, lir->operands[3]); 228 } 229 230 if (flags & REG_USE4) { 231 SetupRegMask(&use_mask, lir->operands[4]); 232 } 233 234 if (flags & SETS_CCODES) { 235 def_mask.SetBit(ResourceMask::kCCode); 236 } 237 238 if (flags & USES_CCODES) { 239 use_mask.SetBit(ResourceMask::kCCode); 240 } 241 242 // Handle target-specific actions 243 SetupTargetResourceMasks(lir, flags, &def_mask, &use_mask); 244 245 lir->u.m.use_mask = mask_cache_.GetMask(use_mask); 246 lir->u.m.def_mask = mask_cache_.GetMask(def_mask); 247} 248 249inline art::Mir2Lir::RegisterInfo* Mir2Lir::GetRegInfo(RegStorage reg) { 250 RegisterInfo* res = reg.IsPair() ? reginfo_map_.Get(reg.GetLowReg()) : 251 reginfo_map_.Get(reg.GetReg()); 252 DCHECK(res != nullptr); 253 return res; 254} 255 256inline void Mir2Lir::CheckRegLocation(RegLocation rl) const { 257 if (kFailOnSizeError || kReportSizeError) { 258 CheckRegLocationImpl(rl, kFailOnSizeError, kReportSizeError); 259 } 260} 261 262inline void Mir2Lir::CheckRegStorage(RegStorage rs, WidenessCheck wide, RefCheck ref, FPCheck fp) 263 const { 264 if (kFailOnSizeError || kReportSizeError) { 265 CheckRegStorageImpl(rs, wide, ref, fp, kFailOnSizeError, kReportSizeError); 266 } 267} 268 269} // namespace art 270 271#endif // ART_COMPILER_DEX_QUICK_MIR_TO_LIR_INL_H_ 272