xref: /freebsd-src/contrib/llvm-project/clang/lib/CodeGen/Targets/Mips.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1*06c3fb27SDimitry Andric //===- Mips.cpp -----------------------------------------------------------===//
2*06c3fb27SDimitry Andric //
3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*06c3fb27SDimitry Andric //
7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
8*06c3fb27SDimitry Andric 
9*06c3fb27SDimitry Andric #include "ABIInfoImpl.h"
10*06c3fb27SDimitry Andric #include "TargetInfo.h"
11*06c3fb27SDimitry Andric 
12*06c3fb27SDimitry Andric using namespace clang;
13*06c3fb27SDimitry Andric using namespace clang::CodeGen;
14*06c3fb27SDimitry Andric 
15*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
16*06c3fb27SDimitry Andric // MIPS ABI Implementation.  This works for both little-endian and
17*06c3fb27SDimitry Andric // big-endian variants.
18*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
19*06c3fb27SDimitry Andric 
20*06c3fb27SDimitry Andric namespace {
21*06c3fb27SDimitry Andric class MipsABIInfo : public ABIInfo {
22*06c3fb27SDimitry Andric   bool IsO32;
23*06c3fb27SDimitry Andric   const unsigned MinABIStackAlignInBytes, StackAlignInBytes;
24*06c3fb27SDimitry Andric   void CoerceToIntArgs(uint64_t TySize,
25*06c3fb27SDimitry Andric                        SmallVectorImpl<llvm::Type *> &ArgList) const;
26*06c3fb27SDimitry Andric   llvm::Type* HandleAggregates(QualType Ty, uint64_t TySize) const;
27*06c3fb27SDimitry Andric   llvm::Type* returnAggregateInRegs(QualType RetTy, uint64_t Size) const;
28*06c3fb27SDimitry Andric   llvm::Type* getPaddingType(uint64_t Align, uint64_t Offset) const;
29*06c3fb27SDimitry Andric public:
30*06c3fb27SDimitry Andric   MipsABIInfo(CodeGenTypes &CGT, bool _IsO32) :
31*06c3fb27SDimitry Andric     ABIInfo(CGT), IsO32(_IsO32), MinABIStackAlignInBytes(IsO32 ? 4 : 8),
32*06c3fb27SDimitry Andric     StackAlignInBytes(IsO32 ? 8 : 16) {}
33*06c3fb27SDimitry Andric 
34*06c3fb27SDimitry Andric   ABIArgInfo classifyReturnType(QualType RetTy) const;
35*06c3fb27SDimitry Andric   ABIArgInfo classifyArgumentType(QualType RetTy, uint64_t &Offset) const;
36*06c3fb27SDimitry Andric   void computeInfo(CGFunctionInfo &FI) const override;
37*06c3fb27SDimitry Andric   Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
38*06c3fb27SDimitry Andric                     QualType Ty) const override;
39*06c3fb27SDimitry Andric   ABIArgInfo extendType(QualType Ty) const;
40*06c3fb27SDimitry Andric };
41*06c3fb27SDimitry Andric 
42*06c3fb27SDimitry Andric class MIPSTargetCodeGenInfo : public TargetCodeGenInfo {
43*06c3fb27SDimitry Andric   unsigned SizeOfUnwindException;
44*06c3fb27SDimitry Andric public:
45*06c3fb27SDimitry Andric   MIPSTargetCodeGenInfo(CodeGenTypes &CGT, bool IsO32)
46*06c3fb27SDimitry Andric       : TargetCodeGenInfo(std::make_unique<MipsABIInfo>(CGT, IsO32)),
47*06c3fb27SDimitry Andric         SizeOfUnwindException(IsO32 ? 24 : 32) {}
48*06c3fb27SDimitry Andric 
49*06c3fb27SDimitry Andric   int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override {
50*06c3fb27SDimitry Andric     return 29;
51*06c3fb27SDimitry Andric   }
52*06c3fb27SDimitry Andric 
53*06c3fb27SDimitry Andric   void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
54*06c3fb27SDimitry Andric                            CodeGen::CodeGenModule &CGM) const override {
55*06c3fb27SDimitry Andric     const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
56*06c3fb27SDimitry Andric     if (!FD) return;
57*06c3fb27SDimitry Andric     llvm::Function *Fn = cast<llvm::Function>(GV);
58*06c3fb27SDimitry Andric 
59*06c3fb27SDimitry Andric     if (FD->hasAttr<MipsLongCallAttr>())
60*06c3fb27SDimitry Andric       Fn->addFnAttr("long-call");
61*06c3fb27SDimitry Andric     else if (FD->hasAttr<MipsShortCallAttr>())
62*06c3fb27SDimitry Andric       Fn->addFnAttr("short-call");
63*06c3fb27SDimitry Andric 
64*06c3fb27SDimitry Andric     // Other attributes do not have a meaning for declarations.
65*06c3fb27SDimitry Andric     if (GV->isDeclaration())
66*06c3fb27SDimitry Andric       return;
67*06c3fb27SDimitry Andric 
68*06c3fb27SDimitry Andric     if (FD->hasAttr<Mips16Attr>()) {
69*06c3fb27SDimitry Andric       Fn->addFnAttr("mips16");
70*06c3fb27SDimitry Andric     }
71*06c3fb27SDimitry Andric     else if (FD->hasAttr<NoMips16Attr>()) {
72*06c3fb27SDimitry Andric       Fn->addFnAttr("nomips16");
73*06c3fb27SDimitry Andric     }
74*06c3fb27SDimitry Andric 
75*06c3fb27SDimitry Andric     if (FD->hasAttr<MicroMipsAttr>())
76*06c3fb27SDimitry Andric       Fn->addFnAttr("micromips");
77*06c3fb27SDimitry Andric     else if (FD->hasAttr<NoMicroMipsAttr>())
78*06c3fb27SDimitry Andric       Fn->addFnAttr("nomicromips");
79*06c3fb27SDimitry Andric 
80*06c3fb27SDimitry Andric     const MipsInterruptAttr *Attr = FD->getAttr<MipsInterruptAttr>();
81*06c3fb27SDimitry Andric     if (!Attr)
82*06c3fb27SDimitry Andric       return;
83*06c3fb27SDimitry Andric 
84*06c3fb27SDimitry Andric     const char *Kind;
85*06c3fb27SDimitry Andric     switch (Attr->getInterrupt()) {
86*06c3fb27SDimitry Andric     case MipsInterruptAttr::eic:     Kind = "eic"; break;
87*06c3fb27SDimitry Andric     case MipsInterruptAttr::sw0:     Kind = "sw0"; break;
88*06c3fb27SDimitry Andric     case MipsInterruptAttr::sw1:     Kind = "sw1"; break;
89*06c3fb27SDimitry Andric     case MipsInterruptAttr::hw0:     Kind = "hw0"; break;
90*06c3fb27SDimitry Andric     case MipsInterruptAttr::hw1:     Kind = "hw1"; break;
91*06c3fb27SDimitry Andric     case MipsInterruptAttr::hw2:     Kind = "hw2"; break;
92*06c3fb27SDimitry Andric     case MipsInterruptAttr::hw3:     Kind = "hw3"; break;
93*06c3fb27SDimitry Andric     case MipsInterruptAttr::hw4:     Kind = "hw4"; break;
94*06c3fb27SDimitry Andric     case MipsInterruptAttr::hw5:     Kind = "hw5"; break;
95*06c3fb27SDimitry Andric     }
96*06c3fb27SDimitry Andric 
97*06c3fb27SDimitry Andric     Fn->addFnAttr("interrupt", Kind);
98*06c3fb27SDimitry Andric 
99*06c3fb27SDimitry Andric   }
100*06c3fb27SDimitry Andric 
101*06c3fb27SDimitry Andric   bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
102*06c3fb27SDimitry Andric                                llvm::Value *Address) const override;
103*06c3fb27SDimitry Andric 
104*06c3fb27SDimitry Andric   unsigned getSizeOfUnwindException() const override {
105*06c3fb27SDimitry Andric     return SizeOfUnwindException;
106*06c3fb27SDimitry Andric   }
107*06c3fb27SDimitry Andric };
108*06c3fb27SDimitry Andric }
109*06c3fb27SDimitry Andric 
110*06c3fb27SDimitry Andric void MipsABIInfo::CoerceToIntArgs(
111*06c3fb27SDimitry Andric     uint64_t TySize, SmallVectorImpl<llvm::Type *> &ArgList) const {
112*06c3fb27SDimitry Andric   llvm::IntegerType *IntTy =
113*06c3fb27SDimitry Andric     llvm::IntegerType::get(getVMContext(), MinABIStackAlignInBytes * 8);
114*06c3fb27SDimitry Andric 
115*06c3fb27SDimitry Andric   // Add (TySize / MinABIStackAlignInBytes) args of IntTy.
116*06c3fb27SDimitry Andric   for (unsigned N = TySize / (MinABIStackAlignInBytes * 8); N; --N)
117*06c3fb27SDimitry Andric     ArgList.push_back(IntTy);
118*06c3fb27SDimitry Andric 
119*06c3fb27SDimitry Andric   // If necessary, add one more integer type to ArgList.
120*06c3fb27SDimitry Andric   unsigned R = TySize % (MinABIStackAlignInBytes * 8);
121*06c3fb27SDimitry Andric 
122*06c3fb27SDimitry Andric   if (R)
123*06c3fb27SDimitry Andric     ArgList.push_back(llvm::IntegerType::get(getVMContext(), R));
124*06c3fb27SDimitry Andric }
125*06c3fb27SDimitry Andric 
126*06c3fb27SDimitry Andric // In N32/64, an aligned double precision floating point field is passed in
127*06c3fb27SDimitry Andric // a register.
128*06c3fb27SDimitry Andric llvm::Type* MipsABIInfo::HandleAggregates(QualType Ty, uint64_t TySize) const {
129*06c3fb27SDimitry Andric   SmallVector<llvm::Type*, 8> ArgList, IntArgList;
130*06c3fb27SDimitry Andric 
131*06c3fb27SDimitry Andric   if (IsO32) {
132*06c3fb27SDimitry Andric     CoerceToIntArgs(TySize, ArgList);
133*06c3fb27SDimitry Andric     return llvm::StructType::get(getVMContext(), ArgList);
134*06c3fb27SDimitry Andric   }
135*06c3fb27SDimitry Andric 
136*06c3fb27SDimitry Andric   if (Ty->isComplexType())
137*06c3fb27SDimitry Andric     return CGT.ConvertType(Ty);
138*06c3fb27SDimitry Andric 
139*06c3fb27SDimitry Andric   const RecordType *RT = Ty->getAs<RecordType>();
140*06c3fb27SDimitry Andric 
141*06c3fb27SDimitry Andric   // Unions/vectors are passed in integer registers.
142*06c3fb27SDimitry Andric   if (!RT || !RT->isStructureOrClassType()) {
143*06c3fb27SDimitry Andric     CoerceToIntArgs(TySize, ArgList);
144*06c3fb27SDimitry Andric     return llvm::StructType::get(getVMContext(), ArgList);
145*06c3fb27SDimitry Andric   }
146*06c3fb27SDimitry Andric 
147*06c3fb27SDimitry Andric   const RecordDecl *RD = RT->getDecl();
148*06c3fb27SDimitry Andric   const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
149*06c3fb27SDimitry Andric   assert(!(TySize % 8) && "Size of structure must be multiple of 8.");
150*06c3fb27SDimitry Andric 
151*06c3fb27SDimitry Andric   uint64_t LastOffset = 0;
152*06c3fb27SDimitry Andric   unsigned idx = 0;
153*06c3fb27SDimitry Andric   llvm::IntegerType *I64 = llvm::IntegerType::get(getVMContext(), 64);
154*06c3fb27SDimitry Andric 
155*06c3fb27SDimitry Andric   // Iterate over fields in the struct/class and check if there are any aligned
156*06c3fb27SDimitry Andric   // double fields.
157*06c3fb27SDimitry Andric   for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
158*06c3fb27SDimitry Andric        i != e; ++i, ++idx) {
159*06c3fb27SDimitry Andric     const QualType Ty = i->getType();
160*06c3fb27SDimitry Andric     const BuiltinType *BT = Ty->getAs<BuiltinType>();
161*06c3fb27SDimitry Andric 
162*06c3fb27SDimitry Andric     if (!BT || BT->getKind() != BuiltinType::Double)
163*06c3fb27SDimitry Andric       continue;
164*06c3fb27SDimitry Andric 
165*06c3fb27SDimitry Andric     uint64_t Offset = Layout.getFieldOffset(idx);
166*06c3fb27SDimitry Andric     if (Offset % 64) // Ignore doubles that are not aligned.
167*06c3fb27SDimitry Andric       continue;
168*06c3fb27SDimitry Andric 
169*06c3fb27SDimitry Andric     // Add ((Offset - LastOffset) / 64) args of type i64.
170*06c3fb27SDimitry Andric     for (unsigned j = (Offset - LastOffset) / 64; j > 0; --j)
171*06c3fb27SDimitry Andric       ArgList.push_back(I64);
172*06c3fb27SDimitry Andric 
173*06c3fb27SDimitry Andric     // Add double type.
174*06c3fb27SDimitry Andric     ArgList.push_back(llvm::Type::getDoubleTy(getVMContext()));
175*06c3fb27SDimitry Andric     LastOffset = Offset + 64;
176*06c3fb27SDimitry Andric   }
177*06c3fb27SDimitry Andric 
178*06c3fb27SDimitry Andric   CoerceToIntArgs(TySize - LastOffset, IntArgList);
179*06c3fb27SDimitry Andric   ArgList.append(IntArgList.begin(), IntArgList.end());
180*06c3fb27SDimitry Andric 
181*06c3fb27SDimitry Andric   return llvm::StructType::get(getVMContext(), ArgList);
182*06c3fb27SDimitry Andric }
183*06c3fb27SDimitry Andric 
184*06c3fb27SDimitry Andric llvm::Type *MipsABIInfo::getPaddingType(uint64_t OrigOffset,
185*06c3fb27SDimitry Andric                                         uint64_t Offset) const {
186*06c3fb27SDimitry Andric   if (OrigOffset + MinABIStackAlignInBytes > Offset)
187*06c3fb27SDimitry Andric     return nullptr;
188*06c3fb27SDimitry Andric 
189*06c3fb27SDimitry Andric   return llvm::IntegerType::get(getVMContext(), (Offset - OrigOffset) * 8);
190*06c3fb27SDimitry Andric }
191*06c3fb27SDimitry Andric 
192*06c3fb27SDimitry Andric ABIArgInfo
193*06c3fb27SDimitry Andric MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const {
194*06c3fb27SDimitry Andric   Ty = useFirstFieldIfTransparentUnion(Ty);
195*06c3fb27SDimitry Andric 
196*06c3fb27SDimitry Andric   uint64_t OrigOffset = Offset;
197*06c3fb27SDimitry Andric   uint64_t TySize = getContext().getTypeSize(Ty);
198*06c3fb27SDimitry Andric   uint64_t Align = getContext().getTypeAlign(Ty) / 8;
199*06c3fb27SDimitry Andric 
200*06c3fb27SDimitry Andric   Align = std::clamp(Align, (uint64_t)MinABIStackAlignInBytes,
201*06c3fb27SDimitry Andric                      (uint64_t)StackAlignInBytes);
202*06c3fb27SDimitry Andric   unsigned CurrOffset = llvm::alignTo(Offset, Align);
203*06c3fb27SDimitry Andric   Offset = CurrOffset + llvm::alignTo(TySize, Align * 8) / 8;
204*06c3fb27SDimitry Andric 
205*06c3fb27SDimitry Andric   if (isAggregateTypeForABI(Ty) || Ty->isVectorType()) {
206*06c3fb27SDimitry Andric     // Ignore empty aggregates.
207*06c3fb27SDimitry Andric     if (TySize == 0)
208*06c3fb27SDimitry Andric       return ABIArgInfo::getIgnore();
209*06c3fb27SDimitry Andric 
210*06c3fb27SDimitry Andric     if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
211*06c3fb27SDimitry Andric       Offset = OrigOffset + MinABIStackAlignInBytes;
212*06c3fb27SDimitry Andric       return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
213*06c3fb27SDimitry Andric     }
214*06c3fb27SDimitry Andric 
215*06c3fb27SDimitry Andric     // If we have reached here, aggregates are passed directly by coercing to
216*06c3fb27SDimitry Andric     // another structure type. Padding is inserted if the offset of the
217*06c3fb27SDimitry Andric     // aggregate is unaligned.
218*06c3fb27SDimitry Andric     ABIArgInfo ArgInfo =
219*06c3fb27SDimitry Andric         ABIArgInfo::getDirect(HandleAggregates(Ty, TySize), 0,
220*06c3fb27SDimitry Andric                               getPaddingType(OrigOffset, CurrOffset));
221*06c3fb27SDimitry Andric     ArgInfo.setInReg(true);
222*06c3fb27SDimitry Andric     return ArgInfo;
223*06c3fb27SDimitry Andric   }
224*06c3fb27SDimitry Andric 
225*06c3fb27SDimitry Andric   // Treat an enum type as its underlying type.
226*06c3fb27SDimitry Andric   if (const EnumType *EnumTy = Ty->getAs<EnumType>())
227*06c3fb27SDimitry Andric     Ty = EnumTy->getDecl()->getIntegerType();
228*06c3fb27SDimitry Andric 
229*06c3fb27SDimitry Andric   // Make sure we pass indirectly things that are too large.
230*06c3fb27SDimitry Andric   if (const auto *EIT = Ty->getAs<BitIntType>())
231*06c3fb27SDimitry Andric     if (EIT->getNumBits() > 128 ||
232*06c3fb27SDimitry Andric         (EIT->getNumBits() > 64 &&
233*06c3fb27SDimitry Andric          !getContext().getTargetInfo().hasInt128Type()))
234*06c3fb27SDimitry Andric       return getNaturalAlignIndirect(Ty);
235*06c3fb27SDimitry Andric 
236*06c3fb27SDimitry Andric   // All integral types are promoted to the GPR width.
237*06c3fb27SDimitry Andric   if (Ty->isIntegralOrEnumerationType())
238*06c3fb27SDimitry Andric     return extendType(Ty);
239*06c3fb27SDimitry Andric 
240*06c3fb27SDimitry Andric   return ABIArgInfo::getDirect(
241*06c3fb27SDimitry Andric       nullptr, 0, IsO32 ? nullptr : getPaddingType(OrigOffset, CurrOffset));
242*06c3fb27SDimitry Andric }
243*06c3fb27SDimitry Andric 
244*06c3fb27SDimitry Andric llvm::Type*
245*06c3fb27SDimitry Andric MipsABIInfo::returnAggregateInRegs(QualType RetTy, uint64_t Size) const {
246*06c3fb27SDimitry Andric   const RecordType *RT = RetTy->getAs<RecordType>();
247*06c3fb27SDimitry Andric   SmallVector<llvm::Type*, 8> RTList;
248*06c3fb27SDimitry Andric 
249*06c3fb27SDimitry Andric   if (RT && RT->isStructureOrClassType()) {
250*06c3fb27SDimitry Andric     const RecordDecl *RD = RT->getDecl();
251*06c3fb27SDimitry Andric     const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
252*06c3fb27SDimitry Andric     unsigned FieldCnt = Layout.getFieldCount();
253*06c3fb27SDimitry Andric 
254*06c3fb27SDimitry Andric     // N32/64 returns struct/classes in floating point registers if the
255*06c3fb27SDimitry Andric     // following conditions are met:
256*06c3fb27SDimitry Andric     // 1. The size of the struct/class is no larger than 128-bit.
257*06c3fb27SDimitry Andric     // 2. The struct/class has one or two fields all of which are floating
258*06c3fb27SDimitry Andric     //    point types.
259*06c3fb27SDimitry Andric     // 3. The offset of the first field is zero (this follows what gcc does).
260*06c3fb27SDimitry Andric     //
261*06c3fb27SDimitry Andric     // Any other composite results are returned in integer registers.
262*06c3fb27SDimitry Andric     //
263*06c3fb27SDimitry Andric     if (FieldCnt && (FieldCnt <= 2) && !Layout.getFieldOffset(0)) {
264*06c3fb27SDimitry Andric       RecordDecl::field_iterator b = RD->field_begin(), e = RD->field_end();
265*06c3fb27SDimitry Andric       for (; b != e; ++b) {
266*06c3fb27SDimitry Andric         const BuiltinType *BT = b->getType()->getAs<BuiltinType>();
267*06c3fb27SDimitry Andric 
268*06c3fb27SDimitry Andric         if (!BT || !BT->isFloatingPoint())
269*06c3fb27SDimitry Andric           break;
270*06c3fb27SDimitry Andric 
271*06c3fb27SDimitry Andric         RTList.push_back(CGT.ConvertType(b->getType()));
272*06c3fb27SDimitry Andric       }
273*06c3fb27SDimitry Andric 
274*06c3fb27SDimitry Andric       if (b == e)
275*06c3fb27SDimitry Andric         return llvm::StructType::get(getVMContext(), RTList,
276*06c3fb27SDimitry Andric                                      RD->hasAttr<PackedAttr>());
277*06c3fb27SDimitry Andric 
278*06c3fb27SDimitry Andric       RTList.clear();
279*06c3fb27SDimitry Andric     }
280*06c3fb27SDimitry Andric   }
281*06c3fb27SDimitry Andric 
282*06c3fb27SDimitry Andric   CoerceToIntArgs(Size, RTList);
283*06c3fb27SDimitry Andric   return llvm::StructType::get(getVMContext(), RTList);
284*06c3fb27SDimitry Andric }
285*06c3fb27SDimitry Andric 
286*06c3fb27SDimitry Andric ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const {
287*06c3fb27SDimitry Andric   uint64_t Size = getContext().getTypeSize(RetTy);
288*06c3fb27SDimitry Andric 
289*06c3fb27SDimitry Andric   if (RetTy->isVoidType())
290*06c3fb27SDimitry Andric     return ABIArgInfo::getIgnore();
291*06c3fb27SDimitry Andric 
292*06c3fb27SDimitry Andric   // O32 doesn't treat zero-sized structs differently from other structs.
293*06c3fb27SDimitry Andric   // However, N32/N64 ignores zero sized return values.
294*06c3fb27SDimitry Andric   if (!IsO32 && Size == 0)
295*06c3fb27SDimitry Andric     return ABIArgInfo::getIgnore();
296*06c3fb27SDimitry Andric 
297*06c3fb27SDimitry Andric   if (isAggregateTypeForABI(RetTy) || RetTy->isVectorType()) {
298*06c3fb27SDimitry Andric     if (Size <= 128) {
299*06c3fb27SDimitry Andric       if (RetTy->isAnyComplexType())
300*06c3fb27SDimitry Andric         return ABIArgInfo::getDirect();
301*06c3fb27SDimitry Andric 
302*06c3fb27SDimitry Andric       // O32 returns integer vectors in registers and N32/N64 returns all small
303*06c3fb27SDimitry Andric       // aggregates in registers.
304*06c3fb27SDimitry Andric       if (!IsO32 ||
305*06c3fb27SDimitry Andric           (RetTy->isVectorType() && !RetTy->hasFloatingRepresentation())) {
306*06c3fb27SDimitry Andric         ABIArgInfo ArgInfo =
307*06c3fb27SDimitry Andric             ABIArgInfo::getDirect(returnAggregateInRegs(RetTy, Size));
308*06c3fb27SDimitry Andric         ArgInfo.setInReg(true);
309*06c3fb27SDimitry Andric         return ArgInfo;
310*06c3fb27SDimitry Andric       }
311*06c3fb27SDimitry Andric     }
312*06c3fb27SDimitry Andric 
313*06c3fb27SDimitry Andric     return getNaturalAlignIndirect(RetTy);
314*06c3fb27SDimitry Andric   }
315*06c3fb27SDimitry Andric 
316*06c3fb27SDimitry Andric   // Treat an enum type as its underlying type.
317*06c3fb27SDimitry Andric   if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
318*06c3fb27SDimitry Andric     RetTy = EnumTy->getDecl()->getIntegerType();
319*06c3fb27SDimitry Andric 
320*06c3fb27SDimitry Andric   // Make sure we pass indirectly things that are too large.
321*06c3fb27SDimitry Andric   if (const auto *EIT = RetTy->getAs<BitIntType>())
322*06c3fb27SDimitry Andric     if (EIT->getNumBits() > 128 ||
323*06c3fb27SDimitry Andric         (EIT->getNumBits() > 64 &&
324*06c3fb27SDimitry Andric          !getContext().getTargetInfo().hasInt128Type()))
325*06c3fb27SDimitry Andric       return getNaturalAlignIndirect(RetTy);
326*06c3fb27SDimitry Andric 
327*06c3fb27SDimitry Andric   if (isPromotableIntegerTypeForABI(RetTy))
328*06c3fb27SDimitry Andric     return ABIArgInfo::getExtend(RetTy);
329*06c3fb27SDimitry Andric 
330*06c3fb27SDimitry Andric   if ((RetTy->isUnsignedIntegerOrEnumerationType() ||
331*06c3fb27SDimitry Andric       RetTy->isSignedIntegerOrEnumerationType()) && Size == 32 && !IsO32)
332*06c3fb27SDimitry Andric     return ABIArgInfo::getSignExtend(RetTy);
333*06c3fb27SDimitry Andric 
334*06c3fb27SDimitry Andric   return ABIArgInfo::getDirect();
335*06c3fb27SDimitry Andric }
336*06c3fb27SDimitry Andric 
337*06c3fb27SDimitry Andric void MipsABIInfo::computeInfo(CGFunctionInfo &FI) const {
338*06c3fb27SDimitry Andric   ABIArgInfo &RetInfo = FI.getReturnInfo();
339*06c3fb27SDimitry Andric   if (!getCXXABI().classifyReturnType(FI))
340*06c3fb27SDimitry Andric     RetInfo = classifyReturnType(FI.getReturnType());
341*06c3fb27SDimitry Andric 
342*06c3fb27SDimitry Andric   // Check if a pointer to an aggregate is passed as a hidden argument.
343*06c3fb27SDimitry Andric   uint64_t Offset = RetInfo.isIndirect() ? MinABIStackAlignInBytes : 0;
344*06c3fb27SDimitry Andric 
345*06c3fb27SDimitry Andric   for (auto &I : FI.arguments())
346*06c3fb27SDimitry Andric     I.info = classifyArgumentType(I.type, Offset);
347*06c3fb27SDimitry Andric }
348*06c3fb27SDimitry Andric 
349*06c3fb27SDimitry Andric Address MipsABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
350*06c3fb27SDimitry Andric                                QualType OrigTy) const {
351*06c3fb27SDimitry Andric   QualType Ty = OrigTy;
352*06c3fb27SDimitry Andric 
353*06c3fb27SDimitry Andric   // Integer arguments are promoted to 32-bit on O32 and 64-bit on N32/N64.
354*06c3fb27SDimitry Andric   // Pointers are also promoted in the same way but this only matters for N32.
355*06c3fb27SDimitry Andric   unsigned SlotSizeInBits = IsO32 ? 32 : 64;
356*06c3fb27SDimitry Andric   unsigned PtrWidth = getTarget().getPointerWidth(LangAS::Default);
357*06c3fb27SDimitry Andric   bool DidPromote = false;
358*06c3fb27SDimitry Andric   if ((Ty->isIntegerType() &&
359*06c3fb27SDimitry Andric           getContext().getIntWidth(Ty) < SlotSizeInBits) ||
360*06c3fb27SDimitry Andric       (Ty->isPointerType() && PtrWidth < SlotSizeInBits)) {
361*06c3fb27SDimitry Andric     DidPromote = true;
362*06c3fb27SDimitry Andric     Ty = getContext().getIntTypeForBitwidth(SlotSizeInBits,
363*06c3fb27SDimitry Andric                                             Ty->isSignedIntegerType());
364*06c3fb27SDimitry Andric   }
365*06c3fb27SDimitry Andric 
366*06c3fb27SDimitry Andric   auto TyInfo = getContext().getTypeInfoInChars(Ty);
367*06c3fb27SDimitry Andric 
368*06c3fb27SDimitry Andric   // The alignment of things in the argument area is never larger than
369*06c3fb27SDimitry Andric   // StackAlignInBytes.
370*06c3fb27SDimitry Andric   TyInfo.Align =
371*06c3fb27SDimitry Andric     std::min(TyInfo.Align, CharUnits::fromQuantity(StackAlignInBytes));
372*06c3fb27SDimitry Andric 
373*06c3fb27SDimitry Andric   // MinABIStackAlignInBytes is the size of argument slots on the stack.
374*06c3fb27SDimitry Andric   CharUnits ArgSlotSize = CharUnits::fromQuantity(MinABIStackAlignInBytes);
375*06c3fb27SDimitry Andric 
376*06c3fb27SDimitry Andric   Address Addr = emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false,
377*06c3fb27SDimitry Andric                           TyInfo, ArgSlotSize, /*AllowHigherAlign*/ true);
378*06c3fb27SDimitry Andric 
379*06c3fb27SDimitry Andric 
380*06c3fb27SDimitry Andric   // If there was a promotion, "unpromote" into a temporary.
381*06c3fb27SDimitry Andric   // TODO: can we just use a pointer into a subset of the original slot?
382*06c3fb27SDimitry Andric   if (DidPromote) {
383*06c3fb27SDimitry Andric     Address Temp = CGF.CreateMemTemp(OrigTy, "vaarg.promotion-temp");
384*06c3fb27SDimitry Andric     llvm::Value *Promoted = CGF.Builder.CreateLoad(Addr);
385*06c3fb27SDimitry Andric 
386*06c3fb27SDimitry Andric     // Truncate down to the right width.
387*06c3fb27SDimitry Andric     llvm::Type *IntTy = (OrigTy->isIntegerType() ? Temp.getElementType()
388*06c3fb27SDimitry Andric                                                  : CGF.IntPtrTy);
389*06c3fb27SDimitry Andric     llvm::Value *V = CGF.Builder.CreateTrunc(Promoted, IntTy);
390*06c3fb27SDimitry Andric     if (OrigTy->isPointerType())
391*06c3fb27SDimitry Andric       V = CGF.Builder.CreateIntToPtr(V, Temp.getElementType());
392*06c3fb27SDimitry Andric 
393*06c3fb27SDimitry Andric     CGF.Builder.CreateStore(V, Temp);
394*06c3fb27SDimitry Andric     Addr = Temp;
395*06c3fb27SDimitry Andric   }
396*06c3fb27SDimitry Andric 
397*06c3fb27SDimitry Andric   return Addr;
398*06c3fb27SDimitry Andric }
399*06c3fb27SDimitry Andric 
400*06c3fb27SDimitry Andric ABIArgInfo MipsABIInfo::extendType(QualType Ty) const {
401*06c3fb27SDimitry Andric   int TySize = getContext().getTypeSize(Ty);
402*06c3fb27SDimitry Andric 
403*06c3fb27SDimitry Andric   // MIPS64 ABI requires unsigned 32 bit integers to be sign extended.
404*06c3fb27SDimitry Andric   if (Ty->isUnsignedIntegerOrEnumerationType() && TySize == 32)
405*06c3fb27SDimitry Andric     return ABIArgInfo::getSignExtend(Ty);
406*06c3fb27SDimitry Andric 
407*06c3fb27SDimitry Andric   return ABIArgInfo::getExtend(Ty);
408*06c3fb27SDimitry Andric }
409*06c3fb27SDimitry Andric 
410*06c3fb27SDimitry Andric bool
411*06c3fb27SDimitry Andric MIPSTargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
412*06c3fb27SDimitry Andric                                                llvm::Value *Address) const {
413*06c3fb27SDimitry Andric   // This information comes from gcc's implementation, which seems to
414*06c3fb27SDimitry Andric   // as canonical as it gets.
415*06c3fb27SDimitry Andric 
416*06c3fb27SDimitry Andric   // Everything on MIPS is 4 bytes.  Double-precision FP registers
417*06c3fb27SDimitry Andric   // are aliased to pairs of single-precision FP registers.
418*06c3fb27SDimitry Andric   llvm::Value *Four8 = llvm::ConstantInt::get(CGF.Int8Ty, 4);
419*06c3fb27SDimitry Andric 
420*06c3fb27SDimitry Andric   // 0-31 are the general purpose registers, $0 - $31.
421*06c3fb27SDimitry Andric   // 32-63 are the floating-point registers, $f0 - $f31.
422*06c3fb27SDimitry Andric   // 64 and 65 are the multiply/divide registers, $hi and $lo.
423*06c3fb27SDimitry Andric   // 66 is the (notional, I think) register for signal-handler return.
424*06c3fb27SDimitry Andric   AssignToArrayRange(CGF.Builder, Address, Four8, 0, 65);
425*06c3fb27SDimitry Andric 
426*06c3fb27SDimitry Andric   // 67-74 are the floating-point status registers, $fcc0 - $fcc7.
427*06c3fb27SDimitry Andric   // They are one bit wide and ignored here.
428*06c3fb27SDimitry Andric 
429*06c3fb27SDimitry Andric   // 80-111 are the coprocessor 0 registers, $c0r0 - $c0r31.
430*06c3fb27SDimitry Andric   // (coprocessor 1 is the FP unit)
431*06c3fb27SDimitry Andric   // 112-143 are the coprocessor 2 registers, $c2r0 - $c2r31.
432*06c3fb27SDimitry Andric   // 144-175 are the coprocessor 3 registers, $c3r0 - $c3r31.
433*06c3fb27SDimitry Andric   // 176-181 are the DSP accumulator registers.
434*06c3fb27SDimitry Andric   AssignToArrayRange(CGF.Builder, Address, Four8, 80, 181);
435*06c3fb27SDimitry Andric   return false;
436*06c3fb27SDimitry Andric }
437*06c3fb27SDimitry Andric 
438*06c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo>
439*06c3fb27SDimitry Andric CodeGen::createMIPSTargetCodeGenInfo(CodeGenModule &CGM, bool IsOS32) {
440*06c3fb27SDimitry Andric   return std::make_unique<MIPSTargetCodeGenInfo>(CGM.getTypes(), IsOS32);
441*06c3fb27SDimitry Andric }
442