The KeyTy of attribute/type storage classes provide enough information for automatically implementing the necessary sub element interface methods. This removes the need for derived classes to do it themselves, which is both much nicer and easier to handle certain invariants (e.g. null handling). In cases where explicitly handling for parameter types is necessary, they can provide an implementation of `AttrTypeSubElementHandler` to opt-in to support. This tickles a few things alias wise, which annoyingly messes with tests that hard code specific affine map numbers. Differential Revision: https://reviews.llvm.org/D137374
124 lines
4.6 KiB
C++
124 lines
4.6 KiB
C++
//===- 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 = llvm::dyn_cast<FusedLoc>(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(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. 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<Location> below.
|
|
return Base::get(context, ArrayRef<Location>{UnknownLoc::get(context)},
|
|
metadata);
|
|
}
|
|
if (locs.size() == 1 && !metadata)
|
|
return locs.front();
|
|
|
|
return Base::get(context, locs, metadata);
|
|
}
|