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 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 return; | 209 return; |
210 } | 210 } |
211 } | 211 } |
212 } | 212 } |
213 } | 213 } |
214 | 214 |
215 uint32_t TargetMIPS32::getStackAlignment() const { | 215 uint32_t TargetMIPS32::getStackAlignment() const { |
216 return MIPS32_STACK_ALIGNMENT_BYTES; | 216 return MIPS32_STACK_ALIGNMENT_BYTES; |
217 } | 217 } |
218 | 218 |
| 219 uint32_t TargetMIPS32::getCallStackArgumentsSizeBytes(const InstCall *Call) { |
| 220 TargetMIPS32::CallingConv CC; |
| 221 RegNumT DummyReg; |
| 222 size_t OutArgsSizeBytes = 0; |
| 223 for (SizeT i = 0, NumArgs = Call->getNumArgs(); i < NumArgs; ++i) { |
| 224 Operand *Arg = legalizeUndef(Call->getArg(i)); |
| 225 const Type Ty = Arg->getType(); |
| 226 RegNumT RegNum; |
| 227 if (CC.argInReg(Ty, i, &RegNum)) { |
| 228 continue; |
| 229 } |
| 230 |
| 231 OutArgsSizeBytes = applyStackAlignmentTy(OutArgsSizeBytes, Ty); |
| 232 OutArgsSizeBytes += typeWidthInBytesOnStack(Ty); |
| 233 } |
| 234 |
| 235 return applyStackAlignment(OutArgsSizeBytes); |
| 236 } |
| 237 |
219 void TargetMIPS32::genTargetHelperCallFor(Inst *Instr) { | 238 void TargetMIPS32::genTargetHelperCallFor(Inst *Instr) { |
220 constexpr bool NoTailCall = false; | 239 constexpr bool NoTailCall = false; |
221 constexpr bool IsTargetHelperCall = true; | 240 constexpr bool IsTargetHelperCall = true; |
222 | 241 |
223 switch (Instr->getKind()) { | 242 switch (Instr->getKind()) { |
224 default: | 243 default: |
225 return; | 244 return; |
226 case Inst::Arithmetic: { | 245 case Inst::Arithmetic: { |
227 Variable *Dest = Instr->getDest(); | 246 Variable *Dest = Instr->getDest(); |
228 const Type DestTy = Dest->getType(); | 247 const Type DestTy = Dest->getType(); |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
579 Context.init(Node); | 598 Context.init(Node); |
580 while (!Context.atEnd()) { | 599 while (!Context.atEnd()) { |
581 PostIncrLoweringContext PostIncrement(Context); | 600 PostIncrLoweringContext PostIncrement(Context); |
582 Inst *CurInstr = iteratorToInst(Context.getCur()); | 601 Inst *CurInstr = iteratorToInst(Context.getCur()); |
583 if (auto *Call = llvm::dyn_cast<InstCall>(CurInstr)) { | 602 if (auto *Call = llvm::dyn_cast<InstCall>(CurInstr)) { |
584 SizeT OutArgsSizeBytes = getCallStackArgumentsSizeBytes(Call); | 603 SizeT OutArgsSizeBytes = getCallStackArgumentsSizeBytes(Call); |
585 MaxOutArgsSizeBytes = std::max(MaxOutArgsSizeBytes, OutArgsSizeBytes); | 604 MaxOutArgsSizeBytes = std::max(MaxOutArgsSizeBytes, OutArgsSizeBytes); |
586 } | 605 } |
587 } | 606 } |
588 } | 607 } |
| 608 CurrentAllocaOffset = MaxOutArgsSizeBytes; |
589 } | 609 } |
590 | 610 |
591 void TargetMIPS32::translateO2() { | 611 void TargetMIPS32::translateO2() { |
592 TimerMarker T(TimerStack::TT_O2, Func); | 612 TimerMarker T(TimerStack::TT_O2, Func); |
593 | 613 |
594 // TODO(stichnot): share passes with X86? | 614 // TODO(stichnot): share passes with X86? |
595 // https://code.google.com/p/nativeclient/issues/detail?id=4094 | 615 // https://code.google.com/p/nativeclient/issues/detail?id=4094 |
596 genTargetHelperCalls(); | 616 genTargetHelperCalls(); |
597 | 617 |
598 unsetIfNonLeafFunc(); | 618 unsetIfNonLeafFunc(); |
(...skipping 1090 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1689 } else { | 1709 } else { |
1690 Target->_sw(SrcR, Addr); | 1710 Target->_sw(SrcR, Addr); |
1691 } | 1711 } |
1692 | 1712 |
1693 Target->Context.insert<InstFakeDef>(Dest); | 1713 Target->Context.insert<InstFakeDef>(Dest); |
1694 Legalized = true; | 1714 Legalized = true; |
1695 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { | 1715 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { |
1696 if (Var->isRematerializable()) { | 1716 if (Var->isRematerializable()) { |
1697 // This is equivalent to an x86 _lea(RematOffset(%esp/%ebp), Variable). | 1717 // This is equivalent to an x86 _lea(RematOffset(%esp/%ebp), Variable). |
1698 | 1718 |
1699 // ExtraOffset is only needed for frame-pointer based frames as we have | 1719 // ExtraOffset is only needed for stack-pointer based frames as we have |
1700 // to account for spill storage. | 1720 // to account for spill storage. |
1701 const int32_t ExtraOffset = (Var->getRegNum() == Target->getFrameReg()) | 1721 const int32_t ExtraOffset = (Var->getRegNum() == Target->getStackReg()) |
1702 ? Target->getFrameFixedAllocaOffset() | 1722 ? Target->getFrameFixedAllocaOffset() |
1703 : 0; | 1723 : 0; |
1704 | 1724 |
1705 const int32_t Offset = Var->getStackOffset() + ExtraOffset; | 1725 const int32_t Offset = Var->getStackOffset() + ExtraOffset; |
1706 Variable *Base = Target->getPhysicalRegister(Var->getRegNum()); | 1726 Variable *Base = Target->getPhysicalRegister(Var->getRegNum()); |
1707 Variable *T = newBaseRegister(Base, Offset, Dest->getRegNum()); | 1727 Variable *T = newBaseRegister(Base, Offset, Dest->getRegNum()); |
1708 Target->_mov(Dest, T); | 1728 Target->_mov(Dest, T); |
1709 Legalized = true; | 1729 Legalized = true; |
1710 } else { | 1730 } else { |
1711 if (!Var->hasReg()) { | 1731 if (!Var->hasReg()) { |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1915 FixedAllocaSizeBytes += Value; | 1935 FixedAllocaSizeBytes += Value; |
1916 // Constant size alloca. | 1936 // Constant size alloca. |
1917 if (!UseFramePointer) { | 1937 if (!UseFramePointer) { |
1918 // If we don't need a Frame Pointer, this alloca has a known offset to the | 1938 // If we don't need a Frame Pointer, this alloca has a known offset to the |
1919 // stack pointer. We don't need adjust the stack pointer, nor assign any | 1939 // stack pointer. We don't need adjust the stack pointer, nor assign any |
1920 // value to Dest, as Dest is rematerializable. | 1940 // value to Dest, as Dest is rematerializable. |
1921 assert(Dest->isRematerializable()); | 1941 assert(Dest->isRematerializable()); |
1922 Context.insert<InstFakeDef>(Dest); | 1942 Context.insert<InstFakeDef>(Dest); |
1923 return; | 1943 return; |
1924 } | 1944 } |
| 1945 |
| 1946 if (Alignment > MIPS32_STACK_ALIGNMENT_BYTES) { |
| 1947 CurrentAllocaOffset = |
| 1948 Utils::applyAlignment(CurrentAllocaOffset, Alignment); |
| 1949 } |
| 1950 auto *T = I32Reg(); |
| 1951 _addiu(T, SP, CurrentAllocaOffset); |
| 1952 _mov(Dest, T); |
| 1953 CurrentAllocaOffset += Value; |
| 1954 return; |
| 1955 |
1925 } else { | 1956 } else { |
1926 // Non-constant sizes need to be adjusted to the next highest multiple of | 1957 // Non-constant sizes need to be adjusted to the next highest multiple of |
1927 // the required alignment at runtime. | 1958 // the required alignment at runtime. |
1928 VariableAllocaUsed = true; | 1959 VariableAllocaUsed = true; |
1929 Variable *AlignAmount; | 1960 Variable *AlignAmount; |
1930 auto *TotalSizeR = legalizeToReg(TotalSize, Legal_Reg); | 1961 auto *TotalSizeR = legalizeToReg(TotalSize, Legal_Reg); |
1931 auto *T1 = I32Reg(); | 1962 auto *T1 = I32Reg(); |
1932 auto *T2 = I32Reg(); | 1963 auto *T2 = I32Reg(); |
1933 auto *T3 = I32Reg(); | 1964 auto *T3 = I32Reg(); |
1934 auto *T4 = I32Reg(); | 1965 auto *T4 = I32Reg(); |
1935 auto *T5 = I32Reg(); | 1966 auto *T5 = I32Reg(); |
1936 _addiu(T1, TotalSizeR, MIPS32_STACK_ALIGNMENT_BYTES - 1); | 1967 _addiu(T1, TotalSizeR, MIPS32_STACK_ALIGNMENT_BYTES - 1); |
1937 _addiu(T2, getZero(), -MIPS32_STACK_ALIGNMENT_BYTES); | 1968 _addiu(T2, getZero(), -MIPS32_STACK_ALIGNMENT_BYTES); |
1938 _and(T3, T1, T2); | 1969 _and(T3, T1, T2); |
1939 _subu(T4, SP, T3); | 1970 _subu(T4, SP, T3); |
1940 if (Instr->getAlignInBytes()) { | 1971 if (Instr->getAlignInBytes()) { |
1941 AlignAmount = | 1972 AlignAmount = |
1942 legalizeToReg(Ctx->getConstantInt32(-AlignmentParam), Legal_Reg); | 1973 legalizeToReg(Ctx->getConstantInt32(-AlignmentParam), Legal_Reg); |
1943 _and(T5, T4, AlignAmount); | 1974 _and(T5, T4, AlignAmount); |
1944 _mov(Dest, T5); | 1975 _mov(Dest, T5); |
1945 } else { | 1976 } else { |
1946 _mov(Dest, T4); | 1977 _mov(Dest, T4); |
1947 } | 1978 } |
1948 _mov(SP, Dest); | 1979 _mov(SP, Dest); |
1949 return; | 1980 return; |
1950 } | 1981 } |
1951 | |
1952 // Add enough to the returned address to account for the out args area. | |
1953 if (MaxOutArgsSizeBytes > 0) { | |
1954 Variable *T = makeReg(getPointerType()); | |
1955 _addiu(T, SP, MaxOutArgsSizeBytes); | |
1956 _mov(Dest, T); | |
1957 } else { | |
1958 _mov(Dest, SP); | |
1959 } | |
1960 } | 1982 } |
1961 | 1983 |
1962 void TargetMIPS32::lowerInt64Arithmetic(const InstArithmetic *Instr, | 1984 void TargetMIPS32::lowerInt64Arithmetic(const InstArithmetic *Instr, |
1963 Variable *Dest, Operand *Src0, | 1985 Variable *Dest, Operand *Src0, |
1964 Operand *Src1) { | 1986 Operand *Src1) { |
1965 InstArithmetic::OpKind Op = Instr->getOp(); | 1987 InstArithmetic::OpKind Op = Instr->getOp(); |
1966 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 1988 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
1967 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 1989 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
1968 Variable *Src0LoR = nullptr; | 1990 Variable *Src0LoR = nullptr; |
1969 Variable *Src1LoR = nullptr; | 1991 Variable *Src1LoR = nullptr; |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2229 return; | 2251 return; |
2230 } | 2252 } |
2231 default: | 2253 default: |
2232 UnimplementedLoweringError(this, Instr); | 2254 UnimplementedLoweringError(this, Instr); |
2233 return; | 2255 return; |
2234 } | 2256 } |
2235 } | 2257 } |
2236 | 2258 |
2237 void TargetMIPS32::lowerArithmetic(const InstArithmetic *Instr) { | 2259 void TargetMIPS32::lowerArithmetic(const InstArithmetic *Instr) { |
2238 Variable *Dest = Instr->getDest(); | 2260 Variable *Dest = Instr->getDest(); |
| 2261 |
| 2262 if (Dest->isRematerializable()) { |
| 2263 Context.insert<InstFakeDef>(Dest); |
| 2264 return; |
| 2265 } |
| 2266 |
2239 // We need to signal all the UnimplementedLoweringError errors before any | 2267 // We need to signal all the UnimplementedLoweringError errors before any |
2240 // legalization into new variables, otherwise Om1 register allocation may fail | 2268 // legalization into new variables, otherwise Om1 register allocation may fail |
2241 // when it sees variables that are defined but not used. | 2269 // when it sees variables that are defined but not used. |
2242 Type DestTy = Dest->getType(); | 2270 Type DestTy = Dest->getType(); |
2243 Operand *Src0 = legalizeUndef(Instr->getSrc(0)); | 2271 Operand *Src0 = legalizeUndef(Instr->getSrc(0)); |
2244 Operand *Src1 = legalizeUndef(Instr->getSrc(1)); | 2272 Operand *Src1 = legalizeUndef(Instr->getSrc(1)); |
2245 if (DestTy == IceType_i64) { | 2273 if (DestTy == IceType_i64) { |
2246 lowerInt64Arithmetic(Instr, Instr->getDest(), Src0, Src1); | 2274 lowerInt64Arithmetic(Instr, Instr->getDest(), Src0, Src1); |
2247 return; | 2275 return; |
2248 } | 2276 } |
(...skipping 2751 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5000 Str << "\t.set\t" | 5028 Str << "\t.set\t" |
5001 << "nomips16\n"; | 5029 << "nomips16\n"; |
5002 } | 5030 } |
5003 | 5031 |
5004 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; | 5032 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; |
5005 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; | 5033 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; |
5006 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; | 5034 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; |
5007 | 5035 |
5008 } // end of namespace MIPS32 | 5036 } // end of namespace MIPS32 |
5009 } // end of namespace Ice | 5037 } // end of namespace Ice |
OLD | NEW |