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 {
IntegerTypeStorageIntegerTypeStorage29   IntegerTypeStorage(unsigned width,
30                      IntegerType::SignednessSemantics signedness)
31       : width(width), signedness(signedness) {}
32 
33   /// The hash key used for uniquing.
34   using KeyTy = std::pair<unsigned, IntegerType::SignednessSemantics>;
35 
hashKeyIntegerTypeStorage36   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 
constructIntegerTypeStorage44   static IntegerTypeStorage *construct(TypeStorageAllocator &allocator,
45                                        KeyTy key) {
46     return new (allocator.allocate<IntegerTypeStorage>())
47         IntegerTypeStorage(key.first, key.second);
48   }
49 
50   unsigned width : 30;
51   IntegerType::SignednessSemantics signedness : 2;
52 };
53 
54 /// Function Type Storage and Uniquing.
55 struct FunctionTypeStorage : public TypeStorage {
FunctionTypeStorageFunctionTypeStorage56   FunctionTypeStorage(unsigned numInputs, unsigned numResults,
57                       Type const *inputsAndResults)
58       : numInputs(numInputs), numResults(numResults),
59         inputsAndResults(inputsAndResults) {}
60 
61   /// The hash key used for uniquing.
62   using KeyTy = std::pair<TypeRange, TypeRange>;
63   bool operator==(const KeyTy &key) const {
64     if (std::get<0>(key) == getInputs())
65       return std::get<1>(key) == getResults();
66     return false;
67   }
68 
69   /// Construction.
constructFunctionTypeStorage70   static FunctionTypeStorage *construct(TypeStorageAllocator &allocator,
71                                         const KeyTy &key) {
72     TypeRange inputs = key.first, results = key.second;
73 
74     // Copy the inputs and results into the bump pointer.
75     SmallVector<Type, 16> types;
76     types.reserve(inputs.size() + results.size());
77     types.append(inputs.begin(), inputs.end());
78     types.append(results.begin(), results.end());
79     auto typesList = allocator.copyInto(ArrayRef<Type>(types));
80 
81     // Initialize the memory using placement new.
82     return new (allocator.allocate<FunctionTypeStorage>())
83         FunctionTypeStorage(inputs.size(), results.size(), typesList.data());
84   }
85 
getInputsFunctionTypeStorage86   ArrayRef<Type> getInputs() const {
87     return ArrayRef<Type>(inputsAndResults, numInputs);
88   }
getResultsFunctionTypeStorage89   ArrayRef<Type> getResults() const {
90     return ArrayRef<Type>(inputsAndResults + numInputs, numResults);
91   }
92 
93   unsigned numInputs;
94   unsigned numResults;
95   Type const *inputsAndResults;
96 };
97 
98 /// A type representing a collection of other types.
99 struct TupleTypeStorage final
100     : public TypeStorage,
101       public llvm::TrailingObjects<TupleTypeStorage, Type> {
102   using KeyTy = TypeRange;
103 
TupleTypeStoragefinal104   TupleTypeStorage(unsigned numTypes) : numElements(numTypes) {}
105 
106   /// Construction.
constructfinal107   static TupleTypeStorage *construct(TypeStorageAllocator &allocator,
108                                      TypeRange key) {
109     // Allocate a new storage instance.
110     auto byteSize = TupleTypeStorage::totalSizeToAlloc<Type>(key.size());
111     auto *rawMem = allocator.allocate(byteSize, alignof(TupleTypeStorage));
112     auto *result = ::new (rawMem) TupleTypeStorage(key.size());
113 
114     // Copy in the element types into the trailing storage.
115     std::uninitialized_copy(key.begin(), key.end(),
116                             result->getTrailingObjects<Type>());
117     return result;
118   }
119 
120   bool operator==(const KeyTy &key) const { return key == getTypes(); }
121 
122   /// Return the number of held types.
sizefinal123   unsigned size() const { return numElements; }
124 
125   /// Return the held types.
getTypesfinal126   ArrayRef<Type> getTypes() const {
127     return {getTrailingObjects<Type>(), size()};
128   }
129 
130   /// The number of tuple elements.
131   unsigned numElements;
132 };
133 
134 /// Checks if the memorySpace has supported Attribute type.
135 bool isSupportedMemorySpace(Attribute memorySpace);
136 
137 /// Wraps deprecated integer memory space to the new Attribute form.
138 Attribute wrapIntegerMemorySpace(unsigned memorySpace, MLIRContext *ctx);
139 
140 /// Replaces default memorySpace (integer == `0`) with empty Attribute.
141 Attribute skipDefaultMemorySpace(Attribute memorySpace);
142 
143 /// [deprecated] Returns the memory space in old raw integer representation.
144 /// New `Attribute getMemorySpace()` method should be used instead.
145 unsigned getMemorySpaceAsInt(Attribute memorySpace);
146 
147 } // namespace detail
148 } // namespace mlir
149 
150 #endif // TYPEDETAIL_H_
151