255 lines · cpp
1//===- Location.cpp - MLIR Location Classes -------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "mlir/IR/Location.h"10#include "mlir/IR/AttributeSupport.h"11#include "mlir/IR/BuiltinAttributes.h"12#include "mlir/IR/BuiltinDialect.h"13#include "mlir/IR/MLIRContext.h"14#include "mlir/IR/Visitors.h"15#include "mlir/Support/LLVM.h"16#include "llvm/ADT/ArrayRef.h"17#include "llvm/ADT/Hashing.h"18#include "llvm/ADT/PointerIntPair.h"19#include "llvm/ADT/STLExtras.h"20#include "llvm/ADT/SetVector.h"21#include "llvm/Support/Casting.h"22#include "llvm/Support/TrailingObjects.h"23#include <cassert>24#include <tuple>25#include <utility>26 27using namespace mlir;28using namespace mlir::detail;29 30namespace mlir::detail {31struct FileLineColRangeAttrStorage final32 : public ::mlir::AttributeStorage,33 private llvm::TrailingObjects<FileLineColRangeAttrStorage, unsigned> {34 friend llvm::TrailingObjects<FileLineColRangeAttrStorage, unsigned>;35 using PointerPair = llvm::PointerIntPair<StringAttr, 2>;36 using KeyTy = std::tuple<StringAttr, ::llvm::ArrayRef<unsigned>>;37 38 FileLineColRangeAttrStorage(StringAttr filename, int numLocs)39 : filenameAndTrailing(filename, numLocs) {}40 41 static FileLineColRangeAttrStorage *42 construct(::mlir::AttributeStorageAllocator &allocator, KeyTy &&tblgenKey) {43 auto numInArray = std::get<1>(tblgenKey).size();44 // Note: Considered asserting that numInArray is at least 1, but this45 // is not needed in memory or in printed form. This should very rarely be46 // 0 here as that means a NamedLoc would have been more efficient. But this47 // does allow for location with just a file, and also having the interface48 // be more uniform.49 auto locEnc = numInArray == 0 ? 1 : numInArray;50 // Allocate a new storage instance.51 auto byteSize =52 FileLineColRangeAttrStorage::totalSizeToAlloc<unsigned>(locEnc - 1);53 auto *rawMem =54 allocator.allocate(byteSize, alignof(FileLineColRangeAttrStorage));55 auto *result = ::new (rawMem)56 FileLineColRangeAttrStorage(std::get<0>(tblgenKey), locEnc - 1);57 if (numInArray > 0) {58 ArrayRef<unsigned> elements = std::get<1>(tblgenKey);59 result->startLine = elements[0];60 // Copy in the element types into the trailing storage.61 llvm::uninitialized_copy(elements.drop_front(),62 result->getTrailingObjects());63 }64 return result;65 }66 67 // Return the number of held types.68 unsigned size() const { return filenameAndTrailing.getInt() + 1; }69 70 bool operator==(const KeyTy &tblgenKey) const {71 return (filenameAndTrailing.getPointer() == std::get<0>(tblgenKey)) &&72 (size() == std::get<1>(tblgenKey).size()) &&73 (startLine == std::get<1>(tblgenKey)[0]) &&74 (getTrailingObjects(size() - 1) ==75 std::get<1>(tblgenKey).drop_front());76 }77 78 unsigned getLineCols(unsigned index) const {79 return getTrailingObjects()[index - 1];80 }81 82 unsigned getStartLine() const { return startLine; }83 unsigned getStartColumn() const {84 if (size() <= 1)85 return 0;86 return getLineCols(1);87 }88 unsigned getEndColumn() const {89 if (size() <= 2)90 return getStartColumn();91 return getLineCols(2);92 }93 unsigned getEndLine() const {94 if (size() <= 3)95 return getStartLine();96 return getLineCols(3);97 }98 99 static ::llvm::hash_code hashKey(const KeyTy &tblgenKey) {100 return ::llvm::hash_combine(std::get<0>(tblgenKey), std::get<1>(tblgenKey));101 }102 103 // Supports104 // - 0 (file:line)105 // - 1 (file:line:col)106 // - 2 (file:line:start_col to file:line:end_col) and107 // - 3 (file:start_line:start_col to file:end_line:end_col)108 llvm::PointerIntPair<StringAttr, 2> filenameAndTrailing;109 unsigned startLine = 0;110};111} // namespace mlir::detail112 113//===----------------------------------------------------------------------===//114/// Tablegen Attribute Definitions115//===----------------------------------------------------------------------===//116 117#define GET_ATTRDEF_CLASSES118#include "mlir/IR/BuiltinLocationAttributes.cpp.inc"119 120//===----------------------------------------------------------------------===//121// LocationAttr122//===----------------------------------------------------------------------===//123 124WalkResult LocationAttr::walk(function_ref<WalkResult(Location)> walkFn) {125 AttrTypeWalker walker;126 // Walk locations, but skip any other attribute.127 walker.addWalk([&](Attribute attr) {128 if (auto loc = llvm::dyn_cast<LocationAttr>(attr))129 return walkFn(loc);130 131 return WalkResult::skip();132 });133 return walker.walk<WalkOrder::PreOrder>(*this);134}135 136/// Methods for support type inquiry through isa, cast, and dyn_cast.137bool LocationAttr::classof(Attribute attr) {138 return attr.hasTrait<AttributeTrait::IsLocation>();139}140 141//===----------------------------------------------------------------------===//142// CallSiteLoc143//===----------------------------------------------------------------------===//144 145CallSiteLoc CallSiteLoc::get(Location name, ArrayRef<Location> frames) {146 assert(!frames.empty() && "required at least 1 call frame");147 Location caller = frames.back();148 for (auto frame : llvm::reverse(frames.drop_back()))149 caller = CallSiteLoc::get(frame, caller);150 return CallSiteLoc::get(name, caller);151}152 153//===----------------------------------------------------------------------===//154// FileLineColLoc155//===----------------------------------------------------------------------===//156 157FileLineColLoc FileLineColLoc::get(StringAttr filename, unsigned line,158 unsigned column) {159 return llvm::cast<FileLineColLoc>(160 FileLineColRange::get(filename, line, column));161}162 163FileLineColLoc FileLineColLoc::get(MLIRContext *context, StringRef fileName,164 unsigned line, unsigned column) {165 return llvm::cast<FileLineColLoc>(166 FileLineColRange::get(context, fileName, line, column));167}168 169StringAttr FileLineColLoc::getFilename() const {170 return FileLineColRange::getFilename();171}172 173unsigned FileLineColLoc::getLine() const { return getStartLine(); }174 175unsigned FileLineColLoc::getColumn() const { return getStartColumn(); }176 177bool mlir::isStrictFileLineColLoc(Location loc) {178 if (auto range = mlir::dyn_cast<FileLineColRange>(loc))179 return range.getImpl()->size() == 2;180 return false;181}182 183//===----------------------------------------------------------------------===//184// FileLineColRange185//===----------------------------------------------------------------------===//186 187StringAttr FileLineColRange::getFilename() const {188 return getImpl()->filenameAndTrailing.getPointer();189}190 191unsigned FileLineColRange::getStartLine() const {192 return getImpl()->getStartLine();193}194unsigned FileLineColRange::getStartColumn() const {195 return getImpl()->getStartColumn();196}197unsigned FileLineColRange::getEndColumn() const {198 return getImpl()->getEndColumn();199}200unsigned FileLineColRange::getEndLine() const {201 return getImpl()->getEndLine();202}203 204//===----------------------------------------------------------------------===//205// FusedLoc206//===----------------------------------------------------------------------===//207 208Location FusedLoc::get(ArrayRef<Location> locs, Attribute metadata,209 MLIRContext *context) {210 // Unique the set of locations to be fused.211 llvm::SmallSetVector<Location, 4> decomposedLocs;212 for (auto loc : locs) {213 // If the location is a fused location we decompose it if it has no214 // metadata or the metadata is the same as the top level metadata.215 if (auto fusedLoc = llvm::dyn_cast<FusedLoc>(loc)) {216 if (fusedLoc.getMetadata() == metadata) {217 // UnknownLoc's have already been removed from FusedLocs so we can218 // simply add all of the internal locations.219 decomposedLocs.insert_range(fusedLoc.getLocations());220 continue;221 }222 }223 // Otherwise, only add known locations to the set.224 if (!llvm::isa<UnknownLoc>(loc))225 decomposedLocs.insert(loc);226 }227 locs = decomposedLocs.getArrayRef();228 229 // Handle the simple cases of less than two locations. Ensure the metadata (if230 // provided) is not dropped.231 if (locs.empty()) {232 if (!metadata)233 return UnknownLoc::get(context);234 // TODO: Investigate ASAN failure when using implicit conversion from235 // Location to ArrayRef<Location> below.236 return Base::get(context, ArrayRef<Location>{UnknownLoc::get(context)},237 metadata);238 }239 if (locs.size() == 1 && !metadata)240 return locs.front();241 242 return Base::get(context, locs, metadata);243}244 245//===----------------------------------------------------------------------===//246// BuiltinDialect247//===----------------------------------------------------------------------===//248 249void BuiltinDialect::registerLocationAttributes() {250 addAttributes<251#define GET_ATTRDEF_LIST252#include "mlir/IR/BuiltinLocationAttributes.cpp.inc"253 >();254}255