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 } |
77 | 85 |
86 // Stack alignment | |
87 constexpr uint32_t MIPS32_STACK_ALIGNMENT_BYTES = 8; | |
88 | |
89 // Value is in bytes. Return Value adjusted to the next highest multiple of the | |
90 // stack alignment required for the given type. | |
91 uint32_t applyStackAlignmentTy(uint32_t Value, Type Ty) { | |
92 size_t typeAlignInBytes = typeWidthInBytes(Ty); | |
93 if (isVectorType(Ty)) | |
94 UnimplementedError(getFlags()); | |
95 return Utils::applyAlignment(Value, typeAlignInBytes); | |
96 } | |
97 | |
78 } // end of anonymous namespace | 98 } // end of anonymous namespace |
79 | 99 |
80 TargetMIPS32::TargetMIPS32(Cfg *Func) : TargetLowering(Func) {} | 100 TargetMIPS32::TargetMIPS32(Cfg *Func) : TargetLowering(Func) {} |
81 | 101 |
82 void TargetMIPS32::staticInit(GlobalContext *Ctx) { | 102 void TargetMIPS32::staticInit(GlobalContext *Ctx) { |
83 (void)Ctx; | 103 (void)Ctx; |
84 RegNumT::setLimit(RegMIPS32::Reg_NUM); | 104 RegNumT::setLimit(RegMIPS32::Reg_NUM); |
85 SmallBitVector IntegerRegisters(RegMIPS32::Reg_NUM); | 105 SmallBitVector IntegerRegisters(RegMIPS32::Reg_NUM); |
86 SmallBitVector I64PairRegisters(RegMIPS32::Reg_NUM); | 106 SmallBitVector I64PairRegisters(RegMIPS32::Reg_NUM); |
87 SmallBitVector Float32Registers(RegMIPS32::Reg_NUM); | 107 SmallBitVector Float32Registers(RegMIPS32::Reg_NUM); |
(...skipping 10 matching lines...) Expand all Loading... | |
98 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ | 118 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ |
99 for (SizeT RegAlias : alias_init) { \ | 119 for (SizeT RegAlias : alias_init) { \ |
100 assert(!RegisterAliases[RegMIPS32::val][RegAlias] && \ | 120 assert(!RegisterAliases[RegMIPS32::val][RegAlias] && \ |
101 "Duplicate alias for " #val); \ | 121 "Duplicate alias for " #val); \ |
102 RegisterAliases[RegMIPS32::val].set(RegAlias); \ | 122 RegisterAliases[RegMIPS32::val].set(RegAlias); \ |
103 } \ | 123 } \ |
104 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ | 124 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ |
105 assert(RegisterAliases[RegMIPS32::val][RegMIPS32::val]); | 125 assert(RegisterAliases[RegMIPS32::val][RegMIPS32::val]); |
106 REGMIPS32_TABLE; | 126 REGMIPS32_TABLE; |
107 #undef X | 127 #undef X |
128 | |
129 // TODO(mohit.bhakkad): Change these inits once we provide argument related | |
130 // field in register tables | |
131 for (size_t i = 0; i < MIPS32_MAX_GPR_ARG; i++) | |
132 GPRArgInitializer[i] = RegNumT::fixme(RegMIPS32::Reg_A0 + i); | |
133 | |
134 for (size_t i = 0; i < MIPS32_MAX_GPR_ARG / 2; i++) | |
135 I64ArgInitializer[i] = RegNumT::fixme(RegMIPS32::Reg_A0A1 + i); | |
136 | |
137 for (size_t i = 0; i < MIPS32_MAX_FP_ARG; i++) { | |
138 FP32ArgInitializer[i] = RegNumT::fixme(RegMIPS32::Reg_F12 + i * 2); | |
139 FP64ArgInitializer[i] = RegNumT::fixme(RegMIPS32::Reg_F12F13 + i); | |
140 } | |
141 | |
108 TypeToRegisterSet[IceType_void] = InvalidRegisters; | 142 TypeToRegisterSet[IceType_void] = InvalidRegisters; |
109 TypeToRegisterSet[IceType_i1] = IntegerRegisters; | 143 TypeToRegisterSet[IceType_i1] = IntegerRegisters; |
110 TypeToRegisterSet[IceType_i8] = IntegerRegisters; | 144 TypeToRegisterSet[IceType_i8] = IntegerRegisters; |
111 TypeToRegisterSet[IceType_i16] = IntegerRegisters; | 145 TypeToRegisterSet[IceType_i16] = IntegerRegisters; |
112 TypeToRegisterSet[IceType_i32] = IntegerRegisters; | 146 TypeToRegisterSet[IceType_i32] = IntegerRegisters; |
113 TypeToRegisterSet[IceType_i64] = IntegerRegisters; | 147 TypeToRegisterSet[IceType_i64] = IntegerRegisters; |
114 TypeToRegisterSet[IceType_f32] = Float32Registers; | 148 TypeToRegisterSet[IceType_f32] = Float32Registers; |
115 TypeToRegisterSet[IceType_f64] = Float64Registers; | 149 TypeToRegisterSet[IceType_f64] = Float64Registers; |
116 TypeToRegisterSet[IceType_v4i1] = VectorRegisters; | 150 TypeToRegisterSet[IceType_v4i1] = VectorRegisters; |
117 TypeToRegisterSet[IceType_v8i1] = VectorRegisters; | 151 TypeToRegisterSet[IceType_v8i1] = VectorRegisters; |
118 TypeToRegisterSet[IceType_v16i1] = VectorRegisters; | 152 TypeToRegisterSet[IceType_v16i1] = VectorRegisters; |
119 TypeToRegisterSet[IceType_v16i8] = VectorRegisters; | 153 TypeToRegisterSet[IceType_v16i8] = VectorRegisters; |
120 TypeToRegisterSet[IceType_v8i16] = VectorRegisters; | 154 TypeToRegisterSet[IceType_v8i16] = VectorRegisters; |
121 TypeToRegisterSet[IceType_v4i32] = VectorRegisters; | 155 TypeToRegisterSet[IceType_v4i32] = VectorRegisters; |
122 TypeToRegisterSet[IceType_v4f32] = VectorRegisters; | 156 TypeToRegisterSet[IceType_v4f32] = VectorRegisters; |
123 | 157 |
124 for (size_t i = 0; i < llvm::array_lengthof(TypeToRegisterSet); ++i) | 158 for (size_t i = 0; i < llvm::array_lengthof(TypeToRegisterSet); ++i) |
125 TypeToRegisterSetUnfiltered[i] = TypeToRegisterSet[i]; | 159 TypeToRegisterSetUnfiltered[i] = TypeToRegisterSet[i]; |
126 | 160 |
127 filterTypeToRegisterSet(Ctx, RegMIPS32::Reg_NUM, TypeToRegisterSet, | 161 filterTypeToRegisterSet(Ctx, RegMIPS32::Reg_NUM, TypeToRegisterSet, |
128 llvm::array_lengthof(TypeToRegisterSet), | 162 llvm::array_lengthof(TypeToRegisterSet), |
129 RegMIPS32::getRegName, getRegClassName); | 163 RegMIPS32::getRegName, getRegClassName); |
130 } | 164 } |
131 | 165 |
166 void TargetMIPS32::findMaxStackOutArgsSize() { | |
167 // MinNeededOutArgsBytes should be updated if the Target ever creates a | |
168 // high-level InstCall that requires more stack bytes. | |
169 constexpr size_t MinNeededOutArgsBytes = 16; | |
170 MaxOutArgsSizeBytes = MinNeededOutArgsBytes; | |
171 for (CfgNode *Node : Func->getNodes()) { | |
172 Context.init(Node); | |
173 while (!Context.atEnd()) { | |
174 PostIncrLoweringContext PostIncrement(Context); | |
175 Inst *CurInstr = iteratorToInst(Context.getCur()); | |
176 if (auto *Call = llvm::dyn_cast<InstCall>(CurInstr)) { | |
177 SizeT OutArgsSizeBytes = getCallStackArgumentsSizeBytes(Call); | |
178 MaxOutArgsSizeBytes = std::max(MaxOutArgsSizeBytes, OutArgsSizeBytes); | |
179 } | |
180 } | |
181 } | |
182 } | |
183 | |
132 void TargetMIPS32::translateO2() { | 184 void TargetMIPS32::translateO2() { |
133 TimerMarker T(TimerStack::TT_O2, Func); | 185 TimerMarker T(TimerStack::TT_O2, Func); |
134 | 186 |
135 // TODO(stichnot): share passes with X86? | 187 // TODO(stichnot): share passes with X86? |
136 // https://code.google.com/p/nativeclient/issues/detail?id=4094 | 188 // https://code.google.com/p/nativeclient/issues/detail?id=4094 |
137 genTargetHelperCalls(); | 189 genTargetHelperCalls(); |
138 | 190 |
191 findMaxStackOutArgsSize(); | |
192 | |
139 // Merge Alloca instructions, and lay out the stack. | 193 // Merge Alloca instructions, and lay out the stack. |
140 static constexpr bool SortAndCombineAllocas = false; | 194 static constexpr bool SortAndCombineAllocas = false; |
141 Func->processAllocas(SortAndCombineAllocas); | 195 Func->processAllocas(SortAndCombineAllocas); |
142 Func->dump("After Alloca processing"); | 196 Func->dump("After Alloca processing"); |
143 | 197 |
144 if (!getFlags().getEnablePhiEdgeSplit()) { | 198 if (!getFlags().getEnablePhiEdgeSplit()) { |
145 // Lower Phi instructions. | 199 // Lower Phi instructions. |
146 Func->placePhiLoads(); | 200 Func->placePhiLoads(); |
147 if (Func->hasError()) | 201 if (Func->hasError()) |
148 return; | 202 return; |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
230 Func->doNopInsertion(); | 284 Func->doNopInsertion(); |
231 } | 285 } |
232 } | 286 } |
233 | 287 |
234 void TargetMIPS32::translateOm1() { | 288 void TargetMIPS32::translateOm1() { |
235 TimerMarker T(TimerStack::TT_Om1, Func); | 289 TimerMarker T(TimerStack::TT_Om1, Func); |
236 | 290 |
237 // TODO: share passes with X86? | 291 // TODO: share passes with X86? |
238 genTargetHelperCalls(); | 292 genTargetHelperCalls(); |
239 | 293 |
294 findMaxStackOutArgsSize(); | |
295 | |
240 // Do not merge Alloca instructions, and lay out the stack. | 296 // Do not merge Alloca instructions, and lay out the stack. |
241 static constexpr bool SortAndCombineAllocas = false; | 297 static constexpr bool SortAndCombineAllocas = false; |
242 Func->processAllocas(SortAndCombineAllocas); | 298 Func->processAllocas(SortAndCombineAllocas); |
243 Func->dump("After Alloca processing"); | 299 Func->dump("After Alloca processing"); |
244 | 300 |
245 Func->placePhiLoads(); | 301 Func->placePhiLoads(); |
246 if (Func->hasError()) | 302 if (Func->hasError()) |
247 return; | 303 return; |
248 Func->placePhiStores(); | 304 Func->placePhiStores(); |
249 if (Func->hasError()) | 305 if (Func->hasError()) |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
396 const Type FrameSPTy = IceType_i32; | 452 const Type FrameSPTy = IceType_i32; |
397 if (Var->hasReg()) { | 453 if (Var->hasReg()) { |
398 Str << '$' << getRegName(Var->getRegNum(), Var->getType()); | 454 Str << '$' << getRegName(Var->getRegNum(), Var->getType()); |
399 return; | 455 return; |
400 } else { | 456 } else { |
401 int32_t Offset = Var->getStackOffset(); | 457 int32_t Offset = Var->getStackOffset(); |
402 Str << Offset; | 458 Str << Offset; |
403 Str << "($" << getRegName(getFrameOrStackReg(), FrameSPTy); | 459 Str << "($" << getRegName(getFrameOrStackReg(), FrameSPTy); |
404 Str << ")"; | 460 Str << ")"; |
405 } | 461 } |
462 // UnimplementedError(getFlags()); | |
Jim Stichnoth
2016/06/13 20:14:19
remove this
| |
463 } | |
464 | |
465 TargetMIPS32::CallingConv::CallingConv() | |
466 : GPRegsUsed(RegMIPS32::Reg_NUM), | |
467 GPRArgs(GPRArgInitializer.rbegin(), GPRArgInitializer.rend()), | |
468 I64Args(I64ArgInitializer.rbegin(), I64ArgInitializer.rend()), | |
469 VFPRegsUsed(RegMIPS32::Reg_NUM), | |
470 FP32Args(FP32ArgInitializer.rbegin(), FP32ArgInitializer.rend()), | |
471 FP64Args(FP64ArgInitializer.rbegin(), FP64ArgInitializer.rend()) {} | |
472 | |
473 // In MIPS O32 abi FP argument registers can be used only if first argument is | |
474 // of type float/double. UseFPRegs flag is used to care of that. Also FP arg | |
475 // registers can be used only for first 2 arguments, so we require argument | |
476 // number to make register allocation decisions. | |
477 bool TargetMIPS32::CallingConv::argInReg(Type Ty, uint32_t ArgNo, | |
478 RegNumT *Reg) { | |
479 if (isScalarIntegerType(Ty)) | |
480 return argInGPR(Ty, Reg); | |
481 if (isScalarFloatingType(Ty)) { | |
482 if (ArgNo == 0) { | |
483 UseFPRegs = true; | |
484 return argInVFP(Ty, Reg); | |
485 } | |
486 if (UseFPRegs && ArgNo == 1) { | |
487 UseFPRegs = false; | |
488 return argInVFP(Ty, Reg); | |
489 } | |
490 return argInGPR(Ty, Reg); | |
491 } | |
406 UnimplementedError(getFlags()); | 492 UnimplementedError(getFlags()); |
493 return false; | |
494 } | |
495 | |
496 bool TargetMIPS32::CallingConv::argInGPR(Type Ty, RegNumT *Reg) { | |
497 CfgVector<RegNumT> *Source; | |
498 | |
499 switch (Ty) { | |
500 default: { | |
501 UnimplementedError(getFlags()); | |
502 return false; | |
503 } break; | |
504 case IceType_i32: | |
505 case IceType_f32: { | |
506 Source = &GPRArgs; | |
507 } break; | |
508 case IceType_i64: | |
509 case IceType_f64: { | |
510 Source = &I64Args; | |
511 } break; | |
512 } | |
513 | |
514 discardUnavailableGPRsAndTheirAliases(Source); | |
515 | |
516 if (Source->empty()) { | |
517 GPRegsUsed.set(); | |
518 return false; | |
519 } | |
520 | |
521 *Reg = Source->back(); | |
522 // Note that we don't Source->pop_back() here. This is intentional. Notice how | |
523 // we mark all of Reg's aliases as Used. So, for the next argument, | |
524 // Source->back() is marked as unavailable, and it is thus implicitly popped | |
525 // from the stack. | |
526 GPRegsUsed |= RegisterAliases[*Reg]; | |
527 return true; | |
528 } | |
529 | |
530 inline void TargetMIPS32::CallingConv::discardNextGPRAndItsAliases( | |
531 CfgVector<RegNumT> *Regs) { | |
532 GPRegsUsed |= RegisterAliases[Regs->back()]; | |
533 Regs->pop_back(); | |
534 } | |
535 | |
536 // GPR are not packed when passing parameters. Thus, a function foo(i32, i64, | |
537 // i32) will have the first argument in a0, the second in a2-a3, and the third | |
538 // on the stack. To model this behavior, whenever we pop a register from Regs, | |
539 // we remove all of its aliases from the pool of available GPRs. This has the | |
540 // effect of computing the "closure" on the GPR registers. | |
541 void TargetMIPS32::CallingConv::discardUnavailableGPRsAndTheirAliases( | |
542 CfgVector<RegNumT> *Regs) { | |
543 while (!Regs->empty() && GPRegsUsed[Regs->back()]) { | |
544 discardNextGPRAndItsAliases(Regs); | |
545 } | |
546 } | |
547 | |
548 bool TargetMIPS32::CallingConv::argInVFP(Type Ty, RegNumT *Reg) { | |
549 CfgVector<RegNumT> *Source; | |
550 | |
551 switch (Ty) { | |
552 default: { | |
553 UnimplementedError(getFlags()); | |
554 return false; | |
555 } break; | |
556 case IceType_f32: { | |
557 Source = &FP32Args; | |
558 } break; | |
559 case IceType_f64: { | |
560 Source = &FP64Args; | |
561 } break; | |
562 } | |
563 | |
564 discardUnavailableVFPRegsAndTheirAliases(Source); | |
565 | |
566 if (Source->empty()) { | |
567 VFPRegsUsed.set(); | |
568 return false; | |
569 } | |
570 | |
571 *Reg = Source->back(); | |
572 VFPRegsUsed |= RegisterAliases[*Reg]; | |
573 | |
574 // In MIPS O32 abi if fun arguments are (f32, i32) then one can not use reg_a0 | |
575 // for second argument even though it's free. f32 arg goes in reg_f12, i32 arg | |
576 // goes in reg_a1. Similarly if arguments are (f64, i32) second argument goes | |
577 // in reg_a3 and a0, a1 are not used. | |
578 Source = &GPRArgs; | |
579 // Discard one GPR reg for f32(4 bytes), two for f64(4 + 4 bytes) | |
580 discardNextGPRAndItsAliases(Source); | |
581 if (Ty == IceType_f64) | |
582 discardNextGPRAndItsAliases(Source); | |
583 | |
584 return true; | |
585 } | |
586 | |
587 void TargetMIPS32::CallingConv::discardUnavailableVFPRegsAndTheirAliases( | |
588 CfgVector<RegNumT> *Regs) { | |
589 while (!Regs->empty() && VFPRegsUsed[Regs->back()]) { | |
590 Regs->pop_back(); | |
591 } | |
407 } | 592 } |
408 | 593 |
409 void TargetMIPS32::lowerArguments() { | 594 void TargetMIPS32::lowerArguments() { |
410 VarList &Args = Func->getArgs(); | 595 VarList &Args = Func->getArgs(); |
411 // We are only handling integer registers for now. The Mips o32 ABI is | 596 TargetMIPS32::CallingConv CC; |
412 // somewhat complex but will be implemented in its totality through follow | 597 |
413 // on patches. | 598 // For each register argument, replace Arg in the argument list with the home |
414 // | 599 // register. Then generate an instruction in the prolog to copy the home |
415 unsigned NumGPRRegsUsed = 0; | 600 // register to the assigned location of Arg. |
416 // 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 | |
418 // home register to the assigned location of Arg. | |
419 Context.init(Func->getEntryNode()); | 601 Context.init(Func->getEntryNode()); |
420 Context.setInsertPoint(Context.getCur()); | 602 Context.setInsertPoint(Context.getCur()); |
603 | |
421 for (SizeT I = 0, E = Args.size(); I < E; ++I) { | 604 for (SizeT I = 0, E = Args.size(); I < E; ++I) { |
422 Variable *Arg = Args[I]; | 605 Variable *Arg = Args[I]; |
423 Type Ty = Arg->getType(); | 606 Type Ty = Arg->getType(); |
424 // TODO(rkotler): handle float/vector types. | 607 RegNumT RegNum; |
425 if (isVectorType(Ty)) { | 608 if (!CC.argInReg(Ty, I, &RegNum)) { |
426 UnimplementedError(getFlags()); | |
427 continue; | 609 continue; |
428 } | 610 } |
429 if (isFloatingType(Ty)) { | 611 Variable *RegisterArg = Func->makeVariable(Ty); |
430 UnimplementedError(getFlags()); | 612 if (BuildDefs::dump()) { |
613 RegisterArg->setName(Func, "home_reg:" + Arg->getName()); | |
614 } | |
615 RegisterArg->setIsArg(); | |
616 Arg->setIsArg(false); | |
617 Args[I] = RegisterArg; | |
618 switch (Ty) { | |
619 default: { RegisterArg->setRegNum(RegNum); } break; | |
620 case IceType_i64: { | |
621 auto *RegisterArg64 = llvm::cast<Variable64On32>(RegisterArg); | |
622 RegisterArg64->initHiLo(Func); | |
623 RegisterArg64->getLo()->setRegNum( | |
624 RegNumT::fixme(RegMIPS32::getI64PairFirstGPRNum(RegNum))); | |
625 RegisterArg64->getHi()->setRegNum( | |
626 RegNumT::fixme(RegMIPS32::getI64PairSecondGPRNum(RegNum))); | |
627 } break; | |
628 } | |
629 Context.insert<InstAssign>(Arg, RegisterArg); | |
630 } | |
631 } | |
632 | |
633 Type TargetMIPS32::stackSlotType() { return IceType_i32; } | |
634 | |
635 // Helper function for addProlog(). | |
636 // | |
637 // This assumes Arg is an argument passed on the stack. This sets the frame | |
638 // offset for Arg and updates InArgsSizeBytes according to Arg's width. For an | |
639 // I64 arg that has been split into Lo and Hi components, it calls itself | |
640 // recursively on the components, taking care to handle Lo first because of the | |
641 // little-endian architecture. Lastly, this function generates an instruction | |
642 // to copy Arg into its assigned register if applicable. | |
643 void TargetMIPS32::finishArgumentLowering(Variable *Arg, Variable *FramePtr, | |
644 size_t BasicFrameOffset, | |
645 size_t *InArgsSizeBytes) { | |
646 const Type Ty = Arg->getType(); | |
647 *InArgsSizeBytes = applyStackAlignmentTy(*InArgsSizeBytes, Ty); | |
648 | |
649 if (auto *Arg64On32 = llvm::dyn_cast<Variable64On32>(Arg)) { | |
650 Variable *const Lo = Arg64On32->getLo(); | |
651 Variable *const Hi = Arg64On32->getHi(); | |
652 finishArgumentLowering(Lo, FramePtr, BasicFrameOffset, InArgsSizeBytes); | |
653 finishArgumentLowering(Hi, FramePtr, BasicFrameOffset, InArgsSizeBytes); | |
654 return; | |
655 } | |
656 assert(Ty != IceType_i64); | |
657 | |
658 const int32_t ArgStackOffset = BasicFrameOffset + *InArgsSizeBytes; | |
659 *InArgsSizeBytes += typeWidthInBytesOnStack(Ty); | |
660 | |
661 if (!Arg->hasReg()) { | |
662 Arg->setStackOffset(ArgStackOffset); | |
663 return; | |
664 } | |
665 | |
666 // If the argument variable has been assigned a register, we need to copy the | |
667 // value from the stack slot. | |
668 Variable *Parameter = Func->makeVariable(Ty); | |
669 Parameter->setMustNotHaveReg(); | |
670 Parameter->setStackOffset(ArgStackOffset); | |
671 _mov(Arg, Parameter); | |
672 } | |
673 | |
674 void TargetMIPS32::addProlog(CfgNode *Node) { | |
675 // Stack frame layout: | |
676 // | |
677 // +------------------------+ | |
678 // | 1. preserved registers | | |
679 // +------------------------+ | |
680 // | 2. padding | | |
681 // +------------------------+ | |
682 // | 3. global spill area | | |
683 // +------------------------+ | |
684 // | 4. padding | | |
685 // +------------------------+ | |
686 // | 5. local spill area | | |
687 // +------------------------+ | |
688 // | 6. padding | | |
689 // +------------------------+ | |
690 // | 7. allocas | | |
691 // +------------------------+ | |
692 // | 8. padding | | |
693 // +------------------------+ | |
694 // | 9. out args | | |
695 // +------------------------+ <--- StackPointer | |
696 // | |
697 // The following variables record the size in bytes of the given areas: | |
698 // * PreservedRegsSizeBytes: area 1 | |
699 // * SpillAreaPaddingBytes: area 2 | |
700 // * GlobalsSize: area 3 | |
701 // * GlobalsAndSubsequentPaddingSize: areas 3 - 4 | |
702 // * LocalsSpillAreaSize: area 5 | |
703 // * SpillAreaSizeBytes: areas 2 - 9 | |
704 // * maxOutArgsSizeBytes(): area 9 | |
705 | |
706 Context.init(Node); | |
707 Context.setInsertPoint(Context.getCur()); | |
708 | |
709 SmallBitVector CalleeSaves = getRegisterSet(RegSet_CalleeSave, RegSet_None); | |
710 RegsUsed = SmallBitVector(CalleeSaves.size()); | |
711 | |
712 VarList SortedSpilledVariables; | |
713 | |
714 size_t GlobalsSize = 0; | |
715 // If there is a separate locals area, this represents that area. Otherwise | |
716 // it counts any variable not counted by GlobalsSize. | |
717 SpillAreaSizeBytes = 0; | |
718 // If there is a separate locals area, this specifies the alignment for it. | |
719 uint32_t LocalsSlotsAlignmentBytes = 0; | |
720 // The entire spill locations area gets aligned to largest natural alignment | |
721 // of the variables that have a spill slot. | |
722 uint32_t SpillAreaAlignmentBytes = 0; | |
723 // For now, we don't have target-specific variables that need special | |
724 // treatment (no stack-slot-linked SpillVariable type). | |
725 std::function<bool(Variable *)> TargetVarHook = [](Variable *Var) { | |
726 static constexpr bool AssignStackSlot = false; | |
727 static constexpr bool DontAssignStackSlot = !AssignStackSlot; | |
728 if (llvm::isa<Variable64On32>(Var)) { | |
729 return DontAssignStackSlot; | |
730 } | |
731 return AssignStackSlot; | |
732 }; | |
733 | |
734 // Compute the list of spilled variables and bounds for GlobalsSize, etc. | |
735 getVarStackSlotParams(SortedSpilledVariables, RegsUsed, &GlobalsSize, | |
736 &SpillAreaSizeBytes, &SpillAreaAlignmentBytes, | |
737 &LocalsSlotsAlignmentBytes, TargetVarHook); | |
738 uint32_t LocalsSpillAreaSize = SpillAreaSizeBytes; | |
739 SpillAreaSizeBytes += GlobalsSize; | |
740 | |
741 PreservedGPRs.reserve(CalleeSaves.size()); | |
742 | |
743 // Consider FP and RA as callee-save / used as needed. | |
744 if (UsesFramePointer) { | |
745 if (RegsUsed[RegMIPS32::Reg_FP]) { | |
746 llvm::report_fatal_error("Frame pointer has been used."); | |
747 } | |
748 CalleeSaves[RegMIPS32::Reg_FP] = true; | |
749 RegsUsed[RegMIPS32::Reg_FP] = true; | |
750 } | |
751 if (!MaybeLeafFunc) { | |
752 CalleeSaves[RegMIPS32::Reg_RA] = true; | |
753 RegsUsed[RegMIPS32::Reg_RA] = true; | |
754 } | |
755 | |
756 // Make two passes over the used registers. The first pass records all the | |
757 // used registers -- and their aliases. Then, we figure out which GPR | |
758 // registers should be saved. | |
759 SmallBitVector ToPreserve(RegMIPS32::Reg_NUM); | |
760 for (SizeT i = 0; i < CalleeSaves.size(); ++i) { | |
761 if (CalleeSaves[i] && RegsUsed[i]) { | |
762 ToPreserve |= RegisterAliases[i]; | |
763 } | |
764 } | |
765 | |
766 uint32_t NumCallee = 0; | |
767 size_t PreservedRegsSizeBytes = 0; | |
768 | |
769 // RegClasses is a tuple of | |
770 // | |
771 // <First Register in Class, Last Register in Class, Vector of Save Registers> | |
772 // | |
773 // We use this tuple to figure out which register we should save/restore | |
774 // during | |
775 // prolog/epilog. | |
776 using RegClassType = std::tuple<uint32_t, uint32_t, VarList *>; | |
777 const RegClassType RegClass = RegClassType( | |
778 RegMIPS32::Reg_GPR_First, RegMIPS32::Reg_GPR_Last, &PreservedGPRs); | |
779 const uint32_t FirstRegInClass = std::get<0>(RegClass); | |
780 const uint32_t LastRegInClass = std::get<1>(RegClass); | |
781 VarList *const PreservedRegsInClass = std::get<2>(RegClass); | |
782 for (uint32_t Reg = LastRegInClass; Reg > FirstRegInClass; Reg--) { | |
783 if (!ToPreserve[Reg]) { | |
431 continue; | 784 continue; |
432 } | 785 } |
433 if (Ty == IceType_i64) { | 786 ++NumCallee; |
434 if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG) | 787 Variable *PhysicalRegister = getPhysicalRegister(RegNumT::fromInt(Reg)); |
435 continue; | 788 PreservedRegsSizeBytes += |
436 auto RegLo = RegNumT::fixme(RegMIPS32::Reg_A0 + NumGPRRegsUsed); | 789 typeWidthInBytesOnStack(PhysicalRegister->getType()); |
437 auto RegHi = RegNumT::fixme(RegLo + 1); | 790 PreservedRegsInClass->push_back(PhysicalRegister); |
438 ++NumGPRRegsUsed; | 791 } |
439 // Always start i64 registers at an even register, so this may end | 792 |
440 // up padding away a register. | 793 Ctx->statsUpdateRegistersSaved(NumCallee); |
441 if (RegLo % 2 != 0) { | 794 |
442 RegLo = RegNumT::fixme(RegLo + 1); | 795 // Align the variables area. SpillAreaPaddingBytes is the size of the region |
443 ++NumGPRRegsUsed; | 796 // after the preserved registers and before the spill areas. |
444 } | 797 // LocalsSlotsPaddingBytes is the amount of padding between the globals and |
445 // If this leaves us without room to consume another register, | 798 // locals area if they are separate. |
446 // leave any previously speculatively consumed registers as consumed. | 799 assert(SpillAreaAlignmentBytes <= MIPS32_STACK_ALIGNMENT_BYTES); |
447 if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG) | 800 (void)MIPS32_STACK_ALIGNMENT_BYTES; |
448 continue; | 801 assert(LocalsSlotsAlignmentBytes <= SpillAreaAlignmentBytes); |
449 // RegHi = RegNumT::fixme(RegMIPS32::Reg_A0 + NumGPRRegsUsed); | 802 uint32_t SpillAreaPaddingBytes = 0; |
450 ++NumGPRRegsUsed; | 803 uint32_t LocalsSlotsPaddingBytes = 0; |
451 Variable *RegisterArg = Func->makeVariable(Ty); | 804 alignStackSpillAreas(PreservedRegsSizeBytes, SpillAreaAlignmentBytes, |
452 auto *RegisterArg64On32 = llvm::cast<Variable64On32>(RegisterArg); | 805 GlobalsSize, LocalsSlotsAlignmentBytes, |
453 if (BuildDefs::dump()) | 806 &SpillAreaPaddingBytes, &LocalsSlotsPaddingBytes); |
454 RegisterArg64On32->setName(Func, "home_reg:" + Arg->getName()); | 807 SpillAreaSizeBytes += SpillAreaPaddingBytes + LocalsSlotsPaddingBytes; |
455 RegisterArg64On32->initHiLo(Func); | 808 uint32_t GlobalsAndSubsequentPaddingSize = |
456 RegisterArg64On32->setIsArg(); | 809 GlobalsSize + LocalsSlotsPaddingBytes; |
457 RegisterArg64On32->getLo()->setRegNum(RegLo); | 810 |
458 RegisterArg64On32->getHi()->setRegNum(RegHi); | 811 if (MaybeLeafFunc) |
459 Arg->setIsArg(false); | 812 MaxOutArgsSizeBytes = 0; |
460 Args[I] = RegisterArg64On32; | 813 |
461 Context.insert<InstAssign>(Arg, RegisterArg); | 814 // Adds the out args space to the stack, and align SP if necessary. |
815 uint32_t TotalStackSizeBytes = PreservedRegsSizeBytes + SpillAreaSizeBytes; | |
816 | |
817 // TODO(sagar.thakur): Combine fixed alloca and maximum out argument size with | |
818 // TotalStackSizeBytes once lowerAlloca is implemented and leaf function | |
819 // information is generated by lowerCall. | |
820 | |
821 // Generate "addiu sp, sp, -TotalStackSizeBytes" | |
822 if (TotalStackSizeBytes) { | |
823 // Use the scratch register if needed to legalize the immediate. | |
824 Variable *SP = getPhysicalRegister(RegMIPS32::Reg_SP); | |
825 _addiu(SP, SP, -(TotalStackSizeBytes)); | |
826 } | |
827 | |
828 Ctx->statsUpdateFrameBytes(TotalStackSizeBytes); | |
829 | |
830 if (!PreservedGPRs.empty()) { | |
831 uint32_t StackOffset = TotalStackSizeBytes; | |
832 for (Variable *Var : *PreservedRegsInClass) { | |
833 Variable *PhysicalRegister = getPhysicalRegister(Var->getRegNum()); | |
834 StackOffset -= typeWidthInBytesOnStack(PhysicalRegister->getType()); | |
835 Variable *SP = getPhysicalRegister(RegMIPS32::Reg_SP); | |
836 OperandMIPS32Mem *MemoryLocation = OperandMIPS32Mem::create( | |
837 Func, IceType_i32, SP, | |
838 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(StackOffset))); | |
839 _sw(PhysicalRegister, MemoryLocation); | |
840 } | |
841 } | |
842 | |
843 Variable *FP = getPhysicalRegister(RegMIPS32::Reg_FP); | |
844 | |
845 // Generate "mov FP, SP" if needed. | |
846 if (UsesFramePointer) { | |
847 Variable *SP = getPhysicalRegister(RegMIPS32::Reg_SP); | |
848 _mov(FP, SP); | |
849 // Keep FP live for late-stage liveness analysis (e.g. asm-verbose mode). | |
850 Context.insert<InstFakeUse>(FP); | |
851 } | |
852 | |
853 // Fill in stack offsets for stack args, and copy args into registers for | |
854 // those that were register-allocated. Args are pushed right to left, so | |
855 // Arg[0] is closest to the stack/frame pointer. | |
856 const VarList &Args = Func->getArgs(); | |
857 size_t InArgsSizeBytes = 0; | |
858 TargetMIPS32::CallingConv CC; | |
859 uint32_t ArgNo = 0; | |
860 | |
861 for (Variable *Arg : Args) { | |
862 RegNumT DummyReg; | |
863 const Type Ty = Arg->getType(); | |
864 // Skip arguments passed in registers. | |
865 if (CC.argInReg(Ty, ArgNo, &DummyReg)) { | |
866 ArgNo++; | |
462 continue; | 867 continue; |
463 } else { | 868 } else { |
464 assert(Ty == IceType_i32); | 869 finishArgumentLowering(Arg, FP, TotalStackSizeBytes, &InArgsSizeBytes); |
465 if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG) | 870 } |
466 continue; | 871 } |
467 const auto RegNum = RegNumT::fixme(RegMIPS32::Reg_A0 + NumGPRRegsUsed); | 872 |
468 ++NumGPRRegsUsed; | 873 // Fill in stack offsets for locals. |
469 Variable *RegisterArg = Func->makeVariable(Ty); | 874 assignVarStackSlots(SortedSpilledVariables, SpillAreaPaddingBytes, |
470 if (BuildDefs::dump()) { | 875 SpillAreaSizeBytes, GlobalsAndSubsequentPaddingSize, |
471 RegisterArg->setName(Func, "home_reg:" + Arg->getName()); | 876 UsesFramePointer); |
472 } | 877 this->HasComputedFrame = true; |
473 RegisterArg->setRegNum(RegNum); | 878 |
474 RegisterArg->setIsArg(); | 879 if (BuildDefs::dump() && Func->isVerbose(IceV_Frame)) { |
475 Arg->setIsArg(false); | 880 OstreamLocker _(Func->getContext()); |
476 Args[I] = RegisterArg; | 881 Ostream &Str = Func->getContext()->getStrDump(); |
477 Context.insert<InstAssign>(Arg, RegisterArg); | 882 |
478 } | 883 Str << "Stack layout:\n"; |
479 } | 884 uint32_t SPAdjustmentPaddingSize = |
480 } | 885 SpillAreaSizeBytes - LocalsSpillAreaSize - |
481 | 886 GlobalsAndSubsequentPaddingSize - SpillAreaPaddingBytes - |
482 Type TargetMIPS32::stackSlotType() { return IceType_i32; } | 887 MaxOutArgsSizeBytes; |
483 | 888 Str << " in-args = " << InArgsSizeBytes << " bytes\n" |
484 void TargetMIPS32::addProlog(CfgNode *Node) { | 889 << " preserved registers = " << PreservedRegsSizeBytes << " bytes\n" |
485 (void)Node; | 890 << " spill area padding = " << SpillAreaPaddingBytes << " bytes\n" |
891 << " globals spill area = " << GlobalsSize << " bytes\n" | |
892 << " globals-locals spill areas intermediate padding = " | |
893 << GlobalsAndSubsequentPaddingSize - GlobalsSize << " bytes\n" | |
894 << " locals spill area = " << LocalsSpillAreaSize << " bytes\n" | |
895 << " SP alignment padding = " << SPAdjustmentPaddingSize << " bytes\n"; | |
896 | |
897 Str << "Stack details:\n" | |
898 << " SP adjustment = " << SpillAreaSizeBytes << " bytes\n" | |
899 << " spill area alignment = " << SpillAreaAlignmentBytes << " bytes\n" | |
900 << " outgoing args size = " << MaxOutArgsSizeBytes << " bytes\n" | |
901 << " locals spill area alignment = " << LocalsSlotsAlignmentBytes | |
902 << " bytes\n" | |
903 << " is FP based = " << 1 << "\n"; | |
904 } | |
486 return; | 905 return; |
487 UnimplementedError(getFlags()); | |
488 } | 906 } |
489 | 907 |
490 void TargetMIPS32::addEpilog(CfgNode *Node) { | 908 void TargetMIPS32::addEpilog(CfgNode *Node) { |
491 (void)Node; | 909 (void)Node; |
492 return; | 910 return; |
493 UnimplementedError(getFlags()); | 911 UnimplementedError(getFlags()); |
494 } | 912 } |
495 | 913 |
496 Operand *TargetMIPS32::loOperand(Operand *Operand) { | 914 Operand *TargetMIPS32::loOperand(Operand *Operand) { |
497 assert(Operand->getType() == IceType_i64); | 915 assert(Operand->getType() == IceType_i64); |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
700 Operand *Src0 = legalizeUndef(Instr->getSrc(0)); | 1118 Operand *Src0 = legalizeUndef(Instr->getSrc(0)); |
701 Operand *Src1 = legalizeUndef(Instr->getSrc(1)); | 1119 Operand *Src1 = legalizeUndef(Instr->getSrc(1)); |
702 if (DestTy == IceType_i64) { | 1120 if (DestTy == IceType_i64) { |
703 lowerInt64Arithmetic(Instr, Instr->getDest(), Src0, Src1); | 1121 lowerInt64Arithmetic(Instr, Instr->getDest(), Src0, Src1); |
704 return; | 1122 return; |
705 } | 1123 } |
706 if (isVectorType(Dest->getType())) { | 1124 if (isVectorType(Dest->getType())) { |
707 UnimplementedLoweringError(this, Instr); | 1125 UnimplementedLoweringError(this, Instr); |
708 return; | 1126 return; |
709 } | 1127 } |
710 switch (Instr->getOp()) { | |
711 default: | |
712 break; | |
713 case InstArithmetic::Fadd: | |
714 case InstArithmetic::Fsub: | |
715 case InstArithmetic::Fmul: | |
716 case InstArithmetic::Fdiv: | |
717 case InstArithmetic::Frem: | |
718 UnimplementedLoweringError(this, Instr); | |
719 return; | |
720 } | |
721 | 1128 |
722 // At this point Dest->getType() is non-i64 scalar | 1129 // At this point Dest->getType() is non-i64 scalar |
723 | 1130 |
724 Variable *T = makeReg(Dest->getType()); | 1131 Variable *T = makeReg(Dest->getType()); |
725 Variable *Src0R = legalizeToReg(Src0); | 1132 Variable *Src0R = legalizeToReg(Src0); |
726 Variable *Src1R = legalizeToReg(Src1); | 1133 Variable *Src1R = legalizeToReg(Src1); |
727 | 1134 |
728 switch (Instr->getOp()) { | 1135 switch (Instr->getOp()) { |
729 case InstArithmetic::_num: | 1136 case InstArithmetic::_num: |
730 break; | 1137 break; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
789 _mov(Dest, T); | 1196 _mov(Dest, T); |
790 return; | 1197 return; |
791 } | 1198 } |
792 case InstArithmetic::Srem: { | 1199 case InstArithmetic::Srem: { |
793 auto *T_Zero = I32Reg(RegMIPS32::Reg_ZERO); | 1200 auto *T_Zero = I32Reg(RegMIPS32::Reg_ZERO); |
794 _div(T_Zero, Src0R, Src1R); | 1201 _div(T_Zero, Src0R, Src1R); |
795 _mfhi(T, T_Zero); | 1202 _mfhi(T, T_Zero); |
796 _mov(Dest, T); | 1203 _mov(Dest, T); |
797 return; | 1204 return; |
798 } | 1205 } |
799 case InstArithmetic::Fadd: | 1206 case InstArithmetic::Fadd: { |
1207 if (DestTy == IceType_f32) { | |
1208 _add_s(T, Src0R, Src1R); | |
1209 _mov_s(Dest, T); | |
Jim Stichnoth
2016/06/13 20:14:19
From this, I am seeing invalid asm code being gene
| |
1210 return; | |
1211 } | |
1212 if (DestTy == IceType_f64) { | |
1213 _add_d(T, Src0R, Src1R); | |
1214 _mov_d(Dest, T); | |
1215 return; | |
1216 } | |
800 break; | 1217 break; |
1218 } | |
801 case InstArithmetic::Fsub: | 1219 case InstArithmetic::Fsub: |
1220 if (DestTy == IceType_f32) { | |
1221 _sub_s(T, Src0R, Src1R); | |
1222 _mov_s(Dest, T); | |
1223 return; | |
1224 } | |
1225 if (DestTy == IceType_f64) { | |
1226 _sub_d(T, Src0R, Src1R); | |
1227 _mov_d(Dest, T); | |
1228 return; | |
1229 } | |
802 break; | 1230 break; |
803 case InstArithmetic::Fmul: | 1231 case InstArithmetic::Fmul: |
1232 if (DestTy == IceType_f32) { | |
1233 _mul_s(T, Src0R, Src1R); | |
1234 _mov_s(Dest, T); | |
1235 return; | |
1236 } | |
1237 if (DestTy == IceType_f64) { | |
1238 _mul_d(T, Src0R, Src1R); | |
1239 _mov_d(Dest, T); | |
1240 return; | |
1241 } | |
804 break; | 1242 break; |
805 case InstArithmetic::Fdiv: | 1243 case InstArithmetic::Fdiv: |
1244 if (DestTy == IceType_f32) { | |
1245 _div_s(T, Src0R, Src1R); | |
1246 _mov_s(Dest, T); | |
1247 return; | |
1248 } | |
1249 if (DestTy == IceType_f64) { | |
1250 _div_d(T, Src0R, Src1R); | |
1251 _mov_d(Dest, T); | |
1252 return; | |
1253 } | |
806 break; | 1254 break; |
807 case InstArithmetic::Frem: | 1255 case InstArithmetic::Frem: |
Jim Stichnoth
2016/06/13 20:14:19
For now, avoid a liveness validation error by addi
| |
808 break; | 1256 break; |
809 } | 1257 } |
810 UnimplementedLoweringError(this, Instr); | 1258 UnimplementedLoweringError(this, Instr); |
811 } | 1259 } |
812 | 1260 |
813 void TargetMIPS32::lowerAssign(const InstAssign *Instr) { | 1261 void TargetMIPS32::lowerAssign(const InstAssign *Instr) { |
814 Variable *Dest = Instr->getDest(); | 1262 Variable *Dest = Instr->getDest(); |
815 Operand *Src0 = Instr->getSrc(0); | 1263 Operand *Src0 = Instr->getSrc(0); |
816 assert(Dest->getType() == Src0->getType()); | 1264 assert(Dest->getType() == Src0->getType()); |
817 if (Dest->getType() == IceType_i64) { | 1265 if (Dest->getType() == IceType_i64) { |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
927 _slt(DestT, Src1R, Src0R); | 1375 _slt(DestT, Src1R, Src0R); |
928 _br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ); | 1376 _br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ); |
929 break; | 1377 break; |
930 } | 1378 } |
931 } | 1379 } |
932 } | 1380 } |
933 } | 1381 } |
934 | 1382 |
935 void TargetMIPS32::lowerCall(const InstCall *Instr) { | 1383 void TargetMIPS32::lowerCall(const InstCall *Instr) { |
936 // TODO(rkotler): assign arguments to registers and stack. Also reserve stack. | 1384 // TODO(rkotler): assign arguments to registers and stack. Also reserve stack. |
937 if (Instr->getNumArgs()) { | 1385 // if (Instr->getNumArgs()) { |
Jim Stichnoth
2016/06/13 20:14:19
remove this
| |
938 UnimplementedLoweringError(this, Instr); | 1386 // UnimplementedLoweringError(this, Instr); |
939 return; | 1387 // return; |
940 } | 1388 //} |
941 // Generate the call instruction. Assign its result to a temporary with high | 1389 // Generate the call instruction. Assign its result to a temporary with high |
942 // register allocation weight. | 1390 // register allocation weight. |
943 Variable *Dest = Instr->getDest(); | 1391 Variable *Dest = Instr->getDest(); |
944 // ReturnReg doubles as ReturnRegLo as necessary. | 1392 // ReturnReg doubles as ReturnRegLo as necessary. |
945 Variable *ReturnReg = nullptr; | 1393 Variable *ReturnReg = nullptr; |
946 Variable *ReturnRegHi = nullptr; | 1394 Variable *ReturnRegHi = nullptr; |
947 if (Dest) { | 1395 if (Dest) { |
948 switch (Dest->getType()) { | 1396 switch (Dest->getType()) { |
949 case IceType_NUM: | 1397 case IceType_NUM: |
950 llvm_unreachable("Invalid Call dest type"); | 1398 llvm_unreachable("Invalid Call dest type"); |
951 return; | 1399 return; |
952 case IceType_void: | 1400 case IceType_void: |
953 break; | 1401 break; |
954 case IceType_i1: | 1402 case IceType_i1: |
955 case IceType_i8: | 1403 case IceType_i8: |
956 case IceType_i16: | 1404 case IceType_i16: |
957 case IceType_i32: | 1405 case IceType_i32: |
958 ReturnReg = makeReg(Dest->getType(), RegMIPS32::Reg_V0); | 1406 ReturnReg = makeReg(Dest->getType(), RegMIPS32::Reg_V0); |
959 break; | 1407 break; |
960 case IceType_i64: | 1408 case IceType_i64: |
961 ReturnReg = I32Reg(RegMIPS32::Reg_V0); | 1409 ReturnReg = I32Reg(RegMIPS32::Reg_V0); |
962 ReturnRegHi = I32Reg(RegMIPS32::Reg_V1); | 1410 ReturnRegHi = I32Reg(RegMIPS32::Reg_V1); |
963 break; | 1411 break; |
964 case IceType_f32: | 1412 case IceType_f32: |
1413 ReturnReg = makeReg(Dest->getType(), RegMIPS32::Reg_F0); | |
1414 break; | |
965 case IceType_f64: | 1415 case IceType_f64: |
966 UnimplementedLoweringError(this, Instr); | 1416 ReturnReg = makeReg(Dest->getType(), RegMIPS32::Reg_F0F1); |
967 return; | 1417 break; |
968 case IceType_v4i1: | 1418 case IceType_v4i1: |
969 case IceType_v8i1: | 1419 case IceType_v8i1: |
970 case IceType_v16i1: | 1420 case IceType_v16i1: |
971 case IceType_v16i8: | 1421 case IceType_v16i8: |
972 case IceType_v8i16: | 1422 case IceType_v8i16: |
973 case IceType_v4i32: | 1423 case IceType_v4i32: |
974 case IceType_v4f32: | 1424 case IceType_v4f32: { |
975 UnimplementedLoweringError(this, Instr); | 1425 UnimplementedLoweringError(this, Instr); |
976 return; | 1426 return; |
977 } | 1427 } |
1428 } | |
978 } | 1429 } |
979 Operand *CallTarget = Instr->getCallTarget(); | 1430 Operand *CallTarget = Instr->getCallTarget(); |
980 // Allow ConstantRelocatable to be left alone as a direct call, | 1431 // Allow ConstantRelocatable to be left alone as a direct call, |
981 // but force other constants like ConstantInteger32 to be in | 1432 // but force other constants like ConstantInteger32 to be in |
982 // a register and make it an indirect call. | 1433 // a register and make it an indirect call. |
983 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { | 1434 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { |
984 CallTarget = legalize(CallTarget, Legal_Reg); | 1435 CallTarget = legalize(CallTarget, Legal_Reg); |
985 } | 1436 } |
986 Inst *NewCall = InstMIPS32Call::create(Func, ReturnReg, CallTarget); | 1437 Inst *NewCall = InstMIPS32Call::create(Func, ReturnReg, CallTarget); |
987 Context.insert(NewCall); | 1438 Context.insert(NewCall); |
988 if (ReturnRegHi) | 1439 if (ReturnRegHi) |
989 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); | 1440 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); |
990 // Insert a register-kill pseudo instruction. | 1441 // Insert a register-kill pseudo instruction. |
991 Context.insert(InstFakeKill::create(Func, NewCall)); | 1442 Context.insert(InstFakeKill::create(Func, NewCall)); |
992 // Generate a FakeUse to keep the call live if necessary. | 1443 // Generate a FakeUse to keep the call live if necessary. |
993 if (Instr->hasSideEffects() && ReturnReg) { | 1444 if (Instr->hasSideEffects() && ReturnReg) { |
994 Context.insert<InstFakeDef>(ReturnReg); | 1445 Context.insert<InstFakeDef>(ReturnReg); |
Jim Stichnoth
2016/06/13 20:14:19
InstFakeUse
| |
995 } | 1446 } |
996 if (Dest == nullptr) | 1447 if (Dest == nullptr) |
997 return; | 1448 return; |
998 | 1449 |
999 // Assign the result of the call to Dest. | 1450 // Assign the result of the call to Dest. |
1000 if (ReturnReg) { | 1451 if (ReturnReg) { |
1001 if (ReturnRegHi) { | 1452 auto *Zero = getZero(); |
1002 assert(Dest->getType() == IceType_i64); | 1453 switch (Dest->getType()) { |
1454 default: | |
1455 UnimplementedLoweringError(this, Instr); | |
1456 case IceType_i1: | |
1457 case IceType_i8: | |
1458 case IceType_i16: | |
1459 case IceType_i32: { | |
1460 _addu(Dest, Zero, ReturnReg); | |
1461 break; | |
1462 } | |
1463 case IceType_i64: { | |
1003 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); | 1464 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); |
1004 Variable *DestLo = Dest64On32->getLo(); | 1465 Variable *DestLo = Dest64On32->getLo(); |
1005 Variable *DestHi = Dest64On32->getHi(); | 1466 Variable *DestHi = Dest64On32->getHi(); |
1006 _mov(DestLo, ReturnReg); | 1467 _addu(DestLo, Zero, ReturnReg); |
1007 _mov(DestHi, ReturnRegHi); | 1468 _addu(DestHi, Zero, ReturnRegHi); |
1008 } else { | 1469 break; |
1009 assert(Dest->getType() == IceType_i32 || Dest->getType() == IceType_i16 || | 1470 } |
1010 Dest->getType() == IceType_i8 || Dest->getType() == IceType_i1 || | 1471 case IceType_f32: { |
1011 isVectorType(Dest->getType())); | 1472 _mov_s(Dest, ReturnReg); |
1012 if (isFloatingType(Dest->getType()) || isVectorType(Dest->getType())) { | 1473 break; |
1013 UnimplementedLoweringError(this, Instr); | 1474 } |
1014 return; | 1475 case IceType_f64: { |
1015 } else { | 1476 _mov_d(Dest, ReturnReg); |
1016 _mov(Dest, ReturnReg); | 1477 break; |
1017 } | 1478 } |
1479 case IceType_v4i1: | |
1480 case IceType_v8i1: | |
1481 case IceType_v16i1: | |
1482 case IceType_v16i8: | |
1483 case IceType_v8i16: | |
1484 case IceType_v4i32: | |
1485 case IceType_v4f32: { | |
1486 UnimplementedLoweringError(this, Instr); | |
1487 return; | |
1488 } | |
1018 } | 1489 } |
1019 } | 1490 } |
1020 } | 1491 } |
1021 | 1492 |
1022 void TargetMIPS32::lowerCast(const InstCast *Instr) { | 1493 void TargetMIPS32::lowerCast(const InstCast *Instr) { |
1023 InstCast::OpKind CastKind = Instr->getCastKind(); | 1494 InstCast::OpKind CastKind = Instr->getCastKind(); |
1024 Variable *Dest = Instr->getDest(); | 1495 Variable *Dest = Instr->getDest(); |
1025 Operand *Src0 = legalizeUndef(Instr->getSrc(0)); | 1496 Operand *Src0 = legalizeUndef(Instr->getSrc(0)); |
1026 const Type DestTy = Dest->getType(); | 1497 const Type DestTy = Dest->getType(); |
1027 const Type Src0Ty = Src0->getType(); | 1498 const Type Src0Ty = Src0->getType(); |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1416 } | 1887 } |
1417 | 1888 |
1418 void TargetMIPS32::lowerPhi(const InstPhi * /*Instr*/) { | 1889 void TargetMIPS32::lowerPhi(const InstPhi * /*Instr*/) { |
1419 Func->setError("Phi found in regular instruction list"); | 1890 Func->setError("Phi found in regular instruction list"); |
1420 } | 1891 } |
1421 | 1892 |
1422 void TargetMIPS32::lowerRet(const InstRet *Instr) { | 1893 void TargetMIPS32::lowerRet(const InstRet *Instr) { |
1423 Variable *Reg = nullptr; | 1894 Variable *Reg = nullptr; |
1424 if (Instr->hasRetValue()) { | 1895 if (Instr->hasRetValue()) { |
1425 Operand *Src0 = Instr->getRetValue(); | 1896 Operand *Src0 = Instr->getRetValue(); |
1897 | |
1426 switch (Src0->getType()) { | 1898 switch (Src0->getType()) { |
1899 default: | |
1900 UnimplementedLoweringError(this, Instr); | |
Jim Stichnoth
2016/06/13 20:14:19
You probably want a "break;" after this, otherwise
| |
1901 case IceType_f32: { | |
1902 if (auto *Src0V = llvm::dyn_cast<Variable>(Src0)) { | |
1903 Reg = makeReg(Src0V->getType(), RegMIPS32::Reg_F0); | |
1904 _mov_s(Reg, Src0V); | |
1905 } | |
1906 break; | |
1907 } | |
1908 case IceType_f64: { | |
1909 if (auto *Src0V = llvm::dyn_cast<Variable>(Src0)) { | |
1910 Reg = makeReg(Src0V->getType(), RegMIPS32::Reg_F0F1); | |
1911 _mov_d(Reg, Src0V); | |
1912 } | |
1913 break; | |
1914 } | |
1427 case IceType_i1: | 1915 case IceType_i1: |
1428 case IceType_i8: | 1916 case IceType_i8: |
1429 case IceType_i16: | 1917 case IceType_i16: |
1430 case IceType_i32: { | 1918 case IceType_i32: { |
1431 // Reg = legalizeToReg(Src0, RegMIPS32::Reg_V0); | 1919 // Reg = legalizeToReg(Src0, RegMIPS32::Reg_V0); |
1432 Operand *Src0F = legalize(Src0, Legal_Reg); | 1920 Operand *Src0F = legalize(Src0, Legal_Reg); |
1433 Reg = makeReg(Src0F->getType(), RegMIPS32::Reg_V0); | 1921 Reg = makeReg(Src0F->getType(), RegMIPS32::Reg_V0); |
1434 _mov(Reg, Src0F); | 1922 _mov(Reg, Src0F); |
1435 break; | 1923 break; |
1436 } | 1924 } |
1437 case IceType_i64: { | 1925 case IceType_i64: { |
1438 Src0 = legalizeUndef(Src0); | 1926 Src0 = legalizeUndef(Src0); |
1439 Variable *R0 = legalizeToReg(loOperand(Src0), RegMIPS32::Reg_V0); | 1927 Variable *R0 = legalizeToReg(loOperand(Src0), RegMIPS32::Reg_V0); |
1440 Variable *R1 = legalizeToReg(hiOperand(Src0), RegMIPS32::Reg_V1); | 1928 Variable *R1 = legalizeToReg(hiOperand(Src0), RegMIPS32::Reg_V1); |
1441 Reg = R0; | 1929 Reg = R0; |
1442 Context.insert<InstFakeUse>(R1); | 1930 Context.insert<InstFakeUse>(R1); |
1443 break; | 1931 break; |
1444 } | 1932 } |
1445 | 1933 case IceType_v4i1: |
1446 default: | 1934 case IceType_v8i1: |
1935 case IceType_v16i1: | |
1936 case IceType_v16i8: | |
1937 case IceType_v8i16: | |
1938 case IceType_v4i32: | |
1939 case IceType_v4f32: { | |
1447 UnimplementedLoweringError(this, Instr); | 1940 UnimplementedLoweringError(this, Instr); |
1941 break; | |
1942 } | |
1448 } | 1943 } |
1449 } | 1944 } |
1450 _ret(getPhysicalRegister(RegMIPS32::Reg_RA), Reg); | 1945 _ret(getPhysicalRegister(RegMIPS32::Reg_RA), Reg); |
1451 } | 1946 } |
1452 | 1947 |
1453 void TargetMIPS32::lowerSelect(const InstSelect *Instr) { | 1948 void TargetMIPS32::lowerSelect(const InstSelect *Instr) { |
1454 UnimplementedLoweringError(this, Instr); | 1949 UnimplementedLoweringError(this, Instr); |
1455 } | 1950 } |
1456 | 1951 |
1457 void TargetMIPS32::lowerShuffleVector(const InstShuffleVector *Instr) { | 1952 void TargetMIPS32::lowerShuffleVector(const InstShuffleVector *Instr) { |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1544 emitGlobal(*Var, SectionSuffix); | 2039 emitGlobal(*Var, SectionSuffix); |
1545 } | 2040 } |
1546 } | 2041 } |
1547 } break; | 2042 } break; |
1548 } | 2043 } |
1549 } | 2044 } |
1550 | 2045 |
1551 void TargetDataMIPS32::lowerConstants() { | 2046 void TargetDataMIPS32::lowerConstants() { |
1552 if (getFlags().getDisableTranslation()) | 2047 if (getFlags().getDisableTranslation()) |
1553 return; | 2048 return; |
1554 UnimplementedError(getFlags()); | 2049 // UnimplementedError(getFlags()); |
Jim Stichnoth
2016/06/13 20:14:19
remove this
| |
1555 } | 2050 } |
1556 | 2051 |
1557 void TargetDataMIPS32::lowerJumpTables() { | 2052 void TargetDataMIPS32::lowerJumpTables() { |
1558 if (getFlags().getDisableTranslation()) | 2053 if (getFlags().getDisableTranslation()) |
1559 return; | 2054 return; |
1560 UnimplementedError(getFlags()); | 2055 // UnimplementedError(getFlags()); |
Jim Stichnoth
2016/06/13 20:14:19
remove this
| |
1561 } | 2056 } |
1562 | 2057 |
1563 // Helper for legalize() to emit the right code to lower an operand to a | 2058 // Helper for legalize() to emit the right code to lower an operand to a |
1564 // register of the appropriate type. | 2059 // register of the appropriate type. |
1565 Variable *TargetMIPS32::copyToReg(Operand *Src, RegNumT RegNum) { | 2060 Variable *TargetMIPS32::copyToReg(Operand *Src, RegNumT RegNum) { |
1566 Type Ty = Src->getType(); | 2061 Type Ty = Src->getType(); |
1567 Variable *Reg = makeReg(Ty, RegNum); | 2062 Variable *Reg = makeReg(Ty, RegNum); |
1568 if (isVectorType(Ty) || isFloatingType(Ty)) { | 2063 if (isVectorType(Ty)) { |
1569 UnimplementedError(getFlags()); | 2064 UnimplementedError(getFlags()); |
2065 } else if (isFloatingType(Ty)) { | |
2066 (Ty == IceType_f32) ? _mov_s(Reg, llvm::dyn_cast<Variable>(Src)) | |
2067 : _mov_d(Reg, llvm::dyn_cast<Variable>(Src)); | |
1570 } else { | 2068 } else { |
1571 // Mov's Src operand can really only be the flexible second operand type | 2069 // Mov's Src operand can really only be the flexible second operand type |
1572 // or a register. Users should guarantee that. | 2070 // or a register. Users should guarantee that. |
1573 _mov(Reg, Src); | 2071 _mov(Reg, Src); |
1574 } | 2072 } |
1575 return Reg; | 2073 return Reg; |
1576 } | 2074 } |
1577 | 2075 |
1578 Operand *TargetMIPS32::legalize(Operand *From, LegalMask Allowed, | 2076 Operand *TargetMIPS32::legalize(Operand *From, LegalMask Allowed, |
1579 RegNumT RegNum) { | 2077 RegNumT RegNum) { |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1714 Str << "\t.set\t" | 2212 Str << "\t.set\t" |
1715 << "nomips16\n"; | 2213 << "nomips16\n"; |
1716 } | 2214 } |
1717 | 2215 |
1718 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; | 2216 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; |
1719 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; | 2217 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; |
1720 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; | 2218 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; |
1721 | 2219 |
1722 } // end of namespace MIPS32 | 2220 } // end of namespace MIPS32 |
1723 } // end of namespace Ice | 2221 } // end of namespace Ice |
OLD | NEW |