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 831 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
842 uint32_t LocalsSlotsPaddingBytes = 0; | 842 uint32_t LocalsSlotsPaddingBytes = 0; |
843 alignStackSpillAreas(PreservedRegsSizeBytes, SpillAreaAlignmentBytes, | 843 alignStackSpillAreas(PreservedRegsSizeBytes, SpillAreaAlignmentBytes, |
844 GlobalsSize, LocalsSlotsAlignmentBytes, | 844 GlobalsSize, LocalsSlotsAlignmentBytes, |
845 &SpillAreaPaddingBytes, &LocalsSlotsPaddingBytes); | 845 &SpillAreaPaddingBytes, &LocalsSlotsPaddingBytes); |
846 SpillAreaSizeBytes += SpillAreaPaddingBytes + LocalsSlotsPaddingBytes; | 846 SpillAreaSizeBytes += SpillAreaPaddingBytes + LocalsSlotsPaddingBytes; |
847 uint32_t GlobalsAndSubsequentPaddingSize = | 847 uint32_t GlobalsAndSubsequentPaddingSize = |
848 GlobalsSize + LocalsSlotsPaddingBytes; | 848 GlobalsSize + LocalsSlotsPaddingBytes; |
849 | 849 |
850 // Adds the out args space to the stack, and align SP if necessary. | 850 // Adds the out args space to the stack, and align SP if necessary. |
851 TotalStackSizeBytes = PreservedRegsSizeBytes + SpillAreaSizeBytes + | 851 TotalStackSizeBytes = PreservedRegsSizeBytes + SpillAreaSizeBytes + |
852 FixedAllocaSizeBytes + MaxOutArgsSizeBytes; | 852 FixedAllocaSizeBytes + |
| 853 (MaxOutArgsSizeBytes * (VariableAllocaUsed ? 0 : 1)); |
853 | 854 |
854 // Generate "addiu sp, sp, -TotalStackSizeBytes" | 855 // Generate "addiu sp, sp, -TotalStackSizeBytes" |
855 if (TotalStackSizeBytes) { | 856 if (TotalStackSizeBytes) { |
856 // Use the scratch register if needed to legalize the immediate. | 857 // Use the scratch register if needed to legalize the immediate. |
857 Variable *SP = getPhysicalRegister(RegMIPS32::Reg_SP); | 858 Variable *SP = getPhysicalRegister(RegMIPS32::Reg_SP); |
858 _addiu(SP, SP, -(TotalStackSizeBytes)); | 859 _addiu(SP, SP, -(TotalStackSizeBytes)); |
859 } | 860 } |
860 | 861 |
861 Ctx->statsUpdateFrameBytes(TotalStackSizeBytes); | 862 Ctx->statsUpdateFrameBytes(TotalStackSizeBytes); |
862 | 863 |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1118 // Constant size alloca. | 1119 // Constant size alloca. |
1119 if (!UseFramePointer) { | 1120 if (!UseFramePointer) { |
1120 // If we don't need a Frame Pointer, this alloca has a known offset to the | 1121 // If we don't need a Frame Pointer, this alloca has a known offset to the |
1121 // stack pointer. We don't need adjust the stack pointer, nor assign any | 1122 // stack pointer. We don't need adjust the stack pointer, nor assign any |
1122 // value to Dest, as Dest is rematerializable. | 1123 // value to Dest, as Dest is rematerializable. |
1123 assert(Dest->isRematerializable()); | 1124 assert(Dest->isRematerializable()); |
1124 Context.insert<InstFakeDef>(Dest); | 1125 Context.insert<InstFakeDef>(Dest); |
1125 return; | 1126 return; |
1126 } | 1127 } |
1127 } else { | 1128 } else { |
1128 UnimplementedLoweringError(this, Instr); | 1129 // Non-constant sizes need to be adjusted to the next highest multiple of |
| 1130 // the required alignment at runtime. |
| 1131 VariableAllocaUsed = true; |
| 1132 Variable *AlignAmount; |
| 1133 auto *TotalSizeR = legalizeToReg(TotalSize, Legal_Reg); |
| 1134 auto *T1 = I32Reg(); |
| 1135 auto *T2 = I32Reg(); |
| 1136 auto *T3 = I32Reg(); |
| 1137 auto *T4 = I32Reg(); |
| 1138 auto *T5 = I32Reg(); |
| 1139 _addiu(T1, TotalSizeR, MIPS32_STACK_ALIGNMENT_BYTES - 1); |
| 1140 _addiu(T2, getZero(), -MIPS32_STACK_ALIGNMENT_BYTES); |
| 1141 _and(T3, T1, T2); |
| 1142 _subu(T4, SP, T3); |
| 1143 if (Instr->getAlignInBytes()) { |
| 1144 AlignAmount = |
| 1145 legalizeToReg(Ctx->getConstantInt32(-AlignmentParam), Legal_Reg); |
| 1146 _and(T5, T4, AlignAmount); |
| 1147 _mov(Dest, T5); |
| 1148 } else { |
| 1149 _mov(Dest, T4); |
| 1150 } |
| 1151 _mov(SP, Dest); |
1129 return; | 1152 return; |
1130 } | 1153 } |
1131 | 1154 |
1132 // Add enough to the returned address to account for the out args area. | 1155 // Add enough to the returned address to account for the out args area. |
1133 if (MaxOutArgsSizeBytes > 0) { | 1156 if (MaxOutArgsSizeBytes > 0) { |
1134 Variable *T = makeReg(getPointerType()); | 1157 Variable *T = makeReg(getPointerType()); |
1135 _addiu(T, SP, MaxOutArgsSizeBytes); | 1158 _addiu(T, SP, MaxOutArgsSizeBytes); |
1136 _mov(Dest, T); | 1159 _mov(Dest, T); |
1137 } else { | 1160 } else { |
1138 _mov(Dest, SP); | 1161 _mov(Dest, SP); |
(...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1640 } | 1663 } |
1641 | 1664 |
1642 // Generate a FakeUse of register arguments so that they do not get dead code | 1665 // Generate a FakeUse of register arguments so that they do not get dead code |
1643 // eliminated as a result of the FakeKill of scratch registers after the call. | 1666 // eliminated as a result of the FakeKill of scratch registers after the call. |
1644 // These fake-uses need to be placed here to avoid argument registers from | 1667 // These fake-uses need to be placed here to avoid argument registers from |
1645 // being used during the legalizeToReg() calls above. | 1668 // being used during the legalizeToReg() calls above. |
1646 for (auto *RegArg : RegArgs) { | 1669 for (auto *RegArg : RegArgs) { |
1647 Context.insert<InstFakeUse>(RegArg); | 1670 Context.insert<InstFakeUse>(RegArg); |
1648 } | 1671 } |
1649 | 1672 |
| 1673 // If variable alloca is used the extra 16 bytes for argument build area |
| 1674 // will be allocated on stack before a call. |
| 1675 if (VariableAllocaUsed) |
| 1676 _addiu(SP, SP, -MaxOutArgsSizeBytes); |
| 1677 |
1650 Inst *NewCall = InstMIPS32Call::create(Func, ReturnReg, CallTarget); | 1678 Inst *NewCall = InstMIPS32Call::create(Func, ReturnReg, CallTarget); |
1651 Context.insert(NewCall); | 1679 Context.insert(NewCall); |
| 1680 |
| 1681 if (VariableAllocaUsed) |
| 1682 _addiu(SP, SP, MaxOutArgsSizeBytes); |
| 1683 |
| 1684 // Insert a fake use of stack pointer to avoid dead code elimination of addiu |
| 1685 // instruction. |
| 1686 Context.insert<InstFakeUse>(SP); |
| 1687 |
1652 if (ReturnRegHi) | 1688 if (ReturnRegHi) |
1653 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); | 1689 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); |
1654 // Insert a register-kill pseudo instruction. | 1690 // Insert a register-kill pseudo instruction. |
1655 Context.insert(InstFakeKill::create(Func, NewCall)); | 1691 Context.insert(InstFakeKill::create(Func, NewCall)); |
1656 // Generate a FakeUse to keep the call live if necessary. | 1692 // Generate a FakeUse to keep the call live if necessary. |
1657 if (Instr->hasSideEffects() && ReturnReg) { | 1693 if (Instr->hasSideEffects() && ReturnReg) { |
1658 Context.insert<InstFakeUse>(ReturnReg); | 1694 Context.insert<InstFakeUse>(ReturnReg); |
1659 } | 1695 } |
1660 if (Dest == nullptr) | 1696 if (Dest == nullptr) |
1661 return; | 1697 return; |
(...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2269 Reg = makeReg(Ty, RegNum); | 2305 Reg = makeReg(Ty, RegNum); |
2270 if (isInt<16>(int32_t(Value))) { | 2306 if (isInt<16>(int32_t(Value))) { |
2271 Variable *Zero = getPhysicalRegister(RegMIPS32::Reg_ZERO, Ty); | 2307 Variable *Zero = getPhysicalRegister(RegMIPS32::Reg_ZERO, Ty); |
2272 Context.insert<InstFakeDef>(Zero); | 2308 Context.insert<InstFakeDef>(Zero); |
2273 _addiu(Reg, Zero, Value); | 2309 _addiu(Reg, Zero, Value); |
2274 } else { | 2310 } else { |
2275 uint32_t UpperBits = (Value >> 16) & 0xFFFF; | 2311 uint32_t UpperBits = (Value >> 16) & 0xFFFF; |
2276 (void)UpperBits; | 2312 (void)UpperBits; |
2277 uint32_t LowerBits = Value & 0xFFFF; | 2313 uint32_t LowerBits = Value & 0xFFFF; |
2278 Variable *TReg = makeReg(Ty, RegNum); | 2314 Variable *TReg = makeReg(Ty, RegNum); |
2279 _lui(TReg, Ctx->getConstantInt32(UpperBits)); | 2315 if (LowerBits) { |
2280 _ori(Reg, TReg, LowerBits); | 2316 _lui(TReg, Ctx->getConstantInt32(UpperBits)); |
| 2317 _ori(Reg, TReg, LowerBits); |
| 2318 } else { |
| 2319 _lui(Reg, Ctx->getConstantInt32(UpperBits)); |
| 2320 } |
2281 } | 2321 } |
2282 return Reg; | 2322 return Reg; |
2283 } else if (isScalarFloatingType(Ty)) { | 2323 } else if (isScalarFloatingType(Ty)) { |
2284 // Load floats/doubles from literal pool. | 2324 // Load floats/doubles from literal pool. |
2285 auto *CFrom = llvm::cast<Constant>(From); | 2325 auto *CFrom = llvm::cast<Constant>(From); |
2286 assert(CFrom->getShouldBePooled()); | 2326 assert(CFrom->getShouldBePooled()); |
2287 Constant *Offset = Ctx->getConstantSym(0, CFrom->getLabelName()); | 2327 Constant *Offset = Ctx->getConstantSym(0, CFrom->getLabelName()); |
2288 Variable *TReg1 = makeReg(getPointerType()); | 2328 Variable *TReg1 = makeReg(getPointerType()); |
2289 Variable *TReg2 = makeReg(Ty); | 2329 Variable *TReg2 = makeReg(Ty); |
2290 Context.insert<InstFakeDef>(TReg2); | 2330 Context.insert<InstFakeDef>(TReg2); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2394 Str << "\t.set\t" | 2434 Str << "\t.set\t" |
2395 << "nomips16\n"; | 2435 << "nomips16\n"; |
2396 } | 2436 } |
2397 | 2437 |
2398 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; | 2438 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; |
2399 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; | 2439 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; |
2400 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; | 2440 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; |
2401 | 2441 |
2402 } // end of namespace MIPS32 | 2442 } // end of namespace MIPS32 |
2403 } // end of namespace Ice | 2443 } // end of namespace Ice |
OLD | NEW |