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