Skip to content

Commit 0e719ea

Browse files
committed
[mlir][mlir-query] Add inital draft for mlir-query tool
This tool is for interactive exploration of the mlir using existing matchers. It currently allows the user to enter a matcher at an interactive prompt and view the matches.
1 parent a7cfcc6 commit 0e719ea

24 files changed

Lines changed: 3064 additions & 0 deletions
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//===- MlirQueryMain.h - MLIR Query main -*- 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+
// Main entry function for mlir-query for when built as standalone
10+
// binary.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef MLIR_TOOLS_MLIRQUERY_MLIRQUERYMAIN_H
15+
#define MLIR_TOOLS_MLIRQUERY_MLIRQUERYMAIN_H
16+
17+
#include "mlir/Support/LogicalResult.h"
18+
19+
namespace mlir {
20+
21+
class MLIRContext;
22+
/// This is the entry point for the implementation
23+
/// of tools like `mlir-query`. The query to perform is parsed from
24+
/// the command line. The `toolName` argument is used for the header displayed
25+
/// by `--help`.
26+
LogicalResult mlirQueryMain(int argc, char **argv, MLIRContext &context);
27+
} // namespace mlir
28+
29+
#endif // MLIR_TOOLS_MLIRQUERY_MLIRQUERYMAIN_H

mlir/lib/Tools/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ add_subdirectory(lsp-server-support)
22
add_subdirectory(mlir-lsp-server)
33
add_subdirectory(mlir-opt)
44
add_subdirectory(mlir-pdll-lsp-server)
5+
add_subdirectory(mlir-query)
56
add_subdirectory(mlir-reduce)
67
add_subdirectory(mlir-tblgen)
78
add_subdirectory(mlir-translate)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
set(LLVM_LINK_COMPONENTS
2+
lineeditor
3+
Support
4+
)
5+
6+
add_mlir_library(MLIRQueryLib
7+
MlirQueryMain.cpp
8+
Query.cpp
9+
QueryParser.cpp
10+
Parser.cpp
11+
Registry.cpp
12+
VariantValue.cpp
13+
Diagnostics.cpp
14+
15+
ADDITIONAL_HEADER_DIRS
16+
${MLIR_MAIN_INCLUDE_DIR}/mlir/Tools/mlir-query
17+
18+
LINK_LIBS PUBLIC
19+
MLIRIR
20+
MLIRParser
21+
)
Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
//===- Diagnostic.cpp -----------------------------------------------------===//
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 "Diagnostics.h"
10+
11+
#include "llvm/Support/Debug.h"
12+
using llvm::dbgs;
13+
14+
#define DEBUG_TYPE "mlir-query"
15+
#define DBGS() (dbgs() << '[' << DEBUG_TYPE << "] ")
16+
17+
namespace mlir {
18+
namespace query {
19+
namespace matcher {
20+
21+
Diagnostics::ArgStream Diagnostics::pushContextFrame(ContextType Type,
22+
SourceRange Range) {
23+
ContextStack.emplace_back();
24+
ContextFrame &data = ContextStack.back();
25+
data.Type = Type;
26+
data.Range = Range;
27+
return ArgStream(&data.Args);
28+
}
29+
30+
Diagnostics::Context::Context(ConstructMatcherEnum, Diagnostics *Error,
31+
StringRef MatcherName, SourceRange MatcherRange)
32+
: Error(Error) {
33+
Error->pushContextFrame(CT_MatcherConstruct, MatcherRange) << MatcherName;
34+
}
35+
36+
Diagnostics::Context::Context(MatcherArgEnum, Diagnostics *Error,
37+
StringRef MatcherName, SourceRange MatcherRange,
38+
unsigned ArgNumber)
39+
: Error(Error) {
40+
Error->pushContextFrame(CT_MatcherArg, MatcherRange)
41+
<< ArgNumber << MatcherName;
42+
}
43+
44+
Diagnostics::Context::~Context() { Error->ContextStack.pop_back(); }
45+
46+
Diagnostics::OverloadContext::OverloadContext(Diagnostics *Error)
47+
: Error(Error), BeginIndex(Error->Errors.size()) {}
48+
49+
Diagnostics::OverloadContext::~OverloadContext() {
50+
// Merge all errors that happened while in this context.
51+
if (BeginIndex < Error->Errors.size()) {
52+
Diagnostics::ErrorContent &Dest = Error->Errors[BeginIndex];
53+
for (size_t i = BeginIndex + 1, e = Error->Errors.size(); i < e; ++i) {
54+
Dest.Messages.push_back(Error->Errors[i].Messages[0]);
55+
}
56+
Error->Errors.resize(BeginIndex + 1);
57+
}
58+
}
59+
60+
void Diagnostics::OverloadContext::revertErrors() {
61+
// Revert the errors.
62+
Error->Errors.resize(BeginIndex);
63+
}
64+
65+
Diagnostics::ArgStream &Diagnostics::ArgStream::operator<<(const Twine &Arg) {
66+
Out->push_back(Arg.str());
67+
return *this;
68+
}
69+
70+
Diagnostics::ArgStream Diagnostics::addError(SourceRange Range,
71+
ErrorType Error) {
72+
Errors.emplace_back();
73+
ErrorContent &Last = Errors.back();
74+
Last.ContextStack = ContextStack;
75+
Last.Messages.emplace_back();
76+
Last.Messages.back().Range = Range;
77+
Last.Messages.back().Type = Error;
78+
return ArgStream(&Last.Messages.back().Args);
79+
}
80+
81+
static StringRef contextTypeToFormatString(Diagnostics::ContextType Type) {
82+
switch (Type) {
83+
case Diagnostics::CT_MatcherConstruct:
84+
return "Error building matcher $0.";
85+
case Diagnostics::CT_MatcherArg:
86+
return "Error parsing argument $0 for matcher $1.";
87+
}
88+
llvm_unreachable("Unknown ContextType value.");
89+
}
90+
91+
static StringRef errorTypeToFormatString(Diagnostics::ErrorType Type) {
92+
switch (Type) {
93+
case Diagnostics::ET_RegistryMatcherNotFound:
94+
return "Matcher not found: $0";
95+
case Diagnostics::ET_RegistryWrongArgCount:
96+
return "Incorrect argument count. (Expected = $0) != (Actual = $1)";
97+
case Diagnostics::ET_RegistryWrongArgType:
98+
return "Incorrect type for arg $0. (Expected = $1) != (Actual = $2)";
99+
case Diagnostics::ET_RegistryNotBindable:
100+
return "Matcher does not support binding.";
101+
case Diagnostics::ET_RegistryAmbiguousOverload:
102+
// TODO: Add type info about the overload error.
103+
return "Ambiguous matcher overload.";
104+
case Diagnostics::ET_RegistryValueNotFound:
105+
return "Value not found: $0";
106+
case Diagnostics::ET_RegistryUnknownEnumWithReplace:
107+
return "Unknown value '$1' for arg $0; did you mean '$2'";
108+
case Diagnostics::ET_RegistryNonNodeMatcher:
109+
return "Matcher not a node matcher: $0";
110+
case Diagnostics::ET_RegistryMatcherNoWithSupport:
111+
return "Matcher does not support with call.";
112+
113+
case Diagnostics::ET_ParserStringError:
114+
return "Error parsing string token: <$0>";
115+
case Diagnostics::ET_ParserNoOpenParen:
116+
return "Error parsing matcher. Found token <$0> while looking for '('.";
117+
case Diagnostics::ET_ParserNoCloseParen:
118+
return "Error parsing matcher. Found end-of-code while looking for ')'.";
119+
case Diagnostics::ET_ParserNoComma:
120+
return "Error parsing matcher. Found token <$0> while looking for ','.";
121+
case Diagnostics::ET_ParserNoCode:
122+
return "End of code found while looking for token.";
123+
case Diagnostics::ET_ParserNotAMatcher:
124+
return "Input value is not a matcher expression.";
125+
case Diagnostics::ET_ParserInvalidToken:
126+
return "Invalid token <$0> found when looking for a value.";
127+
case Diagnostics::ET_ParserMalformedBindExpr:
128+
return "Malformed bind() expression.";
129+
case Diagnostics::ET_ParserTrailingCode:
130+
return "Expected end of code.";
131+
case Diagnostics::ET_ParserNumberError:
132+
return "Error parsing numeric literal: <$0>";
133+
case Diagnostics::ET_ParserOverloadedType:
134+
return "Input value has unresolved overloaded type: $0";
135+
case Diagnostics::ET_ParserMalformedChainedExpr:
136+
return "Period not followed by valid chained call.";
137+
case Diagnostics::ET_ParserFailedToBuildMatcher:
138+
return "Failed to build matcher: $0.";
139+
140+
case Diagnostics::ET_None:
141+
return "<N/A>";
142+
}
143+
llvm_unreachable("Unknown ErrorType value.");
144+
}
145+
146+
static void formatErrorString(StringRef FormatString,
147+
ArrayRef<std::string> Args,
148+
llvm::raw_ostream &OS) {
149+
while (!FormatString.empty()) {
150+
std::pair<StringRef, StringRef> Pieces = FormatString.split("$");
151+
OS << Pieces.first.str();
152+
if (Pieces.second.empty())
153+
break;
154+
155+
const char Next = Pieces.second.front();
156+
FormatString = Pieces.second.drop_front();
157+
if (Next >= '0' && Next <= '9') {
158+
const unsigned Index = Next - '0';
159+
if (Index < Args.size()) {
160+
OS << Args[Index];
161+
} else {
162+
OS << "<Argument_Not_Provided>";
163+
}
164+
}
165+
}
166+
}
167+
168+
static void maybeAddLineAndColumn(SourceRange Range, llvm::raw_ostream &OS) {
169+
if (Range.Start.Line > 0 && Range.Start.Column > 0) {
170+
OS << Range.Start.Line << ":" << Range.Start.Column << ": ";
171+
}
172+
}
173+
174+
static void printContextFrameToStream(const Diagnostics::ContextFrame &Frame,
175+
llvm::raw_ostream &OS) {
176+
maybeAddLineAndColumn(Frame.Range, OS);
177+
formatErrorString(contextTypeToFormatString(Frame.Type), Frame.Args, OS);
178+
}
179+
180+
static void
181+
printMessageToStream(const Diagnostics::ErrorContent::Message &Message,
182+
const Twine Prefix, llvm::raw_ostream &OS) {
183+
maybeAddLineAndColumn(Message.Range, OS);
184+
OS << Prefix;
185+
formatErrorString(errorTypeToFormatString(Message.Type), Message.Args, OS);
186+
}
187+
188+
static void printErrorContentToStream(const Diagnostics::ErrorContent &Content,
189+
llvm::raw_ostream &OS) {
190+
if (Content.Messages.size() == 1) {
191+
printMessageToStream(Content.Messages[0], "", OS);
192+
} else {
193+
for (size_t i = 0, e = Content.Messages.size(); i != e; ++i) {
194+
if (i != 0)
195+
OS << "\n";
196+
printMessageToStream(Content.Messages[i],
197+
"Candidate " + Twine(i + 1) + ": ", OS);
198+
}
199+
}
200+
}
201+
202+
void Diagnostics::printToStream(llvm::raw_ostream &OS) const {
203+
for (size_t i = 0, e = Errors.size(); i != e; ++i) {
204+
if (i != 0)
205+
OS << "\n";
206+
printErrorContentToStream(Errors[i], OS);
207+
}
208+
}
209+
210+
std::string Diagnostics::toString() const {
211+
std::string S;
212+
llvm::raw_string_ostream OS(S);
213+
printToStream(OS);
214+
return S;
215+
}
216+
217+
void Diagnostics::printToStreamFull(llvm::raw_ostream &OS) const {
218+
for (size_t i = 0, e = Errors.size(); i != e; ++i) {
219+
if (i != 0)
220+
OS << "\n";
221+
const ErrorContent &Error = Errors[i];
222+
for (size_t i = 0, e = Error.ContextStack.size(); i != e; ++i) {
223+
printContextFrameToStream(Error.ContextStack[i], OS);
224+
OS << "\n";
225+
}
226+
printErrorContentToStream(Error, OS);
227+
}
228+
}
229+
230+
std::string Diagnostics::toStringFull() const {
231+
std::string S;
232+
llvm::raw_string_ostream OS(S);
233+
printToStreamFull(OS);
234+
return S;
235+
}
236+
237+
} // namespace matcher
238+
} // namespace query
239+
} // namespace mlir

0 commit comments

Comments
 (0)