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