106c3fb27SDimitry Andric //===- Sparc.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 // SPARC v8 ABI Implementation. 1706c3fb27SDimitry Andric // Based on the SPARC Compliance Definition version 2.4.1. 1806c3fb27SDimitry Andric // 1906c3fb27SDimitry Andric // Ensures that complex values are passed in registers. 2006c3fb27SDimitry Andric // 2106c3fb27SDimitry Andric namespace { 2206c3fb27SDimitry Andric class SparcV8ABIInfo : public DefaultABIInfo { 2306c3fb27SDimitry Andric public: 2406c3fb27SDimitry Andric SparcV8ABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {} 2506c3fb27SDimitry Andric 2606c3fb27SDimitry Andric private: 2706c3fb27SDimitry Andric ABIArgInfo classifyReturnType(QualType RetTy) const; 2806c3fb27SDimitry Andric void computeInfo(CGFunctionInfo &FI) const override; 2906c3fb27SDimitry Andric }; 3006c3fb27SDimitry Andric } // end anonymous namespace 3106c3fb27SDimitry Andric 3206c3fb27SDimitry Andric 3306c3fb27SDimitry Andric ABIArgInfo 3406c3fb27SDimitry Andric SparcV8ABIInfo::classifyReturnType(QualType Ty) const { 3506c3fb27SDimitry Andric if (Ty->isAnyComplexType()) { 3606c3fb27SDimitry Andric return ABIArgInfo::getDirect(); 3706c3fb27SDimitry Andric } 3806c3fb27SDimitry Andric else { 3906c3fb27SDimitry Andric return DefaultABIInfo::classifyReturnType(Ty); 4006c3fb27SDimitry Andric } 4106c3fb27SDimitry Andric } 4206c3fb27SDimitry Andric 4306c3fb27SDimitry Andric void SparcV8ABIInfo::computeInfo(CGFunctionInfo &FI) const { 4406c3fb27SDimitry Andric 4506c3fb27SDimitry Andric FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); 4606c3fb27SDimitry Andric for (auto &Arg : FI.arguments()) 4706c3fb27SDimitry Andric Arg.info = classifyArgumentType(Arg.type); 4806c3fb27SDimitry Andric } 4906c3fb27SDimitry Andric 5006c3fb27SDimitry Andric namespace { 5106c3fb27SDimitry Andric class SparcV8TargetCodeGenInfo : public TargetCodeGenInfo { 5206c3fb27SDimitry Andric public: 5306c3fb27SDimitry Andric SparcV8TargetCodeGenInfo(CodeGenTypes &CGT) 5406c3fb27SDimitry Andric : TargetCodeGenInfo(std::make_unique<SparcV8ABIInfo>(CGT)) {} 5506c3fb27SDimitry Andric 5606c3fb27SDimitry Andric llvm::Value *decodeReturnAddress(CodeGen::CodeGenFunction &CGF, 5706c3fb27SDimitry Andric llvm::Value *Address) const override { 5806c3fb27SDimitry Andric int Offset; 5906c3fb27SDimitry Andric if (isAggregateTypeForABI(CGF.CurFnInfo->getReturnType())) 6006c3fb27SDimitry Andric Offset = 12; 6106c3fb27SDimitry Andric else 6206c3fb27SDimitry Andric Offset = 8; 6306c3fb27SDimitry Andric return CGF.Builder.CreateGEP(CGF.Int8Ty, Address, 6406c3fb27SDimitry Andric llvm::ConstantInt::get(CGF.Int32Ty, Offset)); 6506c3fb27SDimitry Andric } 6606c3fb27SDimitry Andric 6706c3fb27SDimitry Andric llvm::Value *encodeReturnAddress(CodeGen::CodeGenFunction &CGF, 6806c3fb27SDimitry Andric llvm::Value *Address) const override { 6906c3fb27SDimitry Andric int Offset; 7006c3fb27SDimitry Andric if (isAggregateTypeForABI(CGF.CurFnInfo->getReturnType())) 7106c3fb27SDimitry Andric Offset = -12; 7206c3fb27SDimitry Andric else 7306c3fb27SDimitry Andric Offset = -8; 7406c3fb27SDimitry Andric return CGF.Builder.CreateGEP(CGF.Int8Ty, Address, 7506c3fb27SDimitry Andric llvm::ConstantInt::get(CGF.Int32Ty, Offset)); 7606c3fb27SDimitry Andric } 7706c3fb27SDimitry Andric }; 7806c3fb27SDimitry Andric } // end anonymous namespace 7906c3fb27SDimitry Andric 8006c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 8106c3fb27SDimitry Andric // SPARC v9 ABI Implementation. 8206c3fb27SDimitry Andric // Based on the SPARC Compliance Definition version 2.4.1. 8306c3fb27SDimitry Andric // 8406c3fb27SDimitry Andric // Function arguments a mapped to a nominal "parameter array" and promoted to 8506c3fb27SDimitry Andric // registers depending on their type. Each argument occupies 8 or 16 bytes in 8606c3fb27SDimitry Andric // the array, structs larger than 16 bytes are passed indirectly. 8706c3fb27SDimitry Andric // 8806c3fb27SDimitry Andric // One case requires special care: 8906c3fb27SDimitry Andric // 9006c3fb27SDimitry Andric // struct mixed { 9106c3fb27SDimitry Andric // int i; 9206c3fb27SDimitry Andric // float f; 9306c3fb27SDimitry Andric // }; 9406c3fb27SDimitry Andric // 9506c3fb27SDimitry Andric // When a struct mixed is passed by value, it only occupies 8 bytes in the 9606c3fb27SDimitry Andric // parameter array, but the int is passed in an integer register, and the float 9706c3fb27SDimitry Andric // is passed in a floating point register. This is represented as two arguments 9806c3fb27SDimitry Andric // with the LLVM IR inreg attribute: 9906c3fb27SDimitry Andric // 10006c3fb27SDimitry Andric // declare void f(i32 inreg %i, float inreg %f) 10106c3fb27SDimitry Andric // 10206c3fb27SDimitry Andric // The code generator will only allocate 4 bytes from the parameter array for 10306c3fb27SDimitry Andric // the inreg arguments. All other arguments are allocated a multiple of 8 10406c3fb27SDimitry Andric // bytes. 10506c3fb27SDimitry Andric // 10606c3fb27SDimitry Andric namespace { 10706c3fb27SDimitry Andric class SparcV9ABIInfo : public ABIInfo { 10806c3fb27SDimitry Andric public: 10906c3fb27SDimitry Andric SparcV9ABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {} 11006c3fb27SDimitry Andric 11106c3fb27SDimitry Andric private: 11206c3fb27SDimitry Andric ABIArgInfo classifyType(QualType RetTy, unsigned SizeLimit) const; 11306c3fb27SDimitry Andric void computeInfo(CGFunctionInfo &FI) const override; 114*0fca6ea1SDimitry Andric RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, 115*0fca6ea1SDimitry Andric AggValueSlot Slot) const override; 11606c3fb27SDimitry Andric 11706c3fb27SDimitry Andric // Coercion type builder for structs passed in registers. The coercion type 11806c3fb27SDimitry Andric // serves two purposes: 11906c3fb27SDimitry Andric // 12006c3fb27SDimitry Andric // 1. Pad structs to a multiple of 64 bits, so they are passed 'left-aligned' 12106c3fb27SDimitry Andric // in registers. 12206c3fb27SDimitry Andric // 2. Expose aligned floating point elements as first-level elements, so the 12306c3fb27SDimitry Andric // code generator knows to pass them in floating point registers. 12406c3fb27SDimitry Andric // 12506c3fb27SDimitry Andric // We also compute the InReg flag which indicates that the struct contains 12606c3fb27SDimitry Andric // aligned 32-bit floats. 12706c3fb27SDimitry Andric // 12806c3fb27SDimitry Andric struct CoerceBuilder { 12906c3fb27SDimitry Andric llvm::LLVMContext &Context; 13006c3fb27SDimitry Andric const llvm::DataLayout &DL; 13106c3fb27SDimitry Andric SmallVector<llvm::Type*, 8> Elems; 13206c3fb27SDimitry Andric uint64_t Size; 13306c3fb27SDimitry Andric bool InReg; 13406c3fb27SDimitry Andric 13506c3fb27SDimitry Andric CoerceBuilder(llvm::LLVMContext &c, const llvm::DataLayout &dl) 13606c3fb27SDimitry Andric : Context(c), DL(dl), Size(0), InReg(false) {} 13706c3fb27SDimitry Andric 13806c3fb27SDimitry Andric // Pad Elems with integers until Size is ToSize. 13906c3fb27SDimitry Andric void pad(uint64_t ToSize) { 14006c3fb27SDimitry Andric assert(ToSize >= Size && "Cannot remove elements"); 14106c3fb27SDimitry Andric if (ToSize == Size) 14206c3fb27SDimitry Andric return; 14306c3fb27SDimitry Andric 14406c3fb27SDimitry Andric // Finish the current 64-bit word. 14506c3fb27SDimitry Andric uint64_t Aligned = llvm::alignTo(Size, 64); 14606c3fb27SDimitry Andric if (Aligned > Size && Aligned <= ToSize) { 14706c3fb27SDimitry Andric Elems.push_back(llvm::IntegerType::get(Context, Aligned - Size)); 14806c3fb27SDimitry Andric Size = Aligned; 14906c3fb27SDimitry Andric } 15006c3fb27SDimitry Andric 15106c3fb27SDimitry Andric // Add whole 64-bit words. 15206c3fb27SDimitry Andric while (Size + 64 <= ToSize) { 15306c3fb27SDimitry Andric Elems.push_back(llvm::Type::getInt64Ty(Context)); 15406c3fb27SDimitry Andric Size += 64; 15506c3fb27SDimitry Andric } 15606c3fb27SDimitry Andric 15706c3fb27SDimitry Andric // Final in-word padding. 15806c3fb27SDimitry Andric if (Size < ToSize) { 15906c3fb27SDimitry Andric Elems.push_back(llvm::IntegerType::get(Context, ToSize - Size)); 16006c3fb27SDimitry Andric Size = ToSize; 16106c3fb27SDimitry Andric } 16206c3fb27SDimitry Andric } 16306c3fb27SDimitry Andric 16406c3fb27SDimitry Andric // Add a floating point element at Offset. 16506c3fb27SDimitry Andric void addFloat(uint64_t Offset, llvm::Type *Ty, unsigned Bits) { 16606c3fb27SDimitry Andric // Unaligned floats are treated as integers. 16706c3fb27SDimitry Andric if (Offset % Bits) 16806c3fb27SDimitry Andric return; 16906c3fb27SDimitry Andric // The InReg flag is only required if there are any floats < 64 bits. 17006c3fb27SDimitry Andric if (Bits < 64) 17106c3fb27SDimitry Andric InReg = true; 17206c3fb27SDimitry Andric pad(Offset); 17306c3fb27SDimitry Andric Elems.push_back(Ty); 17406c3fb27SDimitry Andric Size = Offset + Bits; 17506c3fb27SDimitry Andric } 17606c3fb27SDimitry Andric 17706c3fb27SDimitry Andric // Add a struct type to the coercion type, starting at Offset (in bits). 17806c3fb27SDimitry Andric void addStruct(uint64_t Offset, llvm::StructType *StrTy) { 17906c3fb27SDimitry Andric const llvm::StructLayout *Layout = DL.getStructLayout(StrTy); 18006c3fb27SDimitry Andric for (unsigned i = 0, e = StrTy->getNumElements(); i != e; ++i) { 18106c3fb27SDimitry Andric llvm::Type *ElemTy = StrTy->getElementType(i); 18206c3fb27SDimitry Andric uint64_t ElemOffset = Offset + Layout->getElementOffsetInBits(i); 18306c3fb27SDimitry Andric switch (ElemTy->getTypeID()) { 18406c3fb27SDimitry Andric case llvm::Type::StructTyID: 18506c3fb27SDimitry Andric addStruct(ElemOffset, cast<llvm::StructType>(ElemTy)); 18606c3fb27SDimitry Andric break; 18706c3fb27SDimitry Andric case llvm::Type::FloatTyID: 18806c3fb27SDimitry Andric addFloat(ElemOffset, ElemTy, 32); 18906c3fb27SDimitry Andric break; 19006c3fb27SDimitry Andric case llvm::Type::DoubleTyID: 19106c3fb27SDimitry Andric addFloat(ElemOffset, ElemTy, 64); 19206c3fb27SDimitry Andric break; 19306c3fb27SDimitry Andric case llvm::Type::FP128TyID: 19406c3fb27SDimitry Andric addFloat(ElemOffset, ElemTy, 128); 19506c3fb27SDimitry Andric break; 19606c3fb27SDimitry Andric case llvm::Type::PointerTyID: 19706c3fb27SDimitry Andric if (ElemOffset % 64 == 0) { 19806c3fb27SDimitry Andric pad(ElemOffset); 19906c3fb27SDimitry Andric Elems.push_back(ElemTy); 20006c3fb27SDimitry Andric Size += 64; 20106c3fb27SDimitry Andric } 20206c3fb27SDimitry Andric break; 20306c3fb27SDimitry Andric default: 20406c3fb27SDimitry Andric break; 20506c3fb27SDimitry Andric } 20606c3fb27SDimitry Andric } 20706c3fb27SDimitry Andric } 20806c3fb27SDimitry Andric 20906c3fb27SDimitry Andric // Check if Ty is a usable substitute for the coercion type. 21006c3fb27SDimitry Andric bool isUsableType(llvm::StructType *Ty) const { 21106c3fb27SDimitry Andric return llvm::ArrayRef(Elems) == Ty->elements(); 21206c3fb27SDimitry Andric } 21306c3fb27SDimitry Andric 21406c3fb27SDimitry Andric // Get the coercion type as a literal struct type. 21506c3fb27SDimitry Andric llvm::Type *getType() const { 21606c3fb27SDimitry Andric if (Elems.size() == 1) 21706c3fb27SDimitry Andric return Elems.front(); 21806c3fb27SDimitry Andric else 21906c3fb27SDimitry Andric return llvm::StructType::get(Context, Elems); 22006c3fb27SDimitry Andric } 22106c3fb27SDimitry Andric }; 22206c3fb27SDimitry Andric }; 22306c3fb27SDimitry Andric } // end anonymous namespace 22406c3fb27SDimitry Andric 22506c3fb27SDimitry Andric ABIArgInfo 22606c3fb27SDimitry Andric SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const { 22706c3fb27SDimitry Andric if (Ty->isVoidType()) 22806c3fb27SDimitry Andric return ABIArgInfo::getIgnore(); 22906c3fb27SDimitry Andric 23006c3fb27SDimitry Andric uint64_t Size = getContext().getTypeSize(Ty); 23106c3fb27SDimitry Andric 23206c3fb27SDimitry Andric // Anything too big to fit in registers is passed with an explicit indirect 23306c3fb27SDimitry Andric // pointer / sret pointer. 23406c3fb27SDimitry Andric if (Size > SizeLimit) 23506c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, /*ByVal=*/false); 23606c3fb27SDimitry Andric 23706c3fb27SDimitry Andric // Treat an enum type as its underlying type. 23806c3fb27SDimitry Andric if (const EnumType *EnumTy = Ty->getAs<EnumType>()) 23906c3fb27SDimitry Andric Ty = EnumTy->getDecl()->getIntegerType(); 24006c3fb27SDimitry Andric 24106c3fb27SDimitry Andric // Integer types smaller than a register are extended. 24206c3fb27SDimitry Andric if (Size < 64 && Ty->isIntegerType()) 24306c3fb27SDimitry Andric return ABIArgInfo::getExtend(Ty); 24406c3fb27SDimitry Andric 24506c3fb27SDimitry Andric if (const auto *EIT = Ty->getAs<BitIntType>()) 24606c3fb27SDimitry Andric if (EIT->getNumBits() < 64) 24706c3fb27SDimitry Andric return ABIArgInfo::getExtend(Ty); 24806c3fb27SDimitry Andric 24906c3fb27SDimitry Andric // Other non-aggregates go in registers. 25006c3fb27SDimitry Andric if (!isAggregateTypeForABI(Ty)) 25106c3fb27SDimitry Andric return ABIArgInfo::getDirect(); 25206c3fb27SDimitry Andric 25306c3fb27SDimitry Andric // If a C++ object has either a non-trivial copy constructor or a non-trivial 25406c3fb27SDimitry Andric // destructor, it is passed with an explicit indirect pointer / sret pointer. 25506c3fb27SDimitry Andric if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) 25606c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); 25706c3fb27SDimitry Andric 25806c3fb27SDimitry Andric // This is a small aggregate type that should be passed in registers. 25906c3fb27SDimitry Andric // Build a coercion type from the LLVM struct type. 26006c3fb27SDimitry Andric llvm::StructType *StrTy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty)); 26106c3fb27SDimitry Andric if (!StrTy) 26206c3fb27SDimitry Andric return ABIArgInfo::getDirect(); 26306c3fb27SDimitry Andric 26406c3fb27SDimitry Andric CoerceBuilder CB(getVMContext(), getDataLayout()); 26506c3fb27SDimitry Andric CB.addStruct(0, StrTy); 266*0fca6ea1SDimitry Andric // All structs, even empty ones, should take up a register argument slot, 267*0fca6ea1SDimitry Andric // so pin the minimum struct size to one bit. 268*0fca6ea1SDimitry Andric CB.pad(llvm::alignTo( 269*0fca6ea1SDimitry Andric std::max(CB.DL.getTypeSizeInBits(StrTy).getKnownMinValue(), uint64_t(1)), 270*0fca6ea1SDimitry Andric 64)); 27106c3fb27SDimitry Andric 27206c3fb27SDimitry Andric // Try to use the original type for coercion. 27306c3fb27SDimitry Andric llvm::Type *CoerceTy = CB.isUsableType(StrTy) ? StrTy : CB.getType(); 27406c3fb27SDimitry Andric 27506c3fb27SDimitry Andric if (CB.InReg) 27606c3fb27SDimitry Andric return ABIArgInfo::getDirectInReg(CoerceTy); 27706c3fb27SDimitry Andric else 27806c3fb27SDimitry Andric return ABIArgInfo::getDirect(CoerceTy); 27906c3fb27SDimitry Andric } 28006c3fb27SDimitry Andric 281*0fca6ea1SDimitry Andric RValue SparcV9ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, 282*0fca6ea1SDimitry Andric QualType Ty, AggValueSlot Slot) const { 28306c3fb27SDimitry Andric ABIArgInfo AI = classifyType(Ty, 16 * 8); 28406c3fb27SDimitry Andric llvm::Type *ArgTy = CGT.ConvertType(Ty); 28506c3fb27SDimitry Andric if (AI.canHaveCoerceToType() && !AI.getCoerceToType()) 28606c3fb27SDimitry Andric AI.setCoerceToType(ArgTy); 28706c3fb27SDimitry Andric 28806c3fb27SDimitry Andric CharUnits SlotSize = CharUnits::fromQuantity(8); 28906c3fb27SDimitry Andric 29006c3fb27SDimitry Andric CGBuilderTy &Builder = CGF.Builder; 29106c3fb27SDimitry Andric Address Addr = Address(Builder.CreateLoad(VAListAddr, "ap.cur"), 29206c3fb27SDimitry Andric getVAListElementType(CGF), SlotSize); 2935f757f3fSDimitry Andric llvm::Type *ArgPtrTy = CGF.UnqualPtrTy; 29406c3fb27SDimitry Andric 29506c3fb27SDimitry Andric auto TypeInfo = getContext().getTypeInfoInChars(Ty); 29606c3fb27SDimitry Andric 29706c3fb27SDimitry Andric Address ArgAddr = Address::invalid(); 29806c3fb27SDimitry Andric CharUnits Stride; 29906c3fb27SDimitry Andric switch (AI.getKind()) { 30006c3fb27SDimitry Andric case ABIArgInfo::Expand: 30106c3fb27SDimitry Andric case ABIArgInfo::CoerceAndExpand: 30206c3fb27SDimitry Andric case ABIArgInfo::InAlloca: 30306c3fb27SDimitry Andric llvm_unreachable("Unsupported ABI kind for va_arg"); 30406c3fb27SDimitry Andric 30506c3fb27SDimitry Andric case ABIArgInfo::Extend: { 30606c3fb27SDimitry Andric Stride = SlotSize; 30706c3fb27SDimitry Andric CharUnits Offset = SlotSize - TypeInfo.Width; 30806c3fb27SDimitry Andric ArgAddr = Builder.CreateConstInBoundsByteGEP(Addr, Offset, "extend"); 30906c3fb27SDimitry Andric break; 31006c3fb27SDimitry Andric } 31106c3fb27SDimitry Andric 31206c3fb27SDimitry Andric case ABIArgInfo::Direct: { 31306c3fb27SDimitry Andric auto AllocSize = getDataLayout().getTypeAllocSize(AI.getCoerceToType()); 31406c3fb27SDimitry Andric Stride = CharUnits::fromQuantity(AllocSize).alignTo(SlotSize); 31506c3fb27SDimitry Andric ArgAddr = Addr; 31606c3fb27SDimitry Andric break; 31706c3fb27SDimitry Andric } 31806c3fb27SDimitry Andric 31906c3fb27SDimitry Andric case ABIArgInfo::Indirect: 32006c3fb27SDimitry Andric case ABIArgInfo::IndirectAliased: 32106c3fb27SDimitry Andric Stride = SlotSize; 32206c3fb27SDimitry Andric ArgAddr = Addr.withElementType(ArgPtrTy); 32306c3fb27SDimitry Andric ArgAddr = Address(Builder.CreateLoad(ArgAddr, "indirect.arg"), ArgTy, 32406c3fb27SDimitry Andric TypeInfo.Align); 32506c3fb27SDimitry Andric break; 32606c3fb27SDimitry Andric 32706c3fb27SDimitry Andric case ABIArgInfo::Ignore: 328*0fca6ea1SDimitry Andric return Slot.asRValue(); 32906c3fb27SDimitry Andric } 33006c3fb27SDimitry Andric 33106c3fb27SDimitry Andric // Update VAList. 33206c3fb27SDimitry Andric Address NextPtr = Builder.CreateConstInBoundsByteGEP(Addr, Stride, "ap.next"); 333*0fca6ea1SDimitry Andric Builder.CreateStore(NextPtr.emitRawPointer(CGF), VAListAddr); 33406c3fb27SDimitry Andric 335*0fca6ea1SDimitry Andric return CGF.EmitLoadOfAnyValue( 336*0fca6ea1SDimitry Andric CGF.MakeAddrLValue(ArgAddr.withElementType(ArgTy), Ty), Slot); 33706c3fb27SDimitry Andric } 33806c3fb27SDimitry Andric 33906c3fb27SDimitry Andric void SparcV9ABIInfo::computeInfo(CGFunctionInfo &FI) const { 34006c3fb27SDimitry Andric FI.getReturnInfo() = classifyType(FI.getReturnType(), 32 * 8); 34106c3fb27SDimitry Andric for (auto &I : FI.arguments()) 34206c3fb27SDimitry Andric I.info = classifyType(I.type, 16 * 8); 34306c3fb27SDimitry Andric } 34406c3fb27SDimitry Andric 34506c3fb27SDimitry Andric namespace { 34606c3fb27SDimitry Andric class SparcV9TargetCodeGenInfo : public TargetCodeGenInfo { 34706c3fb27SDimitry Andric public: 34806c3fb27SDimitry Andric SparcV9TargetCodeGenInfo(CodeGenTypes &CGT) 34906c3fb27SDimitry Andric : TargetCodeGenInfo(std::make_unique<SparcV9ABIInfo>(CGT)) {} 35006c3fb27SDimitry Andric 35106c3fb27SDimitry Andric int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override { 35206c3fb27SDimitry Andric return 14; 35306c3fb27SDimitry Andric } 35406c3fb27SDimitry Andric 35506c3fb27SDimitry Andric bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, 35606c3fb27SDimitry Andric llvm::Value *Address) const override; 35706c3fb27SDimitry Andric 35806c3fb27SDimitry Andric llvm::Value *decodeReturnAddress(CodeGen::CodeGenFunction &CGF, 35906c3fb27SDimitry Andric llvm::Value *Address) const override { 36006c3fb27SDimitry Andric return CGF.Builder.CreateGEP(CGF.Int8Ty, Address, 36106c3fb27SDimitry Andric llvm::ConstantInt::get(CGF.Int32Ty, 8)); 36206c3fb27SDimitry Andric } 36306c3fb27SDimitry Andric 36406c3fb27SDimitry Andric llvm::Value *encodeReturnAddress(CodeGen::CodeGenFunction &CGF, 36506c3fb27SDimitry Andric llvm::Value *Address) const override { 36606c3fb27SDimitry Andric return CGF.Builder.CreateGEP(CGF.Int8Ty, Address, 36706c3fb27SDimitry Andric llvm::ConstantInt::get(CGF.Int32Ty, -8)); 36806c3fb27SDimitry Andric } 36906c3fb27SDimitry Andric }; 37006c3fb27SDimitry Andric } // end anonymous namespace 37106c3fb27SDimitry Andric 37206c3fb27SDimitry Andric bool 37306c3fb27SDimitry Andric SparcV9TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, 37406c3fb27SDimitry Andric llvm::Value *Address) const { 37506c3fb27SDimitry Andric // This is calculated from the LLVM and GCC tables and verified 37606c3fb27SDimitry Andric // against gcc output. AFAIK all ABIs use the same encoding. 37706c3fb27SDimitry Andric 37806c3fb27SDimitry Andric CodeGen::CGBuilderTy &Builder = CGF.Builder; 37906c3fb27SDimitry Andric 38006c3fb27SDimitry Andric llvm::IntegerType *i8 = CGF.Int8Ty; 38106c3fb27SDimitry Andric llvm::Value *Four8 = llvm::ConstantInt::get(i8, 4); 38206c3fb27SDimitry Andric llvm::Value *Eight8 = llvm::ConstantInt::get(i8, 8); 38306c3fb27SDimitry Andric 38406c3fb27SDimitry Andric // 0-31: the 8-byte general-purpose registers 38506c3fb27SDimitry Andric AssignToArrayRange(Builder, Address, Eight8, 0, 31); 38606c3fb27SDimitry Andric 38706c3fb27SDimitry Andric // 32-63: f0-31, the 4-byte floating-point registers 38806c3fb27SDimitry Andric AssignToArrayRange(Builder, Address, Four8, 32, 63); 38906c3fb27SDimitry Andric 39006c3fb27SDimitry Andric // Y = 64 39106c3fb27SDimitry Andric // PSR = 65 39206c3fb27SDimitry Andric // WIM = 66 39306c3fb27SDimitry Andric // TBR = 67 39406c3fb27SDimitry Andric // PC = 68 39506c3fb27SDimitry Andric // NPC = 69 39606c3fb27SDimitry Andric // FSR = 70 39706c3fb27SDimitry Andric // CSR = 71 39806c3fb27SDimitry Andric AssignToArrayRange(Builder, Address, Eight8, 64, 71); 39906c3fb27SDimitry Andric 40006c3fb27SDimitry Andric // 72-87: d0-15, the 8-byte floating-point registers 40106c3fb27SDimitry Andric AssignToArrayRange(Builder, Address, Eight8, 72, 87); 40206c3fb27SDimitry Andric 40306c3fb27SDimitry Andric return false; 40406c3fb27SDimitry Andric } 40506c3fb27SDimitry Andric 40606c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo> 40706c3fb27SDimitry Andric CodeGen::createSparcV8TargetCodeGenInfo(CodeGenModule &CGM) { 40806c3fb27SDimitry Andric return std::make_unique<SparcV8TargetCodeGenInfo>(CGM.getTypes()); 40906c3fb27SDimitry Andric } 41006c3fb27SDimitry Andric 41106c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo> 41206c3fb27SDimitry Andric CodeGen::createSparcV9TargetCodeGenInfo(CodeGenModule &CGM) { 41306c3fb27SDimitry Andric return std::make_unique<SparcV9TargetCodeGenInfo>(CGM.getTypes()); 41406c3fb27SDimitry Andric } 415