clang 22.0.0git
Sparc.cpp
Go to the documentation of this file.
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, getDataLayout().getAllocaAddrSpace(),
48 /*ByVal=*/false);
49
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, getDataLayout().getAllocaAddrSpace());
57
59}
60
61void SparcV8ABIInfo::computeInfo(CGFunctionInfo &FI) const {
63 for (auto &Arg : FI.arguments())
64 Arg.info = classifyArgumentType(Arg.type);
65}
66
67namespace {
68class SparcV8TargetCodeGenInfo : public TargetCodeGenInfo {
69public:
70 SparcV8TargetCodeGenInfo(CodeGenTypes &CGT)
71 : TargetCodeGenInfo(std::make_unique<SparcV8ABIInfo>(CGT)) {}
72
73 llvm::Value *decodeReturnAddress(CodeGen::CodeGenFunction &CGF,
74 llvm::Value *Address) const override {
75 int Offset;
77 Offset = 12;
78 else
79 Offset = 8;
80 return CGF.Builder.CreateGEP(CGF.Int8Ty, Address,
81 llvm::ConstantInt::get(CGF.Int32Ty, Offset));
82 }
83
84 llvm::Value *encodeReturnAddress(CodeGen::CodeGenFunction &CGF,
85 llvm::Value *Address) const override {
86 int Offset;
88 Offset = -12;
89 else
90 Offset = -8;
91 return CGF.Builder.CreateGEP(CGF.Int8Ty, Address,
92 llvm::ConstantInt::get(CGF.Int32Ty, 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(Size, 64);
164 if (Aligned > Size && Aligned <= ToSize) {
165 Elems.push_back(llvm::IntegerType::get(Context, Aligned - Size));
166 Size = Aligned;
167 }
168
169 // Add whole 64-bit words.
170 while (Size + 64 <= ToSize) {
171 Elems.push_back(llvm::Type::getInt64Ty(Context));
172 Size += 64;
173 }
174
175 // Final in-word padding.
176 if (Size < ToSize) {
177 Elems.push_back(llvm::IntegerType::get(Context, 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(Offset);
191 Elems.push_back(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(StrTy);
198 for (unsigned i = 0, e = StrTy->getNumElements(); i != e; ++i) {
199 llvm::Type *ElemTy = StrTy->getElementType(i);
200 uint64_t ElemOffset = Offset + Layout->getElementOffsetInBits(i);
201 switch (ElemTy->getTypeID()) {
202 case llvm::Type::StructTyID:
203 addStruct(ElemOffset, cast<llvm::StructType>(ElemTy));
204 break;
205 case llvm::Type::FloatTyID:
206 addFloat(ElemOffset, ElemTy, 32);
207 break;
208 case llvm::Type::DoubleTyID:
209 addFloat(ElemOffset, ElemTy, 64);
210 break;
211 case llvm::Type::FP128TyID:
212 addFloat(ElemOffset, ElemTy, 128);
213 break;
214 case llvm::Type::PointerTyID:
215 if (ElemOffset % 64 == 0) {
216 pad(ElemOffset);
217 Elems.push_back(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, 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(Ty);
252 unsigned Alignment = Context.getTypeAlign(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(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(Ty, getCXXABI())) {
289 RegOffset += 1;
290 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
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>(CGT.ConvertType(Ty));
297 if (!StrTy) {
298 RegOffset += Size / 64;
299 return ABIArgInfo::getDirect();
300 }
301
302 CoerceBuilder CB(VMContext, getDataLayout());
303 CB.addStruct(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(llvm::alignTo(
307 std::max(CB.DL.getTypeSizeInBits(StrTy).getKnownMinValue(), uint64_t(1)),
308 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(VMContext) : nullptr;
317 RegOffset += NeedPadding ? 1 : 0;
318
319 // Try to use the original type for coercion.
320 llvm::Type *CoerceTy = CB.isUsableType(StrTy) ? StrTy : CB.getType();
321
322 ABIArgInfo AAI = ABIArgInfo::getDirect(CoerceTy, 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(8);
330 auto TInfo = getContext().getTypeInfoInChars(Ty);
331
332 // Zero-sized types have a width of one byte for parameter passing purposes.
333 TInfo.Width = std::max(TInfo.Width, CharUnits::fromQuantity(1));
334
335 // Arguments bigger than 2*SlotSize bytes are passed indirectly.
336 return emitVoidPtrVAArg(CGF, VAListAddr, Ty,
337 /*IsIndirect=*/TInfo.Width > 2 * SlotSize, TInfo,
338 SlotSize,
339 /*AllowHigherAlign=*/true, Slot);
340}
341
342void SparcV9ABIInfo::computeInfo(CGFunctionInfo &FI) const {
343 unsigned RetOffset = 0;
344 ABIArgInfo RetType = classifyType(FI.getReturnType(), 32 * 8, 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(I.type, 16 * 8, ArgOffset);
351}
352
353namespace {
354class SparcV9TargetCodeGenInfo : public TargetCodeGenInfo {
355public:
356 SparcV9TargetCodeGenInfo(CodeGenTypes &CGT)
357 : TargetCodeGenInfo(std::make_unique<SparcV9ABIInfo>(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(CGF.Int8Ty, Address,
369 llvm::ConstantInt::get(CGF.Int32Ty, 8));
370 }
371
372 llvm::Value *encodeReturnAddress(CodeGen::CodeGenFunction &CGF,
373 llvm::Value *Address) const override {
374 return CGF.Builder.CreateGEP(CGF.Int8Ty, Address,
375 llvm::ConstantInt::get(CGF.Int32Ty, -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(i8, 4);
390 llvm::Value *Eight8 = llvm::ConstantInt::get(i8, 8);
391
392 // 0-31: the 8-byte general-purpose registers
393 AssignToArrayRange(Builder, Address, Eight8, 0, 31);
394
395 // 32-63: f0-31, the 4-byte floating-point registers
396 AssignToArrayRange(Builder, Address, Four8, 32, 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, Address, Eight8, 64, 71);
407
408 // 72-87: d0-15, the 8-byte floating-point registers
409 AssignToArrayRange(Builder, Address, Eight8, 72, 87);
410
411 return false;
412}
413
414std::unique_ptr<TargetCodeGenInfo>
416 return std::make_unique<SparcV8TargetCodeGenInfo>(CGM.getTypes());
417}
418
419std::unique_ptr<TargetCodeGenInfo>
421 return std::make_unique<SparcV9TargetCodeGenInfo>(CGM.getTypes());
422}
TokenType getType() const
Returns the token's type, e.g.
static ABIArgInfo classifyType(CodeGenModule &CGM, CanQualType type, bool forReturn)
__device__ __2f16 float c
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
unsigned getTypeAlign(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in bits.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:63
ABIArgInfo - Helper class to encapsulate information about how a specific C type should be passed to ...
static ABIArgInfo getIgnore()
static ABIArgInfo getDirect(llvm::Type *T=nullptr, unsigned Offset=0, llvm::Type *Padding=nullptr, bool CanBeFlattened=true, unsigned Align=0)
static ABIArgInfo getExtend(QualType Ty, llvm::Type *T=nullptr)
static ABIArgInfo getDirectInReg(llvm::Type *T=nullptr)
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
Definition CGBuilder.h:296
RecordArgABI
Specify how one should pass an argument of a record type.
Definition CGCXXABI.h:150
@ RAA_DirectInMemory
Pass it on the stack using its defined layout.
Definition CGCXXABI.h:158
CanQualType getReturnType() const
MutableArrayRef< ArgInfo > arguments()
const CGFunctionInfo * CurFnInfo
This class organizes the cross-function state that is used while generating LLVM code.
DefaultABIInfo - The default implementation for ABI specific details.
Definition ABIInfoImpl.h:21
ABIArgInfo classifyArgumentType(QualType RetTy) const
ABIArgInfo classifyReturnType(QualType RetTy) const
QualType getElementType() const
Definition TypeBase.h:3285
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isVoidType() const
Definition TypeBase.h:8871
EnumDecl * getAsEnumDecl() const
Retrieves the EnumDecl this type refers to.
Definition Type.h:53
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9091
ABIArgInfo classifyArgumentType(CodeGenModule &CGM, CanQualType type)
Classify the rules for how to pass a particular type.
CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT, CGCXXABI &CXXABI)
bool classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI, const ABIInfo &Info)
RValue emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType ValueTy, bool IsIndirect, TypeInfoChars ValueInfo, CharUnits SlotSizeAndAlign, bool AllowHigherAlign, AggValueSlot Slot, bool ForceRightAdjust=false)
Emit va_arg for a platform using the common void* representation, where arguments are simply emitted ...
bool isAggregateTypeForABI(QualType T)
void AssignToArrayRange(CodeGen::CGBuilderTy &Builder, llvm::Value *Array, llvm::Value *Value, unsigned FirstIndex, unsigned LastIndex)
std::unique_ptr< TargetCodeGenInfo > createSparcV8TargetCodeGenInfo(CodeGenModule &CGM)
Definition Sparc.cpp:415
std::unique_ptr< TargetCodeGenInfo > createSparcV9TargetCodeGenInfo(CodeGenModule &CGM)
Definition Sparc.cpp:420
The JSON file list parser is used to communicate input to InstallAPI.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
U cast(CodeGen::Address addr)
Definition Address.h:327
unsigned long uint64_t
#define false
Definition stdbool.h:26
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64