Skip to content

Commit

Permalink
FileCheck [8/12]: Define numeric var from expr
Browse files Browse the repository at this point in the history
Summary:
This patch is part of a patch series to add support for FileCheck
numeric expressions. This specific patch lift the restriction for a
numeric expression to either be a variable definition or a numeric
expression to try to match.

This commit allows a numeric variable to be set to the result of the
evaluation of a numeric expression after it has been matched
successfully. When it happens, the variable is allowed to be used on
the same line since its value is known at match time.

It also makes use of this possibility to reuse the parsing code to
parse a command-line definition by crafting a mirror string of the
-D option with the equal sign replaced by a colon sign, e.g. for option
'-D#NUMVAL=10' it creates the string
'-D#NUMVAL=10 (parsed as [[#NUMVAL:10]])' where the numeric expression
is parsed to define NUMVAL. This result in a few tests needing updating
for the location diagnostics on top of the tests for the new feature.

It also enables empty numeric expression which match any number without
defining a variable. This is done here rather than in commit #5 of the
patch series because it requires to dissociate automatic regex insertion
in RegExStr from variable definition which would make commit #5 even
bigger than it already is.

Copyright:
    - Linaro (changes up to diff 183612 of revision D55940)
    - GraphCore (changes in later versions of revision D55940 and
                 in new revision created off D55940)

Reviewers: jhenderson, chandlerc, jdenny, probinson, grimar, arichardson, rnk

Subscribers: hiraditya, llvm-commits, probinson, dblaikie, grimar, arichardson, tra, rnk, kristina, hfinkel, rogfer01, JonChesterfield

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D60388

llvm-svn: 366860
  • Loading branch information
Thomas Preud'homme committed Jul 23, 2019
1 parent f8552e6 commit 1b05977
Show file tree
Hide file tree
Showing 7 changed files with 475 additions and 251 deletions.
26 changes: 21 additions & 5 deletions llvm/docs/CommandGuide/FileCheck.rst
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,12 @@ and from the command line.
Sets a filecheck pattern variable ``VAR`` with value ``VALUE`` that can be
used in ``CHECK:`` lines.

.. option:: -D#<NUMVAR>=<VALUE EXPRESSION>
.. option:: -D#<NUMVAR>=<NUMERIC EXPRESSION>

Sets a filecheck numeric variable ``NUMVAR`` to the result of evaluating
``<VALUE EXPRESSION>`` that can be used in ``CHECK:`` lines. See section
``FileCheck Numeric Variables and Expressions`` for details on the format
and meaning of ``<VALUE EXPRESSION>``.
``<NUMERIC EXPRESSION>`` that can be used in ``CHECK:`` lines. See section
``FileCheck Numeric Variables and Expressions`` for details on supported
numeric expressions.

.. option:: -version

Expand Down Expand Up @@ -625,11 +625,27 @@ but would not match the text:
due to ``7`` being unequal to ``5 + 1``.

The syntax also supports an empty expression, equivalent to writing {{[0-9]+}},
for cases where the input must contain a numeric value but the value itself
does not matter:

.. code-block:: gas
; CHECK-NOT: mov r0, r[[#]]
to check that a value is synthesized rather than moved around.

A numeric variable can also be defined to the result of a numeric expression,
in which case the numeric expression is checked and if verified the variable is
assigned to the value. The unified syntax for both defining numeric variables
and checking a numeric expression is thus ``[[#<NUMVAR>: <expr>]]`` with each
element as described previously.

The ``--enable-var-scope`` option has the same effect on numeric variables as
on string variables.

Important note: In its current implementation, an expression cannot use a
numeric variable defined on the same line.
numeric variable with a non-empty expression defined on the same line.

FileCheck Pseudo Numeric Variables
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
116 changes: 77 additions & 39 deletions llvm/include/llvm/Support/FileCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ class FileCheckNumericVariable {
/// Name of the numeric variable.
StringRef Name;

/// Pointer to expression defining this numeric variable. Null for pseudo
/// variable whose value is known at parse time (e.g. @LINE pseudo variable)
/// or cleared local variable.
FileCheckExpressionAST *ExpressionAST;

/// Value of numeric variable, if defined, or None otherwise.
Optional<uint64_t> Value;

Expand All @@ -104,23 +109,40 @@ class FileCheckNumericVariable {

public:
/// Constructor for a variable \p Name defined at line \p DefLineNumber or
/// defined before input is parsed if DefLineNumber is None.
/// defined before input is parsed if \p DefLineNumber is None. If not null,
/// the value set with setValue must match the result of evaluating
/// \p ExpressionAST.
FileCheckNumericVariable(StringRef Name,
Optional<size_t> DefLineNumber = None)
: Name(Name), DefLineNumber(DefLineNumber) {}
Optional<size_t> DefLineNumber = None,
FileCheckExpressionAST *ExpressionAST = nullptr)
: Name(Name), ExpressionAST(ExpressionAST), DefLineNumber(DefLineNumber) {
}

/// \returns name of this numeric variable.
StringRef getName() const { return Name; }

/// \returns this variable's value.
Optional<uint64_t> getValue() const { return Value; }

/// Sets value of this numeric variable to \p NewValue.
void setValue(uint64_t NewValue) { Value = NewValue; }
/// \returns the pointer to the expression defining this numeric variable, if
/// any, or null otherwise.
FileCheckExpressionAST *getExpressionAST() const { return ExpressionAST; }

/// \returns whether this variable's value is known when performing the
/// substitutions of the line where it is defined.
bool isValueKnownAtMatchTime() const;

/// Sets value of this numeric variable to \p NewValue. Triggers an assertion
/// failure if the variable is defined by an expression and the expression
/// cannot be evaluated to be equal to \p NewValue.
void setValue(uint64_t NewValue);

/// Clears value of this numeric variable, regardless of whether it is
/// currently defined or not.
void clearValue() { Value = None; }
void clearValue() {
Value = None;
ExpressionAST = nullptr;
}

/// \returns the line number where this variable is defined, if any, or None
/// if defined before input is parsed.
Expand Down Expand Up @@ -507,27 +529,22 @@ class FileCheckPattern {
/// \p Str from the variable name.
static Expected<VariableProperties> parseVariable(StringRef &Str,
const SourceMgr &SM);
/// Parses \p Expr for the name of a numeric variable to be defined at line
/// \p LineNumber or before input is parsed if \p LineNumber is None.
/// \returns a pointer to the class instance representing that variable,
/// creating it if needed, or an error holding a diagnostic against \p SM
/// should defining such a variable be invalid.
static Expected<FileCheckNumericVariable *> parseNumericVariableDefinition(
StringRef &Expr, FileCheckPatternContext *Context,
Optional<size_t> LineNumber, const SourceMgr &SM);
/// Parses \p Expr for a numeric substitution block. Parameter
/// Parses \p Expr for a numeric substitution block at line \p LineNumber,
/// or before input is parsed if \p LineNumber is None. Parameter
/// \p IsLegacyLineExpr indicates whether \p Expr should be a legacy @LINE
/// expression. \returns a pointer to the class instance representing the AST
/// of the expression whose value must be substituted, or an error holding a
/// diagnostic against \p SM if parsing fails. If substitution was
/// successful, sets \p DefinedNumericVariable to point to the class
/// representing the numeric variable being defined in this numeric
/// expression and \p Context points to the class instance holding the live
/// string and numeric variables. \returns a pointer to the class instance
/// representing the AST of the expression whose value must be substitued, or
/// an error holding a diagnostic against \p SM if parsing fails. If
/// substitution was successful, sets \p DefinedNumericVariable to point to
/// the class representing the numeric variable defined in this numeric
/// substitution block, or None if this block does not define any variable.
Expected<std::unique_ptr<FileCheckExpressionAST>>
static Expected<std::unique_ptr<FileCheckExpressionAST>>
parseNumericSubstitutionBlock(
StringRef Expr,
Optional<FileCheckNumericVariable *> &DefinedNumericVariable,
bool IsLegacyLineExpr, const SourceMgr &SM) const;
bool IsLegacyLineExpr, Optional<size_t> LineNumber,
FileCheckPatternContext *Context, const SourceMgr &SM);
/// Parses the pattern in \p PatternStr and initializes this FileCheckPattern
/// instance accordingly.
///
Expand Down Expand Up @@ -581,28 +598,49 @@ class FileCheckPattern {
/// was not found.
size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM);

/// Parses \p Name as a (pseudo if \p IsPseudo is true) numeric variable use.
/// \returns the pointer to the class instance representing that variable if
/// successful, or an error holding a diagnostic against \p SM otherwise.
Expected<std::unique_ptr<FileCheckNumericVariableUse>>
/// Parses \p Expr for the name of a numeric variable to be defined at line
/// \p LineNumber, or before input is parsed if \p LineNumber is None.
/// \returns a pointer to the class instance representing that variable,
/// creating it if needed, or an error holding a diagnostic against \p SM
/// should defining such a variable be invalid.
static Expected<FileCheckNumericVariable *> parseNumericVariableDefinition(
StringRef &Expr, FileCheckPatternContext *Context,
Optional<size_t> LineNumber, FileCheckExpressionAST *ExpressionAST,
const SourceMgr &SM);
/// Parses \p Name as a (pseudo if \p IsPseudo is true) numeric variable use
/// at line \p LineNumber, or before input is parsed if \p LineNumber is
/// None. Parameter \p Context points to the class instance holding the live
/// string and numeric variables. \returns the pointer to the class instance
/// representing that variable if successful, or an error holding a
/// diagnostic against \p SM otherwise.
static Expected<std::unique_ptr<FileCheckNumericVariableUse>>
parseNumericVariableUse(StringRef Name, bool IsPseudo,
const SourceMgr &SM) const;
Optional<size_t> LineNumber,
FileCheckPatternContext *Context,
const SourceMgr &SM);
enum class AllowedOperand { LineVar, Literal, Any };
/// Parses \p Expr for use of a numeric operand. Accepts both literal values
/// and numeric variables, depending on the value of \p AO. \returns the
/// class representing that operand in the AST of the expression or an error
/// holding a diagnostic against \p SM otherwise.
Expected<std::unique_ptr<FileCheckExpressionAST>>
/// Parses \p Expr for use of a numeric operand at line \p LineNumber, or
/// before input is parsed if \p LineNumber is None. Accepts both literal
/// values and numeric variables, depending on the value of \p AO. Parameter
/// \p Context points to the class instance holding the live string and
/// numeric variables. \returns the class representing that operand in the
/// AST of the expression or an error holding a diagnostic against \p SM
/// otherwise.
static Expected<std::unique_ptr<FileCheckExpressionAST>>
parseNumericOperand(StringRef &Expr, AllowedOperand AO,
const SourceMgr &SM) const;
/// Parses \p Expr for a binary operation. The left operand of this binary
Optional<size_t> LineNumber,
FileCheckPatternContext *Context, const SourceMgr &SM);
/// Parses \p Expr for a binary operation at line \p LineNumber, or before
/// input is parsed if \p LineNumber is None. The left operand of this binary
/// operation is given in \p LeftOp and \p IsLegacyLineExpr indicates whether
/// we are parsing a legacy @LINE expression. \returns the class representing
/// the binary operation in the AST of the expression, or an error holding a
/// diagnostic against \p SM otherwise.
Expected<std::unique_ptr<FileCheckExpressionAST>>
/// we are parsing a legacy @LINE expression. Parameter \p Context points to
/// the class instance holding the live string and numeric variables.
/// \returns the class representing the binary operation in the AST of the
/// expression, or an error holding a diagnostic against \p SM otherwise.
static Expected<std::unique_ptr<FileCheckExpressionAST>>
parseBinop(StringRef &Expr, std::unique_ptr<FileCheckExpressionAST> LeftOp,
bool IsLegacyLineExpr, const SourceMgr &SM) const;
bool IsLegacyLineExpr, Optional<size_t> LineNumber,
FileCheckPatternContext *Context, const SourceMgr &SM);
};

//===----------------------------------------------------------------------===//
Expand Down
Loading

0 comments on commit 1b05977

Please sign in to comment.