//===- Location.h - MLIR Location Classes -----------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // These classes provide the ability to relate MLIR objects back to source // location position information. // //===----------------------------------------------------------------------===// #ifndef MLIR_IR_LOCATION_H #define MLIR_IR_LOCATION_H #include "mlir/IR/Attributes.h" #include "llvm/Support/PointerLikeTypeTraits.h" namespace mlir { class Location; class WalkResult; class UnknownLoc; //===----------------------------------------------------------------------===// // LocationAttr //===----------------------------------------------------------------------===// /// Location objects represent source locations information in MLIR. /// LocationAttr acts as the anchor for all Location based attributes. class LocationAttr : public Attribute { public: using Attribute::Attribute; /// Walk all of the locations nested directly under, and including, the /// current. This means that if a location is nested under a non-location /// attribute, it will *not* be walked by this method. This walk is performed /// in pre-order to get this behavior. WalkResult walk(function_ref walkFn); /// Return an instance of the given location type if one is nested under the /// current location. Returns nullptr if one could not be found. template T findInstanceOf() { T result = {}; walk([&](auto loc) { if (auto typedLoc = llvm::dyn_cast(loc)) { result = typedLoc; return WalkResult::interrupt(); } return WalkResult::advance(); }); return result; } /// Return an instance of the given location type if one is nested under the /// current location else return unknown location. template LocationAttr findInstanceOfOrUnknown() { if (T result = findInstanceOf()) return result; return UnknownT::get(getContext()); } /// Methods for support type inquiry through isa, cast, and dyn_cast. static bool classof(Attribute attr); }; //===----------------------------------------------------------------------===// // Location //===----------------------------------------------------------------------===// /// This class defines the main interface for locations in MLIR and acts as a /// non-nullable wrapper around a LocationAttr. class Location { public: Location(LocationAttr loc) : impl(loc) { assert(loc && "location should never be null."); } Location(const LocationAttr::ImplType *impl) : impl(impl) { assert(impl && "location should never be null."); } /// Return the context this location is uniqued in. MLIRContext *getContext() const { return impl.getContext(); } /// Access the impl location attribute. operator LocationAttr() const { return impl; } LocationAttr *operator->() const { return const_cast(&impl); } /// Comparison operators. bool operator==(Location rhs) const { return impl == rhs.impl; } bool operator!=(Location rhs) const { return !(*this == rhs); } /// Print the location. void print(raw_ostream &os) const { impl.print(os); } void dump() const { impl.dump(); } friend ::llvm::hash_code hash_value(Location arg); /// Methods for supporting PointerLikeTypeTraits. const void *getAsOpaquePointer() const { return impl.getAsOpaquePointer(); } static Location getFromOpaquePointer(const void *pointer) { return LocationAttr(reinterpret_cast(pointer)); } /// Support llvm style casting. static bool classof(Attribute attr) { return llvm::isa(attr); } protected: /// The internal backing location attribute. LocationAttr impl; }; inline raw_ostream &operator<<(raw_ostream &os, const Location &loc) { loc.print(os); return os; } // Make Location hashable. inline ::llvm::hash_code hash_value(Location arg) { return hash_value(arg.impl); } } // namespace mlir //===----------------------------------------------------------------------===// // Tablegen Attribute Declarations //===----------------------------------------------------------------------===// // Forward declaration for class created later. namespace mlir::detail { struct FileLineColRangeAttrStorage; } // namespace mlir::detail #define GET_ATTRDEF_CLASSES #include "mlir/IR/BuiltinLocationAttributes.h.inc" namespace mlir { //===----------------------------------------------------------------------===// // FusedLoc //===----------------------------------------------------------------------===// /// This class represents a fused location whose metadata is known to be an /// instance of the given type. template class FusedLocWith : public FusedLoc { public: using FusedLoc::FusedLoc; /// Return the metadata associated with this fused location. MetadataT getMetadata() const { return llvm::cast(FusedLoc::getMetadata()); } /// Support llvm style casting. static bool classof(Attribute attr) { auto fusedLoc = llvm::dyn_cast(attr); return fusedLoc && mlir::isa_and_nonnull(fusedLoc.getMetadata()); } }; //===----------------------------------------------------------------------===// // FileLineColLoc //===----------------------------------------------------------------------===// /// An instance of this location represents a tuple of file, line number, and /// column number. This is similar to the type of location that you get from /// most source languages. /// /// FileLineColLoc is a view to FileLineColRange with one line and column. class FileLineColLoc : public FileLineColRange { public: using FileLineColRange::FileLineColRange; static FileLineColLoc get(StringAttr filename, unsigned line, unsigned column); static FileLineColLoc get(MLIRContext *context, StringRef fileName, unsigned line, unsigned column); StringAttr getFilename() const; unsigned getLine() const; unsigned getColumn() const; }; /// Returns true iff the given location is a FileLineColRange with exactly one /// line and column. bool isStrictFileLineColLoc(Location loc); //===----------------------------------------------------------------------===// // OpaqueLoc //===----------------------------------------------------------------------===// /// Returns an instance of opaque location which contains a given pointer to /// an object. The corresponding MLIR location is set to UnknownLoc. template inline OpaqueLoc OpaqueLoc::get(T underlyingLocation, MLIRContext *context) { return get(reinterpret_cast(underlyingLocation), TypeID::get(), UnknownLoc::get(context)); } //===----------------------------------------------------------------------===// // SubElements //===----------------------------------------------------------------------===// /// Enable locations to be introspected as sub-elements. template <> struct AttrTypeSubElementHandler { static void walk(Location param, AttrTypeImmediateSubElementWalker &walker) { walker.walk(param); } static Location replace(Location param, AttrSubElementReplacements &attrRepls, TypeSubElementReplacements &typeRepls) { return cast(attrRepls.take_front(1)[0]); } }; } // namespace mlir //===----------------------------------------------------------------------===// // LLVM Utilities //===----------------------------------------------------------------------===// namespace llvm { // Type hash just like pointers. template <> struct DenseMapInfo { static unsigned getHashValue(mlir::Location val) { return mlir::hash_value(val); } static bool isEqual(mlir::Location LHS, mlir::Location RHS) { return LHS == RHS; } }; /// We align LocationStorage by 8, so allow LLVM to steal the low bits. template <> struct PointerLikeTypeTraits { public: static inline void *getAsVoidPointer(mlir::Location I) { return const_cast(I.getAsOpaquePointer()); } static inline mlir::Location getFromVoidPointer(void *P) { return mlir::Location::getFromOpaquePointer(P); } static constexpr int NumLowBitsAvailable = PointerLikeTypeTraits::NumLowBitsAvailable; }; /// The constructors in mlir::Location ensure that the class is a non-nullable /// wrapper around mlir::LocationAttr. Override default behavior and always /// return true for isPresent(). template <> struct ValueIsPresent { using UnwrappedType = mlir::Location; static inline bool isPresent(const mlir::Location &location) { return true; } }; /// Add support for llvm style casts. We provide a cast between To and From if /// From is mlir::Location or derives from it. template struct CastInfo> || std::is_base_of_v>> : DefaultDoCastIfPossible> { static inline bool isPossible(mlir::Location location) { /// Return a constant true instead of a dynamic true when casting to self or /// up the hierarchy. Additionally, all casting info is deferred to the /// wrapped mlir::LocationAttr instance stored in mlir::Location. return std::is_same_v> || isa(static_cast(location)); } static inline To castFailed() { return To(); } static inline To doCast(mlir::Location location) { return To(location->getImpl()); } }; } // namespace llvm #endif