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 under, and including, the current.
36   WalkResult walk(function_ref<WalkResult(Location)> walkFn);
37 
38   /// Methods for support type inquiry through isa, cast, and dyn_cast.
39   static bool classof(Attribute attr);
40 };
41 
42 //===----------------------------------------------------------------------===//
43 // Location
44 //===----------------------------------------------------------------------===//
45 
46 /// This class defines the main interface for locations in MLIR and acts as a
47 /// non-nullable wrapper around a LocationAttr.
48 class Location {
49 public:
Location(LocationAttr loc)50   Location(LocationAttr loc) : impl(loc) {
51     assert(loc && "location should never be null.");
52   }
Location(const LocationAttr::ImplType * impl)53   Location(const LocationAttr::ImplType *impl) : impl(impl) {
54     assert(impl && "location should never be null.");
55   }
56 
57   /// Return the context this location is uniqued in.
getContext()58   MLIRContext *getContext() const { return impl.getContext(); }
59 
60   /// Access the impl location attribute.
LocationAttr()61   operator LocationAttr() const { return impl; }
62   LocationAttr *operator->() const { return const_cast<LocationAttr *>(&impl); }
63 
64   /// Type casting utilities on the underlying location.
65   template <typename U>
isa()66   bool isa() const {
67     return impl.isa<U>();
68   }
69   template <typename U>
dyn_cast()70   U dyn_cast() const {
71     return impl.dyn_cast<U>();
72   }
73   template <typename U>
cast()74   U cast() const {
75     return impl.cast<U>();
76   }
77 
78   /// Comparison operators.
79   bool operator==(Location rhs) const { return impl == rhs.impl; }
80   bool operator!=(Location rhs) const { return !(*this == rhs); }
81 
82   /// Print the location.
print(raw_ostream & os)83   void print(raw_ostream &os) const { impl.print(os); }
dump()84   void dump() const { impl.dump(); }
85 
86   friend ::llvm::hash_code hash_value(Location arg);
87 
88   /// Methods for supporting PointerLikeTypeTraits.
getAsOpaquePointer()89   const void *getAsOpaquePointer() const { return impl.getAsOpaquePointer(); }
getFromOpaquePointer(const void * pointer)90   static Location getFromOpaquePointer(const void *pointer) {
91     return LocationAttr(reinterpret_cast<const AttributeStorage *>(pointer));
92   }
93 
94 protected:
95   /// The internal backing location attribute.
96   LocationAttr impl;
97 };
98 
99 inline raw_ostream &operator<<(raw_ostream &os, const Location &loc) {
100   loc.print(os);
101   return os;
102 }
103 
104 // Make Location hashable.
hash_value(Location arg)105 inline ::llvm::hash_code hash_value(Location arg) {
106   return hash_value(arg.impl);
107 }
108 
109 } // namespace mlir
110 
111 //===----------------------------------------------------------------------===//
112 // Tablegen Attribute Declarations
113 //===----------------------------------------------------------------------===//
114 
115 #define GET_ATTRDEF_CLASSES
116 #include "mlir/IR/BuiltinLocationAttributes.h.inc"
117 
118 namespace mlir {
119 
120 //===----------------------------------------------------------------------===//
121 // OpaqueLoc
122 //===----------------------------------------------------------------------===//
123 
124 /// Returns an instance of opaque location which contains a given pointer to
125 /// an object. The corresponding MLIR location is set to UnknownLoc.
126 template <typename T>
get(T underlyingLocation,MLIRContext * context)127 inline OpaqueLoc OpaqueLoc::get(T underlyingLocation, MLIRContext *context) {
128   return get(reinterpret_cast<uintptr_t>(underlyingLocation), TypeID::get<T>(),
129              UnknownLoc::get(context));
130 }
131 } // namespace mlir
132 
133 //===----------------------------------------------------------------------===//
134 // LLVM Utilities
135 //===----------------------------------------------------------------------===//
136 
137 namespace llvm {
138 
139 // Type hash just like pointers.
140 template <>
141 struct DenseMapInfo<mlir::Location> {
142   static mlir::Location getEmptyKey() {
143     auto *pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
144     return mlir::Location::getFromOpaquePointer(pointer);
145   }
146   static mlir::Location getTombstoneKey() {
147     auto *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
148     return mlir::Location::getFromOpaquePointer(pointer);
149   }
150   static unsigned getHashValue(mlir::Location val) {
151     return mlir::hash_value(val);
152   }
153   static bool isEqual(mlir::Location LHS, mlir::Location RHS) {
154     return LHS == RHS;
155   }
156 };
157 
158 /// We align LocationStorage by 8, so allow LLVM to steal the low bits.
159 template <>
160 struct PointerLikeTypeTraits<mlir::Location> {
161 public:
162   static inline void *getAsVoidPointer(mlir::Location I) {
163     return const_cast<void *>(I.getAsOpaquePointer());
164   }
165   static inline mlir::Location getFromVoidPointer(void *P) {
166     return mlir::Location::getFromOpaquePointer(P);
167   }
168   static constexpr int NumLowBitsAvailable =
169       PointerLikeTypeTraits<mlir::Attribute>::NumLowBitsAvailable;
170 };
171 
172 } // namespace llvm
173 
174 #endif
175