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