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