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