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 "LocationDetail.h"
11 #include "llvm/ADT/SetVector.h"
12 
13 using namespace mlir;
14 using namespace mlir::detail;
15 
16 //===----------------------------------------------------------------------===//
17 // LocationAttr
18 //===----------------------------------------------------------------------===//
19 
20 /// Methods for support type inquiry through isa, cast, and dyn_cast.
21 bool LocationAttr::classof(Attribute attr) {
22   return attr.isa<CallSiteLoc, FileLineColLoc, FusedLoc, NameLoc, OpaqueLoc,
23                   UnknownLoc>();
24 }
25 
26 //===----------------------------------------------------------------------===//
27 // CallSiteLoc
28 //===----------------------------------------------------------------------===//
29 
30 Location CallSiteLoc::get(Location callee, Location caller) {
31   return Base::get(callee->getContext(), StandardAttributes::CallSiteLocation,
32                    callee, caller);
33 }
34 
35 Location CallSiteLoc::get(Location name, ArrayRef<Location> frames) {
36   assert(!frames.empty() && "required at least 1 call frame");
37   Location caller = frames.back();
38   for (auto frame : llvm::reverse(frames.drop_back()))
39     caller = CallSiteLoc::get(frame, caller);
40   return CallSiteLoc::get(name, caller);
41 }
42 
43 Location CallSiteLoc::getCallee() const { return getImpl()->callee; }
44 
45 Location CallSiteLoc::getCaller() const { return getImpl()->caller; }
46 
47 //===----------------------------------------------------------------------===//
48 // FileLineColLoc
49 //===----------------------------------------------------------------------===//
50 
51 Location FileLineColLoc::get(Identifier filename, unsigned line,
52                              unsigned column, MLIRContext *context) {
53   return Base::get(context, StandardAttributes::FileLineColLocation, filename,
54                    line, column);
55 }
56 
57 Location FileLineColLoc::get(StringRef filename, unsigned line, unsigned column,
58                              MLIRContext *context) {
59   return get(Identifier::get(filename.empty() ? "-" : filename, context), line,
60              column, context);
61 }
62 
63 StringRef FileLineColLoc::getFilename() const { return getImpl()->filename; }
64 unsigned FileLineColLoc::getLine() const { return getImpl()->line; }
65 unsigned FileLineColLoc::getColumn() const { return getImpl()->column; }
66 
67 //===----------------------------------------------------------------------===//
68 // FusedLoc
69 //===----------------------------------------------------------------------===//
70 
71 Location FusedLoc::get(ArrayRef<Location> locs, Attribute metadata,
72                        MLIRContext *context) {
73   // Unique the set of locations to be fused.
74   llvm::SmallSetVector<Location, 4> decomposedLocs;
75   for (auto loc : locs) {
76     // If the location is a fused location we decompose it if it has no
77     // metadata or the metadata is the same as the top level metadata.
78     if (auto fusedLoc = loc.dyn_cast<FusedLoc>()) {
79       if (fusedLoc.getMetadata() == metadata) {
80         // UnknownLoc's have already been removed from FusedLocs so we can
81         // simply add all of the internal locations.
82         decomposedLocs.insert(fusedLoc.getLocations().begin(),
83                               fusedLoc.getLocations().end());
84         continue;
85       }
86     }
87     // Otherwise, only add known locations to the set.
88     if (!loc.isa<UnknownLoc>())
89       decomposedLocs.insert(loc);
90   }
91   locs = decomposedLocs.getArrayRef();
92 
93   // Handle the simple cases of less than two locations.
94   if (locs.empty())
95     return UnknownLoc::get(context);
96   if (locs.size() == 1)
97     return locs.front();
98   return Base::get(context, StandardAttributes::FusedLocation, locs, metadata);
99 }
100 
101 ArrayRef<Location> FusedLoc::getLocations() const {
102   return getImpl()->getLocations();
103 }
104 
105 Attribute FusedLoc::getMetadata() const { return getImpl()->metadata; }
106 
107 //===----------------------------------------------------------------------===//
108 // NameLoc
109 //===----------------------------------------------------------------------===//
110 
111 Location NameLoc::get(Identifier name, Location child) {
112   assert(!child.isa<NameLoc>() &&
113          "a NameLoc cannot be used as a child of another NameLoc");
114   return Base::get(child->getContext(), StandardAttributes::NameLocation, name,
115                    child);
116 }
117 
118 Location NameLoc::get(Identifier name, MLIRContext *context) {
119   return get(name, UnknownLoc::get(context));
120 }
121 
122 /// Return the name identifier.
123 Identifier NameLoc::getName() const { return getImpl()->name; }
124 
125 /// Return the child location.
126 Location NameLoc::getChildLoc() const { return getImpl()->child; }
127 
128 //===----------------------------------------------------------------------===//
129 // OpaqueLoc
130 //===----------------------------------------------------------------------===//
131 
132 Location OpaqueLoc::get(uintptr_t underlyingLocation, TypeID typeID,
133                         Location fallbackLocation) {
134   return Base::get(fallbackLocation->getContext(),
135                    StandardAttributes::OpaqueLocation, underlyingLocation,
136                    typeID, fallbackLocation);
137 }
138 
139 uintptr_t OpaqueLoc::getUnderlyingLocation() const {
140   return Base::getImpl()->underlyingLocation;
141 }
142 
143 TypeID OpaqueLoc::getUnderlyingTypeID() const { return getImpl()->typeID; }
144 
145 Location OpaqueLoc::getFallbackLocation() const {
146   return Base::getImpl()->fallbackLocation;
147 }
148