Skip to content

Commit 8e1718f

Browse files
matthias-springerYilin Li
authored and
Yilin Li
committed
[mlir][IR] Improve error message when parsing incorrect type (llvm#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 llvm#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`).
1 parent bc5bde4 commit 8e1718f

File tree

8 files changed

+45
-17
lines changed

8 files changed

+45
-17
lines changed

mlir/include/mlir/IR/OpImplementation.h

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,19 @@
2121
#include "llvm/Support/SMLoc.h"
2222
#include <optional>
2323

24+
namespace {
25+
// reference https://stackoverflow.com/a/16000226
26+
template <typename T, typename = void>
27+
struct HasStaticName : std::false_type {};
28+
29+
template <typename T>
30+
struct HasStaticName<T,
31+
typename std::enable_if<
32+
std::is_same<::llvm::StringLiteral,
33+
std::decay_t<decltype(T::name)>>::value,
34+
void>::type> : std::true_type {};
35+
} // namespace
36+
2437
namespace mlir {
2538
class AsmParsedResourceEntry;
2639
class AsmResourceBuilder;
@@ -1238,8 +1251,13 @@ class AsmParser {
12381251

12391252
// Check for the right kind of type.
12401253
result = llvm::dyn_cast<TypeT>(type);
1241-
if (!result)
1242-
return emitError(loc, "invalid kind of type specified");
1254+
if (!result) {
1255+
InFlightDiagnostic diag =
1256+
emitError(loc, "invalid kind of type specified");
1257+
if constexpr (HasStaticName<TypeT>::value)
1258+
diag << ": expected " << TypeT::name << ", but found " << type;
1259+
return diag;
1260+
}
12431261

12441262
return success();
12451263
}
@@ -1270,8 +1288,13 @@ class AsmParser {
12701288

12711289
// Check for the right kind of Type.
12721290
result = llvm::dyn_cast<TypeT>(type);
1273-
if (!result)
1274-
return emitError(loc, "invalid kind of Type specified");
1291+
if (!result) {
1292+
InFlightDiagnostic diag =
1293+
emitError(loc, "invalid kind of type specified");
1294+
if constexpr (HasStaticName<TypeT>::value)
1295+
diag << ": expected " << TypeT::name << ", but found " << type;
1296+
return diag;
1297+
}
12751298
return success();
12761299
}
12771300

@@ -1307,8 +1330,13 @@ class AsmParser {
13071330

13081331
// Check for the right kind of type.
13091332
result = llvm::dyn_cast<TypeType>(type);
1310-
if (!result)
1311-
return emitError(loc, "invalid kind of type specified");
1333+
if (!result) {
1334+
InFlightDiagnostic diag =
1335+
emitError(loc, "invalid kind of type specified");
1336+
if constexpr (HasStaticName<TypeType>::value)
1337+
diag << ": expected " << TypeType::name << ", but found " << type;
1338+
return diag;
1339+
}
13121340

13131341
return success();
13141342
}

mlir/test/Dialect/EmitC/invalid_ops.mlir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ func.func @test_assign_type_mismatch(%arg1: f32) {
281281

282282
func.func @test_assign_to_array(%arg1: !emitc.array<4xi32>) {
283283
%v = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.array<4xi32>
284-
// expected-error @+1 {{invalid kind of Type specified}}
284+
// expected-error @+1 {{invalid kind of type specified: expected emitc.lvalue, but found '!emitc.array<4xi32>'}}
285285
emitc.assign %arg1 : !emitc.array<4xi32> to %v : !emitc.array<4xi32>
286286
return
287287
}

mlir/test/Dialect/LLVMIR/invalid.mlir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ func.func @gep_missing_result_type(%pos : i64, %base : !llvm.ptr) {
121121
// -----
122122

123123
func.func @gep_non_function_type(%pos : i64, %base : !llvm.ptr) {
124-
// expected-error@+1 {{invalid kind of type specified}}
124+
// expected-error@+1 {{invalid kind of type specified: expected builtin.function, but found '!llvm.ptr'}}
125125
llvm.getelementptr %base[%pos] : !llvm.ptr
126126
}
127127

mlir/test/Dialect/SparseTensor/invalid.mlir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ func.func @sparse_wrong_arity_compression(%arg0: memref<?xf64>,
347347
// -----
348348

349349
func.func @sparse_convert_unranked(%arg0: tensor<*xf32>) -> tensor<10xf32> {
350-
// expected-error@+1 {{invalid kind of type specified}}
350+
// expected-error@+1 {{invalid kind of type specified: expected builtin.tensor, but found 'tensor<*xf32>'}}
351351
%0 = sparse_tensor.convert %arg0 : tensor<*xf32> to tensor<10xf32>
352352
return %0 : tensor<10xf32>
353353
}

mlir/test/Dialect/Tensor/invalid.mlir

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func.func @insert_too_many_indices(%arg0: f32, %arg1: tensor<?xf32>) {
8181
// -----
8282

8383
func.func @tensor.from_elements_wrong_result_type() {
84-
// expected-error@+2 {{'tensor.from_elements' invalid kind of type specified}}
84+
// expected-error@+2 {{'tensor.from_elements' invalid kind of type specified: expected builtin.tensor, but found 'tensor<*xi32>'}}
8585
%c0 = arith.constant 0 : i32
8686
%0 = tensor.from_elements %c0 : tensor<*xi32>
8787
return
@@ -459,7 +459,7 @@ func.func @pad_yield_type(%arg0: tensor<?x4xi32>, %arg1: i8) -> tensor<?x9xi32>
459459
// -----
460460

461461
func.func @invalid_splat(%v : f32) {
462-
// expected-error@+1 {{invalid kind of type specified}}
462+
// expected-error@+1 {{invalid kind of type specified: expected builtin.tensor, but found 'memref<8xf32>'}}
463463
tensor.splat %v : memref<8xf32>
464464
return
465465
}

mlir/test/Dialect/Vector/invalid.mlir

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// RUN: mlir-opt %s -split-input-file -verify-diagnostics
22

33
func.func @broadcast_to_scalar(%arg0: f32) -> f32 {
4-
// expected-error@+1 {{custom op 'vector.broadcast' invalid kind of type specified}}
4+
// expected-error@+1 {{custom op 'vector.broadcast' invalid kind of type specified: expected builtin.vector, but found 'f32'}}
55
%0 = vector.broadcast %arg0 : f32 to f32
66
}
77

@@ -144,7 +144,7 @@ func.func @extract_element(%arg0: vector<4x4xf32>) {
144144
// -----
145145

146146
func.func @extract_vector_type(%arg0: index) {
147-
// expected-error@+1 {{invalid kind of type specified}}
147+
// expected-error@+1 {{invalid kind of type specified: expected builtin.vector, but found 'index'}}
148148
%1 = vector.extract %arg0[] : index from index
149149
}
150150

@@ -1174,7 +1174,7 @@ func.func @shape_cast_scalability_flag_is_dropped(%arg0 : vector<2x[15]x[2]xf32>
11741174
// -----
11751175

11761176
func.func @bitcast_not_vector(%arg0 : vector<5x1x3x2xf32>) {
1177-
// expected-error@+1 {{'vector.bitcast' invalid kind of type specified}}
1177+
// expected-error@+1 {{'vector.bitcast' invalid kind of type specified: expected builtin.vector, but found 'f32'}}
11781178
%0 = vector.bitcast %arg0 : vector<5x1x3x2xf32> to f32
11791179
}
11801180

@@ -1628,7 +1628,7 @@ func.func @scan_unsupported_kind(%arg0: vector<2x3xf32>, %arg1: vector<3xf32>) -
16281628
// -----
16291629

16301630
func.func @invalid_splat(%v : f32) {
1631-
// expected-error@+1 {{invalid kind of type specified}}
1631+
// expected-error@+1 {{invalid kind of type specified: expected builtin.vector, but found 'memref<8xf32>'}}
16321632
vector.splat %v : memref<8xf32>
16331633
return
16341634
}

mlir/test/Target/LLVMIR/llvmir-invalid.mlir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ llvm.func @matrix_transpose_intr_wrong_type(%matrix : f32) -> vector<48xf32> {
246246
// -----
247247

248248
llvm.func @active_lane_intr_wrong_type(%base : i64, %n : vector<7xi64>) -> vector<7xi1> {
249-
// expected-error @below{{invalid kind of type specified}}
249+
// expected-error @below{{invalid kind of type specified: expected builtin.integer, but found 'vector<7xi64>'}}
250250
%0 = llvm.intr.get.active.lane.mask %base, %n : i64, vector<7xi64> to vector<7xi1>
251251
llvm.return %0 : vector<7xi1>
252252
}

mlir/test/mlir-tblgen/attr-or-type-format.mlir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ func.func private @test_verifier_fails() -> () attributes {
129129
// -----
130130

131131
func.func private @test_attr_with_type_failed_to_parse_type() -> () attributes {
132-
// expected-error@+2 {{invalid kind of type specified}}
132+
// expected-error@+2 {{invalid kind of type specified: expected builtin.integer, but found 'vector<4xi32>'}}
133133
// expected-error@+1 {{failed to parse TestAttrWithTypeParam parameter 'int_type'}}
134134
attr = #test.attr_with_type<vector<4xi32>, vector<4xi32>>
135135
}

0 commit comments

Comments
 (0)