|
| 1 | +#ifndef LLVM_ABI_ABITYPE_H |
| 2 | +#define LLVM_ABI_ABITYPE_H |
| 3 | + |
| 4 | +#include "llvm/ADT/ArrayRef.h" |
| 5 | +#include "llvm/ADT/StringRef.h" |
| 6 | +#include "llvm/Support/Allocator.h" |
| 7 | +#include <cstdint> |
| 8 | +#include <vector> |
| 9 | + |
| 10 | +namespace llvm { |
| 11 | +namespace abi { |
| 12 | + |
| 13 | +enum class ABITypeKind { |
| 14 | + Void, |
| 15 | + Bool, |
| 16 | + Char, |
| 17 | + SChar, |
| 18 | + UChar, |
| 19 | + Short, |
| 20 | + UShort, |
| 21 | + Int, |
| 22 | + UInt, |
| 23 | + Long, |
| 24 | + ULong, |
| 25 | + LongLong, |
| 26 | + ULongLong, |
| 27 | + Float, |
| 28 | + Double, |
| 29 | + LongDouble, |
| 30 | + Pointer, |
| 31 | + Array, |
| 32 | + Record, |
| 33 | + Union |
| 34 | +}; |
| 35 | + |
| 36 | +/// Base class for all types in the ABI type system |
| 37 | +class ABIType { |
| 38 | + const ABITypeKind Kind; |
| 39 | + unsigned Alignment; |
| 40 | + |
| 41 | +protected: |
| 42 | + ABIType(ABITypeKind K, unsigned Align) : Kind(K), Alignment(Align) {} |
| 43 | + |
| 44 | +public: |
| 45 | + ABITypeKind getKind() const { return Kind; } |
| 46 | + unsigned getAlignment() const { return Alignment; } |
| 47 | + |
| 48 | + // Support for LLVM RTTI |
| 49 | + static bool classof(const ABIType *) { return true; } |
| 50 | + |
| 51 | + virtual ~ABIType() = default; |
| 52 | +}; |
| 53 | + |
| 54 | +class VoidType : public ABIType { |
| 55 | +public: |
| 56 | + VoidType() : ABIType(ABITypeKind::Void, 0) {} |
| 57 | + |
| 58 | + static bool classof(const ABIType *T) { |
| 59 | + return T->getKind() == ABITypeKind::Void; |
| 60 | + } |
| 61 | +}; |
| 62 | + |
| 63 | +class ScalarType : public ABIType { |
| 64 | + uint64_t Size; |
| 65 | + |
| 66 | +public: |
| 67 | + ScalarType(ABITypeKind Kind, unsigned Align, uint64_t Size) |
| 68 | + : ABIType(Kind, Align), Size(Size) {} |
| 69 | + |
| 70 | + uint64_t getSize() const { return Size; } |
| 71 | + |
| 72 | + static bool classof(const ABIType *T) { |
| 73 | + return T->getKind() >= ABITypeKind::Bool && |
| 74 | + T->getKind() <= ABITypeKind::LongDouble; |
| 75 | + } |
| 76 | +}; |
| 77 | + |
| 78 | +class PointerType : public ABIType { |
| 79 | + const ABIType *PointeeType; |
| 80 | + uint64_t Size; |
| 81 | + |
| 82 | +public: |
| 83 | + PointerType(const ABIType *Pointee, unsigned Align, uint64_t Size) |
| 84 | + : ABIType(ABITypeKind::Pointer, Align), PointeeType(Pointee), Size(Size) { |
| 85 | + } |
| 86 | + |
| 87 | + const ABIType *getPointeeType() const { return PointeeType; } |
| 88 | + uint64_t getSize() const { return Size; } |
| 89 | + |
| 90 | + static bool classof(const ABIType *T) { |
| 91 | + return T->getKind() == ABITypeKind::Pointer; |
| 92 | + } |
| 93 | +}; |
| 94 | + |
| 95 | +class ArrayType : public ABIType { |
| 96 | + const ABIType *ElementType; |
| 97 | + uint64_t NumElements; |
| 98 | + uint64_t Size; |
| 99 | + |
| 100 | +public: |
| 101 | + ArrayType(const ABIType *ElemType, uint64_t Count, unsigned Align, |
| 102 | + uint64_t Size) |
| 103 | + : ABIType(ABITypeKind::Array, Align), ElementType(ElemType), |
| 104 | + NumElements(Count), Size(Size) {} |
| 105 | + |
| 106 | + const ABIType *getElementType() const { return ElementType; } |
| 107 | + uint64_t getNumElements() const { return NumElements; } |
| 108 | + uint64_t getSize() const { return Size; } |
| 109 | + |
| 110 | + static bool classof(const ABIType *T) { |
| 111 | + return T->getKind() == ABITypeKind::Array; |
| 112 | + } |
| 113 | +}; |
| 114 | + |
| 115 | +struct RecordField { |
| 116 | + StringRef Name; |
| 117 | + const ABIType *Type; |
| 118 | + uint64_t Offset; |
| 119 | + |
| 120 | + RecordField(StringRef Name, const ABIType *Type, uint64_t Offset) |
| 121 | + : Name(Name), Type(Type), Offset(Offset) {} |
| 122 | +}; |
| 123 | + |
| 124 | +class RecordType : public ABIType { |
| 125 | + std::vector<RecordField> Fields; |
| 126 | + uint64_t Size; |
| 127 | + bool Packed; |
| 128 | + |
| 129 | +public: |
| 130 | + RecordType(ArrayRef<RecordField> Fields, unsigned Align, uint64_t Size, |
| 131 | + bool Packed) |
| 132 | + : ABIType(ABITypeKind::Record, Align), |
| 133 | + Fields(Fields.begin(), Fields.end()), Size(Size), Packed(Packed) {} |
| 134 | + |
| 135 | + ArrayRef<RecordField> getFields() const { return Fields; } |
| 136 | + uint64_t getSize() const { return Size; } |
| 137 | + bool isPacked() const { return Packed; } |
| 138 | + |
| 139 | + static bool classof(const ABIType *T) { |
| 140 | + return T->getKind() == ABITypeKind::Record; |
| 141 | + } |
| 142 | +}; |
| 143 | + |
| 144 | +class UnionType : public ABIType { |
| 145 | + std::vector<RecordField> Fields; |
| 146 | + uint64_t Size; |
| 147 | + |
| 148 | +public: |
| 149 | + UnionType(ArrayRef<RecordField> Fields, unsigned Align, uint64_t Size) |
| 150 | + : ABIType(ABITypeKind::Union, Align), |
| 151 | + Fields(Fields.begin(), Fields.end()), Size(Size) {} |
| 152 | + |
| 153 | + ArrayRef<RecordField> getFields() const { return Fields; } |
| 154 | + uint64_t getSize() const { return Size; } |
| 155 | + |
| 156 | + static bool classof(const ABIType *T) { |
| 157 | + return T->getKind() == ABITypeKind::Union; |
| 158 | + } |
| 159 | +}; |
| 160 | + |
| 161 | +class ABITypeContext { |
| 162 | + BumpPtrAllocator Allocator; |
| 163 | + VoidType VoidTy; |
| 164 | + |
| 165 | + ScalarType BoolTy; |
| 166 | + ScalarType CharTy; |
| 167 | + ScalarType SCharTy; |
| 168 | + ScalarType UCharTy; |
| 169 | + ScalarType ShortTy; |
| 170 | + ScalarType UShortTy; |
| 171 | + ScalarType IntTy; |
| 172 | + ScalarType UIntTy; |
| 173 | + ScalarType LongTy; |
| 174 | + ScalarType ULongTy; |
| 175 | + ScalarType LongLongTy; |
| 176 | + ScalarType ULongLongTy; |
| 177 | + ScalarType FloatTy; |
| 178 | + ScalarType DoubleTy; |
| 179 | + ScalarType LongDoubleTy; |
| 180 | + |
| 181 | +public: |
| 182 | + ABITypeContext() |
| 183 | + : VoidTy(), |
| 184 | + // Initialize scalar types with target-independent defaults |
| 185 | + // Real implementations would initialize these based on target info |
| 186 | + BoolTy(ABITypeKind::Bool, 1, 1), CharTy(ABITypeKind::Char, 1, 1), |
| 187 | + SCharTy(ABITypeKind::SChar, 1, 1), UCharTy(ABITypeKind::UChar, 1, 1), |
| 188 | + ShortTy(ABITypeKind::Short, 2, 2), UShortTy(ABITypeKind::UShort, 2, 2), |
| 189 | + IntTy(ABITypeKind::Int, 4, 4), UIntTy(ABITypeKind::UInt, 4, 4), |
| 190 | + LongTy(ABITypeKind::Long, 8, 8), ULongTy(ABITypeKind::ULong, 8, 8), |
| 191 | + LongLongTy(ABITypeKind::LongLong, 8, 8), |
| 192 | + ULongLongTy(ABITypeKind::ULongLong, 8, 8), |
| 193 | + FloatTy(ABITypeKind::Float, 4, 4), DoubleTy(ABITypeKind::Double, 8, 8), |
| 194 | + LongDoubleTy(ABITypeKind::LongDouble, 16, 16) {} |
| 195 | + |
| 196 | + const VoidType *getVoidType() { return &VoidTy; } |
| 197 | + const ScalarType *getBoolType() { return &BoolTy; } |
| 198 | + const ScalarType *getCharType() { return &CharTy; } |
| 199 | + const ScalarType *getSCharType() { return &SCharTy; } |
| 200 | + const ScalarType *getUCharType() { return &UCharTy; } |
| 201 | + const ScalarType *getShortType() { return &ShortTy; } |
| 202 | + const ScalarType *getUShortType() { return &UShortTy; } |
| 203 | + const ScalarType *getIntType() { return &IntTy; } |
| 204 | + const ScalarType *getUIntType() { return &UIntTy; } |
| 205 | + const ScalarType *getLongType() { return &LongTy; } |
| 206 | + const ScalarType *getULongType() { return &ULongTy; } |
| 207 | + const ScalarType *getLongLongType() { return &LongLongTy; } |
| 208 | + const ScalarType *getULongLongType() { return &ULongLongTy; } |
| 209 | + const ScalarType *getFloatType() { return &FloatTy; } |
| 210 | + const ScalarType *getDoubleType() { return &DoubleTy; } |
| 211 | + const ScalarType *getLongDoubleType() { return &LongDoubleTy; } |
| 212 | + |
| 213 | + const PointerType *getPointerType(const ABIType *Pointee, unsigned Align, |
| 214 | + uint64_t Size) { |
| 215 | + return new (Allocator) PointerType(Pointee, Align, Size); |
| 216 | + } |
| 217 | + |
| 218 | + const ArrayType *getArrayType(const ABIType *ElementType, |
| 219 | + uint64_t NumElements, unsigned Align, |
| 220 | + uint64_t Size) { |
| 221 | + return new (Allocator) ArrayType(ElementType, NumElements, Align, Size); |
| 222 | + } |
| 223 | + const RecordType *getRecordType(ArrayRef<RecordField> Fields, unsigned Align, |
| 224 | + uint64_t Size, bool Packed = false) { |
| 225 | + // Take the allocator and make copy |
| 226 | + SmallVector<RecordField, 8> FieldsCopy; |
| 227 | + for (const auto &Field : Fields) { |
| 228 | + StringRef Name; |
| 229 | + if (!Field.Name.empty()) { |
| 230 | + char *NameBuf = Allocator.Allocate<char>(Field.Name.size() + 1); |
| 231 | + std::copy(Field.Name.begin(), Field.Name.end(), NameBuf); |
| 232 | + NameBuf[Field.Name.size()] = '\0'; |
| 233 | + Name = StringRef(NameBuf, Field.Name.size()); |
| 234 | + } |
| 235 | + FieldsCopy.emplace_back(Name, Field.Type, Field.Offset); |
| 236 | + } |
| 237 | + return new (Allocator) RecordType(FieldsCopy, Align, Size, Packed); |
| 238 | + } |
| 239 | + const UnionType *getUnionType(ArrayRef<RecordField> Fields, unsigned Align, |
| 240 | + uint64_t Size) { |
| 241 | + // Make a copy with the allocator |
| 242 | + SmallVector<RecordField, 8> FieldsCopy; |
| 243 | + for (const auto &Field : Fields) { |
| 244 | + StringRef Name; |
| 245 | + if (!Field.Name.empty()) { |
| 246 | + char *NameBuf = Allocator.Allocate<char>(Field.Name.size() + 1); |
| 247 | + std::copy(Field.Name.begin(), Field.Name.end(), NameBuf); |
| 248 | + NameBuf[Field.Name.size()] = '\0'; |
| 249 | + Name = StringRef(NameBuf, Field.Name.size()); |
| 250 | + } |
| 251 | + FieldsCopy.emplace_back(Name, Field.Type, Field.Offset); |
| 252 | + } |
| 253 | + return new (Allocator) UnionType(FieldsCopy, Align, Size); |
| 254 | + } |
| 255 | +}; |
| 256 | +} // namespace abi |
| 257 | +} // namespace llvm |
| 258 | + |
| 259 | +#endif // LLVM_ABI_ABITYPE_H |
0 commit comments