blob: 1de4d73bbe4fa014a00ec4a7655d9dd5f5c9ebc7 [file] [log] [blame]
//===- 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);
}