1 //===- Location.h - MLIR Location Classes -----------------------*- C++ -*-===//
2 //
3 // Part of the MLIR 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
19 namespace mlir {
20
21 class Attribute;
22 class MLIRContext;
23 class Identifier;
24
25 namespace detail {
26
27 struct CallSiteLocationStorage;
28 struct FileLineColLocationStorage;
29 struct FusedLocationStorage;
30 struct LocationStorage;
31 struct NameLocationStorage;
32 struct OpaqueLocationStorage;
33 struct UnknownLocationStorage;
34
35 } // namespace detail
36
37 /// Location objects represent source locations information in MLIR.
38 /// LocationAttr acts as the anchor for all Location based attributes.
39 class LocationAttr : public Attribute {
40 public:
41 using Attribute::Attribute;
42
43 /// Methods for support type inquiry through isa, cast, and dyn_cast.
classof(Attribute attr)44 static bool classof(Attribute attr) {
45 return attr.getKind() >= StandardAttributes::FIRST_LOCATION_ATTR &&
46 attr.getKind() <= StandardAttributes::LAST_LOCATION_ATTR;
47 }
48 };
49
50 /// This class defines the main interface for locations in MLIR and acts as a
51 /// non-nullable wrapper around a LocationAttr.
52 class Location {
53 public:
Location(LocationAttr loc)54 Location(LocationAttr loc) : impl(loc) {
55 assert(loc && "location should never be null.");
56 }
57
58 /// Access the impl location attribute.
LocationAttr()59 operator LocationAttr() const { return impl; }
60 LocationAttr *operator->() const { return const_cast<LocationAttr *>(&impl); }
61
62 /// Type casting utilities on the underlying location.
isa()63 template <typename U> bool isa() const { return impl.isa<U>(); }
dyn_cast()64 template <typename U> U dyn_cast() const { return impl.dyn_cast<U>(); }
cast()65 template <typename U> U cast() const { return impl.cast<U>(); }
66
67 /// Comparison operators.
68 bool operator==(Location rhs) const { return impl == rhs.impl; }
69 bool operator!=(Location rhs) const { return !(*this == rhs); }
70
71 /// Print the location.
print(raw_ostream & os)72 void print(raw_ostream &os) const { impl.print(os); }
dump()73 void dump() const { impl.dump(); }
74
75 friend ::llvm::hash_code hash_value(Location arg);
76
77 /// Methods for supporting PointerLikeTypeTraits.
getAsOpaquePointer()78 const void *getAsOpaquePointer() const { return impl.getAsOpaquePointer(); }
getFromOpaquePointer(const void * pointer)79 static Location getFromOpaquePointer(const void *pointer) {
80 return LocationAttr(reinterpret_cast<const AttributeStorage *>(pointer));
81 }
82
83 protected:
84 /// The internal backing location attribute.
85 LocationAttr impl;
86 };
87
88 inline raw_ostream &operator<<(raw_ostream &os, const Location &loc) {
89 loc.print(os);
90 return os;
91 }
92
93 /// Represents a location as call site. "callee" is the concrete location
94 /// (Unknown/NameLocation/FileLineColLoc/OpaqueLoc) and "caller" points to the
95 /// caller's location (another CallLocation or a concrete location). Multiple
96 /// CallSiteLocs can be chained to form a call stack.
97 class CallSiteLoc
98 : public Attribute::AttrBase<CallSiteLoc, LocationAttr,
99 detail::CallSiteLocationStorage> {
100 public:
101 using Base::Base;
102
103 /// Return a uniqued call location object.
104 static Location get(Location callee, Location caller);
105
106 /// Return a call site location which represents a name reference in one line
107 /// or a stack of frames. The input frames are ordered from innermost to
108 /// outermost.
109 static Location get(Location name, ArrayRef<Location> frames);
110
111 /// The concrete location information this object presents.
112 Location getCallee() const;
113
114 /// The caller's location.
115 Location getCaller() const;
116
117 /// Methods for support type inquiry through isa, cast, and dyn_cast.
kindof(unsigned kind)118 static bool kindof(unsigned kind) {
119 return kind == StandardAttributes::CallSiteLocation;
120 }
121 };
122
123 /// Represents a location derived from a file/line/column location. The column
124 /// and line may be zero to represent unknown column and/or unknown line/column
125 /// information.
126 class FileLineColLoc
127 : public Attribute::AttrBase<FileLineColLoc, LocationAttr,
128 detail::FileLineColLocationStorage> {
129 public:
130 using Base::Base;
131
132 /// Return a uniqued FileLineCol location object.
133 static Location get(Identifier filename, unsigned line, unsigned column,
134 MLIRContext *context);
135 static Location get(StringRef filename, unsigned line, unsigned column,
136 MLIRContext *context);
137
138 StringRef getFilename() const;
139
140 unsigned getLine() const;
141 unsigned getColumn() const;
142
143 /// Methods for support type inquiry through isa, cast, and dyn_cast.
kindof(unsigned kind)144 static bool kindof(unsigned kind) {
145 return kind == StandardAttributes::FileLineColLocation;
146 }
147 };
148
149 /// Represents a value composed of multiple source constructs, with an optional
150 /// metadata attribute.
151 class FusedLoc : public Attribute::AttrBase<FusedLoc, LocationAttr,
152 detail::FusedLocationStorage> {
153 public:
154 using Base::Base;
155
156 /// Return a uniqued Fused Location object. The first location in the list
157 /// will get precedence during diagnostic emission, with the rest being
158 /// displayed as supplementary "fused from here" style notes.
159 static Location get(ArrayRef<Location> locs, Attribute metadata,
160 MLIRContext *context);
get(ArrayRef<Location> locs,MLIRContext * context)161 static Location get(ArrayRef<Location> locs, MLIRContext *context) {
162 return get(locs, Attribute(), context);
163 }
164
165 ArrayRef<Location> getLocations() const;
166
167 /// Returns the optional metadata attached to this fused location. Given that
168 /// it is optional, the return value may be a null node.
169 Attribute getMetadata() const;
170
171 /// Methods for support type inquiry through isa, cast, and dyn_cast.
kindof(unsigned kind)172 static bool kindof(unsigned kind) {
173 return kind == StandardAttributes::FusedLocation;
174 }
175 };
176
177 /// Represents an identity name attached to a child location.
178 class NameLoc : public Attribute::AttrBase<NameLoc, LocationAttr,
179 detail::NameLocationStorage> {
180 public:
181 using Base::Base;
182
183 /// Return a uniqued name location object. The child location must not be
184 /// another NameLoc.
185 static Location get(Identifier name, Location child);
186
187 /// Return a uniqued name location object with an unknown child.
188 static Location get(Identifier name, MLIRContext *context);
189
190 /// Return the name identifier.
191 Identifier getName() const;
192
193 /// Return the child location.
194 Location getChildLoc() const;
195
196 /// Methods for support type inquiry through isa, cast, and dyn_cast.
kindof(unsigned kind)197 static bool kindof(unsigned kind) {
198 return kind == StandardAttributes::NameLocation;
199 }
200 };
201
202 /// Represents an unknown location. This is always a singleton for a given
203 /// MLIRContext.
204 class UnknownLoc : public Attribute::AttrBase<UnknownLoc, LocationAttr> {
205 public:
206 using Base::Base;
207
208 /// Get an instance of the UnknownLoc.
209 static Location get(MLIRContext *context);
210
211 /// Methods for support type inquiry through isa, cast, and dyn_cast.
kindof(unsigned kind)212 static bool kindof(unsigned kind) {
213 return kind == StandardAttributes::UnknownLocation;
214 }
215 };
216
217 /// Represents a location that is external to MLIR. Contains a pointer to some
218 /// data structure and an optional location that can be used if the first one is
219 /// not suitable. Since it contains an external structure, only optional
220 /// location is used during serialization.
221 /// The class also provides a number of methods for making type-safe casts
222 /// between a pointer to an object and opaque location.
223 class OpaqueLoc : public Attribute::AttrBase<OpaqueLoc, LocationAttr,
224 detail::OpaqueLocationStorage> {
225 public:
226 using Base::Base;
227
228 /// Returns an instance of opaque location which contains a given pointer to
229 /// an object. The corresponding MLIR location is set to UnknownLoc.
230 template <typename T>
get(T underlyingLocation,MLIRContext * context)231 static Location get(T underlyingLocation, MLIRContext *context) {
232 return get(reinterpret_cast<uintptr_t>(underlyingLocation),
233 ClassID::getID<T>(), UnknownLoc::get(context));
234 }
235
236 /// Returns an instance of opaque location which contains a given pointer to
237 /// an object and an additional MLIR location.
238 template <typename T>
get(T underlyingLocation,Location fallbackLocation)239 static Location get(T underlyingLocation, Location fallbackLocation) {
240 return get(reinterpret_cast<uintptr_t>(underlyingLocation),
241 ClassID::getID<T>(), fallbackLocation);
242 }
243
244 /// Returns a pointer to some data structure that opaque location stores.
getUnderlyingLocation(Location location)245 template <typename T> static T getUnderlyingLocation(Location location) {
246 assert(isa<T>(location));
247 return reinterpret_cast<T>(
248 location.cast<mlir::OpaqueLoc>().getUnderlyingLocation());
249 }
250
251 /// Returns a pointer to some data structure that opaque location stores.
252 /// Returns nullptr if provided location is not opaque location or if it
253 /// contains a pointer of different type.
254 template <typename T>
getUnderlyingLocationOrNull(Location location)255 static T getUnderlyingLocationOrNull(Location location) {
256 return isa<T>(location)
257 ? reinterpret_cast<T>(
258 location.cast<mlir::OpaqueLoc>().getUnderlyingLocation())
259 : T(nullptr);
260 }
261
262 /// Checks whether provided location is opaque location and contains a pointer
263 /// to an object of particular type.
isa(Location location)264 template <typename T> static bool isa(Location location) {
265 auto opaque_loc = location.dyn_cast<OpaqueLoc>();
266 return opaque_loc && opaque_loc.getClassId() == ClassID::getID<T>();
267 }
268
269 /// Returns a pointer to the corresponding object.
270 uintptr_t getUnderlyingLocation() const;
271
272 /// Returns a ClassID* that represents the underlying objects c++ type.
273 ClassID *getClassId() const;
274
275 /// Returns a fallback location.
276 Location getFallbackLocation() const;
277
278 /// Methods for support type inquiry through isa, cast, and dyn_cast.
kindof(unsigned kind)279 static bool kindof(unsigned kind) {
280 return kind == StandardAttributes::OpaqueLocation;
281 }
282
283 private:
284 static Location get(uintptr_t underlyingLocation, ClassID *classID,
285 Location fallbackLocation);
286 };
287
288 // Make Location hashable.
hash_value(Location arg)289 inline ::llvm::hash_code hash_value(Location arg) {
290 return hash_value(arg.impl);
291 }
292
293 } // end namespace mlir
294
295 namespace llvm {
296
297 // Type hash just like pointers.
298 template <> struct DenseMapInfo<mlir::Location> {
299 static mlir::Location getEmptyKey() {
300 auto pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
301 return mlir::Location::getFromOpaquePointer(pointer);
302 }
303 static mlir::Location getTombstoneKey() {
304 auto pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
305 return mlir::Location::getFromOpaquePointer(pointer);
306 }
307 static unsigned getHashValue(mlir::Location val) {
308 return mlir::hash_value(val);
309 }
310 static bool isEqual(mlir::Location LHS, mlir::Location RHS) {
311 return LHS == RHS;
312 }
313 };
314
315 /// We align LocationStorage by 8, so allow LLVM to steal the low bits.
316 template <> struct PointerLikeTypeTraits<mlir::Location> {
317 public:
318 static inline void *getAsVoidPointer(mlir::Location I) {
319 return const_cast<void *>(I.getAsOpaquePointer());
320 }
321 static inline mlir::Location getFromVoidPointer(void *P) {
322 return mlir::Location::getFromOpaquePointer(P);
323 }
324 enum {
325 NumLowBitsAvailable =
326 PointerLikeTypeTraits<mlir::Attribute>::NumLowBitsAvailable
327 };
328 };
329
330 } // namespace llvm
331
332 #endif
333