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 } else { | |
Jim Stichnoth
2016/06/11 14:13:26
More "else-after-return" simplifications can be do
| |
452 if (UseFPRegs && ArgNo == 1) { | |
453 UseFPRegs = false; | |
454 return argInVFP(Ty, Reg); | |
455 } else | |
456 return argInGPR(Ty, Reg); | |
457 } | |
458 } | |
459 UnimplementedError(getFlags()); | |
460 return false; | |
461 } | |
462 | |
463 bool TargetMIPS32::CallingConv::argInGPR(Type Ty, RegNumT *Reg) { | |
464 CfgVector<RegNumT> *Source; | |
465 | |
466 switch (Ty) { | |
467 default: { | |
468 UnimplementedError(getFlags()); | |
469 return false; | |
470 } break; | |
471 case IceType_i32: | |
472 case IceType_f32: { | |
473 Source = &GPRArgs; | |
474 } break; | |
475 case IceType_i64: | |
476 case IceType_f64: { | |
477 Source = &I64Args; | |
478 } break; | |
479 } | |
480 | |
481 discardUnavailableGPRsAndTheirAliases(Source); | |
482 | |
483 if (Source->empty()) { | |
484 GPRegsUsed.set(); | |
485 return false; | |
486 } | |
487 | |
488 *Reg = Source->back(); | |
489 // Note that we don't Source->pop_back() here. This is intentional. Notice how | |
490 // we mark all of Reg's aliases as Used. So, for the next argument, | |
491 // Source->back() is marked as unavailable, and it is thus implicitly popped | |
492 // from the stack. | |
493 GPRegsUsed |= RegisterAliases[*Reg]; | |
494 return true; | |
495 } | |
496 | |
497 inline void TargetMIPS32::CallingConv::discardNextGPRAndItsAliases( | |
498 CfgVector<RegNumT> *Regs) { | |
499 GPRegsUsed |= RegisterAliases[Regs->back()]; | |
500 Regs->pop_back(); | |
501 } | |
502 | |
503 // GPR are not packed when passing parameters. Thus, a function foo(i32, i64, | |
504 // i32) will have the first argument in a0, the second in a2-a3, and the third | |
505 // on the stack. To model this behavior, whenever we pop a register from Regs, | |
506 // we remove all of its aliases from the pool of available GPRs. This has the | |
507 // effect of computing the "closure" on the GPR registers. | |
508 void TargetMIPS32::CallingConv::discardUnavailableGPRsAndTheirAliases( | |
509 CfgVector<RegNumT> *Regs) { | |
510 while (!Regs->empty() && GPRegsUsed[Regs->back()]) { | |
511 discardNextGPRAndItsAliases(Regs); | |
512 } | |
513 } | |
514 | |
515 bool TargetMIPS32::CallingConv::argInVFP(Type Ty, RegNumT *Reg) { | |
516 CfgVector<RegNumT> *Source; | |
517 | |
518 switch (Ty) { | |
519 default: { | |
520 UnimplementedError(getFlags()); | |
521 return false; | |
522 } break; | |
523 case IceType_f32: { | |
524 Source = &FP32Args; | |
525 } break; | |
526 case IceType_f64: { | |
527 Source = &FP64Args; | |
528 } break; | |
529 } | |
530 | |
531 discardUnavailableVFPRegsAndTheirAliases(Source); | |
532 | |
533 if (Source->empty()) { | |
534 VFPRegsUsed.set(); | |
535 return false; | |
536 } | |
537 | |
538 *Reg = Source->back(); | |
539 VFPRegsUsed |= RegisterAliases[*Reg]; | |
540 | |
541 // In MIPS O32 abi if fun arguments are (f32, i32) then one can not use reg_a0 | |
542 // for second argument even though it's free. f32 arg goes in reg_f12, i32 arg | |
543 // goes in reg_a1. Similarly if arguments are (f64, i32) second argument goes | |
544 // in reg_a3 and a0, a1 are not used. | |
545 Source = &GPRArgs; | |
546 // Discard one GPR reg for f32(4 bytes), two for f64(4 + 4 bytes) | |
547 discardNextGPRAndItsAliases(Source); | |
548 if (Ty == IceType_f64) | |
549 discardNextGPRAndItsAliases(Source); | |
550 | |
551 return true; | |
552 } | |
553 | |
554 void TargetMIPS32::CallingConv::discardUnavailableVFPRegsAndTheirAliases( | |
555 CfgVector<RegNumT> *Regs) { | |
556 while (!Regs->empty() && VFPRegsUsed[Regs->back()]) { | |
557 Regs->pop_back(); | |
558 } | |
559 } | |
560 | |
409 void TargetMIPS32::lowerArguments() { | 561 void TargetMIPS32::lowerArguments() { |
410 VarList &Args = Func->getArgs(); | 562 VarList &Args = Func->getArgs(); |
411 // We are only handling integer registers for now. The Mips o32 ABI is | 563 // 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 | 564 // somewhat complex but will be implemented in its totality through follow |
413 // on patches. | 565 // on patches. |
414 // | 566 // |
415 unsigned NumGPRRegsUsed = 0; | 567 unsigned NumGPRRegsUsed = 0; |
416 // For each register argument, replace Arg in the argument list with the | 568 // 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 | 569 // home register. Then generate an instruction in the prolog to copy the |
418 // home register to the assigned location of Arg. | 570 // 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" | 1866 Str << "\t.set\t" |
1715 << "nomips16\n"; | 1867 << "nomips16\n"; |
1716 } | 1868 } |
1717 | 1869 |
1718 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; | 1870 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; |
1719 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; | 1871 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; |
1720 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; | 1872 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; |
1721 | 1873 |
1722 } // end of namespace MIPS32 | 1874 } // end of namespace MIPS32 |
1723 } // end of namespace Ice | 1875 } // end of namespace Ice |
OLD | NEW |