blob: 00518bdb2f4e8938618c3a041a6a459661115f15 [file] [log] [blame]
Brian Carlstrom7940e442013-07-12 13:46:57 -07001/*
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"
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -080019#include "dex/quick/dex_file_method_inliner.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070020#include "mir_to_lir-inl.h"
21#include "object_utils.h"
Ian Rogers02ed4c02013-09-06 13:10:04 -070022#include "thread-inl.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070023
24namespace art {
25
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -080026void Mir2Lir::LockArg(int in_position, bool wide) {
27 int reg_arg_low = GetArgMappingToPhysicalReg(in_position);
28 int reg_arg_high = wide ? GetArgMappingToPhysicalReg(in_position + 1) : INVALID_REG;
29
30 if (reg_arg_low != INVALID_REG) {
31 LockTemp(reg_arg_low);
32 }
33 if (reg_arg_high != INVALID_REG && reg_arg_low != reg_arg_high) {
34 LockTemp(reg_arg_high);
35 }
36}
37
38int Mir2Lir::LoadArg(int in_position, bool wide) {
39 int reg_arg_low = GetArgMappingToPhysicalReg(in_position);
40 int reg_arg_high = wide ? GetArgMappingToPhysicalReg(in_position + 1) : INVALID_REG;
41
42 int offset = StackVisitor::GetOutVROffset(in_position);
43 if (cu_->instruction_set == kX86) {
44 /*
45 * When doing a call for x86, it moves the stack pointer in order to push return.
46 * Thus, we add another 4 bytes to figure out the out of caller (in of callee).
47 * TODO: This needs revisited for 64-bit.
48 */
49 offset += sizeof(uint32_t);
50 }
51
52 // If the VR is wide and there is no register for high part, we need to load it.
53 if (wide && reg_arg_high == INVALID_REG) {
54 // If the low part is not in a reg, we allocate a pair. Otherwise, we just load to high reg.
55 if (reg_arg_low == INVALID_REG) {
Bill Buzbee86ec5202014-02-26 19:03:09 +000056 int new_regs = AllocTypedTempPair(false, kAnyReg);
57 DECODE_REG_PAIR(new_regs, reg_arg_low, reg_arg_high);
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -080058 LoadBaseDispWide(TargetReg(kSp), offset, reg_arg_low, reg_arg_high, INVALID_SREG);
59 } else {
60 reg_arg_high = AllocTemp();
61 int offset_high = offset + sizeof(uint32_t);
62 LoadWordDisp(TargetReg(kSp), offset_high, reg_arg_high);
63 }
64 }
65
66 // If the low part is not in a register yet, we need to load it.
67 if (reg_arg_low == INVALID_REG) {
68 reg_arg_low = AllocTemp();
69 LoadWordDisp(TargetReg(kSp), offset, reg_arg_low);
70 }
71
72 if (wide) {
73 return ENCODE_REG_PAIR(reg_arg_low, reg_arg_high);
74 } else {
75 return reg_arg_low;
76 }
77}
78
79void Mir2Lir::LoadArgDirect(int in_position, RegLocation rl_dest) {
80 int offset = StackVisitor::GetOutVROffset(in_position);
81 if (cu_->instruction_set == kX86) {
82 /*
83 * When doing a call for x86, it moves the stack pointer in order to push return.
84 * Thus, we add another 4 bytes to figure out the out of caller (in of callee).
85 * TODO: This needs revisited for 64-bit.
86 */
87 offset += sizeof(uint32_t);
88 }
89
90 if (!rl_dest.wide) {
91 int reg = GetArgMappingToPhysicalReg(in_position);
92 if (reg != INVALID_REG) {
Bill Buzbee86ec5202014-02-26 19:03:09 +000093 OpRegCopy(rl_dest.low_reg, reg);
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -080094 } else {
Bill Buzbee86ec5202014-02-26 19:03:09 +000095 LoadWordDisp(TargetReg(kSp), offset, rl_dest.low_reg);
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -080096 }
97 } else {
98 int reg_arg_low = GetArgMappingToPhysicalReg(in_position);
99 int reg_arg_high = GetArgMappingToPhysicalReg(in_position + 1);
100
101 if (reg_arg_low != INVALID_REG && reg_arg_high != INVALID_REG) {
Bill Buzbee86ec5202014-02-26 19:03:09 +0000102 OpRegCopyWide(rl_dest.low_reg, rl_dest.high_reg, reg_arg_low, reg_arg_high);
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800103 } else if (reg_arg_low != INVALID_REG && reg_arg_high == INVALID_REG) {
Bill Buzbee86ec5202014-02-26 19:03:09 +0000104 OpRegCopy(rl_dest.low_reg, reg_arg_low);
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800105 int offset_high = offset + sizeof(uint32_t);
Bill Buzbee86ec5202014-02-26 19:03:09 +0000106 LoadWordDisp(TargetReg(kSp), offset_high, rl_dest.high_reg);
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800107 } else if (reg_arg_low == INVALID_REG && reg_arg_high != INVALID_REG) {
Bill Buzbee86ec5202014-02-26 19:03:09 +0000108 OpRegCopy(rl_dest.high_reg, reg_arg_high);
109 LoadWordDisp(TargetReg(kSp), offset, rl_dest.low_reg);
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800110 } else {
Bill Buzbee86ec5202014-02-26 19:03:09 +0000111 LoadBaseDispWide(TargetReg(kSp), offset, rl_dest.low_reg, rl_dest.high_reg, INVALID_SREG);
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800112 }
113 }
114}
115
116bool Mir2Lir::GenSpecialIGet(MIR* mir, const InlineMethod& special) {
117 // FastInstance() already checked by DexFileMethodInliner.
118 const InlineIGetIPutData& data = special.d.ifield_data;
119 if (data.method_is_static || data.object_arg != 0) {
120 // The object is not "this" and has to be null-checked.
121 return false;
122 }
123
124 DCHECK_NE(data.op_size, kDouble); // The inliner doesn't distinguish kDouble, uses kLong.
125 bool wide = (data.op_size == kLong);
126 bool double_or_float = cu_->shorty[0] == 'F' || cu_->shorty[0] == 'D';
127
128 // Point of no return - no aborts after this
129 GenPrintLabel(mir);
130 LockArg(data.object_arg);
131 RegLocation rl_dest = wide ? GetReturnWide(double_or_float) : GetReturn(double_or_float);
132 int reg_obj = LoadArg(data.object_arg);
133 if (wide) {
Bill Buzbee86ec5202014-02-26 19:03:09 +0000134 LoadBaseDispWide(reg_obj, data.field_offset, rl_dest.low_reg, rl_dest.high_reg, INVALID_SREG);
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800135 } else {
Bill Buzbee86ec5202014-02-26 19:03:09 +0000136 LoadBaseDisp(reg_obj, data.field_offset, rl_dest.low_reg, kWord, INVALID_SREG);
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800137 }
138 if (data.is_volatile) {
139 GenMemBarrier(kLoadLoad);
140 }
141 return true;
142}
143
144bool Mir2Lir::GenSpecialIPut(MIR* mir, const InlineMethod& special) {
145 // FastInstance() already checked by DexFileMethodInliner.
146 const InlineIGetIPutData& data = special.d.ifield_data;
147 if (data.method_is_static || data.object_arg != 0) {
148 // The object is not "this" and has to be null-checked.
149 return false;
150 }
151
152 DCHECK_NE(data.op_size, kDouble); // The inliner doesn't distinguish kDouble, uses kLong.
153 bool wide = (data.op_size == kLong);
154
155 // Point of no return - no aborts after this
156 GenPrintLabel(mir);
157 LockArg(data.object_arg);
158 LockArg(data.src_arg, wide);
159 int reg_obj = LoadArg(data.object_arg);
160 int reg_src = LoadArg(data.src_arg, wide);
161 if (data.is_volatile) {
162 GenMemBarrier(kStoreStore);
163 }
164 if (wide) {
165 int low_reg, high_reg;
166 DECODE_REG_PAIR(reg_src, low_reg, high_reg);
167 StoreBaseDispWide(reg_obj, data.field_offset, low_reg, high_reg);
168 } else {
169 StoreBaseDisp(reg_obj, data.field_offset, reg_src, kWord);
170 }
171 if (data.is_volatile) {
172 GenMemBarrier(kLoadLoad);
173 }
174 if (data.is_object) {
175 MarkGCCard(reg_src, reg_obj);
176 }
177 return true;
178}
179
180bool Mir2Lir::GenSpecialIdentity(MIR* mir, const InlineMethod& special) {
181 const InlineReturnArgData& data = special.d.return_data;
182 DCHECK_NE(data.op_size, kDouble); // The inliner doesn't distinguish kDouble, uses kLong.
183 bool wide = (data.op_size == kLong);
184 bool double_or_float = cu_->shorty[0] == 'F' || cu_->shorty[0] == 'D';
185
186 // Point of no return - no aborts after this
187 GenPrintLabel(mir);
188 LockArg(data.arg, wide);
189 RegLocation rl_dest = wide ? GetReturnWide(double_or_float) : GetReturn(double_or_float);
190 LoadArgDirect(data.arg, rl_dest);
191 return true;
192}
193
194/*
195 * Special-case code generation for simple non-throwing leaf methods.
196 */
197bool Mir2Lir::GenSpecialCase(BasicBlock* bb, MIR* mir, const InlineMethod& special) {
198 DCHECK(special.flags & kInlineSpecial);
199 current_dalvik_offset_ = mir->offset;
200 MIR* return_mir = nullptr;
201 bool successful = false;
202
203 switch (special.opcode) {
204 case kInlineOpNop:
205 successful = true;
206 DCHECK_EQ(mir->dalvikInsn.opcode, Instruction::RETURN_VOID);
207 return_mir = mir;
208 break;
209 case kInlineOpNonWideConst: {
210 successful = true;
211 RegLocation rl_dest = GetReturn(cu_->shorty[0] == 'F');
212 GenPrintLabel(mir);
Bill Buzbee86ec5202014-02-26 19:03:09 +0000213 LoadConstant(rl_dest.low_reg, static_cast<int>(special.d.data));
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800214 return_mir = mir_graph_->GetNextUnconditionalMir(bb, mir);
215 break;
216 }
217 case kInlineOpReturnArg:
218 successful = GenSpecialIdentity(mir, special);
219 return_mir = mir;
220 break;
221 case kInlineOpIGet:
222 successful = GenSpecialIGet(mir, special);
223 return_mir = mir_graph_->GetNextUnconditionalMir(bb, mir);
224 break;
225 case kInlineOpIPut:
226 successful = GenSpecialIPut(mir, special);
227 return_mir = mir_graph_->GetNextUnconditionalMir(bb, mir);
228 break;
229 default:
230 break;
231 }
232
233 if (successful) {
234 // Handle verbosity for return MIR.
235 if (return_mir != nullptr) {
236 current_dalvik_offset_ = return_mir->offset;
237 // Not handling special identity case because it already generated code as part
238 // of the return. The label should have been added before any code was generated.
239 if (special.opcode != kInlineOpReturnArg) {
240 GenPrintLabel(return_mir);
241 }
242 }
243 GenSpecialExitSequence();
244
245 core_spill_mask_ = 0;
246 num_core_spills_ = 0;
247 fp_spill_mask_ = 0;
248 num_fp_spills_ = 0;
249 frame_size_ = 0;
250 core_vmap_table_.clear();
251 fp_vmap_table_.clear();
252 }
253
254 return successful;
255}
256
Brian Carlstrom7940e442013-07-12 13:46:57 -0700257/*
258 * Target-independent code generation. Use only high-level
259 * load/store utilities here, or target-dependent genXX() handlers
260 * when necessary.
261 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700262void Mir2Lir::CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700263 RegLocation rl_src[3];
264 RegLocation rl_dest = mir_graph_->GetBadLoc();
265 RegLocation rl_result = mir_graph_->GetBadLoc();
266 Instruction::Code opcode = mir->dalvikInsn.opcode;
267 int opt_flags = mir->optimization_flags;
268 uint32_t vB = mir->dalvikInsn.vB;
269 uint32_t vC = mir->dalvikInsn.vC;
270
271 // Prep Src and Dest locations.
272 int next_sreg = 0;
273 int next_loc = 0;
buzbee1da1e2f2013-11-15 13:37:01 -0800274 uint64_t attrs = mir_graph_->oat_data_flow_attributes_[opcode];
Brian Carlstrom7940e442013-07-12 13:46:57 -0700275 rl_src[0] = rl_src[1] = rl_src[2] = mir_graph_->GetBadLoc();
276 if (attrs & DF_UA) {
277 if (attrs & DF_A_WIDE) {
278 rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg);
279 next_sreg+= 2;
280 } else {
281 rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg);
282 next_sreg++;
283 }
284 }
285 if (attrs & DF_UB) {
286 if (attrs & DF_B_WIDE) {
287 rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg);
288 next_sreg+= 2;
289 } else {
290 rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg);
291 next_sreg++;
292 }
293 }
294 if (attrs & DF_UC) {
295 if (attrs & DF_C_WIDE) {
296 rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg);
297 } else {
298 rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg);
299 }
300 }
301 if (attrs & DF_DA) {
302 if (attrs & DF_A_WIDE) {
303 rl_dest = mir_graph_->GetDestWide(mir);
304 } else {
305 rl_dest = mir_graph_->GetDest(mir);
306 }
307 }
308 switch (opcode) {
309 case Instruction::NOP:
310 break;
311
312 case Instruction::MOVE_EXCEPTION:
313 GenMoveException(rl_dest);
314 break;
315
316 case Instruction::RETURN_VOID:
317 if (((cu_->access_flags & kAccConstructor) != 0) &&
318 cu_->compiler_driver->RequiresConstructorBarrier(Thread::Current(), cu_->dex_file,
319 cu_->class_def_idx)) {
320 GenMemBarrier(kStoreStore);
321 }
322 if (!mir_graph_->MethodIsLeaf()) {
323 GenSuspendTest(opt_flags);
324 }
325 break;
326
327 case Instruction::RETURN:
328 case Instruction::RETURN_OBJECT:
329 if (!mir_graph_->MethodIsLeaf()) {
330 GenSuspendTest(opt_flags);
331 }
332 StoreValue(GetReturn(cu_->shorty[0] == 'F'), rl_src[0]);
333 break;
334
335 case Instruction::RETURN_WIDE:
336 if (!mir_graph_->MethodIsLeaf()) {
337 GenSuspendTest(opt_flags);
338 }
339 StoreValueWide(GetReturnWide(cu_->shorty[0] == 'D'), rl_src[0]);
340 break;
341
342 case Instruction::MOVE_RESULT_WIDE:
343 if (opt_flags & MIR_INLINED)
344 break; // Nop - combined w/ previous invoke.
345 StoreValueWide(rl_dest, GetReturnWide(rl_dest.fp));
346 break;
347
348 case Instruction::MOVE_RESULT:
349 case Instruction::MOVE_RESULT_OBJECT:
350 if (opt_flags & MIR_INLINED)
351 break; // Nop - combined w/ previous invoke.
352 StoreValue(rl_dest, GetReturn(rl_dest.fp));
353 break;
354
355 case Instruction::MOVE:
356 case Instruction::MOVE_OBJECT:
357 case Instruction::MOVE_16:
358 case Instruction::MOVE_OBJECT_16:
359 case Instruction::MOVE_FROM16:
360 case Instruction::MOVE_OBJECT_FROM16:
361 StoreValue(rl_dest, rl_src[0]);
362 break;
363
364 case Instruction::MOVE_WIDE:
365 case Instruction::MOVE_WIDE_16:
366 case Instruction::MOVE_WIDE_FROM16:
367 StoreValueWide(rl_dest, rl_src[0]);
368 break;
369
370 case Instruction::CONST:
371 case Instruction::CONST_4:
372 case Instruction::CONST_16:
373 rl_result = EvalLoc(rl_dest, kAnyReg, true);
Bill Buzbee86ec5202014-02-26 19:03:09 +0000374 LoadConstantNoClobber(rl_result.low_reg, vB);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700375 StoreValue(rl_dest, rl_result);
376 if (vB == 0) {
Bill Buzbee86ec5202014-02-26 19:03:09 +0000377 Workaround7250540(rl_dest, rl_result.low_reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700378 }
379 break;
380
381 case Instruction::CONST_HIGH16:
382 rl_result = EvalLoc(rl_dest, kAnyReg, true);
Bill Buzbee86ec5202014-02-26 19:03:09 +0000383 LoadConstantNoClobber(rl_result.low_reg, vB << 16);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700384 StoreValue(rl_dest, rl_result);
385 if (vB == 0) {
Bill Buzbee86ec5202014-02-26 19:03:09 +0000386 Workaround7250540(rl_dest, rl_result.low_reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700387 }
388 break;
389
390 case Instruction::CONST_WIDE_16:
391 case Instruction::CONST_WIDE_32:
Bill Buzbeed61ba4b2014-01-13 21:44:01 +0000392 GenConstWide(rl_dest, static_cast<int64_t>(static_cast<int32_t>(vB)));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700393 break;
394
395 case Instruction::CONST_WIDE:
Bill Buzbeed61ba4b2014-01-13 21:44:01 +0000396 GenConstWide(rl_dest, mir->dalvikInsn.vB_wide);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700397 break;
398
399 case Instruction::CONST_WIDE_HIGH16:
400 rl_result = EvalLoc(rl_dest, kAnyReg, true);
Bill Buzbee86ec5202014-02-26 19:03:09 +0000401 LoadConstantWide(rl_result.low_reg, rl_result.high_reg,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700402 static_cast<int64_t>(vB) << 48);
403 StoreValueWide(rl_dest, rl_result);
404 break;
405
406 case Instruction::MONITOR_ENTER:
407 GenMonitorEnter(opt_flags, rl_src[0]);
408 break;
409
410 case Instruction::MONITOR_EXIT:
411 GenMonitorExit(opt_flags, rl_src[0]);
412 break;
413
414 case Instruction::CHECK_CAST: {
415 GenCheckCast(mir->offset, vB, rl_src[0]);
416 break;
417 }
418 case Instruction::INSTANCE_OF:
419 GenInstanceof(vC, rl_dest, rl_src[0]);
420 break;
421
422 case Instruction::NEW_INSTANCE:
423 GenNewInstance(vB, rl_dest);
424 break;
425
426 case Instruction::THROW:
427 GenThrow(rl_src[0]);
428 break;
429
430 case Instruction::ARRAY_LENGTH:
431 int len_offset;
432 len_offset = mirror::Array::LengthOffset().Int32Value();
433 rl_src[0] = LoadValue(rl_src[0], kCoreReg);
Bill Buzbee86ec5202014-02-26 19:03:09 +0000434 GenNullCheck(rl_src[0].s_reg_low, rl_src[0].low_reg, opt_flags);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700435 rl_result = EvalLoc(rl_dest, kCoreReg, true);
Bill Buzbee86ec5202014-02-26 19:03:09 +0000436 LoadWordDisp(rl_src[0].low_reg, len_offset, rl_result.low_reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700437 StoreValue(rl_dest, rl_result);
438 break;
439
440 case Instruction::CONST_STRING:
441 case Instruction::CONST_STRING_JUMBO:
442 GenConstString(vB, rl_dest);
443 break;
444
445 case Instruction::CONST_CLASS:
446 GenConstClass(vB, rl_dest);
447 break;
448
449 case Instruction::FILL_ARRAY_DATA:
450 GenFillArrayData(vB, rl_src[0]);
451 break;
452
453 case Instruction::FILLED_NEW_ARRAY:
454 GenFilledNewArray(mir_graph_->NewMemCallInfo(bb, mir, kStatic,
455 false /* not range */));
456 break;
457
458 case Instruction::FILLED_NEW_ARRAY_RANGE:
459 GenFilledNewArray(mir_graph_->NewMemCallInfo(bb, mir, kStatic,
460 true /* range */));
461 break;
462
463 case Instruction::NEW_ARRAY:
464 GenNewArray(vC, rl_dest, rl_src[0]);
465 break;
466
467 case Instruction::GOTO:
468 case Instruction::GOTO_16:
469 case Instruction::GOTO_32:
buzbee9329e6d2013-08-19 12:55:10 -0700470 if (mir_graph_->IsBackedge(bb, bb->taken)) {
buzbee0d829482013-10-11 15:24:55 -0700471 GenSuspendTestAndBranch(opt_flags, &label_list[bb->taken]);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700472 } else {
buzbee0d829482013-10-11 15:24:55 -0700473 OpUnconditionalBranch(&label_list[bb->taken]);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700474 }
475 break;
476
477 case Instruction::PACKED_SWITCH:
478 GenPackedSwitch(mir, vB, rl_src[0]);
479 break;
480
481 case Instruction::SPARSE_SWITCH:
482 GenSparseSwitch(mir, vB, rl_src[0]);
483 break;
484
485 case Instruction::CMPL_FLOAT:
486 case Instruction::CMPG_FLOAT:
487 case Instruction::CMPL_DOUBLE:
488 case Instruction::CMPG_DOUBLE:
489 GenCmpFP(opcode, rl_dest, rl_src[0], rl_src[1]);
490 break;
491
492 case Instruction::CMP_LONG:
493 GenCmpLong(rl_dest, rl_src[0], rl_src[1]);
494 break;
495
496 case Instruction::IF_EQ:
497 case Instruction::IF_NE:
498 case Instruction::IF_LT:
499 case Instruction::IF_GE:
500 case Instruction::IF_GT:
501 case Instruction::IF_LE: {
buzbee0d829482013-10-11 15:24:55 -0700502 LIR* taken = &label_list[bb->taken];
503 LIR* fall_through = &label_list[bb->fall_through];
Brian Carlstrom7940e442013-07-12 13:46:57 -0700504 // Result known at compile time?
505 if (rl_src[0].is_const && rl_src[1].is_const) {
506 bool is_taken = EvaluateBranch(opcode, mir_graph_->ConstantValue(rl_src[0].orig_sreg),
507 mir_graph_->ConstantValue(rl_src[1].orig_sreg));
buzbee0d829482013-10-11 15:24:55 -0700508 BasicBlockId target_id = is_taken ? bb->taken : bb->fall_through;
509 if (mir_graph_->IsBackedge(bb, target_id)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700510 GenSuspendTest(opt_flags);
511 }
buzbee0d829482013-10-11 15:24:55 -0700512 OpUnconditionalBranch(&label_list[target_id]);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700513 } else {
buzbee9329e6d2013-08-19 12:55:10 -0700514 if (mir_graph_->IsBackwardsBranch(bb)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700515 GenSuspendTest(opt_flags);
516 }
buzbee0d829482013-10-11 15:24:55 -0700517 GenCompareAndBranch(opcode, rl_src[0], rl_src[1], taken, fall_through);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700518 }
519 break;
520 }
521
522 case Instruction::IF_EQZ:
523 case Instruction::IF_NEZ:
524 case Instruction::IF_LTZ:
525 case Instruction::IF_GEZ:
526 case Instruction::IF_GTZ:
527 case Instruction::IF_LEZ: {
buzbee0d829482013-10-11 15:24:55 -0700528 LIR* taken = &label_list[bb->taken];
529 LIR* fall_through = &label_list[bb->fall_through];
Brian Carlstrom7940e442013-07-12 13:46:57 -0700530 // Result known at compile time?
531 if (rl_src[0].is_const) {
532 bool is_taken = EvaluateBranch(opcode, mir_graph_->ConstantValue(rl_src[0].orig_sreg), 0);
buzbee0d829482013-10-11 15:24:55 -0700533 BasicBlockId target_id = is_taken ? bb->taken : bb->fall_through;
534 if (mir_graph_->IsBackedge(bb, target_id)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700535 GenSuspendTest(opt_flags);
536 }
buzbee0d829482013-10-11 15:24:55 -0700537 OpUnconditionalBranch(&label_list[target_id]);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700538 } else {
buzbee9329e6d2013-08-19 12:55:10 -0700539 if (mir_graph_->IsBackwardsBranch(bb)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700540 GenSuspendTest(opt_flags);
541 }
542 GenCompareZeroAndBranch(opcode, rl_src[0], taken, fall_through);
543 }
544 break;
545 }
546
547 case Instruction::AGET_WIDE:
548 GenArrayGet(opt_flags, kLong, rl_src[0], rl_src[1], rl_dest, 3);
549 break;
550 case Instruction::AGET:
551 case Instruction::AGET_OBJECT:
552 GenArrayGet(opt_flags, kWord, rl_src[0], rl_src[1], rl_dest, 2);
553 break;
554 case Instruction::AGET_BOOLEAN:
555 GenArrayGet(opt_flags, kUnsignedByte, rl_src[0], rl_src[1], rl_dest, 0);
556 break;
557 case Instruction::AGET_BYTE:
558 GenArrayGet(opt_flags, kSignedByte, rl_src[0], rl_src[1], rl_dest, 0);
559 break;
560 case Instruction::AGET_CHAR:
561 GenArrayGet(opt_flags, kUnsignedHalf, rl_src[0], rl_src[1], rl_dest, 1);
562 break;
563 case Instruction::AGET_SHORT:
564 GenArrayGet(opt_flags, kSignedHalf, rl_src[0], rl_src[1], rl_dest, 1);
565 break;
566 case Instruction::APUT_WIDE:
Ian Rogersa9a82542013-10-04 11:17:26 -0700567 GenArrayPut(opt_flags, kLong, rl_src[1], rl_src[2], rl_src[0], 3, false);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700568 break;
569 case Instruction::APUT:
Ian Rogersa9a82542013-10-04 11:17:26 -0700570 GenArrayPut(opt_flags, kWord, rl_src[1], rl_src[2], rl_src[0], 2, false);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700571 break;
Ian Rogersa9a82542013-10-04 11:17:26 -0700572 case Instruction::APUT_OBJECT: {
573 bool is_null = mir_graph_->IsConstantNullRef(rl_src[0]);
574 bool is_safe = is_null; // Always safe to store null.
575 if (!is_safe) {
576 // Check safety from verifier type information.
Vladimir Marko2730db02014-01-27 11:15:17 +0000577 const DexCompilationUnit* unit = mir_graph_->GetCurrentDexCompilationUnit();
578 is_safe = cu_->compiler_driver->IsSafeCast(unit, mir->offset);
Ian Rogersa9a82542013-10-04 11:17:26 -0700579 }
580 if (is_null || is_safe) {
581 // Store of constant null doesn't require an assignability test and can be generated inline
582 // without fixed register usage or a card mark.
583 GenArrayPut(opt_flags, kWord, rl_src[1], rl_src[2], rl_src[0], 2, !is_null);
584 } else {
585 GenArrayObjPut(opt_flags, rl_src[1], rl_src[2], rl_src[0]);
586 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700587 break;
Ian Rogersa9a82542013-10-04 11:17:26 -0700588 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700589 case Instruction::APUT_SHORT:
590 case Instruction::APUT_CHAR:
Ian Rogersa9a82542013-10-04 11:17:26 -0700591 GenArrayPut(opt_flags, kUnsignedHalf, rl_src[1], rl_src[2], rl_src[0], 1, false);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700592 break;
593 case Instruction::APUT_BYTE:
594 case Instruction::APUT_BOOLEAN:
Ian Rogersa9a82542013-10-04 11:17:26 -0700595 GenArrayPut(opt_flags, kUnsignedByte, rl_src[1], rl_src[2], rl_src[0], 0, false);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700596 break;
597
598 case Instruction::IGET_OBJECT:
Vladimir Markobe0e5462014-02-26 11:24:15 +0000599 GenIGet(mir, opt_flags, kWord, rl_dest, rl_src[0], false, true);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700600 break;
601
602 case Instruction::IGET_WIDE:
Vladimir Markobe0e5462014-02-26 11:24:15 +0000603 GenIGet(mir, opt_flags, kLong, rl_dest, rl_src[0], true, false);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700604 break;
605
606 case Instruction::IGET:
Vladimir Markobe0e5462014-02-26 11:24:15 +0000607 GenIGet(mir, opt_flags, kWord, rl_dest, rl_src[0], false, false);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700608 break;
609
610 case Instruction::IGET_CHAR:
Vladimir Markobe0e5462014-02-26 11:24:15 +0000611 GenIGet(mir, opt_flags, kUnsignedHalf, rl_dest, rl_src[0], false, false);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700612 break;
613
614 case Instruction::IGET_SHORT:
Vladimir Markobe0e5462014-02-26 11:24:15 +0000615 GenIGet(mir, opt_flags, kSignedHalf, rl_dest, rl_src[0], false, false);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700616 break;
617
618 case Instruction::IGET_BOOLEAN:
619 case Instruction::IGET_BYTE:
Vladimir Markobe0e5462014-02-26 11:24:15 +0000620 GenIGet(mir, opt_flags, kUnsignedByte, rl_dest, rl_src[0], false, false);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700621 break;
622
623 case Instruction::IPUT_WIDE:
Vladimir Markobe0e5462014-02-26 11:24:15 +0000624 GenIPut(mir, opt_flags, kLong, rl_src[0], rl_src[1], true, false);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700625 break;
626
627 case Instruction::IPUT_OBJECT:
Vladimir Markobe0e5462014-02-26 11:24:15 +0000628 GenIPut(mir, opt_flags, kWord, rl_src[0], rl_src[1], false, true);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700629 break;
630
631 case Instruction::IPUT:
Vladimir Markobe0e5462014-02-26 11:24:15 +0000632 GenIPut(mir, opt_flags, kWord, rl_src[0], rl_src[1], false, false);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700633 break;
634
635 case Instruction::IPUT_BOOLEAN:
636 case Instruction::IPUT_BYTE:
Vladimir Markobe0e5462014-02-26 11:24:15 +0000637 GenIPut(mir, opt_flags, kUnsignedByte, rl_src[0], rl_src[1], false, false);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700638 break;
639
640 case Instruction::IPUT_CHAR:
Vladimir Markobe0e5462014-02-26 11:24:15 +0000641 GenIPut(mir, opt_flags, kUnsignedHalf, rl_src[0], rl_src[1], false, false);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700642 break;
643
644 case Instruction::IPUT_SHORT:
Vladimir Markobe0e5462014-02-26 11:24:15 +0000645 GenIPut(mir, opt_flags, kSignedHalf, rl_src[0], rl_src[1], false, false);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700646 break;
647
648 case Instruction::SGET_OBJECT:
Vladimir Markobe0e5462014-02-26 11:24:15 +0000649 GenSget(mir, rl_dest, false, true);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700650 break;
651 case Instruction::SGET:
652 case Instruction::SGET_BOOLEAN:
653 case Instruction::SGET_BYTE:
654 case Instruction::SGET_CHAR:
655 case Instruction::SGET_SHORT:
Vladimir Markobe0e5462014-02-26 11:24:15 +0000656 GenSget(mir, rl_dest, false, false);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700657 break;
658
659 case Instruction::SGET_WIDE:
Vladimir Markobe0e5462014-02-26 11:24:15 +0000660 GenSget(mir, rl_dest, true, false);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700661 break;
662
663 case Instruction::SPUT_OBJECT:
Vladimir Markobe0e5462014-02-26 11:24:15 +0000664 GenSput(mir, rl_src[0], false, true);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700665 break;
666
667 case Instruction::SPUT:
668 case Instruction::SPUT_BOOLEAN:
669 case Instruction::SPUT_BYTE:
670 case Instruction::SPUT_CHAR:
671 case Instruction::SPUT_SHORT:
Vladimir Markobe0e5462014-02-26 11:24:15 +0000672 GenSput(mir, rl_src[0], false, false);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700673 break;
674
675 case Instruction::SPUT_WIDE:
Vladimir Markobe0e5462014-02-26 11:24:15 +0000676 GenSput(mir, rl_src[0], true, false);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700677 break;
678
679 case Instruction::INVOKE_STATIC_RANGE:
680 GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kStatic, true));
681 break;
682 case Instruction::INVOKE_STATIC:
683 GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kStatic, false));
684 break;
685
686 case Instruction::INVOKE_DIRECT:
687 GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kDirect, false));
688 break;
689 case Instruction::INVOKE_DIRECT_RANGE:
690 GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kDirect, true));
691 break;
692
693 case Instruction::INVOKE_VIRTUAL:
694 GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kVirtual, false));
695 break;
696 case Instruction::INVOKE_VIRTUAL_RANGE:
697 GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kVirtual, true));
698 break;
699
700 case Instruction::INVOKE_SUPER:
701 GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kSuper, false));
702 break;
703 case Instruction::INVOKE_SUPER_RANGE:
704 GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kSuper, true));
705 break;
706
707 case Instruction::INVOKE_INTERFACE:
708 GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kInterface, false));
709 break;
710 case Instruction::INVOKE_INTERFACE_RANGE:
711 GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kInterface, true));
712 break;
713
714 case Instruction::NEG_INT:
715 case Instruction::NOT_INT:
716 GenArithOpInt(opcode, rl_dest, rl_src[0], rl_src[0]);
717 break;
718
719 case Instruction::NEG_LONG:
720 case Instruction::NOT_LONG:
721 GenArithOpLong(opcode, rl_dest, rl_src[0], rl_src[0]);
722 break;
723
724 case Instruction::NEG_FLOAT:
725 GenArithOpFloat(opcode, rl_dest, rl_src[0], rl_src[0]);
726 break;
727
728 case Instruction::NEG_DOUBLE:
729 GenArithOpDouble(opcode, rl_dest, rl_src[0], rl_src[0]);
730 break;
731
732 case Instruction::INT_TO_LONG:
733 GenIntToLong(rl_dest, rl_src[0]);
734 break;
735
736 case Instruction::LONG_TO_INT:
737 rl_src[0] = UpdateLocWide(rl_src[0]);
738 rl_src[0] = WideToNarrow(rl_src[0]);
739 StoreValue(rl_dest, rl_src[0]);
740 break;
741
742 case Instruction::INT_TO_BYTE:
743 case Instruction::INT_TO_SHORT:
744 case Instruction::INT_TO_CHAR:
745 GenIntNarrowing(opcode, rl_dest, rl_src[0]);
746 break;
747
748 case Instruction::INT_TO_FLOAT:
749 case Instruction::INT_TO_DOUBLE:
750 case Instruction::LONG_TO_FLOAT:
751 case Instruction::LONG_TO_DOUBLE:
752 case Instruction::FLOAT_TO_INT:
753 case Instruction::FLOAT_TO_LONG:
754 case Instruction::FLOAT_TO_DOUBLE:
755 case Instruction::DOUBLE_TO_INT:
756 case Instruction::DOUBLE_TO_LONG:
757 case Instruction::DOUBLE_TO_FLOAT:
758 GenConversion(opcode, rl_dest, rl_src[0]);
759 break;
760
761
762 case Instruction::ADD_INT:
763 case Instruction::ADD_INT_2ADDR:
764 case Instruction::MUL_INT:
765 case Instruction::MUL_INT_2ADDR:
766 case Instruction::AND_INT:
767 case Instruction::AND_INT_2ADDR:
768 case Instruction::OR_INT:
769 case Instruction::OR_INT_2ADDR:
770 case Instruction::XOR_INT:
771 case Instruction::XOR_INT_2ADDR:
772 if (rl_src[0].is_const &&
773 InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src[0]))) {
774 GenArithOpIntLit(opcode, rl_dest, rl_src[1],
775 mir_graph_->ConstantValue(rl_src[0].orig_sreg));
776 } else if (rl_src[1].is_const &&
777 InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src[1]))) {
778 GenArithOpIntLit(opcode, rl_dest, rl_src[0],
779 mir_graph_->ConstantValue(rl_src[1].orig_sreg));
780 } else {
781 GenArithOpInt(opcode, rl_dest, rl_src[0], rl_src[1]);
782 }
783 break;
784
785 case Instruction::SUB_INT:
786 case Instruction::SUB_INT_2ADDR:
787 case Instruction::DIV_INT:
788 case Instruction::DIV_INT_2ADDR:
789 case Instruction::REM_INT:
790 case Instruction::REM_INT_2ADDR:
791 case Instruction::SHL_INT:
792 case Instruction::SHL_INT_2ADDR:
793 case Instruction::SHR_INT:
794 case Instruction::SHR_INT_2ADDR:
795 case Instruction::USHR_INT:
796 case Instruction::USHR_INT_2ADDR:
797 if (rl_src[1].is_const &&
798 InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src[1]))) {
799 GenArithOpIntLit(opcode, rl_dest, rl_src[0], mir_graph_->ConstantValue(rl_src[1]));
800 } else {
801 GenArithOpInt(opcode, rl_dest, rl_src[0], rl_src[1]);
802 }
803 break;
804
805 case Instruction::ADD_LONG:
806 case Instruction::SUB_LONG:
807 case Instruction::AND_LONG:
808 case Instruction::OR_LONG:
809 case Instruction::XOR_LONG:
810 case Instruction::ADD_LONG_2ADDR:
811 case Instruction::SUB_LONG_2ADDR:
812 case Instruction::AND_LONG_2ADDR:
813 case Instruction::OR_LONG_2ADDR:
814 case Instruction::XOR_LONG_2ADDR:
815 if (rl_src[0].is_const || rl_src[1].is_const) {
816 GenArithImmOpLong(opcode, rl_dest, rl_src[0], rl_src[1]);
817 break;
818 }
819 // Note: intentional fallthrough.
820
821 case Instruction::MUL_LONG:
822 case Instruction::DIV_LONG:
823 case Instruction::REM_LONG:
824 case Instruction::MUL_LONG_2ADDR:
825 case Instruction::DIV_LONG_2ADDR:
826 case Instruction::REM_LONG_2ADDR:
827 GenArithOpLong(opcode, rl_dest, rl_src[0], rl_src[1]);
828 break;
829
830 case Instruction::SHL_LONG:
831 case Instruction::SHR_LONG:
832 case Instruction::USHR_LONG:
833 case Instruction::SHL_LONG_2ADDR:
834 case Instruction::SHR_LONG_2ADDR:
835 case Instruction::USHR_LONG_2ADDR:
836 if (rl_src[1].is_const) {
837 GenShiftImmOpLong(opcode, rl_dest, rl_src[0], rl_src[1]);
838 } else {
839 GenShiftOpLong(opcode, rl_dest, rl_src[0], rl_src[1]);
840 }
841 break;
842
843 case Instruction::ADD_FLOAT:
844 case Instruction::SUB_FLOAT:
845 case Instruction::MUL_FLOAT:
846 case Instruction::DIV_FLOAT:
847 case Instruction::REM_FLOAT:
848 case Instruction::ADD_FLOAT_2ADDR:
849 case Instruction::SUB_FLOAT_2ADDR:
850 case Instruction::MUL_FLOAT_2ADDR:
851 case Instruction::DIV_FLOAT_2ADDR:
852 case Instruction::REM_FLOAT_2ADDR:
853 GenArithOpFloat(opcode, rl_dest, rl_src[0], rl_src[1]);
854 break;
855
856 case Instruction::ADD_DOUBLE:
857 case Instruction::SUB_DOUBLE:
858 case Instruction::MUL_DOUBLE:
859 case Instruction::DIV_DOUBLE:
860 case Instruction::REM_DOUBLE:
861 case Instruction::ADD_DOUBLE_2ADDR:
862 case Instruction::SUB_DOUBLE_2ADDR:
863 case Instruction::MUL_DOUBLE_2ADDR:
864 case Instruction::DIV_DOUBLE_2ADDR:
865 case Instruction::REM_DOUBLE_2ADDR:
866 GenArithOpDouble(opcode, rl_dest, rl_src[0], rl_src[1]);
867 break;
868
869 case Instruction::RSUB_INT:
870 case Instruction::ADD_INT_LIT16:
871 case Instruction::MUL_INT_LIT16:
872 case Instruction::DIV_INT_LIT16:
873 case Instruction::REM_INT_LIT16:
874 case Instruction::AND_INT_LIT16:
875 case Instruction::OR_INT_LIT16:
876 case Instruction::XOR_INT_LIT16:
877 case Instruction::ADD_INT_LIT8:
878 case Instruction::RSUB_INT_LIT8:
879 case Instruction::MUL_INT_LIT8:
880 case Instruction::DIV_INT_LIT8:
881 case Instruction::REM_INT_LIT8:
882 case Instruction::AND_INT_LIT8:
883 case Instruction::OR_INT_LIT8:
884 case Instruction::XOR_INT_LIT8:
885 case Instruction::SHL_INT_LIT8:
886 case Instruction::SHR_INT_LIT8:
887 case Instruction::USHR_INT_LIT8:
888 GenArithOpIntLit(opcode, rl_dest, rl_src[0], vC);
889 break;
890
891 default:
892 LOG(FATAL) << "Unexpected opcode: " << opcode;
893 }
Brian Carlstrom1895ea32013-07-18 13:28:37 -0700894} // NOLINT(readability/fn_size)
Brian Carlstrom7940e442013-07-12 13:46:57 -0700895
896// Process extended MIR instructions
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700897void Mir2Lir::HandleExtendedMethodMIR(BasicBlock* bb, MIR* mir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700898 switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) {
899 case kMirOpCopy: {
900 RegLocation rl_src = mir_graph_->GetSrc(mir, 0);
901 RegLocation rl_dest = mir_graph_->GetDest(mir);
902 StoreValue(rl_dest, rl_src);
903 break;
904 }
905 case kMirOpFusedCmplFloat:
906 GenFusedFPCmpBranch(bb, mir, false /*gt bias*/, false /*double*/);
907 break;
908 case kMirOpFusedCmpgFloat:
909 GenFusedFPCmpBranch(bb, mir, true /*gt bias*/, false /*double*/);
910 break;
911 case kMirOpFusedCmplDouble:
912 GenFusedFPCmpBranch(bb, mir, false /*gt bias*/, true /*double*/);
913 break;
914 case kMirOpFusedCmpgDouble:
915 GenFusedFPCmpBranch(bb, mir, true /*gt bias*/, true /*double*/);
916 break;
917 case kMirOpFusedCmpLong:
918 GenFusedLongCmpBranch(bb, mir);
919 break;
920 case kMirOpSelect:
921 GenSelect(bb, mir);
922 break;
923 default:
924 break;
925 }
926}
927
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800928void Mir2Lir::GenPrintLabel(MIR* mir) {
929 // Mark the beginning of a Dalvik instruction for line tracking.
930 if (cu_->verbose) {
931 char* inst_str = mir_graph_->GetDalvikDisassembly(mir);
932 MarkBoundary(mir->offset, inst_str);
933 }
934}
935
Brian Carlstrom7940e442013-07-12 13:46:57 -0700936// Handle the content in each basic block.
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700937bool Mir2Lir::MethodBlockCodeGen(BasicBlock* bb) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700938 if (bb->block_type == kDead) return false;
939 current_dalvik_offset_ = bb->start_offset;
940 MIR* mir;
941 int block_id = bb->id;
942
943 block_label_list_[block_id].operands[0] = bb->start_offset;
944
945 // Insert the block label.
946 block_label_list_[block_id].opcode = kPseudoNormalBlockLabel;
buzbeeb48819d2013-09-14 16:15:25 -0700947 block_label_list_[block_id].flags.fixup = kFixupLabel;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700948 AppendLIR(&block_label_list_[block_id]);
949
950 LIR* head_lir = NULL;
951
952 // If this is a catch block, export the start address.
953 if (bb->catch_entry) {
954 head_lir = NewLIR0(kPseudoExportedPC);
955 }
956
957 // Free temp registers and reset redundant store tracking.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700958 ClobberAllRegs();
959
960 if (bb->block_type == kEntryBlock) {
buzbee56c71782013-09-05 17:13:19 -0700961 ResetRegPool();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700962 int start_vreg = cu_->num_dalvik_registers - cu_->num_ins;
963 GenEntrySequence(&mir_graph_->reg_location_[start_vreg],
964 mir_graph_->reg_location_[mir_graph_->GetMethodSReg()]);
965 } else if (bb->block_type == kExitBlock) {
buzbee56c71782013-09-05 17:13:19 -0700966 ResetRegPool();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700967 GenExitSequence();
968 }
969
970 for (mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
971 ResetRegPool();
972 if (cu_->disable_opt & (1 << kTrackLiveTemps)) {
973 ClobberAllRegs();
974 }
975
976 if (cu_->disable_opt & (1 << kSuppressLoads)) {
977 ResetDefTracking();
978 }
979
980 // Reset temp tracking sanity check.
981 if (kIsDebugBuild) {
982 live_sreg_ = INVALID_SREG;
983 }
984
985 current_dalvik_offset_ = mir->offset;
986 int opcode = mir->dalvikInsn.opcode;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700987
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800988 GenPrintLabel(mir);
989
Brian Carlstrom7940e442013-07-12 13:46:57 -0700990 // Remember the first LIR for this block.
991 if (head_lir == NULL) {
buzbee252254b2013-09-08 16:20:53 -0700992 head_lir = &block_label_list_[bb->id];
993 // Set the first label as a scheduling barrier.
buzbeeb48819d2013-09-14 16:15:25 -0700994 DCHECK(!head_lir->flags.use_def_invalid);
995 head_lir->u.m.def_mask = ENCODE_ALL;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700996 }
997
998 if (opcode == kMirOpCheck) {
999 // Combine check and work halves of throwing instruction.
1000 MIR* work_half = mir->meta.throw_insn;
1001 mir->dalvikInsn.opcode = work_half->dalvikInsn.opcode;
Vladimir Marko4376c872014-01-23 12:39:29 +00001002 mir->meta = work_half->meta; // Whatever the work_half had, we need to copy it.
Brian Carlstrom7940e442013-07-12 13:46:57 -07001003 opcode = work_half->dalvikInsn.opcode;
1004 SSARepresentation* ssa_rep = work_half->ssa_rep;
1005 work_half->ssa_rep = mir->ssa_rep;
1006 mir->ssa_rep = ssa_rep;
1007 work_half->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpCheckPart2);
Vladimir Marko4376c872014-01-23 12:39:29 +00001008 work_half->meta.throw_insn = mir;
Brian Carlstrom7940e442013-07-12 13:46:57 -07001009 }
1010
1011 if (opcode >= kMirOpFirst) {
1012 HandleExtendedMethodMIR(bb, mir);
1013 continue;
1014 }
1015
1016 CompileDalvikInstruction(mir, bb, block_label_list_);
1017 }
1018
1019 if (head_lir) {
1020 // Eliminate redundant loads/stores and delay stores into later slots.
1021 ApplyLocalOptimizations(head_lir, last_lir_insn_);
Brian Carlstrom7940e442013-07-12 13:46:57 -07001022 }
1023 return false;
1024}
1025
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -08001026bool Mir2Lir::SpecialMIR2LIR(const InlineMethod& special) {
Vladimir Marko5816ed42013-11-27 17:04:20 +00001027 cu_->NewTimingSplit("SpecialMIR2LIR");
Brian Carlstrom7940e442013-07-12 13:46:57 -07001028 // Find the first DalvikByteCode block.
1029 int num_reachable_blocks = mir_graph_->GetNumReachableBlocks();
1030 BasicBlock*bb = NULL;
1031 for (int idx = 0; idx < num_reachable_blocks; idx++) {
1032 // TODO: no direct access of growable lists.
1033 int dfs_index = mir_graph_->GetDfsOrder()->Get(idx);
1034 bb = mir_graph_->GetBasicBlock(dfs_index);
1035 if (bb->block_type == kDalvikByteCode) {
1036 break;
1037 }
1038 }
1039 if (bb == NULL) {
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -08001040 return false;
Brian Carlstrom7940e442013-07-12 13:46:57 -07001041 }
1042 DCHECK_EQ(bb->start_offset, 0);
1043 DCHECK(bb->first_mir_insn != NULL);
1044
1045 // Get the first instruction.
1046 MIR* mir = bb->first_mir_insn;
1047
1048 // Free temp registers and reset redundant store tracking.
1049 ResetRegPool();
1050 ResetDefTracking();
1051 ClobberAllRegs();
1052
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -08001053 return GenSpecialCase(bb, mir, special);
Brian Carlstrom7940e442013-07-12 13:46:57 -07001054}
1055
Brian Carlstrom2ce745c2013-07-17 17:44:30 -07001056void Mir2Lir::MethodMIR2LIR() {
buzbeea61f4952013-08-23 14:27:06 -07001057 cu_->NewTimingSplit("MIR2LIR");
1058
Brian Carlstrom7940e442013-07-12 13:46:57 -07001059 // Hold the labels of each block.
1060 block_label_list_ =
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -07001061 static_cast<LIR*>(arena_->Alloc(sizeof(LIR) * mir_graph_->GetNumBlocks(),
1062 ArenaAllocator::kAllocLIR));
Brian Carlstrom7940e442013-07-12 13:46:57 -07001063
buzbee56c71782013-09-05 17:13:19 -07001064 PreOrderDfsIterator iter(mir_graph_);
buzbee252254b2013-09-08 16:20:53 -07001065 BasicBlock* curr_bb = iter.Next();
1066 BasicBlock* next_bb = iter.Next();
1067 while (curr_bb != NULL) {
1068 MethodBlockCodeGen(curr_bb);
1069 // If the fall_through block is no longer laid out consecutively, drop in a branch.
buzbee0d829482013-10-11 15:24:55 -07001070 BasicBlock* curr_bb_fall_through = mir_graph_->GetBasicBlock(curr_bb->fall_through);
1071 if ((curr_bb_fall_through != NULL) && (curr_bb_fall_through != next_bb)) {
1072 OpUnconditionalBranch(&block_label_list_[curr_bb->fall_through]);
buzbee252254b2013-09-08 16:20:53 -07001073 }
1074 curr_bb = next_bb;
1075 do {
1076 next_bb = iter.Next();
1077 } while ((next_bb != NULL) && (next_bb->block_type == kDead));
Brian Carlstrom7940e442013-07-12 13:46:57 -07001078 }
Dave Allisonbcec6fb2014-01-17 12:52:22 -08001079 HandleSlowPaths();
1080
buzbeea61f4952013-08-23 14:27:06 -07001081 cu_->NewTimingSplit("Launchpads");
Brian Carlstrom7940e442013-07-12 13:46:57 -07001082 HandleSuspendLaunchPads();
1083
1084 HandleThrowLaunchPads();
1085
1086 HandleIntrinsicLaunchPads();
Brian Carlstrom7940e442013-07-12 13:46:57 -07001087}
1088
Dave Allisonbcec6fb2014-01-17 12:52:22 -08001089//
1090// LIR Slow Path
1091//
1092
1093LIR* Mir2Lir::LIRSlowPath::GenerateTargetLabel() {
1094 LIR* target = m2l_->RawLIR(current_dex_pc_, kPseudoTargetLabel);
1095 m2l_->AppendLIR(target);
1096 fromfast_->target = target;
1097 m2l_->SetCurrentDexPc(current_dex_pc_);
1098 return target;
1099}
Brian Carlstrom7940e442013-07-12 13:46:57 -07001100} // namespace art