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::tuple<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(std::get<0>(key), std::get<1>(key)); 48 } 49 getAsKeyIntegerTypeStorage50 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 { FunctionTypeStorageFunctionTypeStorage58 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>(key) == getInputs()) 67 return std::get<1>(key) == getResults(); 68 return false; 69 } 70 71 /// Construction. constructFunctionTypeStorage72 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(inputs.size() + results.size()); 79 types.append(inputs.begin(), inputs.end()); 80 types.append(results.begin(), results.end()); 81 auto typesList = allocator.copyInto(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 getInputsFunctionTypeStorage88 ArrayRef<Type> getInputs() const { 89 return ArrayRef<Type>(inputsAndResults, numInputs); 90 } getResultsFunctionTypeStorage91 ArrayRef<Type> getResults() const { 92 return ArrayRef<Type>(inputsAndResults + numInputs, numResults); 93 } 94 getAsKeyFunctionTypeStorage95 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 TupleTypeStoragefinal108 TupleTypeStorage(unsigned numTypes) : numElements(numTypes) {} 109 110 /// Construction. constructfinal111 static TupleTypeStorage *construct(TypeStorageAllocator &allocator, 112 TypeRange key) { 113 // Allocate a new storage instance. 114 auto byteSize = TupleTypeStorage::totalSizeToAlloc<Type>(key.size()); 115 auto *rawMem = allocator.allocate(byteSize, 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(key.begin(), key.end(), 120 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. sizefinal127 unsigned size() const { return numElements; } 128 129 /// Return the held types. getTypesfinal130 ArrayRef<Type> getTypes() const { 131 return {getTrailingObjects<Type>(), size()}; 132 } 133 getAsKeyfinal134 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