1*06c3fb27SDimitry Andric //===- Sparc.cpp ----------------------------------------------------------===// 2*06c3fb27SDimitry Andric // 3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*06c3fb27SDimitry Andric // 7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 8*06c3fb27SDimitry Andric 9*06c3fb27SDimitry Andric #include "ABIInfoImpl.h" 10*06c3fb27SDimitry Andric #include "TargetInfo.h" 11*06c3fb27SDimitry Andric 12*06c3fb27SDimitry Andric using namespace clang; 13*06c3fb27SDimitry Andric using namespace clang::CodeGen; 14*06c3fb27SDimitry Andric 15*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 16*06c3fb27SDimitry Andric // SPARC v8 ABI Implementation. 17*06c3fb27SDimitry Andric // Based on the SPARC Compliance Definition version 2.4.1. 18*06c3fb27SDimitry Andric // 19*06c3fb27SDimitry Andric // Ensures that complex values are passed in registers. 20*06c3fb27SDimitry Andric // 21*06c3fb27SDimitry Andric namespace { 22*06c3fb27SDimitry Andric class SparcV8ABIInfo : public DefaultABIInfo { 23*06c3fb27SDimitry Andric public: 24*06c3fb27SDimitry Andric SparcV8ABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {} 25*06c3fb27SDimitry Andric 26*06c3fb27SDimitry Andric private: 27*06c3fb27SDimitry Andric ABIArgInfo classifyReturnType(QualType RetTy) const; 28*06c3fb27SDimitry Andric void computeInfo(CGFunctionInfo &FI) const override; 29*06c3fb27SDimitry Andric }; 30*06c3fb27SDimitry Andric } // end anonymous namespace 31*06c3fb27SDimitry Andric 32*06c3fb27SDimitry Andric 33*06c3fb27SDimitry Andric ABIArgInfo 34*06c3fb27SDimitry Andric SparcV8ABIInfo::classifyReturnType(QualType Ty) const { 35*06c3fb27SDimitry Andric if (Ty->isAnyComplexType()) { 36*06c3fb27SDimitry Andric return ABIArgInfo::getDirect(); 37*06c3fb27SDimitry Andric } 38*06c3fb27SDimitry Andric else { 39*06c3fb27SDimitry Andric return DefaultABIInfo::classifyReturnType(Ty); 40*06c3fb27SDimitry Andric } 41*06c3fb27SDimitry Andric } 42*06c3fb27SDimitry Andric 43*06c3fb27SDimitry Andric void SparcV8ABIInfo::computeInfo(CGFunctionInfo &FI) const { 44*06c3fb27SDimitry Andric 45*06c3fb27SDimitry Andric FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); 46*06c3fb27SDimitry Andric for (auto &Arg : FI.arguments()) 47*06c3fb27SDimitry Andric Arg.info = classifyArgumentType(Arg.type); 48*06c3fb27SDimitry Andric } 49*06c3fb27SDimitry Andric 50*06c3fb27SDimitry Andric namespace { 51*06c3fb27SDimitry Andric class SparcV8TargetCodeGenInfo : public TargetCodeGenInfo { 52*06c3fb27SDimitry Andric public: 53*06c3fb27SDimitry Andric SparcV8TargetCodeGenInfo(CodeGenTypes &CGT) 54*06c3fb27SDimitry Andric : TargetCodeGenInfo(std::make_unique<SparcV8ABIInfo>(CGT)) {} 55*06c3fb27SDimitry Andric 56*06c3fb27SDimitry Andric llvm::Value *decodeReturnAddress(CodeGen::CodeGenFunction &CGF, 57*06c3fb27SDimitry Andric llvm::Value *Address) const override { 58*06c3fb27SDimitry Andric int Offset; 59*06c3fb27SDimitry Andric if (isAggregateTypeForABI(CGF.CurFnInfo->getReturnType())) 60*06c3fb27SDimitry Andric Offset = 12; 61*06c3fb27SDimitry Andric else 62*06c3fb27SDimitry Andric Offset = 8; 63*06c3fb27SDimitry Andric return CGF.Builder.CreateGEP(CGF.Int8Ty, Address, 64*06c3fb27SDimitry Andric llvm::ConstantInt::get(CGF.Int32Ty, Offset)); 65*06c3fb27SDimitry Andric } 66*06c3fb27SDimitry Andric 67*06c3fb27SDimitry Andric llvm::Value *encodeReturnAddress(CodeGen::CodeGenFunction &CGF, 68*06c3fb27SDimitry Andric llvm::Value *Address) const override { 69*06c3fb27SDimitry Andric int Offset; 70*06c3fb27SDimitry Andric if (isAggregateTypeForABI(CGF.CurFnInfo->getReturnType())) 71*06c3fb27SDimitry Andric Offset = -12; 72*06c3fb27SDimitry Andric else 73*06c3fb27SDimitry Andric Offset = -8; 74*06c3fb27SDimitry Andric return CGF.Builder.CreateGEP(CGF.Int8Ty, Address, 75*06c3fb27SDimitry Andric llvm::ConstantInt::get(CGF.Int32Ty, Offset)); 76*06c3fb27SDimitry Andric } 77*06c3fb27SDimitry Andric }; 78*06c3fb27SDimitry Andric } // end anonymous namespace 79*06c3fb27SDimitry Andric 80*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 81*06c3fb27SDimitry Andric // SPARC v9 ABI Implementation. 82*06c3fb27SDimitry Andric // Based on the SPARC Compliance Definition version 2.4.1. 83*06c3fb27SDimitry Andric // 84*06c3fb27SDimitry Andric // Function arguments a mapped to a nominal "parameter array" and promoted to 85*06c3fb27SDimitry Andric // registers depending on their type. Each argument occupies 8 or 16 bytes in 86*06c3fb27SDimitry Andric // the array, structs larger than 16 bytes are passed indirectly. 87*06c3fb27SDimitry Andric // 88*06c3fb27SDimitry Andric // One case requires special care: 89*06c3fb27SDimitry Andric // 90*06c3fb27SDimitry Andric // struct mixed { 91*06c3fb27SDimitry Andric // int i; 92*06c3fb27SDimitry Andric // float f; 93*06c3fb27SDimitry Andric // }; 94*06c3fb27SDimitry Andric // 95*06c3fb27SDimitry Andric // When a struct mixed is passed by value, it only occupies 8 bytes in the 96*06c3fb27SDimitry Andric // parameter array, but the int is passed in an integer register, and the float 97*06c3fb27SDimitry Andric // is passed in a floating point register. This is represented as two arguments 98*06c3fb27SDimitry Andric // with the LLVM IR inreg attribute: 99*06c3fb27SDimitry Andric // 100*06c3fb27SDimitry Andric // declare void f(i32 inreg %i, float inreg %f) 101*06c3fb27SDimitry Andric // 102*06c3fb27SDimitry Andric // The code generator will only allocate 4 bytes from the parameter array for 103*06c3fb27SDimitry Andric // the inreg arguments. All other arguments are allocated a multiple of 8 104*06c3fb27SDimitry Andric // bytes. 105*06c3fb27SDimitry Andric // 106*06c3fb27SDimitry Andric namespace { 107*06c3fb27SDimitry Andric class SparcV9ABIInfo : public ABIInfo { 108*06c3fb27SDimitry Andric public: 109*06c3fb27SDimitry Andric SparcV9ABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {} 110*06c3fb27SDimitry Andric 111*06c3fb27SDimitry Andric private: 112*06c3fb27SDimitry Andric ABIArgInfo classifyType(QualType RetTy, unsigned SizeLimit) const; 113*06c3fb27SDimitry Andric void computeInfo(CGFunctionInfo &FI) const override; 114*06c3fb27SDimitry Andric Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, 115*06c3fb27SDimitry Andric QualType Ty) const override; 116*06c3fb27SDimitry Andric 117*06c3fb27SDimitry Andric // Coercion type builder for structs passed in registers. The coercion type 118*06c3fb27SDimitry Andric // serves two purposes: 119*06c3fb27SDimitry Andric // 120*06c3fb27SDimitry Andric // 1. Pad structs to a multiple of 64 bits, so they are passed 'left-aligned' 121*06c3fb27SDimitry Andric // in registers. 122*06c3fb27SDimitry Andric // 2. Expose aligned floating point elements as first-level elements, so the 123*06c3fb27SDimitry Andric // code generator knows to pass them in floating point registers. 124*06c3fb27SDimitry Andric // 125*06c3fb27SDimitry Andric // We also compute the InReg flag which indicates that the struct contains 126*06c3fb27SDimitry Andric // aligned 32-bit floats. 127*06c3fb27SDimitry Andric // 128*06c3fb27SDimitry Andric struct CoerceBuilder { 129*06c3fb27SDimitry Andric llvm::LLVMContext &Context; 130*06c3fb27SDimitry Andric const llvm::DataLayout &DL; 131*06c3fb27SDimitry Andric SmallVector<llvm::Type*, 8> Elems; 132*06c3fb27SDimitry Andric uint64_t Size; 133*06c3fb27SDimitry Andric bool InReg; 134*06c3fb27SDimitry Andric 135*06c3fb27SDimitry Andric CoerceBuilder(llvm::LLVMContext &c, const llvm::DataLayout &dl) 136*06c3fb27SDimitry Andric : Context(c), DL(dl), Size(0), InReg(false) {} 137*06c3fb27SDimitry Andric 138*06c3fb27SDimitry Andric // Pad Elems with integers until Size is ToSize. 139*06c3fb27SDimitry Andric void pad(uint64_t ToSize) { 140*06c3fb27SDimitry Andric assert(ToSize >= Size && "Cannot remove elements"); 141*06c3fb27SDimitry Andric if (ToSize == Size) 142*06c3fb27SDimitry Andric return; 143*06c3fb27SDimitry Andric 144*06c3fb27SDimitry Andric // Finish the current 64-bit word. 145*06c3fb27SDimitry Andric uint64_t Aligned = llvm::alignTo(Size, 64); 146*06c3fb27SDimitry Andric if (Aligned > Size && Aligned <= ToSize) { 147*06c3fb27SDimitry Andric Elems.push_back(llvm::IntegerType::get(Context, Aligned - Size)); 148*06c3fb27SDimitry Andric Size = Aligned; 149*06c3fb27SDimitry Andric } 150*06c3fb27SDimitry Andric 151*06c3fb27SDimitry Andric // Add whole 64-bit words. 152*06c3fb27SDimitry Andric while (Size + 64 <= ToSize) { 153*06c3fb27SDimitry Andric Elems.push_back(llvm::Type::getInt64Ty(Context)); 154*06c3fb27SDimitry Andric Size += 64; 155*06c3fb27SDimitry Andric } 156*06c3fb27SDimitry Andric 157*06c3fb27SDimitry Andric // Final in-word padding. 158*06c3fb27SDimitry Andric if (Size < ToSize) { 159*06c3fb27SDimitry Andric Elems.push_back(llvm::IntegerType::get(Context, ToSize - Size)); 160*06c3fb27SDimitry Andric Size = ToSize; 161*06c3fb27SDimitry Andric } 162*06c3fb27SDimitry Andric } 163*06c3fb27SDimitry Andric 164*06c3fb27SDimitry Andric // Add a floating point element at Offset. 165*06c3fb27SDimitry Andric void addFloat(uint64_t Offset, llvm::Type *Ty, unsigned Bits) { 166*06c3fb27SDimitry Andric // Unaligned floats are treated as integers. 167*06c3fb27SDimitry Andric if (Offset % Bits) 168*06c3fb27SDimitry Andric return; 169*06c3fb27SDimitry Andric // The InReg flag is only required if there are any floats < 64 bits. 170*06c3fb27SDimitry Andric if (Bits < 64) 171*06c3fb27SDimitry Andric InReg = true; 172*06c3fb27SDimitry Andric pad(Offset); 173*06c3fb27SDimitry Andric Elems.push_back(Ty); 174*06c3fb27SDimitry Andric Size = Offset + Bits; 175*06c3fb27SDimitry Andric } 176*06c3fb27SDimitry Andric 177*06c3fb27SDimitry Andric // Add a struct type to the coercion type, starting at Offset (in bits). 178*06c3fb27SDimitry Andric void addStruct(uint64_t Offset, llvm::StructType *StrTy) { 179*06c3fb27SDimitry Andric const llvm::StructLayout *Layout = DL.getStructLayout(StrTy); 180*06c3fb27SDimitry Andric for (unsigned i = 0, e = StrTy->getNumElements(); i != e; ++i) { 181*06c3fb27SDimitry Andric llvm::Type *ElemTy = StrTy->getElementType(i); 182*06c3fb27SDimitry Andric uint64_t ElemOffset = Offset + Layout->getElementOffsetInBits(i); 183*06c3fb27SDimitry Andric switch (ElemTy->getTypeID()) { 184*06c3fb27SDimitry Andric case llvm::Type::StructTyID: 185*06c3fb27SDimitry Andric addStruct(ElemOffset, cast<llvm::StructType>(ElemTy)); 186*06c3fb27SDimitry Andric break; 187*06c3fb27SDimitry Andric case llvm::Type::FloatTyID: 188*06c3fb27SDimitry Andric addFloat(ElemOffset, ElemTy, 32); 189*06c3fb27SDimitry Andric break; 190*06c3fb27SDimitry Andric case llvm::Type::DoubleTyID: 191*06c3fb27SDimitry Andric addFloat(ElemOffset, ElemTy, 64); 192*06c3fb27SDimitry Andric break; 193*06c3fb27SDimitry Andric case llvm::Type::FP128TyID: 194*06c3fb27SDimitry Andric addFloat(ElemOffset, ElemTy, 128); 195*06c3fb27SDimitry Andric break; 196*06c3fb27SDimitry Andric case llvm::Type::PointerTyID: 197*06c3fb27SDimitry Andric if (ElemOffset % 64 == 0) { 198*06c3fb27SDimitry Andric pad(ElemOffset); 199*06c3fb27SDimitry Andric Elems.push_back(ElemTy); 200*06c3fb27SDimitry Andric Size += 64; 201*06c3fb27SDimitry Andric } 202*06c3fb27SDimitry Andric break; 203*06c3fb27SDimitry Andric default: 204*06c3fb27SDimitry Andric break; 205*06c3fb27SDimitry Andric } 206*06c3fb27SDimitry Andric } 207*06c3fb27SDimitry Andric } 208*06c3fb27SDimitry Andric 209*06c3fb27SDimitry Andric // Check if Ty is a usable substitute for the coercion type. 210*06c3fb27SDimitry Andric bool isUsableType(llvm::StructType *Ty) const { 211*06c3fb27SDimitry Andric return llvm::ArrayRef(Elems) == Ty->elements(); 212*06c3fb27SDimitry Andric } 213*06c3fb27SDimitry Andric 214*06c3fb27SDimitry Andric // Get the coercion type as a literal struct type. 215*06c3fb27SDimitry Andric llvm::Type *getType() const { 216*06c3fb27SDimitry Andric if (Elems.size() == 1) 217*06c3fb27SDimitry Andric return Elems.front(); 218*06c3fb27SDimitry Andric else 219*06c3fb27SDimitry Andric return llvm::StructType::get(Context, Elems); 220*06c3fb27SDimitry Andric } 221*06c3fb27SDimitry Andric }; 222*06c3fb27SDimitry Andric }; 223*06c3fb27SDimitry Andric } // end anonymous namespace 224*06c3fb27SDimitry Andric 225*06c3fb27SDimitry Andric ABIArgInfo 226*06c3fb27SDimitry Andric SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const { 227*06c3fb27SDimitry Andric if (Ty->isVoidType()) 228*06c3fb27SDimitry Andric return ABIArgInfo::getIgnore(); 229*06c3fb27SDimitry Andric 230*06c3fb27SDimitry Andric uint64_t Size = getContext().getTypeSize(Ty); 231*06c3fb27SDimitry Andric 232*06c3fb27SDimitry Andric // Anything too big to fit in registers is passed with an explicit indirect 233*06c3fb27SDimitry Andric // pointer / sret pointer. 234*06c3fb27SDimitry Andric if (Size > SizeLimit) 235*06c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, /*ByVal=*/false); 236*06c3fb27SDimitry Andric 237*06c3fb27SDimitry Andric // Treat an enum type as its underlying type. 238*06c3fb27SDimitry Andric if (const EnumType *EnumTy = Ty->getAs<EnumType>()) 239*06c3fb27SDimitry Andric Ty = EnumTy->getDecl()->getIntegerType(); 240*06c3fb27SDimitry Andric 241*06c3fb27SDimitry Andric // Integer types smaller than a register are extended. 242*06c3fb27SDimitry Andric if (Size < 64 && Ty->isIntegerType()) 243*06c3fb27SDimitry Andric return ABIArgInfo::getExtend(Ty); 244*06c3fb27SDimitry Andric 245*06c3fb27SDimitry Andric if (const auto *EIT = Ty->getAs<BitIntType>()) 246*06c3fb27SDimitry Andric if (EIT->getNumBits() < 64) 247*06c3fb27SDimitry Andric return ABIArgInfo::getExtend(Ty); 248*06c3fb27SDimitry Andric 249*06c3fb27SDimitry Andric // Other non-aggregates go in registers. 250*06c3fb27SDimitry Andric if (!isAggregateTypeForABI(Ty)) 251*06c3fb27SDimitry Andric return ABIArgInfo::getDirect(); 252*06c3fb27SDimitry Andric 253*06c3fb27SDimitry Andric // If a C++ object has either a non-trivial copy constructor or a non-trivial 254*06c3fb27SDimitry Andric // destructor, it is passed with an explicit indirect pointer / sret pointer. 255*06c3fb27SDimitry Andric if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) 256*06c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); 257*06c3fb27SDimitry Andric 258*06c3fb27SDimitry Andric // This is a small aggregate type that should be passed in registers. 259*06c3fb27SDimitry Andric // Build a coercion type from the LLVM struct type. 260*06c3fb27SDimitry Andric llvm::StructType *StrTy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty)); 261*06c3fb27SDimitry Andric if (!StrTy) 262*06c3fb27SDimitry Andric return ABIArgInfo::getDirect(); 263*06c3fb27SDimitry Andric 264*06c3fb27SDimitry Andric CoerceBuilder CB(getVMContext(), getDataLayout()); 265*06c3fb27SDimitry Andric CB.addStruct(0, StrTy); 266*06c3fb27SDimitry Andric CB.pad(llvm::alignTo(CB.DL.getTypeSizeInBits(StrTy), 64)); 267*06c3fb27SDimitry Andric 268*06c3fb27SDimitry Andric // Try to use the original type for coercion. 269*06c3fb27SDimitry Andric llvm::Type *CoerceTy = CB.isUsableType(StrTy) ? StrTy : CB.getType(); 270*06c3fb27SDimitry Andric 271*06c3fb27SDimitry Andric if (CB.InReg) 272*06c3fb27SDimitry Andric return ABIArgInfo::getDirectInReg(CoerceTy); 273*06c3fb27SDimitry Andric else 274*06c3fb27SDimitry Andric return ABIArgInfo::getDirect(CoerceTy); 275*06c3fb27SDimitry Andric } 276*06c3fb27SDimitry Andric 277*06c3fb27SDimitry Andric Address SparcV9ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, 278*06c3fb27SDimitry Andric QualType Ty) const { 279*06c3fb27SDimitry Andric ABIArgInfo AI = classifyType(Ty, 16 * 8); 280*06c3fb27SDimitry Andric llvm::Type *ArgTy = CGT.ConvertType(Ty); 281*06c3fb27SDimitry Andric if (AI.canHaveCoerceToType() && !AI.getCoerceToType()) 282*06c3fb27SDimitry Andric AI.setCoerceToType(ArgTy); 283*06c3fb27SDimitry Andric 284*06c3fb27SDimitry Andric CharUnits SlotSize = CharUnits::fromQuantity(8); 285*06c3fb27SDimitry Andric 286*06c3fb27SDimitry Andric CGBuilderTy &Builder = CGF.Builder; 287*06c3fb27SDimitry Andric Address Addr = Address(Builder.CreateLoad(VAListAddr, "ap.cur"), 288*06c3fb27SDimitry Andric getVAListElementType(CGF), SlotSize); 289*06c3fb27SDimitry Andric llvm::Type *ArgPtrTy = llvm::PointerType::getUnqual(ArgTy); 290*06c3fb27SDimitry Andric 291*06c3fb27SDimitry Andric auto TypeInfo = getContext().getTypeInfoInChars(Ty); 292*06c3fb27SDimitry Andric 293*06c3fb27SDimitry Andric Address ArgAddr = Address::invalid(); 294*06c3fb27SDimitry Andric CharUnits Stride; 295*06c3fb27SDimitry Andric switch (AI.getKind()) { 296*06c3fb27SDimitry Andric case ABIArgInfo::Expand: 297*06c3fb27SDimitry Andric case ABIArgInfo::CoerceAndExpand: 298*06c3fb27SDimitry Andric case ABIArgInfo::InAlloca: 299*06c3fb27SDimitry Andric llvm_unreachable("Unsupported ABI kind for va_arg"); 300*06c3fb27SDimitry Andric 301*06c3fb27SDimitry Andric case ABIArgInfo::Extend: { 302*06c3fb27SDimitry Andric Stride = SlotSize; 303*06c3fb27SDimitry Andric CharUnits Offset = SlotSize - TypeInfo.Width; 304*06c3fb27SDimitry Andric ArgAddr = Builder.CreateConstInBoundsByteGEP(Addr, Offset, "extend"); 305*06c3fb27SDimitry Andric break; 306*06c3fb27SDimitry Andric } 307*06c3fb27SDimitry Andric 308*06c3fb27SDimitry Andric case ABIArgInfo::Direct: { 309*06c3fb27SDimitry Andric auto AllocSize = getDataLayout().getTypeAllocSize(AI.getCoerceToType()); 310*06c3fb27SDimitry Andric Stride = CharUnits::fromQuantity(AllocSize).alignTo(SlotSize); 311*06c3fb27SDimitry Andric ArgAddr = Addr; 312*06c3fb27SDimitry Andric break; 313*06c3fb27SDimitry Andric } 314*06c3fb27SDimitry Andric 315*06c3fb27SDimitry Andric case ABIArgInfo::Indirect: 316*06c3fb27SDimitry Andric case ABIArgInfo::IndirectAliased: 317*06c3fb27SDimitry Andric Stride = SlotSize; 318*06c3fb27SDimitry Andric ArgAddr = Addr.withElementType(ArgPtrTy); 319*06c3fb27SDimitry Andric ArgAddr = Address(Builder.CreateLoad(ArgAddr, "indirect.arg"), ArgTy, 320*06c3fb27SDimitry Andric TypeInfo.Align); 321*06c3fb27SDimitry Andric break; 322*06c3fb27SDimitry Andric 323*06c3fb27SDimitry Andric case ABIArgInfo::Ignore: 324*06c3fb27SDimitry Andric return Address(llvm::UndefValue::get(ArgPtrTy), ArgTy, TypeInfo.Align); 325*06c3fb27SDimitry Andric } 326*06c3fb27SDimitry Andric 327*06c3fb27SDimitry Andric // Update VAList. 328*06c3fb27SDimitry Andric Address NextPtr = Builder.CreateConstInBoundsByteGEP(Addr, Stride, "ap.next"); 329*06c3fb27SDimitry Andric Builder.CreateStore(NextPtr.getPointer(), VAListAddr); 330*06c3fb27SDimitry Andric 331*06c3fb27SDimitry Andric return ArgAddr.withElementType(ArgTy); 332*06c3fb27SDimitry Andric } 333*06c3fb27SDimitry Andric 334*06c3fb27SDimitry Andric void SparcV9ABIInfo::computeInfo(CGFunctionInfo &FI) const { 335*06c3fb27SDimitry Andric FI.getReturnInfo() = classifyType(FI.getReturnType(), 32 * 8); 336*06c3fb27SDimitry Andric for (auto &I : FI.arguments()) 337*06c3fb27SDimitry Andric I.info = classifyType(I.type, 16 * 8); 338*06c3fb27SDimitry Andric } 339*06c3fb27SDimitry Andric 340*06c3fb27SDimitry Andric namespace { 341*06c3fb27SDimitry Andric class SparcV9TargetCodeGenInfo : public TargetCodeGenInfo { 342*06c3fb27SDimitry Andric public: 343*06c3fb27SDimitry Andric SparcV9TargetCodeGenInfo(CodeGenTypes &CGT) 344*06c3fb27SDimitry Andric : TargetCodeGenInfo(std::make_unique<SparcV9ABIInfo>(CGT)) {} 345*06c3fb27SDimitry Andric 346*06c3fb27SDimitry Andric int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override { 347*06c3fb27SDimitry Andric return 14; 348*06c3fb27SDimitry Andric } 349*06c3fb27SDimitry Andric 350*06c3fb27SDimitry Andric bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, 351*06c3fb27SDimitry Andric llvm::Value *Address) const override; 352*06c3fb27SDimitry Andric 353*06c3fb27SDimitry Andric llvm::Value *decodeReturnAddress(CodeGen::CodeGenFunction &CGF, 354*06c3fb27SDimitry Andric llvm::Value *Address) const override { 355*06c3fb27SDimitry Andric return CGF.Builder.CreateGEP(CGF.Int8Ty, Address, 356*06c3fb27SDimitry Andric llvm::ConstantInt::get(CGF.Int32Ty, 8)); 357*06c3fb27SDimitry Andric } 358*06c3fb27SDimitry Andric 359*06c3fb27SDimitry Andric llvm::Value *encodeReturnAddress(CodeGen::CodeGenFunction &CGF, 360*06c3fb27SDimitry Andric llvm::Value *Address) const override { 361*06c3fb27SDimitry Andric return CGF.Builder.CreateGEP(CGF.Int8Ty, Address, 362*06c3fb27SDimitry Andric llvm::ConstantInt::get(CGF.Int32Ty, -8)); 363*06c3fb27SDimitry Andric } 364*06c3fb27SDimitry Andric }; 365*06c3fb27SDimitry Andric } // end anonymous namespace 366*06c3fb27SDimitry Andric 367*06c3fb27SDimitry Andric bool 368*06c3fb27SDimitry Andric SparcV9TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, 369*06c3fb27SDimitry Andric llvm::Value *Address) const { 370*06c3fb27SDimitry Andric // This is calculated from the LLVM and GCC tables and verified 371*06c3fb27SDimitry Andric // against gcc output. AFAIK all ABIs use the same encoding. 372*06c3fb27SDimitry Andric 373*06c3fb27SDimitry Andric CodeGen::CGBuilderTy &Builder = CGF.Builder; 374*06c3fb27SDimitry Andric 375*06c3fb27SDimitry Andric llvm::IntegerType *i8 = CGF.Int8Ty; 376*06c3fb27SDimitry Andric llvm::Value *Four8 = llvm::ConstantInt::get(i8, 4); 377*06c3fb27SDimitry Andric llvm::Value *Eight8 = llvm::ConstantInt::get(i8, 8); 378*06c3fb27SDimitry Andric 379*06c3fb27SDimitry Andric // 0-31: the 8-byte general-purpose registers 380*06c3fb27SDimitry Andric AssignToArrayRange(Builder, Address, Eight8, 0, 31); 381*06c3fb27SDimitry Andric 382*06c3fb27SDimitry Andric // 32-63: f0-31, the 4-byte floating-point registers 383*06c3fb27SDimitry Andric AssignToArrayRange(Builder, Address, Four8, 32, 63); 384*06c3fb27SDimitry Andric 385*06c3fb27SDimitry Andric // Y = 64 386*06c3fb27SDimitry Andric // PSR = 65 387*06c3fb27SDimitry Andric // WIM = 66 388*06c3fb27SDimitry Andric // TBR = 67 389*06c3fb27SDimitry Andric // PC = 68 390*06c3fb27SDimitry Andric // NPC = 69 391*06c3fb27SDimitry Andric // FSR = 70 392*06c3fb27SDimitry Andric // CSR = 71 393*06c3fb27SDimitry Andric AssignToArrayRange(Builder, Address, Eight8, 64, 71); 394*06c3fb27SDimitry Andric 395*06c3fb27SDimitry Andric // 72-87: d0-15, the 8-byte floating-point registers 396*06c3fb27SDimitry Andric AssignToArrayRange(Builder, Address, Eight8, 72, 87); 397*06c3fb27SDimitry Andric 398*06c3fb27SDimitry Andric return false; 399*06c3fb27SDimitry Andric } 400*06c3fb27SDimitry Andric 401*06c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo> 402*06c3fb27SDimitry Andric CodeGen::createSparcV8TargetCodeGenInfo(CodeGenModule &CGM) { 403*06c3fb27SDimitry Andric return std::make_unique<SparcV8TargetCodeGenInfo>(CGM.getTypes()); 404*06c3fb27SDimitry Andric } 405*06c3fb27SDimitry Andric 406*06c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo> 407*06c3fb27SDimitry Andric CodeGen::createSparcV9TargetCodeGenInfo(CodeGenModule &CGM) { 408*06c3fb27SDimitry Andric return std::make_unique<SparcV9TargetCodeGenInfo>(CGM.getTypes()); 409*06c3fb27SDimitry Andric } 410