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
12using namespace clang;
13using 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//
21namespace {
22class SparcV8ABIInfo : public DefaultABIInfo {
23public:
24 SparcV8ABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
25
26private:
27 ABIArgInfo classifyReturnType(QualType RetTy) const;
28 void computeInfo(CGFunctionInfo &FI) const override;
29};
30} // end anonymous namespace
31
32
33ABIArgInfo
34SparcV8ABIInfo::classifyReturnType(QualType Ty) const {
35 if (Ty->isAnyComplexType()) {
36 return ABIArgInfo::getDirect();
37 }
38 else {
39 return DefaultABIInfo::classifyReturnType(RetTy: Ty);
40 }
41}
42
43void SparcV8ABIInfo::computeInfo(CGFunctionInfo &FI) const {
44
45 FI.getReturnInfo() = classifyReturnType(Ty: FI.getReturnType());
46 for (auto &Arg : FI.arguments())
47 Arg.info = classifyArgumentType(RetTy: Arg.type);
48}
49
50namespace {
51class SparcV8TargetCodeGenInfo : public TargetCodeGenInfo {
52public:
53 SparcV8TargetCodeGenInfo(CodeGenTypes &CGT)
54 : TargetCodeGenInfo(std::make_unique<SparcV8ABIInfo>(args&: CGT)) {}
55
56 llvm::Value *decodeReturnAddress(CodeGen::CodeGenFunction &CGF,
57 llvm::Value *Address) const override {
58 int Offset;
59 if (isAggregateTypeForABI(T: CGF.CurFnInfo->getReturnType()))
60 Offset = 12;
61 else
62 Offset = 8;
63 return CGF.Builder.CreateGEP(Ty: CGF.Int8Ty, Ptr: Address,
64 IdxList: llvm::ConstantInt::get(Ty: CGF.Int32Ty, V: Offset));
65 }
66
67 llvm::Value *encodeReturnAddress(CodeGen::CodeGenFunction &CGF,
68 llvm::Value *Address) const override {
69 int Offset;
70 if (isAggregateTypeForABI(T: CGF.CurFnInfo->getReturnType()))
71 Offset = -12;
72 else
73 Offset = -8;
74 return CGF.Builder.CreateGEP(Ty: CGF.Int8Ty, Ptr: Address,
75 IdxList: llvm::ConstantInt::get(Ty: CGF.Int32Ty, V: 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//
106namespace {
107class SparcV9ABIInfo : public ABIInfo {
108public:
109 SparcV9ABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {}
110
111private:
112 ABIArgInfo classifyType(QualType RetTy, unsigned SizeLimit) const;
113 void computeInfo(CGFunctionInfo &FI) const override;
114 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
115 AggValueSlot Slot) 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(Value: Size, Align: 64);
146 if (Aligned > Size && Aligned <= ToSize) {
147 Elems.push_back(Elt: llvm::IntegerType::get(C&: Context, NumBits: Aligned - Size));
148 Size = Aligned;
149 }
150
151 // Add whole 64-bit words.
152 while (Size + 64 <= ToSize) {
153 Elems.push_back(Elt: llvm::Type::getInt64Ty(C&: Context));
154 Size += 64;
155 }
156
157 // Final in-word padding.
158 if (Size < ToSize) {
159 Elems.push_back(Elt: llvm::IntegerType::get(C&: Context, NumBits: 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(ToSize: Offset);
173 Elems.push_back(Elt: 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(Ty: StrTy);
180 for (unsigned i = 0, e = StrTy->getNumElements(); i != e; ++i) {
181 llvm::Type *ElemTy = StrTy->getElementType(N: i);
182 uint64_t ElemOffset = Offset + Layout->getElementOffsetInBits(Idx: i);
183 switch (ElemTy->getTypeID()) {
184 case llvm::Type::StructTyID:
185 addStruct(Offset: ElemOffset, StrTy: cast<llvm::StructType>(Val: ElemTy));
186 break;
187 case llvm::Type::FloatTyID:
188 addFloat(Offset: ElemOffset, Ty: ElemTy, Bits: 32);
189 break;
190 case llvm::Type::DoubleTyID:
191 addFloat(Offset: ElemOffset, Ty: ElemTy, Bits: 64);
192 break;
193 case llvm::Type::FP128TyID:
194 addFloat(Offset: ElemOffset, Ty: ElemTy, Bits: 128);
195 break;
196 case llvm::Type::PointerTyID:
197 if (ElemOffset % 64 == 0) {
198 pad(ToSize: ElemOffset);
199 Elems.push_back(Elt: 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, Elements: Elems);
220 }
221 };
222};
223} // end anonymous namespace
224
225ABIArgInfo
226SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const {
227 if (Ty->isVoidType())
228 return ABIArgInfo::getIgnore();
229
230 uint64_t Size = getContext().getTypeSize(T: 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(
236 Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(),
237 /*ByVal=*/false);
238
239 // Treat an enum type as its underlying type.
240 if (const EnumType *EnumTy = Ty->getAs<EnumType>())
241 Ty = EnumTy->getDecl()->getIntegerType();
242
243 // Integer types smaller than a register are extended.
244 if (Size < 64 && Ty->isIntegerType())
245 return ABIArgInfo::getExtend(Ty);
246
247 if (const auto *EIT = Ty->getAs<BitIntType>())
248 if (EIT->getNumBits() < 64)
249 return ABIArgInfo::getExtend(Ty);
250
251 // Other non-aggregates go in registers.
252 if (!isAggregateTypeForABI(T: Ty))
253 return ABIArgInfo::getDirect();
254
255 // If a C++ object has either a non-trivial copy constructor or a non-trivial
256 // destructor, it is passed with an explicit indirect pointer / sret pointer.
257 if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(T: Ty, CXXABI&: getCXXABI()))
258 return getNaturalAlignIndirect(Ty, AddrSpace: getDataLayout().getAllocaAddrSpace(),
259 ByVal: RAA == CGCXXABI::RAA_DirectInMemory);
260
261 // This is a small aggregate type that should be passed in registers.
262 // Build a coercion type from the LLVM struct type.
263 llvm::StructType *StrTy = dyn_cast<llvm::StructType>(Val: CGT.ConvertType(T: Ty));
264 if (!StrTy)
265 return ABIArgInfo::getDirect();
266
267 CoerceBuilder CB(getVMContext(), getDataLayout());
268 CB.addStruct(Offset: 0, StrTy);
269 // All structs, even empty ones, should take up a register argument slot,
270 // so pin the minimum struct size to one bit.
271 CB.pad(ToSize: llvm::alignTo(
272 Value: std::max(a: CB.DL.getTypeSizeInBits(Ty: StrTy).getKnownMinValue(), b: uint64_t(1)),
273 Align: 64));
274
275 // Try to use the original type for coercion.
276 llvm::Type *CoerceTy = CB.isUsableType(Ty: StrTy) ? StrTy : CB.getType();
277
278 if (CB.InReg)
279 return ABIArgInfo::getDirectInReg(T: CoerceTy);
280 else
281 return ABIArgInfo::getDirect(T: CoerceTy);
282}
283
284RValue SparcV9ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
285 QualType Ty, AggValueSlot Slot) const {
286 ABIArgInfo AI = classifyType(Ty, SizeLimit: 16 * 8);
287 llvm::Type *ArgTy = CGT.ConvertType(T: Ty);
288 if (AI.canHaveCoerceToType() && !AI.getCoerceToType())
289 AI.setCoerceToType(ArgTy);
290
291 CharUnits SlotSize = CharUnits::fromQuantity(Quantity: 8);
292
293 CGBuilderTy &Builder = CGF.Builder;
294 Address Addr = Address(Builder.CreateLoad(Addr: VAListAddr, Name: "ap.cur"),
295 getVAListElementType(CGF), SlotSize);
296 llvm::Type *ArgPtrTy = CGF.UnqualPtrTy;
297
298 auto TypeInfo = getContext().getTypeInfoInChars(T: Ty);
299
300 Address ArgAddr = Address::invalid();
301 CharUnits Stride;
302 switch (AI.getKind()) {
303 case ABIArgInfo::Expand:
304 case ABIArgInfo::CoerceAndExpand:
305 case ABIArgInfo::InAlloca:
306 llvm_unreachable("Unsupported ABI kind for va_arg");
307
308 case ABIArgInfo::Extend: {
309 Stride = SlotSize;
310 CharUnits Offset = SlotSize - TypeInfo.Width;
311 ArgAddr = Builder.CreateConstInBoundsByteGEP(Addr, Offset, Name: "extend");
312 break;
313 }
314
315 case ABIArgInfo::Direct: {
316 auto AllocSize = getDataLayout().getTypeAllocSize(Ty: AI.getCoerceToType());
317 Stride = CharUnits::fromQuantity(Quantity: AllocSize).alignTo(Align: SlotSize);
318 ArgAddr = Addr;
319 break;
320 }
321
322 case ABIArgInfo::Indirect:
323 case ABIArgInfo::IndirectAliased:
324 Stride = SlotSize;
325 ArgAddr = Addr.withElementType(ElemTy: ArgPtrTy);
326 ArgAddr = Address(Builder.CreateLoad(Addr: ArgAddr, Name: "indirect.arg"), ArgTy,
327 TypeInfo.Align);
328 break;
329
330 case ABIArgInfo::Ignore:
331 return Slot.asRValue();
332 }
333
334 // Update VAList.
335 Address NextPtr = Builder.CreateConstInBoundsByteGEP(Addr, Offset: Stride, Name: "ap.next");
336 Builder.CreateStore(Val: NextPtr.emitRawPointer(CGF), Addr: VAListAddr);
337
338 return CGF.EmitLoadOfAnyValue(
339 V: CGF.MakeAddrLValue(Addr: ArgAddr.withElementType(ElemTy: ArgTy), T: Ty), Slot);
340}
341
342void SparcV9ABIInfo::computeInfo(CGFunctionInfo &FI) const {
343 FI.getReturnInfo() = classifyType(Ty: FI.getReturnType(), SizeLimit: 32 * 8);
344 for (auto &I : FI.arguments())
345 I.info = classifyType(Ty: I.type, SizeLimit: 16 * 8);
346}
347
348namespace {
349class SparcV9TargetCodeGenInfo : public TargetCodeGenInfo {
350public:
351 SparcV9TargetCodeGenInfo(CodeGenTypes &CGT)
352 : TargetCodeGenInfo(std::make_unique<SparcV9ABIInfo>(args&: CGT)) {}
353
354 int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override {
355 return 14;
356 }
357
358 bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
359 llvm::Value *Address) const override;
360
361 llvm::Value *decodeReturnAddress(CodeGen::CodeGenFunction &CGF,
362 llvm::Value *Address) const override {
363 return CGF.Builder.CreateGEP(Ty: CGF.Int8Ty, Ptr: Address,
364 IdxList: llvm::ConstantInt::get(Ty: CGF.Int32Ty, V: 8));
365 }
366
367 llvm::Value *encodeReturnAddress(CodeGen::CodeGenFunction &CGF,
368 llvm::Value *Address) const override {
369 return CGF.Builder.CreateGEP(Ty: CGF.Int8Ty, Ptr: Address,
370 IdxList: llvm::ConstantInt::get(Ty: CGF.Int32Ty, V: -8));
371 }
372};
373} // end anonymous namespace
374
375bool
376SparcV9TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
377 llvm::Value *Address) const {
378 // This is calculated from the LLVM and GCC tables and verified
379 // against gcc output. AFAIK all ABIs use the same encoding.
380
381 CodeGen::CGBuilderTy &Builder = CGF.Builder;
382
383 llvm::IntegerType *i8 = CGF.Int8Ty;
384 llvm::Value *Four8 = llvm::ConstantInt::get(Ty: i8, V: 4);
385 llvm::Value *Eight8 = llvm::ConstantInt::get(Ty: i8, V: 8);
386
387 // 0-31: the 8-byte general-purpose registers
388 AssignToArrayRange(Builder, Array: Address, Value: Eight8, FirstIndex: 0, LastIndex: 31);
389
390 // 32-63: f0-31, the 4-byte floating-point registers
391 AssignToArrayRange(Builder, Array: Address, Value: Four8, FirstIndex: 32, LastIndex: 63);
392
393 // Y = 64
394 // PSR = 65
395 // WIM = 66
396 // TBR = 67
397 // PC = 68
398 // NPC = 69
399 // FSR = 70
400 // CSR = 71
401 AssignToArrayRange(Builder, Array: Address, Value: Eight8, FirstIndex: 64, LastIndex: 71);
402
403 // 72-87: d0-15, the 8-byte floating-point registers
404 AssignToArrayRange(Builder, Array: Address, Value: Eight8, FirstIndex: 72, LastIndex: 87);
405
406 return false;
407}
408
409std::unique_ptr<TargetCodeGenInfo>
410CodeGen::createSparcV8TargetCodeGenInfo(CodeGenModule &CGM) {
411 return std::make_unique<SparcV8TargetCodeGenInfo>(args&: CGM.getTypes());
412}
413
414std::unique_ptr<TargetCodeGenInfo>
415CodeGen::createSparcV9TargetCodeGenInfo(CodeGenModule &CGM) {
416 return std::make_unique<SparcV9TargetCodeGenInfo>(args&: CGM.getTypes());
417}
418