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

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