1/*
2 * Copyright (C) 2011 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#include "mir_to_lir-inl.h"
18
19#include "dex/dataflow_iterator-inl.h"
20#include "dex/quick/dex_file_method_inliner.h"
21#include "driver/compiler_driver.h"
22#include "primitive.h"
23#include "thread-inl.h"
24
25namespace art {
26
27class Mir2Lir::SpecialSuspendCheckSlowPath : public Mir2Lir::LIRSlowPath {
28 public:
29  SpecialSuspendCheckSlowPath(Mir2Lir* m2l, LIR* branch, LIR* cont)
30      : LIRSlowPath(m2l, branch, cont),
31        num_used_args_(0u) {
32  }
33
34  void PreserveArg(int in_position) {
35    // Avoid duplicates.
36    for (size_t i = 0; i != num_used_args_; ++i) {
37      if (used_args_[i] == in_position) {
38        return;
39      }
40    }
41    DCHECK_LT(num_used_args_, kMaxArgsToPreserve);
42    used_args_[num_used_args_] = in_position;
43    ++num_used_args_;
44  }
45
46  void Compile() OVERRIDE {
47    m2l_->ResetRegPool();
48    m2l_->ResetDefTracking();
49    GenerateTargetLabel(kPseudoSuspendTarget);
50
51    m2l_->LockCallTemps();
52
53    // Generate frame.
54    m2l_->GenSpecialEntryForSuspend();
55
56    // Spill all args.
57    for (size_t i = 0, end = m2l_->in_to_reg_storage_mapping_.GetEndMappedIn(); i < end;
58        i += m2l_->in_to_reg_storage_mapping_.GetShorty(i).IsWide() ? 2u : 1u) {
59      m2l_->SpillArg(i);
60    }
61
62    m2l_->FreeCallTemps();
63
64    // Do the actual suspend call to runtime.
65    m2l_->CallRuntimeHelper(kQuickTestSuspend, true);
66
67    m2l_->LockCallTemps();
68
69    // Unspill used regs. (Don't unspill unused args.)
70    for (size_t i = 0; i != num_used_args_; ++i) {
71      m2l_->UnspillArg(used_args_[i]);
72    }
73
74    // Pop the frame.
75    m2l_->GenSpecialExitForSuspend();
76
77    // Branch to the continue label.
78    DCHECK(cont_ != nullptr);
79    m2l_->OpUnconditionalBranch(cont_);
80
81    m2l_->FreeCallTemps();
82  }
83
84 private:
85  static constexpr size_t kMaxArgsToPreserve = 2u;
86  size_t num_used_args_;
87  int used_args_[kMaxArgsToPreserve];
88};
89
90RegisterClass Mir2Lir::ShortyToRegClass(char shorty_type) {
91  RegisterClass res;
92  switch (shorty_type) {
93    case 'L':
94      res = kRefReg;
95      break;
96    case 'F':
97      // Expected fallthrough.
98    case 'D':
99      res = kFPReg;
100      break;
101    default:
102      res = kCoreReg;
103  }
104  return res;
105}
106
107void Mir2Lir::LockArg(size_t in_position) {
108  RegStorage reg_arg = in_to_reg_storage_mapping_.GetReg(in_position);
109
110  if (reg_arg.Valid()) {
111    LockTemp(reg_arg);
112  }
113}
114
115RegStorage Mir2Lir::LoadArg(size_t in_position, RegisterClass reg_class, bool wide) {
116  ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
117  int offset = StackVisitor::GetOutVROffset(in_position, cu_->instruction_set);
118
119  if (cu_->instruction_set == kX86) {
120    /*
121     * When doing a call for x86, it moves the stack pointer in order to push return.
122     * Thus, we add another 4 bytes to figure out the out of caller (in of callee).
123     */
124    offset += sizeof(uint32_t);
125  }
126
127  if (cu_->instruction_set == kX86_64) {
128    /*
129     * When doing a call for x86, it moves the stack pointer in order to push return.
130     * Thus, we add another 8 bytes to figure out the out of caller (in of callee).
131     */
132    offset += sizeof(uint64_t);
133  }
134
135  RegStorage reg_arg = in_to_reg_storage_mapping_.GetReg(in_position);
136
137  // TODO: REVISIT: This adds a spill of low part while we could just copy it.
138  if (reg_arg.Valid() && wide && (reg_arg.GetWideKind() == kNotWide)) {
139    // For wide register we've got only half of it.
140    // Flush it to memory then.
141    StoreBaseDisp(TargetPtrReg(kSp), offset, reg_arg, k32, kNotVolatile);
142    reg_arg = RegStorage::InvalidReg();
143  }
144
145  if (!reg_arg.Valid()) {
146    reg_arg = wide ?  AllocTypedTempWide(false, reg_class) : AllocTypedTemp(false, reg_class);
147    LoadBaseDisp(TargetPtrReg(kSp), offset, reg_arg, wide ? k64 : k32, kNotVolatile);
148  } else {
149    // Check if we need to copy the arg to a different reg_class.
150    if (!RegClassMatches(reg_class, reg_arg)) {
151      if (wide) {
152        RegStorage new_reg = AllocTypedTempWide(false, reg_class);
153        OpRegCopyWide(new_reg, reg_arg);
154        reg_arg = new_reg;
155      } else {
156        RegStorage new_reg = AllocTypedTemp(false, reg_class);
157        OpRegCopy(new_reg, reg_arg);
158        reg_arg = new_reg;
159      }
160    }
161  }
162  return reg_arg;
163}
164
165void Mir2Lir::LoadArgDirect(size_t in_position, RegLocation rl_dest) {
166  DCHECK_EQ(rl_dest.location, kLocPhysReg);
167  ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
168  int offset = StackVisitor::GetOutVROffset(in_position, cu_->instruction_set);
169  if (cu_->instruction_set == kX86) {
170    /*
171     * When doing a call for x86, it moves the stack pointer in order to push return.
172     * Thus, we add another 4 bytes to figure out the out of caller (in of callee).
173     */
174    offset += sizeof(uint32_t);
175  }
176
177  if (cu_->instruction_set == kX86_64) {
178    /*
179     * When doing a call for x86, it moves the stack pointer in order to push return.
180     * Thus, we add another 8 bytes to figure out the out of caller (in of callee).
181     */
182    offset += sizeof(uint64_t);
183  }
184
185  RegStorage reg_arg = in_to_reg_storage_mapping_.GetReg(in_position);
186
187  // TODO: REVISIT: This adds a spill of low part while we could just copy it.
188  if (reg_arg.Valid() && rl_dest.wide && (reg_arg.GetWideKind() == kNotWide)) {
189    // For wide register we've got only half of it.
190    // Flush it to memory then.
191    StoreBaseDisp(TargetPtrReg(kSp), offset, reg_arg, k32, kNotVolatile);
192    reg_arg = RegStorage::InvalidReg();
193  }
194
195  if (!reg_arg.Valid()) {
196    OpSize op_size = rl_dest.wide ? k64 : (rl_dest.ref ? kReference : k32);
197    LoadBaseDisp(TargetPtrReg(kSp), offset, rl_dest.reg, op_size, kNotVolatile);
198  } else {
199    if (rl_dest.wide) {
200      OpRegCopyWide(rl_dest.reg, reg_arg);
201    } else {
202      OpRegCopy(rl_dest.reg, reg_arg);
203    }
204  }
205}
206
207void Mir2Lir::SpillArg(size_t in_position) {
208  RegStorage reg_arg = in_to_reg_storage_mapping_.GetReg(in_position);
209
210  if (reg_arg.Valid()) {
211    int offset = frame_size_ + StackVisitor::GetOutVROffset(in_position, cu_->instruction_set);
212    ShortyArg arg = in_to_reg_storage_mapping_.GetShorty(in_position);
213    OpSize size = arg.IsRef() ? kReference :
214        (arg.IsWide() && reg_arg.GetWideKind() == kWide) ? k64 : k32;
215    StoreBaseDisp(TargetPtrReg(kSp), offset, reg_arg, size, kNotVolatile);
216  }
217}
218
219void Mir2Lir::UnspillArg(size_t in_position) {
220  RegStorage reg_arg = in_to_reg_storage_mapping_.GetReg(in_position);
221
222  if (reg_arg.Valid()) {
223    int offset = frame_size_ + StackVisitor::GetOutVROffset(in_position, cu_->instruction_set);
224    ShortyArg arg = in_to_reg_storage_mapping_.GetShorty(in_position);
225    OpSize size = arg.IsRef() ? kReference :
226        (arg.IsWide() && reg_arg.GetWideKind() == kWide) ? k64 : k32;
227    LoadBaseDisp(TargetPtrReg(kSp), offset, reg_arg, size, kNotVolatile);
228  }
229}
230
231Mir2Lir::SpecialSuspendCheckSlowPath* Mir2Lir::GenSpecialSuspendTest() {
232  LockCallTemps();
233  LIR* branch = OpTestSuspend(nullptr);
234  FreeCallTemps();
235  LIR* cont = NewLIR0(kPseudoTargetLabel);
236  SpecialSuspendCheckSlowPath* slow_path =
237      new (arena_) SpecialSuspendCheckSlowPath(this, branch, cont);
238  AddSlowPath(slow_path);
239  return slow_path;
240}
241
242bool Mir2Lir::GenSpecialIGet(MIR* mir, const InlineMethod& special) {
243  // FastInstance() already checked by DexFileMethodInliner.
244  const InlineIGetIPutData& data = special.d.ifield_data;
245  if (data.method_is_static != 0u || data.object_arg != 0u) {
246    // The object is not "this" and has to be null-checked.
247    return false;
248  }
249
250  OpSize size;
251  switch (data.op_variant) {
252    case InlineMethodAnalyser::IGetVariant(Instruction::IGET):
253      size = in_to_reg_storage_mapping_.GetShorty(data.src_arg).IsFP() ? kSingle : k32;
254      break;
255    case InlineMethodAnalyser::IGetVariant(Instruction::IGET_WIDE):
256      size = in_to_reg_storage_mapping_.GetShorty(data.src_arg).IsFP() ? kDouble : k64;
257      break;
258    case InlineMethodAnalyser::IGetVariant(Instruction::IGET_OBJECT):
259      size = kReference;
260      break;
261    case InlineMethodAnalyser::IGetVariant(Instruction::IGET_SHORT):
262      size = kSignedHalf;
263      break;
264    case InlineMethodAnalyser::IGetVariant(Instruction::IGET_CHAR):
265      size = kUnsignedHalf;
266      break;
267    case InlineMethodAnalyser::IGetVariant(Instruction::IGET_BYTE):
268      size = kSignedByte;
269      break;
270    case InlineMethodAnalyser::IGetVariant(Instruction::IGET_BOOLEAN):
271      size = kUnsignedByte;
272      break;
273    default:
274      LOG(FATAL) << "Unknown variant: " << data.op_variant;
275      UNREACHABLE();
276  }
277
278  // Point of no return - no aborts after this
279  if (!kLeafOptimization) {
280    auto* slow_path = GenSpecialSuspendTest();
281    slow_path->PreserveArg(data.object_arg);
282  }
283  LockArg(data.object_arg);
284  GenPrintLabel(mir);
285  RegStorage reg_obj = LoadArg(data.object_arg, kRefReg);
286  RegisterClass reg_class = RegClassForFieldLoadStore(size, data.is_volatile);
287  RegisterClass ret_reg_class = ShortyToRegClass(cu_->shorty[0]);
288  RegLocation rl_dest = IsWide(size) ? GetReturnWide(ret_reg_class) : GetReturn(ret_reg_class);
289  RegStorage r_result = rl_dest.reg;
290  if (!RegClassMatches(reg_class, r_result)) {
291    r_result = IsWide(size) ? AllocTypedTempWide(rl_dest.fp, reg_class)
292                            : AllocTypedTemp(rl_dest.fp, reg_class);
293  }
294  if (IsRef(size)) {
295    LoadRefDisp(reg_obj, data.field_offset, r_result, data.is_volatile ? kVolatile : kNotVolatile);
296  } else {
297    LoadBaseDisp(reg_obj, data.field_offset, r_result, size, data.is_volatile ? kVolatile :
298        kNotVolatile);
299  }
300  if (r_result.NotExactlyEquals(rl_dest.reg)) {
301    if (IsWide(size)) {
302      OpRegCopyWide(rl_dest.reg, r_result);
303    } else {
304      OpRegCopy(rl_dest.reg, r_result);
305    }
306  }
307  return true;
308}
309
310bool Mir2Lir::GenSpecialIPut(MIR* mir, const InlineMethod& special) {
311  // FastInstance() already checked by DexFileMethodInliner.
312  const InlineIGetIPutData& data = special.d.ifield_data;
313  if (data.method_is_static != 0u || data.object_arg != 0u) {
314    // The object is not "this" and has to be null-checked.
315    return false;
316  }
317  if (data.return_arg_plus1 != 0u) {
318    // The setter returns a method argument which we don't support here.
319    return false;
320  }
321
322  OpSize size;
323  switch (data.op_variant) {
324    case InlineMethodAnalyser::IPutVariant(Instruction::IPUT):
325      size = in_to_reg_storage_mapping_.GetShorty(data.src_arg).IsFP() ? kSingle : k32;
326      break;
327    case InlineMethodAnalyser::IPutVariant(Instruction::IPUT_WIDE):
328      size = in_to_reg_storage_mapping_.GetShorty(data.src_arg).IsFP() ? kDouble : k64;
329      break;
330    case InlineMethodAnalyser::IPutVariant(Instruction::IPUT_OBJECT):
331      size = kReference;
332      break;
333    case InlineMethodAnalyser::IPutVariant(Instruction::IPUT_SHORT):
334      size = kSignedHalf;
335      break;
336    case InlineMethodAnalyser::IPutVariant(Instruction::IPUT_CHAR):
337      size = kUnsignedHalf;
338      break;
339    case InlineMethodAnalyser::IPutVariant(Instruction::IPUT_BYTE):
340      size = kSignedByte;
341      break;
342    case InlineMethodAnalyser::IPutVariant(Instruction::IPUT_BOOLEAN):
343      size = kUnsignedByte;
344      break;
345    default:
346      LOG(FATAL) << "Unknown variant: " << data.op_variant;
347      UNREACHABLE();
348  }
349
350  // Point of no return - no aborts after this
351  if (!kLeafOptimization) {
352    auto* slow_path = GenSpecialSuspendTest();
353    slow_path->PreserveArg(data.object_arg);
354    slow_path->PreserveArg(data.src_arg);
355  }
356  LockArg(data.object_arg);
357  LockArg(data.src_arg);
358  GenPrintLabel(mir);
359  RegStorage reg_obj = LoadArg(data.object_arg, kRefReg);
360  RegisterClass reg_class = RegClassForFieldLoadStore(size, data.is_volatile);
361  RegStorage reg_src = LoadArg(data.src_arg, reg_class, IsWide(size));
362  if (IsRef(size)) {
363    StoreRefDisp(reg_obj, data.field_offset, reg_src, data.is_volatile ? kVolatile : kNotVolatile);
364  } else {
365    StoreBaseDisp(reg_obj, data.field_offset, reg_src, size, data.is_volatile ? kVolatile :
366        kNotVolatile);
367  }
368  if (IsRef(size)) {
369    MarkGCCard(0, reg_src, reg_obj);
370  }
371  return true;
372}
373
374bool Mir2Lir::GenSpecialIdentity(MIR* mir, const InlineMethod& special) {
375  const InlineReturnArgData& data = special.d.return_data;
376  bool wide = (data.is_wide != 0u);
377
378  // Point of no return - no aborts after this
379  if (!kLeafOptimization) {
380    auto* slow_path = GenSpecialSuspendTest();
381    slow_path->PreserveArg(data.arg);
382  }
383  LockArg(data.arg);
384  GenPrintLabel(mir);
385  RegisterClass reg_class = ShortyToRegClass(cu_->shorty[0]);
386  RegLocation rl_dest = wide ? GetReturnWide(reg_class) : GetReturn(reg_class);
387  LoadArgDirect(data.arg, rl_dest);
388  return true;
389}
390
391/*
392 * Special-case code generation for simple non-throwing leaf methods.
393 */
394bool Mir2Lir::GenSpecialCase(BasicBlock* bb, MIR* mir, const InlineMethod& special) {
395  DCHECK(special.flags & kInlineSpecial);
396  current_dalvik_offset_ = mir->offset;
397  DCHECK(current_mir_ == nullptr);  // Safepoints attributed to prologue.
398  MIR* return_mir = nullptr;
399  bool successful = false;
400  EnsureInitializedArgMappingToPhysicalReg();
401
402  switch (special.opcode) {
403    case kInlineOpNop:
404      successful = true;
405      DCHECK_EQ(mir->dalvikInsn.opcode, Instruction::RETURN_VOID);
406      if (!kLeafOptimization) {
407        GenSpecialSuspendTest();
408      }
409      return_mir = mir;
410      break;
411    case kInlineOpNonWideConst: {
412      successful = true;
413      if (!kLeafOptimization) {
414        GenSpecialSuspendTest();
415      }
416      RegLocation rl_dest = GetReturn(ShortyToRegClass(cu_->shorty[0]));
417      GenPrintLabel(mir);
418      LoadConstant(rl_dest.reg, static_cast<int>(special.d.data));
419      return_mir = bb->GetNextUnconditionalMir(mir_graph_, mir);
420      break;
421    }
422    case kInlineOpReturnArg:
423      successful = GenSpecialIdentity(mir, special);
424      return_mir = mir;
425      break;
426    case kInlineOpIGet:
427      successful = GenSpecialIGet(mir, special);
428      return_mir = bb->GetNextUnconditionalMir(mir_graph_, mir);
429      break;
430    case kInlineOpIPut:
431      successful = GenSpecialIPut(mir, special);
432      return_mir = bb->GetNextUnconditionalMir(mir_graph_, mir);
433      break;
434    default:
435      break;
436  }
437
438  if (successful) {
439    if (kIsDebugBuild) {
440      // Clear unreachable catch entries.
441      mir_graph_->catches_.clear();
442    }
443
444    // Handle verbosity for return MIR.
445    if (return_mir != nullptr) {
446      current_dalvik_offset_ = return_mir->offset;
447      // Not handling special identity case because it already generated code as part
448      // of the return. The label should have been added before any code was generated.
449      if (special.opcode != kInlineOpReturnArg) {
450        GenPrintLabel(return_mir);
451      }
452    }
453    GenSpecialExitSequence();
454
455    if (!kLeafOptimization) {
456      HandleSlowPaths();
457    } else {
458      core_spill_mask_ = 0;
459      num_core_spills_ = 0;
460      fp_spill_mask_ = 0;
461      num_fp_spills_ = 0;
462      frame_size_ = 0;
463      core_vmap_table_.clear();
464      fp_vmap_table_.clear();
465    }
466  }
467
468  return successful;
469}
470
471/*
472 * Target-independent code generation.  Use only high-level
473 * load/store utilities here, or target-dependent genXX() handlers
474 * when necessary.
475 */
476void Mir2Lir::CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list) {
477  RegLocation rl_src[3];
478  RegLocation rl_dest = mir_graph_->GetBadLoc();
479  RegLocation rl_result = mir_graph_->GetBadLoc();
480  const Instruction::Code opcode = mir->dalvikInsn.opcode;
481  const int opt_flags = mir->optimization_flags;
482  const uint32_t vB = mir->dalvikInsn.vB;
483  const uint32_t vC = mir->dalvikInsn.vC;
484  DCHECK(CheckCorePoolSanity()) << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " @ 0x:"
485                                << std::hex << current_dalvik_offset_;
486
487  // Prep Src and Dest locations.
488  int next_sreg = 0;
489  int next_loc = 0;
490  uint64_t attrs = MIRGraph::GetDataFlowAttributes(opcode);
491  rl_src[0] = rl_src[1] = rl_src[2] = mir_graph_->GetBadLoc();
492  if (attrs & DF_UA) {
493    if (attrs & DF_A_WIDE) {
494      rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg);
495      next_sreg+= 2;
496    } else {
497      rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg);
498      next_sreg++;
499    }
500  }
501  if (attrs & DF_UB) {
502    if (attrs & DF_B_WIDE) {
503      rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg);
504      next_sreg+= 2;
505    } else {
506      rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg);
507      next_sreg++;
508    }
509  }
510  if (attrs & DF_UC) {
511    if (attrs & DF_C_WIDE) {
512      rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg);
513    } else {
514      rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg);
515    }
516  }
517  if (attrs & DF_DA) {
518    if (attrs & DF_A_WIDE) {
519      rl_dest = mir_graph_->GetDestWide(mir);
520    } else {
521      rl_dest = mir_graph_->GetDest(mir);
522    }
523  }
524  switch (opcode) {
525    case Instruction::NOP:
526      break;
527
528    case Instruction::MOVE_EXCEPTION:
529      GenMoveException(rl_dest);
530      break;
531
532    case Instruction::RETURN_VOID_NO_BARRIER:
533    case Instruction::RETURN_VOID:
534      if (((cu_->access_flags & kAccConstructor) != 0) &&
535          cu_->compiler_driver->RequiresConstructorBarrier(Thread::Current(), cu_->dex_file,
536                                                          cu_->class_def_idx)) {
537        GenMemBarrier(kStoreStore);
538      }
539      if (!kLeafOptimization || !mir_graph_->MethodIsLeaf()) {
540        GenSuspendTest(opt_flags);
541      }
542      break;
543
544    case Instruction::RETURN_OBJECT:
545      DCHECK(rl_src[0].ref);
546      FALLTHROUGH_INTENDED;
547    case Instruction::RETURN:
548      if (!kLeafOptimization || !mir_graph_->MethodIsLeaf()) {
549        GenSuspendTest(opt_flags);
550      }
551      StoreValue(GetReturn(ShortyToRegClass(cu_->shorty[0])), rl_src[0]);
552      break;
553
554    case Instruction::RETURN_WIDE:
555      if (!kLeafOptimization || !mir_graph_->MethodIsLeaf()) {
556        GenSuspendTest(opt_flags);
557      }
558      StoreValueWide(GetReturnWide(ShortyToRegClass(cu_->shorty[0])), rl_src[0]);
559      break;
560
561    case Instruction::MOVE_RESULT:
562    case Instruction::MOVE_RESULT_WIDE:
563    case Instruction::MOVE_RESULT_OBJECT:
564      // Already processed with invoke or filled-new-array.
565      break;
566
567    case Instruction::MOVE:
568    case Instruction::MOVE_OBJECT:
569    case Instruction::MOVE_16:
570    case Instruction::MOVE_OBJECT_16:
571    case Instruction::MOVE_FROM16:
572    case Instruction::MOVE_OBJECT_FROM16:
573      StoreValue(rl_dest, rl_src[0]);
574      break;
575
576    case Instruction::MOVE_WIDE:
577    case Instruction::MOVE_WIDE_16:
578    case Instruction::MOVE_WIDE_FROM16:
579      StoreValueWide(rl_dest, rl_src[0]);
580      break;
581
582    case Instruction::CONST:
583    case Instruction::CONST_4:
584    case Instruction::CONST_16:
585      GenConst(rl_dest, vB);
586      break;
587
588    case Instruction::CONST_HIGH16:
589      GenConst(rl_dest, vB << 16);
590      break;
591
592    case Instruction::CONST_WIDE_16:
593    case Instruction::CONST_WIDE_32:
594      GenConstWide(rl_dest, static_cast<int64_t>(static_cast<int32_t>(vB)));
595      break;
596
597    case Instruction::CONST_WIDE:
598      GenConstWide(rl_dest, mir->dalvikInsn.vB_wide);
599      break;
600
601    case Instruction::CONST_WIDE_HIGH16:
602      rl_result = EvalLoc(rl_dest, kAnyReg, true);
603      LoadConstantWide(rl_result.reg, static_cast<int64_t>(vB) << 48);
604      StoreValueWide(rl_dest, rl_result);
605      break;
606
607    case Instruction::MONITOR_ENTER:
608      GenMonitorEnter(opt_flags, rl_src[0]);
609      break;
610
611    case Instruction::MONITOR_EXIT:
612      GenMonitorExit(opt_flags, rl_src[0]);
613      break;
614
615    case Instruction::CHECK_CAST: {
616      GenCheckCast(opt_flags, mir->offset, vB, rl_src[0]);
617      break;
618    }
619    case Instruction::INSTANCE_OF:
620      GenInstanceof(vC, rl_dest, rl_src[0]);
621      break;
622
623    case Instruction::NEW_INSTANCE:
624      GenNewInstance(vB, rl_dest);
625      break;
626
627    case Instruction::THROW:
628      GenThrow(rl_src[0]);
629      break;
630
631    case Instruction::ARRAY_LENGTH: {
632      int len_offset;
633      len_offset = mirror::Array::LengthOffset().Int32Value();
634      rl_src[0] = LoadValue(rl_src[0], kRefReg);
635      GenNullCheck(rl_src[0].reg, opt_flags);
636      rl_result = EvalLoc(rl_dest, kCoreReg, true);
637      Load32Disp(rl_src[0].reg, len_offset, rl_result.reg);
638      MarkPossibleNullPointerException(opt_flags);
639      StoreValue(rl_dest, rl_result);
640      break;
641    }
642    case Instruction::CONST_STRING:
643    case Instruction::CONST_STRING_JUMBO:
644      GenConstString(vB, rl_dest);
645      break;
646
647    case Instruction::CONST_CLASS:
648      GenConstClass(vB, rl_dest);
649      break;
650
651    case Instruction::FILL_ARRAY_DATA:
652      GenFillArrayData(mir, vB, rl_src[0]);
653      break;
654
655    case Instruction::FILLED_NEW_ARRAY:
656      GenFilledNewArray(mir_graph_->NewMemCallInfo(bb, mir, kStatic,
657                        false /* not range */));
658      break;
659
660    case Instruction::FILLED_NEW_ARRAY_RANGE:
661      GenFilledNewArray(mir_graph_->NewMemCallInfo(bb, mir, kStatic,
662                        true /* range */));
663      break;
664
665    case Instruction::NEW_ARRAY:
666      GenNewArray(vC, rl_dest, rl_src[0]);
667      break;
668
669    case Instruction::GOTO:
670    case Instruction::GOTO_16:
671    case Instruction::GOTO_32:
672      if (mir_graph_->IsBackEdge(bb, bb->taken)) {
673        GenSuspendTestAndBranch(opt_flags, &label_list[bb->taken]);
674      } else {
675        OpUnconditionalBranch(&label_list[bb->taken]);
676      }
677      break;
678
679    case Instruction::PACKED_SWITCH:
680      GenPackedSwitch(mir, vB, rl_src[0]);
681      break;
682
683    case Instruction::SPARSE_SWITCH:
684      GenSparseSwitch(mir, vB, rl_src[0]);
685      break;
686
687    case Instruction::CMPL_FLOAT:
688    case Instruction::CMPG_FLOAT:
689    case Instruction::CMPL_DOUBLE:
690    case Instruction::CMPG_DOUBLE:
691      GenCmpFP(opcode, rl_dest, rl_src[0], rl_src[1]);
692      break;
693
694    case Instruction::CMP_LONG:
695      GenCmpLong(rl_dest, rl_src[0], rl_src[1]);
696      break;
697
698    case Instruction::IF_EQ:
699    case Instruction::IF_NE:
700    case Instruction::IF_LT:
701    case Instruction::IF_GE:
702    case Instruction::IF_GT:
703    case Instruction::IF_LE: {
704      if (mir_graph_->IsBackEdge(bb, bb->taken) || mir_graph_->IsBackEdge(bb, bb->fall_through)) {
705        GenSuspendTest(opt_flags);
706      }
707      LIR* taken = &label_list[bb->taken];
708      GenCompareAndBranch(opcode, rl_src[0], rl_src[1], taken);
709      break;
710    }
711    case Instruction::IF_EQZ:
712    case Instruction::IF_NEZ:
713    case Instruction::IF_LTZ:
714    case Instruction::IF_GEZ:
715    case Instruction::IF_GTZ:
716    case Instruction::IF_LEZ: {
717      if (mir_graph_->IsBackEdge(bb, bb->taken) || mir_graph_->IsBackEdge(bb, bb->fall_through)) {
718        GenSuspendTest(opt_flags);
719      }
720      LIR* taken = &label_list[bb->taken];
721      GenCompareZeroAndBranch(opcode, rl_src[0], taken);
722      break;
723    }
724
725    case Instruction::AGET_WIDE:
726      GenArrayGet(opt_flags, rl_dest.fp ? kDouble : k64, rl_src[0], rl_src[1], rl_dest, 3);
727      break;
728    case Instruction::AGET_OBJECT:
729      GenArrayGet(opt_flags, kReference, rl_src[0], rl_src[1], rl_dest, 2);
730      break;
731    case Instruction::AGET:
732      GenArrayGet(opt_flags, rl_dest.fp ? kSingle : k32, rl_src[0], rl_src[1], rl_dest, 2);
733      break;
734    case Instruction::AGET_BOOLEAN:
735      GenArrayGet(opt_flags, kUnsignedByte, rl_src[0], rl_src[1], rl_dest, 0);
736      break;
737    case Instruction::AGET_BYTE:
738      GenArrayGet(opt_flags, kSignedByte, rl_src[0], rl_src[1], rl_dest, 0);
739      break;
740    case Instruction::AGET_CHAR:
741      GenArrayGet(opt_flags, kUnsignedHalf, rl_src[0], rl_src[1], rl_dest, 1);
742      break;
743    case Instruction::AGET_SHORT:
744      GenArrayGet(opt_flags, kSignedHalf, rl_src[0], rl_src[1], rl_dest, 1);
745      break;
746    case Instruction::APUT_WIDE:
747      GenArrayPut(opt_flags, rl_src[0].fp ? kDouble : k64, rl_src[1], rl_src[2], rl_src[0], 3, false);
748      break;
749    case Instruction::APUT:
750      GenArrayPut(opt_flags, rl_src[0].fp ? kSingle : k32, rl_src[1], rl_src[2], rl_src[0], 2, false);
751      break;
752    case Instruction::APUT_OBJECT: {
753      bool is_null = mir_graph_->IsConstantNullRef(rl_src[0]);
754      bool is_safe = is_null;  // Always safe to store null.
755      if (!is_safe) {
756        // Check safety from verifier type information.
757        const DexCompilationUnit* unit = mir_graph_->GetCurrentDexCompilationUnit();
758        is_safe = cu_->compiler_driver->IsSafeCast(unit, mir->offset);
759      }
760      if (is_null || is_safe) {
761        // Store of constant null doesn't require an assignability test and can be generated inline
762        // without fixed register usage or a card mark.
763        GenArrayPut(opt_flags, kReference, rl_src[1], rl_src[2], rl_src[0], 2, !is_null);
764      } else {
765        GenArrayObjPut(opt_flags, rl_src[1], rl_src[2], rl_src[0]);
766      }
767      break;
768    }
769    case Instruction::APUT_SHORT:
770    case Instruction::APUT_CHAR:
771      GenArrayPut(opt_flags, kUnsignedHalf, rl_src[1], rl_src[2], rl_src[0], 1, false);
772      break;
773    case Instruction::APUT_BYTE:
774    case Instruction::APUT_BOOLEAN:
775      GenArrayPut(opt_flags, kUnsignedByte, rl_src[1], rl_src[2], rl_src[0], 0, false);
776      break;
777
778    case Instruction::IGET_OBJECT_QUICK:
779    case Instruction::IGET_OBJECT:
780      GenIGet(mir, opt_flags, kReference, Primitive::kPrimNot, rl_dest, rl_src[0]);
781      break;
782
783    case Instruction::IGET_WIDE_QUICK:
784    case Instruction::IGET_WIDE:
785      // kPrimLong and kPrimDouble share the same entrypoints.
786      if (rl_dest.fp) {
787        GenIGet(mir, opt_flags, kDouble, Primitive::kPrimDouble, rl_dest, rl_src[0]);
788      } else {
789        GenIGet(mir, opt_flags, k64, Primitive::kPrimLong, rl_dest, rl_src[0]);
790      }
791      break;
792
793    case Instruction::IGET_QUICK:
794    case Instruction::IGET:
795      if (rl_dest.fp) {
796        GenIGet(mir, opt_flags, kSingle, Primitive::kPrimFloat, rl_dest, rl_src[0]);
797      } else {
798        GenIGet(mir, opt_flags, k32, Primitive::kPrimInt, rl_dest, rl_src[0]);
799      }
800      break;
801
802    case Instruction::IGET_CHAR_QUICK:
803    case Instruction::IGET_CHAR:
804      GenIGet(mir, opt_flags, kUnsignedHalf, Primitive::kPrimChar, rl_dest, rl_src[0]);
805      break;
806
807    case Instruction::IGET_SHORT_QUICK:
808    case Instruction::IGET_SHORT:
809      GenIGet(mir, opt_flags, kSignedHalf, Primitive::kPrimShort, rl_dest, rl_src[0]);
810      break;
811
812    case Instruction::IGET_BOOLEAN_QUICK:
813    case Instruction::IGET_BOOLEAN:
814      GenIGet(mir, opt_flags, kUnsignedByte, Primitive::kPrimBoolean, rl_dest, rl_src[0]);
815      break;
816
817    case Instruction::IGET_BYTE_QUICK:
818    case Instruction::IGET_BYTE:
819      GenIGet(mir, opt_flags, kSignedByte, Primitive::kPrimByte, rl_dest, rl_src[0]);
820      break;
821
822    case Instruction::IPUT_WIDE_QUICK:
823    case Instruction::IPUT_WIDE:
824      GenIPut(mir, opt_flags, rl_src[0].fp ? kDouble : k64, rl_src[0], rl_src[1]);
825      break;
826
827    case Instruction::IPUT_OBJECT_QUICK:
828    case Instruction::IPUT_OBJECT:
829      GenIPut(mir, opt_flags, kReference, rl_src[0], rl_src[1]);
830      break;
831
832    case Instruction::IPUT_QUICK:
833    case Instruction::IPUT:
834      GenIPut(mir, opt_flags, rl_src[0].fp ? kSingle : k32, rl_src[0], rl_src[1]);
835      break;
836
837    case Instruction::IPUT_BYTE_QUICK:
838    case Instruction::IPUT_BOOLEAN_QUICK:
839    case Instruction::IPUT_BYTE:
840    case Instruction::IPUT_BOOLEAN:
841      GenIPut(mir, opt_flags, kUnsignedByte, rl_src[0], rl_src[1]);
842      break;
843
844    case Instruction::IPUT_CHAR_QUICK:
845    case Instruction::IPUT_CHAR:
846      GenIPut(mir, opt_flags, kUnsignedHalf, rl_src[0], rl_src[1]);
847      break;
848
849    case Instruction::IPUT_SHORT_QUICK:
850    case Instruction::IPUT_SHORT:
851      GenIPut(mir, opt_flags, kSignedHalf, rl_src[0], rl_src[1]);
852      break;
853
854    case Instruction::SGET_OBJECT:
855      GenSget(mir, rl_dest, kReference, Primitive::kPrimNot);
856      break;
857
858    case Instruction::SGET:
859      GenSget(mir, rl_dest, rl_dest.fp ? kSingle : k32, Primitive::kPrimInt);
860      break;
861
862    case Instruction::SGET_CHAR:
863      GenSget(mir, rl_dest, kUnsignedHalf, Primitive::kPrimChar);
864      break;
865
866    case Instruction::SGET_SHORT:
867      GenSget(mir, rl_dest, kSignedHalf, Primitive::kPrimShort);
868      break;
869
870    case Instruction::SGET_BOOLEAN:
871      GenSget(mir, rl_dest, kUnsignedByte, Primitive::kPrimBoolean);
872      break;
873
874    case Instruction::SGET_BYTE:
875      GenSget(mir, rl_dest, kSignedByte, Primitive::kPrimByte);
876      break;
877
878    case Instruction::SGET_WIDE:
879      // kPrimLong and kPrimDouble share the same entrypoints.
880      GenSget(mir, rl_dest, rl_dest.fp ? kDouble : k64, Primitive::kPrimDouble);
881      break;
882
883    case Instruction::SPUT_OBJECT:
884      GenSput(mir, rl_src[0], kReference);
885      break;
886
887    case Instruction::SPUT:
888      GenSput(mir, rl_src[0], rl_src[0].fp ? kSingle : k32);
889      break;
890
891    case Instruction::SPUT_BYTE:
892    case Instruction::SPUT_BOOLEAN:
893      GenSput(mir, rl_src[0], kUnsignedByte);
894      break;
895
896    case Instruction::SPUT_CHAR:
897      GenSput(mir, rl_src[0], kUnsignedHalf);
898      break;
899
900    case Instruction::SPUT_SHORT:
901      GenSput(mir, rl_src[0], kSignedHalf);
902      break;
903
904
905    case Instruction::SPUT_WIDE:
906      GenSput(mir, rl_src[0], rl_src[0].fp ? kDouble : k64);
907      break;
908
909    case Instruction::INVOKE_STATIC_RANGE:
910      GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kStatic, true));
911      break;
912    case Instruction::INVOKE_STATIC:
913      GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kStatic, false));
914      break;
915
916    case Instruction::INVOKE_DIRECT:
917      GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kDirect, false));
918      break;
919    case Instruction::INVOKE_DIRECT_RANGE:
920      GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kDirect, true));
921      break;
922
923    case Instruction::INVOKE_VIRTUAL_QUICK:
924    case Instruction::INVOKE_VIRTUAL:
925      GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kVirtual, false));
926      break;
927
928    case Instruction::INVOKE_VIRTUAL_RANGE_QUICK:
929    case Instruction::INVOKE_VIRTUAL_RANGE:
930      GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kVirtual, true));
931      break;
932
933    case Instruction::INVOKE_SUPER:
934      GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kSuper, false));
935      break;
936    case Instruction::INVOKE_SUPER_RANGE:
937      GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kSuper, true));
938      break;
939
940    case Instruction::INVOKE_INTERFACE:
941      GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kInterface, false));
942      break;
943    case Instruction::INVOKE_INTERFACE_RANGE:
944      GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kInterface, true));
945      break;
946
947    case Instruction::NEG_INT:
948    case Instruction::NOT_INT:
949      GenArithOpInt(opcode, rl_dest, rl_src[0], rl_src[0], opt_flags);
950      break;
951
952    case Instruction::NEG_LONG:
953    case Instruction::NOT_LONG:
954      GenArithOpLong(opcode, rl_dest, rl_src[0], rl_src[0], opt_flags);
955      break;
956
957    case Instruction::NEG_FLOAT:
958      GenArithOpFloat(opcode, rl_dest, rl_src[0], rl_src[0]);
959      break;
960
961    case Instruction::NEG_DOUBLE:
962      GenArithOpDouble(opcode, rl_dest, rl_src[0], rl_src[0]);
963      break;
964
965    case Instruction::INT_TO_LONG:
966      GenIntToLong(rl_dest, rl_src[0]);
967      break;
968
969    case Instruction::LONG_TO_INT:
970      GenLongToInt(rl_dest, rl_src[0]);
971      break;
972
973    case Instruction::INT_TO_BYTE:
974    case Instruction::INT_TO_SHORT:
975    case Instruction::INT_TO_CHAR:
976      GenIntNarrowing(opcode, rl_dest, rl_src[0]);
977      break;
978
979    case Instruction::INT_TO_FLOAT:
980    case Instruction::INT_TO_DOUBLE:
981    case Instruction::LONG_TO_FLOAT:
982    case Instruction::LONG_TO_DOUBLE:
983    case Instruction::FLOAT_TO_INT:
984    case Instruction::FLOAT_TO_LONG:
985    case Instruction::FLOAT_TO_DOUBLE:
986    case Instruction::DOUBLE_TO_INT:
987    case Instruction::DOUBLE_TO_LONG:
988    case Instruction::DOUBLE_TO_FLOAT:
989      GenConversion(opcode, rl_dest, rl_src[0]);
990      break;
991
992
993    case Instruction::ADD_INT:
994    case Instruction::ADD_INT_2ADDR:
995    case Instruction::MUL_INT:
996    case Instruction::MUL_INT_2ADDR:
997    case Instruction::AND_INT:
998    case Instruction::AND_INT_2ADDR:
999    case Instruction::OR_INT:
1000    case Instruction::OR_INT_2ADDR:
1001    case Instruction::XOR_INT:
1002    case Instruction::XOR_INT_2ADDR:
1003      if (rl_src[0].is_const &&
1004          InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src[0]), opcode)) {
1005        GenArithOpIntLit(opcode, rl_dest, rl_src[1],
1006                             mir_graph_->ConstantValue(rl_src[0].orig_sreg));
1007      } else if (rl_src[1].is_const &&
1008                 InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src[1]), opcode)) {
1009        GenArithOpIntLit(opcode, rl_dest, rl_src[0],
1010                             mir_graph_->ConstantValue(rl_src[1].orig_sreg));
1011      } else {
1012        GenArithOpInt(opcode, rl_dest, rl_src[0], rl_src[1], opt_flags);
1013      }
1014      break;
1015
1016    case Instruction::SUB_INT:
1017    case Instruction::SUB_INT_2ADDR:
1018    case Instruction::DIV_INT:
1019    case Instruction::DIV_INT_2ADDR:
1020    case Instruction::REM_INT:
1021    case Instruction::REM_INT_2ADDR:
1022    case Instruction::SHL_INT:
1023    case Instruction::SHL_INT_2ADDR:
1024    case Instruction::SHR_INT:
1025    case Instruction::SHR_INT_2ADDR:
1026    case Instruction::USHR_INT:
1027    case Instruction::USHR_INT_2ADDR:
1028      if (rl_src[1].is_const &&
1029          InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src[1]), opcode)) {
1030        GenArithOpIntLit(opcode, rl_dest, rl_src[0], mir_graph_->ConstantValue(rl_src[1]));
1031      } else {
1032        GenArithOpInt(opcode, rl_dest, rl_src[0], rl_src[1], opt_flags);
1033      }
1034      break;
1035
1036    case Instruction::ADD_LONG:
1037    case Instruction::SUB_LONG:
1038    case Instruction::AND_LONG:
1039    case Instruction::OR_LONG:
1040    case Instruction::XOR_LONG:
1041    case Instruction::ADD_LONG_2ADDR:
1042    case Instruction::SUB_LONG_2ADDR:
1043    case Instruction::AND_LONG_2ADDR:
1044    case Instruction::OR_LONG_2ADDR:
1045    case Instruction::XOR_LONG_2ADDR:
1046      if (rl_src[0].is_const || rl_src[1].is_const) {
1047        GenArithImmOpLong(opcode, rl_dest, rl_src[0], rl_src[1], opt_flags);
1048        break;
1049      }
1050      FALLTHROUGH_INTENDED;
1051    case Instruction::MUL_LONG:
1052    case Instruction::DIV_LONG:
1053    case Instruction::REM_LONG:
1054    case Instruction::MUL_LONG_2ADDR:
1055    case Instruction::DIV_LONG_2ADDR:
1056    case Instruction::REM_LONG_2ADDR:
1057      GenArithOpLong(opcode, rl_dest, rl_src[0], rl_src[1], opt_flags);
1058      break;
1059
1060    case Instruction::SHL_LONG:
1061    case Instruction::SHR_LONG:
1062    case Instruction::USHR_LONG:
1063    case Instruction::SHL_LONG_2ADDR:
1064    case Instruction::SHR_LONG_2ADDR:
1065    case Instruction::USHR_LONG_2ADDR:
1066      if (rl_src[1].is_const) {
1067        GenShiftImmOpLong(opcode, rl_dest, rl_src[0], rl_src[1], opt_flags);
1068      } else {
1069        GenShiftOpLong(opcode, rl_dest, rl_src[0], rl_src[1]);
1070      }
1071      break;
1072
1073    case Instruction::DIV_FLOAT:
1074    case Instruction::DIV_FLOAT_2ADDR:
1075      if (HandleEasyFloatingPointDiv(rl_dest, rl_src[0], rl_src[1])) {
1076        break;
1077      }
1078      FALLTHROUGH_INTENDED;
1079    case Instruction::ADD_FLOAT:
1080    case Instruction::SUB_FLOAT:
1081    case Instruction::MUL_FLOAT:
1082    case Instruction::REM_FLOAT:
1083    case Instruction::ADD_FLOAT_2ADDR:
1084    case Instruction::SUB_FLOAT_2ADDR:
1085    case Instruction::MUL_FLOAT_2ADDR:
1086    case Instruction::REM_FLOAT_2ADDR:
1087      GenArithOpFloat(opcode, rl_dest, rl_src[0], rl_src[1]);
1088      break;
1089
1090    case Instruction::DIV_DOUBLE:
1091    case Instruction::DIV_DOUBLE_2ADDR:
1092      if (HandleEasyFloatingPointDiv(rl_dest, rl_src[0], rl_src[1])) {
1093        break;
1094      }
1095      FALLTHROUGH_INTENDED;
1096    case Instruction::ADD_DOUBLE:
1097    case Instruction::SUB_DOUBLE:
1098    case Instruction::MUL_DOUBLE:
1099    case Instruction::REM_DOUBLE:
1100    case Instruction::ADD_DOUBLE_2ADDR:
1101    case Instruction::SUB_DOUBLE_2ADDR:
1102    case Instruction::MUL_DOUBLE_2ADDR:
1103    case Instruction::REM_DOUBLE_2ADDR:
1104      GenArithOpDouble(opcode, rl_dest, rl_src[0], rl_src[1]);
1105      break;
1106
1107    case Instruction::RSUB_INT:
1108    case Instruction::ADD_INT_LIT16:
1109    case Instruction::MUL_INT_LIT16:
1110    case Instruction::DIV_INT_LIT16:
1111    case Instruction::REM_INT_LIT16:
1112    case Instruction::AND_INT_LIT16:
1113    case Instruction::OR_INT_LIT16:
1114    case Instruction::XOR_INT_LIT16:
1115    case Instruction::ADD_INT_LIT8:
1116    case Instruction::RSUB_INT_LIT8:
1117    case Instruction::MUL_INT_LIT8:
1118    case Instruction::DIV_INT_LIT8:
1119    case Instruction::REM_INT_LIT8:
1120    case Instruction::AND_INT_LIT8:
1121    case Instruction::OR_INT_LIT8:
1122    case Instruction::XOR_INT_LIT8:
1123    case Instruction::SHL_INT_LIT8:
1124    case Instruction::SHR_INT_LIT8:
1125    case Instruction::USHR_INT_LIT8:
1126      GenArithOpIntLit(opcode, rl_dest, rl_src[0], vC);
1127      break;
1128
1129    default:
1130      LOG(FATAL) << "Unexpected opcode: " << opcode;
1131  }
1132  DCHECK(CheckCorePoolSanity());
1133}  // NOLINT(readability/fn_size)
1134
1135// Process extended MIR instructions
1136void Mir2Lir::HandleExtendedMethodMIR(BasicBlock* bb, MIR* mir) {
1137  switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) {
1138    case kMirOpCopy: {
1139      RegLocation rl_src = mir_graph_->GetSrc(mir, 0);
1140      RegLocation rl_dest = mir_graph_->GetDest(mir);
1141      StoreValue(rl_dest, rl_src);
1142      break;
1143    }
1144    case kMirOpFusedCmplFloat:
1145      if (mir_graph_->IsBackEdge(bb, bb->taken) || mir_graph_->IsBackEdge(bb, bb->fall_through)) {
1146        GenSuspendTest(mir->optimization_flags);
1147      }
1148      GenFusedFPCmpBranch(bb, mir, false /*gt bias*/, false /*double*/);
1149      break;
1150    case kMirOpFusedCmpgFloat:
1151      if (mir_graph_->IsBackEdge(bb, bb->taken) || mir_graph_->IsBackEdge(bb, bb->fall_through)) {
1152        GenSuspendTest(mir->optimization_flags);
1153      }
1154      GenFusedFPCmpBranch(bb, mir, true /*gt bias*/, false /*double*/);
1155      break;
1156    case kMirOpFusedCmplDouble:
1157      if (mir_graph_->IsBackEdge(bb, bb->taken) || mir_graph_->IsBackEdge(bb, bb->fall_through)) {
1158        GenSuspendTest(mir->optimization_flags);
1159      }
1160      GenFusedFPCmpBranch(bb, mir, false /*gt bias*/, true /*double*/);
1161      break;
1162    case kMirOpFusedCmpgDouble:
1163      if (mir_graph_->IsBackEdge(bb, bb->taken) || mir_graph_->IsBackEdge(bb, bb->fall_through)) {
1164        GenSuspendTest(mir->optimization_flags);
1165      }
1166      GenFusedFPCmpBranch(bb, mir, true /*gt bias*/, true /*double*/);
1167      break;
1168    case kMirOpFusedCmpLong:
1169      if (mir_graph_->IsBackEdge(bb, bb->taken) || mir_graph_->IsBackEdge(bb, bb->fall_through)) {
1170        GenSuspendTest(mir->optimization_flags);
1171      }
1172      GenFusedLongCmpBranch(bb, mir);
1173      break;
1174    case kMirOpSelect:
1175      GenSelect(bb, mir);
1176      break;
1177    case kMirOpNullCheck: {
1178      RegLocation rl_obj = mir_graph_->GetSrc(mir, 0);
1179      rl_obj = LoadValue(rl_obj, kRefReg);
1180      // An explicit check is done because it is not expected that when this is used,
1181      // that it will actually trip up the implicit checks (since an invalid access
1182      // is needed on the null object).
1183      GenExplicitNullCheck(rl_obj.reg, mir->optimization_flags);
1184      break;
1185    }
1186    case kMirOpPhi:
1187    case kMirOpNop:
1188    case kMirOpRangeCheck:
1189    case kMirOpDivZeroCheck:
1190    case kMirOpCheck:
1191      // Ignore these known opcodes
1192      break;
1193    default:
1194      // Give the backends a chance to handle unknown extended MIR opcodes.
1195      GenMachineSpecificExtendedMethodMIR(bb, mir);
1196      break;
1197  }
1198}
1199
1200void Mir2Lir::GenPrintLabel(MIR* mir) {
1201  // Mark the beginning of a Dalvik instruction for line tracking.
1202  if (cu_->verbose) {
1203     char* inst_str = mir_graph_->GetDalvikDisassembly(mir);
1204     MarkBoundary(mir->offset, inst_str);
1205  }
1206}
1207
1208// Handle the content in each basic block.
1209bool Mir2Lir::MethodBlockCodeGen(BasicBlock* bb) {
1210  if (bb->block_type == kDead) return false;
1211  current_dalvik_offset_ = bb->start_offset;
1212  MIR* mir;
1213  int block_id = bb->id;
1214
1215  block_label_list_[block_id].operands[0] = bb->start_offset;
1216
1217  // Insert the block label.
1218  block_label_list_[block_id].opcode = kPseudoNormalBlockLabel;
1219  block_label_list_[block_id].flags.fixup = kFixupLabel;
1220  AppendLIR(&block_label_list_[block_id]);
1221
1222  LIR* head_lir = nullptr;
1223
1224  // If this is a catch block, export the start address.
1225  if (bb->catch_entry) {
1226    head_lir = NewLIR0(kPseudoExportedPC);
1227  }
1228
1229  // Free temp registers and reset redundant store tracking.
1230  ClobberAllTemps();
1231
1232  if (bb->block_type == kEntryBlock) {
1233    ResetRegPool();
1234    int start_vreg = mir_graph_->GetFirstInVR();
1235    AppendLIR(NewLIR0(kPseudoPrologueBegin));
1236    DCHECK_EQ(cu_->target64, Is64BitInstructionSet(cu_->instruction_set));
1237    if (cu_->target64) {
1238      DCHECK(mir_graph_->GetMethodLoc().wide);
1239    }
1240    GenEntrySequence(&mir_graph_->reg_location_[start_vreg], mir_graph_->GetMethodLoc());
1241    AppendLIR(NewLIR0(kPseudoPrologueEnd));
1242    DCHECK_EQ(cfi_.GetCurrentCFAOffset(), frame_size_);
1243  } else if (bb->block_type == kExitBlock) {
1244    ResetRegPool();
1245    DCHECK_EQ(cfi_.GetCurrentCFAOffset(), frame_size_);
1246    AppendLIR(NewLIR0(kPseudoEpilogueBegin));
1247    GenExitSequence();
1248    AppendLIR(NewLIR0(kPseudoEpilogueEnd));
1249    DCHECK_EQ(cfi_.GetCurrentCFAOffset(), frame_size_);
1250  }
1251
1252  for (mir = bb->first_mir_insn; mir != nullptr; mir = mir->next) {
1253    ResetRegPool();
1254    if (cu_->disable_opt & (1 << kTrackLiveTemps)) {
1255      ClobberAllTemps();
1256      // Reset temp allocation to minimize differences when A/B testing.
1257      reg_pool_->ResetNextTemp();
1258    }
1259
1260    if (cu_->disable_opt & (1 << kSuppressLoads)) {
1261      ResetDefTracking();
1262    }
1263
1264    // Reset temp tracking sanity check.
1265    if (kIsDebugBuild) {
1266      live_sreg_ = INVALID_SREG;
1267    }
1268
1269    current_dalvik_offset_ = mir->offset;
1270    current_mir_ = mir;
1271    int opcode = mir->dalvikInsn.opcode;
1272
1273    GenPrintLabel(mir);
1274
1275    // Remember the first LIR for this block.
1276    if (head_lir == nullptr) {
1277      head_lir = &block_label_list_[bb->id];
1278      // Set the first label as a scheduling barrier.
1279      DCHECK(!head_lir->flags.use_def_invalid);
1280      head_lir->u.m.def_mask = &kEncodeAll;
1281    }
1282
1283    if (MIR::DecodedInstruction::IsPseudoMirOp(opcode)) {
1284      HandleExtendedMethodMIR(bb, mir);
1285      continue;
1286    }
1287
1288    CompileDalvikInstruction(mir, bb, block_label_list_);
1289  }
1290
1291  if (head_lir) {
1292    // Eliminate redundant loads/stores and delay stores into later slots.
1293    ApplyLocalOptimizations(head_lir, last_lir_insn_);
1294  }
1295  return false;
1296}
1297
1298bool Mir2Lir::SpecialMIR2LIR(const InlineMethod& special) {
1299  cu_->NewTimingSplit("SpecialMIR2LIR");
1300  // Find the first DalvikByteCode block.
1301  DCHECK_EQ(mir_graph_->GetNumReachableBlocks(), mir_graph_->GetDfsOrder().size());
1302  BasicBlock*bb = nullptr;
1303  for (BasicBlockId dfs_id : mir_graph_->GetDfsOrder()) {
1304    BasicBlock* candidate = mir_graph_->GetBasicBlock(dfs_id);
1305    if (candidate->block_type == kDalvikByteCode) {
1306      bb = candidate;
1307      break;
1308    }
1309  }
1310  if (bb == nullptr) {
1311    return false;
1312  }
1313  DCHECK_EQ(bb->start_offset, 0);
1314  DCHECK(bb->first_mir_insn != nullptr);
1315
1316  // Get the first instruction.
1317  MIR* mir = bb->first_mir_insn;
1318
1319  // Free temp registers and reset redundant store tracking.
1320  ResetRegPool();
1321  ResetDefTracking();
1322  ClobberAllTemps();
1323
1324  return GenSpecialCase(bb, mir, special);
1325}
1326
1327void Mir2Lir::MethodMIR2LIR() {
1328  cu_->NewTimingSplit("MIR2LIR");
1329
1330  // Hold the labels of each block.
1331  block_label_list_ = arena_->AllocArray<LIR>(mir_graph_->GetNumBlocks(), kArenaAllocLIR);
1332
1333  PreOrderDfsIterator iter(mir_graph_);
1334  BasicBlock* curr_bb = iter.Next();
1335  BasicBlock* next_bb = iter.Next();
1336  while (curr_bb != nullptr) {
1337    MethodBlockCodeGen(curr_bb);
1338    // If the fall_through block is no longer laid out consecutively, drop in a branch.
1339    BasicBlock* curr_bb_fall_through = mir_graph_->GetBasicBlock(curr_bb->fall_through);
1340    if ((curr_bb_fall_through != nullptr) && (curr_bb_fall_through != next_bb)) {
1341      OpUnconditionalBranch(&block_label_list_[curr_bb->fall_through]);
1342    }
1343    curr_bb = next_bb;
1344    do {
1345      next_bb = iter.Next();
1346    } while ((next_bb != nullptr) && (next_bb->block_type == kDead));
1347  }
1348  HandleSlowPaths();
1349}
1350
1351//
1352// LIR Slow Path
1353//
1354
1355LIR* Mir2Lir::LIRSlowPath::GenerateTargetLabel(int opcode) {
1356  m2l_->SetCurrentDexPc(current_dex_pc_);
1357  m2l_->current_mir_ = current_mir_;
1358  LIR* target = m2l_->NewLIR0(opcode);
1359  fromfast_->target = target;
1360  return target;
1361}
1362
1363
1364void Mir2Lir::CheckRegStorageImpl(RegStorage rs, WidenessCheck wide, RefCheck ref, FPCheck fp,
1365                                  bool fail, bool report)
1366    const  {
1367  if (rs.Valid()) {
1368    if (ref == RefCheck::kCheckRef) {
1369      if (cu_->target64 && !rs.Is64Bit()) {
1370        if (fail) {
1371          CHECK(false) << "Reg storage not 64b for ref.";
1372        } else if (report) {
1373          LOG(WARNING) << "Reg storage not 64b for ref.";
1374        }
1375      }
1376    }
1377    if (wide == WidenessCheck::kCheckWide) {
1378      if (!rs.Is64Bit()) {
1379        if (fail) {
1380          CHECK(false) << "Reg storage not 64b for wide.";
1381        } else if (report) {
1382          LOG(WARNING) << "Reg storage not 64b for wide.";
1383        }
1384      }
1385    }
1386    // A tighter check would be nice, but for now soft-float will not check float at all.
1387    if (fp == FPCheck::kCheckFP && cu_->instruction_set != kArm) {
1388      if (!rs.IsFloat()) {
1389        if (fail) {
1390          CHECK(false) << "Reg storage not float for fp.";
1391        } else if (report) {
1392          LOG(WARNING) << "Reg storage not float for fp.";
1393        }
1394      }
1395    } else if (fp == FPCheck::kCheckNotFP) {
1396      if (rs.IsFloat()) {
1397        if (fail) {
1398          CHECK(false) << "Reg storage float for not-fp.";
1399        } else if (report) {
1400          LOG(WARNING) << "Reg storage float for not-fp.";
1401        }
1402      }
1403    }
1404  }
1405}
1406
1407void Mir2Lir::CheckRegLocationImpl(RegLocation rl, bool fail, bool report) const {
1408  // Regrettably can't use the fp part of rl, as that is not really indicative of where a value
1409  // will be stored.
1410  CheckRegStorageImpl(rl.reg, rl.wide ? WidenessCheck::kCheckWide : WidenessCheck::kCheckNotWide,
1411      rl.ref ? RefCheck::kCheckRef : RefCheck::kCheckNotRef, FPCheck::kIgnoreFP, fail, report);
1412}
1413
1414size_t Mir2Lir::GetInstructionOffset(LIR* lir) {
1415  UNUSED(lir);
1416  UNIMPLEMENTED(FATAL) << "Unsupported GetInstructionOffset()";
1417  UNREACHABLE();
1418}
1419
1420void Mir2Lir::InToRegStorageMapping::Initialize(ShortyIterator* shorty,
1421                                                InToRegStorageMapper* mapper) {
1422  DCHECK(mapper != nullptr);
1423  DCHECK(shorty != nullptr);
1424  DCHECK(!IsInitialized());
1425  DCHECK_EQ(end_mapped_in_, 0u);
1426  DCHECK(!has_arguments_on_stack_);
1427  while (shorty->Next()) {
1428     ShortyArg arg = shorty->GetArg();
1429     RegStorage reg = mapper->GetNextReg(arg);
1430     mapping_.emplace_back(arg, reg);
1431     if (arg.IsWide()) {
1432       mapping_.emplace_back(ShortyArg(kInvalidShorty), RegStorage::InvalidReg());
1433     }
1434     if (reg.Valid()) {
1435       end_mapped_in_ = mapping_.size();
1436       // If the VR is wide but wasn't mapped as wide then account for it.
1437       if (arg.IsWide() && !reg.Is64Bit()) {
1438         --end_mapped_in_;
1439       }
1440     } else {
1441       has_arguments_on_stack_ = true;
1442     }
1443  }
1444  initialized_ = true;
1445}
1446
1447RegStorage Mir2Lir::InToRegStorageMapping::GetReg(size_t in_position) {
1448  DCHECK(IsInitialized());
1449  DCHECK_LT(in_position, mapping_.size());
1450  DCHECK_NE(mapping_[in_position].first.GetType(), kInvalidShorty);
1451  return mapping_[in_position].second;
1452}
1453
1454Mir2Lir::ShortyArg Mir2Lir::InToRegStorageMapping::GetShorty(size_t in_position) {
1455  DCHECK(IsInitialized());
1456  DCHECK_LT(static_cast<size_t>(in_position), mapping_.size());
1457  DCHECK_NE(mapping_[in_position].first.GetType(), kInvalidShorty);
1458  return mapping_[in_position].first;
1459}
1460
1461}  // namespace art
1462