12fa4bc9fSRiver Riddle //===- Location.cpp - MLIR Location Classes -------------------------------===// 22fa4bc9fSRiver Riddle // 330857107SMehdi Amini // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 456222a06SMehdi Amini // See https://llvm.org/LICENSE.txt for license information. 556222a06SMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 62fa4bc9fSRiver Riddle // 756222a06SMehdi Amini //===----------------------------------------------------------------------===// 82fa4bc9fSRiver Riddle 92fa4bc9fSRiver Riddle #include "mlir/IR/Location.h" 1001e75646SJacques Pienaar #include "mlir/IR/AttributeSupport.h" 1101e75646SJacques Pienaar #include "mlir/IR/BuiltinAttributes.h" 1231bb8efdSRiver Riddle #include "mlir/IR/BuiltinDialect.h" 1301e75646SJacques Pienaar #include "mlir/IR/MLIRContext.h" 14706c9c5cSRiver Riddle #include "mlir/IR/Visitors.h" 1501e75646SJacques Pienaar #include "mlir/Support/LLVM.h" 1601e75646SJacques Pienaar #include "llvm/ADT/ArrayRef.h" 1701e75646SJacques Pienaar #include "llvm/ADT/Hashing.h" 1801e75646SJacques Pienaar #include "llvm/ADT/PointerIntPair.h" 1901e75646SJacques Pienaar #include "llvm/ADT/STLExtras.h" 2036b7c2daSRiver Riddle #include "llvm/ADT/SetVector.h" 21706c9c5cSRiver Riddle #include "llvm/ADT/TypeSwitch.h" 2201e75646SJacques Pienaar #include "llvm/Support/Casting.h" 2301e75646SJacques Pienaar #include "llvm/Support/TrailingObjects.h" 2401e75646SJacques Pienaar #include <cassert> 2501e75646SJacques Pienaar #include <iterator> 2601e75646SJacques Pienaar #include <memory> 2701e75646SJacques Pienaar #include <optional> 2801e75646SJacques Pienaar #include <tuple> 2901e75646SJacques Pienaar #include <utility> 302fa4bc9fSRiver Riddle 312fa4bc9fSRiver Riddle using namespace mlir; 322fa4bc9fSRiver Riddle using namespace mlir::detail; 332fa4bc9fSRiver Riddle 3401e75646SJacques Pienaar namespace mlir::detail { 3501e75646SJacques Pienaar struct FileLineColRangeAttrStorage final 3601e75646SJacques Pienaar : public ::mlir::AttributeStorage, 3701e75646SJacques Pienaar public llvm::TrailingObjects<FileLineColRangeAttrStorage, unsigned> { 3801e75646SJacques Pienaar using PointerPair = llvm::PointerIntPair<StringAttr, 2>; 3901e75646SJacques Pienaar using KeyTy = std::tuple<StringAttr, ::llvm::ArrayRef<unsigned>>; 4001e75646SJacques Pienaar 4101e75646SJacques Pienaar FileLineColRangeAttrStorage(StringAttr filename, int numLocs) 4201e75646SJacques Pienaar : filenameAndTrailing(filename, numLocs) {} 4301e75646SJacques Pienaar 4401e75646SJacques Pienaar static FileLineColRangeAttrStorage * 4501e75646SJacques Pienaar construct(::mlir::AttributeStorageAllocator &allocator, KeyTy &&tblgenKey) { 4601e75646SJacques Pienaar auto numInArray = std::get<1>(tblgenKey).size(); 4701e75646SJacques Pienaar // Note: Considered asserting that numInArray is at least 1, but this 4801e75646SJacques Pienaar // is not needed in memory or in printed form. This should very rarely be 4901e75646SJacques Pienaar // 0 here as that means a NamedLoc would have been more efficient. But this 5001e75646SJacques Pienaar // does allow for location with just a file, and also having the interface 5101e75646SJacques Pienaar // be more uniform. 5201e75646SJacques Pienaar auto locEnc = numInArray == 0 ? 1 : numInArray; 5301e75646SJacques Pienaar // Allocate a new storage instance. 5401e75646SJacques Pienaar auto byteSize = 5501e75646SJacques Pienaar FileLineColRangeAttrStorage::totalSizeToAlloc<unsigned>(locEnc - 1); 5601e75646SJacques Pienaar auto *rawMem = 5701e75646SJacques Pienaar allocator.allocate(byteSize, alignof(FileLineColRangeAttrStorage)); 5801e75646SJacques Pienaar auto *result = ::new (rawMem) FileLineColRangeAttrStorage( 5901e75646SJacques Pienaar std::move(std::get<0>(tblgenKey)), locEnc - 1); 6001e75646SJacques Pienaar if (numInArray > 0) { 6101e75646SJacques Pienaar result->startLine = std::get<1>(tblgenKey)[0]; 6201e75646SJacques Pienaar // Copy in the element types into the trailing storage. 6301e75646SJacques Pienaar std::uninitialized_copy(std::next(std::get<1>(tblgenKey).begin()), 6401e75646SJacques Pienaar std::get<1>(tblgenKey).end(), 6501e75646SJacques Pienaar result->getTrailingObjects<unsigned>()); 6601e75646SJacques Pienaar } 6701e75646SJacques Pienaar return result; 6801e75646SJacques Pienaar } 6901e75646SJacques Pienaar 7001e75646SJacques Pienaar // Return the number of held types. 7101e75646SJacques Pienaar unsigned size() const { return filenameAndTrailing.getInt() + 1; } 7201e75646SJacques Pienaar 7301e75646SJacques Pienaar bool operator==(const KeyTy &tblgenKey) const { 7401e75646SJacques Pienaar return (filenameAndTrailing.getPointer() == std::get<0>(tblgenKey)) && 7501e75646SJacques Pienaar (size() == std::get<1>(tblgenKey).size()) && 7601e75646SJacques Pienaar (startLine == std::get<1>(tblgenKey)[0]) && 7701e75646SJacques Pienaar (ArrayRef<unsigned>{getTrailingObjects<unsigned>(), size() - 1} == 7801e75646SJacques Pienaar ArrayRef<unsigned>{std::get<1>(tblgenKey)}.drop_front()); 7901e75646SJacques Pienaar } 8001e75646SJacques Pienaar 8101e75646SJacques Pienaar unsigned getLineCols(unsigned index) const { 8201e75646SJacques Pienaar return getTrailingObjects<unsigned>()[index - 1]; 8301e75646SJacques Pienaar } 8401e75646SJacques Pienaar 8501e75646SJacques Pienaar unsigned getStartLine() const { return startLine; } 8601e75646SJacques Pienaar unsigned getStartColumn() const { 8701e75646SJacques Pienaar if (size() <= 1) 8801e75646SJacques Pienaar return 0; 8901e75646SJacques Pienaar return getLineCols(1); 9001e75646SJacques Pienaar } 9101e75646SJacques Pienaar unsigned getEndColumn() const { 9201e75646SJacques Pienaar if (size() <= 2) 9301e75646SJacques Pienaar return getStartColumn(); 9401e75646SJacques Pienaar return getLineCols(2); 9501e75646SJacques Pienaar } 9601e75646SJacques Pienaar unsigned getEndLine() const { 9701e75646SJacques Pienaar if (size() <= 3) 9801e75646SJacques Pienaar return getStartLine(); 9901e75646SJacques Pienaar return getLineCols(3); 10001e75646SJacques Pienaar } 10101e75646SJacques Pienaar 10201e75646SJacques Pienaar static ::llvm::hash_code hashKey(const KeyTy &tblgenKey) { 10301e75646SJacques Pienaar return ::llvm::hash_combine(std::get<0>(tblgenKey), std::get<1>(tblgenKey)); 10401e75646SJacques Pienaar } 10501e75646SJacques Pienaar 10601e75646SJacques Pienaar // Supports 10701e75646SJacques Pienaar // - 0 (file:line) 10801e75646SJacques Pienaar // - 1 (file:line:col) 10901e75646SJacques Pienaar // - 2 (file:line:start_col to file:line:end_col) and 11001e75646SJacques Pienaar // - 3 (file:start_line:start_col to file:end_line:end_col) 11101e75646SJacques Pienaar llvm::PointerIntPair<StringAttr, 2> filenameAndTrailing; 11201e75646SJacques Pienaar unsigned startLine = 0; 11301e75646SJacques Pienaar }; 11401e75646SJacques Pienaar } // namespace mlir::detail 11501e75646SJacques Pienaar 116e18a55f1SRiver Riddle //===----------------------------------------------------------------------===// 117a4bb667dSRiver Riddle /// Tablegen Attribute Definitions 118a4bb667dSRiver Riddle //===----------------------------------------------------------------------===// 119a4bb667dSRiver Riddle 120a4bb667dSRiver Riddle #define GET_ATTRDEF_CLASSES 121a4bb667dSRiver Riddle #include "mlir/IR/BuiltinLocationAttributes.cpp.inc" 122a4bb667dSRiver Riddle 123a4bb667dSRiver Riddle //===----------------------------------------------------------------------===// 124fff39b62SRiver Riddle // LocationAttr 125fff39b62SRiver Riddle //===----------------------------------------------------------------------===// 126fff39b62SRiver Riddle 127706c9c5cSRiver Riddle WalkResult LocationAttr::walk(function_ref<WalkResult(Location)> walkFn) { 128759a7b59SAman LaChapelle AttrTypeWalker walker; 129759a7b59SAman LaChapelle // Walk locations, but skip any other attribute. 130759a7b59SAman LaChapelle walker.addWalk([&](Attribute attr) { 131759a7b59SAman LaChapelle if (auto loc = llvm::dyn_cast<LocationAttr>(attr)) 132759a7b59SAman LaChapelle return walkFn(loc); 133706c9c5cSRiver Riddle 134759a7b59SAman LaChapelle return WalkResult::skip(); 135759a7b59SAman LaChapelle }); 136759a7b59SAman LaChapelle return walker.walk<WalkOrder::PreOrder>(*this); 137706c9c5cSRiver Riddle } 138706c9c5cSRiver Riddle 139fff39b62SRiver Riddle /// Methods for support type inquiry through isa, cast, and dyn_cast. 140fff39b62SRiver Riddle bool LocationAttr::classof(Attribute attr) { 141759a7b59SAman LaChapelle return attr.hasTrait<AttributeTrait::IsLocation>(); 142fff39b62SRiver Riddle } 143fff39b62SRiver Riddle 144fff39b62SRiver Riddle //===----------------------------------------------------------------------===// 145e18a55f1SRiver Riddle // CallSiteLoc 146e18a55f1SRiver Riddle //===----------------------------------------------------------------------===// 147e18a55f1SRiver Riddle 148a4bb667dSRiver Riddle CallSiteLoc CallSiteLoc::get(Location name, ArrayRef<Location> frames) { 14923251f9fSRiver Riddle assert(!frames.empty() && "required at least 1 call frame"); 150e18a55f1SRiver Riddle Location caller = frames.back(); 151e18a55f1SRiver Riddle for (auto frame : llvm::reverse(frames.drop_back())) 15223251f9fSRiver Riddle caller = CallSiteLoc::get(frame, caller); 15323251f9fSRiver Riddle return CallSiteLoc::get(name, caller); 154e18a55f1SRiver Riddle } 15563068da4SFeng Liu 156e18a55f1SRiver Riddle //===----------------------------------------------------------------------===// 15701e75646SJacques Pienaar // FileLineColLoc 15801e75646SJacques Pienaar //===----------------------------------------------------------------------===// 15901e75646SJacques Pienaar 16001e75646SJacques Pienaar FileLineColLoc FileLineColLoc::get(StringAttr filename, unsigned line, 16101e75646SJacques Pienaar unsigned column) { 16201e75646SJacques Pienaar return llvm::cast<FileLineColLoc>( 16301e75646SJacques Pienaar FileLineColRange::get(filename, line, column)); 16401e75646SJacques Pienaar } 16501e75646SJacques Pienaar 16601e75646SJacques Pienaar FileLineColLoc FileLineColLoc::get(MLIRContext *context, StringRef fileName, 16701e75646SJacques Pienaar unsigned line, unsigned column) { 16801e75646SJacques Pienaar return llvm::cast<FileLineColLoc>( 16901e75646SJacques Pienaar FileLineColRange::get(context, fileName, line, column)); 17001e75646SJacques Pienaar } 17101e75646SJacques Pienaar 17201e75646SJacques Pienaar StringAttr FileLineColLoc::getFilename() const { 17301e75646SJacques Pienaar return FileLineColRange::getFilename(); 17401e75646SJacques Pienaar } 17501e75646SJacques Pienaar 17601e75646SJacques Pienaar unsigned FileLineColLoc::getLine() const { return getStartLine(); } 17701e75646SJacques Pienaar 17801e75646SJacques Pienaar unsigned FileLineColLoc::getColumn() const { return getStartColumn(); } 17901e75646SJacques Pienaar 180*3b35b4c7SJacques Pienaar bool mlir::isStrictFileLineColLoc(Location loc) { 181*3b35b4c7SJacques Pienaar if (auto range = mlir::dyn_cast<FileLineColRange>(loc)) 18201e75646SJacques Pienaar return range.getImpl()->size() == 2; 18301e75646SJacques Pienaar return false; 18401e75646SJacques Pienaar } 18501e75646SJacques Pienaar 18601e75646SJacques Pienaar //===----------------------------------------------------------------------===// 18701e75646SJacques Pienaar // FileLineColRange 18801e75646SJacques Pienaar //===----------------------------------------------------------------------===// 18901e75646SJacques Pienaar 19001e75646SJacques Pienaar StringAttr FileLineColRange::getFilename() const { 19101e75646SJacques Pienaar return getImpl()->filenameAndTrailing.getPointer(); 19201e75646SJacques Pienaar } 19301e75646SJacques Pienaar 19401e75646SJacques Pienaar unsigned FileLineColRange::getStartLine() const { 19501e75646SJacques Pienaar return getImpl()->getStartLine(); 19601e75646SJacques Pienaar } 19701e75646SJacques Pienaar unsigned FileLineColRange::getStartColumn() const { 19801e75646SJacques Pienaar return getImpl()->getStartColumn(); 19901e75646SJacques Pienaar } 20001e75646SJacques Pienaar unsigned FileLineColRange::getEndColumn() const { 20101e75646SJacques Pienaar return getImpl()->getEndColumn(); 20201e75646SJacques Pienaar } 20301e75646SJacques Pienaar unsigned FileLineColRange::getEndLine() const { 20401e75646SJacques Pienaar return getImpl()->getEndLine(); 20501e75646SJacques Pienaar } 20601e75646SJacques Pienaar 20701e75646SJacques Pienaar //===----------------------------------------------------------------------===// 208e18a55f1SRiver Riddle // FusedLoc 209e18a55f1SRiver Riddle //===----------------------------------------------------------------------===// 210e18a55f1SRiver Riddle 21149162524SRiver Riddle Location FusedLoc::get(ArrayRef<Location> locs, Attribute metadata, 21236b7c2daSRiver Riddle MLIRContext *context) { 21336b7c2daSRiver Riddle // Unique the set of locations to be fused. 21436b7c2daSRiver Riddle llvm::SmallSetVector<Location, 4> decomposedLocs; 21536b7c2daSRiver Riddle for (auto loc : locs) { 21636b7c2daSRiver Riddle // If the location is a fused location we decompose it if it has no 21736b7c2daSRiver Riddle // metadata or the metadata is the same as the top level metadata. 21818066b52SNick Kreeger if (auto fusedLoc = llvm::dyn_cast<FusedLoc>(loc)) { 21936b7c2daSRiver Riddle if (fusedLoc.getMetadata() == metadata) { 22036b7c2daSRiver Riddle // UnknownLoc's have already been removed from FusedLocs so we can 22136b7c2daSRiver Riddle // simply add all of the internal locations. 22236b7c2daSRiver Riddle decomposedLocs.insert(fusedLoc.getLocations().begin(), 22336b7c2daSRiver Riddle fusedLoc.getLocations().end()); 22436b7c2daSRiver Riddle continue; 22536b7c2daSRiver Riddle } 22636b7c2daSRiver Riddle } 22736b7c2daSRiver Riddle // Otherwise, only add known locations to the set. 228c1fa60b4STres Popp if (!llvm::isa<UnknownLoc>(loc)) 22936b7c2daSRiver Riddle decomposedLocs.insert(loc); 23036b7c2daSRiver Riddle } 23136b7c2daSRiver Riddle locs = decomposedLocs.getArrayRef(); 23236b7c2daSRiver Riddle 2339e365fe3SJacques Pienaar // Handle the simple cases of less than two locations. Ensure the metadata (if 2349e365fe3SJacques Pienaar // provided) is not dropped. 2359e365fe3SJacques Pienaar if (locs.empty()) { 2369e365fe3SJacques Pienaar if (!metadata) 23736b7c2daSRiver Riddle return UnknownLoc::get(context); 2389e365fe3SJacques Pienaar // TODO: Investigate ASAN failure when using implicit conversion from 2399e365fe3SJacques Pienaar // Location to ArrayRef<Location> below. 2409e365fe3SJacques Pienaar return Base::get(context, ArrayRef<Location>{UnknownLoc::get(context)}, 2419e365fe3SJacques Pienaar metadata); 2429e365fe3SJacques Pienaar } 2439e365fe3SJacques Pienaar if (locs.size() == 1 && !metadata) 24436b7c2daSRiver Riddle return locs.front(); 2459e365fe3SJacques Pienaar 246250f43d3SRiver Riddle return Base::get(context, locs, metadata); 247e18a55f1SRiver Riddle } 24801e75646SJacques Pienaar 24901e75646SJacques Pienaar //===----------------------------------------------------------------------===// 25001e75646SJacques Pienaar // BuiltinDialect 25101e75646SJacques Pienaar //===----------------------------------------------------------------------===// 25201e75646SJacques Pienaar 25301e75646SJacques Pienaar void BuiltinDialect::registerLocationAttributes() { 25401e75646SJacques Pienaar addAttributes< 25501e75646SJacques Pienaar #define GET_ATTRDEF_LIST 25601e75646SJacques Pienaar #include "mlir/IR/BuiltinLocationAttributes.cpp.inc" 25701e75646SJacques Pienaar >(); 25801e75646SJacques Pienaar } 259