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 "base/logging.h" 23 #include "dex/compiler_ir.h" 24 #include "utils.h" 25 26 namespace art { 27 28 /* Mark a temp register as dead. Does not affect allocation state. */ 29 inline void Mir2Lir::ClobberBody(RegisterInfo* p) { 30 DCHECK(p->IsTemp()); 31 if (p->SReg() != INVALID_SREG) { 32 DCHECK(!(p->IsLive() && p->IsDirty())) << "Live & dirty temp in clobber"; 33 p->MarkDead(); 34 if (p->IsWide()) { 35 p->SetIsWide(false); 36 if (p->GetReg().NotExactlyEquals(p->Partner())) { 37 // Register pair - deal with the other half. 38 p = GetRegInfo(p->Partner()); 39 p->SetIsWide(false); 40 p->MarkDead(); 41 } 42 } 43 } 44 } 45 46 inline LIR* Mir2Lir::RawLIR(DexOffset dalvik_offset, int opcode, int op0, 47 int op1, int op2, int op3, int op4, LIR* target) { 48 LIR* insn = static_cast<LIR*>(arena_->Alloc(sizeof(LIR), kArenaAllocLIR)); 49 insn->dalvik_offset = dalvik_offset; 50 insn->opcode = opcode; 51 insn->operands[0] = op0; 52 insn->operands[1] = op1; 53 insn->operands[2] = op2; 54 insn->operands[3] = op3; 55 insn->operands[4] = op4; 56 insn->target = target; 57 SetupResourceMasks(insn); 58 if ((opcode == kPseudoTargetLabel) || (opcode == kPseudoSafepointPC) || 59 (opcode == kPseudoExportedPC)) { 60 // Always make labels scheduling barriers 61 DCHECK(!insn->flags.use_def_invalid); 62 insn->u.m.use_mask = insn->u.m.def_mask = &kEncodeAll; 63 } 64 return insn; 65 } 66 67 /* 68 * The following are building blocks to construct low-level IRs with 0 - 4 69 * operands. 70 */ 71 inline LIR* Mir2Lir::NewLIR0(int opcode) { 72 DCHECK(IsPseudoLirOp(opcode) || (GetTargetInstFlags(opcode) & NO_OPERAND)) 73 << GetTargetInstName(opcode) << " " << opcode << " " 74 << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " " 75 << current_dalvik_offset_; 76 LIR* insn = RawLIR(current_dalvik_offset_, opcode); 77 AppendLIR(insn); 78 return insn; 79 } 80 81 inline LIR* Mir2Lir::NewLIR1(int opcode, int dest) { 82 DCHECK(IsPseudoLirOp(opcode) || (GetTargetInstFlags(opcode) & IS_UNARY_OP)) 83 << GetTargetInstName(opcode) << " " << opcode << " " 84 << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " " 85 << current_dalvik_offset_; 86 LIR* insn = RawLIR(current_dalvik_offset_, opcode, dest); 87 AppendLIR(insn); 88 return insn; 89 } 90 91 inline LIR* Mir2Lir::NewLIR2(int opcode, int dest, int src1) { 92 DCHECK(IsPseudoLirOp(opcode) || (GetTargetInstFlags(opcode) & IS_BINARY_OP)) 93 << GetTargetInstName(opcode) << " " << opcode << " " 94 << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " " 95 << current_dalvik_offset_; 96 LIR* insn = RawLIR(current_dalvik_offset_, opcode, dest, src1); 97 AppendLIR(insn); 98 return insn; 99 } 100 101 inline LIR* Mir2Lir::NewLIR2NoDest(int opcode, int src, int info) { 102 DCHECK(IsPseudoLirOp(opcode) || (GetTargetInstFlags(opcode) & IS_BINARY_OP)) 103 << GetTargetInstName(opcode) << " " << opcode << " " 104 << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " " 105 << current_dalvik_offset_; 106 LIR* insn = RawLIR(current_dalvik_offset_, opcode, src, info); 107 AppendLIR(insn); 108 return insn; 109 } 110 111 inline LIR* Mir2Lir::NewLIR3(int opcode, int dest, int src1, int src2) { 112 DCHECK(IsPseudoLirOp(opcode) || (GetTargetInstFlags(opcode) & IS_TERTIARY_OP)) 113 << GetTargetInstName(opcode) << " " << opcode << " " 114 << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " " 115 << current_dalvik_offset_; 116 LIR* insn = RawLIR(current_dalvik_offset_, opcode, dest, src1, src2); 117 AppendLIR(insn); 118 return insn; 119 } 120 121 inline LIR* Mir2Lir::NewLIR4(int opcode, int dest, int src1, int src2, int info) { 122 DCHECK(IsPseudoLirOp(opcode) || (GetTargetInstFlags(opcode) & IS_QUAD_OP)) 123 << GetTargetInstName(opcode) << " " << opcode << " " 124 << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " " 125 << current_dalvik_offset_; 126 LIR* insn = RawLIR(current_dalvik_offset_, opcode, dest, src1, src2, info); 127 AppendLIR(insn); 128 return insn; 129 } 130 131 inline LIR* Mir2Lir::NewLIR5(int opcode, int dest, int src1, int src2, int info1, 132 int info2) { 133 DCHECK(IsPseudoLirOp(opcode) || (GetTargetInstFlags(opcode) & IS_QUIN_OP)) 134 << GetTargetInstName(opcode) << " " << opcode << " " 135 << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " " 136 << current_dalvik_offset_; 137 LIR* insn = RawLIR(current_dalvik_offset_, opcode, dest, src1, src2, info1, info2); 138 AppendLIR(insn); 139 return insn; 140 } 141 142 /* 143 * Mark the corresponding bit(s). 144 */ 145 inline void Mir2Lir::SetupRegMask(ResourceMask* mask, int reg) { 146 DCHECK_EQ((reg & ~RegStorage::kRegValMask), 0); 147 DCHECK_LT(static_cast<size_t>(reg), reginfo_map_.size()); 148 DCHECK(reginfo_map_[reg] != nullptr) << "No info for 0x" << reg; 149 *mask = mask->Union(reginfo_map_[reg]->DefUseMask()); 150 } 151 152 /* 153 * Clear the corresponding bit(s). 154 */ 155 inline void Mir2Lir::ClearRegMask(ResourceMask* mask, int reg) { 156 DCHECK_EQ((reg & ~RegStorage::kRegValMask), 0); 157 DCHECK_LT(static_cast<size_t>(reg), reginfo_map_.size()); 158 DCHECK(reginfo_map_[reg] != nullptr) << "No info for 0x" << reg; 159 *mask = mask->ClearBits(reginfo_map_[reg]->DefUseMask()); 160 } 161 162 /* 163 * Set up the proper fields in the resource mask 164 */ 165 inline void Mir2Lir::SetupResourceMasks(LIR* lir) { 166 int opcode = lir->opcode; 167 168 if (IsPseudoLirOp(opcode)) { 169 lir->u.m.use_mask = lir->u.m.def_mask = &kEncodeNone; 170 if (opcode != kPseudoBarrier) { 171 lir->flags.fixup = kFixupLabel; 172 } 173 return; 174 } 175 176 uint64_t flags = GetTargetInstFlags(opcode); 177 178 if (flags & NEEDS_FIXUP) { 179 // Note: target-specific setup may specialize the fixup kind. 180 lir->flags.fixup = kFixupLabel; 181 } 182 183 /* Get the starting size of the instruction's template. */ 184 lir->flags.size = GetInsnSize(lir); 185 estimated_native_code_size_ += lir->flags.size; 186 187 /* Set up the mask for resources. */ 188 ResourceMask use_mask; 189 ResourceMask def_mask; 190 191 if (flags & (IS_LOAD | IS_STORE)) { 192 /* Set memory reference type (defaults to heap, overridden by ScopedMemRefType). */ 193 if (flags & IS_LOAD) { 194 use_mask.SetBit(mem_ref_type_); 195 } else { 196 /* Currently only loads can be marked as kMustNotAlias. */ 197 DCHECK(mem_ref_type_ != ResourceMask::kMustNotAlias); 198 } 199 if (flags & IS_STORE) { 200 /* Literals cannot be written to. */ 201 DCHECK(mem_ref_type_ != ResourceMask::kLiteral); 202 def_mask.SetBit(mem_ref_type_); 203 } 204 } 205 206 /* 207 * Conservatively assume the branch here will call out a function that in 208 * turn will trash everything. 209 */ 210 if (flags & IS_BRANCH) { 211 lir->u.m.def_mask = lir->u.m.use_mask = &kEncodeAll; 212 return; 213 } 214 215 if (flags & REG_DEF0) { 216 SetupRegMask(&def_mask, lir->operands[0]); 217 } 218 219 if (flags & REG_DEF1) { 220 SetupRegMask(&def_mask, lir->operands[1]); 221 } 222 223 if (flags & REG_DEF2) { 224 SetupRegMask(&def_mask, lir->operands[2]); 225 } 226 227 if (flags & REG_USE0) { 228 SetupRegMask(&use_mask, lir->operands[0]); 229 } 230 231 if (flags & REG_USE1) { 232 SetupRegMask(&use_mask, lir->operands[1]); 233 } 234 235 if (flags & REG_USE2) { 236 SetupRegMask(&use_mask, lir->operands[2]); 237 } 238 239 if (flags & REG_USE3) { 240 SetupRegMask(&use_mask, lir->operands[3]); 241 } 242 243 if (flags & REG_USE4) { 244 SetupRegMask(&use_mask, lir->operands[4]); 245 } 246 247 if (flags & SETS_CCODES) { 248 def_mask.SetBit(ResourceMask::kCCode); 249 } 250 251 if (flags & USES_CCODES) { 252 use_mask.SetBit(ResourceMask::kCCode); 253 } 254 255 // Handle target-specific actions 256 SetupTargetResourceMasks(lir, flags, &use_mask, &def_mask); 257 258 lir->u.m.use_mask = mask_cache_.GetMask(use_mask); 259 lir->u.m.def_mask = mask_cache_.GetMask(def_mask); 260 } 261 262 inline art::Mir2Lir::RegisterInfo* Mir2Lir::GetRegInfo(RegStorage reg) { 263 RegisterInfo* res = reg.IsPair() ? reginfo_map_[reg.GetLowReg()] : reginfo_map_[reg.GetReg()]; 264 DCHECK(res != nullptr); 265 return res; 266 } 267 268 inline void Mir2Lir::CheckRegLocation(RegLocation rl) const { 269 if (kFailOnSizeError || kReportSizeError) { 270 CheckRegLocationImpl(rl, kFailOnSizeError, kReportSizeError); 271 } 272 } 273 274 inline void Mir2Lir::CheckRegStorage(RegStorage rs, WidenessCheck wide, RefCheck ref, FPCheck fp) 275 const { 276 if (kFailOnSizeError || kReportSizeError) { 277 CheckRegStorageImpl(rs, wide, ref, fp, kFailOnSizeError, kReportSizeError); 278 } 279 } 280 281 inline Mir2Lir::ShortyIterator::ShortyIterator(const char* shorty, bool is_static) 282 : cur_(shorty + 1), pending_this_(!is_static), initialized_(false) { 283 DCHECK(shorty != nullptr); 284 DCHECK_NE(*shorty, 0); 285 } 286 287 inline bool Mir2Lir::ShortyIterator::Next() { 288 if (!initialized_) { 289 initialized_ = true; 290 } else if (pending_this_) { 291 pending_this_ = false; 292 } else if (*cur_ != 0) { 293 cur_++; 294 } 295 296 return *cur_ != 0 || pending_this_; 297 } 298 299 } // namespace art 300 301 #endif // ART_COMPILER_DEX_QUICK_MIR_TO_LIR_INL_H_ 302