xref: /freebsd-src/contrib/llvm-project/clang/lib/CodeGen/Targets/Sparc.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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