1 //===- FileLineColLocBreakpointManager.h - TODO: add message ----*- C++ -*-===// 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 #ifndef MLIR_TRACING_BREAKPOINTMANAGERS_FILELINECOLLOCBREAKPOINTMANAGER_H 10 #define MLIR_TRACING_BREAKPOINTMANAGERS_FILELINECOLLOCBREAKPOINTMANAGER_H 11 12 #include "mlir/Debug/BreakpointManager.h" 13 #include "mlir/Debug/ExecutionContext.h" 14 #include "mlir/IR/Action.h" 15 #include "mlir/IR/Location.h" 16 #include "mlir/IR/Operation.h" 17 #include "llvm/ADT/DenseMap.h" 18 #include <memory> 19 #include <optional> 20 21 namespace mlir { 22 namespace tracing { 23 24 /// This breakpoing intends to match a FileLineColLocation, that is a tuple of 25 /// file name, line number, and column number. Using -1 for the column and the 26 /// line number will match any column and line number respectively. 27 class FileLineColLocBreakpoint 28 : public BreakpointBase<FileLineColLocBreakpoint> { 29 public: FileLineColLocBreakpoint(StringRef file,int64_t line,int64_t col)30 FileLineColLocBreakpoint(StringRef file, int64_t line, int64_t col) 31 : line(line), col(col) {} 32 print(raw_ostream & os)33 void print(raw_ostream &os) const override { 34 os << "Location: " << file << ':' << line << ':' << col; 35 } 36 37 /// Parse a string representation in the form of "<file>:<line>:<col>". Return 38 /// a tuple with these three elements, the first one is a StringRef pointing 39 /// into the original string. 40 static FailureOr<std::tuple<StringRef, int64_t, int64_t>> parseFromString( 41 StringRef str, llvm::function_ref<void(Twine)> diag = [](Twine) {}); 42 43 private: 44 /// A filename on which to break. 45 StringRef file; 46 47 /// A particular line on which to break, or -1 to break on any line. 48 int64_t line; 49 50 /// A particular column on which to break, or -1 to break on any column 51 int64_t col; 52 53 friend class FileLineColLocBreakpointManager; 54 }; 55 56 /// This breakpoint manager is responsible for matching 57 /// FileLineColLocBreakpoint. It'll extract the location from the action context 58 /// looking for a FileLineColLocation, and match it against the registered 59 /// breakpoints. 60 class FileLineColLocBreakpointManager 61 : public BreakpointManagerBase<FileLineColLocBreakpointManager> { 62 public: match(const Action & action)63 Breakpoint *match(const Action &action) const override { 64 for (const IRUnit &unit : action.getContextIRUnits()) { 65 if (auto *op = llvm::dyn_cast_if_present<Operation *>(unit)) { 66 if (auto match = matchFromLocation(op->getLoc())) 67 return *match; 68 continue; 69 } 70 if (auto *block = llvm::dyn_cast_if_present<Block *>(unit)) { 71 for (auto &op : block->getOperations()) { 72 if (auto match = matchFromLocation(op.getLoc())) 73 return *match; 74 } 75 continue; 76 } 77 if (Region *region = llvm::dyn_cast_if_present<Region *>(unit)) { 78 if (auto match = matchFromLocation(region->getLoc())) 79 return *match; 80 continue; 81 } 82 } 83 return {}; 84 } 85 86 FileLineColLocBreakpoint *addBreakpoint(StringRef file, int64_t line, 87 int64_t col = -1) { 88 auto &breakpoint = breakpoints[std::make_tuple(file, line, col)]; 89 if (!breakpoint) 90 breakpoint = std::make_unique<FileLineColLocBreakpoint>(file, line, col); 91 return breakpoint.get(); 92 } 93 94 private: matchFromLocation(Location initialLoc)95 std::optional<Breakpoint *> matchFromLocation(Location initialLoc) const { 96 std::optional<Breakpoint *> match = std::nullopt; 97 initialLoc->walk([&](Location loc) { 98 auto fileLoc = dyn_cast<FileLineColLoc>(loc); 99 if (!fileLoc) 100 return WalkResult::advance(); 101 StringRef file = fileLoc.getFilename(); 102 int64_t line = fileLoc.getLine(); 103 int64_t col = fileLoc.getColumn(); 104 auto lookup = breakpoints.find(std::make_tuple(file, line, col)); 105 if (lookup != breakpoints.end() && lookup->second->isEnabled()) { 106 match = lookup->second.get(); 107 return WalkResult::interrupt(); 108 } 109 // If not found, check with the -1 key if we have a breakpoint for any 110 // col. 111 lookup = breakpoints.find(std::make_tuple(file, line, -1)); 112 if (lookup != breakpoints.end() && lookup->second->isEnabled()) { 113 match = lookup->second.get(); 114 return WalkResult::interrupt(); 115 } 116 // If not found, check with the -1 key if we have a breakpoint for any 117 // line. 118 lookup = breakpoints.find(std::make_tuple(file, -1, -1)); 119 if (lookup != breakpoints.end() && lookup->second->isEnabled()) { 120 match = lookup->second.get(); 121 return WalkResult::interrupt(); 122 } 123 return WalkResult::advance(); 124 }); 125 return match; 126 } 127 128 /// A map from a (filename, line, column) -> breakpoint. 129 DenseMap<std::tuple<StringRef, int64_t, int64_t>, 130 std::unique_ptr<FileLineColLocBreakpoint>> 131 breakpoints; 132 }; 133 134 } // namespace tracing 135 } // namespace mlir 136 137 #endif // MLIR_TRACING_BREAKPOINTMANAGERS_FILELINECOLLOCBREAKPOINTMANAGER_H 138