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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "mlir/IR/Location.h"
10#include "mlir/IR/BuiltinDialect.h"
11#include "mlir/IR/Visitors.h"
12#include "llvm/ADT/SetVector.h"
13#include "llvm/ADT/TypeSwitch.h"
14
15using namespace mlir;
16using namespace mlir::detail;
17
18//===----------------------------------------------------------------------===//
19/// Tablegen Attribute Definitions
20//===----------------------------------------------------------------------===//
21
22#define GET_ATTRDEF_CLASSES
23#include "mlir/IR/BuiltinLocationAttributes.cpp.inc"
24
25//===----------------------------------------------------------------------===//
26// BuiltinDialect
27//===----------------------------------------------------------------------===//
28
29void BuiltinDialect::registerLocationAttributes() {
30 addAttributes<
31#define GET_ATTRDEF_LIST
32#include "mlir/IR/BuiltinLocationAttributes.cpp.inc"
33 >();
34}
35
36//===----------------------------------------------------------------------===//
37// LocationAttr
38//===----------------------------------------------------------------------===//
39
40WalkResult LocationAttr::walk(function_ref<WalkResult(Location)> walkFn) {
41 if (walkFn(*this).wasInterrupted())
42 return WalkResult::interrupt();
43
44 return TypeSwitch<LocationAttr, WalkResult>(*this)
45 .Case([&](CallSiteLoc callLoc) -> WalkResult {
46 if (callLoc.getCallee()->walk(walkFn).wasInterrupted())
47 return WalkResult::interrupt();
48 return callLoc.getCaller()->walk(walkFn);
49 })
50 .Case([&](FusedLoc fusedLoc) -> WalkResult {
51 for (Location subLoc : fusedLoc.getLocations())
52 if (subLoc->walk(walkFn).wasInterrupted())
53 return WalkResult::interrupt();
54 return WalkResult::advance();
55 })
56 .Case([&](NameLoc nameLoc) -> WalkResult {
57 return nameLoc.getChildLoc()->walk(walkFn);
58 })
59 .Case([&](OpaqueLoc opaqueLoc) -> WalkResult {
60 return opaqueLoc.getFallbackLocation()->walk(walkFn);
61 })
62 .Default(WalkResult::advance());
63}
64
65/// Methods for support type inquiry through isa, cast, and dyn_cast.
66bool LocationAttr::classof(Attribute attr) {
67 return llvm::isa<CallSiteLoc, FileLineColLoc, FusedLoc, NameLoc, OpaqueLoc,
68 UnknownLoc>(attr);
69}
70
71//===----------------------------------------------------------------------===//
72// CallSiteLoc
73//===----------------------------------------------------------------------===//
74
75CallSiteLoc CallSiteLoc::get(Location name, ArrayRef<Location> frames) {
76 assert(!frames.empty() && "required at least 1 call frame");
77 Location caller = frames.back();
78 for (auto frame : llvm::reverse(frames.drop_back()))
79 caller = CallSiteLoc::get(frame, caller);
80 return CallSiteLoc::get(name, caller);
81}
82
83//===----------------------------------------------------------------------===//
84// FusedLoc
85//===----------------------------------------------------------------------===//
86
87Location FusedLoc::get(ArrayRef<Location> locs, Attribute metadata,
88 MLIRContext *context) {
89 // Unique the set of locations to be fused.
90 llvm::SmallSetVector<Location, 4> decomposedLocs;
91 for (auto loc : locs) {
92 // If the location is a fused location we decompose it if it has no
93 // metadata or the metadata is the same as the top level metadata.
94 if (auto fusedLoc = llvm::dyn_cast<FusedLoc>(loc)) {
95 if (fusedLoc.getMetadata() == metadata) {
96 // UnknownLoc's have already been removed from FusedLocs so we can
97 // simply add all of the internal locations.
98 decomposedLocs.insert(fusedLoc.getLocations().begin(),
99 fusedLoc.getLocations().end());
100 continue;
101 }
102 }
103 // Otherwise, only add known locations to the set.
104 if (!llvm::isa<UnknownLoc>(loc))
105 decomposedLocs.insert(loc);
106 }
107 locs = decomposedLocs.getArrayRef();
108
109 // Handle the simple cases of less than two locations. Ensure the metadata (if
110 // provided) is not dropped.
111 if (locs.empty()) {
112 if (!metadata)
113 return UnknownLoc::get(context);
114 // TODO: Investigate ASAN failure when using implicit conversion from
115 // Location to ArrayRef<Location> below.
116 return Base::get(context, ArrayRef<Location>{UnknownLoc::get(context)},
117 metadata);
118 }
119 if (locs.size() == 1 && !metadata)
120 return locs.front();
121
122 return Base::get(context, locs, metadata);
123}
124

source code of mlir/lib/IR/Location.cpp