xref: /freebsd-src/contrib/llvm-project/clang/lib/CodeGen/Targets/Mips.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
106c3fb27SDimitry Andric //===- Mips.cpp -----------------------------------------------------------===//
206c3fb27SDimitry Andric //
306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606c3fb27SDimitry Andric //
706c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
806c3fb27SDimitry Andric 
906c3fb27SDimitry Andric #include "ABIInfoImpl.h"
1006c3fb27SDimitry Andric #include "TargetInfo.h"
1106c3fb27SDimitry Andric 
1206c3fb27SDimitry Andric using namespace clang;
1306c3fb27SDimitry Andric using namespace clang::CodeGen;
1406c3fb27SDimitry Andric 
1506c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
1606c3fb27SDimitry Andric // MIPS ABI Implementation.  This works for both little-endian and
1706c3fb27SDimitry Andric // big-endian variants.
1806c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
1906c3fb27SDimitry Andric 
2006c3fb27SDimitry Andric namespace {
2106c3fb27SDimitry Andric class MipsABIInfo : public ABIInfo {
2206c3fb27SDimitry Andric   bool IsO32;
2306c3fb27SDimitry Andric   const unsigned MinABIStackAlignInBytes, StackAlignInBytes;
2406c3fb27SDimitry Andric   void CoerceToIntArgs(uint64_t TySize,
2506c3fb27SDimitry Andric                        SmallVectorImpl<llvm::Type *> &ArgList) const;
2606c3fb27SDimitry Andric   llvm::Type* HandleAggregates(QualType Ty, uint64_t TySize) const;
2706c3fb27SDimitry Andric   llvm::Type* returnAggregateInRegs(QualType RetTy, uint64_t Size) const;
2806c3fb27SDimitry Andric   llvm::Type* getPaddingType(uint64_t Align, uint64_t Offset) const;
2906c3fb27SDimitry Andric public:
3006c3fb27SDimitry Andric   MipsABIInfo(CodeGenTypes &CGT, bool _IsO32) :
3106c3fb27SDimitry Andric     ABIInfo(CGT), IsO32(_IsO32), MinABIStackAlignInBytes(IsO32 ? 4 : 8),
3206c3fb27SDimitry Andric     StackAlignInBytes(IsO32 ? 8 : 16) {}
3306c3fb27SDimitry Andric 
3406c3fb27SDimitry Andric   ABIArgInfo classifyReturnType(QualType RetTy) const;
3506c3fb27SDimitry Andric   ABIArgInfo classifyArgumentType(QualType RetTy, uint64_t &Offset) const;
3606c3fb27SDimitry Andric   void computeInfo(CGFunctionInfo &FI) const override;
37*0fca6ea1SDimitry Andric   RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
38*0fca6ea1SDimitry Andric                    AggValueSlot Slot) const override;
3906c3fb27SDimitry Andric   ABIArgInfo extendType(QualType Ty) const;
4006c3fb27SDimitry Andric };
4106c3fb27SDimitry Andric 
4206c3fb27SDimitry Andric class MIPSTargetCodeGenInfo : public TargetCodeGenInfo {
4306c3fb27SDimitry Andric   unsigned SizeOfUnwindException;
4406c3fb27SDimitry Andric public:
4506c3fb27SDimitry Andric   MIPSTargetCodeGenInfo(CodeGenTypes &CGT, bool IsO32)
4606c3fb27SDimitry Andric       : TargetCodeGenInfo(std::make_unique<MipsABIInfo>(CGT, IsO32)),
4706c3fb27SDimitry Andric         SizeOfUnwindException(IsO32 ? 24 : 32) {}
4806c3fb27SDimitry Andric 
4906c3fb27SDimitry Andric   int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override {
5006c3fb27SDimitry Andric     return 29;
5106c3fb27SDimitry Andric   }
5206c3fb27SDimitry Andric 
5306c3fb27SDimitry Andric   void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
5406c3fb27SDimitry Andric                            CodeGen::CodeGenModule &CGM) const override {
5506c3fb27SDimitry Andric     const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
5606c3fb27SDimitry Andric     if (!FD) return;
5706c3fb27SDimitry Andric     llvm::Function *Fn = cast<llvm::Function>(GV);
5806c3fb27SDimitry Andric 
5906c3fb27SDimitry Andric     if (FD->hasAttr<MipsLongCallAttr>())
6006c3fb27SDimitry Andric       Fn->addFnAttr("long-call");
6106c3fb27SDimitry Andric     else if (FD->hasAttr<MipsShortCallAttr>())
6206c3fb27SDimitry Andric       Fn->addFnAttr("short-call");
6306c3fb27SDimitry Andric 
6406c3fb27SDimitry Andric     // Other attributes do not have a meaning for declarations.
6506c3fb27SDimitry Andric     if (GV->isDeclaration())
6606c3fb27SDimitry Andric       return;
6706c3fb27SDimitry Andric 
6806c3fb27SDimitry Andric     if (FD->hasAttr<Mips16Attr>()) {
6906c3fb27SDimitry Andric       Fn->addFnAttr("mips16");
7006c3fb27SDimitry Andric     }
7106c3fb27SDimitry Andric     else if (FD->hasAttr<NoMips16Attr>()) {
7206c3fb27SDimitry Andric       Fn->addFnAttr("nomips16");
7306c3fb27SDimitry Andric     }
7406c3fb27SDimitry Andric 
7506c3fb27SDimitry Andric     if (FD->hasAttr<MicroMipsAttr>())
7606c3fb27SDimitry Andric       Fn->addFnAttr("micromips");
7706c3fb27SDimitry Andric     else if (FD->hasAttr<NoMicroMipsAttr>())
7806c3fb27SDimitry Andric       Fn->addFnAttr("nomicromips");
7906c3fb27SDimitry Andric 
8006c3fb27SDimitry Andric     const MipsInterruptAttr *Attr = FD->getAttr<MipsInterruptAttr>();
8106c3fb27SDimitry Andric     if (!Attr)
8206c3fb27SDimitry Andric       return;
8306c3fb27SDimitry Andric 
8406c3fb27SDimitry Andric     const char *Kind;
8506c3fb27SDimitry Andric     switch (Attr->getInterrupt()) {
8606c3fb27SDimitry Andric     case MipsInterruptAttr::eic:     Kind = "eic"; break;
8706c3fb27SDimitry Andric     case MipsInterruptAttr::sw0:     Kind = "sw0"; break;
8806c3fb27SDimitry Andric     case MipsInterruptAttr::sw1:     Kind = "sw1"; break;
8906c3fb27SDimitry Andric     case MipsInterruptAttr::hw0:     Kind = "hw0"; break;
9006c3fb27SDimitry Andric     case MipsInterruptAttr::hw1:     Kind = "hw1"; break;
9106c3fb27SDimitry Andric     case MipsInterruptAttr::hw2:     Kind = "hw2"; break;
9206c3fb27SDimitry Andric     case MipsInterruptAttr::hw3:     Kind = "hw3"; break;
9306c3fb27SDimitry Andric     case MipsInterruptAttr::hw4:     Kind = "hw4"; break;
9406c3fb27SDimitry Andric     case MipsInterruptAttr::hw5:     Kind = "hw5"; break;
9506c3fb27SDimitry Andric     }
9606c3fb27SDimitry Andric 
9706c3fb27SDimitry Andric     Fn->addFnAttr("interrupt", Kind);
9806c3fb27SDimitry Andric 
9906c3fb27SDimitry Andric   }
10006c3fb27SDimitry Andric 
10106c3fb27SDimitry Andric   bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
10206c3fb27SDimitry Andric                                llvm::Value *Address) const override;
10306c3fb27SDimitry Andric 
10406c3fb27SDimitry Andric   unsigned getSizeOfUnwindException() const override {
10506c3fb27SDimitry Andric     return SizeOfUnwindException;
10606c3fb27SDimitry Andric   }
10706c3fb27SDimitry Andric };
10806c3fb27SDimitry Andric }
10906c3fb27SDimitry Andric 
11006c3fb27SDimitry Andric void MipsABIInfo::CoerceToIntArgs(
11106c3fb27SDimitry Andric     uint64_t TySize, SmallVectorImpl<llvm::Type *> &ArgList) const {
11206c3fb27SDimitry Andric   llvm::IntegerType *IntTy =
11306c3fb27SDimitry Andric     llvm::IntegerType::get(getVMContext(), MinABIStackAlignInBytes * 8);
11406c3fb27SDimitry Andric 
11506c3fb27SDimitry Andric   // Add (TySize / MinABIStackAlignInBytes) args of IntTy.
11606c3fb27SDimitry Andric   for (unsigned N = TySize / (MinABIStackAlignInBytes * 8); N; --N)
11706c3fb27SDimitry Andric     ArgList.push_back(IntTy);
11806c3fb27SDimitry Andric 
11906c3fb27SDimitry Andric   // If necessary, add one more integer type to ArgList.
12006c3fb27SDimitry Andric   unsigned R = TySize % (MinABIStackAlignInBytes * 8);
12106c3fb27SDimitry Andric 
12206c3fb27SDimitry Andric   if (R)
12306c3fb27SDimitry Andric     ArgList.push_back(llvm::IntegerType::get(getVMContext(), R));
12406c3fb27SDimitry Andric }
12506c3fb27SDimitry Andric 
12606c3fb27SDimitry Andric // In N32/64, an aligned double precision floating point field is passed in
12706c3fb27SDimitry Andric // a register.
12806c3fb27SDimitry Andric llvm::Type* MipsABIInfo::HandleAggregates(QualType Ty, uint64_t TySize) const {
12906c3fb27SDimitry Andric   SmallVector<llvm::Type*, 8> ArgList, IntArgList;
13006c3fb27SDimitry Andric 
13106c3fb27SDimitry Andric   if (IsO32) {
13206c3fb27SDimitry Andric     CoerceToIntArgs(TySize, ArgList);
13306c3fb27SDimitry Andric     return llvm::StructType::get(getVMContext(), ArgList);
13406c3fb27SDimitry Andric   }
13506c3fb27SDimitry Andric 
13606c3fb27SDimitry Andric   if (Ty->isComplexType())
13706c3fb27SDimitry Andric     return CGT.ConvertType(Ty);
13806c3fb27SDimitry Andric 
13906c3fb27SDimitry Andric   const RecordType *RT = Ty->getAs<RecordType>();
14006c3fb27SDimitry Andric 
14106c3fb27SDimitry Andric   // Unions/vectors are passed in integer registers.
14206c3fb27SDimitry Andric   if (!RT || !RT->isStructureOrClassType()) {
14306c3fb27SDimitry Andric     CoerceToIntArgs(TySize, ArgList);
14406c3fb27SDimitry Andric     return llvm::StructType::get(getVMContext(), ArgList);
14506c3fb27SDimitry Andric   }
14606c3fb27SDimitry Andric 
14706c3fb27SDimitry Andric   const RecordDecl *RD = RT->getDecl();
14806c3fb27SDimitry Andric   const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
14906c3fb27SDimitry Andric   assert(!(TySize % 8) && "Size of structure must be multiple of 8.");
15006c3fb27SDimitry Andric 
15106c3fb27SDimitry Andric   uint64_t LastOffset = 0;
15206c3fb27SDimitry Andric   unsigned idx = 0;
15306c3fb27SDimitry Andric   llvm::IntegerType *I64 = llvm::IntegerType::get(getVMContext(), 64);
15406c3fb27SDimitry Andric 
15506c3fb27SDimitry Andric   // Iterate over fields in the struct/class and check if there are any aligned
15606c3fb27SDimitry Andric   // double fields.
15706c3fb27SDimitry Andric   for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
15806c3fb27SDimitry Andric        i != e; ++i, ++idx) {
15906c3fb27SDimitry Andric     const QualType Ty = i->getType();
16006c3fb27SDimitry Andric     const BuiltinType *BT = Ty->getAs<BuiltinType>();
16106c3fb27SDimitry Andric 
16206c3fb27SDimitry Andric     if (!BT || BT->getKind() != BuiltinType::Double)
16306c3fb27SDimitry Andric       continue;
16406c3fb27SDimitry Andric 
16506c3fb27SDimitry Andric     uint64_t Offset = Layout.getFieldOffset(idx);
16606c3fb27SDimitry Andric     if (Offset % 64) // Ignore doubles that are not aligned.
16706c3fb27SDimitry Andric       continue;
16806c3fb27SDimitry Andric 
16906c3fb27SDimitry Andric     // Add ((Offset - LastOffset) / 64) args of type i64.
17006c3fb27SDimitry Andric     for (unsigned j = (Offset - LastOffset) / 64; j > 0; --j)
17106c3fb27SDimitry Andric       ArgList.push_back(I64);
17206c3fb27SDimitry Andric 
17306c3fb27SDimitry Andric     // Add double type.
17406c3fb27SDimitry Andric     ArgList.push_back(llvm::Type::getDoubleTy(getVMContext()));
17506c3fb27SDimitry Andric     LastOffset = Offset + 64;
17606c3fb27SDimitry Andric   }
17706c3fb27SDimitry Andric 
17806c3fb27SDimitry Andric   CoerceToIntArgs(TySize - LastOffset, IntArgList);
17906c3fb27SDimitry Andric   ArgList.append(IntArgList.begin(), IntArgList.end());
18006c3fb27SDimitry Andric 
18106c3fb27SDimitry Andric   return llvm::StructType::get(getVMContext(), ArgList);
18206c3fb27SDimitry Andric }
18306c3fb27SDimitry Andric 
18406c3fb27SDimitry Andric llvm::Type *MipsABIInfo::getPaddingType(uint64_t OrigOffset,
18506c3fb27SDimitry Andric                                         uint64_t Offset) const {
18606c3fb27SDimitry Andric   if (OrigOffset + MinABIStackAlignInBytes > Offset)
18706c3fb27SDimitry Andric     return nullptr;
18806c3fb27SDimitry Andric 
18906c3fb27SDimitry Andric   return llvm::IntegerType::get(getVMContext(), (Offset - OrigOffset) * 8);
19006c3fb27SDimitry Andric }
19106c3fb27SDimitry Andric 
19206c3fb27SDimitry Andric ABIArgInfo
19306c3fb27SDimitry Andric MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const {
19406c3fb27SDimitry Andric   Ty = useFirstFieldIfTransparentUnion(Ty);
19506c3fb27SDimitry Andric 
19606c3fb27SDimitry Andric   uint64_t OrigOffset = Offset;
19706c3fb27SDimitry Andric   uint64_t TySize = getContext().getTypeSize(Ty);
19806c3fb27SDimitry Andric   uint64_t Align = getContext().getTypeAlign(Ty) / 8;
19906c3fb27SDimitry Andric 
20006c3fb27SDimitry Andric   Align = std::clamp(Align, (uint64_t)MinABIStackAlignInBytes,
20106c3fb27SDimitry Andric                      (uint64_t)StackAlignInBytes);
20206c3fb27SDimitry Andric   unsigned CurrOffset = llvm::alignTo(Offset, Align);
20306c3fb27SDimitry Andric   Offset = CurrOffset + llvm::alignTo(TySize, Align * 8) / 8;
20406c3fb27SDimitry Andric 
20506c3fb27SDimitry Andric   if (isAggregateTypeForABI(Ty) || Ty->isVectorType()) {
20606c3fb27SDimitry Andric     // Ignore empty aggregates.
20706c3fb27SDimitry Andric     if (TySize == 0)
20806c3fb27SDimitry Andric       return ABIArgInfo::getIgnore();
20906c3fb27SDimitry Andric 
21006c3fb27SDimitry Andric     if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
21106c3fb27SDimitry Andric       Offset = OrigOffset + MinABIStackAlignInBytes;
21206c3fb27SDimitry Andric       return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
21306c3fb27SDimitry Andric     }
21406c3fb27SDimitry Andric 
21506c3fb27SDimitry Andric     // If we have reached here, aggregates are passed directly by coercing to
21606c3fb27SDimitry Andric     // another structure type. Padding is inserted if the offset of the
21706c3fb27SDimitry Andric     // aggregate is unaligned.
21806c3fb27SDimitry Andric     ABIArgInfo ArgInfo =
21906c3fb27SDimitry Andric         ABIArgInfo::getDirect(HandleAggregates(Ty, TySize), 0,
22006c3fb27SDimitry Andric                               getPaddingType(OrigOffset, CurrOffset));
22106c3fb27SDimitry Andric     ArgInfo.setInReg(true);
22206c3fb27SDimitry Andric     return ArgInfo;
22306c3fb27SDimitry Andric   }
22406c3fb27SDimitry Andric 
22506c3fb27SDimitry Andric   // Treat an enum type as its underlying type.
22606c3fb27SDimitry Andric   if (const EnumType *EnumTy = Ty->getAs<EnumType>())
22706c3fb27SDimitry Andric     Ty = EnumTy->getDecl()->getIntegerType();
22806c3fb27SDimitry Andric 
22906c3fb27SDimitry Andric   // Make sure we pass indirectly things that are too large.
23006c3fb27SDimitry Andric   if (const auto *EIT = Ty->getAs<BitIntType>())
23106c3fb27SDimitry Andric     if (EIT->getNumBits() > 128 ||
23206c3fb27SDimitry Andric         (EIT->getNumBits() > 64 &&
23306c3fb27SDimitry Andric          !getContext().getTargetInfo().hasInt128Type()))
23406c3fb27SDimitry Andric       return getNaturalAlignIndirect(Ty);
23506c3fb27SDimitry Andric 
23606c3fb27SDimitry Andric   // All integral types are promoted to the GPR width.
23706c3fb27SDimitry Andric   if (Ty->isIntegralOrEnumerationType())
23806c3fb27SDimitry Andric     return extendType(Ty);
23906c3fb27SDimitry Andric 
24006c3fb27SDimitry Andric   return ABIArgInfo::getDirect(
24106c3fb27SDimitry Andric       nullptr, 0, IsO32 ? nullptr : getPaddingType(OrigOffset, CurrOffset));
24206c3fb27SDimitry Andric }
24306c3fb27SDimitry Andric 
24406c3fb27SDimitry Andric llvm::Type*
24506c3fb27SDimitry Andric MipsABIInfo::returnAggregateInRegs(QualType RetTy, uint64_t Size) const {
24606c3fb27SDimitry Andric   const RecordType *RT = RetTy->getAs<RecordType>();
24706c3fb27SDimitry Andric   SmallVector<llvm::Type*, 8> RTList;
24806c3fb27SDimitry Andric 
24906c3fb27SDimitry Andric   if (RT && RT->isStructureOrClassType()) {
25006c3fb27SDimitry Andric     const RecordDecl *RD = RT->getDecl();
25106c3fb27SDimitry Andric     const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
25206c3fb27SDimitry Andric     unsigned FieldCnt = Layout.getFieldCount();
25306c3fb27SDimitry Andric 
25406c3fb27SDimitry Andric     // N32/64 returns struct/classes in floating point registers if the
25506c3fb27SDimitry Andric     // following conditions are met:
25606c3fb27SDimitry Andric     // 1. The size of the struct/class is no larger than 128-bit.
25706c3fb27SDimitry Andric     // 2. The struct/class has one or two fields all of which are floating
25806c3fb27SDimitry Andric     //    point types.
25906c3fb27SDimitry Andric     // 3. The offset of the first field is zero (this follows what gcc does).
26006c3fb27SDimitry Andric     //
26106c3fb27SDimitry Andric     // Any other composite results are returned in integer registers.
26206c3fb27SDimitry Andric     //
26306c3fb27SDimitry Andric     if (FieldCnt && (FieldCnt <= 2) && !Layout.getFieldOffset(0)) {
26406c3fb27SDimitry Andric       RecordDecl::field_iterator b = RD->field_begin(), e = RD->field_end();
26506c3fb27SDimitry Andric       for (; b != e; ++b) {
26606c3fb27SDimitry Andric         const BuiltinType *BT = b->getType()->getAs<BuiltinType>();
26706c3fb27SDimitry Andric 
26806c3fb27SDimitry Andric         if (!BT || !BT->isFloatingPoint())
26906c3fb27SDimitry Andric           break;
27006c3fb27SDimitry Andric 
27106c3fb27SDimitry Andric         RTList.push_back(CGT.ConvertType(b->getType()));
27206c3fb27SDimitry Andric       }
27306c3fb27SDimitry Andric 
27406c3fb27SDimitry Andric       if (b == e)
27506c3fb27SDimitry Andric         return llvm::StructType::get(getVMContext(), RTList,
27606c3fb27SDimitry Andric                                      RD->hasAttr<PackedAttr>());
27706c3fb27SDimitry Andric 
27806c3fb27SDimitry Andric       RTList.clear();
27906c3fb27SDimitry Andric     }
28006c3fb27SDimitry Andric   }
28106c3fb27SDimitry Andric 
28206c3fb27SDimitry Andric   CoerceToIntArgs(Size, RTList);
28306c3fb27SDimitry Andric   return llvm::StructType::get(getVMContext(), RTList);
28406c3fb27SDimitry Andric }
28506c3fb27SDimitry Andric 
28606c3fb27SDimitry Andric ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const {
28706c3fb27SDimitry Andric   uint64_t Size = getContext().getTypeSize(RetTy);
28806c3fb27SDimitry Andric 
28906c3fb27SDimitry Andric   if (RetTy->isVoidType())
29006c3fb27SDimitry Andric     return ABIArgInfo::getIgnore();
29106c3fb27SDimitry Andric 
29206c3fb27SDimitry Andric   // O32 doesn't treat zero-sized structs differently from other structs.
29306c3fb27SDimitry Andric   // However, N32/N64 ignores zero sized return values.
29406c3fb27SDimitry Andric   if (!IsO32 && Size == 0)
29506c3fb27SDimitry Andric     return ABIArgInfo::getIgnore();
29606c3fb27SDimitry Andric 
29706c3fb27SDimitry Andric   if (isAggregateTypeForABI(RetTy) || RetTy->isVectorType()) {
29806c3fb27SDimitry Andric     if (Size <= 128) {
29906c3fb27SDimitry Andric       if (RetTy->isAnyComplexType())
30006c3fb27SDimitry Andric         return ABIArgInfo::getDirect();
30106c3fb27SDimitry Andric 
30206c3fb27SDimitry Andric       // O32 returns integer vectors in registers and N32/N64 returns all small
30306c3fb27SDimitry Andric       // aggregates in registers.
30406c3fb27SDimitry Andric       if (!IsO32 ||
30506c3fb27SDimitry Andric           (RetTy->isVectorType() && !RetTy->hasFloatingRepresentation())) {
30606c3fb27SDimitry Andric         ABIArgInfo ArgInfo =
30706c3fb27SDimitry Andric             ABIArgInfo::getDirect(returnAggregateInRegs(RetTy, Size));
30806c3fb27SDimitry Andric         ArgInfo.setInReg(true);
30906c3fb27SDimitry Andric         return ArgInfo;
31006c3fb27SDimitry Andric       }
31106c3fb27SDimitry Andric     }
31206c3fb27SDimitry Andric 
31306c3fb27SDimitry Andric     return getNaturalAlignIndirect(RetTy);
31406c3fb27SDimitry Andric   }
31506c3fb27SDimitry Andric 
31606c3fb27SDimitry Andric   // Treat an enum type as its underlying type.
31706c3fb27SDimitry Andric   if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
31806c3fb27SDimitry Andric     RetTy = EnumTy->getDecl()->getIntegerType();
31906c3fb27SDimitry Andric 
32006c3fb27SDimitry Andric   // Make sure we pass indirectly things that are too large.
32106c3fb27SDimitry Andric   if (const auto *EIT = RetTy->getAs<BitIntType>())
32206c3fb27SDimitry Andric     if (EIT->getNumBits() > 128 ||
32306c3fb27SDimitry Andric         (EIT->getNumBits() > 64 &&
32406c3fb27SDimitry Andric          !getContext().getTargetInfo().hasInt128Type()))
32506c3fb27SDimitry Andric       return getNaturalAlignIndirect(RetTy);
32606c3fb27SDimitry Andric 
32706c3fb27SDimitry Andric   if (isPromotableIntegerTypeForABI(RetTy))
32806c3fb27SDimitry Andric     return ABIArgInfo::getExtend(RetTy);
32906c3fb27SDimitry Andric 
33006c3fb27SDimitry Andric   if ((RetTy->isUnsignedIntegerOrEnumerationType() ||
33106c3fb27SDimitry Andric       RetTy->isSignedIntegerOrEnumerationType()) && Size == 32 && !IsO32)
33206c3fb27SDimitry Andric     return ABIArgInfo::getSignExtend(RetTy);
33306c3fb27SDimitry Andric 
33406c3fb27SDimitry Andric   return ABIArgInfo::getDirect();
33506c3fb27SDimitry Andric }
33606c3fb27SDimitry Andric 
33706c3fb27SDimitry Andric void MipsABIInfo::computeInfo(CGFunctionInfo &FI) const {
33806c3fb27SDimitry Andric   ABIArgInfo &RetInfo = FI.getReturnInfo();
33906c3fb27SDimitry Andric   if (!getCXXABI().classifyReturnType(FI))
34006c3fb27SDimitry Andric     RetInfo = classifyReturnType(FI.getReturnType());
34106c3fb27SDimitry Andric 
34206c3fb27SDimitry Andric   // Check if a pointer to an aggregate is passed as a hidden argument.
34306c3fb27SDimitry Andric   uint64_t Offset = RetInfo.isIndirect() ? MinABIStackAlignInBytes : 0;
34406c3fb27SDimitry Andric 
34506c3fb27SDimitry Andric   for (auto &I : FI.arguments())
34606c3fb27SDimitry Andric     I.info = classifyArgumentType(I.type, Offset);
34706c3fb27SDimitry Andric }
34806c3fb27SDimitry Andric 
349*0fca6ea1SDimitry Andric RValue MipsABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
350*0fca6ea1SDimitry Andric                               QualType OrigTy, AggValueSlot Slot) const {
35106c3fb27SDimitry Andric   QualType Ty = OrigTy;
35206c3fb27SDimitry Andric 
35306c3fb27SDimitry Andric   // Integer arguments are promoted to 32-bit on O32 and 64-bit on N32/N64.
35406c3fb27SDimitry Andric   // Pointers are also promoted in the same way but this only matters for N32.
35506c3fb27SDimitry Andric   unsigned SlotSizeInBits = IsO32 ? 32 : 64;
35606c3fb27SDimitry Andric   unsigned PtrWidth = getTarget().getPointerWidth(LangAS::Default);
35706c3fb27SDimitry Andric   bool DidPromote = false;
35806c3fb27SDimitry Andric   if ((Ty->isIntegerType() &&
35906c3fb27SDimitry Andric           getContext().getIntWidth(Ty) < SlotSizeInBits) ||
36006c3fb27SDimitry Andric       (Ty->isPointerType() && PtrWidth < SlotSizeInBits)) {
36106c3fb27SDimitry Andric     DidPromote = true;
36206c3fb27SDimitry Andric     Ty = getContext().getIntTypeForBitwidth(SlotSizeInBits,
36306c3fb27SDimitry Andric                                             Ty->isSignedIntegerType());
36406c3fb27SDimitry Andric   }
36506c3fb27SDimitry Andric 
36606c3fb27SDimitry Andric   auto TyInfo = getContext().getTypeInfoInChars(Ty);
36706c3fb27SDimitry Andric 
36806c3fb27SDimitry Andric   // The alignment of things in the argument area is never larger than
36906c3fb27SDimitry Andric   // StackAlignInBytes.
37006c3fb27SDimitry Andric   TyInfo.Align =
37106c3fb27SDimitry Andric     std::min(TyInfo.Align, CharUnits::fromQuantity(StackAlignInBytes));
37206c3fb27SDimitry Andric 
37306c3fb27SDimitry Andric   // MinABIStackAlignInBytes is the size of argument slots on the stack.
37406c3fb27SDimitry Andric   CharUnits ArgSlotSize = CharUnits::fromQuantity(MinABIStackAlignInBytes);
37506c3fb27SDimitry Andric 
376*0fca6ea1SDimitry Andric   RValue Res = emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false, TyInfo,
377*0fca6ea1SDimitry Andric                                 ArgSlotSize, /*AllowHigherAlign*/ true, Slot);
37806c3fb27SDimitry Andric 
379*0fca6ea1SDimitry Andric   // If there was a promotion, "unpromote".
38006c3fb27SDimitry Andric   // TODO: can we just use a pointer into a subset of the original slot?
38106c3fb27SDimitry Andric   if (DidPromote) {
382*0fca6ea1SDimitry Andric     llvm::Type *ValTy = CGF.ConvertType(OrigTy);
383*0fca6ea1SDimitry Andric     llvm::Value *Promoted = Res.getScalarVal();
38406c3fb27SDimitry Andric 
38506c3fb27SDimitry Andric     // Truncate down to the right width.
386*0fca6ea1SDimitry Andric     llvm::Type *IntTy = (OrigTy->isIntegerType() ? ValTy : CGF.IntPtrTy);
38706c3fb27SDimitry Andric     llvm::Value *V = CGF.Builder.CreateTrunc(Promoted, IntTy);
38806c3fb27SDimitry Andric     if (OrigTy->isPointerType())
389*0fca6ea1SDimitry Andric       V = CGF.Builder.CreateIntToPtr(V, ValTy);
39006c3fb27SDimitry Andric 
391*0fca6ea1SDimitry Andric     return RValue::get(V);
39206c3fb27SDimitry Andric   }
39306c3fb27SDimitry Andric 
394*0fca6ea1SDimitry Andric   return Res;
39506c3fb27SDimitry Andric }
39606c3fb27SDimitry Andric 
39706c3fb27SDimitry Andric ABIArgInfo MipsABIInfo::extendType(QualType Ty) const {
39806c3fb27SDimitry Andric   int TySize = getContext().getTypeSize(Ty);
39906c3fb27SDimitry Andric 
40006c3fb27SDimitry Andric   // MIPS64 ABI requires unsigned 32 bit integers to be sign extended.
40106c3fb27SDimitry Andric   if (Ty->isUnsignedIntegerOrEnumerationType() && TySize == 32)
40206c3fb27SDimitry Andric     return ABIArgInfo::getSignExtend(Ty);
40306c3fb27SDimitry Andric 
40406c3fb27SDimitry Andric   return ABIArgInfo::getExtend(Ty);
40506c3fb27SDimitry Andric }
40606c3fb27SDimitry Andric 
40706c3fb27SDimitry Andric bool
40806c3fb27SDimitry Andric MIPSTargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
40906c3fb27SDimitry Andric                                                llvm::Value *Address) const {
41006c3fb27SDimitry Andric   // This information comes from gcc's implementation, which seems to
41106c3fb27SDimitry Andric   // as canonical as it gets.
41206c3fb27SDimitry Andric 
41306c3fb27SDimitry Andric   // Everything on MIPS is 4 bytes.  Double-precision FP registers
41406c3fb27SDimitry Andric   // are aliased to pairs of single-precision FP registers.
41506c3fb27SDimitry Andric   llvm::Value *Four8 = llvm::ConstantInt::get(CGF.Int8Ty, 4);
41606c3fb27SDimitry Andric 
41706c3fb27SDimitry Andric   // 0-31 are the general purpose registers, $0 - $31.
41806c3fb27SDimitry Andric   // 32-63 are the floating-point registers, $f0 - $f31.
41906c3fb27SDimitry Andric   // 64 and 65 are the multiply/divide registers, $hi and $lo.
42006c3fb27SDimitry Andric   // 66 is the (notional, I think) register for signal-handler return.
42106c3fb27SDimitry Andric   AssignToArrayRange(CGF.Builder, Address, Four8, 0, 65);
42206c3fb27SDimitry Andric 
42306c3fb27SDimitry Andric   // 67-74 are the floating-point status registers, $fcc0 - $fcc7.
42406c3fb27SDimitry Andric   // They are one bit wide and ignored here.
42506c3fb27SDimitry Andric 
42606c3fb27SDimitry Andric   // 80-111 are the coprocessor 0 registers, $c0r0 - $c0r31.
42706c3fb27SDimitry Andric   // (coprocessor 1 is the FP unit)
42806c3fb27SDimitry Andric   // 112-143 are the coprocessor 2 registers, $c2r0 - $c2r31.
42906c3fb27SDimitry Andric   // 144-175 are the coprocessor 3 registers, $c3r0 - $c3r31.
43006c3fb27SDimitry Andric   // 176-181 are the DSP accumulator registers.
43106c3fb27SDimitry Andric   AssignToArrayRange(CGF.Builder, Address, Four8, 80, 181);
43206c3fb27SDimitry Andric   return false;
43306c3fb27SDimitry Andric }
43406c3fb27SDimitry Andric 
43506c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo>
43606c3fb27SDimitry Andric CodeGen::createMIPSTargetCodeGenInfo(CodeGenModule &CGM, bool IsOS32) {
43706c3fb27SDimitry Andric   return std::make_unique<MIPSTargetCodeGenInfo>(CGM.getTypes(), IsOS32);
43806c3fb27SDimitry Andric }
439