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