xref: /llvm-project/clang/lib/CodeGen/Targets/Sparc.cpp (revision 6d973b4548e281d0b8e75e85833804bb45b6a0e8)
1992cb984SSergei Barannikov //===- Sparc.cpp ----------------------------------------------------------===//
2992cb984SSergei Barannikov //
3992cb984SSergei Barannikov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4992cb984SSergei Barannikov // See https://llvm.org/LICENSE.txt for license information.
5992cb984SSergei Barannikov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6992cb984SSergei Barannikov //
7992cb984SSergei Barannikov //===----------------------------------------------------------------------===//
8992cb984SSergei Barannikov 
9992cb984SSergei Barannikov #include "ABIInfoImpl.h"
10992cb984SSergei Barannikov #include "TargetInfo.h"
11992cb984SSergei Barannikov 
12992cb984SSergei Barannikov using namespace clang;
13992cb984SSergei Barannikov using namespace clang::CodeGen;
14992cb984SSergei Barannikov 
15992cb984SSergei Barannikov //===----------------------------------------------------------------------===//
16992cb984SSergei Barannikov // SPARC v8 ABI Implementation.
17992cb984SSergei Barannikov // Based on the SPARC Compliance Definition version 2.4.1.
18992cb984SSergei Barannikov //
19992cb984SSergei Barannikov // Ensures that complex values are passed in registers.
20992cb984SSergei Barannikov //
21992cb984SSergei Barannikov namespace {
22992cb984SSergei Barannikov class SparcV8ABIInfo : public DefaultABIInfo {
23992cb984SSergei Barannikov public:
SparcV8ABIInfo(CodeGenTypes & CGT)24992cb984SSergei Barannikov   SparcV8ABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
25992cb984SSergei Barannikov 
26992cb984SSergei Barannikov private:
27992cb984SSergei Barannikov   ABIArgInfo classifyReturnType(QualType RetTy) const;
28992cb984SSergei Barannikov   void computeInfo(CGFunctionInfo &FI) const override;
29992cb984SSergei Barannikov };
30992cb984SSergei Barannikov } // end anonymous namespace
31992cb984SSergei Barannikov 
32992cb984SSergei Barannikov 
33992cb984SSergei Barannikov ABIArgInfo
classifyReturnType(QualType Ty) const34992cb984SSergei Barannikov SparcV8ABIInfo::classifyReturnType(QualType Ty) const {
35992cb984SSergei Barannikov   if (Ty->isAnyComplexType()) {
36992cb984SSergei Barannikov     return ABIArgInfo::getDirect();
37992cb984SSergei Barannikov   }
38992cb984SSergei Barannikov   else {
39992cb984SSergei Barannikov     return DefaultABIInfo::classifyReturnType(Ty);
40992cb984SSergei Barannikov   }
41992cb984SSergei Barannikov }
42992cb984SSergei Barannikov 
computeInfo(CGFunctionInfo & FI) const43992cb984SSergei Barannikov void SparcV8ABIInfo::computeInfo(CGFunctionInfo &FI) const {
44992cb984SSergei Barannikov 
45992cb984SSergei Barannikov   FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
46992cb984SSergei Barannikov   for (auto &Arg : FI.arguments())
47992cb984SSergei Barannikov     Arg.info = classifyArgumentType(Arg.type);
48992cb984SSergei Barannikov }
49992cb984SSergei Barannikov 
50992cb984SSergei Barannikov namespace {
51992cb984SSergei Barannikov class SparcV8TargetCodeGenInfo : public TargetCodeGenInfo {
52992cb984SSergei Barannikov public:
SparcV8TargetCodeGenInfo(CodeGenTypes & CGT)53992cb984SSergei Barannikov   SparcV8TargetCodeGenInfo(CodeGenTypes &CGT)
54992cb984SSergei Barannikov       : TargetCodeGenInfo(std::make_unique<SparcV8ABIInfo>(CGT)) {}
55992cb984SSergei Barannikov 
decodeReturnAddress(CodeGen::CodeGenFunction & CGF,llvm::Value * Address) const56992cb984SSergei Barannikov   llvm::Value *decodeReturnAddress(CodeGen::CodeGenFunction &CGF,
57992cb984SSergei Barannikov                                    llvm::Value *Address) const override {
58992cb984SSergei Barannikov     int Offset;
59992cb984SSergei Barannikov     if (isAggregateTypeForABI(CGF.CurFnInfo->getReturnType()))
60992cb984SSergei Barannikov       Offset = 12;
61992cb984SSergei Barannikov     else
62992cb984SSergei Barannikov       Offset = 8;
63992cb984SSergei Barannikov     return CGF.Builder.CreateGEP(CGF.Int8Ty, Address,
64992cb984SSergei Barannikov                                  llvm::ConstantInt::get(CGF.Int32Ty, Offset));
65992cb984SSergei Barannikov   }
66992cb984SSergei Barannikov 
encodeReturnAddress(CodeGen::CodeGenFunction & CGF,llvm::Value * Address) const67992cb984SSergei Barannikov   llvm::Value *encodeReturnAddress(CodeGen::CodeGenFunction &CGF,
68992cb984SSergei Barannikov                                    llvm::Value *Address) const override {
69992cb984SSergei Barannikov     int Offset;
70992cb984SSergei Barannikov     if (isAggregateTypeForABI(CGF.CurFnInfo->getReturnType()))
71992cb984SSergei Barannikov       Offset = -12;
72992cb984SSergei Barannikov     else
73992cb984SSergei Barannikov       Offset = -8;
74992cb984SSergei Barannikov     return CGF.Builder.CreateGEP(CGF.Int8Ty, Address,
75992cb984SSergei Barannikov                                  llvm::ConstantInt::get(CGF.Int32Ty, Offset));
76992cb984SSergei Barannikov   }
77992cb984SSergei Barannikov };
78992cb984SSergei Barannikov } // end anonymous namespace
79992cb984SSergei Barannikov 
80992cb984SSergei Barannikov //===----------------------------------------------------------------------===//
81992cb984SSergei Barannikov // SPARC v9 ABI Implementation.
82992cb984SSergei Barannikov // Based on the SPARC Compliance Definition version 2.4.1.
83992cb984SSergei Barannikov //
84992cb984SSergei Barannikov // Function arguments a mapped to a nominal "parameter array" and promoted to
85992cb984SSergei Barannikov // registers depending on their type. Each argument occupies 8 or 16 bytes in
86992cb984SSergei Barannikov // the array, structs larger than 16 bytes are passed indirectly.
87992cb984SSergei Barannikov //
88992cb984SSergei Barannikov // One case requires special care:
89992cb984SSergei Barannikov //
90992cb984SSergei Barannikov //   struct mixed {
91992cb984SSergei Barannikov //     int i;
92992cb984SSergei Barannikov //     float f;
93992cb984SSergei Barannikov //   };
94992cb984SSergei Barannikov //
95992cb984SSergei Barannikov // When a struct mixed is passed by value, it only occupies 8 bytes in the
96992cb984SSergei Barannikov // parameter array, but the int is passed in an integer register, and the float
97992cb984SSergei Barannikov // is passed in a floating point register. This is represented as two arguments
98992cb984SSergei Barannikov // with the LLVM IR inreg attribute:
99992cb984SSergei Barannikov //
100992cb984SSergei Barannikov //   declare void f(i32 inreg %i, float inreg %f)
101992cb984SSergei Barannikov //
102992cb984SSergei Barannikov // The code generator will only allocate 4 bytes from the parameter array for
103992cb984SSergei Barannikov // the inreg arguments. All other arguments are allocated a multiple of 8
104992cb984SSergei Barannikov // bytes.
105992cb984SSergei Barannikov //
106992cb984SSergei Barannikov namespace {
107992cb984SSergei Barannikov class SparcV9ABIInfo : public ABIInfo {
108992cb984SSergei Barannikov public:
SparcV9ABIInfo(CodeGenTypes & CGT)109992cb984SSergei Barannikov   SparcV9ABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {}
110992cb984SSergei Barannikov 
111992cb984SSergei Barannikov private:
112992cb984SSergei Barannikov   ABIArgInfo classifyType(QualType RetTy, unsigned SizeLimit) const;
113992cb984SSergei Barannikov   void computeInfo(CGFunctionInfo &FI) const override;
114*6d973b45SMariya Podchishchaeva   RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
115*6d973b45SMariya Podchishchaeva                    AggValueSlot Slot) const override;
116992cb984SSergei Barannikov 
117992cb984SSergei Barannikov   // Coercion type builder for structs passed in registers. The coercion type
118992cb984SSergei Barannikov   // serves two purposes:
119992cb984SSergei Barannikov   //
120992cb984SSergei Barannikov   // 1. Pad structs to a multiple of 64 bits, so they are passed 'left-aligned'
121992cb984SSergei Barannikov   //    in registers.
122992cb984SSergei Barannikov   // 2. Expose aligned floating point elements as first-level elements, so the
123992cb984SSergei Barannikov   //    code generator knows to pass them in floating point registers.
124992cb984SSergei Barannikov   //
125992cb984SSergei Barannikov   // We also compute the InReg flag which indicates that the struct contains
126992cb984SSergei Barannikov   // aligned 32-bit floats.
127992cb984SSergei Barannikov   //
128992cb984SSergei Barannikov   struct CoerceBuilder {
129992cb984SSergei Barannikov     llvm::LLVMContext &Context;
130992cb984SSergei Barannikov     const llvm::DataLayout &DL;
131992cb984SSergei Barannikov     SmallVector<llvm::Type*, 8> Elems;
132992cb984SSergei Barannikov     uint64_t Size;
133992cb984SSergei Barannikov     bool InReg;
134992cb984SSergei Barannikov 
CoerceBuilder__anonb533a2d30311::SparcV9ABIInfo::CoerceBuilder135992cb984SSergei Barannikov     CoerceBuilder(llvm::LLVMContext &c, const llvm::DataLayout &dl)
136992cb984SSergei Barannikov       : Context(c), DL(dl), Size(0), InReg(false) {}
137992cb984SSergei Barannikov 
138992cb984SSergei Barannikov     // Pad Elems with integers until Size is ToSize.
pad__anonb533a2d30311::SparcV9ABIInfo::CoerceBuilder139992cb984SSergei Barannikov     void pad(uint64_t ToSize) {
140992cb984SSergei Barannikov       assert(ToSize >= Size && "Cannot remove elements");
141992cb984SSergei Barannikov       if (ToSize == Size)
142992cb984SSergei Barannikov         return;
143992cb984SSergei Barannikov 
144992cb984SSergei Barannikov       // Finish the current 64-bit word.
145992cb984SSergei Barannikov       uint64_t Aligned = llvm::alignTo(Size, 64);
146992cb984SSergei Barannikov       if (Aligned > Size && Aligned <= ToSize) {
147992cb984SSergei Barannikov         Elems.push_back(llvm::IntegerType::get(Context, Aligned - Size));
148992cb984SSergei Barannikov         Size = Aligned;
149992cb984SSergei Barannikov       }
150992cb984SSergei Barannikov 
151992cb984SSergei Barannikov       // Add whole 64-bit words.
152992cb984SSergei Barannikov       while (Size + 64 <= ToSize) {
153992cb984SSergei Barannikov         Elems.push_back(llvm::Type::getInt64Ty(Context));
154992cb984SSergei Barannikov         Size += 64;
155992cb984SSergei Barannikov       }
156992cb984SSergei Barannikov 
157992cb984SSergei Barannikov       // Final in-word padding.
158992cb984SSergei Barannikov       if (Size < ToSize) {
159992cb984SSergei Barannikov         Elems.push_back(llvm::IntegerType::get(Context, ToSize - Size));
160992cb984SSergei Barannikov         Size = ToSize;
161992cb984SSergei Barannikov       }
162992cb984SSergei Barannikov     }
163992cb984SSergei Barannikov 
164992cb984SSergei Barannikov     // Add a floating point element at Offset.
addFloat__anonb533a2d30311::SparcV9ABIInfo::CoerceBuilder165992cb984SSergei Barannikov     void addFloat(uint64_t Offset, llvm::Type *Ty, unsigned Bits) {
166992cb984SSergei Barannikov       // Unaligned floats are treated as integers.
167992cb984SSergei Barannikov       if (Offset % Bits)
168992cb984SSergei Barannikov         return;
169992cb984SSergei Barannikov       // The InReg flag is only required if there are any floats < 64 bits.
170992cb984SSergei Barannikov       if (Bits < 64)
171992cb984SSergei Barannikov         InReg = true;
172992cb984SSergei Barannikov       pad(Offset);
173992cb984SSergei Barannikov       Elems.push_back(Ty);
174992cb984SSergei Barannikov       Size = Offset + Bits;
175992cb984SSergei Barannikov     }
176992cb984SSergei Barannikov 
177992cb984SSergei Barannikov     // Add a struct type to the coercion type, starting at Offset (in bits).
addStruct__anonb533a2d30311::SparcV9ABIInfo::CoerceBuilder178992cb984SSergei Barannikov     void addStruct(uint64_t Offset, llvm::StructType *StrTy) {
179992cb984SSergei Barannikov       const llvm::StructLayout *Layout = DL.getStructLayout(StrTy);
180992cb984SSergei Barannikov       for (unsigned i = 0, e = StrTy->getNumElements(); i != e; ++i) {
181992cb984SSergei Barannikov         llvm::Type *ElemTy = StrTy->getElementType(i);
182992cb984SSergei Barannikov         uint64_t ElemOffset = Offset + Layout->getElementOffsetInBits(i);
183992cb984SSergei Barannikov         switch (ElemTy->getTypeID()) {
184992cb984SSergei Barannikov         case llvm::Type::StructTyID:
185992cb984SSergei Barannikov           addStruct(ElemOffset, cast<llvm::StructType>(ElemTy));
186992cb984SSergei Barannikov           break;
187992cb984SSergei Barannikov         case llvm::Type::FloatTyID:
188992cb984SSergei Barannikov           addFloat(ElemOffset, ElemTy, 32);
189992cb984SSergei Barannikov           break;
190992cb984SSergei Barannikov         case llvm::Type::DoubleTyID:
191992cb984SSergei Barannikov           addFloat(ElemOffset, ElemTy, 64);
192992cb984SSergei Barannikov           break;
193992cb984SSergei Barannikov         case llvm::Type::FP128TyID:
194992cb984SSergei Barannikov           addFloat(ElemOffset, ElemTy, 128);
195992cb984SSergei Barannikov           break;
196992cb984SSergei Barannikov         case llvm::Type::PointerTyID:
197992cb984SSergei Barannikov           if (ElemOffset % 64 == 0) {
198992cb984SSergei Barannikov             pad(ElemOffset);
199992cb984SSergei Barannikov             Elems.push_back(ElemTy);
200992cb984SSergei Barannikov             Size += 64;
201992cb984SSergei Barannikov           }
202992cb984SSergei Barannikov           break;
203992cb984SSergei Barannikov         default:
204992cb984SSergei Barannikov           break;
205992cb984SSergei Barannikov         }
206992cb984SSergei Barannikov       }
207992cb984SSergei Barannikov     }
208992cb984SSergei Barannikov 
209992cb984SSergei Barannikov     // Check if Ty is a usable substitute for the coercion type.
isUsableType__anonb533a2d30311::SparcV9ABIInfo::CoerceBuilder210992cb984SSergei Barannikov     bool isUsableType(llvm::StructType *Ty) const {
211992cb984SSergei Barannikov       return llvm::ArrayRef(Elems) == Ty->elements();
212992cb984SSergei Barannikov     }
213992cb984SSergei Barannikov 
214992cb984SSergei Barannikov     // Get the coercion type as a literal struct type.
getType__anonb533a2d30311::SparcV9ABIInfo::CoerceBuilder215992cb984SSergei Barannikov     llvm::Type *getType() const {
216992cb984SSergei Barannikov       if (Elems.size() == 1)
217992cb984SSergei Barannikov         return Elems.front();
218992cb984SSergei Barannikov       else
219992cb984SSergei Barannikov         return llvm::StructType::get(Context, Elems);
220992cb984SSergei Barannikov     }
221992cb984SSergei Barannikov   };
222992cb984SSergei Barannikov };
223992cb984SSergei Barannikov } // end anonymous namespace
224992cb984SSergei Barannikov 
225992cb984SSergei Barannikov ABIArgInfo
classifyType(QualType Ty,unsigned SizeLimit) const226992cb984SSergei Barannikov SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const {
227992cb984SSergei Barannikov   if (Ty->isVoidType())
228992cb984SSergei Barannikov     return ABIArgInfo::getIgnore();
229992cb984SSergei Barannikov 
230992cb984SSergei Barannikov   uint64_t Size = getContext().getTypeSize(Ty);
231992cb984SSergei Barannikov 
232992cb984SSergei Barannikov   // Anything too big to fit in registers is passed with an explicit indirect
233992cb984SSergei Barannikov   // pointer / sret pointer.
234992cb984SSergei Barannikov   if (Size > SizeLimit)
235992cb984SSergei Barannikov     return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
236992cb984SSergei Barannikov 
237992cb984SSergei Barannikov   // Treat an enum type as its underlying type.
238992cb984SSergei Barannikov   if (const EnumType *EnumTy = Ty->getAs<EnumType>())
239992cb984SSergei Barannikov     Ty = EnumTy->getDecl()->getIntegerType();
240992cb984SSergei Barannikov 
241992cb984SSergei Barannikov   // Integer types smaller than a register are extended.
242992cb984SSergei Barannikov   if (Size < 64 && Ty->isIntegerType())
243992cb984SSergei Barannikov     return ABIArgInfo::getExtend(Ty);
244992cb984SSergei Barannikov 
245992cb984SSergei Barannikov   if (const auto *EIT = Ty->getAs<BitIntType>())
246992cb984SSergei Barannikov     if (EIT->getNumBits() < 64)
247992cb984SSergei Barannikov       return ABIArgInfo::getExtend(Ty);
248992cb984SSergei Barannikov 
249992cb984SSergei Barannikov   // Other non-aggregates go in registers.
250992cb984SSergei Barannikov   if (!isAggregateTypeForABI(Ty))
251992cb984SSergei Barannikov     return ABIArgInfo::getDirect();
252992cb984SSergei Barannikov 
253992cb984SSergei Barannikov   // If a C++ object has either a non-trivial copy constructor or a non-trivial
254992cb984SSergei Barannikov   // destructor, it is passed with an explicit indirect pointer / sret pointer.
255992cb984SSergei Barannikov   if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
256992cb984SSergei Barannikov     return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
257992cb984SSergei Barannikov 
258992cb984SSergei Barannikov   // This is a small aggregate type that should be passed in registers.
259992cb984SSergei Barannikov   // Build a coercion type from the LLVM struct type.
260992cb984SSergei Barannikov   llvm::StructType *StrTy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty));
261992cb984SSergei Barannikov   if (!StrTy)
262992cb984SSergei Barannikov     return ABIArgInfo::getDirect();
263992cb984SSergei Barannikov 
264992cb984SSergei Barannikov   CoerceBuilder CB(getVMContext(), getDataLayout());
265992cb984SSergei Barannikov   CB.addStruct(0, StrTy);
266c2fba6dfSKoakuma   // All structs, even empty ones, should take up a register argument slot,
267c2fba6dfSKoakuma   // so pin the minimum struct size to one bit.
268c2fba6dfSKoakuma   CB.pad(llvm::alignTo(
2698a4cbeadSFlorian Hahn       std::max(CB.DL.getTypeSizeInBits(StrTy).getKnownMinValue(), uint64_t(1)),
2708a4cbeadSFlorian Hahn       64));
271992cb984SSergei Barannikov 
272992cb984SSergei Barannikov   // Try to use the original type for coercion.
273992cb984SSergei Barannikov   llvm::Type *CoerceTy = CB.isUsableType(StrTy) ? StrTy : CB.getType();
274992cb984SSergei Barannikov 
275992cb984SSergei Barannikov   if (CB.InReg)
276992cb984SSergei Barannikov     return ABIArgInfo::getDirectInReg(CoerceTy);
277992cb984SSergei Barannikov   else
278992cb984SSergei Barannikov     return ABIArgInfo::getDirect(CoerceTy);
279992cb984SSergei Barannikov }
280992cb984SSergei Barannikov 
EmitVAArg(CodeGenFunction & CGF,Address VAListAddr,QualType Ty,AggValueSlot Slot) const281*6d973b45SMariya Podchishchaeva RValue SparcV9ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
282*6d973b45SMariya Podchishchaeva                                  QualType Ty, AggValueSlot Slot) const {
283992cb984SSergei Barannikov   ABIArgInfo AI = classifyType(Ty, 16 * 8);
284992cb984SSergei Barannikov   llvm::Type *ArgTy = CGT.ConvertType(Ty);
285992cb984SSergei Barannikov   if (AI.canHaveCoerceToType() && !AI.getCoerceToType())
286992cb984SSergei Barannikov     AI.setCoerceToType(ArgTy);
287992cb984SSergei Barannikov 
288992cb984SSergei Barannikov   CharUnits SlotSize = CharUnits::fromQuantity(8);
289992cb984SSergei Barannikov 
290992cb984SSergei Barannikov   CGBuilderTy &Builder = CGF.Builder;
291992cb984SSergei Barannikov   Address Addr = Address(Builder.CreateLoad(VAListAddr, "ap.cur"),
292992cb984SSergei Barannikov                          getVAListElementType(CGF), SlotSize);
293b4858c63SBjörn Pettersson   llvm::Type *ArgPtrTy = CGF.UnqualPtrTy;
294992cb984SSergei Barannikov 
295992cb984SSergei Barannikov   auto TypeInfo = getContext().getTypeInfoInChars(Ty);
296992cb984SSergei Barannikov 
297992cb984SSergei Barannikov   Address ArgAddr = Address::invalid();
298992cb984SSergei Barannikov   CharUnits Stride;
299992cb984SSergei Barannikov   switch (AI.getKind()) {
300992cb984SSergei Barannikov   case ABIArgInfo::Expand:
301992cb984SSergei Barannikov   case ABIArgInfo::CoerceAndExpand:
302992cb984SSergei Barannikov   case ABIArgInfo::InAlloca:
303992cb984SSergei Barannikov     llvm_unreachable("Unsupported ABI kind for va_arg");
304992cb984SSergei Barannikov 
305992cb984SSergei Barannikov   case ABIArgInfo::Extend: {
306992cb984SSergei Barannikov     Stride = SlotSize;
307992cb984SSergei Barannikov     CharUnits Offset = SlotSize - TypeInfo.Width;
308992cb984SSergei Barannikov     ArgAddr = Builder.CreateConstInBoundsByteGEP(Addr, Offset, "extend");
309992cb984SSergei Barannikov     break;
310992cb984SSergei Barannikov   }
311992cb984SSergei Barannikov 
312992cb984SSergei Barannikov   case ABIArgInfo::Direct: {
313992cb984SSergei Barannikov     auto AllocSize = getDataLayout().getTypeAllocSize(AI.getCoerceToType());
314992cb984SSergei Barannikov     Stride = CharUnits::fromQuantity(AllocSize).alignTo(SlotSize);
315992cb984SSergei Barannikov     ArgAddr = Addr;
316992cb984SSergei Barannikov     break;
317992cb984SSergei Barannikov   }
318992cb984SSergei Barannikov 
319992cb984SSergei Barannikov   case ABIArgInfo::Indirect:
320992cb984SSergei Barannikov   case ABIArgInfo::IndirectAliased:
321992cb984SSergei Barannikov     Stride = SlotSize;
32244e63ffeSYoungsuk Kim     ArgAddr = Addr.withElementType(ArgPtrTy);
323992cb984SSergei Barannikov     ArgAddr = Address(Builder.CreateLoad(ArgAddr, "indirect.arg"), ArgTy,
324992cb984SSergei Barannikov                       TypeInfo.Align);
325992cb984SSergei Barannikov     break;
326992cb984SSergei Barannikov 
327992cb984SSergei Barannikov   case ABIArgInfo::Ignore:
328*6d973b45SMariya Podchishchaeva     return Slot.asRValue();
329992cb984SSergei Barannikov   }
330992cb984SSergei Barannikov 
331992cb984SSergei Barannikov   // Update VAList.
332992cb984SSergei Barannikov   Address NextPtr = Builder.CreateConstInBoundsByteGEP(Addr, Stride, "ap.next");
33384780af4SAkira Hatanaka   Builder.CreateStore(NextPtr.emitRawPointer(CGF), VAListAddr);
334992cb984SSergei Barannikov 
335*6d973b45SMariya Podchishchaeva   return CGF.EmitLoadOfAnyValue(
336*6d973b45SMariya Podchishchaeva       CGF.MakeAddrLValue(ArgAddr.withElementType(ArgTy), Ty), Slot);
337992cb984SSergei Barannikov }
338992cb984SSergei Barannikov 
computeInfo(CGFunctionInfo & FI) const339992cb984SSergei Barannikov void SparcV9ABIInfo::computeInfo(CGFunctionInfo &FI) const {
340992cb984SSergei Barannikov   FI.getReturnInfo() = classifyType(FI.getReturnType(), 32 * 8);
341992cb984SSergei Barannikov   for (auto &I : FI.arguments())
342992cb984SSergei Barannikov     I.info = classifyType(I.type, 16 * 8);
343992cb984SSergei Barannikov }
344992cb984SSergei Barannikov 
345992cb984SSergei Barannikov namespace {
346992cb984SSergei Barannikov class SparcV9TargetCodeGenInfo : public TargetCodeGenInfo {
347992cb984SSergei Barannikov public:
SparcV9TargetCodeGenInfo(CodeGenTypes & CGT)348992cb984SSergei Barannikov   SparcV9TargetCodeGenInfo(CodeGenTypes &CGT)
349992cb984SSergei Barannikov       : TargetCodeGenInfo(std::make_unique<SparcV9ABIInfo>(CGT)) {}
350992cb984SSergei Barannikov 
getDwarfEHStackPointer(CodeGen::CodeGenModule & M) const351992cb984SSergei Barannikov   int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override {
352992cb984SSergei Barannikov     return 14;
353992cb984SSergei Barannikov   }
354992cb984SSergei Barannikov 
355992cb984SSergei Barannikov   bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
356992cb984SSergei Barannikov                                llvm::Value *Address) const override;
357992cb984SSergei Barannikov 
decodeReturnAddress(CodeGen::CodeGenFunction & CGF,llvm::Value * Address) const358992cb984SSergei Barannikov   llvm::Value *decodeReturnAddress(CodeGen::CodeGenFunction &CGF,
359992cb984SSergei Barannikov                                    llvm::Value *Address) const override {
360992cb984SSergei Barannikov     return CGF.Builder.CreateGEP(CGF.Int8Ty, Address,
361992cb984SSergei Barannikov                                  llvm::ConstantInt::get(CGF.Int32Ty, 8));
362992cb984SSergei Barannikov   }
363992cb984SSergei Barannikov 
encodeReturnAddress(CodeGen::CodeGenFunction & CGF,llvm::Value * Address) const364992cb984SSergei Barannikov   llvm::Value *encodeReturnAddress(CodeGen::CodeGenFunction &CGF,
365992cb984SSergei Barannikov                                    llvm::Value *Address) const override {
366992cb984SSergei Barannikov     return CGF.Builder.CreateGEP(CGF.Int8Ty, Address,
367992cb984SSergei Barannikov                                  llvm::ConstantInt::get(CGF.Int32Ty, -8));
368992cb984SSergei Barannikov   }
369992cb984SSergei Barannikov };
370992cb984SSergei Barannikov } // end anonymous namespace
371992cb984SSergei Barannikov 
372992cb984SSergei Barannikov bool
initDwarfEHRegSizeTable(CodeGen::CodeGenFunction & CGF,llvm::Value * Address) const373992cb984SSergei Barannikov SparcV9TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
374992cb984SSergei Barannikov                                                 llvm::Value *Address) const {
375992cb984SSergei Barannikov   // This is calculated from the LLVM and GCC tables and verified
376992cb984SSergei Barannikov   // against gcc output.  AFAIK all ABIs use the same encoding.
377992cb984SSergei Barannikov 
378992cb984SSergei Barannikov   CodeGen::CGBuilderTy &Builder = CGF.Builder;
379992cb984SSergei Barannikov 
380992cb984SSergei Barannikov   llvm::IntegerType *i8 = CGF.Int8Ty;
381992cb984SSergei Barannikov   llvm::Value *Four8 = llvm::ConstantInt::get(i8, 4);
382992cb984SSergei Barannikov   llvm::Value *Eight8 = llvm::ConstantInt::get(i8, 8);
383992cb984SSergei Barannikov 
384992cb984SSergei Barannikov   // 0-31: the 8-byte general-purpose registers
385992cb984SSergei Barannikov   AssignToArrayRange(Builder, Address, Eight8, 0, 31);
386992cb984SSergei Barannikov 
387992cb984SSergei Barannikov   // 32-63: f0-31, the 4-byte floating-point registers
388992cb984SSergei Barannikov   AssignToArrayRange(Builder, Address, Four8, 32, 63);
389992cb984SSergei Barannikov 
390992cb984SSergei Barannikov   //   Y   = 64
391992cb984SSergei Barannikov   //   PSR = 65
392992cb984SSergei Barannikov   //   WIM = 66
393992cb984SSergei Barannikov   //   TBR = 67
394992cb984SSergei Barannikov   //   PC  = 68
395992cb984SSergei Barannikov   //   NPC = 69
396992cb984SSergei Barannikov   //   FSR = 70
397992cb984SSergei Barannikov   //   CSR = 71
398992cb984SSergei Barannikov   AssignToArrayRange(Builder, Address, Eight8, 64, 71);
399992cb984SSergei Barannikov 
400992cb984SSergei Barannikov   // 72-87: d0-15, the 8-byte floating-point registers
401992cb984SSergei Barannikov   AssignToArrayRange(Builder, Address, Eight8, 72, 87);
402992cb984SSergei Barannikov 
403992cb984SSergei Barannikov   return false;
404992cb984SSergei Barannikov }
405992cb984SSergei Barannikov 
406992cb984SSergei Barannikov std::unique_ptr<TargetCodeGenInfo>
createSparcV8TargetCodeGenInfo(CodeGenModule & CGM)407992cb984SSergei Barannikov CodeGen::createSparcV8TargetCodeGenInfo(CodeGenModule &CGM) {
408992cb984SSergei Barannikov   return std::make_unique<SparcV8TargetCodeGenInfo>(CGM.getTypes());
409992cb984SSergei Barannikov }
410992cb984SSergei Barannikov 
411992cb984SSergei Barannikov std::unique_ptr<TargetCodeGenInfo>
createSparcV9TargetCodeGenInfo(CodeGenModule & CGM)412992cb984SSergei Barannikov CodeGen::createSparcV9TargetCodeGenInfo(CodeGenModule &CGM) {
413992cb984SSergei Barannikov   return std::make_unique<SparcV9TargetCodeGenInfo>(CGM.getTypes());
414992cb984SSergei Barannikov }
415