1 //===- DataLayoutInterfaces.h - Data Layout Interface Decls -----*- 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 // Defines the interfaces for the data layout specification, operations to which 10 // they can be attached, types subject to data layout and dialects containing 11 // data layout entries. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef MLIR_INTERFACES_DATALAYOUTINTERFACES_H 16 #define MLIR_INTERFACES_DATALAYOUTINTERFACES_H 17 18 #include "mlir/IR/DialectInterface.h" 19 #include "mlir/IR/OpDefinition.h" 20 #include "llvm/ADT/DenseMap.h" 21 22 namespace mlir { 23 class DataLayout; 24 class DataLayoutEntryInterface; 25 using DataLayoutEntryKey = llvm::PointerUnion<Type, StringAttr>; 26 // Using explicit SmallVector size because we cannot infer the size from the 27 // forward declaration, and we need the typedef in the actual declaration. 28 using DataLayoutEntryList = llvm::SmallVector<DataLayoutEntryInterface, 4>; 29 using DataLayoutEntryListRef = llvm::ArrayRef<DataLayoutEntryInterface>; 30 class DataLayoutOpInterface; 31 class DataLayoutSpecInterface; 32 class ModuleOp; 33 34 namespace detail { 35 /// Default handler for the type size request. Computes results for built-in 36 /// types and dispatches to the DataLayoutTypeInterface for other types. 37 unsigned getDefaultTypeSize(Type type, const DataLayout &dataLayout, 38 DataLayoutEntryListRef params); 39 40 /// Default handler for the type size in bits request. Computes results for 41 /// built-in types and dispatches to the DataLayoutTypeInterface for other 42 /// types. 43 unsigned getDefaultTypeSizeInBits(Type type, const DataLayout &dataLayout, 44 DataLayoutEntryListRef params); 45 46 /// Default handler for the required alignemnt request. Computes results for 47 /// built-in types and dispatches to the DataLayoutTypeInterface for other 48 /// types. 49 unsigned getDefaultABIAlignment(Type type, const DataLayout &dataLayout, 50 ArrayRef<DataLayoutEntryInterface> params); 51 52 /// Default handler for the preferred alignemnt request. Computes results for 53 /// built-in types and dispatches to the DataLayoutTypeInterface for other 54 /// types. 55 unsigned 56 getDefaultPreferredAlignment(Type type, const DataLayout &dataLayout, 57 ArrayRef<DataLayoutEntryInterface> params); 58 59 /// Given a list of data layout entries, returns a new list containing the 60 /// entries with keys having the given type ID, i.e. belonging to the same type 61 /// class. 62 DataLayoutEntryList filterEntriesForType(DataLayoutEntryListRef entries, 63 TypeID typeID); 64 65 /// Given a list of data layout entries, returns the entry that has the given 66 /// identifier as key, if such an entry exists in the list. 67 DataLayoutEntryInterface 68 filterEntryForIdentifier(DataLayoutEntryListRef entries, StringAttr id); 69 70 /// Verifies that the operation implementing the data layout interface, or a 71 /// module operation, is valid. This calls the verifier of the spec attribute 72 /// and checks if the layout is compatible with specs attached to the enclosing 73 /// operations. 74 LogicalResult verifyDataLayoutOp(Operation *op); 75 76 /// Verifies that a data layout spec is valid. This dispatches to individual 77 /// entry verifiers, and then to the verifiers implemented by the relevant type 78 /// and dialect interfaces for type and identifier keys respectively. 79 LogicalResult verifyDataLayoutSpec(DataLayoutSpecInterface spec, Location loc); 80 } // namespace detail 81 } // namespace mlir 82 83 #include "mlir/Interfaces/DataLayoutAttrInterface.h.inc" 84 #include "mlir/Interfaces/DataLayoutOpInterface.h.inc" 85 #include "mlir/Interfaces/DataLayoutTypeInterface.h.inc" 86 87 namespace mlir { 88 89 //===----------------------------------------------------------------------===// 90 // DataLayoutDialectInterface 91 //===----------------------------------------------------------------------===// 92 93 /// An interface to be implemented by dialects that can have identifiers in the 94 /// data layout specification entries. Provides hooks for verifying the entry 95 /// validity and combining two entries. 96 class DataLayoutDialectInterface 97 : public DialectInterface::Base<DataLayoutDialectInterface> { 98 public: DataLayoutDialectInterface(Dialect * dialect)99 DataLayoutDialectInterface(Dialect *dialect) : Base(dialect) {} 100 101 /// Checks whether the given data layout entry is valid and reports any errors 102 /// at the provided location. Derived classes should override this. verifyEntry(DataLayoutEntryInterface entry,Location loc)103 virtual LogicalResult verifyEntry(DataLayoutEntryInterface entry, 104 Location loc) const { 105 return success(); 106 } 107 108 /// Default implementation of entry combination that combines identical 109 /// entries and returns null otherwise. 110 static DataLayoutEntryInterface defaultCombine(DataLayoutEntryInterface outer,DataLayoutEntryInterface inner)111 defaultCombine(DataLayoutEntryInterface outer, 112 DataLayoutEntryInterface inner) { 113 if (!outer || outer == inner) 114 return inner; 115 return {}; 116 } 117 118 /// Combines two entries with identifiers that belong to this dialect. Returns 119 /// the combined entry or null if the entries are not compatible. Derived 120 /// classes likely need to reimplement this. 121 virtual DataLayoutEntryInterface combine(DataLayoutEntryInterface outer,DataLayoutEntryInterface inner)122 combine(DataLayoutEntryInterface outer, 123 DataLayoutEntryInterface inner) const { 124 return defaultCombine(outer, inner); 125 } 126 }; 127 128 //===----------------------------------------------------------------------===// 129 // DataLayout 130 //===----------------------------------------------------------------------===// 131 132 /// The main mechanism for performing data layout queries. Instances of this 133 /// class can be created for an operation implementing DataLayoutOpInterface. 134 /// Upon construction, a layout spec combining that of the given operation with 135 /// all its ancestors will be computed and used to handle further requests. For 136 /// efficiency, results to all requests will be cached in this object. 137 /// Therefore, if the data layout spec for the scoping operation, or any of the 138 /// enclosing operations, changes, the cache is no longer valid. The user is 139 /// responsible creating a new DataLayout object after any spec change. In debug 140 /// mode, the cache validity is being checked in every request. 141 class DataLayout { 142 public: 143 explicit DataLayout(); 144 explicit DataLayout(DataLayoutOpInterface op); 145 explicit DataLayout(ModuleOp op); 146 147 /// Returns the layout of the closest parent operation carrying layout info. 148 static DataLayout closest(Operation *op); 149 150 /// Returns the size of the given type in the current scope. 151 unsigned getTypeSize(Type t) const; 152 153 /// Returns the size in bits of the given type in the current scope. 154 unsigned getTypeSizeInBits(Type t) const; 155 156 /// Returns the required alignment of the given type in the current scope. 157 unsigned getTypeABIAlignment(Type t) const; 158 159 /// Returns the preferred of the given type in the current scope. 160 unsigned getTypePreferredAlignment(Type t) const; 161 162 private: 163 /// Combined layout spec at the given scope. 164 const DataLayoutSpecInterface originalLayout; 165 166 #if LLVM_ENABLE_ABI_BREAKING_CHECKS 167 /// List of enclosing layout specs. 168 SmallVector<DataLayoutSpecInterface, 2> layoutStack; 169 #endif 170 171 /// Asserts that the cache is still valid. Expensive in debug mode. No-op in 172 /// release mode. 173 void checkValid() const; 174 175 /// Operation defining the scope of requests. 176 Operation *scope; 177 178 /// Caches for individual requests. 179 mutable DenseMap<Type, unsigned> sizes; 180 mutable DenseMap<Type, unsigned> bitsizes; 181 mutable DenseMap<Type, unsigned> abiAlignments; 182 mutable DenseMap<Type, unsigned> preferredAlignments; 183 }; 184 185 } // namespace mlir 186 187 #endif // MLIR_INTERFACES_DATALAYOUTINTERFACES_H 188