LLVM 23.0.0git
Types.h
Go to the documentation of this file.
1//===- ABI/Types.h ----------------------------------------------*- C++ -*-===//
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/// \file
10/// This file defines the type system for the LLVMABI library, which mirrors
11/// ABI-relevant aspects of frontend types.
12///
13//===----------------------------------------------------------------------===//
14#ifndef LLVM_ABI_TYPES_H
15#define LLVM_ABI_TYPES_H
16
17#include "llvm/ADT/APFloat.h"
18#include "llvm/ADT/ArrayRef.h"
23
24namespace llvm {
25namespace abi {
26
38
39/// Represents the ABI-specific view of a type in LLVM.
40///
41/// This abstracts platform and language-specific ABI details from the
42/// frontend, providing a consistent interface for the ABI Library.
43class Type {
44private:
45 TypeSize getTypeStoreSize() const {
46 TypeSize StoreSizeInBits = getTypeStoreSizeInBits();
47 return {StoreSizeInBits.getKnownMinValue() / 8,
48 StoreSizeInBits.isScalable()};
49 }
50 TypeSize getTypeStoreSizeInBits() const {
51 TypeSize BaseSize = getSizeInBits();
52 uint64_t AlignedSizeInBits =
53 alignToPowerOf2(BaseSize.getKnownMinValue(), 8);
54 return {AlignedSizeInBits, BaseSize.isScalable()};
55 }
56
57protected:
61
64
65public:
66 TypeKind getKind() const { return Kind; }
67 TypeSize getSizeInBits() const { return SizeInBits; }
68 Align getAlignment() const { return ABIAlignment; }
69
71 return alignTo(getTypeStoreSize(), getAlignment().value());
72 }
73
74 bool isVoid() const { return Kind == TypeKind::Void; }
75 bool isInteger() const { return Kind == TypeKind::Integer; }
76 bool isFloat() const { return Kind == TypeKind::Float; }
77 bool isPointer() const { return Kind == TypeKind::Pointer; }
78 bool isArray() const { return Kind == TypeKind::Array; }
79 bool isVector() const { return Kind == TypeKind::Vector; }
80 bool isRecord() const { return Kind == TypeKind::Record; }
81 bool isMemberPointer() const { return Kind == TypeKind::MemberPointer; }
82 bool isComplex() const { return Kind == TypeKind::Complex; }
83 bool isZeroSize() const { return getSizeInBits().getFixedValue() == 0; }
84};
85
86class VoidType : public Type {
87public:
88 VoidType() : Type(TypeKind::Void, TypeSize::getFixed(0), Align(1)) {}
89
90 static bool classof(const Type *T) { return T->getKind() == TypeKind::Void; }
91};
92
93class ComplexType : public Type {
94public:
95 ComplexType(const Type *ElementType, uint64_t SizeInBits, Align Alignment)
96 : Type(TypeKind::Complex, TypeSize::getFixed(SizeInBits), Alignment),
97 ElementType(ElementType) {}
98
99 const Type *getElementType() const { return ElementType; }
100
101 static bool classof(const Type *T) {
102 return T->getKind() == TypeKind::Complex;
103 }
104
105private:
106 const Type *ElementType;
107};
108
109class IntegerType : public Type {
110private:
111 bool IsSigned;
112 bool IsBitInt;
113
114public:
115 IntegerType(uint64_t BitWidth, Align ABIAlign, bool IsSigned,
116 bool IsBitInt = false)
117 : Type(TypeKind::Integer, TypeSize::getFixed(BitWidth), ABIAlign),
118 IsSigned(IsSigned), IsBitInt(IsBitInt) {}
119
120 bool isSigned() const { return IsSigned; }
121 bool isBitInt() const { return IsBitInt; }
122 bool isBool() const {
123 return getSizeInBits().getFixedValue() == 1 && !IsBitInt;
124 }
125
126 static bool classof(const Type *T) {
127 return T->getKind() == TypeKind::Integer;
128 }
129};
130
131class FloatType : public Type {
132private:
133 const fltSemantics *Semantics;
134
135public:
136 FloatType(const fltSemantics &FloatSemantics, Align ABIAlign)
138 TypeSize::getFixed(APFloat::getSizeInBits(FloatSemantics)),
139 ABIAlign),
140 Semantics(&FloatSemantics) {}
141
142 const fltSemantics *getSemantics() const { return Semantics; }
143 static bool classof(const Type *T) { return T->getKind() == TypeKind::Float; }
144};
145
146class PointerLikeType : public Type {
147protected:
148 unsigned AddrSpace;
150 : Type(K, SizeInBits, ABIAlign), AddrSpace(AS) {}
151
152public:
153 unsigned getAddrSpace() const { return AddrSpace; }
154 bool isMemberPointer() const { return getKind() == TypeKind::MemberPointer; }
155
156 static bool classof(const Type *T) {
157 return T->getKind() == TypeKind::Pointer ||
158 T->getKind() == TypeKind::MemberPointer;
159 }
160};
161
163public:
164 PointerType(uint64_t Size, Align ABIAlign, unsigned AddressSpace = 0)
165 : PointerLikeType(TypeKind::Pointer, TypeSize::getFixed(Size), ABIAlign,
166 AddressSpace) {}
167
168 static bool classof(const Type *T) {
169 return T->getKind() == TypeKind::Pointer;
170 }
171};
172
174private:
175 bool IsFunctionPointer;
176
177public:
178 MemberPointerType(bool IsFunctionPointer, uint64_t SizeInBits, Align ABIAlign,
179 unsigned AddressSpace = 0)
181 ABIAlign, AddressSpace),
182 IsFunctionPointer(IsFunctionPointer) {}
183 bool isFunctionPointer() const { return IsFunctionPointer; }
184
185 static bool classof(const Type *T) {
186 return T->getKind() == TypeKind::MemberPointer;
187 }
188};
189
190class ArrayType : public Type {
191private:
192 const Type *ElementType;
193 uint64_t NumElements;
194 bool IsMatrix;
195
196public:
197 ArrayType(const Type *ElementType, uint64_t NumElements, uint64_t SizeInBits,
198 bool IsMatrixType = false)
199 : Type(TypeKind::Array, TypeSize::getFixed(SizeInBits),
200 ElementType->getAlignment()),
201 ElementType(ElementType), NumElements(NumElements),
202 IsMatrix(IsMatrixType) {}
203
204 const Type *getElementType() const { return ElementType; }
205 uint64_t getNumElements() const { return NumElements; }
206 bool isMatrixType() const { return IsMatrix; }
207
208 static bool classof(const Type *T) { return T->getKind() == TypeKind::Array; }
209};
210
211class VectorType : public Type {
212private:
213 const Type *ElementType;
214 ElementCount NumElements;
215
216public:
217 VectorType(const Type *ElementType, ElementCount NumElements, Align ABIAlign)
219 TypeSize(ElementType->getSizeInBits().getFixedValue() *
220 NumElements.getKnownMinValue(),
221 NumElements.isScalable()),
222 ABIAlign),
223 ElementType(ElementType), NumElements(NumElements) {}
224
225 const Type *getElementType() const { return ElementType; }
226 ElementCount getNumElements() const { return NumElements; }
227
228 static bool classof(const Type *T) {
229 return T->getKind() == TypeKind::Vector;
230 }
231};
232
233struct FieldInfo {
239
241 bool IsBitField = false, uint64_t BitFieldWidth = 0,
242 bool IsUnnamedBitField = false)
245 IsUnnamedBitfield(IsUnnamedBitField) {}
246
247 bool isEmpty() const;
248};
249
251
252enum RecordFlags : unsigned {
253 None = 0,
255 IsUnion = 1 << 1,
257 IsCXXRecord = 1 << 3,
261};
262
263class RecordType : public Type {
264private:
265 ArrayRef<FieldInfo> Fields;
266 ArrayRef<FieldInfo> BaseClasses;
267 ArrayRef<FieldInfo> VirtualBaseClasses;
268 StructPacking Packing;
269 RecordFlags Flags;
270
271public:
276 : Type(TypeKind::Record, Size, Align), Fields(StructFields),
277 BaseClasses(Bases), VirtualBaseClasses(VBases), Packing(Pack),
278 Flags(RecFlags) {}
279 uint32_t getNumFields() const { return Fields.size(); }
280 StructPacking getPacking() const { return Packing; }
281
282 bool isUnion() const {
283 return static_cast<unsigned>(Flags & RecordFlags::IsUnion) != 0;
284 }
285 bool isCXXRecord() const {
286 return static_cast<unsigned>(Flags & RecordFlags::IsCXXRecord) != 0;
287 }
288 bool isPolymorphic() const {
289 return static_cast<unsigned>(Flags & RecordFlags::IsPolymorphic) != 0;
290 }
291 bool canPassInRegisters() const {
292 return static_cast<unsigned>(Flags & RecordFlags::CanPassInRegisters) != 0;
293 }
295 return static_cast<unsigned>(Flags & RecordFlags::HasFlexibleArrayMember) !=
296 0;
297 }
298 uint32_t getNumBaseClasses() const { return BaseClasses.size(); }
300 return VirtualBaseClasses.size();
301 }
302 bool isTransparentUnion() const {
303 return static_cast<unsigned>(Flags & RecordFlags::IsTransparent) != 0;
304 }
305 ArrayRef<FieldInfo> getFields() const { return Fields; }
306 ArrayRef<FieldInfo> getBaseClasses() const { return BaseClasses; }
308 return VirtualBaseClasses;
309 }
310
311 bool isEmpty() const;
312
313 static bool classof(const Type *T) {
314 return T->getKind() == TypeKind::Record;
315 }
316};
317
318/// TypeBuilder manages the lifecycle of ABI types using bump pointer
319/// allocation. Types created by a TypeBuilder are valid for the lifetime of the
320/// allocator.
321///
322/// Example usage:
323/// \code
324/// BumpPtrAllocator Alloc;
325/// TypeBuilder Builder(Alloc);
326/// const auto *IntTy = Builder.getIntegerType(32, Align(4), true);
327/// \endcode
329private:
330 BumpPtrAllocator &Allocator;
331
332public:
333 explicit TypeBuilder(BumpPtrAllocator &Alloc) : Allocator(Alloc) {}
334
336 return new (Allocator.Allocate<VoidType>()) VoidType();
337 }
338
340 bool IsBitInt = false) {
341 return new (Allocator.Allocate<IntegerType>())
342 IntegerType(BitWidth, Align, Signed, IsBitInt);
343 }
344
345 const FloatType *getFloatType(const fltSemantics &Semantics, Align Align) {
346 return new (Allocator.Allocate<FloatType>()) FloatType(Semantics, Align);
347 }
348
350 unsigned Addrspace = 0) {
351 return new (Allocator.Allocate<PointerType>())
352 PointerType(Size, Align, Addrspace);
353 }
354
355 const ArrayType *getArrayType(const Type *ElementType, uint64_t NumElements,
356 uint64_t SizeInBits,
357 bool IsMatrixType = false) {
358 return new (Allocator.Allocate<ArrayType>())
359 ArrayType(ElementType, NumElements, SizeInBits, IsMatrixType);
360 }
361
362 const VectorType *getVectorType(const Type *ElementType,
363 ElementCount NumElements, Align Align) {
364 return new (Allocator.Allocate<VectorType>())
365 VectorType(ElementType, NumElements, Align);
366 }
367
369 Align Align,
371 ArrayRef<FieldInfo> BaseClasses = {},
372 ArrayRef<FieldInfo> VirtualBaseClasses = {},
373 RecordFlags RecFlags = RecordFlags::None) {
374 FieldInfo *FieldArray = Allocator.Allocate<FieldInfo>(Fields.size());
375 std::copy(Fields.begin(), Fields.end(), FieldArray);
376
377 FieldInfo *BaseArray = nullptr;
378 if (!BaseClasses.empty()) {
379 BaseArray = Allocator.Allocate<FieldInfo>(BaseClasses.size());
380 std::copy(BaseClasses.begin(), BaseClasses.end(), BaseArray);
381 }
382
383 FieldInfo *VBaseArray = nullptr;
384 if (!VirtualBaseClasses.empty()) {
385 VBaseArray = Allocator.Allocate<FieldInfo>(VirtualBaseClasses.size());
386 std::copy(VirtualBaseClasses.begin(), VirtualBaseClasses.end(),
387 VBaseArray);
388 }
389
390 ArrayRef<FieldInfo> FieldsRef(FieldArray, Fields.size());
391 ArrayRef<FieldInfo> BasesRef(BaseArray, BaseClasses.size());
392 ArrayRef<FieldInfo> VBasesRef(VBaseArray, VirtualBaseClasses.size());
393
394 return new (Allocator.Allocate<RecordType>())
395 RecordType(FieldsRef, BasesRef, VBasesRef, Size, Align, Pack, RecFlags);
396 }
397
399 Align Align,
401 RecordFlags RecFlags = RecordFlags::None) {
402 FieldInfo *FieldArray = Allocator.Allocate<FieldInfo>(Fields.size());
403
404 for (size_t I = 0, E = Fields.size(); I != E; ++I) {
405 const FieldInfo &Field = Fields[I];
406 new (&FieldArray[I])
407 FieldInfo(Field.FieldType, 0, Field.IsBitField, Field.BitFieldWidth,
408 Field.IsUnnamedBitfield);
409 }
410
411 ArrayRef<FieldInfo> FieldsRef(FieldArray, Fields.size());
412
413 return new (Allocator.Allocate<RecordType>())
415 Size, Align, Pack, RecFlags | RecordFlags::IsUnion);
416 }
417
418 const ComplexType *getComplexType(const Type *ElementType, Align Align) {
419 // Complex types have two elements (real and imaginary parts)
420 uint64_t ElementSizeInBits = ElementType->getSizeInBits().getFixedValue();
421 uint64_t ComplexSizeInBits = ElementSizeInBits * 2;
422
423 return new (Allocator.Allocate<ComplexType>())
424 ComplexType(ElementType, ComplexSizeInBits, Align);
425 }
426
427 const MemberPointerType *getMemberPointerType(bool IsFunctionPointer,
428 uint64_t SizeInBits,
429 Align Align) {
430 return new (Allocator.Allocate<MemberPointerType>())
431 MemberPointerType(IsFunctionPointer, SizeInBits, Align);
432 }
433};
434
435} // namespace abi
436} // namespace llvm
437
438#endif
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file defines the BumpPtrAllocator interface.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define I(x, y, z)
Definition MD5.cpp:57
#define T
OptimizedStructLayoutField Field
Basic Register Allocator
FunctionLoweringInfo::StatepointRelocationRecord RecordType
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
iterator end() const
Definition ArrayRef.h:131
size_t size() const
size - Get the array size.
Definition ArrayRef.h:142
iterator begin() const
Definition ArrayRef.h:130
bool empty() const
empty - Check if the array is empty.
Definition ArrayRef.h:137
const Type * getElementType() const
Definition Types.h:204
bool isMatrixType() const
Definition Types.h:206
static bool classof(const Type *T)
Definition Types.h:208
ArrayType(const Type *ElementType, uint64_t NumElements, uint64_t SizeInBits, bool IsMatrixType=false)
Definition Types.h:197
uint64_t getNumElements() const
Definition Types.h:205
ComplexType(const Type *ElementType, uint64_t SizeInBits, Align Alignment)
Definition Types.h:95
const Type * getElementType() const
Definition Types.h:99
static bool classof(const Type *T)
Definition Types.h:101
FloatType(const fltSemantics &FloatSemantics, Align ABIAlign)
Definition Types.h:136
const fltSemantics * getSemantics() const
Definition Types.h:142
static bool classof(const Type *T)
Definition Types.h:143
static bool classof(const Type *T)
Definition Types.h:126
bool isBitInt() const
Definition Types.h:121
IntegerType(uint64_t BitWidth, Align ABIAlign, bool IsSigned, bool IsBitInt=false)
Definition Types.h:115
bool isBool() const
Definition Types.h:122
bool isSigned() const
Definition Types.h:120
bool isFunctionPointer() const
Definition Types.h:183
static bool classof(const Type *T)
Definition Types.h:185
MemberPointerType(bool IsFunctionPointer, uint64_t SizeInBits, Align ABIAlign, unsigned AddressSpace=0)
Definition Types.h:178
PointerLikeType(TypeKind K, TypeSize SizeInBits, Align ABIAlign, unsigned AS)
Definition Types.h:149
static bool classof(const Type *T)
Definition Types.h:156
bool isMemberPointer() const
Definition Types.h:154
unsigned getAddrSpace() const
Definition Types.h:153
PointerType(uint64_t Size, Align ABIAlign, unsigned AddressSpace=0)
Definition Types.h:164
static bool classof(const Type *T)
Definition Types.h:168
bool isPolymorphic() const
Definition Types.h:288
bool isUnion() const
Definition Types.h:282
bool canPassInRegisters() const
Definition Types.h:291
ArrayRef< FieldInfo > getBaseClasses() const
Definition Types.h:306
uint32_t getNumBaseClasses() const
Definition Types.h:298
ArrayRef< FieldInfo > getFields() const
Definition Types.h:305
uint32_t getNumVirtualBaseClasses() const
Definition Types.h:299
bool hasFlexibleArrayMember() const
Definition Types.h:294
bool isCXXRecord() const
Definition Types.h:285
bool isTransparentUnion() const
Definition Types.h:302
static bool classof(const Type *T)
Definition Types.h:313
bool isEmpty() const
Definition Types.cpp:15
RecordType(ArrayRef< FieldInfo > StructFields, ArrayRef< FieldInfo > Bases, ArrayRef< FieldInfo > VBases, TypeSize Size, Align Align, StructPacking Pack=StructPacking::Default, RecordFlags RecFlags=RecordFlags::None)
Definition Types.h:272
uint32_t getNumFields() const
Definition Types.h:279
ArrayRef< FieldInfo > getVirtualBaseClasses() const
Definition Types.h:307
StructPacking getPacking() const
Definition Types.h:280
const ComplexType * getComplexType(const Type *ElementType, Align Align)
Definition Types.h:418
const FloatType * getFloatType(const fltSemantics &Semantics, Align Align)
Definition Types.h:345
const IntegerType * getIntegerType(uint64_t BitWidth, Align Align, bool Signed, bool IsBitInt=false)
Definition Types.h:339
const MemberPointerType * getMemberPointerType(bool IsFunctionPointer, uint64_t SizeInBits, Align Align)
Definition Types.h:427
const RecordType * getRecordType(ArrayRef< FieldInfo > Fields, TypeSize Size, Align Align, StructPacking Pack=StructPacking::Default, ArrayRef< FieldInfo > BaseClasses={}, ArrayRef< FieldInfo > VirtualBaseClasses={}, RecordFlags RecFlags=RecordFlags::None)
Definition Types.h:368
TypeBuilder(BumpPtrAllocator &Alloc)
Definition Types.h:333
const ArrayType * getArrayType(const Type *ElementType, uint64_t NumElements, uint64_t SizeInBits, bool IsMatrixType=false)
Definition Types.h:355
const PointerType * getPointerType(uint64_t Size, Align Align, unsigned Addrspace=0)
Definition Types.h:349
const VoidType * getVoidType()
Definition Types.h:335
const RecordType * getUnionType(ArrayRef< FieldInfo > Fields, TypeSize Size, Align Align, StructPacking Pack=StructPacking::Default, RecordFlags RecFlags=RecordFlags::None)
Definition Types.h:398
const VectorType * getVectorType(const Type *ElementType, ElementCount NumElements, Align Align)
Definition Types.h:362
Represents the ABI-specific view of a type in LLVM.
Definition Types.h:43
TypeSize getTypeAllocSize() const
Definition Types.h:70
Align ABIAlignment
Definition Types.h:60
bool isMemberPointer() const
Definition Types.h:81
bool isVoid() const
Definition Types.h:74
TypeSize SizeInBits
Definition Types.h:59
TypeSize getSizeInBits() const
Definition Types.h:67
bool isInteger() const
Definition Types.h:75
Type(TypeKind K, TypeSize SizeInBits, Align ABIAlign)
Definition Types.h:62
TypeKind Kind
Definition Types.h:58
bool isRecord() const
Definition Types.h:80
bool isArray() const
Definition Types.h:78
bool isZeroSize() const
Definition Types.h:83
bool isVector() const
Definition Types.h:79
bool isFloat() const
Definition Types.h:76
Align getAlignment() const
Definition Types.h:68
bool isComplex() const
Definition Types.h:82
TypeKind getKind() const
Definition Types.h:66
bool isPointer() const
Definition Types.h:77
ElementCount getNumElements() const
Definition Types.h:226
const Type * getElementType() const
Definition Types.h:225
static bool classof(const Type *T)
Definition Types.h:228
VectorType(const Type *ElementType, ElementCount NumElements, Align ABIAlign)
Definition Types.h:217
static bool classof(const Type *T)
Definition Types.h:90
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:200
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:168
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:165
RecordFlags
Definition Types.h:252
@ IsPolymorphic
Definition Types.h:258
@ IsCXXRecord
Definition Types.h:257
@ CanPassInRegisters
Definition Types.h:254
@ IsTransparent
Definition Types.h:256
@ LLVM_MARK_AS_BITMASK_ENUM
Definition Types.h:260
@ IsUnion
Definition Types.h:255
@ HasFlexibleArrayMember
Definition Types.h:259
StructPacking
Definition Types.h:250
This is an optimization pass for GlobalISel generic memory operations.
constexpr T alignToPowerOf2(U Value, V Align)
Will overflow only if result is not representable in T.
Definition MathExtras.h:493
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Definition Allocator.h:383
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
FieldInfo(const Type *FieldType, uint64_t OffsetInBits=0, bool IsBitField=false, uint64_t BitFieldWidth=0, bool IsUnnamedBitField=false)
Definition Types.h:240
const Type * FieldType
Definition Types.h:234
uint64_t BitFieldWidth
Definition Types.h:236
bool isEmpty() const
Definition Types.cpp:33
uint64_t OffsetInBits
Definition Types.h:235