mir_to_lir.cc revision a9a8254c920ce8e22210abfc16c9842ce0aea28f
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 "dex/compiler_internals.h"
18#include "dex/dataflow_iterator-inl.h"
19#include "mir_to_lir-inl.h"
20#include "object_utils.h"
21#include "thread-inl.h"
22
23namespace art {
24
25/*
26 * Target-independent code generation.  Use only high-level
27 * load/store utilities here, or target-dependent genXX() handlers
28 * when necessary.
29 */
30void Mir2Lir::CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list) {
31  RegLocation rl_src[3];
32  RegLocation rl_dest = mir_graph_->GetBadLoc();
33  RegLocation rl_result = mir_graph_->GetBadLoc();
34  Instruction::Code opcode = mir->dalvikInsn.opcode;
35  int opt_flags = mir->optimization_flags;
36  uint32_t vB = mir->dalvikInsn.vB;
37  uint32_t vC = mir->dalvikInsn.vC;
38
39  // Prep Src and Dest locations.
40  int next_sreg = 0;
41  int next_loc = 0;
42  int attrs = mir_graph_->oat_data_flow_attributes_[opcode];
43  rl_src[0] = rl_src[1] = rl_src[2] = mir_graph_->GetBadLoc();
44  if (attrs & DF_UA) {
45    if (attrs & DF_A_WIDE) {
46      rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg);
47      next_sreg+= 2;
48    } else {
49      rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg);
50      next_sreg++;
51    }
52  }
53  if (attrs & DF_UB) {
54    if (attrs & DF_B_WIDE) {
55      rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg);
56      next_sreg+= 2;
57    } else {
58      rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg);
59      next_sreg++;
60    }
61  }
62  if (attrs & DF_UC) {
63    if (attrs & DF_C_WIDE) {
64      rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg);
65    } else {
66      rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg);
67    }
68  }
69  if (attrs & DF_DA) {
70    if (attrs & DF_A_WIDE) {
71      rl_dest = mir_graph_->GetDestWide(mir);
72    } else {
73      rl_dest = mir_graph_->GetDest(mir);
74    }
75  }
76  switch (opcode) {
77    case Instruction::NOP:
78      break;
79
80    case Instruction::MOVE_EXCEPTION:
81      GenMoveException(rl_dest);
82      break;
83
84    case Instruction::RETURN_VOID:
85      if (((cu_->access_flags & kAccConstructor) != 0) &&
86          cu_->compiler_driver->RequiresConstructorBarrier(Thread::Current(), cu_->dex_file,
87                                                          cu_->class_def_idx)) {
88        GenMemBarrier(kStoreStore);
89      }
90      if (!mir_graph_->MethodIsLeaf()) {
91        GenSuspendTest(opt_flags);
92      }
93      break;
94
95    case Instruction::RETURN:
96    case Instruction::RETURN_OBJECT:
97      if (!mir_graph_->MethodIsLeaf()) {
98        GenSuspendTest(opt_flags);
99      }
100      StoreValue(GetReturn(cu_->shorty[0] == 'F'), rl_src[0]);
101      break;
102
103    case Instruction::RETURN_WIDE:
104      if (!mir_graph_->MethodIsLeaf()) {
105        GenSuspendTest(opt_flags);
106      }
107      StoreValueWide(GetReturnWide(cu_->shorty[0] == 'D'), rl_src[0]);
108      break;
109
110    case Instruction::MOVE_RESULT_WIDE:
111      if (opt_flags & MIR_INLINED)
112        break;  // Nop - combined w/ previous invoke.
113      StoreValueWide(rl_dest, GetReturnWide(rl_dest.fp));
114      break;
115
116    case Instruction::MOVE_RESULT:
117    case Instruction::MOVE_RESULT_OBJECT:
118      if (opt_flags & MIR_INLINED)
119        break;  // Nop - combined w/ previous invoke.
120      StoreValue(rl_dest, GetReturn(rl_dest.fp));
121      break;
122
123    case Instruction::MOVE:
124    case Instruction::MOVE_OBJECT:
125    case Instruction::MOVE_16:
126    case Instruction::MOVE_OBJECT_16:
127    case Instruction::MOVE_FROM16:
128    case Instruction::MOVE_OBJECT_FROM16:
129      StoreValue(rl_dest, rl_src[0]);
130      break;
131
132    case Instruction::MOVE_WIDE:
133    case Instruction::MOVE_WIDE_16:
134    case Instruction::MOVE_WIDE_FROM16:
135      StoreValueWide(rl_dest, rl_src[0]);
136      break;
137
138    case Instruction::CONST:
139    case Instruction::CONST_4:
140    case Instruction::CONST_16:
141      rl_result = EvalLoc(rl_dest, kAnyReg, true);
142      LoadConstantNoClobber(rl_result.low_reg, vB);
143      StoreValue(rl_dest, rl_result);
144      if (vB == 0) {
145        Workaround7250540(rl_dest, rl_result.low_reg);
146      }
147      break;
148
149    case Instruction::CONST_HIGH16:
150      rl_result = EvalLoc(rl_dest, kAnyReg, true);
151      LoadConstantNoClobber(rl_result.low_reg, vB << 16);
152      StoreValue(rl_dest, rl_result);
153      if (vB == 0) {
154        Workaround7250540(rl_dest, rl_result.low_reg);
155      }
156      break;
157
158    case Instruction::CONST_WIDE_16:
159    case Instruction::CONST_WIDE_32:
160      rl_result = EvalLoc(rl_dest, kAnyReg, true);
161      LoadConstantWide(rl_result.low_reg, rl_result.high_reg,
162                           static_cast<int64_t>(static_cast<int32_t>(vB)));
163      StoreValueWide(rl_dest, rl_result);
164      break;
165
166    case Instruction::CONST_WIDE:
167      rl_result = EvalLoc(rl_dest, kAnyReg, true);
168      LoadConstantWide(rl_result.low_reg, rl_result.high_reg, mir->dalvikInsn.vB_wide);
169      StoreValueWide(rl_dest, rl_result);
170      break;
171
172    case Instruction::CONST_WIDE_HIGH16:
173      rl_result = EvalLoc(rl_dest, kAnyReg, true);
174      LoadConstantWide(rl_result.low_reg, rl_result.high_reg,
175                           static_cast<int64_t>(vB) << 48);
176      StoreValueWide(rl_dest, rl_result);
177      break;
178
179    case Instruction::MONITOR_ENTER:
180      GenMonitorEnter(opt_flags, rl_src[0]);
181      break;
182
183    case Instruction::MONITOR_EXIT:
184      GenMonitorExit(opt_flags, rl_src[0]);
185      break;
186
187    case Instruction::CHECK_CAST: {
188      GenCheckCast(mir->offset, vB, rl_src[0]);
189      break;
190    }
191    case Instruction::INSTANCE_OF:
192      GenInstanceof(vC, rl_dest, rl_src[0]);
193      break;
194
195    case Instruction::NEW_INSTANCE:
196      GenNewInstance(vB, rl_dest);
197      break;
198
199    case Instruction::THROW:
200      GenThrow(rl_src[0]);
201      break;
202
203    case Instruction::ARRAY_LENGTH:
204      int len_offset;
205      len_offset = mirror::Array::LengthOffset().Int32Value();
206      rl_src[0] = LoadValue(rl_src[0], kCoreReg);
207      GenNullCheck(rl_src[0].s_reg_low, rl_src[0].low_reg, opt_flags);
208      rl_result = EvalLoc(rl_dest, kCoreReg, true);
209      LoadWordDisp(rl_src[0].low_reg, len_offset, rl_result.low_reg);
210      StoreValue(rl_dest, rl_result);
211      break;
212
213    case Instruction::CONST_STRING:
214    case Instruction::CONST_STRING_JUMBO:
215      GenConstString(vB, rl_dest);
216      break;
217
218    case Instruction::CONST_CLASS:
219      GenConstClass(vB, rl_dest);
220      break;
221
222    case Instruction::FILL_ARRAY_DATA:
223      GenFillArrayData(vB, rl_src[0]);
224      break;
225
226    case Instruction::FILLED_NEW_ARRAY:
227      GenFilledNewArray(mir_graph_->NewMemCallInfo(bb, mir, kStatic,
228                        false /* not range */));
229      break;
230
231    case Instruction::FILLED_NEW_ARRAY_RANGE:
232      GenFilledNewArray(mir_graph_->NewMemCallInfo(bb, mir, kStatic,
233                        true /* range */));
234      break;
235
236    case Instruction::NEW_ARRAY:
237      GenNewArray(vC, rl_dest, rl_src[0]);
238      break;
239
240    case Instruction::GOTO:
241    case Instruction::GOTO_16:
242    case Instruction::GOTO_32:
243      if (mir_graph_->IsBackedge(bb, bb->taken)) {
244        GenSuspendTestAndBranch(opt_flags, &label_list[bb->taken->id]);
245      } else {
246        OpUnconditionalBranch(&label_list[bb->taken->id]);
247      }
248      break;
249
250    case Instruction::PACKED_SWITCH:
251      GenPackedSwitch(mir, vB, rl_src[0]);
252      break;
253
254    case Instruction::SPARSE_SWITCH:
255      GenSparseSwitch(mir, vB, rl_src[0]);
256      break;
257
258    case Instruction::CMPL_FLOAT:
259    case Instruction::CMPG_FLOAT:
260    case Instruction::CMPL_DOUBLE:
261    case Instruction::CMPG_DOUBLE:
262      GenCmpFP(opcode, rl_dest, rl_src[0], rl_src[1]);
263      break;
264
265    case Instruction::CMP_LONG:
266      GenCmpLong(rl_dest, rl_src[0], rl_src[1]);
267      break;
268
269    case Instruction::IF_EQ:
270    case Instruction::IF_NE:
271    case Instruction::IF_LT:
272    case Instruction::IF_GE:
273    case Instruction::IF_GT:
274    case Instruction::IF_LE: {
275      LIR* taken = &label_list[bb->taken->id];
276      LIR* fall_through = &label_list[bb->fall_through->id];
277      // Result known at compile time?
278      if (rl_src[0].is_const && rl_src[1].is_const) {
279        bool is_taken = EvaluateBranch(opcode, mir_graph_->ConstantValue(rl_src[0].orig_sreg),
280                                       mir_graph_->ConstantValue(rl_src[1].orig_sreg));
281        BasicBlock* target = is_taken ? bb->taken : bb->fall_through;
282        if (mir_graph_->IsBackedge(bb, target)) {
283          GenSuspendTest(opt_flags);
284        }
285        OpUnconditionalBranch(&label_list[target->id]);
286      } else {
287        if (mir_graph_->IsBackwardsBranch(bb)) {
288          GenSuspendTest(opt_flags);
289        }
290        GenCompareAndBranch(opcode, rl_src[0], rl_src[1], taken,
291                                fall_through);
292      }
293      break;
294      }
295
296    case Instruction::IF_EQZ:
297    case Instruction::IF_NEZ:
298    case Instruction::IF_LTZ:
299    case Instruction::IF_GEZ:
300    case Instruction::IF_GTZ:
301    case Instruction::IF_LEZ: {
302      LIR* taken = &label_list[bb->taken->id];
303      LIR* fall_through = &label_list[bb->fall_through->id];
304      // Result known at compile time?
305      if (rl_src[0].is_const) {
306        bool is_taken = EvaluateBranch(opcode, mir_graph_->ConstantValue(rl_src[0].orig_sreg), 0);
307        BasicBlock* target = is_taken ? bb->taken : bb->fall_through;
308        if (mir_graph_->IsBackedge(bb, target)) {
309          GenSuspendTest(opt_flags);
310        }
311        OpUnconditionalBranch(&label_list[target->id]);
312      } else {
313        if (mir_graph_->IsBackwardsBranch(bb)) {
314          GenSuspendTest(opt_flags);
315        }
316        GenCompareZeroAndBranch(opcode, rl_src[0], taken, fall_through);
317      }
318      break;
319      }
320
321    case Instruction::AGET_WIDE:
322      GenArrayGet(opt_flags, kLong, rl_src[0], rl_src[1], rl_dest, 3);
323      break;
324    case Instruction::AGET:
325    case Instruction::AGET_OBJECT:
326      GenArrayGet(opt_flags, kWord, rl_src[0], rl_src[1], rl_dest, 2);
327      break;
328    case Instruction::AGET_BOOLEAN:
329      GenArrayGet(opt_flags, kUnsignedByte, rl_src[0], rl_src[1], rl_dest, 0);
330      break;
331    case Instruction::AGET_BYTE:
332      GenArrayGet(opt_flags, kSignedByte, rl_src[0], rl_src[1], rl_dest, 0);
333      break;
334    case Instruction::AGET_CHAR:
335      GenArrayGet(opt_flags, kUnsignedHalf, rl_src[0], rl_src[1], rl_dest, 1);
336      break;
337    case Instruction::AGET_SHORT:
338      GenArrayGet(opt_flags, kSignedHalf, rl_src[0], rl_src[1], rl_dest, 1);
339      break;
340    case Instruction::APUT_WIDE:
341      GenArrayPut(opt_flags, kLong, rl_src[1], rl_src[2], rl_src[0], 3, false);
342      break;
343    case Instruction::APUT:
344      GenArrayPut(opt_flags, kWord, rl_src[1], rl_src[2], rl_src[0], 2, false);
345      break;
346    case Instruction::APUT_OBJECT: {
347      bool is_null = mir_graph_->IsConstantNullRef(rl_src[0]);
348      bool is_safe = is_null;  // Always safe to store null.
349      if (!is_safe) {
350        // Check safety from verifier type information.
351        const MethodReference mr(cu_->dex_file, cu_->method_idx);
352        is_safe = cu_->compiler_driver->IsSafeCast(mr, mir->offset);
353      }
354      if (is_null || is_safe) {
355        // Store of constant null doesn't require an assignability test and can be generated inline
356        // without fixed register usage or a card mark.
357        GenArrayPut(opt_flags, kWord, rl_src[1], rl_src[2], rl_src[0], 2, !is_null);
358      } else {
359        GenArrayObjPut(opt_flags, rl_src[1], rl_src[2], rl_src[0]);
360      }
361      break;
362    }
363    case Instruction::APUT_SHORT:
364    case Instruction::APUT_CHAR:
365      GenArrayPut(opt_flags, kUnsignedHalf, rl_src[1], rl_src[2], rl_src[0], 1, false);
366      break;
367    case Instruction::APUT_BYTE:
368    case Instruction::APUT_BOOLEAN:
369      GenArrayPut(opt_flags, kUnsignedByte, rl_src[1], rl_src[2], rl_src[0], 0, false);
370      break;
371
372    case Instruction::IGET_OBJECT:
373      GenIGet(vC, opt_flags, kWord, rl_dest, rl_src[0], false, true);
374      break;
375
376    case Instruction::IGET_WIDE:
377      GenIGet(vC, opt_flags, kLong, rl_dest, rl_src[0], true, false);
378      break;
379
380    case Instruction::IGET:
381      GenIGet(vC, opt_flags, kWord, rl_dest, rl_src[0], false, false);
382      break;
383
384    case Instruction::IGET_CHAR:
385      GenIGet(vC, opt_flags, kUnsignedHalf, rl_dest, rl_src[0], false, false);
386      break;
387
388    case Instruction::IGET_SHORT:
389      GenIGet(vC, opt_flags, kSignedHalf, rl_dest, rl_src[0], false, false);
390      break;
391
392    case Instruction::IGET_BOOLEAN:
393    case Instruction::IGET_BYTE:
394      GenIGet(vC, opt_flags, kUnsignedByte, rl_dest, rl_src[0], false, false);
395      break;
396
397    case Instruction::IPUT_WIDE:
398      GenIPut(vC, opt_flags, kLong, rl_src[0], rl_src[1], true, false);
399      break;
400
401    case Instruction::IPUT_OBJECT:
402      GenIPut(vC, opt_flags, kWord, rl_src[0], rl_src[1], false, true);
403      break;
404
405    case Instruction::IPUT:
406      GenIPut(vC, opt_flags, kWord, rl_src[0], rl_src[1], false, false);
407      break;
408
409    case Instruction::IPUT_BOOLEAN:
410    case Instruction::IPUT_BYTE:
411      GenIPut(vC, opt_flags, kUnsignedByte, rl_src[0], rl_src[1], false, false);
412      break;
413
414    case Instruction::IPUT_CHAR:
415      GenIPut(vC, opt_flags, kUnsignedHalf, rl_src[0], rl_src[1], false, false);
416      break;
417
418    case Instruction::IPUT_SHORT:
419      GenIPut(vC, opt_flags, kSignedHalf, rl_src[0], rl_src[1], false, false);
420      break;
421
422    case Instruction::SGET_OBJECT:
423      GenSget(vB, rl_dest, false, true);
424      break;
425    case Instruction::SGET:
426    case Instruction::SGET_BOOLEAN:
427    case Instruction::SGET_BYTE:
428    case Instruction::SGET_CHAR:
429    case Instruction::SGET_SHORT:
430      GenSget(vB, rl_dest, false, false);
431      break;
432
433    case Instruction::SGET_WIDE:
434      GenSget(vB, rl_dest, true, false);
435      break;
436
437    case Instruction::SPUT_OBJECT:
438      GenSput(vB, rl_src[0], false, true);
439      break;
440
441    case Instruction::SPUT:
442    case Instruction::SPUT_BOOLEAN:
443    case Instruction::SPUT_BYTE:
444    case Instruction::SPUT_CHAR:
445    case Instruction::SPUT_SHORT:
446      GenSput(vB, rl_src[0], false, false);
447      break;
448
449    case Instruction::SPUT_WIDE:
450      GenSput(vB, rl_src[0], true, false);
451      break;
452
453    case Instruction::INVOKE_STATIC_RANGE:
454      GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kStatic, true));
455      break;
456    case Instruction::INVOKE_STATIC:
457      GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kStatic, false));
458      break;
459
460    case Instruction::INVOKE_DIRECT:
461      GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kDirect, false));
462      break;
463    case Instruction::INVOKE_DIRECT_RANGE:
464      GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kDirect, true));
465      break;
466
467    case Instruction::INVOKE_VIRTUAL:
468      GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kVirtual, false));
469      break;
470    case Instruction::INVOKE_VIRTUAL_RANGE:
471      GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kVirtual, true));
472      break;
473
474    case Instruction::INVOKE_SUPER:
475      GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kSuper, false));
476      break;
477    case Instruction::INVOKE_SUPER_RANGE:
478      GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kSuper, true));
479      break;
480
481    case Instruction::INVOKE_INTERFACE:
482      GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kInterface, false));
483      break;
484    case Instruction::INVOKE_INTERFACE_RANGE:
485      GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kInterface, true));
486      break;
487
488    case Instruction::NEG_INT:
489    case Instruction::NOT_INT:
490      GenArithOpInt(opcode, rl_dest, rl_src[0], rl_src[0]);
491      break;
492
493    case Instruction::NEG_LONG:
494    case Instruction::NOT_LONG:
495      GenArithOpLong(opcode, rl_dest, rl_src[0], rl_src[0]);
496      break;
497
498    case Instruction::NEG_FLOAT:
499      GenArithOpFloat(opcode, rl_dest, rl_src[0], rl_src[0]);
500      break;
501
502    case Instruction::NEG_DOUBLE:
503      GenArithOpDouble(opcode, rl_dest, rl_src[0], rl_src[0]);
504      break;
505
506    case Instruction::INT_TO_LONG:
507      GenIntToLong(rl_dest, rl_src[0]);
508      break;
509
510    case Instruction::LONG_TO_INT:
511      rl_src[0] = UpdateLocWide(rl_src[0]);
512      rl_src[0] = WideToNarrow(rl_src[0]);
513      StoreValue(rl_dest, rl_src[0]);
514      break;
515
516    case Instruction::INT_TO_BYTE:
517    case Instruction::INT_TO_SHORT:
518    case Instruction::INT_TO_CHAR:
519      GenIntNarrowing(opcode, rl_dest, rl_src[0]);
520      break;
521
522    case Instruction::INT_TO_FLOAT:
523    case Instruction::INT_TO_DOUBLE:
524    case Instruction::LONG_TO_FLOAT:
525    case Instruction::LONG_TO_DOUBLE:
526    case Instruction::FLOAT_TO_INT:
527    case Instruction::FLOAT_TO_LONG:
528    case Instruction::FLOAT_TO_DOUBLE:
529    case Instruction::DOUBLE_TO_INT:
530    case Instruction::DOUBLE_TO_LONG:
531    case Instruction::DOUBLE_TO_FLOAT:
532      GenConversion(opcode, rl_dest, rl_src[0]);
533      break;
534
535
536    case Instruction::ADD_INT:
537    case Instruction::ADD_INT_2ADDR:
538    case Instruction::MUL_INT:
539    case Instruction::MUL_INT_2ADDR:
540    case Instruction::AND_INT:
541    case Instruction::AND_INT_2ADDR:
542    case Instruction::OR_INT:
543    case Instruction::OR_INT_2ADDR:
544    case Instruction::XOR_INT:
545    case Instruction::XOR_INT_2ADDR:
546      if (rl_src[0].is_const &&
547          InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src[0]))) {
548        GenArithOpIntLit(opcode, rl_dest, rl_src[1],
549                             mir_graph_->ConstantValue(rl_src[0].orig_sreg));
550      } else if (rl_src[1].is_const &&
551          InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src[1]))) {
552        GenArithOpIntLit(opcode, rl_dest, rl_src[0],
553                             mir_graph_->ConstantValue(rl_src[1].orig_sreg));
554      } else {
555        GenArithOpInt(opcode, rl_dest, rl_src[0], rl_src[1]);
556      }
557      break;
558
559    case Instruction::SUB_INT:
560    case Instruction::SUB_INT_2ADDR:
561    case Instruction::DIV_INT:
562    case Instruction::DIV_INT_2ADDR:
563    case Instruction::REM_INT:
564    case Instruction::REM_INT_2ADDR:
565    case Instruction::SHL_INT:
566    case Instruction::SHL_INT_2ADDR:
567    case Instruction::SHR_INT:
568    case Instruction::SHR_INT_2ADDR:
569    case Instruction::USHR_INT:
570    case Instruction::USHR_INT_2ADDR:
571      if (rl_src[1].is_const &&
572          InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src[1]))) {
573        GenArithOpIntLit(opcode, rl_dest, rl_src[0], mir_graph_->ConstantValue(rl_src[1]));
574      } else {
575        GenArithOpInt(opcode, rl_dest, rl_src[0], rl_src[1]);
576      }
577      break;
578
579    case Instruction::ADD_LONG:
580    case Instruction::SUB_LONG:
581    case Instruction::AND_LONG:
582    case Instruction::OR_LONG:
583    case Instruction::XOR_LONG:
584    case Instruction::ADD_LONG_2ADDR:
585    case Instruction::SUB_LONG_2ADDR:
586    case Instruction::AND_LONG_2ADDR:
587    case Instruction::OR_LONG_2ADDR:
588    case Instruction::XOR_LONG_2ADDR:
589      if (rl_src[0].is_const || rl_src[1].is_const) {
590        GenArithImmOpLong(opcode, rl_dest, rl_src[0], rl_src[1]);
591        break;
592      }
593      // Note: intentional fallthrough.
594
595    case Instruction::MUL_LONG:
596    case Instruction::DIV_LONG:
597    case Instruction::REM_LONG:
598    case Instruction::MUL_LONG_2ADDR:
599    case Instruction::DIV_LONG_2ADDR:
600    case Instruction::REM_LONG_2ADDR:
601      GenArithOpLong(opcode, rl_dest, rl_src[0], rl_src[1]);
602      break;
603
604    case Instruction::SHL_LONG:
605    case Instruction::SHR_LONG:
606    case Instruction::USHR_LONG:
607    case Instruction::SHL_LONG_2ADDR:
608    case Instruction::SHR_LONG_2ADDR:
609    case Instruction::USHR_LONG_2ADDR:
610      if (rl_src[1].is_const) {
611        GenShiftImmOpLong(opcode, rl_dest, rl_src[0], rl_src[1]);
612      } else {
613        GenShiftOpLong(opcode, rl_dest, rl_src[0], rl_src[1]);
614      }
615      break;
616
617    case Instruction::ADD_FLOAT:
618    case Instruction::SUB_FLOAT:
619    case Instruction::MUL_FLOAT:
620    case Instruction::DIV_FLOAT:
621    case Instruction::REM_FLOAT:
622    case Instruction::ADD_FLOAT_2ADDR:
623    case Instruction::SUB_FLOAT_2ADDR:
624    case Instruction::MUL_FLOAT_2ADDR:
625    case Instruction::DIV_FLOAT_2ADDR:
626    case Instruction::REM_FLOAT_2ADDR:
627      GenArithOpFloat(opcode, rl_dest, rl_src[0], rl_src[1]);
628      break;
629
630    case Instruction::ADD_DOUBLE:
631    case Instruction::SUB_DOUBLE:
632    case Instruction::MUL_DOUBLE:
633    case Instruction::DIV_DOUBLE:
634    case Instruction::REM_DOUBLE:
635    case Instruction::ADD_DOUBLE_2ADDR:
636    case Instruction::SUB_DOUBLE_2ADDR:
637    case Instruction::MUL_DOUBLE_2ADDR:
638    case Instruction::DIV_DOUBLE_2ADDR:
639    case Instruction::REM_DOUBLE_2ADDR:
640      GenArithOpDouble(opcode, rl_dest, rl_src[0], rl_src[1]);
641      break;
642
643    case Instruction::RSUB_INT:
644    case Instruction::ADD_INT_LIT16:
645    case Instruction::MUL_INT_LIT16:
646    case Instruction::DIV_INT_LIT16:
647    case Instruction::REM_INT_LIT16:
648    case Instruction::AND_INT_LIT16:
649    case Instruction::OR_INT_LIT16:
650    case Instruction::XOR_INT_LIT16:
651    case Instruction::ADD_INT_LIT8:
652    case Instruction::RSUB_INT_LIT8:
653    case Instruction::MUL_INT_LIT8:
654    case Instruction::DIV_INT_LIT8:
655    case Instruction::REM_INT_LIT8:
656    case Instruction::AND_INT_LIT8:
657    case Instruction::OR_INT_LIT8:
658    case Instruction::XOR_INT_LIT8:
659    case Instruction::SHL_INT_LIT8:
660    case Instruction::SHR_INT_LIT8:
661    case Instruction::USHR_INT_LIT8:
662      GenArithOpIntLit(opcode, rl_dest, rl_src[0], vC);
663      break;
664
665    default:
666      LOG(FATAL) << "Unexpected opcode: " << opcode;
667  }
668}  // NOLINT(readability/fn_size)
669
670// Process extended MIR instructions
671void Mir2Lir::HandleExtendedMethodMIR(BasicBlock* bb, MIR* mir) {
672  switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) {
673    case kMirOpCopy: {
674      RegLocation rl_src = mir_graph_->GetSrc(mir, 0);
675      RegLocation rl_dest = mir_graph_->GetDest(mir);
676      StoreValue(rl_dest, rl_src);
677      break;
678    }
679    case kMirOpFusedCmplFloat:
680      GenFusedFPCmpBranch(bb, mir, false /*gt bias*/, false /*double*/);
681      break;
682    case kMirOpFusedCmpgFloat:
683      GenFusedFPCmpBranch(bb, mir, true /*gt bias*/, false /*double*/);
684      break;
685    case kMirOpFusedCmplDouble:
686      GenFusedFPCmpBranch(bb, mir, false /*gt bias*/, true /*double*/);
687      break;
688    case kMirOpFusedCmpgDouble:
689      GenFusedFPCmpBranch(bb, mir, true /*gt bias*/, true /*double*/);
690      break;
691    case kMirOpFusedCmpLong:
692      GenFusedLongCmpBranch(bb, mir);
693      break;
694    case kMirOpSelect:
695      GenSelect(bb, mir);
696      break;
697    default:
698      break;
699  }
700}
701
702// Handle the content in each basic block.
703bool Mir2Lir::MethodBlockCodeGen(BasicBlock* bb) {
704  if (bb->block_type == kDead) return false;
705  current_dalvik_offset_ = bb->start_offset;
706  MIR* mir;
707  int block_id = bb->id;
708
709  block_label_list_[block_id].operands[0] = bb->start_offset;
710
711  // Insert the block label.
712  block_label_list_[block_id].opcode = kPseudoNormalBlockLabel;
713  block_label_list_[block_id].flags.fixup = kFixupLabel;
714  AppendLIR(&block_label_list_[block_id]);
715
716  LIR* head_lir = NULL;
717
718  // If this is a catch block, export the start address.
719  if (bb->catch_entry) {
720    head_lir = NewLIR0(kPseudoExportedPC);
721  }
722
723  // Free temp registers and reset redundant store tracking.
724  ClobberAllRegs();
725
726  if (bb->block_type == kEntryBlock) {
727    ResetRegPool();
728    int start_vreg = cu_->num_dalvik_registers - cu_->num_ins;
729    GenEntrySequence(&mir_graph_->reg_location_[start_vreg],
730                         mir_graph_->reg_location_[mir_graph_->GetMethodSReg()]);
731  } else if (bb->block_type == kExitBlock) {
732    ResetRegPool();
733    GenExitSequence();
734  }
735
736  for (mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
737    ResetRegPool();
738    if (cu_->disable_opt & (1 << kTrackLiveTemps)) {
739      ClobberAllRegs();
740    }
741
742    if (cu_->disable_opt & (1 << kSuppressLoads)) {
743      ResetDefTracking();
744    }
745
746    // Reset temp tracking sanity check.
747    if (kIsDebugBuild) {
748      live_sreg_ = INVALID_SREG;
749    }
750
751    current_dalvik_offset_ = mir->offset;
752    int opcode = mir->dalvikInsn.opcode;
753
754    // Mark the beginning of a Dalvik instruction for line tracking.
755    if (cu_->verbose) {
756       char* inst_str = mir_graph_->GetDalvikDisassembly(mir);
757       MarkBoundary(mir->offset, inst_str);
758    }
759    // Remember the first LIR for this block.
760    if (head_lir == NULL) {
761      head_lir = &block_label_list_[bb->id];
762      // Set the first label as a scheduling barrier.
763      DCHECK(!head_lir->flags.use_def_invalid);
764      head_lir->u.m.def_mask = ENCODE_ALL;
765    }
766
767    if (opcode == kMirOpCheck) {
768      // Combine check and work halves of throwing instruction.
769      MIR* work_half = mir->meta.throw_insn;
770      mir->dalvikInsn.opcode = work_half->dalvikInsn.opcode;
771      opcode = work_half->dalvikInsn.opcode;
772      SSARepresentation* ssa_rep = work_half->ssa_rep;
773      work_half->ssa_rep = mir->ssa_rep;
774      mir->ssa_rep = ssa_rep;
775      work_half->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpCheckPart2);
776    }
777
778    if (opcode >= kMirOpFirst) {
779      HandleExtendedMethodMIR(bb, mir);
780      continue;
781    }
782
783    CompileDalvikInstruction(mir, bb, block_label_list_);
784  }
785
786  if (head_lir) {
787    // Eliminate redundant loads/stores and delay stores into later slots.
788    ApplyLocalOptimizations(head_lir, last_lir_insn_);
789  }
790  return false;
791}
792
793void Mir2Lir::SpecialMIR2LIR(SpecialCaseHandler special_case) {
794  // Find the first DalvikByteCode block.
795  int num_reachable_blocks = mir_graph_->GetNumReachableBlocks();
796  BasicBlock*bb = NULL;
797  for (int idx = 0; idx < num_reachable_blocks; idx++) {
798    // TODO: no direct access of growable lists.
799    int dfs_index = mir_graph_->GetDfsOrder()->Get(idx);
800    bb = mir_graph_->GetBasicBlock(dfs_index);
801    if (bb->block_type == kDalvikByteCode) {
802      break;
803    }
804  }
805  if (bb == NULL) {
806    return;
807  }
808  DCHECK_EQ(bb->start_offset, 0);
809  DCHECK(bb->first_mir_insn != NULL);
810
811  // Get the first instruction.
812  MIR* mir = bb->first_mir_insn;
813
814  // Free temp registers and reset redundant store tracking.
815  ResetRegPool();
816  ResetDefTracking();
817  ClobberAllRegs();
818
819  GenSpecialCase(bb, mir, special_case);
820}
821
822void Mir2Lir::MethodMIR2LIR() {
823  // Hold the labels of each block.
824  block_label_list_ =
825      static_cast<LIR*>(arena_->Alloc(sizeof(LIR) * mir_graph_->GetNumBlocks(),
826                                      ArenaAllocator::kAllocLIR));
827
828  PreOrderDfsIterator iter(mir_graph_);
829  BasicBlock* curr_bb = iter.Next();
830  BasicBlock* next_bb = iter.Next();
831  while (curr_bb != NULL) {
832    MethodBlockCodeGen(curr_bb);
833    // If the fall_through block is no longer laid out consecutively, drop in a branch.
834    if ((curr_bb->fall_through != NULL) && (curr_bb->fall_through != next_bb)) {
835      OpUnconditionalBranch(&block_label_list_[curr_bb->fall_through->id]);
836    }
837    curr_bb = next_bb;
838    do {
839      next_bb = iter.Next();
840    } while ((next_bb != NULL) && (next_bb->block_type == kDead));
841  }
842
843  HandleSuspendLaunchPads();
844
845  HandleThrowLaunchPads();
846
847  HandleIntrinsicLaunchPads();
848}
849
850}  // namespace art
851