xref: /freebsd/contrib/llvm-project/clang/lib/CodeGen/Targets/Sparc.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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:
SparcV8ABIInfo(CodeGenTypes & CGT)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
classifyReturnType(QualType Ty) const3406c3fb27SDimitry 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 
computeInfo(CGFunctionInfo & FI) const4306c3fb27SDimitry 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:
SparcV8TargetCodeGenInfo(CodeGenTypes & CGT)5306c3fb27SDimitry Andric   SparcV8TargetCodeGenInfo(CodeGenTypes &CGT)
5406c3fb27SDimitry Andric       : TargetCodeGenInfo(std::make_unique<SparcV8ABIInfo>(CGT)) {}
5506c3fb27SDimitry Andric 
decodeReturnAddress(CodeGen::CodeGenFunction & CGF,llvm::Value * Address) const5606c3fb27SDimitry 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 
encodeReturnAddress(CodeGen::CodeGenFunction & CGF,llvm::Value * Address) const6706c3fb27SDimitry 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:
SparcV9ABIInfo(CodeGenTypes & CGT)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 
CoerceBuilder__anoncb6a8a600311::SparcV9ABIInfo::CoerceBuilder13506c3fb27SDimitry 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.
pad__anoncb6a8a600311::SparcV9ABIInfo::CoerceBuilder13906c3fb27SDimitry 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.
addFloat__anoncb6a8a600311::SparcV9ABIInfo::CoerceBuilder16506c3fb27SDimitry 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).
addStruct__anoncb6a8a600311::SparcV9ABIInfo::CoerceBuilder17806c3fb27SDimitry 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.
isUsableType__anoncb6a8a600311::SparcV9ABIInfo::CoerceBuilder21006c3fb27SDimitry 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.
getType__anoncb6a8a600311::SparcV9ABIInfo::CoerceBuilder21506c3fb27SDimitry 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
classifyType(QualType Ty,unsigned SizeLimit) const22606c3fb27SDimitry 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 
EmitVAArg(CodeGenFunction & CGF,Address VAListAddr,QualType Ty,AggValueSlot Slot) const281*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 
computeInfo(CGFunctionInfo & FI) const33906c3fb27SDimitry 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:
SparcV9TargetCodeGenInfo(CodeGenTypes & CGT)34806c3fb27SDimitry Andric   SparcV9TargetCodeGenInfo(CodeGenTypes &CGT)
34906c3fb27SDimitry Andric       : TargetCodeGenInfo(std::make_unique<SparcV9ABIInfo>(CGT)) {}
35006c3fb27SDimitry Andric 
getDwarfEHStackPointer(CodeGen::CodeGenModule & M) const35106c3fb27SDimitry 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 
decodeReturnAddress(CodeGen::CodeGenFunction & CGF,llvm::Value * Address) const35806c3fb27SDimitry 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 
encodeReturnAddress(CodeGen::CodeGenFunction & CGF,llvm::Value * Address) const36406c3fb27SDimitry 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
initDwarfEHRegSizeTable(CodeGen::CodeGenFunction & CGF,llvm::Value * Address) const37306c3fb27SDimitry 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>
createSparcV8TargetCodeGenInfo(CodeGenModule & CGM)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>
createSparcV9TargetCodeGenInfo(CodeGenModule & CGM)41206c3fb27SDimitry Andric CodeGen::createSparcV9TargetCodeGenInfo(CodeGenModule &CGM) {
41306c3fb27SDimitry Andric   return std::make_unique<SparcV9TargetCodeGenInfo>(CGM.getTypes());
41406c3fb27SDimitry Andric }
415