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 | |
15 | using namespace mlir; |
16 | using 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 | |
29 | void BuiltinDialect::registerLocationAttributes() { |
30 | addAttributes< |
31 | #define GET_ATTRDEF_LIST |
32 | #include "mlir/IR/BuiltinLocationAttributes.cpp.inc" |
33 | >(); |
34 | } |
35 | |
36 | //===----------------------------------------------------------------------===// |
37 | // LocationAttr |
38 | //===----------------------------------------------------------------------===// |
39 | |
40 | WalkResult 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. |
66 | bool LocationAttr::classof(Attribute attr) { |
67 | return llvm::isa<CallSiteLoc, FileLineColLoc, FusedLoc, NameLoc, OpaqueLoc, |
68 | UnknownLoc>(attr); |
69 | } |
70 | |
71 | //===----------------------------------------------------------------------===// |
72 | // CallSiteLoc |
73 | //===----------------------------------------------------------------------===// |
74 | |
75 | CallSiteLoc 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 | |
87 | Location 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 | |