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