1 //===- Location.h - MLIR Location Classes -----------------------*- 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 // These classes provide the ability to relate MLIR objects back to source 10 // location position information. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef MLIR_IR_LOCATION_H 15 #define MLIR_IR_LOCATION_H 16 17 #include "mlir/IR/Attributes.h" 18 #include "llvm/Support/PointerLikeTypeTraits.h" 19 20 namespace mlir { 21 22 class Location; 23 class WalkResult; 24 25 //===----------------------------------------------------------------------===// 26 // LocationAttr 27 //===----------------------------------------------------------------------===// 28 29 /// Location objects represent source locations information in MLIR. 30 /// LocationAttr acts as the anchor for all Location based attributes. 31 class LocationAttr : public Attribute { 32 public: 33 using Attribute::Attribute; 34 35 /// Walk all of the locations nested directly under, and including, the 36 /// current. This means that if a location is nested under a non-location 37 /// attribute, it will *not* be walked by this method. This walk is performed 38 /// in pre-order to get this behavior. 39 WalkResult walk(function_ref<WalkResult(Location)> walkFn); 40 41 /// Return an instance of the given location type if one is nested under the 42 /// current location. Returns nullptr if one could not be found. 43 template <typename T> 44 T findInstanceOf() { 45 T result = {}; 46 walk([&](auto loc) { 47 if (auto typedLoc = llvm::dyn_cast<T>(loc)) { 48 result = typedLoc; 49 return WalkResult::interrupt(); 50 } 51 return WalkResult::advance(); 52 }); 53 return result; 54 } 55 56 /// Methods for support type inquiry through isa, cast, and dyn_cast. 57 static bool classof(Attribute attr); 58 }; 59 60 //===----------------------------------------------------------------------===// 61 // Location 62 //===----------------------------------------------------------------------===// 63 64 /// This class defines the main interface for locations in MLIR and acts as a 65 /// non-nullable wrapper around a LocationAttr. 66 class Location { 67 public: 68 Location(LocationAttr loc) : impl(loc) { 69 assert(loc && "location should never be null."); 70 } 71 Location(const LocationAttr::ImplType *impl) : impl(impl) { 72 assert(impl && "location should never be null."); 73 } 74 75 /// Return the context this location is uniqued in. 76 MLIRContext *getContext() const { return impl.getContext(); } 77 78 /// Access the impl location attribute. 79 operator LocationAttr() const { return impl; } 80 LocationAttr *operator->() const { return const_cast<LocationAttr *>(&impl); } 81 82 /// Type casting utilities on the underlying location. 83 template <typename U> 84 [[deprecated("Use mlir::isa<U>() instead")]] 85 bool isa() const { 86 return llvm::isa<U>(*this); 87 } 88 template <typename U> 89 [[deprecated("Use mlir::dyn_cast<U>() instead")]] 90 U dyn_cast() const { 91 return llvm::dyn_cast<U>(*this); 92 } 93 template <typename U> 94 [[deprecated("Use mlir::cast<U>() instead")]] 95 U cast() const { 96 return llvm::cast<U>(*this); 97 } 98 99 /// Comparison operators. 100 bool operator==(Location rhs) const { return impl == rhs.impl; } 101 bool operator!=(Location rhs) const { return !(*this == rhs); } 102 103 /// Print the location. 104 void print(raw_ostream &os) const { impl.print(os); } 105 void dump() const { impl.dump(); } 106 107 friend ::llvm::hash_code hash_value(Location arg); 108 109 /// Methods for supporting PointerLikeTypeTraits. 110 const void *getAsOpaquePointer() const { return impl.getAsOpaquePointer(); } 111 static Location getFromOpaquePointer(const void *pointer) { 112 return LocationAttr(reinterpret_cast<const AttributeStorage *>(pointer)); 113 } 114 115 /// Support llvm style casting. 116 static bool classof(Attribute attr) { return llvm::isa<LocationAttr>(attr); } 117 118 protected: 119 /// The internal backing location attribute. 120 LocationAttr impl; 121 }; 122 123 inline raw_ostream &operator<<(raw_ostream &os, const Location &loc) { 124 loc.print(os); 125 return os; 126 } 127 128 // Make Location hashable. 129 inline ::llvm::hash_code hash_value(Location arg) { 130 return hash_value(arg.impl); 131 } 132 133 } // namespace mlir 134 135 //===----------------------------------------------------------------------===// 136 // Tablegen Attribute Declarations 137 //===----------------------------------------------------------------------===// 138 139 // Forward declaration for class created later. 140 namespace mlir::detail { 141 struct FileLineColRangeAttrStorage; 142 } // namespace mlir::detail 143 144 #define GET_ATTRDEF_CLASSES 145 #include "mlir/IR/BuiltinLocationAttributes.h.inc" 146 147 namespace mlir { 148 149 //===----------------------------------------------------------------------===// 150 // FusedLoc 151 //===----------------------------------------------------------------------===// 152 153 /// This class represents a fused location whose metadata is known to be an 154 /// instance of the given type. 155 template <typename MetadataT> 156 class FusedLocWith : public FusedLoc { 157 public: 158 using FusedLoc::FusedLoc; 159 160 /// Return the metadata associated with this fused location. 161 MetadataT getMetadata() const { 162 return llvm::cast<MetadataT>(FusedLoc::getMetadata()); 163 } 164 165 /// Support llvm style casting. 166 static bool classof(Attribute attr) { 167 auto fusedLoc = llvm::dyn_cast<FusedLoc>(attr); 168 return fusedLoc && mlir::isa_and_nonnull<MetadataT>(fusedLoc.getMetadata()); 169 } 170 }; 171 172 //===----------------------------------------------------------------------===// 173 // FileLineColLoc 174 //===----------------------------------------------------------------------===// 175 176 /// An instance of this location represents a tuple of file, line number, and 177 /// column number. This is similar to the type of location that you get from 178 /// most source languages. 179 /// 180 /// FileLineColLoc is a view to FileLineColRange with one line and column. 181 class FileLineColLoc : public FileLineColRange { 182 public: 183 using FileLineColRange::FileLineColRange; 184 185 static FileLineColLoc get(StringAttr filename, unsigned line, 186 unsigned column); 187 static FileLineColLoc get(MLIRContext *context, StringRef fileName, 188 unsigned line, unsigned column); 189 190 StringAttr getFilename() const; 191 unsigned getLine() const; 192 unsigned getColumn() const; 193 }; 194 195 /// Returns true iff the given location is a FileLineColRange with exactly one 196 /// line and column. 197 bool isStrictFileLineColLoc(Location loc); 198 199 //===----------------------------------------------------------------------===// 200 // OpaqueLoc 201 //===----------------------------------------------------------------------===// 202 203 /// Returns an instance of opaque location which contains a given pointer to 204 /// an object. The corresponding MLIR location is set to UnknownLoc. 205 template <typename T> 206 inline OpaqueLoc OpaqueLoc::get(T underlyingLocation, MLIRContext *context) { 207 return get(reinterpret_cast<uintptr_t>(underlyingLocation), TypeID::get<T>(), 208 UnknownLoc::get(context)); 209 } 210 211 //===----------------------------------------------------------------------===// 212 // SubElements 213 //===----------------------------------------------------------------------===// 214 215 /// Enable locations to be introspected as sub-elements. 216 template <> 217 struct AttrTypeSubElementHandler<Location> { 218 static void walk(Location param, AttrTypeImmediateSubElementWalker &walker) { 219 walker.walk(param); 220 } 221 static Location replace(Location param, AttrSubElementReplacements &attrRepls, 222 TypeSubElementReplacements &typeRepls) { 223 return cast<LocationAttr>(attrRepls.take_front(1)[0]); 224 } 225 }; 226 227 } // namespace mlir 228 229 //===----------------------------------------------------------------------===// 230 // LLVM Utilities 231 //===----------------------------------------------------------------------===// 232 233 namespace llvm { 234 235 // Type hash just like pointers. 236 template <> 237 struct DenseMapInfo<mlir::Location> { 238 static mlir::Location getEmptyKey() { 239 auto *pointer = llvm::DenseMapInfo<void *>::getEmptyKey(); 240 return mlir::Location::getFromOpaquePointer(pointer); 241 } 242 static mlir::Location getTombstoneKey() { 243 auto *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey(); 244 return mlir::Location::getFromOpaquePointer(pointer); 245 } 246 static unsigned getHashValue(mlir::Location val) { 247 return mlir::hash_value(val); 248 } 249 static bool isEqual(mlir::Location LHS, mlir::Location RHS) { 250 return LHS == RHS; 251 } 252 }; 253 254 /// We align LocationStorage by 8, so allow LLVM to steal the low bits. 255 template <> 256 struct PointerLikeTypeTraits<mlir::Location> { 257 public: 258 static inline void *getAsVoidPointer(mlir::Location I) { 259 return const_cast<void *>(I.getAsOpaquePointer()); 260 } 261 static inline mlir::Location getFromVoidPointer(void *P) { 262 return mlir::Location::getFromOpaquePointer(P); 263 } 264 static constexpr int NumLowBitsAvailable = 265 PointerLikeTypeTraits<mlir::Attribute>::NumLowBitsAvailable; 266 }; 267 268 /// The constructors in mlir::Location ensure that the class is a non-nullable 269 /// wrapper around mlir::LocationAttr. Override default behavior and always 270 /// return true for isPresent(). 271 template <> 272 struct ValueIsPresent<mlir::Location> { 273 using UnwrappedType = mlir::Location; 274 static inline bool isPresent(const mlir::Location &location) { return true; } 275 }; 276 277 /// Add support for llvm style casts. We provide a cast between To and From if 278 /// From is mlir::Location or derives from it. 279 template <typename To, typename From> 280 struct CastInfo<To, From, 281 std::enable_if_t< 282 std::is_same_v<mlir::Location, std::remove_const_t<From>> || 283 std::is_base_of_v<mlir::Location, From>>> 284 : DefaultDoCastIfPossible<To, From, CastInfo<To, From>> { 285 286 static inline bool isPossible(mlir::Location location) { 287 /// Return a constant true instead of a dynamic true when casting to self or 288 /// up the hierarchy. Additionally, all casting info is deferred to the 289 /// wrapped mlir::LocationAttr instance stored in mlir::Location. 290 return std::is_same_v<To, std::remove_const_t<From>> || 291 isa<To>(static_cast<mlir::LocationAttr>(location)); 292 } 293 294 static inline To castFailed() { return To(); } 295 296 static inline To doCast(mlir::Location location) { 297 return To(location->getImpl()); 298 } 299 }; 300 301 } // namespace llvm 302 303 #endif 304