xref: /llvm-project/clang/lib/CodeGen/Targets/Mips.cpp (revision 71d6287f5b1e65466de5fe5c093852fa7903cdbe)
1992cb984SSergei Barannikov //===- Mips.cpp -----------------------------------------------------------===//
2992cb984SSergei Barannikov //
3992cb984SSergei Barannikov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4992cb984SSergei Barannikov // See https://llvm.org/LICENSE.txt for license information.
5992cb984SSergei Barannikov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6992cb984SSergei Barannikov //
7992cb984SSergei Barannikov //===----------------------------------------------------------------------===//
8992cb984SSergei Barannikov 
9992cb984SSergei Barannikov #include "ABIInfoImpl.h"
10992cb984SSergei Barannikov #include "TargetInfo.h"
11992cb984SSergei Barannikov 
12992cb984SSergei Barannikov using namespace clang;
13992cb984SSergei Barannikov using namespace clang::CodeGen;
14992cb984SSergei Barannikov 
15992cb984SSergei Barannikov //===----------------------------------------------------------------------===//
16992cb984SSergei Barannikov // MIPS ABI Implementation.  This works for both little-endian and
17992cb984SSergei Barannikov // big-endian variants.
18992cb984SSergei Barannikov //===----------------------------------------------------------------------===//
19992cb984SSergei Barannikov 
20992cb984SSergei Barannikov namespace {
21992cb984SSergei Barannikov class MipsABIInfo : public ABIInfo {
22992cb984SSergei Barannikov   bool IsO32;
23992cb984SSergei Barannikov   const unsigned MinABIStackAlignInBytes, StackAlignInBytes;
24992cb984SSergei Barannikov   void CoerceToIntArgs(uint64_t TySize,
25992cb984SSergei Barannikov                        SmallVectorImpl<llvm::Type *> &ArgList) const;
26992cb984SSergei Barannikov   llvm::Type* HandleAggregates(QualType Ty, uint64_t TySize) const;
27992cb984SSergei Barannikov   llvm::Type* returnAggregateInRegs(QualType RetTy, uint64_t Size) const;
28992cb984SSergei Barannikov   llvm::Type* getPaddingType(uint64_t Align, uint64_t Offset) const;
29992cb984SSergei Barannikov public:
30992cb984SSergei Barannikov   MipsABIInfo(CodeGenTypes &CGT, bool _IsO32) :
31992cb984SSergei Barannikov     ABIInfo(CGT), IsO32(_IsO32), MinABIStackAlignInBytes(IsO32 ? 4 : 8),
32992cb984SSergei Barannikov     StackAlignInBytes(IsO32 ? 8 : 16) {}
33992cb984SSergei Barannikov 
34992cb984SSergei Barannikov   ABIArgInfo classifyReturnType(QualType RetTy) const;
35992cb984SSergei Barannikov   ABIArgInfo classifyArgumentType(QualType RetTy, uint64_t &Offset) const;
36992cb984SSergei Barannikov   void computeInfo(CGFunctionInfo &FI) const override;
376d973b45SMariya Podchishchaeva   RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
386d973b45SMariya Podchishchaeva                    AggValueSlot Slot) const override;
39992cb984SSergei Barannikov   ABIArgInfo extendType(QualType Ty) const;
40992cb984SSergei Barannikov };
41992cb984SSergei Barannikov 
42992cb984SSergei Barannikov class MIPSTargetCodeGenInfo : public TargetCodeGenInfo {
43992cb984SSergei Barannikov   unsigned SizeOfUnwindException;
44992cb984SSergei Barannikov public:
45992cb984SSergei Barannikov   MIPSTargetCodeGenInfo(CodeGenTypes &CGT, bool IsO32)
46992cb984SSergei Barannikov       : TargetCodeGenInfo(std::make_unique<MipsABIInfo>(CGT, IsO32)),
47992cb984SSergei Barannikov         SizeOfUnwindException(IsO32 ? 24 : 32) {}
48992cb984SSergei Barannikov 
49992cb984SSergei Barannikov   int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override {
50992cb984SSergei Barannikov     return 29;
51992cb984SSergei Barannikov   }
52992cb984SSergei Barannikov 
53992cb984SSergei Barannikov   void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
54992cb984SSergei Barannikov                            CodeGen::CodeGenModule &CGM) const override {
55992cb984SSergei Barannikov     const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
56992cb984SSergei Barannikov     if (!FD) return;
57992cb984SSergei Barannikov     llvm::Function *Fn = cast<llvm::Function>(GV);
58992cb984SSergei Barannikov 
59992cb984SSergei Barannikov     if (FD->hasAttr<MipsLongCallAttr>())
60992cb984SSergei Barannikov       Fn->addFnAttr("long-call");
61992cb984SSergei Barannikov     else if (FD->hasAttr<MipsShortCallAttr>())
62992cb984SSergei Barannikov       Fn->addFnAttr("short-call");
63992cb984SSergei Barannikov 
64992cb984SSergei Barannikov     // Other attributes do not have a meaning for declarations.
65992cb984SSergei Barannikov     if (GV->isDeclaration())
66992cb984SSergei Barannikov       return;
67992cb984SSergei Barannikov 
68992cb984SSergei Barannikov     if (FD->hasAttr<Mips16Attr>()) {
69992cb984SSergei Barannikov       Fn->addFnAttr("mips16");
70992cb984SSergei Barannikov     }
71992cb984SSergei Barannikov     else if (FD->hasAttr<NoMips16Attr>()) {
72992cb984SSergei Barannikov       Fn->addFnAttr("nomips16");
73992cb984SSergei Barannikov     }
74992cb984SSergei Barannikov 
75992cb984SSergei Barannikov     if (FD->hasAttr<MicroMipsAttr>())
76992cb984SSergei Barannikov       Fn->addFnAttr("micromips");
77992cb984SSergei Barannikov     else if (FD->hasAttr<NoMicroMipsAttr>())
78992cb984SSergei Barannikov       Fn->addFnAttr("nomicromips");
79992cb984SSergei Barannikov 
80992cb984SSergei Barannikov     const MipsInterruptAttr *Attr = FD->getAttr<MipsInterruptAttr>();
81992cb984SSergei Barannikov     if (!Attr)
82992cb984SSergei Barannikov       return;
83992cb984SSergei Barannikov 
84992cb984SSergei Barannikov     const char *Kind;
85992cb984SSergei Barannikov     switch (Attr->getInterrupt()) {
86992cb984SSergei Barannikov     case MipsInterruptAttr::eic:     Kind = "eic"; break;
87992cb984SSergei Barannikov     case MipsInterruptAttr::sw0:     Kind = "sw0"; break;
88992cb984SSergei Barannikov     case MipsInterruptAttr::sw1:     Kind = "sw1"; break;
89992cb984SSergei Barannikov     case MipsInterruptAttr::hw0:     Kind = "hw0"; break;
90992cb984SSergei Barannikov     case MipsInterruptAttr::hw1:     Kind = "hw1"; break;
91992cb984SSergei Barannikov     case MipsInterruptAttr::hw2:     Kind = "hw2"; break;
92992cb984SSergei Barannikov     case MipsInterruptAttr::hw3:     Kind = "hw3"; break;
93992cb984SSergei Barannikov     case MipsInterruptAttr::hw4:     Kind = "hw4"; break;
94992cb984SSergei Barannikov     case MipsInterruptAttr::hw5:     Kind = "hw5"; break;
95992cb984SSergei Barannikov     }
96992cb984SSergei Barannikov 
97992cb984SSergei Barannikov     Fn->addFnAttr("interrupt", Kind);
98992cb984SSergei Barannikov 
99992cb984SSergei Barannikov   }
100992cb984SSergei Barannikov 
101992cb984SSergei Barannikov   bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
102992cb984SSergei Barannikov                                llvm::Value *Address) const override;
103992cb984SSergei Barannikov 
104992cb984SSergei Barannikov   unsigned getSizeOfUnwindException() const override {
105992cb984SSergei Barannikov     return SizeOfUnwindException;
106992cb984SSergei Barannikov   }
107992cb984SSergei Barannikov };
108*71d6287fSHervé Poussineau 
109*71d6287fSHervé Poussineau class WindowsMIPSTargetCodeGenInfo : public MIPSTargetCodeGenInfo {
110*71d6287fSHervé Poussineau public:
111*71d6287fSHervé Poussineau   WindowsMIPSTargetCodeGenInfo(CodeGenTypes &CGT, bool IsO32)
112*71d6287fSHervé Poussineau       : MIPSTargetCodeGenInfo(CGT, IsO32) {}
113*71d6287fSHervé Poussineau 
114*71d6287fSHervé Poussineau   void getDependentLibraryOption(llvm::StringRef Lib,
115*71d6287fSHervé Poussineau                                  llvm::SmallString<24> &Opt) const override {
116*71d6287fSHervé Poussineau     Opt = "/DEFAULTLIB:";
117*71d6287fSHervé Poussineau     Opt += qualifyWindowsLibrary(Lib);
118*71d6287fSHervé Poussineau   }
119*71d6287fSHervé Poussineau 
120*71d6287fSHervé Poussineau   void getDetectMismatchOption(llvm::StringRef Name, llvm::StringRef Value,
121*71d6287fSHervé Poussineau                                llvm::SmallString<32> &Opt) const override {
122*71d6287fSHervé Poussineau     Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\"";
123*71d6287fSHervé Poussineau   }
124*71d6287fSHervé Poussineau };
125992cb984SSergei Barannikov }
126992cb984SSergei Barannikov 
127992cb984SSergei Barannikov void MipsABIInfo::CoerceToIntArgs(
128992cb984SSergei Barannikov     uint64_t TySize, SmallVectorImpl<llvm::Type *> &ArgList) const {
129992cb984SSergei Barannikov   llvm::IntegerType *IntTy =
130992cb984SSergei Barannikov     llvm::IntegerType::get(getVMContext(), MinABIStackAlignInBytes * 8);
131992cb984SSergei Barannikov 
132992cb984SSergei Barannikov   // Add (TySize / MinABIStackAlignInBytes) args of IntTy.
133992cb984SSergei Barannikov   for (unsigned N = TySize / (MinABIStackAlignInBytes * 8); N; --N)
134992cb984SSergei Barannikov     ArgList.push_back(IntTy);
135992cb984SSergei Barannikov 
136992cb984SSergei Barannikov   // If necessary, add one more integer type to ArgList.
137992cb984SSergei Barannikov   unsigned R = TySize % (MinABIStackAlignInBytes * 8);
138992cb984SSergei Barannikov 
139992cb984SSergei Barannikov   if (R)
140992cb984SSergei Barannikov     ArgList.push_back(llvm::IntegerType::get(getVMContext(), R));
141992cb984SSergei Barannikov }
142992cb984SSergei Barannikov 
143992cb984SSergei Barannikov // In N32/64, an aligned double precision floating point field is passed in
144992cb984SSergei Barannikov // a register.
145992cb984SSergei Barannikov llvm::Type* MipsABIInfo::HandleAggregates(QualType Ty, uint64_t TySize) const {
146992cb984SSergei Barannikov   SmallVector<llvm::Type*, 8> ArgList, IntArgList;
147992cb984SSergei Barannikov 
148992cb984SSergei Barannikov   if (IsO32) {
149992cb984SSergei Barannikov     CoerceToIntArgs(TySize, ArgList);
150992cb984SSergei Barannikov     return llvm::StructType::get(getVMContext(), ArgList);
151992cb984SSergei Barannikov   }
152992cb984SSergei Barannikov 
153992cb984SSergei Barannikov   if (Ty->isComplexType())
154992cb984SSergei Barannikov     return CGT.ConvertType(Ty);
155992cb984SSergei Barannikov 
156992cb984SSergei Barannikov   const RecordType *RT = Ty->getAs<RecordType>();
157992cb984SSergei Barannikov 
158992cb984SSergei Barannikov   // Unions/vectors are passed in integer registers.
159992cb984SSergei Barannikov   if (!RT || !RT->isStructureOrClassType()) {
160992cb984SSergei Barannikov     CoerceToIntArgs(TySize, ArgList);
161992cb984SSergei Barannikov     return llvm::StructType::get(getVMContext(), ArgList);
162992cb984SSergei Barannikov   }
163992cb984SSergei Barannikov 
164992cb984SSergei Barannikov   const RecordDecl *RD = RT->getDecl();
165992cb984SSergei Barannikov   const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
166992cb984SSergei Barannikov   assert(!(TySize % 8) && "Size of structure must be multiple of 8.");
167992cb984SSergei Barannikov 
168992cb984SSergei Barannikov   uint64_t LastOffset = 0;
169992cb984SSergei Barannikov   unsigned idx = 0;
170992cb984SSergei Barannikov   llvm::IntegerType *I64 = llvm::IntegerType::get(getVMContext(), 64);
171992cb984SSergei Barannikov 
172992cb984SSergei Barannikov   // Iterate over fields in the struct/class and check if there are any aligned
173992cb984SSergei Barannikov   // double fields.
174992cb984SSergei Barannikov   for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
175992cb984SSergei Barannikov        i != e; ++i, ++idx) {
176992cb984SSergei Barannikov     const QualType Ty = i->getType();
177992cb984SSergei Barannikov     const BuiltinType *BT = Ty->getAs<BuiltinType>();
178992cb984SSergei Barannikov 
179992cb984SSergei Barannikov     if (!BT || BT->getKind() != BuiltinType::Double)
180992cb984SSergei Barannikov       continue;
181992cb984SSergei Barannikov 
182992cb984SSergei Barannikov     uint64_t Offset = Layout.getFieldOffset(idx);
183992cb984SSergei Barannikov     if (Offset % 64) // Ignore doubles that are not aligned.
184992cb984SSergei Barannikov       continue;
185992cb984SSergei Barannikov 
186992cb984SSergei Barannikov     // Add ((Offset - LastOffset) / 64) args of type i64.
187992cb984SSergei Barannikov     for (unsigned j = (Offset - LastOffset) / 64; j > 0; --j)
188992cb984SSergei Barannikov       ArgList.push_back(I64);
189992cb984SSergei Barannikov 
190992cb984SSergei Barannikov     // Add double type.
191992cb984SSergei Barannikov     ArgList.push_back(llvm::Type::getDoubleTy(getVMContext()));
192992cb984SSergei Barannikov     LastOffset = Offset + 64;
193992cb984SSergei Barannikov   }
194992cb984SSergei Barannikov 
195992cb984SSergei Barannikov   CoerceToIntArgs(TySize - LastOffset, IntArgList);
196992cb984SSergei Barannikov   ArgList.append(IntArgList.begin(), IntArgList.end());
197992cb984SSergei Barannikov 
198992cb984SSergei Barannikov   return llvm::StructType::get(getVMContext(), ArgList);
199992cb984SSergei Barannikov }
200992cb984SSergei Barannikov 
201992cb984SSergei Barannikov llvm::Type *MipsABIInfo::getPaddingType(uint64_t OrigOffset,
202992cb984SSergei Barannikov                                         uint64_t Offset) const {
203992cb984SSergei Barannikov   if (OrigOffset + MinABIStackAlignInBytes > Offset)
204992cb984SSergei Barannikov     return nullptr;
205992cb984SSergei Barannikov 
206992cb984SSergei Barannikov   return llvm::IntegerType::get(getVMContext(), (Offset - OrigOffset) * 8);
207992cb984SSergei Barannikov }
208992cb984SSergei Barannikov 
209992cb984SSergei Barannikov ABIArgInfo
210992cb984SSergei Barannikov MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const {
211992cb984SSergei Barannikov   Ty = useFirstFieldIfTransparentUnion(Ty);
212992cb984SSergei Barannikov 
213992cb984SSergei Barannikov   uint64_t OrigOffset = Offset;
214992cb984SSergei Barannikov   uint64_t TySize = getContext().getTypeSize(Ty);
215992cb984SSergei Barannikov   uint64_t Align = getContext().getTypeAlign(Ty) / 8;
216992cb984SSergei Barannikov 
217992cb984SSergei Barannikov   Align = std::clamp(Align, (uint64_t)MinABIStackAlignInBytes,
218992cb984SSergei Barannikov                      (uint64_t)StackAlignInBytes);
219992cb984SSergei Barannikov   unsigned CurrOffset = llvm::alignTo(Offset, Align);
220992cb984SSergei Barannikov   Offset = CurrOffset + llvm::alignTo(TySize, Align * 8) / 8;
221992cb984SSergei Barannikov 
222992cb984SSergei Barannikov   if (isAggregateTypeForABI(Ty) || Ty->isVectorType()) {
223992cb984SSergei Barannikov     // Ignore empty aggregates.
224992cb984SSergei Barannikov     if (TySize == 0)
225992cb984SSergei Barannikov       return ABIArgInfo::getIgnore();
226992cb984SSergei Barannikov 
227992cb984SSergei Barannikov     if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
228992cb984SSergei Barannikov       Offset = OrigOffset + MinABIStackAlignInBytes;
229992cb984SSergei Barannikov       return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
230992cb984SSergei Barannikov     }
231992cb984SSergei Barannikov 
232992cb984SSergei Barannikov     // If we have reached here, aggregates are passed directly by coercing to
233992cb984SSergei Barannikov     // another structure type. Padding is inserted if the offset of the
234992cb984SSergei Barannikov     // aggregate is unaligned.
235992cb984SSergei Barannikov     ABIArgInfo ArgInfo =
236992cb984SSergei Barannikov         ABIArgInfo::getDirect(HandleAggregates(Ty, TySize), 0,
237992cb984SSergei Barannikov                               getPaddingType(OrigOffset, CurrOffset));
238992cb984SSergei Barannikov     ArgInfo.setInReg(true);
239992cb984SSergei Barannikov     return ArgInfo;
240992cb984SSergei Barannikov   }
241992cb984SSergei Barannikov 
242992cb984SSergei Barannikov   // Treat an enum type as its underlying type.
243992cb984SSergei Barannikov   if (const EnumType *EnumTy = Ty->getAs<EnumType>())
244992cb984SSergei Barannikov     Ty = EnumTy->getDecl()->getIntegerType();
245992cb984SSergei Barannikov 
246992cb984SSergei Barannikov   // Make sure we pass indirectly things that are too large.
247992cb984SSergei Barannikov   if (const auto *EIT = Ty->getAs<BitIntType>())
248992cb984SSergei Barannikov     if (EIT->getNumBits() > 128 ||
249992cb984SSergei Barannikov         (EIT->getNumBits() > 64 &&
250992cb984SSergei Barannikov          !getContext().getTargetInfo().hasInt128Type()))
251992cb984SSergei Barannikov       return getNaturalAlignIndirect(Ty);
252992cb984SSergei Barannikov 
253992cb984SSergei Barannikov   // All integral types are promoted to the GPR width.
254992cb984SSergei Barannikov   if (Ty->isIntegralOrEnumerationType())
255992cb984SSergei Barannikov     return extendType(Ty);
256992cb984SSergei Barannikov 
257992cb984SSergei Barannikov   return ABIArgInfo::getDirect(
258992cb984SSergei Barannikov       nullptr, 0, IsO32 ? nullptr : getPaddingType(OrigOffset, CurrOffset));
259992cb984SSergei Barannikov }
260992cb984SSergei Barannikov 
261992cb984SSergei Barannikov llvm::Type*
262992cb984SSergei Barannikov MipsABIInfo::returnAggregateInRegs(QualType RetTy, uint64_t Size) const {
263992cb984SSergei Barannikov   const RecordType *RT = RetTy->getAs<RecordType>();
264992cb984SSergei Barannikov   SmallVector<llvm::Type*, 8> RTList;
265992cb984SSergei Barannikov 
266992cb984SSergei Barannikov   if (RT && RT->isStructureOrClassType()) {
267992cb984SSergei Barannikov     const RecordDecl *RD = RT->getDecl();
268992cb984SSergei Barannikov     const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
269992cb984SSergei Barannikov     unsigned FieldCnt = Layout.getFieldCount();
270992cb984SSergei Barannikov 
271992cb984SSergei Barannikov     // N32/64 returns struct/classes in floating point registers if the
272992cb984SSergei Barannikov     // following conditions are met:
273992cb984SSergei Barannikov     // 1. The size of the struct/class is no larger than 128-bit.
274992cb984SSergei Barannikov     // 2. The struct/class has one or two fields all of which are floating
275992cb984SSergei Barannikov     //    point types.
276992cb984SSergei Barannikov     // 3. The offset of the first field is zero (this follows what gcc does).
277992cb984SSergei Barannikov     //
278992cb984SSergei Barannikov     // Any other composite results are returned in integer registers.
279992cb984SSergei Barannikov     //
280992cb984SSergei Barannikov     if (FieldCnt && (FieldCnt <= 2) && !Layout.getFieldOffset(0)) {
281992cb984SSergei Barannikov       RecordDecl::field_iterator b = RD->field_begin(), e = RD->field_end();
282992cb984SSergei Barannikov       for (; b != e; ++b) {
283992cb984SSergei Barannikov         const BuiltinType *BT = b->getType()->getAs<BuiltinType>();
284992cb984SSergei Barannikov 
285992cb984SSergei Barannikov         if (!BT || !BT->isFloatingPoint())
286992cb984SSergei Barannikov           break;
287992cb984SSergei Barannikov 
288992cb984SSergei Barannikov         RTList.push_back(CGT.ConvertType(b->getType()));
289992cb984SSergei Barannikov       }
290992cb984SSergei Barannikov 
291992cb984SSergei Barannikov       if (b == e)
292992cb984SSergei Barannikov         return llvm::StructType::get(getVMContext(), RTList,
293992cb984SSergei Barannikov                                      RD->hasAttr<PackedAttr>());
294992cb984SSergei Barannikov 
295992cb984SSergei Barannikov       RTList.clear();
296992cb984SSergei Barannikov     }
297992cb984SSergei Barannikov   }
298992cb984SSergei Barannikov 
299992cb984SSergei Barannikov   CoerceToIntArgs(Size, RTList);
300992cb984SSergei Barannikov   return llvm::StructType::get(getVMContext(), RTList);
301992cb984SSergei Barannikov }
302992cb984SSergei Barannikov 
303992cb984SSergei Barannikov ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const {
304992cb984SSergei Barannikov   uint64_t Size = getContext().getTypeSize(RetTy);
305992cb984SSergei Barannikov 
306992cb984SSergei Barannikov   if (RetTy->isVoidType())
307992cb984SSergei Barannikov     return ABIArgInfo::getIgnore();
308992cb984SSergei Barannikov 
309992cb984SSergei Barannikov   // O32 doesn't treat zero-sized structs differently from other structs.
310992cb984SSergei Barannikov   // However, N32/N64 ignores zero sized return values.
311992cb984SSergei Barannikov   if (!IsO32 && Size == 0)
312992cb984SSergei Barannikov     return ABIArgInfo::getIgnore();
313992cb984SSergei Barannikov 
314992cb984SSergei Barannikov   if (isAggregateTypeForABI(RetTy) || RetTy->isVectorType()) {
315992cb984SSergei Barannikov     if (Size <= 128) {
316992cb984SSergei Barannikov       if (RetTy->isAnyComplexType())
317992cb984SSergei Barannikov         return ABIArgInfo::getDirect();
318992cb984SSergei Barannikov 
319992cb984SSergei Barannikov       // O32 returns integer vectors in registers and N32/N64 returns all small
320992cb984SSergei Barannikov       // aggregates in registers.
321992cb984SSergei Barannikov       if (!IsO32 ||
322992cb984SSergei Barannikov           (RetTy->isVectorType() && !RetTy->hasFloatingRepresentation())) {
323992cb984SSergei Barannikov         ABIArgInfo ArgInfo =
324992cb984SSergei Barannikov             ABIArgInfo::getDirect(returnAggregateInRegs(RetTy, Size));
325992cb984SSergei Barannikov         ArgInfo.setInReg(true);
326992cb984SSergei Barannikov         return ArgInfo;
327992cb984SSergei Barannikov       }
328992cb984SSergei Barannikov     }
329992cb984SSergei Barannikov 
330992cb984SSergei Barannikov     return getNaturalAlignIndirect(RetTy);
331992cb984SSergei Barannikov   }
332992cb984SSergei Barannikov 
333992cb984SSergei Barannikov   // Treat an enum type as its underlying type.
334992cb984SSergei Barannikov   if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
335992cb984SSergei Barannikov     RetTy = EnumTy->getDecl()->getIntegerType();
336992cb984SSergei Barannikov 
337992cb984SSergei Barannikov   // Make sure we pass indirectly things that are too large.
338992cb984SSergei Barannikov   if (const auto *EIT = RetTy->getAs<BitIntType>())
339992cb984SSergei Barannikov     if (EIT->getNumBits() > 128 ||
340992cb984SSergei Barannikov         (EIT->getNumBits() > 64 &&
341992cb984SSergei Barannikov          !getContext().getTargetInfo().hasInt128Type()))
342992cb984SSergei Barannikov       return getNaturalAlignIndirect(RetTy);
343992cb984SSergei Barannikov 
344992cb984SSergei Barannikov   if (isPromotableIntegerTypeForABI(RetTy))
345992cb984SSergei Barannikov     return ABIArgInfo::getExtend(RetTy);
346992cb984SSergei Barannikov 
347992cb984SSergei Barannikov   if ((RetTy->isUnsignedIntegerOrEnumerationType() ||
348992cb984SSergei Barannikov       RetTy->isSignedIntegerOrEnumerationType()) && Size == 32 && !IsO32)
349992cb984SSergei Barannikov     return ABIArgInfo::getSignExtend(RetTy);
350992cb984SSergei Barannikov 
351992cb984SSergei Barannikov   return ABIArgInfo::getDirect();
352992cb984SSergei Barannikov }
353992cb984SSergei Barannikov 
354992cb984SSergei Barannikov void MipsABIInfo::computeInfo(CGFunctionInfo &FI) const {
355992cb984SSergei Barannikov   ABIArgInfo &RetInfo = FI.getReturnInfo();
356992cb984SSergei Barannikov   if (!getCXXABI().classifyReturnType(FI))
357992cb984SSergei Barannikov     RetInfo = classifyReturnType(FI.getReturnType());
358992cb984SSergei Barannikov 
359992cb984SSergei Barannikov   // Check if a pointer to an aggregate is passed as a hidden argument.
360992cb984SSergei Barannikov   uint64_t Offset = RetInfo.isIndirect() ? MinABIStackAlignInBytes : 0;
361992cb984SSergei Barannikov 
362992cb984SSergei Barannikov   for (auto &I : FI.arguments())
363992cb984SSergei Barannikov     I.info = classifyArgumentType(I.type, Offset);
364992cb984SSergei Barannikov }
365992cb984SSergei Barannikov 
3666d973b45SMariya Podchishchaeva RValue MipsABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
3676d973b45SMariya Podchishchaeva                               QualType OrigTy, AggValueSlot Slot) const {
368992cb984SSergei Barannikov   QualType Ty = OrigTy;
369992cb984SSergei Barannikov 
370992cb984SSergei Barannikov   // Integer arguments are promoted to 32-bit on O32 and 64-bit on N32/N64.
371992cb984SSergei Barannikov   // Pointers are also promoted in the same way but this only matters for N32.
372992cb984SSergei Barannikov   unsigned SlotSizeInBits = IsO32 ? 32 : 64;
373992cb984SSergei Barannikov   unsigned PtrWidth = getTarget().getPointerWidth(LangAS::Default);
374992cb984SSergei Barannikov   bool DidPromote = false;
375992cb984SSergei Barannikov   if ((Ty->isIntegerType() &&
376992cb984SSergei Barannikov           getContext().getIntWidth(Ty) < SlotSizeInBits) ||
377992cb984SSergei Barannikov       (Ty->isPointerType() && PtrWidth < SlotSizeInBits)) {
378992cb984SSergei Barannikov     DidPromote = true;
379992cb984SSergei Barannikov     Ty = getContext().getIntTypeForBitwidth(SlotSizeInBits,
380992cb984SSergei Barannikov                                             Ty->isSignedIntegerType());
381992cb984SSergei Barannikov   }
382992cb984SSergei Barannikov 
383992cb984SSergei Barannikov   auto TyInfo = getContext().getTypeInfoInChars(Ty);
384992cb984SSergei Barannikov 
385992cb984SSergei Barannikov   // The alignment of things in the argument area is never larger than
386992cb984SSergei Barannikov   // StackAlignInBytes.
387992cb984SSergei Barannikov   TyInfo.Align =
388992cb984SSergei Barannikov     std::min(TyInfo.Align, CharUnits::fromQuantity(StackAlignInBytes));
389992cb984SSergei Barannikov 
390992cb984SSergei Barannikov   // MinABIStackAlignInBytes is the size of argument slots on the stack.
391992cb984SSergei Barannikov   CharUnits ArgSlotSize = CharUnits::fromQuantity(MinABIStackAlignInBytes);
392992cb984SSergei Barannikov 
3936d973b45SMariya Podchishchaeva   RValue Res = emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false, TyInfo,
3946d973b45SMariya Podchishchaeva                                 ArgSlotSize, /*AllowHigherAlign*/ true, Slot);
395992cb984SSergei Barannikov 
3966d973b45SMariya Podchishchaeva   // If there was a promotion, "unpromote".
397992cb984SSergei Barannikov   // TODO: can we just use a pointer into a subset of the original slot?
398992cb984SSergei Barannikov   if (DidPromote) {
3996d973b45SMariya Podchishchaeva     llvm::Type *ValTy = CGF.ConvertType(OrigTy);
4006d973b45SMariya Podchishchaeva     llvm::Value *Promoted = Res.getScalarVal();
401992cb984SSergei Barannikov 
402992cb984SSergei Barannikov     // Truncate down to the right width.
4036d973b45SMariya Podchishchaeva     llvm::Type *IntTy = (OrigTy->isIntegerType() ? ValTy : CGF.IntPtrTy);
404992cb984SSergei Barannikov     llvm::Value *V = CGF.Builder.CreateTrunc(Promoted, IntTy);
405992cb984SSergei Barannikov     if (OrigTy->isPointerType())
4066d973b45SMariya Podchishchaeva       V = CGF.Builder.CreateIntToPtr(V, ValTy);
407992cb984SSergei Barannikov 
4086d973b45SMariya Podchishchaeva     return RValue::get(V);
409992cb984SSergei Barannikov   }
410992cb984SSergei Barannikov 
4116d973b45SMariya Podchishchaeva   return Res;
412992cb984SSergei Barannikov }
413992cb984SSergei Barannikov 
414992cb984SSergei Barannikov ABIArgInfo MipsABIInfo::extendType(QualType Ty) const {
415992cb984SSergei Barannikov   int TySize = getContext().getTypeSize(Ty);
416992cb984SSergei Barannikov 
417992cb984SSergei Barannikov   // MIPS64 ABI requires unsigned 32 bit integers to be sign extended.
418992cb984SSergei Barannikov   if (Ty->isUnsignedIntegerOrEnumerationType() && TySize == 32)
419992cb984SSergei Barannikov     return ABIArgInfo::getSignExtend(Ty);
420992cb984SSergei Barannikov 
421992cb984SSergei Barannikov   return ABIArgInfo::getExtend(Ty);
422992cb984SSergei Barannikov }
423992cb984SSergei Barannikov 
424992cb984SSergei Barannikov bool
425992cb984SSergei Barannikov MIPSTargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
426992cb984SSergei Barannikov                                                llvm::Value *Address) const {
427992cb984SSergei Barannikov   // This information comes from gcc's implementation, which seems to
428992cb984SSergei Barannikov   // as canonical as it gets.
429992cb984SSergei Barannikov 
430992cb984SSergei Barannikov   // Everything on MIPS is 4 bytes.  Double-precision FP registers
431992cb984SSergei Barannikov   // are aliased to pairs of single-precision FP registers.
432992cb984SSergei Barannikov   llvm::Value *Four8 = llvm::ConstantInt::get(CGF.Int8Ty, 4);
433992cb984SSergei Barannikov 
434992cb984SSergei Barannikov   // 0-31 are the general purpose registers, $0 - $31.
435992cb984SSergei Barannikov   // 32-63 are the floating-point registers, $f0 - $f31.
436992cb984SSergei Barannikov   // 64 and 65 are the multiply/divide registers, $hi and $lo.
437992cb984SSergei Barannikov   // 66 is the (notional, I think) register for signal-handler return.
438992cb984SSergei Barannikov   AssignToArrayRange(CGF.Builder, Address, Four8, 0, 65);
439992cb984SSergei Barannikov 
440992cb984SSergei Barannikov   // 67-74 are the floating-point status registers, $fcc0 - $fcc7.
441992cb984SSergei Barannikov   // They are one bit wide and ignored here.
442992cb984SSergei Barannikov 
443992cb984SSergei Barannikov   // 80-111 are the coprocessor 0 registers, $c0r0 - $c0r31.
444992cb984SSergei Barannikov   // (coprocessor 1 is the FP unit)
445992cb984SSergei Barannikov   // 112-143 are the coprocessor 2 registers, $c2r0 - $c2r31.
446992cb984SSergei Barannikov   // 144-175 are the coprocessor 3 registers, $c3r0 - $c3r31.
447992cb984SSergei Barannikov   // 176-181 are the DSP accumulator registers.
448992cb984SSergei Barannikov   AssignToArrayRange(CGF.Builder, Address, Four8, 80, 181);
449992cb984SSergei Barannikov   return false;
450992cb984SSergei Barannikov }
451992cb984SSergei Barannikov 
452992cb984SSergei Barannikov std::unique_ptr<TargetCodeGenInfo>
453992cb984SSergei Barannikov CodeGen::createMIPSTargetCodeGenInfo(CodeGenModule &CGM, bool IsOS32) {
454992cb984SSergei Barannikov   return std::make_unique<MIPSTargetCodeGenInfo>(CGM.getTypes(), IsOS32);
455992cb984SSergei Barannikov }
456*71d6287fSHervé Poussineau 
457*71d6287fSHervé Poussineau std::unique_ptr<TargetCodeGenInfo>
458*71d6287fSHervé Poussineau CodeGen::createWindowsMIPSTargetCodeGenInfo(CodeGenModule &CGM, bool IsOS32) {
459*71d6287fSHervé Poussineau   return std::make_unique<WindowsMIPSTargetCodeGenInfo>(CGM.getTypes(), IsOS32);
460*71d6287fSHervé Poussineau }
461