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: |
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 | |
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: |
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 | |
94 | private: |
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 | |