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