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 24 namespace art { 25 26 /* Mark a temp register as dead. Does not affect allocation state. */ 27 inline 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 44 inline 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 */ 69 inline 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 79 inline 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 89 inline 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 99 inline 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 109 inline 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 119 inline 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 129 inline 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 */ 143 inline 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 * Clear the corresponding bit(s). 151 */ 152 inline void Mir2Lir::ClearRegMask(ResourceMask* mask, int reg) { 153 DCHECK_EQ((reg & ~RegStorage::kRegValMask), 0); 154 DCHECK(reginfo_map_.Get(reg) != nullptr) << "No info for 0x" << reg; 155 *mask = mask->ClearBits(reginfo_map_.Get(reg)->DefUseMask()); 156 } 157 158 /* 159 * Set up the proper fields in the resource mask 160 */ 161 inline void Mir2Lir::SetupResourceMasks(LIR* lir) { 162 int opcode = lir->opcode; 163 164 if (IsPseudoLirOp(opcode)) { 165 lir->u.m.use_mask = lir->u.m.def_mask = &kEncodeNone; 166 if (opcode != kPseudoBarrier) { 167 lir->flags.fixup = kFixupLabel; 168 } 169 return; 170 } 171 172 uint64_t flags = GetTargetInstFlags(opcode); 173 174 if (flags & NEEDS_FIXUP) { 175 // Note: target-specific setup may specialize the fixup kind. 176 lir->flags.fixup = kFixupLabel; 177 } 178 179 /* Get the starting size of the instruction's template. */ 180 lir->flags.size = GetInsnSize(lir); 181 estimated_native_code_size_ += lir->flags.size; 182 183 /* Set up the mask for resources. */ 184 ResourceMask use_mask; 185 ResourceMask def_mask; 186 187 if (flags & (IS_LOAD | IS_STORE)) { 188 /* Set memory reference type (defaults to heap, overridden by ScopedMemRefType). */ 189 if (flags & IS_LOAD) { 190 use_mask.SetBit(mem_ref_type_); 191 } else { 192 /* Currently only loads can be marked as kMustNotAlias. */ 193 DCHECK(mem_ref_type_ != ResourceMask::kMustNotAlias); 194 } 195 if (flags & IS_STORE) { 196 /* Literals cannot be written to. */ 197 DCHECK(mem_ref_type_ != ResourceMask::kLiteral); 198 def_mask.SetBit(mem_ref_type_); 199 } 200 } 201 202 /* 203 * Conservatively assume the branch here will call out a function that in 204 * turn will trash everything. 205 */ 206 if (flags & IS_BRANCH) { 207 lir->u.m.def_mask = lir->u.m.use_mask = &kEncodeAll; 208 return; 209 } 210 211 if (flags & REG_DEF0) { 212 SetupRegMask(&def_mask, lir->operands[0]); 213 } 214 215 if (flags & REG_DEF1) { 216 SetupRegMask(&def_mask, lir->operands[1]); 217 } 218 219 if (flags & REG_DEF2) { 220 SetupRegMask(&def_mask, lir->operands[2]); 221 } 222 223 if (flags & REG_USE0) { 224 SetupRegMask(&use_mask, lir->operands[0]); 225 } 226 227 if (flags & REG_USE1) { 228 SetupRegMask(&use_mask, lir->operands[1]); 229 } 230 231 if (flags & REG_USE2) { 232 SetupRegMask(&use_mask, lir->operands[2]); 233 } 234 235 if (flags & REG_USE3) { 236 SetupRegMask(&use_mask, lir->operands[3]); 237 } 238 239 if (flags & REG_USE4) { 240 SetupRegMask(&use_mask, lir->operands[4]); 241 } 242 243 if (flags & SETS_CCODES) { 244 def_mask.SetBit(ResourceMask::kCCode); 245 } 246 247 if (flags & USES_CCODES) { 248 use_mask.SetBit(ResourceMask::kCCode); 249 } 250 251 // Handle target-specific actions 252 SetupTargetResourceMasks(lir, flags, &use_mask, &def_mask); 253 254 lir->u.m.use_mask = mask_cache_.GetMask(use_mask); 255 lir->u.m.def_mask = mask_cache_.GetMask(def_mask); 256 } 257 258 inline art::Mir2Lir::RegisterInfo* Mir2Lir::GetRegInfo(RegStorage reg) { 259 RegisterInfo* res = reg.IsPair() ? reginfo_map_.Get(reg.GetLowReg()) : 260 reginfo_map_.Get(reg.GetReg()); 261 DCHECK(res != nullptr); 262 return res; 263 } 264 265 inline void Mir2Lir::CheckRegLocation(RegLocation rl) const { 266 if (kFailOnSizeError || kReportSizeError) { 267 CheckRegLocationImpl(rl, kFailOnSizeError, kReportSizeError); 268 } 269 } 270 271 inline void Mir2Lir::CheckRegStorage(RegStorage rs, WidenessCheck wide, RefCheck ref, FPCheck fp) 272 const { 273 if (kFailOnSizeError || kReportSizeError) { 274 CheckRegStorageImpl(rs, wide, ref, fp, kFailOnSizeError, kReportSizeError); 275 } 276 } 277 278 } // namespace art 279 280 #endif // ART_COMPILER_DEX_QUICK_MIR_TO_LIR_INL_H_ 281