
Improve mlir-query tool by implementing `getBackwardSlice` and `getForwardSlice` matchers. As an addition `SetQuery` also needed to be added to enable custom configuration for each query. e.g: `inclusive`, `omitUsesFromAbove`, `omitBlockArguments`. Note: backwardSlice and forwardSlice algoritms are the same as the ones in `mlir/lib/Analysis/SliceAnalysis.cpp` Example of current matcher. The query was made to the file: `mlir/test/mlir-query/complex-test.mlir` ```mlir ./mlir-query /home/dbudii/personal/llvm-project/mlir/test/mlir-query/complex-test.mlir -c "match getDefinitions(hasOpName(\"arith.add f\"),2)" Match #1: /home/dbudii/personal/llvm-project/mlir/test/mlir-query/complex-test.mlir:5:8: %0 = linalg.generic {indexing_maps = [#map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0 : tensor<5x5xf32>) outs(%arg1 : tensor<5x5xf32>) { ^ /home/dbudii/personal/llvm-project/mlir/test/mlir-query/complex-test.mlir:7:10: note: "root" binds here %2 = arith.addf %in, %in : f32 ^ Match #2: /home/dbudii/personal/llvm-project/mlir/test/mlir-query/complex-test.mlir:10:16: %collapsed = tensor.collapse_shape %0 [[0, 1]] : tensor<5x5xf32> into tensor<25xf32> ^ /home/dbudii/personal/llvm-project/mlir/test/mlir-query/complex-test.mlir:13:11: %c2 = arith.constant 2 : index ^ /home/dbudii/personal/llvm-project/mlir/test/mlir-query/complex-test.mlir:14:18: %extracted = tensor.extract %collapsed[%c2] : tensor<25xf32> ^ /home/dbudii/personal/llvm-project/mlir/test/mlir-query/complex-test.mlir:15:10: note: "root" binds here %2 = arith.addf %extracted, %extracted : f32 ^ 2 matches. ```
194 lines
7.0 KiB
C++
194 lines
7.0 KiB
C++
//===--- Parser.h - Matcher expression parser -------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Simple matcher expression parser.
|
|
//
|
|
// This file contains the Parser class, which is responsible for parsing
|
|
// expressions in a specific format: matcherName(Arg0, Arg1, ..., ArgN). The
|
|
// parser can also interpret simple types, like strings.
|
|
//
|
|
// The actual processing of the matchers is handled by a Sema object that is
|
|
// provided to the parser.
|
|
//
|
|
// The grammar for the supported expressions is as follows:
|
|
// <Expression> := <Literal> | <MatcherExpression>
|
|
// <Literal> := <StringLiteral> | <NumericLiteral> | <BooleanLiteral>
|
|
// <StringLiteral> := "quoted string"
|
|
// <BooleanLiteral> := "true" | "false"
|
|
// <NumericLiteral> := [0-9]+
|
|
// <MatcherExpression> := <MatcherName>(<ArgumentList>)
|
|
// <MatcherName> := [a-zA-Z]+
|
|
// <ArgumentList> := <Expression> | <Expression>,<ArgumentList>
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef MLIR_TOOLS_MLIRQUERY_MATCHER_PARSER_H
|
|
#define MLIR_TOOLS_MLIRQUERY_MATCHER_PARSER_H
|
|
|
|
#include "Diagnostics.h"
|
|
#include "RegistryManager.h"
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
#include "llvm/ADT/StringMap.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
namespace mlir::query::matcher::internal {
|
|
|
|
// Matcher expression parser.
|
|
class Parser {
|
|
public:
|
|
// Different possible tokens.
|
|
enum class TokenKind {
|
|
Eof,
|
|
NewLine,
|
|
OpenParen,
|
|
CloseParen,
|
|
Comma,
|
|
Period,
|
|
Literal,
|
|
Ident,
|
|
InvalidChar,
|
|
CodeCompletion,
|
|
Error
|
|
};
|
|
|
|
// Interface to connect the parser with the registry and more. The parser uses
|
|
// the Sema instance passed into parseMatcherExpression() to handle all
|
|
// matcher tokens.
|
|
class Sema {
|
|
public:
|
|
virtual ~Sema();
|
|
|
|
// Process a matcher expression. The caller takes ownership of the Matcher
|
|
// object returned.
|
|
virtual VariantMatcher actOnMatcherExpression(
|
|
MatcherCtor ctor, SourceRange nameRange, llvm::StringRef functionName,
|
|
llvm::ArrayRef<ParserValue> args, Diagnostics *error) = 0;
|
|
|
|
// Look up a matcher by name in the matcher name found by the parser.
|
|
virtual std::optional<MatcherCtor>
|
|
lookupMatcherCtor(llvm::StringRef matcherName) = 0;
|
|
|
|
// Compute the list of completion types for Context.
|
|
virtual std::vector<ArgKind> getAcceptedCompletionTypes(
|
|
llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context);
|
|
|
|
// Compute the list of completions that match any of acceptedTypes.
|
|
virtual std::vector<MatcherCompletion>
|
|
getMatcherCompletions(llvm::ArrayRef<ArgKind> acceptedTypes);
|
|
};
|
|
|
|
// An implementation of the Sema interface that uses the matcher registry to
|
|
// process tokens.
|
|
class RegistrySema : public Parser::Sema {
|
|
public:
|
|
RegistrySema(const Registry &matcherRegistry)
|
|
: matcherRegistry(matcherRegistry) {}
|
|
~RegistrySema() override;
|
|
|
|
std::optional<MatcherCtor>
|
|
lookupMatcherCtor(llvm::StringRef matcherName) override;
|
|
|
|
VariantMatcher actOnMatcherExpression(MatcherCtor Ctor,
|
|
SourceRange NameRange,
|
|
StringRef functionName,
|
|
ArrayRef<ParserValue> Args,
|
|
Diagnostics *Error) override;
|
|
|
|
std::vector<ArgKind> getAcceptedCompletionTypes(
|
|
llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> context) override;
|
|
|
|
std::vector<MatcherCompletion>
|
|
getMatcherCompletions(llvm::ArrayRef<ArgKind> acceptedTypes) override;
|
|
|
|
private:
|
|
const Registry &matcherRegistry;
|
|
};
|
|
|
|
using NamedValueMap = llvm::StringMap<VariantValue>;
|
|
|
|
// Methods to parse a matcher expression and return a DynMatcher object,
|
|
// transferring ownership to the caller.
|
|
static std::optional<DynMatcher>
|
|
parseMatcherExpression(llvm::StringRef &matcherCode,
|
|
const Registry &matcherRegistry,
|
|
const NamedValueMap *namedValues, Diagnostics *error);
|
|
static std::optional<DynMatcher>
|
|
parseMatcherExpression(llvm::StringRef &matcherCode,
|
|
const Registry &matcherRegistry, Diagnostics *error) {
|
|
return parseMatcherExpression(matcherCode, matcherRegistry, nullptr, error);
|
|
}
|
|
|
|
// Methods to parse any expression supported by this parser.
|
|
static bool parseExpression(llvm::StringRef &code,
|
|
const Registry &matcherRegistry,
|
|
const NamedValueMap *namedValues,
|
|
VariantValue *value, Diagnostics *error);
|
|
|
|
static bool parseExpression(llvm::StringRef &code,
|
|
const Registry &matcherRegistry,
|
|
VariantValue *value, Diagnostics *error) {
|
|
return parseExpression(code, matcherRegistry, nullptr, value, error);
|
|
}
|
|
|
|
// Methods to complete an expression at a given offset.
|
|
static std::vector<MatcherCompletion>
|
|
completeExpression(llvm::StringRef &code, unsigned completionOffset,
|
|
const Registry &matcherRegistry,
|
|
const NamedValueMap *namedValues);
|
|
static std::vector<MatcherCompletion>
|
|
completeExpression(llvm::StringRef &code, unsigned completionOffset,
|
|
const Registry &matcherRegistry) {
|
|
return completeExpression(code, completionOffset, matcherRegistry, nullptr);
|
|
}
|
|
|
|
private:
|
|
class CodeTokenizer;
|
|
struct ScopedContextEntry;
|
|
struct TokenInfo;
|
|
|
|
Parser(CodeTokenizer *tokenizer, const Registry &matcherRegistry,
|
|
const NamedValueMap *namedValues, Diagnostics *error);
|
|
|
|
bool parseChainedExpression(std::string &argument);
|
|
|
|
bool parseExpressionImpl(VariantValue *value);
|
|
|
|
bool parseMatcherArgs(std::vector<ParserValue> &args, MatcherCtor ctor,
|
|
const TokenInfo &nameToken, TokenInfo &endToken);
|
|
|
|
bool parseMatcherExpressionImpl(const TokenInfo &nameToken,
|
|
const TokenInfo &openToken,
|
|
std::optional<MatcherCtor> ctor,
|
|
VariantValue *value);
|
|
|
|
bool parseIdentifierPrefixImpl(VariantValue *value);
|
|
|
|
void addCompletion(const TokenInfo &compToken,
|
|
const MatcherCompletion &completion);
|
|
void addExpressionCompletions();
|
|
|
|
std::vector<MatcherCompletion>
|
|
getNamedValueCompletions(llvm::ArrayRef<ArgKind> acceptedTypes);
|
|
|
|
CodeTokenizer *const tokenizer;
|
|
std::unique_ptr<RegistrySema> sema;
|
|
const NamedValueMap *const namedValues;
|
|
Diagnostics *const error;
|
|
|
|
using ContextStackTy = std::vector<std::pair<MatcherCtor, unsigned>>;
|
|
|
|
ContextStackTy contextStack;
|
|
std::vector<MatcherCompletion> completions;
|
|
};
|
|
|
|
} // namespace mlir::query::matcher::internal
|
|
|
|
#endif // MLIR_TOOLS_MLIRQUERY_MATCHER_PARSER_H
|