diff --git a/mlir/test/mlir-tblgen/op-format-spec.td b/mlir/test/mlir-tblgen/op-format-spec.td --- a/mlir/test/mlir-tblgen/op-format-spec.td +++ b/mlir/test/mlir-tblgen/op-format-spec.td @@ -280,26 +280,32 @@ // Coverage Checks //===----------------------------------------------------------------------===// -// CHECK: error: format missing instance of result #0('result') type +// CHECK: error: Type of result #0, named 'result', is not buildable and a buildable type cannot be inferred from other types. Suggest adding a type constraint to the operation or adding a 'type($result)' directive to the custom assembly format. def ZCoverageInvalidA : TestFormat_Op<"variable_invalid_a", [{ attr-dict }]>, Arguments<(ins AnyMemRef:$operand)>, Results<(outs AnyMemRef:$result)>; -// CHECK: error: format missing instance of operand #0('operand') +// CHECK: error: Operand #0, named 'operand', not found. Suggest adding a '$operand' directive to the custom assembly format. def ZCoverageInvalidB : TestFormat_Op<"variable_invalid_b", [{ type($result) attr-dict }]>, Arguments<(ins AnyMemRef:$operand)>, Results<(outs AnyMemRef:$result)>; -// CHECK: error: format missing instance of operand #0('operand') type +// CHECK: error: Type of operand #0, named 'operand', is not buildable and a buildable type cannot be inferred from other types. Suggest adding a type constraint to the operation or adding a 'type($operand)' directive to the custom assembly format. def ZCoverageInvalidC : TestFormat_Op<"variable_invalid_c", [{ $operand type($result) attr-dict }]>, Arguments<(ins AnyMemRef:$operand)>, Results<(outs AnyMemRef:$result)>; -// CHECK: error: format missing instance of operand #0('operand') type +// CHECK: error: Type of operand #0, named 'operand', is not buildable and a buildable type cannot be inferred from other types. Suggest adding a type constraint to the operation or adding a 'type($operand)' directive to the custom assembly format. def ZCoverageInvalidD : TestFormat_Op<"variable_invalid_d", [{ operands attr-dict }]>, Arguments<(ins Variadic:$operand)>; -// CHECK: error: format missing instance of result #0('result') type +// CHECK: error: Type of result #0, named 'result', is not buildable and a buildable type cannot be inferred from other types. Suggest adding a type constraint to the operation or adding a 'type($result)' directive to the custom assembly format. def ZCoverageInvalidE : TestFormat_Op<"variable_invalid_e", [{ attr-dict }]>, Results<(outs Variadic:$result)>; +// CHECK: error: Successor #0, named 'successor', not found. Suggest adding a '$successor' directive to the custom assembly format. +def ZCoverageInvalidF : TestFormat_Op<"variable_invalid_f", [{ + attr-dict +}]> { + let successors = (successor AnySuccessor:$successor); +} // CHECK-NOT: error def ZCoverageValidA : TestFormat_Op<"variable_valid_a", [{ $operand type($operand) type($result) attr-dict diff --git a/mlir/tools/mlir-tblgen/OpFormatGen.cpp b/mlir/tools/mlir-tblgen/OpFormatGen.cpp --- a/mlir/tools/mlir-tblgen/OpFormatGen.cpp +++ b/mlir/tools/mlir-tblgen/OpFormatGen.cpp @@ -1337,7 +1337,7 @@ // Check that the attribute dictionary is in the format. if (!hasAttrDict) - return emitError(loc, "format missing 'attr-dict' directive"); + return emitError(loc, "format missing 'attr-dict' directive."); // Check for any type traits that we can use for inferring types. llvm::StringMap variableTyResolver; @@ -1377,8 +1377,13 @@ NamedTypeConstraint &result = op.getResult(i); Optional builder = result.constraint.getBuilderCall(); if (!builder || result.constraint.isVariadic()) { - return emitError(loc, "format missing instance of result #" + Twine(i) + - "('" + result.name + "') type"); + return emitError(loc, "Type of result #" + Twine(i) + + ", named '" + result.name + + "', is not buildable and a buildable type cannot " + + "be inferred from other types. Suggest adding a " + + "type constraint to the operation or adding a " + + "'type($" + result.name + ")' directive to the " + + "custom assembly format."); } // Note in the format that this result uses the custom builder. auto it = buildableTypes.insert({*builder, buildableTypes.size()}); @@ -1393,8 +1398,10 @@ // Check that the operand itself is in the format. if (!hasAllOperands && !seenOperands.count(&operand)) { - return emitError(loc, "format missing instance of operand #" + Twine(i) + - "('" + operand.name + "')"); + return emitError(loc, "Operand #" + Twine(i) + + ", named '" + operand.name + "', not found." + + " Suggest adding a '$" + operand.name + + "' directive to the custom assembly format."); } // Check that the operand type is in the format, or that it can be inferred. @@ -1413,8 +1420,13 @@ // we aren't using the 'operands' directive. Optional builder = operand.constraint.getBuilderCall(); if (!builder || (hasAllOperands && operand.isVariadic())) { - return emitError(loc, "format missing instance of operand #" + Twine(i) + - "('" + operand.name + "') type"); + return emitError(loc, "Type of operand #" + Twine(i) + + ", named '" + operand.name + + "', is not buildable and a buildable type cannot " + + "be inferred from other types. Suggest adding a " + + "type constraint to the operation or adding a " + + "'type($" + operand.name + ")' directive to the " + + "custom assembly format."); } auto it = buildableTypes.insert({*builder, buildableTypes.size()}); fmt.operandTypes[i].setBuilderIdx(it.first->second); @@ -1425,8 +1437,10 @@ for (unsigned i = 0, e = op.getNumSuccessors(); i != e; ++i) { const NamedSuccessor &successor = op.getSuccessor(i); if (!seenSuccessors.count(&successor)) { - return emitError(loc, "format missing instance of successor #" + - Twine(i) + "('" + successor.name + "')"); + return emitError(loc, "Successor #" + Twine(i) + + ", named '" + successor.name + "', not found." + + " Suggest adding a '$" + successor.name + + "' directive to the custom assembly format."); } } }