[MLIR] Add note for file-line numbers in tablegen errors for assembly formats
authorStephen Neuendorffer <stephen.neuendorffer@xilinx.com>
Sun, 5 Apr 2020 05:54:35 +0000 (22:54 -0700)
committerStephen Neuendorffer <stephen.neuendorffer@xilinx.com>
Tue, 7 Apr 2020 22:06:51 +0000 (15:06 -0700)
Error messages for the custom assembly format are difficult to understand
because there are no line numbers.  This happens because the assembly format
is parsed as a standalone line, separate from it's parent file, with no useful
location information.  Fixing this properly probably requires quite a bit
of invasive plumbing through the SourceMgr, similar to how included files
are handled

This proposal is a less invasive short term solution.  When generating an
error message we generate an additional note which at least properly describes
the operation definition the error occured in, if not the actual line number
of the assemblyFormat definition.

A typical message is like:

error: type of operand #0, named 'operand', is not buildable and a buildable type cannot be inferred
  $operand type($result) attr-dict
  ^
/src/llvm-project/mlir/test/mlir-tblgen/op-format-spec.td:296:1: note: in custom assembly format for this operation
def ZCoverageInvalidC : TestFormat_Op<"variable_invalid_c", [{
^
note: suggest adding a type constraint to the operation or adding a 'type($operand)' directive to the custom assembly format
  $operand type($result) attr-dict
  ^

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

mlir/test/mlir-tblgen/op-format-spec.td
mlir/tools/mlir-tblgen/OpFormatGen.cpp

index 1e7a974..482175b 100644 (file)
@@ -19,7 +19,7 @@ class TestFormat_Op<string name, string fmt, list<OpTrait> traits = []>
 //===----------------------------------------------------------------------===//
 // attr-dict
 
-// CHECK: error: 'attr-dict' directive not found in custom assembly format
+// CHECK: error: 'attr-dict' directive not found
 def DirectiveAttrDictInvalidA : TestFormat_Op<"attrdict_invalid_a", [{
 }]>;
 // CHECK: error: 'attr-dict' directive has already been seen
@@ -300,7 +300,7 @@ def VariableInvalidK : TestFormat_Op<"variable_invalid_k", [{
 def ZCoverageInvalidA : TestFormat_Op<"variable_invalid_a", [{
   attr-dict
 }]>, Arguments<(ins AnyMemRef:$operand)>, Results<(outs AnyMemRef:$result)>;
-// CHECK: error: operand #0, named 'operand', not found in custom assembly format
+// CHECK: error: operand #0, named 'operand', not found
 // CHECK: note: suggest adding a '$operand' directive to the custom assembly format
 def ZCoverageInvalidB : TestFormat_Op<"variable_invalid_b", [{
   type($result) attr-dict
@@ -320,7 +320,7 @@ def ZCoverageInvalidD : TestFormat_Op<"variable_invalid_d", [{
 def ZCoverageInvalidE : TestFormat_Op<"variable_invalid_e", [{
   attr-dict
 }]>, Results<(outs Variadic<I64>:$result)>;
-// CHECK: error: successor #0, named 'successor', not found in custom assembly format
+// CHECK: error: successor #0, named 'successor', not found
 // CHECK: note: suggest adding a '$successor' directive to the custom assembly format
 def ZCoverageInvalidF : TestFormat_Op<"variable_invalid_f", [{
         attr-dict
index e4b6694..4cd9dfb 100644 (file)
@@ -1055,7 +1055,7 @@ private:
 /// This class implements a simple lexer for operation assembly format strings.
 class FormatLexer {
 public:
-  FormatLexer(llvm::SourceMgr &mgr);
+  FormatLexer(llvm::SourceMgr &mgr, Operator &op);
 
   /// Lex the next token and return it.
   Token lexToken();
@@ -1080,23 +1080,29 @@ private:
   Token lexVariable(const char *tokStart);
 
   llvm::SourceMgr &srcMgr;
+  Operator &op;
   StringRef curBuffer;
   const char *curPtr;
 };
 } // end anonymous namespace
 
-FormatLexer::FormatLexer(llvm::SourceMgr &mgr) : srcMgr(mgr) {
+FormatLexer::FormatLexer(llvm::SourceMgr &mgr, Operator &op)
+    : srcMgr(mgr), op(op) {
   curBuffer = srcMgr.getMemoryBuffer(mgr.getMainFileID())->getBuffer();
   curPtr = curBuffer.begin();
 }
 
 Token FormatLexer::emitError(llvm::SMLoc loc, const Twine &msg) {
   srcMgr.PrintMessage(loc, llvm::SourceMgr::DK_Error, msg);
+  llvm::SrcMgr.PrintMessage(op.getLoc()[0], llvm::SourceMgr::DK_Note,
+                            "in custom assembly format for this operation");
   return formToken(Token::error, loc.getPointer());
 }
 Token FormatLexer::emitErrorAndNote(llvm::SMLoc loc, const Twine &msg,
                                     const Twine &note) {
   srcMgr.PrintMessage(loc, llvm::SourceMgr::DK_Error, msg);
+  llvm::SrcMgr.PrintMessage(op.getLoc()[0], llvm::SourceMgr::DK_Note,
+                            "in custom assembly format for this operation");
   srcMgr.PrintMessage(loc, llvm::SourceMgr::DK_Note, note);
   return formToken(Token::error, loc.getPointer());
 }
@@ -1233,7 +1239,7 @@ namespace {
 class FormatParser {
 public:
   FormatParser(llvm::SourceMgr &mgr, OperationFormat &format, Operator &op)
-      : lexer(mgr), curToken(lexer.lexToken()), fmt(format), op(op),
+      : lexer(mgr, op), curToken(lexer.lexToken()), fmt(format), op(op),
         seenOperandTypes(op.getNumOperands()),
         seenResultTypes(op.getNumResults()) {}
 
@@ -1481,8 +1487,7 @@ LogicalResult FormatParser::verifyOperands(
     if (!hasAllOperands && !seenOperands.count(&operand)) {
       return emitErrorAndNote(loc,
                               "operand #" + Twine(i) + ", named '" +
-                                  operand.name +
-                                  "', not found in custom assembly format",
+                                  operand.name + "', not found",
                               "suggest adding a '$" + operand.name +
                                   "' directive to the custom assembly format");
     }
@@ -1572,8 +1577,7 @@ LogicalResult FormatParser::verifySuccessors(llvm::SMLoc loc) {
     if (!seenSuccessors.count(&successor)) {
       return emitErrorAndNote(loc,
                               "successor #" + Twine(i) + ", named '" +
-                                  successor.name +
-                                  "', not found in custom assembly format",
+                                  successor.name + "', not found",
                               "suggest adding a '$" + successor.name +
                                   "' directive to the custom assembly format");
     }