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

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: Modifying calling conventions to follow all the O32 abi rules 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/IceTargetLoweringMIPS32.h ('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 // For now CallingConv takes care of only i32,f32 and f64 types
432 // TODO(mohit.bhakkad): Add support for other types (struct as arg, functions
Jim Stichnoth 2016/06/10 23:03:46 Fortunately, the PNaCl ABI only allows primitive (
433 // returning struct)
434 TargetMIPS32::CallingConv::CallingConv()
435 : GPRegsUsed(RegMIPS32::Reg_NUM),
436 GPRArgs(GPRArgInitializer.rbegin(), GPRArgInitializer.rend()),
437 I64Args(I64ArgInitializer.rbegin(), I64ArgInitializer.rend()),
438 VFPRegsUsed(RegMIPS32::Reg_NUM),
439 FP32Args(FP32ArgInitializer.rbegin(), FP32ArgInitializer.rend()),
440 FP64Args(FP64ArgInitializer.rbegin(), FP64ArgInitializer.rend()),
441 UseFPRegs(false) {}
Jim Stichnoth 2016/06/10 23:03:46 "UseFPRegs(false)" will be unnecessary when declar
442
443 // In MIPS O32 abi FP argument registers can be used only if first argument is
444 // of type float/double. UseFPRegs flag is used to care of that. Also FP arg
445 // registers can be used only for first 2 arguments, so we require argument
446 // number to make register allocation decisions.
447 bool TargetMIPS32::CallingConv::argInReg(Type Ty, uint32_t ArgNo,
448 RegNumT *Reg) {
449 if (isScalarIntegerType(Ty))
450 return argInGPR(Ty, Reg);
451 else if (isScalarFloatingType(Ty)) {
Jim Stichnoth 2016/06/10 23:03:46 You don't need "else if" when the previous branch
452 if (ArgNo == 0) {
453 UseFPRegs = true;
454 return argInVFP(Ty, Reg);
455 } else {
456 if (UseFPRegs && ArgNo == 1) {
457 UseFPRegs = false;
458 return argInVFP(Ty, Reg);
459 } else
460 return argInGPR(Ty, Reg);
461 }
462 } else {
463 UnimplementedError(getFlags());
464 return false;
465 }
466 }
467
468 bool TargetMIPS32::CallingConv::argInGPR(Type Ty, RegNumT *Reg) {
469 CfgVector<RegNumT> *Source;
470
471 switch (Ty) {
472 default: {
473 UnimplementedError(getFlags());
474 return false;
475 } break;
476 case IceType_i32:
477 case IceType_f32: {
478 Source = &GPRArgs;
479 } break;
480 case IceType_i64:
481 case IceType_f64: {
482 Source = &I64Args;
483 } break;
484 }
485
486 discardUnavailableGPRsAndTheirAliases(Source);
487
488 if (Source->empty()) {
489 GPRegsUsed.set();
490 return false;
491 }
492
493 *Reg = Source->back();
494 // Note that we don't Source->pop_back() here. This is intentional. Notice how
495 // we mark all of Reg's aliases as Used. So, for the next argument,
496 // Source->back() is marked as unavailable, and it is thus implicitly popped
497 // from the stack.
498 GPRegsUsed |= RegisterAliases[*Reg];
499 return true;
500 }
501
502 inline void TargetMIPS32::CallingConv::discardNextGPRAndItsAliases(
503 CfgVector<RegNumT> *Regs) {
504 GPRegsUsed |= RegisterAliases[Regs->back()];
505 Regs->pop_back();
506 }
507
508 // GPR are not packed when passing parameters. Thus, a function foo(i32, i64,
509 // i32) will have the first argument in a0, the second in a2-a3, and the third
510 // on the stack. To model this behavior, whenever we pop a register from Regs,
511 // we remove all of its aliases from the pool of available GPRs. This has the
512 // effect of computing the "closure" on the GPR registers.
513 void TargetMIPS32::CallingConv::discardUnavailableGPRsAndTheirAliases(
514 CfgVector<RegNumT> *Regs) {
515 while (!Regs->empty() && GPRegsUsed[Regs->back()]) {
516 discardNextGPRAndItsAliases(Regs);
517 }
518 }
519
520 bool TargetMIPS32::CallingConv::argInVFP(Type Ty, RegNumT *Reg) {
521 CfgVector<RegNumT> *Source;
522
523 switch (Ty) {
524 default: {
525 UnimplementedError(getFlags());
526 return false;
527 } break;
528 case IceType_f32: {
529 Source = &FP32Args;
530 } break;
531 case IceType_f64: {
532 Source = &FP64Args;
533 } break;
534 }
535
536 discardUnavailableVFPRegsAndTheirAliases(Source);
537
538 if (Source->empty()) {
539 VFPRegsUsed.set();
540 return false;
541 }
542
543 *Reg = Source->back();
544 VFPRegsUsed |= RegisterAliases[*Reg];
545
546 // In MIPS O32 abi if fun argumets are (f32, i32) then one can not use reg_a0
Jim Stichnoth 2016/06/10 23:03:46 arguments
547 // for second argument even though its free. f32 arg goes in reg_f12, i32 arg
Jim Stichnoth 2016/06/10 23:03:46 it's
548 // goes in reg_a1. Similarly if arguments are (f64, i32) second argumnent goes
549 // in reg_a3 and a0, a1 are not used.
550 Source = &GPRArgs;
551 // Discard one GPR reg for f32(4 bytes), two for f64(4 + 4 bytes)
552 discardNextGPRAndItsAliases(Source);
553 if (Ty == IceType_f64)
554 discardNextGPRAndItsAliases(Source);
555
556 return true;
557 }
558
559 void TargetMIPS32::CallingConv::discardUnavailableVFPRegsAndTheirAliases(
560 CfgVector<RegNumT> *Regs) {
561 while (!Regs->empty() && VFPRegsUsed[Regs->back()]) {
562 Regs->pop_back();
563 }
564 }
565
409 void TargetMIPS32::lowerArguments() { 566 void TargetMIPS32::lowerArguments() {
410 VarList &Args = Func->getArgs(); 567 VarList &Args = Func->getArgs();
411 // We are only handling integer registers for now. The Mips o32 ABI is 568 // 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 569 // somewhat complex but will be implemented in its totality through follow
413 // on patches. 570 // on patches.
414 // 571 //
415 unsigned NumGPRRegsUsed = 0; 572 unsigned NumGPRRegsUsed = 0;
416 // For each register argument, replace Arg in the argument list with the 573 // 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 574 // home register. Then generate an instruction in the prolog to copy the
418 // home register to the assigned location of Arg. 575 // 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" 1871 Str << "\t.set\t"
1715 << "nomips16\n"; 1872 << "nomips16\n";
1716 } 1873 }
1717 1874
1718 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; 1875 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM];
1719 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; 1876 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM];
1720 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; 1877 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM];
1721 1878
1722 } // end of namespace MIPS32 1879 } // end of namespace MIPS32
1723 } // end of namespace Ice 1880 } // end of namespace Ice
OLDNEW
« src/IceTargetLoweringMIPS32.h ('K') | « src/IceTargetLoweringMIPS32.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698