| //===- 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/BuiltinDialect.h" |
| #include "mlir/IR/Visitors.h" |
| #include "llvm/ADT/SetVector.h" |
| #include "llvm/ADT/TypeSwitch.h" |
| |
| using namespace mlir; |
| using namespace mlir::detail; |
| |
| //===----------------------------------------------------------------------===// |
| /// Tablegen Attribute Definitions |
| //===----------------------------------------------------------------------===// |
| |
| #define GET_ATTRDEF_CLASSES |
| #include "mlir/IR/BuiltinLocationAttributes.cpp.inc" |
| |
| //===----------------------------------------------------------------------===// |
| // BuiltinDialect |
| //===----------------------------------------------------------------------===// |
| |
| void BuiltinDialect::registerLocationAttributes() { |
| addAttributes< |
| #define GET_ATTRDEF_LIST |
| #include "mlir/IR/BuiltinLocationAttributes.cpp.inc" |
| >(); |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // LocationAttr |
| //===----------------------------------------------------------------------===// |
| |
| WalkResult LocationAttr::walk(function_ref<WalkResult(Location)> walkFn) { |
| if (walkFn(*this).wasInterrupted()) |
| return WalkResult::interrupt(); |
| |
| return TypeSwitch<LocationAttr, WalkResult>(*this) |
| .Case([&](CallSiteLoc callLoc) -> WalkResult { |
| if (callLoc.getCallee()->walk(walkFn).wasInterrupted()) |
| return WalkResult::interrupt(); |
| return callLoc.getCaller()->walk(walkFn); |
| }) |
| .Case([&](FusedLoc fusedLoc) -> WalkResult { |
| for (Location subLoc : fusedLoc.getLocations()) |
| if (subLoc->walk(walkFn).wasInterrupted()) |
| return WalkResult::interrupt(); |
| return WalkResult::advance(); |
| }) |
| .Case([&](NameLoc nameLoc) -> WalkResult { |
| return nameLoc.getChildLoc()->walk(walkFn); |
| }) |
| .Case([&](OpaqueLoc opaqueLoc) -> WalkResult { |
| return opaqueLoc.getFallbackLocation()->walk(walkFn); |
| }) |
| .Default(WalkResult::advance()); |
| } |
| |
| /// Methods for support type inquiry through isa, cast, and dyn_cast. |
| bool LocationAttr::classof(Attribute attr) { |
| return attr.isa<CallSiteLoc, FileLineColLoc, FusedLoc, NameLoc, OpaqueLoc, |
| UnknownLoc>(); |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // CallSiteLoc |
| //===----------------------------------------------------------------------===// |
| |
| CallSiteLoc CallSiteLoc::get(Location name, ArrayRef<Location> 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); |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // FusedLoc |
| //===----------------------------------------------------------------------===// |
| |
| Location FusedLoc::get(ArrayRef<Location> locs, Attribute metadata, |
| MLIRContext *context) { |
| // Unique the set of locations to be fused. |
| llvm::SmallSetVector<Location, 4> 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 = loc.dyn_cast<FusedLoc>()) { |
| if (fusedLoc.getMetadata() == metadata) { |
| // UnknownLoc's have already been removed from FusedLocs so we can |
| // simply add all of the internal locations. |
| decomposedLocs.insert(fusedLoc.getLocations().begin(), |
| fusedLoc.getLocations().end()); |
| continue; |
| } |
| } |
| // Otherwise, only add known locations to the set. |
| if (!loc.isa<UnknownLoc>()) |
| decomposedLocs.insert(loc); |
| } |
| locs = decomposedLocs.getArrayRef(); |
| |
| // Handle the simple cases of less than two locations. |
| if (locs.empty()) |
| return UnknownLoc::get(context); |
| if (locs.size() == 1) |
| return locs.front(); |
| return Base::get(context, locs, metadata); |
| } |