1 | //===- Type.cpp - Implement the Type class --------------------------------===// |
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 | // This file implements the Type class for the IR library. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "llvm/IR/Type.h" |
14 | #include "LLVMContextImpl.h" |
15 | #include "llvm/ADT/APInt.h" |
16 | #include "llvm/ADT/SmallString.h" |
17 | #include "llvm/ADT/StringMap.h" |
18 | #include "llvm/ADT/StringRef.h" |
19 | #include "llvm/IR/Constant.h" |
20 | #include "llvm/IR/Constants.h" |
21 | #include "llvm/IR/DerivedTypes.h" |
22 | #include "llvm/IR/LLVMContext.h" |
23 | #include "llvm/IR/Value.h" |
24 | #include "llvm/Support/Casting.h" |
25 | #include "llvm/Support/TypeSize.h" |
26 | #include "llvm/Support/raw_ostream.h" |
27 | #include <cassert> |
28 | #include <utility> |
29 | |
30 | using namespace llvm; |
31 | |
32 | //===----------------------------------------------------------------------===// |
33 | // Type Class Implementation |
34 | //===----------------------------------------------------------------------===// |
35 | |
36 | Type *Type::getPrimitiveType(LLVMContext &C, TypeID IDNumber) { |
37 | switch (IDNumber) { |
38 | case VoidTyID : return getVoidTy(C); |
39 | case HalfTyID : return getHalfTy(C); |
40 | case BFloatTyID : return getBFloatTy(C); |
41 | case FloatTyID : return getFloatTy(C); |
42 | case DoubleTyID : return getDoubleTy(C); |
43 | case X86_FP80TyID : return getX86_FP80Ty(C); |
44 | case FP128TyID : return getFP128Ty(C); |
45 | case PPC_FP128TyID : return getPPC_FP128Ty(C); |
46 | case LabelTyID : return getLabelTy(C); |
47 | case MetadataTyID : return getMetadataTy(C); |
48 | case X86_MMXTyID : return getX86_MMXTy(C); |
49 | case X86_AMXTyID : return getX86_AMXTy(C); |
50 | case TokenTyID : return getTokenTy(C); |
51 | default: |
52 | return nullptr; |
53 | } |
54 | } |
55 | |
56 | bool Type::isIntegerTy(unsigned Bitwidth) const { |
57 | return isIntegerTy() && cast<IntegerType>(Val: this)->getBitWidth() == Bitwidth; |
58 | } |
59 | |
60 | bool Type::isScalableTy() const { |
61 | if (const auto *ATy = dyn_cast<ArrayType>(Val: this)) |
62 | return ATy->getElementType()->isScalableTy(); |
63 | if (const auto *STy = dyn_cast<StructType>(Val: this)) { |
64 | SmallPtrSet<Type *, 4> Visited; |
65 | return STy->containsScalableVectorType(Visited: &Visited); |
66 | } |
67 | return getTypeID() == ScalableVectorTyID || isScalableTargetExtTy(); |
68 | } |
69 | |
70 | const fltSemantics &Type::getFltSemantics() const { |
71 | switch (getTypeID()) { |
72 | case HalfTyID: return APFloat::IEEEhalf(); |
73 | case BFloatTyID: return APFloat::BFloat(); |
74 | case FloatTyID: return APFloat::IEEEsingle(); |
75 | case DoubleTyID: return APFloat::IEEEdouble(); |
76 | case X86_FP80TyID: return APFloat::x87DoubleExtended(); |
77 | case FP128TyID: return APFloat::IEEEquad(); |
78 | case PPC_FP128TyID: return APFloat::PPCDoubleDouble(); |
79 | default: llvm_unreachable("Invalid floating type" ); |
80 | } |
81 | } |
82 | |
83 | bool Type::isIEEE() const { |
84 | return APFloat::getZero(Sem: getFltSemantics()).isIEEE(); |
85 | } |
86 | |
87 | bool Type::isScalableTargetExtTy() const { |
88 | if (auto *TT = dyn_cast<TargetExtType>(Val: this)) |
89 | return isa<ScalableVectorType>(Val: TT->getLayoutType()); |
90 | return false; |
91 | } |
92 | |
93 | Type *Type::getFloatingPointTy(LLVMContext &C, const fltSemantics &S) { |
94 | Type *Ty; |
95 | if (&S == &APFloat::IEEEhalf()) |
96 | Ty = Type::getHalfTy(C); |
97 | else if (&S == &APFloat::BFloat()) |
98 | Ty = Type::getBFloatTy(C); |
99 | else if (&S == &APFloat::IEEEsingle()) |
100 | Ty = Type::getFloatTy(C); |
101 | else if (&S == &APFloat::IEEEdouble()) |
102 | Ty = Type::getDoubleTy(C); |
103 | else if (&S == &APFloat::x87DoubleExtended()) |
104 | Ty = Type::getX86_FP80Ty(C); |
105 | else if (&S == &APFloat::IEEEquad()) |
106 | Ty = Type::getFP128Ty(C); |
107 | else { |
108 | assert(&S == &APFloat::PPCDoubleDouble() && "Unknown FP format" ); |
109 | Ty = Type::getPPC_FP128Ty(C); |
110 | } |
111 | return Ty; |
112 | } |
113 | |
114 | bool Type::canLosslesslyBitCastTo(Type *Ty) const { |
115 | // Identity cast means no change so return true |
116 | if (this == Ty) |
117 | return true; |
118 | |
119 | // They are not convertible unless they are at least first class types |
120 | if (!this->isFirstClassType() || !Ty->isFirstClassType()) |
121 | return false; |
122 | |
123 | // Vector -> Vector conversions are always lossless if the two vector types |
124 | // have the same size, otherwise not. |
125 | if (isa<VectorType>(Val: this) && isa<VectorType>(Val: Ty)) |
126 | return getPrimitiveSizeInBits() == Ty->getPrimitiveSizeInBits(); |
127 | |
128 | // 64-bit fixed width vector types can be losslessly converted to x86mmx. |
129 | if (((isa<FixedVectorType>(Val: this)) && Ty->isX86_MMXTy()) && |
130 | getPrimitiveSizeInBits().getFixedValue() == 64) |
131 | return true; |
132 | if ((isX86_MMXTy() && isa<FixedVectorType>(Val: Ty)) && |
133 | Ty->getPrimitiveSizeInBits().getFixedValue() == 64) |
134 | return true; |
135 | |
136 | // 8192-bit fixed width vector types can be losslessly converted to x86amx. |
137 | if (((isa<FixedVectorType>(Val: this)) && Ty->isX86_AMXTy()) && |
138 | getPrimitiveSizeInBits().getFixedValue() == 8192) |
139 | return true; |
140 | if ((isX86_AMXTy() && isa<FixedVectorType>(Val: Ty)) && |
141 | Ty->getPrimitiveSizeInBits().getFixedValue() == 8192) |
142 | return true; |
143 | |
144 | // Conservatively assume we can't losslessly convert between pointers with |
145 | // different address spaces. |
146 | return false; |
147 | } |
148 | |
149 | bool Type::isEmptyTy() const { |
150 | if (auto *ATy = dyn_cast<ArrayType>(Val: this)) { |
151 | unsigned NumElements = ATy->getNumElements(); |
152 | return NumElements == 0 || ATy->getElementType()->isEmptyTy(); |
153 | } |
154 | |
155 | if (auto *STy = dyn_cast<StructType>(Val: this)) { |
156 | unsigned NumElements = STy->getNumElements(); |
157 | for (unsigned i = 0; i < NumElements; ++i) |
158 | if (!STy->getElementType(N: i)->isEmptyTy()) |
159 | return false; |
160 | return true; |
161 | } |
162 | |
163 | return false; |
164 | } |
165 | |
166 | TypeSize Type::getPrimitiveSizeInBits() const { |
167 | switch (getTypeID()) { |
168 | case Type::HalfTyID: |
169 | return TypeSize::getFixed(ExactSize: 16); |
170 | case Type::BFloatTyID: |
171 | return TypeSize::getFixed(ExactSize: 16); |
172 | case Type::FloatTyID: |
173 | return TypeSize::getFixed(ExactSize: 32); |
174 | case Type::DoubleTyID: |
175 | return TypeSize::getFixed(ExactSize: 64); |
176 | case Type::X86_FP80TyID: |
177 | return TypeSize::getFixed(ExactSize: 80); |
178 | case Type::FP128TyID: |
179 | return TypeSize::getFixed(ExactSize: 128); |
180 | case Type::PPC_FP128TyID: |
181 | return TypeSize::getFixed(ExactSize: 128); |
182 | case Type::X86_MMXTyID: |
183 | return TypeSize::getFixed(ExactSize: 64); |
184 | case Type::X86_AMXTyID: |
185 | return TypeSize::getFixed(ExactSize: 8192); |
186 | case Type::IntegerTyID: |
187 | return TypeSize::getFixed(ExactSize: cast<IntegerType>(Val: this)->getBitWidth()); |
188 | case Type::FixedVectorTyID: |
189 | case Type::ScalableVectorTyID: { |
190 | const VectorType *VTy = cast<VectorType>(Val: this); |
191 | ElementCount EC = VTy->getElementCount(); |
192 | TypeSize ETS = VTy->getElementType()->getPrimitiveSizeInBits(); |
193 | assert(!ETS.isScalable() && "Vector type should have fixed-width elements" ); |
194 | return {ETS.getFixedValue() * EC.getKnownMinValue(), EC.isScalable()}; |
195 | } |
196 | default: |
197 | return TypeSize::getFixed(ExactSize: 0); |
198 | } |
199 | } |
200 | |
201 | unsigned Type::getScalarSizeInBits() const { |
202 | // It is safe to assume that the scalar types have a fixed size. |
203 | return getScalarType()->getPrimitiveSizeInBits().getFixedValue(); |
204 | } |
205 | |
206 | int Type::getFPMantissaWidth() const { |
207 | if (auto *VTy = dyn_cast<VectorType>(Val: this)) |
208 | return VTy->getElementType()->getFPMantissaWidth(); |
209 | assert(isFloatingPointTy() && "Not a floating point type!" ); |
210 | if (getTypeID() == HalfTyID) return 11; |
211 | if (getTypeID() == BFloatTyID) return 8; |
212 | if (getTypeID() == FloatTyID) return 24; |
213 | if (getTypeID() == DoubleTyID) return 53; |
214 | if (getTypeID() == X86_FP80TyID) return 64; |
215 | if (getTypeID() == FP128TyID) return 113; |
216 | assert(getTypeID() == PPC_FP128TyID && "unknown fp type" ); |
217 | return -1; |
218 | } |
219 | |
220 | bool Type::isSizedDerivedType(SmallPtrSetImpl<Type*> *Visited) const { |
221 | if (auto *ATy = dyn_cast<ArrayType>(Val: this)) |
222 | return ATy->getElementType()->isSized(Visited); |
223 | |
224 | if (auto *VTy = dyn_cast<VectorType>(Val: this)) |
225 | return VTy->getElementType()->isSized(Visited); |
226 | |
227 | if (auto *TTy = dyn_cast<TargetExtType>(Val: this)) |
228 | return TTy->getLayoutType()->isSized(Visited); |
229 | |
230 | return cast<StructType>(Val: this)->isSized(Visited); |
231 | } |
232 | |
233 | //===----------------------------------------------------------------------===// |
234 | // Primitive 'Type' data |
235 | //===----------------------------------------------------------------------===// |
236 | |
237 | Type *Type::getVoidTy(LLVMContext &C) { return &C.pImpl->VoidTy; } |
238 | Type *Type::getLabelTy(LLVMContext &C) { return &C.pImpl->LabelTy; } |
239 | Type *Type::getHalfTy(LLVMContext &C) { return &C.pImpl->HalfTy; } |
240 | Type *Type::getBFloatTy(LLVMContext &C) { return &C.pImpl->BFloatTy; } |
241 | Type *Type::getFloatTy(LLVMContext &C) { return &C.pImpl->FloatTy; } |
242 | Type *Type::getDoubleTy(LLVMContext &C) { return &C.pImpl->DoubleTy; } |
243 | Type *Type::getMetadataTy(LLVMContext &C) { return &C.pImpl->MetadataTy; } |
244 | Type *Type::getTokenTy(LLVMContext &C) { return &C.pImpl->TokenTy; } |
245 | Type *Type::getX86_FP80Ty(LLVMContext &C) { return &C.pImpl->X86_FP80Ty; } |
246 | Type *Type::getFP128Ty(LLVMContext &C) { return &C.pImpl->FP128Ty; } |
247 | Type *Type::getPPC_FP128Ty(LLVMContext &C) { return &C.pImpl->PPC_FP128Ty; } |
248 | Type *Type::getX86_MMXTy(LLVMContext &C) { return &C.pImpl->X86_MMXTy; } |
249 | Type *Type::getX86_AMXTy(LLVMContext &C) { return &C.pImpl->X86_AMXTy; } |
250 | |
251 | IntegerType *Type::getInt1Ty(LLVMContext &C) { return &C.pImpl->Int1Ty; } |
252 | IntegerType *Type::getInt8Ty(LLVMContext &C) { return &C.pImpl->Int8Ty; } |
253 | IntegerType *Type::getInt16Ty(LLVMContext &C) { return &C.pImpl->Int16Ty; } |
254 | IntegerType *Type::getInt32Ty(LLVMContext &C) { return &C.pImpl->Int32Ty; } |
255 | IntegerType *Type::getInt64Ty(LLVMContext &C) { return &C.pImpl->Int64Ty; } |
256 | IntegerType *Type::getInt128Ty(LLVMContext &C) { return &C.pImpl->Int128Ty; } |
257 | |
258 | IntegerType *Type::getIntNTy(LLVMContext &C, unsigned N) { |
259 | return IntegerType::get(C, NumBits: N); |
260 | } |
261 | |
262 | Type *Type::getWasm_ExternrefTy(LLVMContext &C) { |
263 | // opaque pointer in addrspace(10) |
264 | static PointerType *Ty = PointerType::get(C, AddressSpace: 10); |
265 | return Ty; |
266 | } |
267 | |
268 | Type *Type::getWasm_FuncrefTy(LLVMContext &C) { |
269 | // opaque pointer in addrspace(20) |
270 | static PointerType *Ty = PointerType::get(C, AddressSpace: 20); |
271 | return Ty; |
272 | } |
273 | |
274 | //===----------------------------------------------------------------------===// |
275 | // IntegerType Implementation |
276 | //===----------------------------------------------------------------------===// |
277 | |
278 | IntegerType *IntegerType::get(LLVMContext &C, unsigned NumBits) { |
279 | assert(NumBits >= MIN_INT_BITS && "bitwidth too small" ); |
280 | assert(NumBits <= MAX_INT_BITS && "bitwidth too large" ); |
281 | |
282 | // Check for the built-in integer types |
283 | switch (NumBits) { |
284 | case 1: return cast<IntegerType>(Val: Type::getInt1Ty(C)); |
285 | case 8: return cast<IntegerType>(Val: Type::getInt8Ty(C)); |
286 | case 16: return cast<IntegerType>(Val: Type::getInt16Ty(C)); |
287 | case 32: return cast<IntegerType>(Val: Type::getInt32Ty(C)); |
288 | case 64: return cast<IntegerType>(Val: Type::getInt64Ty(C)); |
289 | case 128: return cast<IntegerType>(Val: Type::getInt128Ty(C)); |
290 | default: |
291 | break; |
292 | } |
293 | |
294 | IntegerType *&Entry = C.pImpl->IntegerTypes[NumBits]; |
295 | |
296 | if (!Entry) |
297 | Entry = new (C.pImpl->Alloc) IntegerType(C, NumBits); |
298 | |
299 | return Entry; |
300 | } |
301 | |
302 | APInt IntegerType::getMask() const { return APInt::getAllOnes(numBits: getBitWidth()); } |
303 | |
304 | //===----------------------------------------------------------------------===// |
305 | // FunctionType Implementation |
306 | //===----------------------------------------------------------------------===// |
307 | |
308 | FunctionType::FunctionType(Type *Result, ArrayRef<Type*> Params, |
309 | bool IsVarArgs) |
310 | : Type(Result->getContext(), FunctionTyID) { |
311 | Type **SubTys = reinterpret_cast<Type**>(this+1); |
312 | assert(isValidReturnType(Result) && "invalid return type for function" ); |
313 | setSubclassData(IsVarArgs); |
314 | |
315 | SubTys[0] = Result; |
316 | |
317 | for (unsigned i = 0, e = Params.size(); i != e; ++i) { |
318 | assert(isValidArgumentType(Params[i]) && |
319 | "Not a valid type for function argument!" ); |
320 | SubTys[i+1] = Params[i]; |
321 | } |
322 | |
323 | ContainedTys = SubTys; |
324 | NumContainedTys = Params.size() + 1; // + 1 for result type |
325 | } |
326 | |
327 | // This is the factory function for the FunctionType class. |
328 | FunctionType *FunctionType::get(Type *ReturnType, |
329 | ArrayRef<Type*> Params, bool isVarArg) { |
330 | LLVMContextImpl *pImpl = ReturnType->getContext().pImpl; |
331 | const FunctionTypeKeyInfo::KeyTy Key(ReturnType, Params, isVarArg); |
332 | FunctionType *FT; |
333 | // Since we only want to allocate a fresh function type in case none is found |
334 | // and we don't want to perform two lookups (one for checking if existent and |
335 | // one for inserting the newly allocated one), here we instead lookup based on |
336 | // Key and update the reference to the function type in-place to a newly |
337 | // allocated one if not found. |
338 | auto Insertion = pImpl->FunctionTypes.insert_as(V: nullptr, LookupKey: Key); |
339 | if (Insertion.second) { |
340 | // The function type was not found. Allocate one and update FunctionTypes |
341 | // in-place. |
342 | FT = (FunctionType *)pImpl->Alloc.Allocate( |
343 | Size: sizeof(FunctionType) + sizeof(Type *) * (Params.size() + 1), |
344 | Alignment: alignof(FunctionType)); |
345 | new (FT) FunctionType(ReturnType, Params, isVarArg); |
346 | *Insertion.first = FT; |
347 | } else { |
348 | // The function type was found. Just return it. |
349 | FT = *Insertion.first; |
350 | } |
351 | return FT; |
352 | } |
353 | |
354 | FunctionType *FunctionType::get(Type *Result, bool isVarArg) { |
355 | return get(ReturnType: Result, Params: std::nullopt, isVarArg); |
356 | } |
357 | |
358 | bool FunctionType::isValidReturnType(Type *RetTy) { |
359 | return !RetTy->isFunctionTy() && !RetTy->isLabelTy() && |
360 | !RetTy->isMetadataTy(); |
361 | } |
362 | |
363 | bool FunctionType::isValidArgumentType(Type *ArgTy) { |
364 | return ArgTy->isFirstClassType(); |
365 | } |
366 | |
367 | //===----------------------------------------------------------------------===// |
368 | // StructType Implementation |
369 | //===----------------------------------------------------------------------===// |
370 | |
371 | // Primitive Constructors. |
372 | |
373 | StructType *StructType::get(LLVMContext &Context, ArrayRef<Type*> ETypes, |
374 | bool isPacked) { |
375 | LLVMContextImpl *pImpl = Context.pImpl; |
376 | const AnonStructTypeKeyInfo::KeyTy Key(ETypes, isPacked); |
377 | |
378 | StructType *ST; |
379 | // Since we only want to allocate a fresh struct type in case none is found |
380 | // and we don't want to perform two lookups (one for checking if existent and |
381 | // one for inserting the newly allocated one), here we instead lookup based on |
382 | // Key and update the reference to the struct type in-place to a newly |
383 | // allocated one if not found. |
384 | auto Insertion = pImpl->AnonStructTypes.insert_as(V: nullptr, LookupKey: Key); |
385 | if (Insertion.second) { |
386 | // The struct type was not found. Allocate one and update AnonStructTypes |
387 | // in-place. |
388 | ST = new (Context.pImpl->Alloc) StructType(Context); |
389 | ST->setSubclassData(SCDB_IsLiteral); // Literal struct. |
390 | ST->setBody(Elements: ETypes, isPacked); |
391 | *Insertion.first = ST; |
392 | } else { |
393 | // The struct type was found. Just return it. |
394 | ST = *Insertion.first; |
395 | } |
396 | |
397 | return ST; |
398 | } |
399 | |
400 | bool StructType::containsScalableVectorType( |
401 | SmallPtrSetImpl<Type *> *Visited) const { |
402 | if ((getSubclassData() & SCDB_ContainsScalableVector) != 0) |
403 | return true; |
404 | |
405 | if ((getSubclassData() & SCDB_NotContainsScalableVector) != 0) |
406 | return false; |
407 | |
408 | if (Visited && !Visited->insert(Ptr: const_cast<StructType *>(this)).second) |
409 | return false; |
410 | |
411 | for (Type *Ty : elements()) { |
412 | if (isa<ScalableVectorType>(Val: Ty)) { |
413 | const_cast<StructType *>(this)->setSubclassData( |
414 | getSubclassData() | SCDB_ContainsScalableVector); |
415 | return true; |
416 | } |
417 | if (auto *STy = dyn_cast<StructType>(Val: Ty)) { |
418 | if (STy->containsScalableVectorType(Visited)) { |
419 | const_cast<StructType *>(this)->setSubclassData( |
420 | getSubclassData() | SCDB_ContainsScalableVector); |
421 | return true; |
422 | } |
423 | } |
424 | } |
425 | |
426 | // For structures that are opaque, return false but do not set the |
427 | // SCDB_NotContainsScalableVector flag since it may gain scalable vector type |
428 | // when it becomes non-opaque. |
429 | if (!isOpaque()) |
430 | const_cast<StructType *>(this)->setSubclassData( |
431 | getSubclassData() | SCDB_NotContainsScalableVector); |
432 | return false; |
433 | } |
434 | |
435 | bool StructType::containsHomogeneousScalableVectorTypes() const { |
436 | Type *FirstTy = getNumElements() > 0 ? elements()[0] : nullptr; |
437 | if (!FirstTy || !isa<ScalableVectorType>(Val: FirstTy)) |
438 | return false; |
439 | for (Type *Ty : elements()) |
440 | if (Ty != FirstTy) |
441 | return false; |
442 | return true; |
443 | } |
444 | |
445 | void StructType::setBody(ArrayRef<Type*> Elements, bool isPacked) { |
446 | assert(isOpaque() && "Struct body already set!" ); |
447 | |
448 | setSubclassData(getSubclassData() | SCDB_HasBody); |
449 | if (isPacked) |
450 | setSubclassData(getSubclassData() | SCDB_Packed); |
451 | |
452 | NumContainedTys = Elements.size(); |
453 | |
454 | if (Elements.empty()) { |
455 | ContainedTys = nullptr; |
456 | return; |
457 | } |
458 | |
459 | ContainedTys = Elements.copy(A&: getContext().pImpl->Alloc).data(); |
460 | } |
461 | |
462 | void StructType::setName(StringRef Name) { |
463 | if (Name == getName()) return; |
464 | |
465 | StringMap<StructType *> &SymbolTable = getContext().pImpl->NamedStructTypes; |
466 | |
467 | using EntryTy = StringMap<StructType *>::MapEntryTy; |
468 | |
469 | // If this struct already had a name, remove its symbol table entry. Don't |
470 | // delete the data yet because it may be part of the new name. |
471 | if (SymbolTableEntry) |
472 | SymbolTable.remove(KeyValue: (EntryTy *)SymbolTableEntry); |
473 | |
474 | // If this is just removing the name, we're done. |
475 | if (Name.empty()) { |
476 | if (SymbolTableEntry) { |
477 | // Delete the old string data. |
478 | ((EntryTy *)SymbolTableEntry)->Destroy(allocator&: SymbolTable.getAllocator()); |
479 | SymbolTableEntry = nullptr; |
480 | } |
481 | return; |
482 | } |
483 | |
484 | // Look up the entry for the name. |
485 | auto IterBool = |
486 | getContext().pImpl->NamedStructTypes.insert(KV: std::make_pair(x&: Name, y: this)); |
487 | |
488 | // While we have a name collision, try a random rename. |
489 | if (!IterBool.second) { |
490 | SmallString<64> TempStr(Name); |
491 | TempStr.push_back(Elt: '.'); |
492 | raw_svector_ostream TmpStream(TempStr); |
493 | unsigned NameSize = Name.size(); |
494 | |
495 | do { |
496 | TempStr.resize(N: NameSize + 1); |
497 | TmpStream << getContext().pImpl->NamedStructTypesUniqueID++; |
498 | |
499 | IterBool = getContext().pImpl->NamedStructTypes.insert( |
500 | KV: std::make_pair(x: TmpStream.str(), y: this)); |
501 | } while (!IterBool.second); |
502 | } |
503 | |
504 | // Delete the old string data. |
505 | if (SymbolTableEntry) |
506 | ((EntryTy *)SymbolTableEntry)->Destroy(allocator&: SymbolTable.getAllocator()); |
507 | SymbolTableEntry = &*IterBool.first; |
508 | } |
509 | |
510 | //===----------------------------------------------------------------------===// |
511 | // StructType Helper functions. |
512 | |
513 | StructType *StructType::create(LLVMContext &Context, StringRef Name) { |
514 | StructType *ST = new (Context.pImpl->Alloc) StructType(Context); |
515 | if (!Name.empty()) |
516 | ST->setName(Name); |
517 | return ST; |
518 | } |
519 | |
520 | StructType *StructType::get(LLVMContext &Context, bool isPacked) { |
521 | return get(Context, ETypes: std::nullopt, isPacked); |
522 | } |
523 | |
524 | StructType *StructType::create(LLVMContext &Context, ArrayRef<Type*> Elements, |
525 | StringRef Name, bool isPacked) { |
526 | StructType *ST = create(Context, Name); |
527 | ST->setBody(Elements, isPacked); |
528 | return ST; |
529 | } |
530 | |
531 | StructType *StructType::create(LLVMContext &Context, ArrayRef<Type*> Elements) { |
532 | return create(Context, Elements, Name: StringRef()); |
533 | } |
534 | |
535 | StructType *StructType::create(LLVMContext &Context) { |
536 | return create(Context, Name: StringRef()); |
537 | } |
538 | |
539 | StructType *StructType::create(ArrayRef<Type*> Elements, StringRef Name, |
540 | bool isPacked) { |
541 | assert(!Elements.empty() && |
542 | "This method may not be invoked with an empty list" ); |
543 | return create(Context&: Elements[0]->getContext(), Elements, Name, isPacked); |
544 | } |
545 | |
546 | StructType *StructType::create(ArrayRef<Type*> Elements) { |
547 | assert(!Elements.empty() && |
548 | "This method may not be invoked with an empty list" ); |
549 | return create(Context&: Elements[0]->getContext(), Elements, Name: StringRef()); |
550 | } |
551 | |
552 | bool StructType::isSized(SmallPtrSetImpl<Type*> *Visited) const { |
553 | if ((getSubclassData() & SCDB_IsSized) != 0) |
554 | return true; |
555 | if (isOpaque()) |
556 | return false; |
557 | |
558 | if (Visited && !Visited->insert(Ptr: const_cast<StructType*>(this)).second) |
559 | return false; |
560 | |
561 | // Okay, our struct is sized if all of the elements are, but if one of the |
562 | // elements is opaque, the struct isn't sized *yet*, but may become sized in |
563 | // the future, so just bail out without caching. |
564 | // The ONLY special case inside a struct that is considered sized is when the |
565 | // elements are homogeneous of a scalable vector type. |
566 | if (containsHomogeneousScalableVectorTypes()) { |
567 | const_cast<StructType *>(this)->setSubclassData(getSubclassData() | |
568 | SCDB_IsSized); |
569 | return true; |
570 | } |
571 | for (Type *Ty : elements()) { |
572 | // If the struct contains a scalable vector type, don't consider it sized. |
573 | // This prevents it from being used in loads/stores/allocas/GEPs. The ONLY |
574 | // special case right now is a structure of homogenous scalable vector |
575 | // types and is handled by the if-statement before this for-loop. |
576 | if (Ty->isScalableTy()) |
577 | return false; |
578 | if (!Ty->isSized(Visited)) |
579 | return false; |
580 | } |
581 | |
582 | // Here we cheat a bit and cast away const-ness. The goal is to memoize when |
583 | // we find a sized type, as types can only move from opaque to sized, not the |
584 | // other way. |
585 | const_cast<StructType*>(this)->setSubclassData( |
586 | getSubclassData() | SCDB_IsSized); |
587 | return true; |
588 | } |
589 | |
590 | StringRef StructType::getName() const { |
591 | assert(!isLiteral() && "Literal structs never have names" ); |
592 | if (!SymbolTableEntry) return StringRef(); |
593 | |
594 | return ((StringMapEntry<StructType*> *)SymbolTableEntry)->getKey(); |
595 | } |
596 | |
597 | bool StructType::isValidElementType(Type *ElemTy) { |
598 | return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && |
599 | !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy() && |
600 | !ElemTy->isTokenTy(); |
601 | } |
602 | |
603 | bool StructType::isLayoutIdentical(StructType *Other) const { |
604 | if (this == Other) return true; |
605 | |
606 | if (isPacked() != Other->isPacked()) |
607 | return false; |
608 | |
609 | return elements() == Other->elements(); |
610 | } |
611 | |
612 | Type *StructType::getTypeAtIndex(const Value *V) const { |
613 | unsigned Idx = (unsigned)cast<Constant>(Val: V)->getUniqueInteger().getZExtValue(); |
614 | assert(indexValid(Idx) && "Invalid structure index!" ); |
615 | return getElementType(N: Idx); |
616 | } |
617 | |
618 | bool StructType::indexValid(const Value *V) const { |
619 | // Structure indexes require (vectors of) 32-bit integer constants. In the |
620 | // vector case all of the indices must be equal. |
621 | if (!V->getType()->isIntOrIntVectorTy(BitWidth: 32)) |
622 | return false; |
623 | if (isa<ScalableVectorType>(Val: V->getType())) |
624 | return false; |
625 | const Constant *C = dyn_cast<Constant>(Val: V); |
626 | if (C && V->getType()->isVectorTy()) |
627 | C = C->getSplatValue(); |
628 | const ConstantInt *CU = dyn_cast_or_null<ConstantInt>(Val: C); |
629 | return CU && CU->getZExtValue() < getNumElements(); |
630 | } |
631 | |
632 | StructType *StructType::getTypeByName(LLVMContext &C, StringRef Name) { |
633 | return C.pImpl->NamedStructTypes.lookup(Key: Name); |
634 | } |
635 | |
636 | //===----------------------------------------------------------------------===// |
637 | // ArrayType Implementation |
638 | //===----------------------------------------------------------------------===// |
639 | |
640 | ArrayType::ArrayType(Type *ElType, uint64_t NumEl) |
641 | : Type(ElType->getContext(), ArrayTyID), ContainedType(ElType), |
642 | NumElements(NumEl) { |
643 | ContainedTys = &ContainedType; |
644 | NumContainedTys = 1; |
645 | } |
646 | |
647 | ArrayType *ArrayType::get(Type *ElementType, uint64_t NumElements) { |
648 | assert(isValidElementType(ElementType) && "Invalid type for array element!" ); |
649 | |
650 | LLVMContextImpl *pImpl = ElementType->getContext().pImpl; |
651 | ArrayType *&Entry = |
652 | pImpl->ArrayTypes[std::make_pair(x&: ElementType, y&: NumElements)]; |
653 | |
654 | if (!Entry) |
655 | Entry = new (pImpl->Alloc) ArrayType(ElementType, NumElements); |
656 | return Entry; |
657 | } |
658 | |
659 | bool ArrayType::isValidElementType(Type *ElemTy) { |
660 | return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && |
661 | !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy() && |
662 | !ElemTy->isTokenTy() && !ElemTy->isX86_AMXTy(); |
663 | } |
664 | |
665 | //===----------------------------------------------------------------------===// |
666 | // VectorType Implementation |
667 | //===----------------------------------------------------------------------===// |
668 | |
669 | VectorType::VectorType(Type *ElType, unsigned EQ, Type::TypeID TID) |
670 | : Type(ElType->getContext(), TID), ContainedType(ElType), |
671 | ElementQuantity(EQ) { |
672 | ContainedTys = &ContainedType; |
673 | NumContainedTys = 1; |
674 | } |
675 | |
676 | VectorType *VectorType::get(Type *ElementType, ElementCount EC) { |
677 | if (EC.isScalable()) |
678 | return ScalableVectorType::get(ElementType, MinNumElts: EC.getKnownMinValue()); |
679 | else |
680 | return FixedVectorType::get(ElementType, NumElts: EC.getKnownMinValue()); |
681 | } |
682 | |
683 | bool VectorType::isValidElementType(Type *ElemTy) { |
684 | return ElemTy->isIntegerTy() || ElemTy->isFloatingPointTy() || |
685 | ElemTy->isPointerTy() || ElemTy->getTypeID() == TypedPointerTyID; |
686 | } |
687 | |
688 | //===----------------------------------------------------------------------===// |
689 | // FixedVectorType Implementation |
690 | //===----------------------------------------------------------------------===// |
691 | |
692 | FixedVectorType *FixedVectorType::get(Type *ElementType, unsigned NumElts) { |
693 | assert(NumElts > 0 && "#Elements of a VectorType must be greater than 0" ); |
694 | assert(isValidElementType(ElementType) && "Element type of a VectorType must " |
695 | "be an integer, floating point, or " |
696 | "pointer type." ); |
697 | |
698 | auto EC = ElementCount::getFixed(MinVal: NumElts); |
699 | |
700 | LLVMContextImpl *pImpl = ElementType->getContext().pImpl; |
701 | VectorType *&Entry = ElementType->getContext() |
702 | .pImpl->VectorTypes[std::make_pair(x&: ElementType, y&: EC)]; |
703 | |
704 | if (!Entry) |
705 | Entry = new (pImpl->Alloc) FixedVectorType(ElementType, NumElts); |
706 | return cast<FixedVectorType>(Val: Entry); |
707 | } |
708 | |
709 | //===----------------------------------------------------------------------===// |
710 | // ScalableVectorType Implementation |
711 | //===----------------------------------------------------------------------===// |
712 | |
713 | ScalableVectorType *ScalableVectorType::get(Type *ElementType, |
714 | unsigned MinNumElts) { |
715 | assert(MinNumElts > 0 && "#Elements of a VectorType must be greater than 0" ); |
716 | assert(isValidElementType(ElementType) && "Element type of a VectorType must " |
717 | "be an integer, floating point, or " |
718 | "pointer type." ); |
719 | |
720 | auto EC = ElementCount::getScalable(MinVal: MinNumElts); |
721 | |
722 | LLVMContextImpl *pImpl = ElementType->getContext().pImpl; |
723 | VectorType *&Entry = ElementType->getContext() |
724 | .pImpl->VectorTypes[std::make_pair(x&: ElementType, y&: EC)]; |
725 | |
726 | if (!Entry) |
727 | Entry = new (pImpl->Alloc) ScalableVectorType(ElementType, MinNumElts); |
728 | return cast<ScalableVectorType>(Val: Entry); |
729 | } |
730 | |
731 | //===----------------------------------------------------------------------===// |
732 | // PointerType Implementation |
733 | //===----------------------------------------------------------------------===// |
734 | |
735 | PointerType *PointerType::get(Type *EltTy, unsigned AddressSpace) { |
736 | assert(EltTy && "Can't get a pointer to <null> type!" ); |
737 | assert(isValidElementType(EltTy) && "Invalid type for pointer element!" ); |
738 | |
739 | // Automatically convert typed pointers to opaque pointers. |
740 | return get(C&: EltTy->getContext(), AddressSpace); |
741 | } |
742 | |
743 | PointerType *PointerType::get(LLVMContext &C, unsigned AddressSpace) { |
744 | LLVMContextImpl *CImpl = C.pImpl; |
745 | |
746 | // Since AddressSpace #0 is the common case, we special case it. |
747 | PointerType *&Entry = AddressSpace == 0 ? CImpl->AS0PointerType |
748 | : CImpl->PointerTypes[AddressSpace]; |
749 | |
750 | if (!Entry) |
751 | Entry = new (CImpl->Alloc) PointerType(C, AddressSpace); |
752 | return Entry; |
753 | } |
754 | |
755 | PointerType::PointerType(LLVMContext &C, unsigned AddrSpace) |
756 | : Type(C, PointerTyID) { |
757 | setSubclassData(AddrSpace); |
758 | } |
759 | |
760 | PointerType *Type::getPointerTo(unsigned AddrSpace) const { |
761 | return PointerType::get(EltTy: const_cast<Type*>(this), AddressSpace: AddrSpace); |
762 | } |
763 | |
764 | bool PointerType::isValidElementType(Type *ElemTy) { |
765 | return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && |
766 | !ElemTy->isMetadataTy() && !ElemTy->isTokenTy() && |
767 | !ElemTy->isX86_AMXTy(); |
768 | } |
769 | |
770 | bool PointerType::isLoadableOrStorableType(Type *ElemTy) { |
771 | return isValidElementType(ElemTy) && !ElemTy->isFunctionTy(); |
772 | } |
773 | |
774 | //===----------------------------------------------------------------------===// |
775 | // TargetExtType Implementation |
776 | //===----------------------------------------------------------------------===// |
777 | |
778 | TargetExtType::TargetExtType(LLVMContext &C, StringRef Name, |
779 | ArrayRef<Type *> Types, ArrayRef<unsigned> Ints) |
780 | : Type(C, TargetExtTyID), Name(C.pImpl->Saver.save(S: Name)) { |
781 | NumContainedTys = Types.size(); |
782 | |
783 | // Parameter storage immediately follows the class in allocation. |
784 | Type **Params = reinterpret_cast<Type **>(this + 1); |
785 | ContainedTys = Params; |
786 | for (Type *T : Types) |
787 | *Params++ = T; |
788 | |
789 | setSubclassData(Ints.size()); |
790 | unsigned *IntParamSpace = reinterpret_cast<unsigned *>(Params); |
791 | IntParams = IntParamSpace; |
792 | for (unsigned IntParam : Ints) |
793 | *IntParamSpace++ = IntParam; |
794 | } |
795 | |
796 | TargetExtType *TargetExtType::get(LLVMContext &C, StringRef Name, |
797 | ArrayRef<Type *> Types, |
798 | ArrayRef<unsigned> Ints) { |
799 | const TargetExtTypeKeyInfo::KeyTy Key(Name, Types, Ints); |
800 | TargetExtType *TT; |
801 | // Since we only want to allocate a fresh target type in case none is found |
802 | // and we don't want to perform two lookups (one for checking if existent and |
803 | // one for inserting the newly allocated one), here we instead lookup based on |
804 | // Key and update the reference to the target type in-place to a newly |
805 | // allocated one if not found. |
806 | auto Insertion = C.pImpl->TargetExtTypes.insert_as(V: nullptr, LookupKey: Key); |
807 | if (Insertion.second) { |
808 | // The target type was not found. Allocate one and update TargetExtTypes |
809 | // in-place. |
810 | TT = (TargetExtType *)C.pImpl->Alloc.Allocate( |
811 | Size: sizeof(TargetExtType) + sizeof(Type *) * Types.size() + |
812 | sizeof(unsigned) * Ints.size(), |
813 | Alignment: alignof(TargetExtType)); |
814 | new (TT) TargetExtType(C, Name, Types, Ints); |
815 | *Insertion.first = TT; |
816 | } else { |
817 | // The target type was found. Just return it. |
818 | TT = *Insertion.first; |
819 | } |
820 | return TT; |
821 | } |
822 | |
823 | namespace { |
824 | struct TargetTypeInfo { |
825 | Type *LayoutType; |
826 | uint64_t Properties; |
827 | |
828 | template <typename... ArgTys> |
829 | TargetTypeInfo(Type *LayoutType, ArgTys... Properties) |
830 | : LayoutType(LayoutType), Properties((0 | ... | Properties)) {} |
831 | }; |
832 | } // anonymous namespace |
833 | |
834 | static TargetTypeInfo getTargetTypeInfo(const TargetExtType *Ty) { |
835 | LLVMContext &C = Ty->getContext(); |
836 | StringRef Name = Ty->getName(); |
837 | if (Name == "spirv.Image" ) |
838 | return TargetTypeInfo(PointerType::get(C, AddressSpace: 0), TargetExtType::CanBeGlobal); |
839 | if (Name.starts_with(Prefix: "spirv." )) |
840 | return TargetTypeInfo(PointerType::get(C, AddressSpace: 0), TargetExtType::HasZeroInit, |
841 | TargetExtType::CanBeGlobal); |
842 | |
843 | // Opaque types in the AArch64 name space. |
844 | if (Name == "aarch64.svcount" ) |
845 | return TargetTypeInfo(ScalableVectorType::get(ElementType: Type::getInt1Ty(C), MinNumElts: 16), |
846 | TargetExtType::HasZeroInit); |
847 | |
848 | return TargetTypeInfo(Type::getVoidTy(C)); |
849 | } |
850 | |
851 | Type *TargetExtType::getLayoutType() const { |
852 | return getTargetTypeInfo(Ty: this).LayoutType; |
853 | } |
854 | |
855 | bool TargetExtType::hasProperty(Property Prop) const { |
856 | uint64_t Properties = getTargetTypeInfo(Ty: this).Properties; |
857 | return (Properties & Prop) == Prop; |
858 | } |
859 | |