289 lines
9.8 KiB
C++
289 lines
9.8 KiB
C++
//===- 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<WalkResult(Location)> 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 <typename T>
|
|
T findInstanceOf() {
|
|
T result = {};
|
|
walk([&](auto loc) {
|
|
if (auto typedLoc = llvm::dyn_cast<T>(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 <typename T, typename UnknownT = UnknownLoc>
|
|
LocationAttr findInstanceOfOrUnknown() {
|
|
if (T result = findInstanceOf<T>())
|
|
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<LocationAttr *>(&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<const AttributeStorage *>(pointer));
|
|
}
|
|
|
|
/// Support llvm style casting.
|
|
static bool classof(Attribute attr) { return llvm::isa<LocationAttr>(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 <typename MetadataT>
|
|
class FusedLocWith : public FusedLoc {
|
|
public:
|
|
using FusedLoc::FusedLoc;
|
|
|
|
/// Return the metadata associated with this fused location.
|
|
MetadataT getMetadata() const {
|
|
return llvm::cast<MetadataT>(FusedLoc::getMetadata());
|
|
}
|
|
|
|
/// Support llvm style casting.
|
|
static bool classof(Attribute attr) {
|
|
auto fusedLoc = llvm::dyn_cast<FusedLoc>(attr);
|
|
return fusedLoc && mlir::isa_and_nonnull<MetadataT>(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 <typename T>
|
|
inline OpaqueLoc OpaqueLoc::get(T underlyingLocation, MLIRContext *context) {
|
|
return get(reinterpret_cast<uintptr_t>(underlyingLocation), TypeID::get<T>(),
|
|
UnknownLoc::get(context));
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// SubElements
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// Enable locations to be introspected as sub-elements.
|
|
template <>
|
|
struct AttrTypeSubElementHandler<Location> {
|
|
static void walk(Location param, AttrTypeImmediateSubElementWalker &walker) {
|
|
walker.walk(param);
|
|
}
|
|
static Location replace(Location param, AttrSubElementReplacements &attrRepls,
|
|
TypeSubElementReplacements &typeRepls) {
|
|
return cast<LocationAttr>(attrRepls.take_front(1)[0]);
|
|
}
|
|
};
|
|
|
|
} // namespace mlir
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// LLVM Utilities
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
namespace llvm {
|
|
|
|
// Type hash just like pointers.
|
|
template <>
|
|
struct DenseMapInfo<mlir::Location> {
|
|
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<mlir::Location> {
|
|
public:
|
|
static inline void *getAsVoidPointer(mlir::Location I) {
|
|
return const_cast<void *>(I.getAsOpaquePointer());
|
|
}
|
|
static inline mlir::Location getFromVoidPointer(void *P) {
|
|
return mlir::Location::getFromOpaquePointer(P);
|
|
}
|
|
static constexpr int NumLowBitsAvailable =
|
|
PointerLikeTypeTraits<mlir::Attribute>::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<mlir::Location> {
|
|
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 <typename To, typename From>
|
|
struct CastInfo<To, From,
|
|
std::enable_if_t<
|
|
std::is_same_v<mlir::Location, std::remove_const_t<From>> ||
|
|
std::is_base_of_v<mlir::Location, From>>>
|
|
: DefaultDoCastIfPossible<To, From, CastInfo<To, From>> {
|
|
|
|
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<To, std::remove_const_t<From>> ||
|
|
isa<To>(static_cast<mlir::LocationAttr>(location));
|
|
}
|
|
|
|
static inline To castFailed() { return To(); }
|
|
|
|
static inline To doCast(mlir::Location location) {
|
|
return To(location->getImpl());
|
|
}
|
|
};
|
|
|
|
} // namespace llvm
|
|
|
|
#endif
|