[mlir][IR] Improve error message when parsing incorrect type (#134984)
Improve error messages when parsing an incorrect type. Before: ``` invalid kind of type specified ``` After: ``` invalid kind of type specified: expected builtin.tensor, but found 'tensor<*xi32>' ``` This error message is produced when a certain operand/result type is expected according to an op's TableGen definition, but a different type is parsed. Type constraints (which may have nice error messages) are checked after parsing a type. If an incorrect type is parsed, we never get to the point of printing type constraint error messages. This may discourage users from specifying C++ classes with type constraints. (Explicitly specifying C++ classes is beneficial because the auto-generated C++ code will have richer type information; explicit casts are unnecessary, etc.) See #134981 for an example where specifying additional type information with type constraints (e.g., `LLVM_AnyVector`) lead to worse error messages. Note: In order to generate a better error message, the parser must retrieve a type's name from the C++ class. TableGen-generated type classes always have a `name` field, but hand-written C++ type classes may not. The `HasStaticName` template was copied from `DialectImplementation.h` (`HasStaticDialectName`).
This commit is contained in:
parent
9344b2196c
commit
a00a61d59b
@ -21,6 +21,19 @@
|
||||
#include "llvm/Support/SMLoc.h"
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
// reference https://stackoverflow.com/a/16000226
|
||||
template <typename T, typename = void>
|
||||
struct HasStaticName : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct HasStaticName<T,
|
||||
typename std::enable_if<
|
||||
std::is_same<::llvm::StringLiteral,
|
||||
std::decay_t<decltype(T::name)>>::value,
|
||||
void>::type> : std::true_type {};
|
||||
} // namespace
|
||||
|
||||
namespace mlir {
|
||||
class AsmParsedResourceEntry;
|
||||
class AsmResourceBuilder;
|
||||
@ -1238,8 +1251,13 @@ public:
|
||||
|
||||
// Check for the right kind of type.
|
||||
result = llvm::dyn_cast<TypeT>(type);
|
||||
if (!result)
|
||||
return emitError(loc, "invalid kind of type specified");
|
||||
if (!result) {
|
||||
InFlightDiagnostic diag =
|
||||
emitError(loc, "invalid kind of type specified");
|
||||
if constexpr (HasStaticName<TypeT>::value)
|
||||
diag << ": expected " << TypeT::name << ", but found " << type;
|
||||
return diag;
|
||||
}
|
||||
|
||||
return success();
|
||||
}
|
||||
@ -1270,8 +1288,13 @@ public:
|
||||
|
||||
// Check for the right kind of Type.
|
||||
result = llvm::dyn_cast<TypeT>(type);
|
||||
if (!result)
|
||||
return emitError(loc, "invalid kind of Type specified");
|
||||
if (!result) {
|
||||
InFlightDiagnostic diag =
|
||||
emitError(loc, "invalid kind of type specified");
|
||||
if constexpr (HasStaticName<TypeT>::value)
|
||||
diag << ": expected " << TypeT::name << ", but found " << type;
|
||||
return diag;
|
||||
}
|
||||
return success();
|
||||
}
|
||||
|
||||
@ -1307,8 +1330,13 @@ public:
|
||||
|
||||
// Check for the right kind of type.
|
||||
result = llvm::dyn_cast<TypeType>(type);
|
||||
if (!result)
|
||||
return emitError(loc, "invalid kind of type specified");
|
||||
if (!result) {
|
||||
InFlightDiagnostic diag =
|
||||
emitError(loc, "invalid kind of type specified");
|
||||
if constexpr (HasStaticName<TypeType>::value)
|
||||
diag << ": expected " << TypeType::name << ", but found " << type;
|
||||
return diag;
|
||||
}
|
||||
|
||||
return success();
|
||||
}
|
||||
|
||||
@ -281,7 +281,7 @@ func.func @test_assign_type_mismatch(%arg1: f32) {
|
||||
|
||||
func.func @test_assign_to_array(%arg1: !emitc.array<4xi32>) {
|
||||
%v = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.array<4xi32>
|
||||
// expected-error @+1 {{invalid kind of Type specified}}
|
||||
// expected-error @+1 {{invalid kind of type specified: expected emitc.lvalue, but found '!emitc.array<4xi32>'}}
|
||||
emitc.assign %arg1 : !emitc.array<4xi32> to %v : !emitc.array<4xi32>
|
||||
return
|
||||
}
|
||||
|
||||
@ -121,7 +121,7 @@ func.func @gep_missing_result_type(%pos : i64, %base : !llvm.ptr) {
|
||||
// -----
|
||||
|
||||
func.func @gep_non_function_type(%pos : i64, %base : !llvm.ptr) {
|
||||
// expected-error@+1 {{invalid kind of type specified}}
|
||||
// expected-error@+1 {{invalid kind of type specified: expected builtin.function, but found '!llvm.ptr'}}
|
||||
llvm.getelementptr %base[%pos] : !llvm.ptr
|
||||
}
|
||||
|
||||
|
||||
@ -347,7 +347,7 @@ func.func @sparse_wrong_arity_compression(%arg0: memref<?xf64>,
|
||||
// -----
|
||||
|
||||
func.func @sparse_convert_unranked(%arg0: tensor<*xf32>) -> tensor<10xf32> {
|
||||
// expected-error@+1 {{invalid kind of type specified}}
|
||||
// expected-error@+1 {{invalid kind of type specified: expected builtin.tensor, but found 'tensor<*xf32>'}}
|
||||
%0 = sparse_tensor.convert %arg0 : tensor<*xf32> to tensor<10xf32>
|
||||
return %0 : tensor<10xf32>
|
||||
}
|
||||
|
||||
@ -81,7 +81,7 @@ func.func @insert_too_many_indices(%arg0: f32, %arg1: tensor<?xf32>) {
|
||||
// -----
|
||||
|
||||
func.func @tensor.from_elements_wrong_result_type() {
|
||||
// expected-error@+2 {{'tensor.from_elements' invalid kind of type specified}}
|
||||
// expected-error@+2 {{'tensor.from_elements' invalid kind of type specified: expected builtin.tensor, but found 'tensor<*xi32>'}}
|
||||
%c0 = arith.constant 0 : i32
|
||||
%0 = tensor.from_elements %c0 : tensor<*xi32>
|
||||
return
|
||||
@ -459,7 +459,7 @@ func.func @pad_yield_type(%arg0: tensor<?x4xi32>, %arg1: i8) -> tensor<?x9xi32>
|
||||
// -----
|
||||
|
||||
func.func @invalid_splat(%v : f32) {
|
||||
// expected-error@+1 {{invalid kind of type specified}}
|
||||
// expected-error@+1 {{invalid kind of type specified: expected builtin.tensor, but found 'memref<8xf32>'}}
|
||||
tensor.splat %v : memref<8xf32>
|
||||
return
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// RUN: mlir-opt %s -split-input-file -verify-diagnostics
|
||||
|
||||
func.func @broadcast_to_scalar(%arg0: f32) -> f32 {
|
||||
// expected-error@+1 {{custom op 'vector.broadcast' invalid kind of type specified}}
|
||||
// expected-error@+1 {{custom op 'vector.broadcast' invalid kind of type specified: expected builtin.vector, but found 'f32'}}
|
||||
%0 = vector.broadcast %arg0 : f32 to f32
|
||||
}
|
||||
|
||||
@ -144,7 +144,7 @@ func.func @extract_element(%arg0: vector<4x4xf32>) {
|
||||
// -----
|
||||
|
||||
func.func @extract_vector_type(%arg0: index) {
|
||||
// expected-error@+1 {{invalid kind of type specified}}
|
||||
// expected-error@+1 {{invalid kind of type specified: expected builtin.vector, but found 'index'}}
|
||||
%1 = vector.extract %arg0[] : index from index
|
||||
}
|
||||
|
||||
@ -1174,7 +1174,7 @@ func.func @shape_cast_scalability_flag_is_dropped(%arg0 : vector<2x[15]x[2]xf32>
|
||||
// -----
|
||||
|
||||
func.func @bitcast_not_vector(%arg0 : vector<5x1x3x2xf32>) {
|
||||
// expected-error@+1 {{'vector.bitcast' invalid kind of type specified}}
|
||||
// expected-error@+1 {{'vector.bitcast' invalid kind of type specified: expected builtin.vector, but found 'f32'}}
|
||||
%0 = vector.bitcast %arg0 : vector<5x1x3x2xf32> to f32
|
||||
}
|
||||
|
||||
@ -1628,7 +1628,7 @@ func.func @scan_unsupported_kind(%arg0: vector<2x3xf32>, %arg1: vector<3xf32>) -
|
||||
// -----
|
||||
|
||||
func.func @invalid_splat(%v : f32) {
|
||||
// expected-error@+1 {{invalid kind of type specified}}
|
||||
// expected-error@+1 {{invalid kind of type specified: expected builtin.vector, but found 'memref<8xf32>'}}
|
||||
vector.splat %v : memref<8xf32>
|
||||
return
|
||||
}
|
||||
|
||||
@ -246,7 +246,7 @@ llvm.func @matrix_transpose_intr_wrong_type(%matrix : f32) -> vector<48xf32> {
|
||||
// -----
|
||||
|
||||
llvm.func @active_lane_intr_wrong_type(%base : i64, %n : vector<7xi64>) -> vector<7xi1> {
|
||||
// expected-error @below{{invalid kind of type specified}}
|
||||
// expected-error @below{{invalid kind of type specified: expected builtin.integer, but found 'vector<7xi64>'}}
|
||||
%0 = llvm.intr.get.active.lane.mask %base, %n : i64, vector<7xi64> to vector<7xi1>
|
||||
llvm.return %0 : vector<7xi1>
|
||||
}
|
||||
|
||||
@ -129,7 +129,7 @@ func.func private @test_verifier_fails() -> () attributes {
|
||||
// -----
|
||||
|
||||
func.func private @test_attr_with_type_failed_to_parse_type() -> () attributes {
|
||||
// expected-error@+2 {{invalid kind of type specified}}
|
||||
// expected-error@+2 {{invalid kind of type specified: expected builtin.integer, but found 'vector<4xi32>'}}
|
||||
// expected-error@+1 {{failed to parse TestAttrWithTypeParam parameter 'int_type'}}
|
||||
attr = #test.attr_with_type<vector<4xi32>, vector<4xi32>>
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user