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 
registerLocationAttributes()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 
walk(function_ref<WalkResult (Location)> walkFn)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.
classof(Attribute attr)66 bool LocationAttr::classof(Attribute attr) {
67   return attr.isa<CallSiteLoc, FileLineColLoc, FusedLoc, NameLoc, OpaqueLoc,
68                   UnknownLoc>();
69 }
70 
71 //===----------------------------------------------------------------------===//
72 // CallSiteLoc
73 //===----------------------------------------------------------------------===//
74 
get(Location name,ArrayRef<Location> frames)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 
get(ArrayRef<Location> locs,Attribute metadata,MLIRContext * context)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 = loc.dyn_cast<FusedLoc>()) {
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 (!loc.isa<UnknownLoc>())
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