clang 19.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
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:
28 void computeInfo(CGFunctionInfo &FI) const override;
29};
30} // end anonymous namespace
31
32
34SparcV8ABIInfo::classifyReturnType(QualType Ty) const {
35 if (Ty->isAnyComplexType()) {
36 return ABIArgInfo::getDirect();
37 }
38 else {
40 }
41}
42
43void SparcV8ABIInfo::computeInfo(CGFunctionInfo &FI) const {
44
46 for (auto &Arg : FI.arguments())
47 Arg.info = classifyArgumentType(Arg.type);
48}
49
50namespace {
51class SparcV8TargetCodeGenInfo : public TargetCodeGenInfo {
52public:
53 SparcV8TargetCodeGenInfo(CodeGenTypes &CGT)
54 : TargetCodeGenInfo(std::make_unique<SparcV8ABIInfo>(CGT)) {}
55
57 llvm::Value *Address) const override {
58 int Offset;
60 Offset = 12;
61 else
62 Offset = 8;
63 return CGF.Builder.CreateGEP(CGF.Int8Ty, Address,
64 llvm::ConstantInt::get(CGF.Int32Ty, Offset));
65 }
66
68 llvm::Value *Address) const override {
69 int Offset;
71 Offset = -12;
72 else
73 Offset = -8;
74 return CGF.Builder.CreateGEP(CGF.Int8Ty, Address,
75 llvm::ConstantInt::get(CGF.Int32Ty, 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 Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
115 QualType Ty) 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;
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(Size, 64);
146 if (Aligned > Size && Aligned <= ToSize) {
147 Elems.push_back(llvm::IntegerType::get(Context, Aligned - Size));
148 Size = Aligned;
149 }
150
151 // Add whole 64-bit words.
152 while (Size + 64 <= ToSize) {
153 Elems.push_back(llvm::Type::getInt64Ty(Context));
154 Size += 64;
155 }
156
157 // Final in-word padding.
158 if (Size < ToSize) {
159 Elems.push_back(llvm::IntegerType::get(Context, 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(Offset);
173 Elems.push_back(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(StrTy);
180 for (unsigned i = 0, e = StrTy->getNumElements(); i != e; ++i) {
181 llvm::Type *ElemTy = StrTy->getElementType(i);
182 uint64_t ElemOffset = Offset + Layout->getElementOffsetInBits(i);
183 switch (ElemTy->getTypeID()) {
184 case llvm::Type::StructTyID:
185 addStruct(ElemOffset, cast<llvm::StructType>(ElemTy));
186 break;
187 case llvm::Type::FloatTyID:
188 addFloat(ElemOffset, ElemTy, 32);
189 break;
190 case llvm::Type::DoubleTyID:
191 addFloat(ElemOffset, ElemTy, 64);
192 break;
193 case llvm::Type::FP128TyID:
194 addFloat(ElemOffset, ElemTy, 128);
195 break;
196 case llvm::Type::PointerTyID:
197 if (ElemOffset % 64 == 0) {
198 pad(ElemOffset);
199 Elems.push_back(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, Elems);
220 }
221 };
222};
223} // end anonymous namespace
224
226SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const {
227 if (Ty->isVoidType())
228 return ABIArgInfo::getIgnore();
229
230 uint64_t Size = getContext().getTypeSize(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(Ty, /*ByVal=*/false);
236
237 // Treat an enum type as its underlying type.
238 if (const EnumType *EnumTy = Ty->getAs<EnumType>())
239 Ty = EnumTy->getDecl()->getIntegerType();
240
241 // Integer types smaller than a register are extended.
242 if (Size < 64 && Ty->isIntegerType())
243 return ABIArgInfo::getExtend(Ty);
244
245 if (const auto *EIT = Ty->getAs<BitIntType>())
246 if (EIT->getNumBits() < 64)
247 return ABIArgInfo::getExtend(Ty);
248
249 // Other non-aggregates go in registers.
250 if (!isAggregateTypeForABI(Ty))
251 return ABIArgInfo::getDirect();
252
253 // If a C++ object has either a non-trivial copy constructor or a non-trivial
254 // destructor, it is passed with an explicit indirect pointer / sret pointer.
255 if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
256 return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
257
258 // This is a small aggregate type that should be passed in registers.
259 // Build a coercion type from the LLVM struct type.
260 llvm::StructType *StrTy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty));
261 if (!StrTy)
262 return ABIArgInfo::getDirect();
263
264 CoerceBuilder CB(getVMContext(), getDataLayout());
265 CB.addStruct(0, StrTy);
266 CB.pad(llvm::alignTo(CB.DL.getTypeSizeInBits(StrTy), 64));
267
268 // Try to use the original type for coercion.
269 llvm::Type *CoerceTy = CB.isUsableType(StrTy) ? StrTy : CB.getType();
270
271 if (CB.InReg)
272 return ABIArgInfo::getDirectInReg(CoerceTy);
273 else
274 return ABIArgInfo::getDirect(CoerceTy);
275}
276
277Address SparcV9ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
278 QualType Ty) const {
279 ABIArgInfo AI = classifyType(Ty, 16 * 8);
280 llvm::Type *ArgTy = CGT.ConvertType(Ty);
281 if (AI.canHaveCoerceToType() && !AI.getCoerceToType())
282 AI.setCoerceToType(ArgTy);
283
285
286 CGBuilderTy &Builder = CGF.Builder;
287 Address Addr = Address(Builder.CreateLoad(VAListAddr, "ap.cur"),
288 getVAListElementType(CGF), SlotSize);
289 llvm::Type *ArgPtrTy = CGF.UnqualPtrTy;
290
291 auto TypeInfo = getContext().getTypeInfoInChars(Ty);
292
293 Address ArgAddr = Address::invalid();
294 CharUnits Stride;
295 switch (AI.getKind()) {
299 llvm_unreachable("Unsupported ABI kind for va_arg");
300
301 case ABIArgInfo::Extend: {
302 Stride = SlotSize;
303 CharUnits Offset = SlotSize - TypeInfo.Width;
304 ArgAddr = Builder.CreateConstInBoundsByteGEP(Addr, Offset, "extend");
305 break;
306 }
307
308 case ABIArgInfo::Direct: {
309 auto AllocSize = getDataLayout().getTypeAllocSize(AI.getCoerceToType());
310 Stride = CharUnits::fromQuantity(AllocSize).alignTo(SlotSize);
311 ArgAddr = Addr;
312 break;
313 }
314
317 Stride = SlotSize;
318 ArgAddr = Addr.withElementType(ArgPtrTy);
319 ArgAddr = Address(Builder.CreateLoad(ArgAddr, "indirect.arg"), ArgTy,
321 break;
322
324 return Address(llvm::UndefValue::get(ArgPtrTy), ArgTy, TypeInfo.Align);
325 }
326
327 // Update VAList.
328 Address NextPtr = Builder.CreateConstInBoundsByteGEP(Addr, Stride, "ap.next");
329 Builder.CreateStore(NextPtr.emitRawPointer(CGF), VAListAddr);
330
331 return ArgAddr.withElementType(ArgTy);
332}
333
334void SparcV9ABIInfo::computeInfo(CGFunctionInfo &FI) const {
335 FI.getReturnInfo() = classifyType(FI.getReturnType(), 32 * 8);
336 for (auto &I : FI.arguments())
337 I.info = classifyType(I.type, 16 * 8);
338}
339
340namespace {
341class SparcV9TargetCodeGenInfo : public TargetCodeGenInfo {
342public:
343 SparcV9TargetCodeGenInfo(CodeGenTypes &CGT)
344 : TargetCodeGenInfo(std::make_unique<SparcV9ABIInfo>(CGT)) {}
345
346 int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override {
347 return 14;
348 }
349
351 llvm::Value *Address) const override;
352
354 llvm::Value *Address) const override {
355 return CGF.Builder.CreateGEP(CGF.Int8Ty, Address,
356 llvm::ConstantInt::get(CGF.Int32Ty, 8));
357 }
358
360 llvm::Value *Address) const override {
361 return CGF.Builder.CreateGEP(CGF.Int8Ty, Address,
362 llvm::ConstantInt::get(CGF.Int32Ty, -8));
363 }
364};
365} // end anonymous namespace
366
367bool
368SparcV9TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
369 llvm::Value *Address) const {
370 // This is calculated from the LLVM and GCC tables and verified
371 // against gcc output. AFAIK all ABIs use the same encoding.
372
373 CodeGen::CGBuilderTy &Builder = CGF.Builder;
374
375 llvm::IntegerType *i8 = CGF.Int8Ty;
376 llvm::Value *Four8 = llvm::ConstantInt::get(i8, 4);
377 llvm::Value *Eight8 = llvm::ConstantInt::get(i8, 8);
378
379 // 0-31: the 8-byte general-purpose registers
380 AssignToArrayRange(Builder, Address, Eight8, 0, 31);
381
382 // 32-63: f0-31, the 4-byte floating-point registers
383 AssignToArrayRange(Builder, Address, Four8, 32, 63);
384
385 // Y = 64
386 // PSR = 65
387 // WIM = 66
388 // TBR = 67
389 // PC = 68
390 // NPC = 69
391 // FSR = 70
392 // CSR = 71
393 AssignToArrayRange(Builder, Address, Eight8, 64, 71);
394
395 // 72-87: d0-15, the 8-byte floating-point registers
396 AssignToArrayRange(Builder, Address, Eight8, 72, 87);
397
398 return false;
399}
400
401std::unique_ptr<TargetCodeGenInfo>
403 return std::make_unique<SparcV8TargetCodeGenInfo>(CGM.getTypes());
404}
405
406std::unique_ptr<TargetCodeGenInfo>
408 return std::make_unique<SparcV9TargetCodeGenInfo>(CGM.getTypes());
409}
static ABIArgInfo classifyType(CodeGenModule &CGM, CanQualType type, bool forReturn)
__device__ __2f16 float c
A fixed int type of a specified bitwidth.
Definition: Type.h:7242
CharUnits - This is an opaque type for sizes expressed in character units.
Definition: CharUnits.h:38
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition: CharUnits.h:63
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
Definition: CharUnits.h:201
ABIArgInfo - Helper class to encapsulate information about how a specific C type should be passed to ...
static ABIArgInfo getIgnore()
void setCoerceToType(llvm::Type *T)
static ABIArgInfo getDirect(llvm::Type *T=nullptr, unsigned Offset=0, llvm::Type *Padding=nullptr, bool CanBeFlattened=true, unsigned Align=0)
@ Extend
Extend - Valid only for integer argument types.
@ Ignore
Ignore - Ignore the argument (treat as void).
@ IndirectAliased
IndirectAliased - Similar to Indirect, but the pointer may be to an object that is otherwise referenc...
@ Expand
Expand - Only valid for aggregate argument types.
@ InAlloca
InAlloca - Pass the argument directly using the LLVM inalloca attribute.
@ Indirect
Indirect - Pass the argument indirectly via a hidden pointer with the specified alignment (0 indicate...
@ CoerceAndExpand
CoerceAndExpand - Only valid for aggregate argument types.
@ Direct
Direct - Pass the argument directly using the normal converted LLVM type, or by coercing to another s...
static ABIArgInfo getExtend(QualType Ty, llvm::Type *T=nullptr)
llvm::Type * getCoerceToType() const
static ABIArgInfo getDirectInReg(llvm::Type *T=nullptr)
ABIInfo - Target specific hooks for defining how a type should be passed or returned from functions.
Definition: ABIInfo.h:45
virtual CodeGen::Address EmitVAArg(CodeGen::CodeGenFunction &CGF, CodeGen::Address VAListAddr, QualType Ty) const =0
EmitVAArg - Emit the target dependent code to load a value of.
virtual void computeInfo(CodeGen::CGFunctionInfo &FI) const =0
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
Definition: Address.h:111
static Address invalid()
Definition: Address.h:153
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
Definition: Address.h:220
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
Definition: Address.h:241
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
Definition: CGBuilder.h:292
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
CGFunctionInfo - Class to encapsulate the information about a function definition.
CanQualType getReturnType() const
MutableArrayRef< ArgInfo > arguments()
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
const CGFunctionInfo * CurFnInfo
This class organizes the cross-function state that is used while generating LLVM code.
This class organizes the cross-module state that is used while lowering AST types to LLVM types.
Definition: CodeGenTypes.h:54
DefaultABIInfo - The default implementation for ABI specific details.
Definition: ABIInfoImpl.h:21
ABIArgInfo classifyReturnType(QualType RetTy) const
Definition: ABIInfoImpl.cpp:45
void computeInfo(CGFunctionInfo &FI) const override
Definition: ABIInfoImpl.cpp:67
TargetCodeGenInfo - This class organizes various target-specific codegeneration issues,...
Definition: TargetInfo.h:46
virtual llvm::Value * encodeReturnAddress(CodeGen::CodeGenFunction &CGF, llvm::Value *Address) const
Performs the code-generation required to convert the address of an instruction into a return address ...
Definition: TargetInfo.h:150
virtual llvm::Value * decodeReturnAddress(CodeGen::CodeGenFunction &CGF, llvm::Value *Address) const
Performs the code-generation required to convert a return address as stored by the system into the ac...
Definition: TargetInfo.h:140
virtual bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, llvm::Value *Address) const
Initializes the given DWARF EH register-size table, a char*.
Definition: TargetInfo.h:130
virtual int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const
Determines the DWARF register number for the stack pointer, for exception-handling purposes.
Definition: TargetInfo.h:122
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.
Definition: Type.h:5575
A (possibly-)qualified type.
Definition: Type.h:940
bool isVoidType() const
Definition: Type.h:7905
bool isAnyComplexType() const
Definition: Type.h:7714
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8123
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)
bool isAggregateTypeForABI(QualType T)
llvm::Type * getVAListElementType(CodeGenFunction &CGF)
void AssignToArrayRange(CodeGen::CGBuilderTy &Builder, llvm::Value *Array, llvm::Value *Value, unsigned FirstIndex, unsigned LastIndex)
Definition: ABIInfoImpl.cpp:89
std::unique_ptr< TargetCodeGenInfo > createSparcV8TargetCodeGenInfo(CodeGenModule &CGM)
Definition: Sparc.cpp:402
std::unique_ptr< TargetCodeGenInfo > createSparcV9TargetCodeGenInfo(CodeGenModule &CGM)
Definition: Sparc.cpp:407
The JSON file list parser is used to communicate input to InstallAPI.
unsigned long uint64_t
Definition: Format.h:5394
#define false
Definition: stdbool.h:26
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
uint64_t Width
Definition: ASTContext.h:153
unsigned Align
Definition: ASTContext.h:154