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