[tint][ir] Stylize more validator diagnostics
Change-Id: I9c9712c6aaad4d90769407edb45e6529849e74e3
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/186624
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/lang/core/ir/disassembly.cc b/src/tint/lang/core/ir/disassembly.cc
index a07033f..df0cc4e 100644
--- a/src/tint/lang/core/ir/disassembly.cc
+++ b/src/tint/lang/core/ir/disassembly.cc
@@ -30,6 +30,7 @@
#include <string_view>
#include "src//tint/lang/core/ir/unary.h"
+#include "src/tint/lang/core/binary_op.h"
#include "src/tint/lang/core/constant/composite.h"
#include "src/tint/lang/core/constant/scalar.h"
#include "src/tint/lang/core/constant/splat.h"
@@ -796,64 +797,7 @@
void Disassembly::EmitBinary(const Binary* b) {
SourceMarker sm(this);
EmitValueWithType(b);
- out_ << " = ";
- switch (b->Op()) {
- case BinaryOp::kAdd:
- out_ << StyleInstruction("add");
- break;
- case BinaryOp::kSubtract:
- out_ << StyleInstruction("sub");
- break;
- case BinaryOp::kMultiply:
- out_ << StyleInstruction("mul");
- break;
- case BinaryOp::kDivide:
- out_ << StyleInstruction("div");
- break;
- case BinaryOp::kModulo:
- out_ << StyleInstruction("mod");
- break;
- case BinaryOp::kAnd:
- out_ << StyleInstruction("and");
- break;
- case BinaryOp::kOr:
- out_ << StyleInstruction("or");
- break;
- case BinaryOp::kXor:
- out_ << StyleInstruction("xor");
- break;
- case BinaryOp::kEqual:
- out_ << StyleInstruction("eq");
- break;
- case BinaryOp::kNotEqual:
- out_ << StyleInstruction("neq");
- break;
- case BinaryOp::kLessThan:
- out_ << StyleInstruction("lt");
- break;
- case BinaryOp::kGreaterThan:
- out_ << StyleInstruction("gt");
- break;
- case BinaryOp::kLessThanEqual:
- out_ << StyleInstruction("lte");
- break;
- case BinaryOp::kGreaterThanEqual:
- out_ << StyleInstruction("gte");
- break;
- case BinaryOp::kShiftLeft:
- out_ << StyleInstruction("shl");
- break;
- case BinaryOp::kShiftRight:
- out_ << StyleInstruction("shr");
- break;
- case BinaryOp::kLogicalAnd:
- out_ << StyleInstruction("logical-and");
- break;
- case BinaryOp::kLogicalOr:
- out_ << StyleInstruction("logical-or");
- break;
- }
- out_ << " ";
+ out_ << " = " << NameOf(b->Op()) << " ";
EmitOperandList(b);
sm.Store(b);
@@ -862,25 +806,7 @@
void Disassembly::EmitUnary(const Unary* u) {
SourceMarker sm(this);
EmitValueWithType(u);
- out_ << " = ";
- switch (u->Op()) {
- case UnaryOp::kComplement:
- out_ << StyleInstruction("complement");
- break;
- case UnaryOp::kNegation:
- out_ << StyleInstruction("negation");
- break;
- case UnaryOp::kAddressOf:
- out_ << StyleInstruction("ref-to-ptr");
- break;
- case UnaryOp::kIndirection:
- out_ << StyleInstruction("ptr-to-ref");
- break;
- case UnaryOp::kNot:
- out_ << StyleInstruction("not");
- break;
- }
- out_ << " ";
+ out_ << " = " << NameOf(u->Op()) << " ";
EmitOperandList(u);
sm.Store(u);
@@ -984,4 +910,62 @@
return StyledText{} << StyleInstruction(name);
}
+StyledText Disassembly::NameOf(BinaryOp op) {
+ switch (op) {
+ case BinaryOp::kAdd:
+ return StyledText{} << StyleInstruction("add");
+ case BinaryOp::kSubtract:
+ return StyledText{} << StyleInstruction("sub");
+ case BinaryOp::kMultiply:
+ return StyledText{} << StyleInstruction("mul");
+ case BinaryOp::kDivide:
+ return StyledText{} << StyleInstruction("div");
+ case BinaryOp::kModulo:
+ return StyledText{} << StyleInstruction("mod");
+ case BinaryOp::kAnd:
+ return StyledText{} << StyleInstruction("and");
+ case BinaryOp::kOr:
+ return StyledText{} << StyleInstruction("or");
+ case BinaryOp::kXor:
+ return StyledText{} << StyleInstruction("xor");
+ case BinaryOp::kEqual:
+ return StyledText{} << StyleInstruction("eq");
+ case BinaryOp::kNotEqual:
+ return StyledText{} << StyleInstruction("neq");
+ case BinaryOp::kLessThan:
+ return StyledText{} << StyleInstruction("lt");
+ case BinaryOp::kGreaterThan:
+ return StyledText{} << StyleInstruction("gt");
+ case BinaryOp::kLessThanEqual:
+ return StyledText{} << StyleInstruction("lte");
+ case BinaryOp::kGreaterThanEqual:
+ return StyledText{} << StyleInstruction("gte");
+ case BinaryOp::kShiftLeft:
+ return StyledText{} << StyleInstruction("shl");
+ case BinaryOp::kShiftRight:
+ return StyledText{} << StyleInstruction("shr");
+ case BinaryOp::kLogicalAnd:
+ return StyledText{} << StyleInstruction("logical-and");
+ case BinaryOp::kLogicalOr:
+ return StyledText{} << StyleInstruction("logical-or");
+ }
+ TINT_UNREACHABLE() << op;
+}
+
+StyledText Disassembly::NameOf(UnaryOp op) {
+ switch (op) {
+ case UnaryOp::kComplement:
+ return StyledText{} << StyleInstruction("complement");
+ case UnaryOp::kNegation:
+ return StyledText{} << StyleInstruction("negation");
+ case UnaryOp::kAddressOf:
+ return StyledText{} << StyleInstruction("ref-to-ptr");
+ case UnaryOp::kIndirection:
+ return StyledText{} << StyleInstruction("ptr-to-ref");
+ case UnaryOp::kNot:
+ return StyledText{} << StyleInstruction("not");
+ }
+ TINT_UNREACHABLE() << op;
+}
+
} // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/disassembly.h b/src/tint/lang/core/ir/disassembly.h
index 677b386..70c48b4 100644
--- a/src/tint/lang/core/ir/disassembly.h
+++ b/src/tint/lang/core/ir/disassembly.h
@@ -32,6 +32,7 @@
#include <string>
#include <string_view>
+#include "src/tint/lang/core/binary_op.h"
#include "src/tint/lang/core/ir/binary.h"
#include "src/tint/lang/core/ir/block.h"
#include "src/tint/lang/core/ir/block_param.h"
@@ -108,6 +109,12 @@
/// @returns the disassembled name for the Switch @p inst
StyledText NameOf(const Switch* inst);
+ /// @returns the disassembled name for the BinaryOp @p op
+ StyledText NameOf(BinaryOp op);
+
+ /// @returns the disassembled name for the UnaryOp @p op
+ StyledText NameOf(UnaryOp op);
+
/// @param inst the instruction to retrieve
/// @returns the source for the instruction
Source InstructionSource(const Instruction* inst) const {
diff --git a/src/tint/lang/core/ir/validator.cc b/src/tint/lang/core/ir/validator.cc
index e945cc6..892aa4a 100644
--- a/src/tint/lang/core/ir/validator.cc
+++ b/src/tint/lang/core/ir/validator.cc
@@ -80,7 +80,6 @@
#include "src/tint/utils/containers/transform.h"
#include "src/tint/utils/ice/ice.h"
#include "src/tint/utils/macros/defer.h"
-#include "src/tint/utils/macros/scoped_assignment.h"
#include "src/tint/utils/rtti/switch.h"
#include "src/tint/utils/text/styled_text.h"
#include "src/tint/utils/text/text_style.h"
@@ -789,7 +788,10 @@
void Validator::CheckVar(const Var* var) {
if (var->Result(0) && var->Initializer()) {
if (var->Initializer()->Type() != var->Result(0)->Type()->UnwrapPtrOrRef()) {
- AddError(var) << "initializer has incorrect type";
+ AddError(var) << "initializer type "
+ << style::Type(var->Initializer()->Type()->FriendlyName())
+ << " does not match store type "
+ << style::Type(var->Result(0)->Type()->UnwrapPtrOrRef()->FriendlyName());
}
}
}
@@ -799,7 +801,9 @@
if (let->Result(0) && let->Value()) {
if (let->Result(0)->Type() != let->Value()->Type()) {
- AddError(let) << "result type does not match value type";
+ AddError(let) << "result type " << style::Type(let->Result(0)->Type()->FriendlyName())
+ << " does not match value type "
+ << style::Type(let->Value()->Type()->FriendlyName());
}
}
}
@@ -859,8 +863,9 @@
for (size_t i = 0; i < args.Length(); i++) {
if (args[i]->Type() != params[i]->Type()) {
AddError(call, UserCall::kArgsOperandOffset + i)
- << "function parameter " << i << " is of type " << params[i]->Type()->FriendlyName()
- << ", but argument is of type " << args[i]->Type()->FriendlyName();
+ << "function parameter " << i << " is of type "
+ << style::Type(params[i]->Type()->FriendlyName()) << ", but argument is of type "
+ << style::Type(args[i]->Type()->FriendlyName());
}
}
}
@@ -880,13 +885,15 @@
auto desc_of = [&](Kind kind, const core::type::Type* type) {
switch (kind) {
case kPtr:
- return StyledText{} << "ptr<" << obj_view->AddressSpace() << ", "
- << type->FriendlyName() << ", " << obj_view->Access() << ">";
+ return StyledText{}
+ << style::Type("ptr<", obj_view->AddressSpace(), ", ", type->FriendlyName(),
+ ", ", obj_view->Access(), ">");
case kRef:
- return StyledText{} << "ref<" << obj_view->AddressSpace() << ", "
- << type->FriendlyName() << ", " << obj_view->Access() << ">";
+ return StyledText{}
+ << style::Type("ref<", obj_view->AddressSpace(), ", ", type->FriendlyName(),
+ ", ", obj_view->Access(), ">");
default:
- return StyledText{} << type->FriendlyName();
+ return StyledText{} << style::Type(type->FriendlyName());
}
};
@@ -957,7 +964,7 @@
if (TINT_UNLIKELY(!ok)) {
AddError(a) << "result of access chain is type " << desc_of(in_kind, ty)
- << " but instruction type is " << want->FriendlyName();
+ << " but instruction type is " << style::Type(want->FriendlyName());
}
}
@@ -966,11 +973,7 @@
if (b->LHS() && b->RHS()) {
auto symbols = SymbolTable::Wrap(mod_.symbols);
auto type_mgr = type::Manager::Wrap(mod_.Types());
- intrinsic::Context context{
- b->TableData(),
- type_mgr,
- symbols,
- };
+ intrinsic::Context context{b->TableData(), type_mgr, symbols};
auto overload =
core::intrinsic::LookupBinary(context, b->Op(), b->LHS()->Type(), b->RHS()->Type(),
@@ -982,11 +985,10 @@
if (auto* result = b->Result(0)) {
if (overload->return_type != result->Type()) {
- StringStream err;
- err << "binary instruction result type (" << result->Type()->FriendlyName()
- << ") does not match overload result type ("
- << overload->return_type->FriendlyName() << ")";
- AddError(b) << err.str();
+ AddError(b) << "result value type " << style::Type(result->Type()->FriendlyName())
+ << " does not match "
+ << style::Instruction(Disassembly().NameOf(b->Op())) << " result type "
+ << style::Type(overload->return_type->FriendlyName());
}
}
}
@@ -997,11 +999,7 @@
if (u->Val()) {
auto symbols = SymbolTable::Wrap(mod_.symbols);
auto type_mgr = type::Manager::Wrap(mod_.Types());
- intrinsic::Context context{
- u->TableData(),
- type_mgr,
- symbols,
- };
+ intrinsic::Context context{u->TableData(), type_mgr, symbols};
auto overload = core::intrinsic::LookupUnary(context, u->Op(), u->Val()->Type(),
core::EvaluationStage::kRuntime);
@@ -1012,11 +1010,10 @@
if (auto* result = u->Result(0)) {
if (overload->return_type != result->Type()) {
- StringStream err;
- err << "unary instruction result type (" << result->Type()->FriendlyName()
- << ") does not match overload result type ("
- << overload->return_type->FriendlyName() << ")";
- AddError(u) << err.str();
+ AddError(u) << "result value type " << style::Type(result->Type()->FriendlyName())
+ << " does not match "
+ << style::Instruction(Disassembly().NameOf(u->Op())) << " result type "
+ << style::Type(overload->return_type->FriendlyName());
}
}
}
@@ -1026,7 +1023,8 @@
CheckOperandNotNull(if_, if_->Condition(), If::kConditionOperandOffset);
if (if_->Condition() && !if_->Condition()->Type()->Is<core::type::Bool>()) {
- AddError(if_, If::kConditionOperandOffset) << "condition must be a `bool` type";
+ AddError(if_, If::kConditionOperandOffset)
+ << "condition type must be " << style::Type("bool");
}
tasks_.Push([this] { control_stack_.Pop(); });
@@ -1114,9 +1112,9 @@
for (size_t i = 0; i < results.Length(); ++i) {
if (results[i] && args[i] && results[i]->Type() != args[i]->Type()) {
- AddError(e, i) << "argument type (" << results[i]->Type()->FriendlyName()
- << ") does not match control instruction type ("
- << args[i]->Type()->FriendlyName() << ")";
+ AddError(e, i) << "argument type " << style::Type(results[i]->Type()->FriendlyName())
+ << " does not match control instruction type "
+ << style::Type(args[i]->Type()->FriendlyName());
AddNote(e->ControlInstruction()) << "control instruction";
}
}
@@ -1150,7 +1148,10 @@
if (!ret->Value()) {
AddError(ret) << "expected return value";
} else if (ret->Value()->Type() != func->ReturnType()) {
- AddError(ret) << "return value type does not match function return type";
+ AddError(ret) << "return value type "
+ << style::Type(ret->Value()->Type()->FriendlyName())
+ << " does not match function return type "
+ << style::Type(func->ReturnType()->FriendlyName());
}
}
}
@@ -1214,7 +1215,10 @@
return;
}
if (l->Result(0)->Type() != mv->StoreType()) {
- AddError(l, Load::kFromOperandOffset) << "result type does not match source store type";
+ AddError(l, Load::kFromOperandOffset)
+ << "result type " << style::Type(l->Result(0)->Type()->FriendlyName())
+ << " does not match source store type "
+ << style::Type(mv->StoreType()->FriendlyName());
}
}
}
@@ -1230,8 +1234,12 @@
<< "store target operand is not a memory view";
return;
}
- if (from->Type() != mv->StoreType()) {
- AddError(s, Store::kFromOperandOffset) << "value type does not match store type";
+ auto* value_type = from->Type();
+ auto* store_type = mv->StoreType();
+ if (value_type != store_type) {
+ AddError(s, Store::kFromOperandOffset)
+ << "value type " << style::Type(value_type->FriendlyName())
+ << " does not match store type " << style::Type(store_type->FriendlyName());
}
}
}
@@ -1245,7 +1253,9 @@
if (auto* res = l->Result(0)) {
if (auto* el_ty = GetVectorPtrElementType(l, LoadVectorElement::kFromOperandOffset)) {
if (res->Type() != el_ty) {
- AddResultError(l, 0) << "result type does not match vector pointer element type";
+ AddResultError(l, 0) << "result type " << style::Type(res->Type()->FriendlyName())
+ << " does not match vector pointer element type "
+ << style::Type(el_ty->FriendlyName());
}
}
}
@@ -1260,7 +1270,9 @@
if (auto* el_ty = GetVectorPtrElementType(s, StoreVectorElement::kToOperandOffset)) {
if (value->Type() != el_ty) {
AddError(s, StoreVectorElement::kValueOperandOffset)
- << "value type does not match vector pointer element type";
+ << "value type " << style::Type(value->Type()->FriendlyName())
+ << " does not match vector pointer element type "
+ << style::Type(el_ty->FriendlyName());
}
}
}
@@ -1285,7 +1297,8 @@
}
}
- AddError(inst, idx) << "operand must be a pointer to vector, got " << type->FriendlyName();
+ AddError(inst, idx) << "operand must be a pointer to vector, got "
+ << style::Type(type->FriendlyName());
return nullptr;
}
diff --git a/src/tint/lang/core/ir/validator_test.cc b/src/tint/lang/core/ir/validator_test.cc
index 864e24d..2619338 100644
--- a/src/tint/lang/core/ir/validator_test.cc
+++ b/src/tint/lang/core/ir/validator_test.cc
@@ -394,8 +394,9 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
- EXPECT_EQ(res.Failure().reason.Str(),
- R"(:8:28 error: call: function parameter 1 is of type i32, but argument is of type f32
+ EXPECT_EQ(
+ res.Failure().reason.Str(),
+ R"(:8:28 error: call: function parameter 1 is of type 'i32', but argument is of type 'f32'
%6:void = call %g, 1i, 2.0f, 3i
^^^^
@@ -631,7 +632,7 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
EXPECT_EQ(res.Failure().reason.Str(),
- R"(:3:29 error: access: index out of bounds for type vec2<f32>
+ R"(:3:29 error: access: index out of bounds for type 'vec2<f32>'
%3:f32 = access %2, 1u, 3u
^^
@@ -667,7 +668,7 @@
ASSERT_NE(res, Success);
EXPECT_EQ(
res.Failure().reason.Str(),
- R"(:3:55 error: access: index out of bounds for type ptr<private, array<f32, 2>, read_write>
+ R"(:3:55 error: access: index out of bounds for type 'ptr<private, array<f32, 2>, read_write>'
%3:ptr<private, f32, read_write> = access %2, 1u, 3u
^^
@@ -701,7 +702,7 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
- EXPECT_EQ(res.Failure().reason.Str(), R"(:3:25 error: access: type f32 cannot be indexed
+ EXPECT_EQ(res.Failure().reason.Str(), R"(:3:25 error: access: type 'f32' cannot be indexed
%3:f32 = access %2, 1u
^^
@@ -732,7 +733,7 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
EXPECT_EQ(res.Failure().reason.Str(),
- R"(:3:51 error: access: type ptr<private, f32, read_write> cannot be indexed
+ R"(:3:51 error: access: type 'ptr<private, f32, read_write>' cannot be indexed
%3:ptr<private, f32, read_write> = access %2, 1u
^^
@@ -769,7 +770,7 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
EXPECT_EQ(res.Failure().reason.Str(),
- R"(:8:25 error: access: type MyStruct cannot be dynamically indexed
+ R"(:8:25 error: access: type 'MyStruct' cannot be dynamically indexed
%4:i32 = access %2, %3
^^
@@ -812,7 +813,7 @@
ASSERT_NE(res, Success);
EXPECT_EQ(
res.Failure().reason.Str(),
- R"(:8:25 error: access: type ptr<private, MyStruct, read_write> cannot be dynamically indexed
+ R"(:8:25 error: access: type 'ptr<private, MyStruct, read_write>' cannot be dynamically indexed
%4:i32 = access %2, %3
^^
@@ -847,8 +848,9 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
- EXPECT_EQ(res.Failure().reason.Str(),
- R"(:3:14 error: access: result of access chain is type f32 but instruction type is i32
+ EXPECT_EQ(
+ res.Failure().reason.Str(),
+ R"(:3:14 error: access: result of access chain is type 'f32' but instruction type is 'i32'
%3:i32 = access %2, 1u, 1u
^^^^^^
@@ -880,7 +882,7 @@
ASSERT_NE(res, Success);
EXPECT_EQ(
res.Failure().reason.Str(),
- R"(:3:40 error: access: result of access chain is type ptr<private, f32, read_write> but instruction type is ptr<private, i32, read_write>
+ R"(:3:40 error: access: result of access chain is type 'ptr<private, f32, read_write>' but instruction type is 'ptr<private, i32, read_write>'
%3:ptr<private, i32, read_write> = access %2, 1u, 1u
^^^^^^
@@ -912,7 +914,7 @@
ASSERT_NE(res, Success);
EXPECT_EQ(
res.Failure().reason.Str(),
- R"(:3:14 error: access: result of access chain is type ptr<private, f32, read_write> but instruction type is f32
+ R"(:3:14 error: access: result of access chain is type 'ptr<private, f32, read_write>' but instruction type is 'f32'
%3:f32 = access %2, 1u, 1u
^^^^^^
@@ -1034,7 +1036,7 @@
ASSERT_NE(res, Success);
EXPECT_EQ(
res.Failure().reason.Str(),
- R"(:3:34 error: access: result of access chain is type ptr<storage, f32, read> but instruction type is ptr<uniform, f32, read>
+ R"(:3:34 error: access: result of access chain is type 'ptr<storage, f32, read>' but instruction type is 'ptr<uniform, f32, read>'
%3:ptr<uniform, f32, read> = access %2, 1u
^^^^^^
@@ -1066,7 +1068,7 @@
ASSERT_NE(res, Success);
EXPECT_EQ(
res.Failure().reason.Str(),
- R"(:3:40 error: access: result of access chain is type ptr<storage, f32, read> but instruction type is ptr<storage, f32, read_write>
+ R"(:3:40 error: access: result of access chain is type 'ptr<storage, f32, read>' but instruction type is 'ptr<storage, f32, read_write>'
%3:ptr<storage, f32, read_write> = access %2, 1u
^^^^^^
@@ -1197,7 +1199,7 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
- EXPECT_EQ(res.Failure().reason.Str(), R"(:3:8 error: if: condition must be a `bool` type
+ EXPECT_EQ(res.Failure().reason.Str(), R"(:3:8 error: if: condition type must be 'bool'
if 1i [t: $B2, f: $B3] { # if_1
^^
@@ -1400,7 +1402,8 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
- EXPECT_EQ(res.Failure().reason.Str(), R"(:3:41 error: var: initializer has incorrect type
+ EXPECT_EQ(res.Failure().reason.Str(),
+ R"(:3:41 error: var: initializer type 'i32' does not match store type 'f32'
%2:ptr<function, f32, read_write> = var, 1i
^^^
@@ -1488,7 +1491,8 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
- EXPECT_EQ(res.Failure().reason.Str(), R"(:3:14 error: let: result type does not match value type
+ EXPECT_EQ(res.Failure().reason.Str(),
+ R"(:3:14 error: let: result type 'f32' does not match value type 'i32'
%2:f32 = let 1i
^^^
@@ -1813,7 +1817,7 @@
ASSERT_NE(res, Success);
EXPECT_EQ(
res.Failure().reason.Str(),
- R"(:3:5 error: unary: unary instruction result type (f32) does not match overload result type (i32)
+ R"(:3:5 error: unary: result value type 'f32' does not match complement result type 'i32'
%2:f32 = complement 2i
^^^^^^^^^^^^^^^^^^^^^^
@@ -1998,7 +2002,7 @@
ASSERT_NE(res, Success);
EXPECT_EQ(
res.Failure().reason.Str(),
- R"(:5:21 error: exit_if: argument type (f32) does not match control instruction type (i32)
+ R"(:5:21 error: exit_if: argument type 'f32' does not match control instruction type 'i32'
exit_if 1i, 2i # if_1
^^
@@ -2392,7 +2396,7 @@
ASSERT_NE(res, Success);
EXPECT_EQ(
res.Failure().reason.Str(),
- R"(:5:25 error: exit_switch: argument type (f32) does not match control instruction type (i32)
+ R"(:5:25 error: exit_switch: argument type 'f32' does not match control instruction type 'i32'
exit_switch 1i, 2i # switch_1
^^
@@ -2780,7 +2784,7 @@
ASSERT_NE(res, Success);
EXPECT_EQ(
res.Failure().reason.Str(),
- R"(:5:23 error: exit_loop: argument type (f32) does not match control instruction type (i32)
+ R"(:5:23 error: exit_loop: argument type 'f32' does not match control instruction type 'i32'
exit_loop 1i, 2i # loop_1
^^
@@ -3300,8 +3304,9 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
- EXPECT_EQ(res.Failure().reason.Str(),
- R"(:3:5 error: return: return value type does not match function return type
+ EXPECT_EQ(
+ res.Failure().reason.Str(),
+ R"(:3:5 error: return: return value type 'f32' does not match function return type 'i32'
ret 42.0f
^^^^^^^^^
@@ -3392,7 +3397,7 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
EXPECT_EQ(res.Failure().reason.Str(),
- R"(:4:19 error: load: result type does not match source store type
+ R"(:4:19 error: load: result type 'f32' does not match source store type 'i32'
%3:f32 = load %2
^^
@@ -3512,7 +3517,7 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
EXPECT_EQ(res.Failure().reason.Str(),
- R"(:4:15 error: store: value type does not match store type
+ R"(:4:15 error: store: value type 'u32' does not match store type 'i32'
store %2, 42u
^^^
@@ -3672,7 +3677,7 @@
$B1: {
^^^
-:4:37 error: store_vector_element: value type does not match vector pointer element type
+:4:37 error: store_vector_element: value type 'i32' does not match vector pointer element type 'f32'
store_vector_element %2, undef, 2i
^^