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

source code of mlir/include/mlir/IR/Location.h