//===- Location.cpp - MLIR Location Classes -------------------------------===// // // 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 // //===----------------------------------------------------------------------===// #include "mlir/IR/Location.h" #include "mlir/IR/AttributeSupport.h" #include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/BuiltinDialect.h" #include "mlir/IR/MLIRContext.h" #include "mlir/IR/Visitors.h" #include "mlir/Support/LLVM.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetVector.h" #include "llvm/Support/Casting.h" #include "llvm/Support/TrailingObjects.h" #include #include #include using namespace mlir; using namespace mlir::detail; namespace mlir::detail { struct FileLineColRangeAttrStorage final : public ::mlir::AttributeStorage, private llvm::TrailingObjects { friend llvm::TrailingObjects; using PointerPair = llvm::PointerIntPair; using KeyTy = std::tuple>; FileLineColRangeAttrStorage(StringAttr filename, int numLocs) : filenameAndTrailing(filename, numLocs) {} static FileLineColRangeAttrStorage * construct(::mlir::AttributeStorageAllocator &allocator, KeyTy &&tblgenKey) { auto numInArray = std::get<1>(tblgenKey).size(); // Note: Considered asserting that numInArray is at least 1, but this // is not needed in memory or in printed form. This should very rarely be // 0 here as that means a NamedLoc would have been more efficient. But this // does allow for location with just a file, and also having the interface // be more uniform. auto locEnc = numInArray == 0 ? 1 : numInArray; // Allocate a new storage instance. auto byteSize = FileLineColRangeAttrStorage::totalSizeToAlloc(locEnc - 1); auto *rawMem = allocator.allocate(byteSize, alignof(FileLineColRangeAttrStorage)); auto *result = ::new (rawMem) FileLineColRangeAttrStorage( std::move(std::get<0>(tblgenKey)), locEnc - 1); if (numInArray > 0) { ArrayRef elements = std::get<1>(tblgenKey); result->startLine = elements[0]; // Copy in the element types into the trailing storage. llvm::uninitialized_copy(elements.drop_front(), result->getTrailingObjects()); } return result; } // Return the number of held types. unsigned size() const { return filenameAndTrailing.getInt() + 1; } bool operator==(const KeyTy &tblgenKey) const { return (filenameAndTrailing.getPointer() == std::get<0>(tblgenKey)) && (size() == std::get<1>(tblgenKey).size()) && (startLine == std::get<1>(tblgenKey)[0]) && (getTrailingObjects(size() - 1) == std::get<1>(tblgenKey).drop_front()); } unsigned getLineCols(unsigned index) const { return getTrailingObjects()[index - 1]; } unsigned getStartLine() const { return startLine; } unsigned getStartColumn() const { if (size() <= 1) return 0; return getLineCols(1); } unsigned getEndColumn() const { if (size() <= 2) return getStartColumn(); return getLineCols(2); } unsigned getEndLine() const { if (size() <= 3) return getStartLine(); return getLineCols(3); } static ::llvm::hash_code hashKey(const KeyTy &tblgenKey) { return ::llvm::hash_combine(std::get<0>(tblgenKey), std::get<1>(tblgenKey)); } // Supports // - 0 (file:line) // - 1 (file:line:col) // - 2 (file:line:start_col to file:line:end_col) and // - 3 (file:start_line:start_col to file:end_line:end_col) llvm::PointerIntPair filenameAndTrailing; unsigned startLine = 0; }; } // namespace mlir::detail //===----------------------------------------------------------------------===// /// Tablegen Attribute Definitions //===----------------------------------------------------------------------===// #define GET_ATTRDEF_CLASSES #include "mlir/IR/BuiltinLocationAttributes.cpp.inc" //===----------------------------------------------------------------------===// // LocationAttr //===----------------------------------------------------------------------===// WalkResult LocationAttr::walk(function_ref walkFn) { AttrTypeWalker walker; // Walk locations, but skip any other attribute. walker.addWalk([&](Attribute attr) { if (auto loc = llvm::dyn_cast(attr)) return walkFn(loc); return WalkResult::skip(); }); return walker.walk(*this); } /// Methods for support type inquiry through isa, cast, and dyn_cast. bool LocationAttr::classof(Attribute attr) { return attr.hasTrait(); } //===----------------------------------------------------------------------===// // CallSiteLoc //===----------------------------------------------------------------------===// CallSiteLoc CallSiteLoc::get(Location name, ArrayRef frames) { assert(!frames.empty() && "required at least 1 call frame"); Location caller = frames.back(); for (auto frame : llvm::reverse(frames.drop_back())) caller = CallSiteLoc::get(frame, caller); return CallSiteLoc::get(name, caller); } //===----------------------------------------------------------------------===// // FileLineColLoc //===----------------------------------------------------------------------===// FileLineColLoc FileLineColLoc::get(StringAttr filename, unsigned line, unsigned column) { return llvm::cast( FileLineColRange::get(filename, line, column)); } FileLineColLoc FileLineColLoc::get(MLIRContext *context, StringRef fileName, unsigned line, unsigned column) { return llvm::cast( FileLineColRange::get(context, fileName, line, column)); } StringAttr FileLineColLoc::getFilename() const { return FileLineColRange::getFilename(); } unsigned FileLineColLoc::getLine() const { return getStartLine(); } unsigned FileLineColLoc::getColumn() const { return getStartColumn(); } bool mlir::isStrictFileLineColLoc(Location loc) { if (auto range = mlir::dyn_cast(loc)) return range.getImpl()->size() == 2; return false; } //===----------------------------------------------------------------------===// // FileLineColRange //===----------------------------------------------------------------------===// StringAttr FileLineColRange::getFilename() const { return getImpl()->filenameAndTrailing.getPointer(); } unsigned FileLineColRange::getStartLine() const { return getImpl()->getStartLine(); } unsigned FileLineColRange::getStartColumn() const { return getImpl()->getStartColumn(); } unsigned FileLineColRange::getEndColumn() const { return getImpl()->getEndColumn(); } unsigned FileLineColRange::getEndLine() const { return getImpl()->getEndLine(); } //===----------------------------------------------------------------------===// // FusedLoc //===----------------------------------------------------------------------===// Location FusedLoc::get(ArrayRef locs, Attribute metadata, MLIRContext *context) { // Unique the set of locations to be fused. llvm::SmallSetVector decomposedLocs; for (auto loc : locs) { // If the location is a fused location we decompose it if it has no // metadata or the metadata is the same as the top level metadata. if (auto fusedLoc = llvm::dyn_cast(loc)) { if (fusedLoc.getMetadata() == metadata) { // UnknownLoc's have already been removed from FusedLocs so we can // simply add all of the internal locations. decomposedLocs.insert_range(fusedLoc.getLocations()); continue; } } // Otherwise, only add known locations to the set. if (!llvm::isa(loc)) decomposedLocs.insert(loc); } locs = decomposedLocs.getArrayRef(); // Handle the simple cases of less than two locations. Ensure the metadata (if // provided) is not dropped. if (locs.empty()) { if (!metadata) return UnknownLoc::get(context); // TODO: Investigate ASAN failure when using implicit conversion from // Location to ArrayRef below. return Base::get(context, ArrayRef{UnknownLoc::get(context)}, metadata); } if (locs.size() == 1 && !metadata) return locs.front(); return Base::get(context, locs, metadata); } //===----------------------------------------------------------------------===// // BuiltinDialect //===----------------------------------------------------------------------===// void BuiltinDialect::registerLocationAttributes() { addAttributes< #define GET_ATTRDEF_LIST #include "mlir/IR/BuiltinLocationAttributes.cpp.inc" >(); }