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

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
« no previous file with comments | « 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 }
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
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
OLDNEW
« no previous file with comments | « src/IceTargetLoweringMIPS32.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698