OLD | NEW |
1 // | 1 // |
2 // The Subzero Code Generator | 2 // The Subzero Code Generator |
3 // | 3 // |
4 // This file is distributed under the University of Illinois Open Source | 4 // This file is distributed under the University of Illinois Open Source |
5 // License. See LICENSE.TXT for details. | 5 // License. See LICENSE.TXT for details. |
6 // | 6 // |
7 //===----------------------------------------------------------------------===// | 7 //===----------------------------------------------------------------------===// |
8 /// | 8 /// |
9 /// \file | 9 /// \file |
10 /// \brief Implements the TargetLoweringMIPS32 class, which consists almost | 10 /// \brief Implements the TargetLoweringMIPS32 class, which consists almost |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 namespace Ice { | 57 namespace Ice { |
58 namespace MIPS32 { | 58 namespace MIPS32 { |
59 | 59 |
60 using llvm::isInt; | 60 using llvm::isInt; |
61 | 61 |
62 namespace { | 62 namespace { |
63 | 63 |
64 // The maximum number of arguments to pass in GPR registers. | 64 // The maximum number of arguments to pass in GPR registers. |
65 constexpr uint32_t MIPS32_MAX_GPR_ARG = 4; | 65 constexpr uint32_t MIPS32_MAX_GPR_ARG = 4; |
66 | 66 |
| 67 std::array<RegNumT, MIPS32_MAX_GPR_ARG> GPRArgInitializer; |
| 68 std::array<RegNumT, MIPS32_MAX_GPR_ARG / 2> I64ArgInitializer; |
| 69 |
| 70 constexpr uint32_t MIPS32_MAX_FP_ARG = 2; |
| 71 |
| 72 std::array<RegNumT, MIPS32_MAX_FP_ARG> FP32ArgInitializer; |
| 73 std::array<RegNumT, MIPS32_MAX_FP_ARG> FP64ArgInitializer; |
| 74 |
67 const char *getRegClassName(RegClass C) { | 75 const char *getRegClassName(RegClass C) { |
68 auto ClassNum = static_cast<RegClassMIPS32>(C); | 76 auto ClassNum = static_cast<RegClassMIPS32>(C); |
69 assert(ClassNum < RCMIPS32_NUM); | 77 assert(ClassNum < RCMIPS32_NUM); |
70 switch (ClassNum) { | 78 switch (ClassNum) { |
71 default: | 79 default: |
72 assert(C < RC_Target); | 80 assert(C < RC_Target); |
73 return regClassString(C); | 81 return regClassString(C); |
74 // Add handling of new register classes below. | 82 // Add handling of new register classes below. |
75 } | 83 } |
76 } | 84 } |
(...skipping 21 matching lines...) Expand all Loading... |
98 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ | 106 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ |
99 for (SizeT RegAlias : alias_init) { \ | 107 for (SizeT RegAlias : alias_init) { \ |
100 assert(!RegisterAliases[RegMIPS32::val][RegAlias] && \ | 108 assert(!RegisterAliases[RegMIPS32::val][RegAlias] && \ |
101 "Duplicate alias for " #val); \ | 109 "Duplicate alias for " #val); \ |
102 RegisterAliases[RegMIPS32::val].set(RegAlias); \ | 110 RegisterAliases[RegMIPS32::val].set(RegAlias); \ |
103 } \ | 111 } \ |
104 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ | 112 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ |
105 assert(RegisterAliases[RegMIPS32::val][RegMIPS32::val]); | 113 assert(RegisterAliases[RegMIPS32::val][RegMIPS32::val]); |
106 REGMIPS32_TABLE; | 114 REGMIPS32_TABLE; |
107 #undef X | 115 #undef X |
| 116 |
| 117 // TODO(mohit.bhakkad): Change these inits once we provide argument related |
| 118 // field in register tables |
| 119 for (size_t i = 0; i < MIPS32_MAX_GPR_ARG; i++) |
| 120 GPRArgInitializer[i] = RegNumT::fixme(RegMIPS32::Reg_A0 + i); |
| 121 |
| 122 for (size_t i = 0; i < MIPS32_MAX_GPR_ARG / 2; i++) |
| 123 I64ArgInitializer[i] = RegNumT::fixme(RegMIPS32::Reg_A0A1 + i); |
| 124 |
| 125 for (size_t i = 0; i < MIPS32_MAX_FP_ARG; i++) { |
| 126 FP32ArgInitializer[i] = RegNumT::fixme(RegMIPS32::Reg_F12 + i * 2); |
| 127 FP64ArgInitializer[i] = RegNumT::fixme(RegMIPS32::Reg_F12F13 + i); |
| 128 } |
| 129 |
108 TypeToRegisterSet[IceType_void] = InvalidRegisters; | 130 TypeToRegisterSet[IceType_void] = InvalidRegisters; |
109 TypeToRegisterSet[IceType_i1] = IntegerRegisters; | 131 TypeToRegisterSet[IceType_i1] = IntegerRegisters; |
110 TypeToRegisterSet[IceType_i8] = IntegerRegisters; | 132 TypeToRegisterSet[IceType_i8] = IntegerRegisters; |
111 TypeToRegisterSet[IceType_i16] = IntegerRegisters; | 133 TypeToRegisterSet[IceType_i16] = IntegerRegisters; |
112 TypeToRegisterSet[IceType_i32] = IntegerRegisters; | 134 TypeToRegisterSet[IceType_i32] = IntegerRegisters; |
113 TypeToRegisterSet[IceType_i64] = IntegerRegisters; | 135 TypeToRegisterSet[IceType_i64] = IntegerRegisters; |
114 TypeToRegisterSet[IceType_f32] = Float32Registers; | 136 TypeToRegisterSet[IceType_f32] = Float32Registers; |
115 TypeToRegisterSet[IceType_f64] = Float64Registers; | 137 TypeToRegisterSet[IceType_f64] = Float64Registers; |
116 TypeToRegisterSet[IceType_v4i1] = VectorRegisters; | 138 TypeToRegisterSet[IceType_v4i1] = VectorRegisters; |
117 TypeToRegisterSet[IceType_v8i1] = VectorRegisters; | 139 TypeToRegisterSet[IceType_v8i1] = VectorRegisters; |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 return; | 421 return; |
400 } else { | 422 } else { |
401 int32_t Offset = Var->getStackOffset(); | 423 int32_t Offset = Var->getStackOffset(); |
402 Str << Offset; | 424 Str << Offset; |
403 Str << "($" << getRegName(getFrameOrStackReg(), FrameSPTy); | 425 Str << "($" << getRegName(getFrameOrStackReg(), FrameSPTy); |
404 Str << ")"; | 426 Str << ")"; |
405 } | 427 } |
406 UnimplementedError(getFlags()); | 428 UnimplementedError(getFlags()); |
407 } | 429 } |
408 | 430 |
| 431 TargetMIPS32::CallingConv::CallingConv() |
| 432 : GPRegsUsed(RegMIPS32::Reg_NUM), |
| 433 GPRArgs(GPRArgInitializer.rbegin(), GPRArgInitializer.rend()), |
| 434 I64Args(I64ArgInitializer.rbegin(), I64ArgInitializer.rend()), |
| 435 VFPRegsUsed(RegMIPS32::Reg_NUM), |
| 436 FP32Args(FP32ArgInitializer.rbegin(), FP32ArgInitializer.rend()), |
| 437 FP64Args(FP64ArgInitializer.rbegin(), FP64ArgInitializer.rend()) {} |
| 438 |
| 439 // In MIPS O32 abi FP argument registers can be used only if first argument is |
| 440 // of type float/double. UseFPRegs flag is used to care of that. Also FP arg |
| 441 // registers can be used only for first 2 arguments, so we require argument |
| 442 // number to make register allocation decisions. |
| 443 bool TargetMIPS32::CallingConv::argInReg(Type Ty, uint32_t ArgNo, |
| 444 RegNumT *Reg) { |
| 445 if (isScalarIntegerType(Ty)) |
| 446 return argInGPR(Ty, Reg); |
| 447 if (isScalarFloatingType(Ty)) { |
| 448 if (ArgNo == 0) { |
| 449 UseFPRegs = true; |
| 450 return argInVFP(Ty, Reg); |
| 451 } |
| 452 if (UseFPRegs && ArgNo == 1) { |
| 453 UseFPRegs = false; |
| 454 return argInVFP(Ty, Reg); |
| 455 } |
| 456 return argInGPR(Ty, Reg); |
| 457 } |
| 458 UnimplementedError(getFlags()); |
| 459 return false; |
| 460 } |
| 461 |
| 462 bool TargetMIPS32::CallingConv::argInGPR(Type Ty, RegNumT *Reg) { |
| 463 CfgVector<RegNumT> *Source; |
| 464 |
| 465 switch (Ty) { |
| 466 default: { |
| 467 UnimplementedError(getFlags()); |
| 468 return false; |
| 469 } break; |
| 470 case IceType_i32: |
| 471 case IceType_f32: { |
| 472 Source = &GPRArgs; |
| 473 } break; |
| 474 case IceType_i64: |
| 475 case IceType_f64: { |
| 476 Source = &I64Args; |
| 477 } break; |
| 478 } |
| 479 |
| 480 discardUnavailableGPRsAndTheirAliases(Source); |
| 481 |
| 482 if (Source->empty()) { |
| 483 GPRegsUsed.set(); |
| 484 return false; |
| 485 } |
| 486 |
| 487 *Reg = Source->back(); |
| 488 // Note that we don't Source->pop_back() here. This is intentional. Notice how |
| 489 // we mark all of Reg's aliases as Used. So, for the next argument, |
| 490 // Source->back() is marked as unavailable, and it is thus implicitly popped |
| 491 // from the stack. |
| 492 GPRegsUsed |= RegisterAliases[*Reg]; |
| 493 return true; |
| 494 } |
| 495 |
| 496 inline void TargetMIPS32::CallingConv::discardNextGPRAndItsAliases( |
| 497 CfgVector<RegNumT> *Regs) { |
| 498 GPRegsUsed |= RegisterAliases[Regs->back()]; |
| 499 Regs->pop_back(); |
| 500 } |
| 501 |
| 502 // GPR are not packed when passing parameters. Thus, a function foo(i32, i64, |
| 503 // i32) will have the first argument in a0, the second in a2-a3, and the third |
| 504 // on the stack. To model this behavior, whenever we pop a register from Regs, |
| 505 // we remove all of its aliases from the pool of available GPRs. This has the |
| 506 // effect of computing the "closure" on the GPR registers. |
| 507 void TargetMIPS32::CallingConv::discardUnavailableGPRsAndTheirAliases( |
| 508 CfgVector<RegNumT> *Regs) { |
| 509 while (!Regs->empty() && GPRegsUsed[Regs->back()]) { |
| 510 discardNextGPRAndItsAliases(Regs); |
| 511 } |
| 512 } |
| 513 |
| 514 bool TargetMIPS32::CallingConv::argInVFP(Type Ty, RegNumT *Reg) { |
| 515 CfgVector<RegNumT> *Source; |
| 516 |
| 517 switch (Ty) { |
| 518 default: { |
| 519 UnimplementedError(getFlags()); |
| 520 return false; |
| 521 } break; |
| 522 case IceType_f32: { |
| 523 Source = &FP32Args; |
| 524 } break; |
| 525 case IceType_f64: { |
| 526 Source = &FP64Args; |
| 527 } break; |
| 528 } |
| 529 |
| 530 discardUnavailableVFPRegsAndTheirAliases(Source); |
| 531 |
| 532 if (Source->empty()) { |
| 533 VFPRegsUsed.set(); |
| 534 return false; |
| 535 } |
| 536 |
| 537 *Reg = Source->back(); |
| 538 VFPRegsUsed |= RegisterAliases[*Reg]; |
| 539 |
| 540 // In MIPS O32 abi if fun arguments are (f32, i32) then one can not use reg_a0 |
| 541 // for second argument even though it's free. f32 arg goes in reg_f12, i32 arg |
| 542 // goes in reg_a1. Similarly if arguments are (f64, i32) second argument goes |
| 543 // in reg_a3 and a0, a1 are not used. |
| 544 Source = &GPRArgs; |
| 545 // Discard one GPR reg for f32(4 bytes), two for f64(4 + 4 bytes) |
| 546 discardNextGPRAndItsAliases(Source); |
| 547 if (Ty == IceType_f64) |
| 548 discardNextGPRAndItsAliases(Source); |
| 549 |
| 550 return true; |
| 551 } |
| 552 |
| 553 void TargetMIPS32::CallingConv::discardUnavailableVFPRegsAndTheirAliases( |
| 554 CfgVector<RegNumT> *Regs) { |
| 555 while (!Regs->empty() && VFPRegsUsed[Regs->back()]) { |
| 556 Regs->pop_back(); |
| 557 } |
| 558 } |
| 559 |
409 void TargetMIPS32::lowerArguments() { | 560 void TargetMIPS32::lowerArguments() { |
410 VarList &Args = Func->getArgs(); | 561 VarList &Args = Func->getArgs(); |
411 // We are only handling integer registers for now. The Mips o32 ABI is | 562 // We are only handling integer registers for now. The Mips o32 ABI is |
412 // somewhat complex but will be implemented in its totality through follow | 563 // somewhat complex but will be implemented in its totality through follow |
413 // on patches. | 564 // on patches. |
414 // | 565 // |
415 unsigned NumGPRRegsUsed = 0; | 566 unsigned NumGPRRegsUsed = 0; |
416 // For each register argument, replace Arg in the argument list with the | 567 // For each register argument, replace Arg in the argument list with the |
417 // home register. Then generate an instruction in the prolog to copy the | 568 // home register. Then generate an instruction in the prolog to copy the |
418 // home register to the assigned location of Arg. | 569 // home register to the assigned location of Arg. |
(...skipping 1295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1714 Str << "\t.set\t" | 1865 Str << "\t.set\t" |
1715 << "nomips16\n"; | 1866 << "nomips16\n"; |
1716 } | 1867 } |
1717 | 1868 |
1718 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; | 1869 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; |
1719 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; | 1870 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; |
1720 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; | 1871 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; |
1721 | 1872 |
1722 } // end of namespace MIPS32 | 1873 } // end of namespace MIPS32 |
1723 } // end of namespace Ice | 1874 } // end of namespace Ice |
OLD | NEW |