1 | //===- TypeDetail.h - MLIR Type storage details -----------------*- 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 | // This holds implementation details of Type. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | #ifndef TYPEDETAIL_H_ |
13 | #define TYPEDETAIL_H_ |
14 | |
15 | #include "mlir/IR/AffineMap.h" |
16 | #include "mlir/IR/BuiltinTypes.h" |
17 | #include "mlir/IR/MLIRContext.h" |
18 | #include "mlir/IR/OperationSupport.h" |
19 | #include "mlir/IR/TypeRange.h" |
20 | #include "llvm/ADT/bit.h" |
21 | #include "llvm/Support/TrailingObjects.h" |
22 | |
23 | namespace mlir { |
24 | |
25 | namespace detail { |
26 | |
27 | /// Integer Type Storage and Uniquing. |
28 | struct IntegerTypeStorage : public TypeStorage { |
29 | IntegerTypeStorage(unsigned width, |
30 | IntegerType::SignednessSemantics signedness) |
31 | : width(width), signedness(signedness) {} |
32 | |
33 | /// The hash key used for uniquing. |
34 | using KeyTy = std::tuple<unsigned, IntegerType::SignednessSemantics>; |
35 | |
36 | static llvm::hash_code hashKey(const KeyTy &key) { |
37 | return llvm::hash_value(key); |
38 | } |
39 | |
40 | bool operator==(const KeyTy &key) const { |
41 | return KeyTy(width, signedness) == key; |
42 | } |
43 | |
44 | static IntegerTypeStorage *construct(TypeStorageAllocator &allocator, |
45 | KeyTy key) { |
46 | return new (allocator.allocate<IntegerTypeStorage>()) |
47 | IntegerTypeStorage(std::get<0>(key), std::get<1>(key)); |
48 | } |
49 | |
50 | KeyTy getAsKey() const { return KeyTy(width, signedness); } |
51 | |
52 | unsigned width : 30; |
53 | IntegerType::SignednessSemantics signedness : 2; |
54 | }; |
55 | |
56 | /// Function Type Storage and Uniquing. |
57 | struct FunctionTypeStorage : public TypeStorage { |
58 | FunctionTypeStorage(unsigned numInputs, unsigned numResults, |
59 | Type const *inputsAndResults) |
60 | : numInputs(numInputs), numResults(numResults), |
61 | inputsAndResults(inputsAndResults) {} |
62 | |
63 | /// The hash key used for uniquing. |
64 | using KeyTy = std::tuple<TypeRange, TypeRange>; |
65 | bool operator==(const KeyTy &key) const { |
66 | if (std::get<0>(t: key) == getInputs()) |
67 | return std::get<1>(t: key) == getResults(); |
68 | return false; |
69 | } |
70 | |
71 | /// Construction. |
72 | static FunctionTypeStorage *construct(TypeStorageAllocator &allocator, |
73 | const KeyTy &key) { |
74 | auto [inputs, results] = key; |
75 | |
76 | // Copy the inputs and results into the bump pointer. |
77 | SmallVector<Type, 16> types; |
78 | types.reserve(N: inputs.size() + results.size()); |
79 | types.append(in_start: inputs.begin(), in_end: inputs.end()); |
80 | types.append(in_start: results.begin(), in_end: results.end()); |
81 | auto typesList = allocator.copyInto(elements: ArrayRef<Type>(types)); |
82 | |
83 | // Initialize the memory using placement new. |
84 | return new (allocator.allocate<FunctionTypeStorage>()) |
85 | FunctionTypeStorage(inputs.size(), results.size(), typesList.data()); |
86 | } |
87 | |
88 | ArrayRef<Type> getInputs() const { |
89 | return ArrayRef<Type>(inputsAndResults, numInputs); |
90 | } |
91 | ArrayRef<Type> getResults() const { |
92 | return ArrayRef<Type>(inputsAndResults + numInputs, numResults); |
93 | } |
94 | |
95 | KeyTy getAsKey() const { return KeyTy(getInputs(), getResults()); } |
96 | |
97 | unsigned numInputs; |
98 | unsigned numResults; |
99 | Type const *inputsAndResults; |
100 | }; |
101 | |
102 | /// A type representing a collection of other types. |
103 | struct TupleTypeStorage final |
104 | : public TypeStorage, |
105 | public llvm::TrailingObjects<TupleTypeStorage, Type> { |
106 | using KeyTy = TypeRange; |
107 | |
108 | TupleTypeStorage(unsigned numTypes) : numElements(numTypes) {} |
109 | |
110 | /// Construction. |
111 | static TupleTypeStorage *construct(TypeStorageAllocator &allocator, |
112 | TypeRange key) { |
113 | // Allocate a new storage instance. |
114 | auto byteSize = TupleTypeStorage::totalSizeToAlloc<Type>(Counts: key.size()); |
115 | auto *rawMem = allocator.allocate(size: byteSize, alignment: alignof(TupleTypeStorage)); |
116 | auto *result = ::new (rawMem) TupleTypeStorage(key.size()); |
117 | |
118 | // Copy in the element types into the trailing storage. |
119 | std::uninitialized_copy(first: key.begin(), last: key.end(), |
120 | result: result->getTrailingObjects<Type>()); |
121 | return result; |
122 | } |
123 | |
124 | bool operator==(const KeyTy &key) const { return key == getTypes(); } |
125 | |
126 | /// Return the number of held types. |
127 | unsigned size() const { return numElements; } |
128 | |
129 | /// Return the held types. |
130 | ArrayRef<Type> getTypes() const { |
131 | return {getTrailingObjects<Type>(), size()}; |
132 | } |
133 | |
134 | KeyTy getAsKey() const { return getTypes(); } |
135 | |
136 | /// The number of tuple elements. |
137 | unsigned numElements; |
138 | }; |
139 | |
140 | /// Checks if the memorySpace has supported Attribute type. |
141 | bool isSupportedMemorySpace(Attribute memorySpace); |
142 | |
143 | /// Wraps deprecated integer memory space to the new Attribute form. |
144 | Attribute wrapIntegerMemorySpace(unsigned memorySpace, MLIRContext *ctx); |
145 | |
146 | /// Replaces default memorySpace (integer == `0`) with empty Attribute. |
147 | Attribute skipDefaultMemorySpace(Attribute memorySpace); |
148 | |
149 | /// [deprecated] Returns the memory space in old raw integer representation. |
150 | /// New `Attribute getMemorySpace()` method should be used instead. |
151 | unsigned getMemorySpaceAsInt(Attribute memorySpace); |
152 | |
153 | } // namespace detail |
154 | } // namespace mlir |
155 | |
156 | #endif // TYPEDETAIL_H_ |
157 | |