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
21namespace mlir {
22namespace 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.
27class FileLineColLocBreakpoint
28 : public BreakpointBase<FileLineColLocBreakpoint> {
29public:
30 FileLineColLocBreakpoint(StringRef file, int64_t line, int64_t col)
31 : line(line), col(col) {}
32
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
43private:
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.
60class FileLineColLocBreakpointManager
61 : public BreakpointManagerBase<FileLineColLocBreakpointManager> {
62public:
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 *>(Val: unit)) {
66 if (auto match = matchFromLocation(initialLoc: op->getLoc()))
67 return *match;
68 continue;
69 }
70 if (auto *block = llvm::dyn_cast_if_present<Block *>(Val: unit)) {
71 for (auto &op : block->getOperations()) {
72 if (auto match = matchFromLocation(initialLoc: op.getLoc()))
73 return *match;
74 }
75 continue;
76 }
77 if (Region *region = llvm::dyn_cast_if_present<Region *>(Val: unit)) {
78 if (auto match = matchFromLocation(initialLoc: 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(args&: file, args&: line, args&: col)];
89 if (!breakpoint)
90 breakpoint = std::make_unique<FileLineColLocBreakpoint>(args&: file, args&: line, args&: col);
91 return breakpoint.get();
92 }
93
94private:
95 std::optional<Breakpoint *> matchFromLocation(Location initialLoc) const {
96 std::optional<Breakpoint *> match = std::nullopt;
97 initialLoc->walk(walkFn: [&](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(Val: std::make_tuple(args&: file, args&: line, args&: 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(Val: std::make_tuple(args&: file, args&: line, args: -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(Val: std::make_tuple(args&: file, args: -1, args: -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

source code of mlir/include/mlir/Debug/BreakpointManagers/FileLineColLocBreakpointManager.h