Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(491)

Side by Side Diff: src/IceTargetLoweringMIPS32.cpp

Issue 2052793003: Calling convention for MIPS32 (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero@master
Patch Set: Addressed review comments Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« src/IceInstMIPS32.def ('K') | « src/IceTargetLoweringMIPS32.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« src/IceInstMIPS32.def ('K') | « src/IceTargetLoweringMIPS32.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698