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