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 attr.isa<CallSiteLoc, FileLineColLoc, FusedLoc, NameLoc, OpaqueLoc, 68 UnknownLoc>(); 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 = 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