[ir][spirv-writer] Rework remaining unit tests
Switch almost all tests over to using the `Generate()` and EXPECT_INST
helpers. Fixup some cases of invalid IR that this caught, and tweak
some tests to make sure we're testing the right thing in the presence
of sanitizer transforms.
The `Type` and `Constant` tests still use the PIMPL methods directly,
as types and constants are emitted lazily on first use.
Make almost all of the PIMPL methods private.
Bug: tint:1906
Change-Id: Ia52700e8298b5da5d22770a3949509082cb208bb
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/139543
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: James Price <jrprice@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir.cc b/src/tint/writer/spirv/ir/generator_impl_ir.cc
index 2498fcc..7b96272 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir.cc
@@ -194,7 +194,14 @@
}
uint32_t GeneratorImplIr::Constant(ir::Constant* constant) {
- return Constant(constant->Value());
+ auto id = Constant(constant->Value());
+
+ // Set the name for the SPIR-V result ID if provided in the module.
+ if (auto name = ir_->NameOf(constant)) {
+ module_.PushDebug(spv::Op::OpName, {id, Operand(name.Name())});
+ }
+
+ return id;
}
uint32_t GeneratorImplIr::Constant(const constant::Value* constant) {
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir.h b/src/tint/writer/spirv/ir/generator_impl_ir.h
index 01ab913..e2a78bc 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir.h
+++ b/src/tint/writer/spirv/ir/generator_impl_ir.h
@@ -85,11 +85,6 @@
/// @returns the result ID of the constant
uint32_t Constant(ir::Constant* constant);
- /// Get the result ID of the OpConstantNull instruction for `type`, emitting it if necessary.
- /// @param type the type to get the ID for
- /// @returns the result ID of the OpConstantNull instruction
- uint32_t ConstantNull(const type::Type* type);
-
/// Get the result ID of the type `ty`, emitting a type declaration instruction if necessary.
/// @param ty the type to get the ID for
/// @param addrspace the optional address space that this type is being used for
@@ -97,6 +92,29 @@
uint32_t Type(const type::Type* ty,
builtin::AddressSpace addrspace = builtin::AddressSpace::kUndefined);
+ private:
+ /// Convert a builtin to the corresponding SPIR-V enum value, taking into account the target
+ /// address space. Adds any capabilities needed for the builtin.
+ /// @param builtin the builtin to convert
+ /// @param addrspace the address space the builtin is being used in
+ /// @returns the enum value of the corresponding SPIR-V builtin
+ uint32_t Builtin(builtin::BuiltinValue builtin, builtin::AddressSpace addrspace);
+
+ /// Get the result ID of the constant `constant`, emitting its instruction if necessary.
+ /// @param constant the constant to get the ID for
+ /// @returns the result ID of the constant
+ uint32_t Constant(const constant::Value* constant);
+
+ /// Get the result ID of the OpConstantNull instruction for `type`, emitting it if necessary.
+ /// @param type the type to get the ID for
+ /// @returns the result ID of the OpConstantNull instruction
+ uint32_t ConstantNull(const type::Type* type);
+
+ /// Get the ID of the label for `block`.
+ /// @param block the block to get the label ID for
+ /// @returns the ID of the block's label
+ uint32_t Label(ir::Block* block);
+
/// Get the result ID of the value `value`, emitting its instruction if necessary.
/// @param value the value to get the ID for
/// @returns the result ID of the value
@@ -112,11 +130,6 @@
/// @returns the result ID of the instruction
uint32_t Undef(const type::Type* ty);
- /// Get the ID of the label for `block`.
- /// @param block the block to get the label ID for
- /// @returns the ID of the block's label
- uint32_t Label(ir::Block* block);
-
/// Emit a struct type.
/// @param id the result ID to use
/// @param addrspace the optional address space that this type is being used for
@@ -202,19 +215,6 @@
/// @param inst the flow control instruction
void EmitExitPhis(ir::ControlInstruction* inst);
- private:
- /// Convert a builtin to the corresponding SPIR-V enum value, taking into account the target
- /// address space. Adds any capabilities needed for the builtin.
- /// @param builtin the builtin to convert
- /// @param addrspace the address space the builtin is being used in
- /// @returns the enum value of the corresponding SPIR-V builtin
- uint32_t Builtin(builtin::BuiltinValue builtin, builtin::AddressSpace addrspace);
-
- /// Get the result ID of the constant `constant`, emitting its instruction if necessary.
- /// @param constant the constant to get the ID for
- /// @returns the result ID of the constant
- uint32_t Constant(const constant::Value* constant);
-
ir::Module* ir_;
spirv::Module module_;
BinaryWriter writer_;
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_access_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_access_test.cc
index df494fb..86d09f7 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_access_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_access_test.cc
@@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "gmock/gmock.h"
#include "src/tint/writer/spirv/ir/test_helper_ir.h"
namespace tint::writer::spirv {
@@ -31,7 +30,7 @@
mod.SetName(result, "result");
});
- ASSERT_TRUE(Generate()) << Error();
+ ASSERT_TRUE(Generate()) << Error() << output_;
EXPECT_INST("%result = OpCompositeExtract %int %arr 1");
}
@@ -44,7 +43,7 @@
mod.SetName(result, "result");
});
- ASSERT_TRUE(Generate()) << Error();
+ ASSERT_TRUE(Generate()) << Error() << output_;
EXPECT_INST("%result = OpAccessChain %_ptr_Function_int %arr %uint_1");
}
@@ -59,7 +58,7 @@
mod.SetName(result, "result");
});
- ASSERT_TRUE(Generate()) << Error();
+ ASSERT_TRUE(Generate()) << Error() << output_;
EXPECT_INST("%result = OpAccessChain %_ptr_Function_int %arr %idx");
}
@@ -75,7 +74,7 @@
mod.SetName(result_scalar, "result_scalar");
});
- ASSERT_TRUE(Generate()) << Error();
+ ASSERT_TRUE(Generate()) << Error() << output_;
EXPECT_INST("%result_vector = OpCompositeExtract %v2float %mat 1");
EXPECT_INST("%result_scalar = OpCompositeExtract %float %mat 1 0");
}
@@ -91,7 +90,7 @@
mod.SetName(result_scalar, "result_scalar");
});
- ASSERT_TRUE(Generate()) << Error();
+ ASSERT_TRUE(Generate()) << Error() << output_;
EXPECT_INST("%result_vector = OpAccessChain %_ptr_Function_v2float %mat %uint_1");
EXPECT_INST("%result_scalar = OpAccessChain %_ptr_Function_float %mat %uint_1 %uint_0");
}
@@ -109,7 +108,7 @@
mod.SetName(result_scalar, "result_scalar");
});
- ASSERT_TRUE(Generate()) << Error();
+ ASSERT_TRUE(Generate()) << Error() << output_;
EXPECT_INST("%result_vector = OpAccessChain %_ptr_Function_v2float %mat %idx");
EXPECT_INST("%result_scalar = OpAccessChain %_ptr_Function_float %mat %idx %idx");
}
@@ -124,7 +123,7 @@
mod.SetName(result, "result");
});
- ASSERT_TRUE(Generate()) << Error();
+ ASSERT_TRUE(Generate()) << Error() << output_;
EXPECT_INST("%result = OpCompositeExtract %int %vec 1");
}
@@ -139,7 +138,7 @@
mod.SetName(result, "result");
});
- ASSERT_TRUE(Generate()) << Error();
+ ASSERT_TRUE(Generate()) << Error() << output_;
EXPECT_INST("%result = OpVectorExtractDynamic %int %vec %idx");
}
@@ -152,7 +151,7 @@
mod.SetName(result, "result");
});
- ASSERT_TRUE(Generate()) << Error();
+ ASSERT_TRUE(Generate()) << Error() << output_;
EXPECT_INST("%result = OpAccessChain %_ptr_Function_int %vec %uint_1");
}
@@ -167,7 +166,7 @@
mod.SetName(result, "result");
});
- ASSERT_TRUE(Generate()) << Error();
+ ASSERT_TRUE(Generate()) << Error() << output_;
EXPECT_INST("%result = OpAccessChain %_ptr_Function_int %vec %idx");
}
@@ -182,7 +181,7 @@
mod.SetName(result, "result");
});
- ASSERT_TRUE(Generate()) << Error();
+ ASSERT_TRUE(Generate()) << Error() << output_;
EXPECT_INST("%14 = OpCompositeExtract %v4int %arr 1 2");
EXPECT_INST("%result = OpVectorExtractDynamic %int %14 %idx");
}
@@ -204,7 +203,7 @@
mod.SetName(result_b, "result_b");
});
- ASSERT_TRUE(Generate()) << Error();
+ ASSERT_TRUE(Generate()) << Error() << output_;
EXPECT_INST("%result_a = OpCompositeExtract %float %str 0");
EXPECT_INST("%result_b = OpCompositeExtract %int %str 1 2");
}
@@ -225,7 +224,7 @@
mod.SetName(result_b, "result_b");
});
- ASSERT_TRUE(Generate()) << Error();
+ ASSERT_TRUE(Generate()) << Error() << output_;
EXPECT_INST("%result_a = OpAccessChain %_ptr_Function_float %str %uint_0");
EXPECT_INST("%result_b = OpAccessChain %_ptr_Function_int %str %uint_1 %uint_2");
}
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_binary_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_binary_test.cc
index 6d4d890..42e1c87 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_binary_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_binary_test.cc
@@ -14,7 +14,6 @@
#include "src/tint/writer/spirv/ir/test_helper_ir.h"
-#include "gmock/gmock.h"
#include "src/tint/ir/binary.h"
using namespace tint::number_suffixes; // NOLINT
@@ -30,103 +29,67 @@
enum ir::Binary::Kind kind;
/// The expected SPIR-V instruction.
std::string spirv_inst;
+ /// The expected SPIR-V result type name.
+ std::string spirv_type_name;
};
-using Arithmetic = SpvGeneratorImplTestWithParam<BinaryTestCase>;
-TEST_P(Arithmetic, Scalar) {
+using Arithmetic_Bitwise = SpvGeneratorImplTestWithParam<BinaryTestCase>;
+TEST_P(Arithmetic_Bitwise, Scalar) {
auto params = GetParam();
auto* func = b.Function("foo", ty.void_());
b.With(func->Block(), [&] {
- b.Binary(params.kind, MakeScalarType(params.type), MakeScalarValue(params.type),
- MakeScalarValue(params.type));
+ auto* lhs = MakeScalarValue(params.type);
+ auto* rhs = MakeScalarValue(params.type);
+ auto* result = b.Binary(params.kind, MakeScalarType(params.type), lhs, rhs);
b.Return(func);
+ mod.SetName(result, "result");
});
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_THAT(DumpModule(generator_.Module()), ::testing::HasSubstr(params.spirv_inst));
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%result = " + params.spirv_inst + " %" + params.spirv_type_name);
}
-TEST_P(Arithmetic, Vector) {
+TEST_P(Arithmetic_Bitwise, Vector) {
auto params = GetParam();
auto* func = b.Function("foo", ty.void_());
b.With(func->Block(), [&] {
- b.Binary(params.kind, MakeVectorType(params.type), MakeVectorValue(params.type),
- MakeVectorValue(params.type));
+ auto* lhs = MakeVectorValue(params.type);
+ auto* rhs = MakeVectorValue(params.type);
+ auto* result = b.Binary(params.kind, MakeVectorType(params.type), lhs, rhs);
b.Return(func);
+ mod.SetName(result, "result");
});
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_THAT(DumpModule(generator_.Module()), ::testing::HasSubstr(params.spirv_inst));
-}
-INSTANTIATE_TEST_SUITE_P(SpvGeneratorImplTest_Binary_I32,
- Arithmetic,
- testing::Values(BinaryTestCase{kI32, ir::Binary::Kind::kAdd, "OpIAdd"},
- BinaryTestCase{kI32, ir::Binary::Kind::kSubtract,
- "OpISub"}));
-INSTANTIATE_TEST_SUITE_P(SpvGeneratorImplTest_Binary_U32,
- Arithmetic,
- testing::Values(BinaryTestCase{kU32, ir::Binary::Kind::kAdd, "OpIAdd"},
- BinaryTestCase{kU32, ir::Binary::Kind::kSubtract,
- "OpISub"}));
-INSTANTIATE_TEST_SUITE_P(SpvGeneratorImplTest_Binary_F32,
- Arithmetic,
- testing::Values(BinaryTestCase{kF32, ir::Binary::Kind::kAdd, "OpFAdd"},
- BinaryTestCase{kF32, ir::Binary::Kind::kSubtract,
- "OpFSub"}));
-INSTANTIATE_TEST_SUITE_P(SpvGeneratorImplTest_Binary_F16,
- Arithmetic,
- testing::Values(BinaryTestCase{kF16, ir::Binary::Kind::kAdd, "OpFAdd"},
- BinaryTestCase{kF16, ir::Binary::Kind::kSubtract,
- "OpFSub"}));
-
-using Bitwise = SpvGeneratorImplTestWithParam<BinaryTestCase>;
-TEST_P(Bitwise, Scalar) {
- auto params = GetParam();
-
- auto* func = b.Function("foo", ty.void_());
- b.With(func->Block(), [&] {
- b.Binary(params.kind, MakeScalarType(params.type), MakeScalarValue(params.type),
- MakeScalarValue(params.type));
- b.Return(func);
- });
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_THAT(DumpModule(generator_.Module()), ::testing::HasSubstr(params.spirv_inst));
-}
-TEST_P(Bitwise, Vector) {
- auto params = GetParam();
-
- auto* func = b.Function("foo", ty.void_());
- b.With(func->Block(), [&] {
- b.Binary(params.kind, MakeVectorType(params.type), MakeVectorValue(params.type),
- MakeVectorValue(params.type));
- b.Return(func);
- });
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_THAT(DumpModule(generator_.Module()), ::testing::HasSubstr(params.spirv_inst));
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%result = " + params.spirv_inst + " %v2" + params.spirv_type_name);
}
INSTANTIATE_TEST_SUITE_P(
SpvGeneratorImplTest_Binary_I32,
- Bitwise,
- testing::Values(BinaryTestCase{kI32, ir::Binary::Kind::kAnd, "OpBitwiseAnd"},
- BinaryTestCase{kI32, ir::Binary::Kind::kOr, "OpBitwiseOr"},
- BinaryTestCase{kI32, ir::Binary::Kind::kXor, "OpBitwiseXor"}));
+ Arithmetic_Bitwise,
+ testing::Values(BinaryTestCase{kI32, ir::Binary::Kind::kAdd, "OpIAdd", "int"},
+ BinaryTestCase{kI32, ir::Binary::Kind::kSubtract, "OpISub", "int"},
+ BinaryTestCase{kI32, ir::Binary::Kind::kAnd, "OpBitwiseAnd", "int"},
+ BinaryTestCase{kI32, ir::Binary::Kind::kOr, "OpBitwiseOr", "int"},
+ BinaryTestCase{kI32, ir::Binary::Kind::kXor, "OpBitwiseXor", "int"}));
INSTANTIATE_TEST_SUITE_P(
SpvGeneratorImplTest_Binary_U32,
- Bitwise,
- testing::Values(BinaryTestCase{kU32, ir::Binary::Kind::kAnd, "OpBitwiseAnd"},
- BinaryTestCase{kU32, ir::Binary::Kind::kOr, "OpBitwiseOr"},
- BinaryTestCase{kU32, ir::Binary::Kind::kXor, "OpBitwiseXor"}));
+ Arithmetic_Bitwise,
+ testing::Values(BinaryTestCase{kU32, ir::Binary::Kind::kAdd, "OpIAdd", "uint"},
+ BinaryTestCase{kU32, ir::Binary::Kind::kSubtract, "OpISub", "uint"},
+ BinaryTestCase{kU32, ir::Binary::Kind::kAnd, "OpBitwiseAnd", "uint"},
+ BinaryTestCase{kU32, ir::Binary::Kind::kOr, "OpBitwiseOr", "uint"},
+ BinaryTestCase{kU32, ir::Binary::Kind::kXor, "OpBitwiseXor", "uint"}));
+INSTANTIATE_TEST_SUITE_P(
+ SpvGeneratorImplTest_Binary_F32,
+ Arithmetic_Bitwise,
+ testing::Values(BinaryTestCase{kF32, ir::Binary::Kind::kAdd, "OpFAdd", "float"},
+ BinaryTestCase{kF32, ir::Binary::Kind::kSubtract, "OpFSub", "float"}));
+INSTANTIATE_TEST_SUITE_P(
+ SpvGeneratorImplTest_Binary_F16,
+ Arithmetic_Bitwise,
+ testing::Values(BinaryTestCase{kF16, ir::Binary::Kind::kAdd, "OpFAdd", "half"},
+ BinaryTestCase{kF16, ir::Binary::Kind::kSubtract, "OpFSub", "half"}));
using Comparison = SpvGeneratorImplTestWithParam<BinaryTestCase>;
TEST_P(Comparison, Scalar) {
@@ -134,15 +97,15 @@
auto* func = b.Function("foo", ty.void_());
b.With(func->Block(), [&] {
- b.Binary(params.kind, ty.bool_(), MakeScalarValue(params.type),
- MakeScalarValue(params.type));
+ auto* lhs = MakeScalarValue(params.type);
+ auto* rhs = MakeScalarValue(params.type);
+ auto* result = b.Binary(params.kind, ty.bool_(), lhs, rhs);
b.Return(func);
+ mod.SetName(result, "result");
});
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_THAT(DumpModule(generator_.Module()), ::testing::HasSubstr(params.spirv_inst));
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%result = " + params.spirv_inst + " %bool");
}
TEST_P(Comparison, Vector) {
@@ -150,87 +113,77 @@
auto* func = b.Function("foo", ty.void_());
b.With(func->Block(), [&] {
- b.Binary(params.kind, ty.vec2(ty.bool_()), MakeVectorValue(params.type),
- MakeVectorValue(params.type));
+ auto* lhs = MakeVectorValue(params.type);
+ auto* rhs = MakeVectorValue(params.type);
+ auto* result = b.Binary(params.kind, ty.vec2<bool>(), lhs, rhs);
b.Return(func);
+ mod.SetName(result, "result");
});
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_THAT(DumpModule(generator_.Module()), ::testing::HasSubstr(params.spirv_inst));
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%result = " + params.spirv_inst + " %v2bool");
}
INSTANTIATE_TEST_SUITE_P(
SpvGeneratorImplTest_Binary_I32,
Comparison,
- testing::Values(BinaryTestCase{kI32, ir::Binary::Kind::kEqual, "OpIEqual"},
- BinaryTestCase{kI32, ir::Binary::Kind::kNotEqual, "OpINotEqual"},
- BinaryTestCase{kI32, ir::Binary::Kind::kGreaterThan, "OpSGreaterThan"},
- BinaryTestCase{kI32, ir::Binary::Kind::kGreaterThanEqual,
- "OpSGreaterThanEqual"},
- BinaryTestCase{kI32, ir::Binary::Kind::kLessThan, "OpSLessThan"},
- BinaryTestCase{kI32, ir::Binary::Kind::kLessThanEqual, "OpSLessThanEqual"}));
+ testing::Values(
+ BinaryTestCase{kI32, ir::Binary::Kind::kEqual, "OpIEqual", "bool"},
+ BinaryTestCase{kI32, ir::Binary::Kind::kNotEqual, "OpINotEqual", "bool"},
+ BinaryTestCase{kI32, ir::Binary::Kind::kGreaterThan, "OpSGreaterThan", "bool"},
+ BinaryTestCase{kI32, ir::Binary::Kind::kGreaterThanEqual, "OpSGreaterThanEqual", "bool"},
+ BinaryTestCase{kI32, ir::Binary::Kind::kLessThan, "OpSLessThan", "bool"},
+ BinaryTestCase{kI32, ir::Binary::Kind::kLessThanEqual, "OpSLessThanEqual", "bool"}));
INSTANTIATE_TEST_SUITE_P(
SpvGeneratorImplTest_Binary_U32,
Comparison,
- testing::Values(BinaryTestCase{kU32, ir::Binary::Kind::kEqual, "OpIEqual"},
- BinaryTestCase{kU32, ir::Binary::Kind::kNotEqual, "OpINotEqual"},
- BinaryTestCase{kU32, ir::Binary::Kind::kGreaterThan, "OpUGreaterThan"},
- BinaryTestCase{kU32, ir::Binary::Kind::kGreaterThanEqual,
- "OpUGreaterThanEqual"},
- BinaryTestCase{kU32, ir::Binary::Kind::kLessThan, "OpULessThan"},
- BinaryTestCase{kU32, ir::Binary::Kind::kLessThanEqual, "OpULessThanEqual"}));
+ testing::Values(
+ BinaryTestCase{kU32, ir::Binary::Kind::kEqual, "OpIEqual", "bool"},
+ BinaryTestCase{kU32, ir::Binary::Kind::kNotEqual, "OpINotEqual", "bool"},
+ BinaryTestCase{kU32, ir::Binary::Kind::kGreaterThan, "OpUGreaterThan", "bool"},
+ BinaryTestCase{kU32, ir::Binary::Kind::kGreaterThanEqual, "OpUGreaterThanEqual", "bool"},
+ BinaryTestCase{kU32, ir::Binary::Kind::kLessThan, "OpULessThan", "bool"},
+ BinaryTestCase{kU32, ir::Binary::Kind::kLessThanEqual, "OpULessThanEqual", "bool"}));
INSTANTIATE_TEST_SUITE_P(
SpvGeneratorImplTest_Binary_F32,
Comparison,
- testing::Values(BinaryTestCase{kF32, ir::Binary::Kind::kEqual, "OpFOrdEqual"},
- BinaryTestCase{kF32, ir::Binary::Kind::kNotEqual, "OpFOrdNotEqual"},
- BinaryTestCase{kF32, ir::Binary::Kind::kGreaterThan, "OpFOrdGreaterThan"},
- BinaryTestCase{kF32, ir::Binary::Kind::kGreaterThanEqual,
- "OpFOrdGreaterThanEqual"},
- BinaryTestCase{kF32, ir::Binary::Kind::kLessThan, "OpFOrdLessThan"},
- BinaryTestCase{kF32, ir::Binary::Kind::kLessThanEqual, "OpFOrdLessThanEqual"}));
+ testing::Values(
+ BinaryTestCase{kF32, ir::Binary::Kind::kEqual, "OpFOrdEqual", "bool"},
+ BinaryTestCase{kF32, ir::Binary::Kind::kNotEqual, "OpFOrdNotEqual", "bool"},
+ BinaryTestCase{kF32, ir::Binary::Kind::kGreaterThan, "OpFOrdGreaterThan", "bool"},
+ BinaryTestCase{kF32, ir::Binary::Kind::kGreaterThanEqual, "OpFOrdGreaterThanEqual", "bool"},
+ BinaryTestCase{kF32, ir::Binary::Kind::kLessThan, "OpFOrdLessThan", "bool"},
+ BinaryTestCase{kF32, ir::Binary::Kind::kLessThanEqual, "OpFOrdLessThanEqual", "bool"}));
INSTANTIATE_TEST_SUITE_P(
SpvGeneratorImplTest_Binary_F16,
Comparison,
- testing::Values(BinaryTestCase{kF16, ir::Binary::Kind::kEqual, "OpFOrdEqual"},
- BinaryTestCase{kF16, ir::Binary::Kind::kNotEqual, "OpFOrdNotEqual"},
- BinaryTestCase{kF16, ir::Binary::Kind::kGreaterThan, "OpFOrdGreaterThan"},
- BinaryTestCase{kF16, ir::Binary::Kind::kGreaterThanEqual,
- "OpFOrdGreaterThanEqual"},
- BinaryTestCase{kF16, ir::Binary::Kind::kLessThan, "OpFOrdLessThan"},
- BinaryTestCase{kF16, ir::Binary::Kind::kLessThanEqual, "OpFOrdLessThanEqual"}));
-INSTANTIATE_TEST_SUITE_P(
- SpvGeneratorImplTest_Binary_Bool,
- Comparison,
- testing::Values(BinaryTestCase{kBool, ir::Binary::Kind::kEqual, "OpLogicalEqual"},
- BinaryTestCase{kBool, ir::Binary::Kind::kNotEqual, "OpLogicalNotEqual"}));
+ testing::Values(
+ BinaryTestCase{kF16, ir::Binary::Kind::kEqual, "OpFOrdEqual", "bool"},
+ BinaryTestCase{kF16, ir::Binary::Kind::kNotEqual, "OpFOrdNotEqual", "bool"},
+ BinaryTestCase{kF16, ir::Binary::Kind::kGreaterThan, "OpFOrdGreaterThan", "bool"},
+ BinaryTestCase{kF16, ir::Binary::Kind::kGreaterThanEqual, "OpFOrdGreaterThanEqual", "bool"},
+ BinaryTestCase{kF16, ir::Binary::Kind::kLessThan, "OpFOrdLessThan", "bool"},
+ BinaryTestCase{kF16, ir::Binary::Kind::kLessThanEqual, "OpFOrdLessThanEqual", "bool"}));
+INSTANTIATE_TEST_SUITE_P(SpvGeneratorImplTest_Binary_Bool,
+ Comparison,
+ testing::Values(BinaryTestCase{kBool, ir::Binary::Kind::kEqual,
+ "OpLogicalEqual", "bool"},
+ BinaryTestCase{kBool, ir::Binary::Kind::kNotEqual,
+ "OpLogicalNotEqual", "bool"}));
TEST_F(SpvGeneratorImplTest, Binary_Chain) {
auto* func = b.Function("foo", ty.void_());
b.With(func->Block(), [&] {
- auto* a = b.Subtract(ty.i32(), 1_i, 2_i);
- b.Add(ty.i32(), a, a);
+ auto* sub = b.Subtract(ty.i32(), 1_i, 2_i);
+ auto* add = b.Add(ty.i32(), sub, sub);
b.Return(func);
+ mod.SetName(sub, "sub");
+ mod.SetName(add, "add");
});
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%6 = OpTypeInt 32 1
-%7 = OpConstant %6 1
-%8 = OpConstant %6 2
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-%5 = OpISub %6 %7 %8
-%9 = OpIAdd %6 %5 %5
-OpReturn
-OpFunctionEnd
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%sub = OpISub %int %int_1 %int_2");
+ EXPECT_INST("%add = OpIAdd %int %sub %sub");
}
} // namespace
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_builtin_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_builtin_test.cc
index f9bbcd6..758bdf8 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_builtin_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_builtin_test.cc
@@ -14,7 +14,6 @@
#include "src/tint/writer/spirv/ir/test_helper_ir.h"
-#include "gmock/gmock.h"
#include "src/tint/builtin/function.h"
using namespace tint::number_suffixes; // NOLINT
@@ -43,10 +42,8 @@
b.Return(func);
});
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_THAT(DumpModule(generator_.Module()), ::testing::HasSubstr(params.spirv_inst));
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(params.spirv_inst);
}
TEST_P(Builtin_1arg, Vector) {
auto params = GetParam();
@@ -57,10 +54,8 @@
b.Return(func);
});
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_THAT(DumpModule(generator_.Module()), ::testing::HasSubstr(params.spirv_inst));
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(params.spirv_inst);
}
INSTANTIATE_TEST_SUITE_P(SpvGeneratorImplTest,
Builtin_1arg,
@@ -71,45 +66,36 @@
TEST_F(SpvGeneratorImplTest, Builtin_Abs_u32) {
auto* func = b.Function("foo", MakeScalarType(kU32));
b.With(func->Block(), [&] {
- auto* result = b.Call(MakeScalarType(kU32), builtin::Function::kAbs, MakeScalarValue(kU32));
+ auto* arg = MakeScalarValue(kU32);
+ auto* result = b.Call(MakeScalarType(kU32), builtin::Function::kAbs, arg);
b.Return(func, result);
+ mod.SetName(arg, "arg");
});
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeInt 32 0
-%3 = OpTypeFunction %2
-%5 = OpConstant %2 1
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpReturnValue %5
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %foo = OpFunction %uint None %3
+ %4 = OpLabel
+ OpReturnValue %arg
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, Builtin_Abs_vec2u) {
auto* func = b.Function("foo", MakeVectorType(kU32));
b.With(func->Block(), [&] {
- auto* result = b.Call(MakeVectorType(kU32), builtin::Function::kAbs, MakeVectorValue(kU32));
+ auto* arg = MakeVectorValue(kU32);
+ auto* result = b.Call(MakeVectorType(kU32), builtin::Function::kAbs, arg);
b.Return(func, result);
+ mod.SetName(arg, "arg");
});
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%3 = OpTypeInt 32 0
-%2 = OpTypeVector %3 2
-%4 = OpTypeFunction %2
-%7 = OpConstant %3 42
-%8 = OpConstant %3 10
-%6 = OpConstantComposite %2 %7 %8
-%1 = OpFunction %2 None %4
-%5 = OpLabel
-OpReturnValue %6
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %foo = OpFunction %v2uint None %4
+ %5 = OpLabel
+ OpReturnValue %arg
+ OpFunctionEnd
)");
}
@@ -125,10 +111,8 @@
b.Return(func);
});
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_THAT(DumpModule(generator_.Module()), ::testing::HasSubstr(params.spirv_inst));
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(params.spirv_inst);
}
TEST_P(Builtin_2arg, Vector) {
auto params = GetParam();
@@ -140,10 +124,8 @@
b.Return(func);
});
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_THAT(DumpModule(generator_.Module()), ::testing::HasSubstr(params.spirv_inst));
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(params.spirv_inst);
}
INSTANTIATE_TEST_SUITE_P(SpvGeneratorImplTest,
Builtin_2arg,
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_constant_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_constant_test.cc
index 40fae96..e526f0b 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_constant_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_constant_test.cc
@@ -22,46 +22,41 @@
TEST_F(SpvGeneratorImplTest, Constant_Bool) {
generator_.Constant(b.Constant(true));
generator_.Constant(b.Constant(false));
- EXPECT_EQ(DumpTypes(), R"(%2 = OpTypeBool
-%1 = OpConstantTrue %2
-%3 = OpConstantFalse %2
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%true = OpConstantTrue %bool");
+ EXPECT_INST("%false = OpConstantFalse %bool");
}
TEST_F(SpvGeneratorImplTest, Constant_I32) {
generator_.Constant(b.Constant(i32(42)));
generator_.Constant(b.Constant(i32(-1)));
- EXPECT_EQ(DumpTypes(), R"(%2 = OpTypeInt 32 1
-%1 = OpConstant %2 42
-%3 = OpConstant %2 -1
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%int_42 = OpConstant %int 42");
+ EXPECT_INST("%int_n1 = OpConstant %int -1");
}
TEST_F(SpvGeneratorImplTest, Constant_U32) {
generator_.Constant(b.Constant(u32(42)));
generator_.Constant(b.Constant(u32(4000000000)));
- EXPECT_EQ(DumpTypes(), R"(%2 = OpTypeInt 32 0
-%1 = OpConstant %2 42
-%3 = OpConstant %2 4000000000
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%uint_42 = OpConstant %uint 42");
+ EXPECT_INST("%uint_4000000000 = OpConstant %uint 4000000000");
}
TEST_F(SpvGeneratorImplTest, Constant_F32) {
generator_.Constant(b.Constant(f32(42)));
generator_.Constant(b.Constant(f32(-1)));
- EXPECT_EQ(DumpTypes(), R"(%2 = OpTypeFloat 32
-%1 = OpConstant %2 42
-%3 = OpConstant %2 -1
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%float_42 = OpConstant %float 42");
+ EXPECT_INST("%float_n1 = OpConstant %float -1");
}
TEST_F(SpvGeneratorImplTest, Constant_F16) {
generator_.Constant(b.Constant(f16(42)));
generator_.Constant(b.Constant(f16(-1)));
- EXPECT_EQ(DumpTypes(), R"(%2 = OpTypeFloat 16
-%1 = OpConstant %2 0x1.5p+5
-%3 = OpConstant %2 -0x1p+0
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%half_0x1_5p_5 = OpConstant %half 0x1.5p+5");
+ EXPECT_INST("%half_n0x1p_0 = OpConstant %half -0x1p+0");
}
TEST_F(SpvGeneratorImplTest, Constant_Vec4Bool) {
@@ -71,12 +66,8 @@
utils::Vector{const_bool(true), const_bool(false), const_bool(false), const_bool(true)});
generator_.Constant(b.Constant(v));
- EXPECT_EQ(DumpTypes(), R"(%3 = OpTypeBool
-%2 = OpTypeVector %3 4
-%4 = OpConstantTrue %3
-%5 = OpConstantFalse %3
-%1 = OpConstantComposite %2 %4 %5 %5 %4
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%1 = OpConstantComposite %v4bool %true %false %false %true");
}
TEST_F(SpvGeneratorImplTest, Constant_Vec2i) {
@@ -84,12 +75,8 @@
auto* v = mod.constant_values.Composite(ty.vec2(ty.i32()),
utils::Vector{const_i32(42), const_i32(-1)});
generator_.Constant(b.Constant(v));
- EXPECT_EQ(DumpTypes(), R"(%3 = OpTypeInt 32 1
-%2 = OpTypeVector %3 2
-%4 = OpConstant %3 42
-%5 = OpConstant %3 -1
-%1 = OpConstantComposite %2 %4 %5
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%1 = OpConstantComposite %v2int %int_42 %int_n1");
}
TEST_F(SpvGeneratorImplTest, Constant_Vec3u) {
@@ -97,13 +84,8 @@
auto* v = mod.constant_values.Composite(
ty.vec3(ty.u32()), utils::Vector{const_u32(42), const_u32(0), const_u32(4000000000)});
generator_.Constant(b.Constant(v));
- EXPECT_EQ(DumpTypes(), R"(%3 = OpTypeInt 32 0
-%2 = OpTypeVector %3 3
-%4 = OpConstant %3 42
-%5 = OpConstant %3 0
-%6 = OpConstant %3 4000000000
-%1 = OpConstantComposite %2 %4 %5 %6
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%1 = OpConstantComposite %v3uint %uint_42 %uint_0 %uint_4000000000");
}
TEST_F(SpvGeneratorImplTest, Constant_Vec4f) {
@@ -112,14 +94,8 @@
ty.vec4(ty.f32()),
utils::Vector{const_f32(42), const_f32(0), const_f32(0.25), const_f32(-1)});
generator_.Constant(b.Constant(v));
- EXPECT_EQ(DumpTypes(), R"(%3 = OpTypeFloat 32
-%2 = OpTypeVector %3 4
-%4 = OpConstant %3 42
-%5 = OpConstant %3 0
-%6 = OpConstant %3 0.25
-%7 = OpConstant %3 -1
-%1 = OpConstantComposite %2 %4 %5 %6 %7
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%1 = OpConstantComposite %v4float %float_42 %float_0 %float_0_25 %float_n1");
}
TEST_F(SpvGeneratorImplTest, Constant_Vec2h) {
@@ -127,12 +103,8 @@
auto* v = mod.constant_values.Composite(ty.vec2(ty.f16()),
utils::Vector{const_f16(42), const_f16(0.25)});
generator_.Constant(b.Constant(v));
- EXPECT_EQ(DumpTypes(), R"(%3 = OpTypeFloat 16
-%2 = OpTypeVector %3 2
-%4 = OpConstant %3 0x1.5p+5
-%5 = OpConstant %3 0x1p-2
-%1 = OpConstantComposite %2 %4 %5
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%1 = OpConstantComposite %v2half %half_0x1_5p_5 %half_0x1pn2");
}
TEST_F(SpvGeneratorImplTest, Constant_Mat2x3f) {
@@ -147,18 +119,17 @@
ty.vec3(f32), utils::Vector{const_f32(-42), const_f32(0), const_f32(-0.25)}),
});
generator_.Constant(b.Constant(v));
- EXPECT_EQ(DumpTypes(), R"(%4 = OpTypeFloat 32
-%3 = OpTypeVector %4 3
-%2 = OpTypeMatrix %3 2
-%6 = OpConstant %4 42
-%7 = OpConstant %4 -1
-%8 = OpConstant %4 0.25
-%5 = OpConstantComposite %3 %6 %7 %8
-%10 = OpConstant %4 -42
-%11 = OpConstant %4 0
-%12 = OpConstant %4 -0.25
-%9 = OpConstantComposite %3 %10 %11 %12
-%1 = OpConstantComposite %2 %5 %9
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %float_42 = OpConstant %float 42
+ %float_n1 = OpConstant %float -1
+ %float_0_25 = OpConstant %float 0.25
+ %5 = OpConstantComposite %v3float %float_42 %float_n1 %float_0_25
+ %float_n42 = OpConstant %float -42
+ %float_0 = OpConstant %float 0
+%float_n0_25 = OpConstant %float -0.25
+ %9 = OpConstantComposite %v3float %float_n42 %float_0 %float_n0_25
+ %1 = OpConstantComposite %mat2v3float %5 %9
)");
}
@@ -177,21 +148,20 @@
ty.vec2(f16), utils::Vector{const_f16(0.5), const_f16(-0)}),
});
generator_.Constant(b.Constant(v));
- EXPECT_EQ(DumpTypes(), R"(%4 = OpTypeFloat 16
-%3 = OpTypeVector %4 2
-%2 = OpTypeMatrix %3 4
-%6 = OpConstant %4 0x1.5p+5
-%7 = OpConstant %4 -0x1p+0
-%5 = OpConstantComposite %3 %6 %7
-%9 = OpConstant %4 0x0p+0
-%10 = OpConstant %4 0x1p-2
-%8 = OpConstantComposite %3 %9 %10
-%12 = OpConstant %4 -0x1.5p+5
-%13 = OpConstant %4 0x1p+0
-%11 = OpConstantComposite %3 %12 %13
-%15 = OpConstant %4 0x1p-1
-%14 = OpConstantComposite %3 %15 %9
-%1 = OpConstantComposite %2 %5 %8 %11 %14
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+%half_0x1_5p_5 = OpConstant %half 0x1.5p+5
+%half_n0x1p_0 = OpConstant %half -0x1p+0
+ %5 = OpConstantComposite %v2half %half_0x1_5p_5 %half_n0x1p_0
+%half_0x0p_0 = OpConstant %half 0x0p+0
+%half_0x1pn2 = OpConstant %half 0x1p-2
+ %8 = OpConstantComposite %v2half %half_0x0p_0 %half_0x1pn2
+%half_n0x1_5p_5 = OpConstant %half -0x1.5p+5
+%half_0x1p_0 = OpConstant %half 0x1p+0
+ %11 = OpConstantComposite %v2half %half_n0x1_5p_5 %half_0x1p_0
+%half_0x1pn1 = OpConstant %half 0x1p-1
+ %14 = OpConstantComposite %v2half %half_0x1pn1 %half_0x0p_0
+ %1 = OpConstantComposite %mat4v2half %5 %8 %11 %14
)");
}
@@ -204,16 +174,8 @@
mod.constant_values.Get(4_i),
});
generator_.Constant(b.Constant(arr));
- EXPECT_EQ(DumpTypes(), R"(%3 = OpTypeInt 32 1
-%5 = OpTypeInt 32 0
-%4 = OpConstant %5 4
-%2 = OpTypeArray %3 %4
-%6 = OpConstant %3 1
-%7 = OpConstant %3 2
-%8 = OpConstant %3 3
-%9 = OpConstant %3 4
-%1 = OpConstantComposite %2 %6 %7 %8 %9
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%1 = OpConstantComposite %_arr_int_uint_4 %int_1 %int_2 %int_3 %int_4");
}
TEST_F(SpvGeneratorImplTest, Constant_Array_Array_I32) {
@@ -231,21 +193,14 @@
inner,
});
generator_.Constant(b.Constant(arr));
- EXPECT_EQ(DumpTypes(), R"(%4 = OpTypeInt 32 1
-%6 = OpTypeInt 32 0
-%5 = OpConstant %6 4
-%3 = OpTypeArray %4 %5
-%2 = OpTypeArray %3 %5
-%8 = OpConstant %4 1
-%9 = OpConstant %4 2
-%10 = OpConstant %4 3
-%11 = OpConstant %4 4
-%7 = OpConstantComposite %3 %8 %9 %10 %11
-%1 = OpConstantComposite %2 %7 %7 %7 %7
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %7 = OpConstantComposite %_arr_int_uint_4 %int_1 %int_2 %int_3 %int_4
+ %1 = OpConstantComposite %_arr__arr_int_uint_4_uint_4 %7 %7 %7 %7
)");
}
-TEST_F(SpvGeneratorImplTest, Struct) {
+TEST_F(SpvGeneratorImplTest, Constant_Struct) {
auto* str_ty = ty.Struct(mod.symbols.New("MyStruct"), {
{mod.symbols.New("a"), ty.i32()},
{mod.symbols.New("b"), ty.u32()},
@@ -257,15 +212,8 @@
mod.constant_values.Get(3_f),
});
generator_.Constant(b.Constant(str));
- EXPECT_EQ(DumpTypes(), R"(%3 = OpTypeInt 32 1
-%4 = OpTypeInt 32 0
-%5 = OpTypeFloat 32
-%2 = OpTypeStruct %3 %4 %5
-%6 = OpConstant %3 1
-%7 = OpConstant %4 2
-%8 = OpConstant %5 3
-%1 = OpConstantComposite %2 %6 %7 %8
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%1 = OpConstantComposite %MyStruct %int_1 %uint_2 %float_3");
}
// Test that we do not emit the same constant more than once.
@@ -273,9 +221,8 @@
generator_.Constant(b.Constant(i32(42)));
generator_.Constant(b.Constant(i32(42)));
generator_.Constant(b.Constant(i32(42)));
- EXPECT_EQ(DumpTypes(), R"(%2 = OpTypeInt 32 1
-%1 = OpConstant %2 42
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%int_42 = OpConstant %int 42");
}
} // namespace
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_construct_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_construct_test.cc
index 7ba7cff..0f33beb 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_construct_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_construct_test.cc
@@ -23,93 +23,54 @@
TEST_F(SpvGeneratorImplTest, Construct_Vector) {
auto* func = b.Function("foo", ty.vec4<i32>());
func->SetParams({
- b.FunctionParam(ty.i32()),
- b.FunctionParam(ty.i32()),
- b.FunctionParam(ty.i32()),
- b.FunctionParam(ty.i32()),
+ b.FunctionParam("a", ty.i32()),
+ b.FunctionParam("b", ty.i32()),
+ b.FunctionParam("c", ty.i32()),
+ b.FunctionParam("d", ty.i32()),
+ });
+ b.With(func->Block(), [&] {
+ auto* result = b.Construct(ty.vec4<i32>(), func->Params());
+ b.Return(func, result);
+ mod.SetName(result, "result");
});
- b.With(func->Block(), [&] { b.Return(func, b.Construct(ty.vec4<i32>(), func->Params())); });
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%3 = OpTypeInt 32 1
-%2 = OpTypeVector %3 4
-%8 = OpTypeFunction %2 %3 %3 %3 %3
-%1 = OpFunction %2 None %8
-%4 = OpFunctionParameter %3
-%5 = OpFunctionParameter %3
-%6 = OpFunctionParameter %3
-%7 = OpFunctionParameter %3
-%9 = OpLabel
-%10 = OpCompositeConstruct %2 %4 %5 %6 %7
-OpReturnValue %10
-OpFunctionEnd
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%result = OpCompositeConstruct %v4int %a %b %c %d");
}
TEST_F(SpvGeneratorImplTest, Construct_Matrix) {
auto* func = b.Function("foo", ty.mat3x4<f32>());
func->SetParams({
- b.FunctionParam(ty.vec4<f32>()),
- b.FunctionParam(ty.vec4<f32>()),
- b.FunctionParam(ty.vec4<f32>()),
+ b.FunctionParam("a", ty.vec4<f32>()),
+ b.FunctionParam("b", ty.vec4<f32>()),
+ b.FunctionParam("c", ty.vec4<f32>()),
+ });
+ b.With(func->Block(), [&] {
+ auto* result = b.Construct(ty.mat3x4<f32>(), func->Params());
+ b.Return(func, result);
+ mod.SetName(result, "result");
});
- b.With(func->Block(), [&] { b.Return(func, b.Construct(ty.mat3x4<f32>(), func->Params())); });
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%4 = OpTypeFloat 32
-%3 = OpTypeVector %4 4
-%2 = OpTypeMatrix %3 3
-%8 = OpTypeFunction %2 %3 %3 %3
-%1 = OpFunction %2 None %8
-%5 = OpFunctionParameter %3
-%6 = OpFunctionParameter %3
-%7 = OpFunctionParameter %3
-%9 = OpLabel
-%10 = OpCompositeConstruct %2 %5 %6 %7
-OpReturnValue %10
-OpFunctionEnd
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%result = OpCompositeConstruct %mat3v4float %a %b %c");
}
TEST_F(SpvGeneratorImplTest, Construct_Array) {
auto* func = b.Function("foo", ty.array<f32, 4>());
func->SetParams({
- b.FunctionParam(ty.f32()),
- b.FunctionParam(ty.f32()),
- b.FunctionParam(ty.f32()),
- b.FunctionParam(ty.f32()),
+ b.FunctionParam("a", ty.f32()),
+ b.FunctionParam("b", ty.f32()),
+ b.FunctionParam("c", ty.f32()),
+ b.FunctionParam("d", ty.f32()),
+ });
+ b.With(func->Block(), [&] {
+ auto* result = b.Construct(ty.array<f32, 4>(), func->Params());
+ b.Return(func, result);
+ mod.SetName(result, "result");
});
- b.With(func->Block(), [&] { b.Return(func, b.Construct(ty.array<f32, 4>(), func->Params())); });
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-OpDecorate %2 ArrayStride 4
-%3 = OpTypeFloat 32
-%5 = OpTypeInt 32 0
-%4 = OpConstant %5 4
-%2 = OpTypeArray %3 %4
-%10 = OpTypeFunction %2 %3 %3 %3 %3
-%1 = OpFunction %2 None %10
-%6 = OpFunctionParameter %3
-%7 = OpFunctionParameter %3
-%8 = OpFunctionParameter %3
-%9 = OpFunctionParameter %3
-%11 = OpLabel
-%12 = OpCompositeConstruct %2 %6 %7 %8 %9
-OpReturnValue %12
-OpFunctionEnd
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%result = OpCompositeConstruct %_arr_float_uint_4 %a %b %c %d");
}
TEST_F(SpvGeneratorImplTest, Construct_Struct) {
@@ -119,42 +80,20 @@
{mod.symbols.Register("b"), ty.u32()},
{mod.symbols.Register("c"), ty.vec4<f32>()},
});
-
auto* func = b.Function("foo", str);
func->SetParams({
- b.FunctionParam(ty.i32()),
- b.FunctionParam(ty.u32()),
- b.FunctionParam(ty.vec4<f32>()),
+ b.FunctionParam("a", ty.i32()),
+ b.FunctionParam("b", ty.u32()),
+ b.FunctionParam("c", ty.vec4<f32>()),
+ });
+ b.With(func->Block(), [&] {
+ auto* result = b.Construct(str, func->Params());
+ b.Return(func, result);
+ mod.SetName(result, "result");
});
- b.With(func->Block(), [&] { b.Return(func, b.Construct(str, func->Params())); });
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-OpMemberName %2 0 "a"
-OpMemberName %2 1 "b"
-OpMemberName %2 2 "c"
-OpName %2 "MyStruct"
-OpMemberDecorate %2 0 Offset 0
-OpMemberDecorate %2 1 Offset 4
-OpMemberDecorate %2 2 Offset 16
-%3 = OpTypeInt 32 1
-%4 = OpTypeInt 32 0
-%6 = OpTypeFloat 32
-%5 = OpTypeVector %6 4
-%2 = OpTypeStruct %3 %4 %5
-%10 = OpTypeFunction %2 %3 %4 %5
-%1 = OpFunction %2 None %10
-%7 = OpFunctionParameter %3
-%8 = OpFunctionParameter %4
-%9 = OpFunctionParameter %5
-%11 = OpLabel
-%12 = OpCompositeConstruct %2 %7 %8 %9
-OpReturnValue %12
-OpFunctionEnd
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%result = OpCompositeConstruct %MyStruct %a %b %c");
}
} // namespace
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_function_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_function_test.cc
index 8450235..5251157 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_function_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_function_test.cc
@@ -17,151 +17,215 @@
namespace tint::writer::spirv {
namespace {
+using namespace tint::builtin::fluent_types; // NOLINT
+using namespace tint::number_suffixes; // NOLINT
+
TEST_F(SpvGeneratorImplTest, Function_Empty) {
auto* func = b.Function("foo", ty.void_());
- func->Block()->Append(b.Return(func));
+ b.With(func->Block(), [&] { //
+ b.Return(func);
+ });
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpReturn
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %foo = OpFunction %void None %3
+ %4 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
// Test that we do not emit the same function type more than once.
TEST_F(SpvGeneratorImplTest, Function_DeduplicateType) {
- auto* func = b.Function("foo", ty.void_());
- func->Block()->Append(b.Return(func));
+ auto* func_a = b.Function("func_a", ty.void_());
+ b.With(func_a->Block(), [&] { //
+ b.Return(func_a);
+ });
+ auto* func_b = b.Function("func_b", ty.void_());
+ b.With(func_b->Block(), [&] { //
+ b.Return(func_b);
+ });
+ auto* func_c = b.Function("func_c", ty.void_());
+ b.With(func_c->Block(), [&] { //
+ b.Return(func_c);
+ });
- ASSERT_TRUE(IRIsValid()) << Error();
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ ; Types, variables and constants
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
- generator_.EmitFunction(func);
- generator_.EmitFunction(func);
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpTypes(), R"(%2 = OpTypeVoid
-%3 = OpTypeFunction %2
+ ; Function func_a
+ %func_a = OpFunction %void None %3
+ %4 = OpLabel
+ OpReturn
+ OpFunctionEnd
+
+ ; Function func_b
+ %func_b = OpFunction %void None %3
+ %6 = OpLabel
+ OpReturn
+ OpFunctionEnd
+
+ ; Function func_c
+ %func_c = OpFunction %void None %3
+ %8 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, Function_EntryPoint_Compute) {
auto* func =
b.Function("main", ty.void_(), ir::Function::PipelineStage::kCompute, {{32, 4, 1}});
- func->Block()->Append(b.Return(func));
+ b.With(func->Block(), [&] { //
+ b.Return(func);
+ });
- ASSERT_TRUE(IRIsValid()) << Error();
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ OpEntryPoint GLCompute %main "main"
+ OpExecutionMode %main LocalSize 32 4 1
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpEntryPoint GLCompute %1 "main"
-OpExecutionMode %1 LocalSize 32 4 1
-OpName %1 "main"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpReturn
-OpFunctionEnd
+ ; Debug Information
+ OpName %main "main" ; id %1
+
+ ; Types, variables and constants
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+
+ ; Function main
+ %main = OpFunction %void None %3
+ %4 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, Function_EntryPoint_Fragment) {
auto* func = b.Function("main", ty.void_(), ir::Function::PipelineStage::kFragment);
- func->Block()->Append(b.Return(func));
+ b.With(func->Block(), [&] { //
+ b.Return(func);
+ });
- ASSERT_TRUE(IRIsValid()) << Error();
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ OpEntryPoint Fragment %main "main"
+ OpExecutionMode %main OriginUpperLeft
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpEntryPoint Fragment %1 "main"
-OpExecutionMode %1 OriginUpperLeft
-OpName %1 "main"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpReturn
-OpFunctionEnd
+ ; Debug Information
+ OpName %main "main" ; id %1
+
+ ; Types, variables and constants
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+
+ ; Function main
+ %main = OpFunction %void None %3
+ %4 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, Function_EntryPoint_Vertex) {
auto* func = b.Function("main", ty.void_(), ir::Function::PipelineStage::kVertex);
- func->Block()->Append(b.Return(func));
+ b.With(func->Block(), [&] { //
+ b.Return(func);
+ });
- ASSERT_TRUE(IRIsValid()) << Error();
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ OpEntryPoint Vertex %main "main"
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpEntryPoint Vertex %1 "main"
-OpName %1 "main"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpReturn
-OpFunctionEnd
+ ; Debug Information
+ OpName %main "main" ; id %1
+
+ ; Types, variables and constants
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+
+ ; Function main
+ %main = OpFunction %void None %3
+ %4 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, Function_EntryPoint_Multiple) {
auto* f1 = b.Function("main1", ty.void_(), ir::Function::PipelineStage::kCompute, {{32, 4, 1}});
- f1->Block()->Append(b.Return(f1));
+ b.With(f1->Block(), [&] { //
+ b.Return(f1);
+ });
auto* f2 = b.Function("main2", ty.void_(), ir::Function::PipelineStage::kCompute, {{8, 2, 16}});
- f2->Block()->Append(b.Return(f2));
+ b.With(f2->Block(), [&] { //
+ b.Return(f2);
+ });
auto* f3 = b.Function("main3", ty.void_(), ir::Function::PipelineStage::kFragment);
- f3->Block()->Append(b.Return(f3));
+ b.With(f3->Block(), [&] { //
+ b.Return(f3);
+ });
- ASSERT_TRUE(IRIsValid()) << Error();
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ OpEntryPoint GLCompute %main1 "main1"
+ OpEntryPoint GLCompute %main2 "main2"
+ OpEntryPoint Fragment %main3 "main3"
+ OpExecutionMode %main1 LocalSize 32 4 1
+ OpExecutionMode %main2 LocalSize 8 2 16
+ OpExecutionMode %main3 OriginUpperLeft
- generator_.EmitFunction(f1);
- generator_.EmitFunction(f2);
- generator_.EmitFunction(f3);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpEntryPoint GLCompute %1 "main1"
-OpEntryPoint GLCompute %5 "main2"
-OpEntryPoint Fragment %7 "main3"
-OpExecutionMode %1 LocalSize 32 4 1
-OpExecutionMode %5 LocalSize 8 2 16
-OpExecutionMode %7 OriginUpperLeft
-OpName %1 "main1"
-OpName %5 "main2"
-OpName %7 "main3"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpReturn
-OpFunctionEnd
-%5 = OpFunction %2 None %3
-%6 = OpLabel
-OpReturn
-OpFunctionEnd
-%7 = OpFunction %2 None %3
-%8 = OpLabel
-OpReturn
-OpFunctionEnd
+ ; Debug Information
+ OpName %main1 "main1" ; id %1
+ OpName %main2 "main2" ; id %5
+ OpName %main3 "main3" ; id %7
+
+ ; Types, variables and constants
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+
+ ; Function main1
+ %main1 = OpFunction %void None %3
+ %4 = OpLabel
+ OpReturn
+ OpFunctionEnd
+
+ ; Function main2
+ %main2 = OpFunction %void None %3
+ %6 = OpLabel
+ OpReturn
+ OpFunctionEnd
+
+ ; Function main3
+ %main3 = OpFunction %void None %3
+ %8 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, Function_ReturnValue) {
auto* func = b.Function("foo", ty.i32());
- func->Block()->Append(b.Return(func, i32(42)));
+ b.With(func->Block(), [&] { //
+ b.Return(func, 42_i);
+ });
- ASSERT_TRUE(IRIsValid()) << Error();
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %3 = OpTypeFunction %int
+ %int_42 = OpConstant %int 42
+ %void = OpTypeVoid
+ %8 = OpTypeFunction %void
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeInt 32 1
-%3 = OpTypeFunction %2
-%5 = OpConstant %2 42
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpReturnValue %5
-OpFunctionEnd
+ ; Function foo
+ %foo = OpFunction %int None %3
+ %4 = OpLabel
+ OpReturnValue %int_42
+ OpFunctionEnd
)");
}
@@ -177,97 +241,61 @@
b.Return(func, result);
});
- ASSERT_TRUE(IRIsValid()) << Error();
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %5 = OpTypeFunction %int %int %int
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-OpName %3 "x"
-OpName %4 "y"
-%2 = OpTypeInt 32 1
-%5 = OpTypeFunction %2 %2 %2
-%1 = OpFunction %2 None %5
-%3 = OpFunctionParameter %2
-%4 = OpFunctionParameter %2
-%6 = OpLabel
-%7 = OpIAdd %2 %3 %4
-OpReturnValue %7
-OpFunctionEnd
+ ; Function foo
+ %foo = OpFunction %int None %5
+ %x = OpFunctionParameter %int
+ %y = OpFunctionParameter %int
+ %6 = OpLabel
+ %7 = OpIAdd %int %x %y
+ OpReturnValue %7
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, Function_Call) {
- auto* i32_ty = ty.i32();
- auto* x = b.FunctionParam(i32_ty);
- auto* y = b.FunctionParam(i32_ty);
- auto* foo = b.Function("foo", i32_ty);
+ auto* i32 = ty.i32();
+ auto* x = b.FunctionParam("x", i32);
+ auto* y = b.FunctionParam("y", i32);
+ auto* foo = b.Function("foo", i32);
foo->SetParams({x, y});
b.With(foo->Block(), [&] {
- auto* result = b.Add(i32_ty, x, y);
+ auto* result = b.Add(i32, x, y);
b.Return(foo, result);
});
auto* bar = b.Function("bar", ty.void_());
b.With(bar->Block(), [&] {
- b.Call(i32_ty, foo, i32(2), i32(3));
+ auto* result = b.Call(i32, foo, 2_i, 3_i);
b.Return(bar);
+ mod.SetName(result, "result");
});
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(foo);
- generator_.EmitFunction(bar);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-OpName %8 "bar"
-%2 = OpTypeInt 32 1
-%5 = OpTypeFunction %2 %2 %2
-%9 = OpTypeVoid
-%10 = OpTypeFunction %9
-%13 = OpConstant %2 2
-%14 = OpConstant %2 3
-%1 = OpFunction %2 None %5
-%3 = OpFunctionParameter %2
-%4 = OpFunctionParameter %2
-%6 = OpLabel
-%7 = OpIAdd %2 %3 %4
-OpReturnValue %7
-OpFunctionEnd
-%8 = OpFunction %9 None %10
-%11 = OpLabel
-%12 = OpFunctionCall %2 %1 %13 %14
-OpReturn
-OpFunctionEnd
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%result = OpFunctionCall %int %foo %int_2 %int_3");
}
TEST_F(SpvGeneratorImplTest, Function_Call_Void) {
auto* foo = b.Function("foo", ty.void_());
- foo->Block()->Append(b.Return(foo));
+ b.With(foo->Block(), [&] { //
+ b.Return(foo);
+ });
auto* bar = b.Function("bar", ty.void_());
b.With(bar->Block(), [&] {
- b.Call(ty.void_(), foo, utils::Empty);
+ auto* result = b.Call(ty.void_(), foo);
b.Return(bar);
+ mod.SetName(result, "result");
});
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(foo);
- generator_.EmitFunction(bar);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-OpName %5 "bar"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpReturn
-OpFunctionEnd
-%5 = OpFunction %2 None %3
-%6 = OpLabel
-%7 = OpFunctionCall %2 %1
-OpReturn
-OpFunctionEnd
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%result = OpFunctionCall %void %foo");
}
} // namespace
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_if_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_if_test.cc
index 892409d..b548745 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_if_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_if_test.cc
@@ -21,316 +21,270 @@
TEST_F(SpvGeneratorImplTest, If_TrueEmpty_FalseEmpty) {
auto* func = b.Function("foo", ty.void_());
+ b.With(func->Block(), [&] {
+ auto* i = b.If(true);
+ b.With(i->True(), [&] { //
+ b.ExitIf(i);
+ });
+ b.With(i->False(), [&] { //
+ b.ExitIf(i);
+ });
+ b.Return(func);
+ });
- auto* i = b.If(true);
- i->True()->Append(b.ExitIf(i));
- i->False()->Append(b.ExitIf(i));
- func->Block()->Append(i);
- func->Block()->Append(b.Return(func));
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%7 = OpTypeBool
-%6 = OpConstantTrue %7
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpSelectionMerge %5 None
-OpBranchConditional %6 %5 %5
-%5 = OpLabel
-OpReturn
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ OpSelectionMerge %5 None
+ OpBranchConditional %true %5 %5
+ %5 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, If_FalseEmpty) {
auto* func = b.Function("foo", ty.void_());
-
- auto* i = b.If(true);
- i->False()->Append(b.ExitIf(i));
-
- b.With(i->True(), [&] {
- b.Add(ty.i32(), 1_i, 1_i);
- b.ExitIf(i);
+ b.With(func->Block(), [&] {
+ auto* i = b.If(true);
+ b.With(i->True(), [&] {
+ b.Add(ty.i32(), 1_i, 1_i);
+ b.ExitIf(i);
+ });
+ b.With(i->False(), [&] { //
+ b.ExitIf(i);
+ });
+ b.Return(func);
});
- func->Block()->Append(i);
- func->Block()->Append(b.Return(func));
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%8 = OpTypeBool
-%7 = OpConstantTrue %8
-%10 = OpTypeInt 32 1
-%11 = OpConstant %10 1
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpSelectionMerge %5 None
-OpBranchConditional %7 %6 %5
-%6 = OpLabel
-%9 = OpIAdd %10 %11 %11
-OpBranch %5
-%5 = OpLabel
-OpReturn
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ OpSelectionMerge %5 None
+ OpBranchConditional %true %6 %5
+ %6 = OpLabel
+ %9 = OpIAdd %int %int_1 %int_1
+ OpBranch %5
+ %5 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, If_TrueEmpty) {
auto* func = b.Function("foo", ty.void_());
-
- auto* i = b.If(true);
- i->True()->Append(b.ExitIf(i));
-
- b.With(i->False(), [&] {
- b.Add(ty.i32(), 1_i, 1_i);
- b.ExitIf(i);
+ b.With(func->Block(), [&] {
+ auto* i = b.If(true);
+ b.With(i->True(), [&] { //
+ b.ExitIf(i);
+ });
+ b.With(i->False(), [&] {
+ b.Add(ty.i32(), 1_i, 1_i);
+ b.ExitIf(i);
+ });
+ b.Return(func);
});
- func->Block()->Append(i);
- func->Block()->Append(b.Return(func));
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%8 = OpTypeBool
-%7 = OpConstantTrue %8
-%10 = OpTypeInt 32 1
-%11 = OpConstant %10 1
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpSelectionMerge %5 None
-OpBranchConditional %7 %5 %6
-%6 = OpLabel
-%9 = OpIAdd %10 %11 %11
-OpBranch %5
-%5 = OpLabel
-OpReturn
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ OpSelectionMerge %5 None
+ OpBranchConditional %true %5 %6
+ %6 = OpLabel
+ %9 = OpIAdd %int %int_1 %int_1
+ OpBranch %5
+ %5 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, If_BothBranchesReturn) {
auto* func = b.Function("foo", ty.void_());
+ b.With(func->Block(), [&] {
+ auto* i = b.If(true);
+ b.With(i->True(), [&] { //
+ b.Return(func);
+ });
+ b.With(i->False(), [&] { //
+ b.Return(func);
+ });
+ b.Unreachable();
+ });
- auto* i = b.If(true);
- i->True()->Append(b.Return(func));
- i->False()->Append(b.Return(func));
-
- func->Block()->Append(i);
- func->Block()->Append(b.Unreachable());
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%9 = OpTypeBool
-%8 = OpConstantTrue %9
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpSelectionMerge %5 None
-OpBranchConditional %8 %6 %7
-%6 = OpLabel
-OpReturn
-%7 = OpLabel
-OpReturn
-%5 = OpLabel
-OpUnreachable
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ OpSelectionMerge %5 None
+ OpBranchConditional %true %5 %5
+ %5 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, If_Phi_SingleValue) {
auto* func = b.Function("foo", ty.i32());
+ b.With(func->Block(), [&] {
+ auto* i = b.If(true);
+ i->SetResults(b.InstructionResult(ty.i32()));
+ b.With(i->True(), [&] { //
+ b.ExitIf(i, 10_i);
+ });
+ b.With(i->False(), [&] { //
+ b.ExitIf(i, 20_i);
+ });
+ b.Return(func, i);
+ });
- auto* i = b.If(true);
- i->SetResults(b.InstructionResult(ty.i32()));
- i->True()->Append(b.ExitIf(i, 10_i));
- i->False()->Append(b.ExitIf(i, 20_i));
-
- func->Block()->Append(i);
- func->Block()->Append(b.Return(func, i));
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeInt 32 1
-%3 = OpTypeFunction %2
-%9 = OpTypeBool
-%8 = OpConstantTrue %9
-%11 = OpConstant %2 10
-%12 = OpConstant %2 20
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpSelectionMerge %5 None
-OpBranchConditional %8 %6 %7
-%6 = OpLabel
-OpBranch %5
-%7 = OpLabel
-OpBranch %5
-%5 = OpLabel
-%10 = OpPhi %2 %11 %6 %12 %7
-OpReturnValue %10
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ OpSelectionMerge %5 None
+ OpBranchConditional %true %6 %7
+ %6 = OpLabel
+ OpBranch %5
+ %7 = OpLabel
+ OpBranch %5
+ %5 = OpLabel
+ %10 = OpPhi %int %int_10 %6 %int_20 %7
+ OpReturnValue %10
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, If_Phi_SingleValue_TrueReturn) {
auto* func = b.Function("foo", ty.i32());
+ b.With(func->Block(), [&] {
+ auto* i = b.If(true);
+ i->SetResults(b.InstructionResult(ty.i32()));
+ b.With(i->True(), [&] { //
+ b.Return(func, 42_i);
+ });
+ b.With(i->False(), [&] { //
+ b.ExitIf(i, 20_i);
+ });
+ b.Return(func, i);
+ });
- auto* i = b.If(true);
- i->SetResults(b.InstructionResult(ty.i32()));
- i->True()->Append(b.Return(func, 42_i));
- i->False()->Append(b.ExitIf(i, 20_i));
-
- func->Block()->Append(i);
- func->Block()->Append(b.Return(func, i));
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeInt 32 1
-%3 = OpTypeFunction %2
-%9 = OpTypeBool
-%8 = OpConstantTrue %9
-%10 = OpConstant %2 42
-%12 = OpConstant %2 20
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpSelectionMerge %5 None
-OpBranchConditional %8 %6 %7
-%6 = OpLabel
-OpReturnValue %10
-%7 = OpLabel
-OpBranch %5
-%5 = OpLabel
-%11 = OpPhi %2 %12 %7
-OpReturnValue %11
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%17 = OpUndef %int");
+ EXPECT_INST(R"(
+ OpSelectionMerge %11 None
+ OpBranchConditional %true %12 %13
+ %12 = OpLabel
+ OpStore %continue_execution %false
+ OpStore %return_value %int_42
+ OpBranch %11
+ %13 = OpLabel
+ OpBranch %11
+ %11 = OpLabel
+ %16 = OpPhi %int %17 %12 %int_20 %13
+ %19 = OpLoad %bool %continue_execution
+ OpSelectionMerge %20 None
+ OpBranchConditional %19 %21 %20
+ %21 = OpLabel
+ OpStore %return_value %16
+ OpBranch %20
+ %20 = OpLabel
+ %22 = OpLoad %int %return_value
+ OpReturnValue %22
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, If_Phi_SingleValue_FalseReturn) {
auto* func = b.Function("foo", ty.i32());
+ b.With(func->Block(), [&] {
+ auto* i = b.If(true);
+ i->SetResults(b.InstructionResult(ty.i32()));
+ b.With(i->True(), [&] { //
+ b.ExitIf(i, 10_i);
+ });
+ b.With(i->False(), [&] { //
+ b.Return(func, 42_i);
+ });
+ b.Return(func, i);
+ });
- auto* i = b.If(true);
- i->SetResults(b.InstructionResult(ty.i32()));
- i->True()->Append(b.ExitIf(i, 10_i));
- i->False()->Append(b.Return(func, 42_i));
-
- func->Block()->Append(i);
- func->Block()->Append(b.Return(func, i));
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeInt 32 1
-%3 = OpTypeFunction %2
-%9 = OpTypeBool
-%8 = OpConstantTrue %9
-%10 = OpConstant %2 42
-%12 = OpConstant %2 10
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpSelectionMerge %5 None
-OpBranchConditional %8 %6 %7
-%6 = OpLabel
-OpBranch %5
-%7 = OpLabel
-OpReturnValue %10
-%5 = OpLabel
-%11 = OpPhi %2 %12 %6
-OpReturnValue %11
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%18 = OpUndef %int");
+ EXPECT_INST(R"(
+ OpSelectionMerge %11 None
+ OpBranchConditional %true %12 %13
+ %12 = OpLabel
+ OpBranch %11
+ %13 = OpLabel
+ OpStore %continue_execution %false
+ OpStore %return_value %int_42
+ OpBranch %11
+ %11 = OpLabel
+ %16 = OpPhi %int %int_10 %12 %18 %13
+ %19 = OpLoad %bool %continue_execution
+ OpSelectionMerge %20 None
+ OpBranchConditional %19 %21 %20
+ %21 = OpLabel
+ OpStore %return_value %16
+ OpBranch %20
+ %20 = OpLabel
+ %22 = OpLoad %int %return_value
+ OpReturnValue %22
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, If_Phi_MultipleValue_0) {
auto* func = b.Function("foo", ty.i32());
+ b.With(func->Block(), [&] {
+ auto* i = b.If(true);
+ i->SetResults(b.InstructionResult(ty.i32()), b.InstructionResult(ty.bool_()));
+ b.With(i->True(), [&] { //
+ b.ExitIf(i, 10_i, true);
+ });
+ b.With(i->False(), [&] { //
+ b.ExitIf(i, 20_i, false);
+ });
+ b.Return(func, i->Result(0));
+ });
- auto* i = b.If(true);
- i->SetResults(b.InstructionResult(ty.i32()), b.InstructionResult(ty.bool_()));
- i->True()->Append(b.ExitIf(i, 10_i, true));
- i->False()->Append(b.ExitIf(i, 20_i, false));
-
- func->Block()->Append(i);
- func->Block()->Append(b.Return(func, i->Result(0)));
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeInt 32 1
-%3 = OpTypeFunction %2
-%9 = OpTypeBool
-%8 = OpConstantTrue %9
-%11 = OpConstant %2 10
-%12 = OpConstant %2 20
-%14 = OpConstantFalse %9
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpSelectionMerge %5 None
-OpBranchConditional %8 %6 %7
-%6 = OpLabel
-OpBranch %5
-%7 = OpLabel
-OpBranch %5
-%5 = OpLabel
-%10 = OpPhi %2 %11 %6 %12 %7
-%13 = OpPhi %9 %8 %6 %14 %7
-OpReturnValue %10
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ OpSelectionMerge %5 None
+ OpBranchConditional %true %6 %7
+ %6 = OpLabel
+ OpBranch %5
+ %7 = OpLabel
+ OpBranch %5
+ %5 = OpLabel
+ %10 = OpPhi %int %int_10 %6 %int_20 %7
+ %13 = OpPhi %bool %true %6 %false %7
+ OpReturnValue %10
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, If_Phi_MultipleValue_1) {
auto* func = b.Function("foo", ty.bool_());
+ b.With(func->Block(), [&] {
+ auto* i = b.If(true);
+ i->SetResults(b.InstructionResult(ty.i32()), b.InstructionResult(ty.bool_()));
+ b.With(i->True(), [&] { //
+ b.ExitIf(i, 10_i, true);
+ });
+ b.With(i->False(), [&] { //
+ b.ExitIf(i, 20_i, false);
+ });
+ b.Return(func, i->Result(1));
+ });
- auto* i = b.If(true);
- i->SetResults(b.InstructionResult(ty.i32()), b.InstructionResult(ty.bool_()));
- i->True()->Append(b.ExitIf(i, 10_i, true));
- i->False()->Append(b.ExitIf(i, 20_i, false));
-
- func->Block()->Append(i);
- func->Block()->Append(b.Return(func, i->Result(1)));
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeBool
-%3 = OpTypeFunction %2
-%8 = OpConstantTrue %2
-%9 = OpTypeInt 32 1
-%11 = OpConstant %9 10
-%12 = OpConstant %9 20
-%14 = OpConstantFalse %2
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpSelectionMerge %5 None
-OpBranchConditional %8 %6 %7
-%6 = OpLabel
-OpBranch %5
-%7 = OpLabel
-OpBranch %5
-%5 = OpLabel
-%10 = OpPhi %9 %11 %6 %12 %7
-%13 = OpPhi %2 %8 %6 %14 %7
-OpReturnValue %13
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ OpSelectionMerge %5 None
+ OpBranchConditional %true %6 %7
+ %6 = OpLabel
+ OpBranch %5
+ %7 = OpLabel
+ OpBranch %5
+ %5 = OpLabel
+ %10 = OpPhi %int %int_10 %6 %int_20 %7
+ %13 = OpPhi %bool %true %6 %false %7
+ OpReturnValue %13
+ OpFunctionEnd
)");
}
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_loop_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_loop_test.cc
index 31bb501..67efd6a 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_loop_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_loop_test.cc
@@ -21,159 +21,146 @@
TEST_F(SpvGeneratorImplTest, Loop_BreakIf) {
auto* func = b.Function("foo", ty.void_());
+ b.With(func->Block(), [&] {
+ auto* loop = b.Loop();
+ b.With(loop->Body(), [&] { //
+ b.Continue(loop);
- auto* loop = b.Loop();
+ b.With(loop->Continuing(), [&] { //
+ b.BreakIf(loop, true);
+ });
+ });
+ b.Return(func);
+ });
- loop->Body()->Append(b.Continue(loop));
- loop->Continuing()->Append(b.BreakIf(loop, true));
-
- func->Block()->Append(loop);
- func->Block()->Append(b.Return(func));
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%10 = OpTypeBool
-%9 = OpConstantTrue %10
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpBranch %7
-%7 = OpLabel
-OpLoopMerge %8 %6 None
-OpBranch %5
-%5 = OpLabel
-OpBranch %6
-%6 = OpLabel
-OpBranchConditional %9 %8 %7
-%8 = OpLabel
-OpReturn
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %4 = OpLabel
+ OpBranch %7
+ %7 = OpLabel
+ OpLoopMerge %8 %6 None
+ OpBranch %5
+ %5 = OpLabel
+ OpBranch %6
+ %6 = OpLabel
+ OpBranchConditional %true %8 %7
+ %8 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
// Test that we still emit the continuing block with a back-edge, even when it is unreachable.
TEST_F(SpvGeneratorImplTest, Loop_UnconditionalBreakInBody) {
auto* func = b.Function("foo", ty.void_());
+ b.With(func->Block(), [&] {
+ auto* loop = b.Loop();
+ b.With(loop->Body(), [&] { //
+ b.ExitLoop(loop);
+ });
+ b.Return(func);
+ });
- auto* loop = b.Loop();
-
- loop->Body()->Append(b.ExitLoop(loop));
-
- func->Block()->Append(loop);
- func->Block()->Append(b.Return(func));
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpBranch %7
-%7 = OpLabel
-OpLoopMerge %8 %6 None
-OpBranch %5
-%5 = OpLabel
-OpBranch %8
-%6 = OpLabel
-OpBranch %7
-%8 = OpLabel
-OpReturn
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %4 = OpLabel
+ OpBranch %7
+ %7 = OpLabel
+ OpLoopMerge %8 %6 None
+ OpBranch %5
+ %5 = OpLabel
+ OpBranch %8
+ %6 = OpLabel
+ OpBranch %7
+ %8 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, Loop_ConditionalBreakInBody) {
auto* func = b.Function("foo", ty.void_());
+ b.With(func->Block(), [&] {
+ auto* loop = b.Loop();
+ b.With(loop->Body(), [&] {
+ auto* cond_break = b.If(true);
+ b.With(cond_break->True(), [&] { //
+ b.ExitLoop(loop);
+ });
+ b.With(cond_break->False(), [&] { //
+ b.ExitIf(cond_break);
+ });
+ b.Continue(loop);
- auto* loop = b.Loop();
+ b.With(loop->Continuing(), [&] { //
+ b.NextIteration(loop);
+ });
+ });
+ b.Return(func);
+ });
- auto* cond_break = b.If(true);
- cond_break->True()->Append(b.ExitLoop(loop));
- cond_break->False()->Append(b.ExitIf(cond_break));
-
- loop->Body()->Append(cond_break);
- loop->Body()->Append(b.Continue(loop));
- loop->Continuing()->Append(b.NextIteration(loop));
-
- func->Block()->Append(loop);
- func->Block()->Append(b.Return(func));
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%12 = OpTypeBool
-%11 = OpConstantTrue %12
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpBranch %7
-%7 = OpLabel
-OpLoopMerge %8 %6 None
-OpBranch %5
-%5 = OpLabel
-OpSelectionMerge %9 None
-OpBranchConditional %11 %10 %9
-%10 = OpLabel
-OpBranch %8
-%9 = OpLabel
-OpBranch %6
-%6 = OpLabel
-OpBranch %7
-%8 = OpLabel
-OpReturn
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %4 = OpLabel
+ OpBranch %7
+ %7 = OpLabel
+ OpLoopMerge %8 %6 None
+ OpBranch %5
+ %5 = OpLabel
+ OpSelectionMerge %9 None
+ OpBranchConditional %true %10 %9
+ %10 = OpLabel
+ OpBranch %8
+ %9 = OpLabel
+ OpBranch %6
+ %6 = OpLabel
+ OpBranch %7
+ %8 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, Loop_ConditionalContinueInBody) {
auto* func = b.Function("foo", ty.void_());
+ b.With(func->Block(), [&] {
+ auto* loop = b.Loop();
+ b.With(loop->Body(), [&] {
+ auto* cond_break = b.If(true);
+ b.With(cond_break->True(), [&] { //
+ b.Continue(loop);
+ });
+ b.With(cond_break->False(), [&] { //
+ b.ExitIf(cond_break);
+ });
+ b.ExitLoop(loop);
- auto* loop = b.Loop();
+ b.With(loop->Continuing(), [&] { //
+ b.NextIteration(loop);
+ });
+ });
+ b.Return(func);
+ });
- auto* cond_break = b.If(true);
- cond_break->True()->Append(b.Continue(loop));
- cond_break->False()->Append(b.ExitIf(cond_break));
-
- loop->Body()->Append(cond_break);
- loop->Body()->Append(b.ExitLoop(loop));
- loop->Continuing()->Append(b.NextIteration(loop));
-
- func->Block()->Append(loop);
- func->Block()->Append(b.Return(func));
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%12 = OpTypeBool
-%11 = OpConstantTrue %12
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpBranch %7
-%7 = OpLabel
-OpLoopMerge %8 %6 None
-OpBranch %5
-%5 = OpLabel
-OpSelectionMerge %9 None
-OpBranchConditional %11 %10 %9
-%10 = OpLabel
-OpBranch %6
-%9 = OpLabel
-OpBranch %8
-%6 = OpLabel
-OpBranch %7
-%8 = OpLabel
-OpReturn
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %4 = OpLabel
+ OpBranch %7
+ %7 = OpLabel
+ OpLoopMerge %8 %6 None
+ OpBranch %5
+ %5 = OpLabel
+ OpSelectionMerge %9 None
+ OpBranchConditional %true %10 %9
+ %10 = OpLabel
+ OpBranch %6
+ %9 = OpLabel
+ OpBranch %8
+ %6 = OpLabel
+ OpBranch %7
+ %8 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
@@ -181,169 +168,158 @@
// they are unreachable.
TEST_F(SpvGeneratorImplTest, Loop_UnconditionalReturnInBody) {
auto* func = b.Function("foo", ty.void_());
+ b.With(func->Block(), [&] {
+ auto* loop = b.Loop();
+ b.With(loop->Body(), [&] { //
+ b.Return(func);
+ });
+ b.Unreachable();
+ });
- auto* loop = b.Loop();
- loop->Body()->Append(b.Return(func));
-
- func->Block()->Append(loop);
- func->Block()->Append(b.Unreachable());
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpBranch %7
-%7 = OpLabel
-OpLoopMerge %8 %6 None
-OpBranch %5
-%5 = OpLabel
-OpReturn
-%6 = OpLabel
-OpBranch %7
-%8 = OpLabel
-OpUnreachable
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %4 = OpLabel
+ OpBranch %7
+ %7 = OpLabel
+ OpLoopMerge %8 %6 None
+ OpBranch %5
+ %5 = OpLabel
+ OpBranch %8
+ %6 = OpLabel
+ OpBranch %7
+ %8 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, Loop_UseResultFromBodyInContinuing) {
auto* func = b.Function("foo", ty.void_());
+ b.With(func->Block(), [&] {
+ auto* loop = b.Loop();
+ b.With(loop->Body(), [&] {
+ auto* result = b.Equal(ty.bool_(), 1_i, 2_i);
+ b.Continue(loop, result);
- auto* loop = b.Loop();
+ b.With(loop->Continuing(), [&] { //
+ b.BreakIf(loop, result);
+ });
+ });
+ b.Return(func);
+ });
- auto* result = loop->Body()->Append(b.Equal(ty.i32(), 1_i, 2_i));
- loop->Body()->Append(b.Continue(loop, result));
-
- loop->Continuing()->Append(b.BreakIf(loop, result));
-
- func->Block()->Append(loop);
- func->Block()->Append(b.Return(func));
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%10 = OpTypeInt 32 1
-%11 = OpConstant %10 1
-%12 = OpConstant %10 2
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpBranch %7
-%7 = OpLabel
-OpLoopMerge %8 %6 None
-OpBranch %5
-%5 = OpLabel
-%9 = OpIEqual %10 %11 %12
-OpBranch %6
-%6 = OpLabel
-OpBranchConditional %9 %8 %7
-%8 = OpLabel
-OpReturn
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %4 = OpLabel
+ OpBranch %7
+ %7 = OpLabel
+ OpLoopMerge %8 %6 None
+ OpBranch %5
+ %5 = OpLabel
+ %9 = OpIEqual %bool %int_1 %int_2
+ OpBranch %6
+ %6 = OpLabel
+ OpBranchConditional %9 %8 %7
+ %8 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, Loop_NestedLoopInBody) {
auto* func = b.Function("foo", ty.void_());
+ b.With(func->Block(), [&] {
+ auto* outer_loop = b.Loop();
+ b.With(outer_loop->Body(), [&] {
+ auto* inner_loop = b.Loop();
+ b.With(inner_loop->Body(), [&] {
+ b.ExitLoop(inner_loop);
- auto* outer_loop = b.Loop();
- auto* inner_loop = b.Loop();
+ b.With(inner_loop->Continuing(), [&] { //
+ b.NextIteration(inner_loop);
+ });
+ });
+ b.Continue(outer_loop);
- inner_loop->Body()->Append(b.ExitLoop(inner_loop));
- inner_loop->Continuing()->Append(b.NextIteration(inner_loop));
+ b.With(outer_loop->Continuing(),
+ [&] { //
+ b.BreakIf(outer_loop, true);
+ });
+ });
+ b.Return(func);
+ });
- outer_loop->Body()->Append(inner_loop);
- outer_loop->Body()->Append(b.Continue(outer_loop));
- outer_loop->Continuing()->Append(b.BreakIf(outer_loop, true));
-
- func->Block()->Append(outer_loop);
- func->Block()->Append(b.Return(func));
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%14 = OpTypeBool
-%13 = OpConstantTrue %14
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpBranch %7
-%7 = OpLabel
-OpLoopMerge %8 %6 None
-OpBranch %5
-%5 = OpLabel
-OpBranch %11
-%11 = OpLabel
-OpLoopMerge %12 %10 None
-OpBranch %9
-%9 = OpLabel
-OpBranch %12
-%10 = OpLabel
-OpBranch %11
-%12 = OpLabel
-OpBranch %6
-%6 = OpLabel
-OpBranchConditional %13 %8 %7
-%8 = OpLabel
-OpReturn
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %4 = OpLabel
+ OpBranch %7
+ %7 = OpLabel
+ OpLoopMerge %8 %6 None
+ OpBranch %5
+ %5 = OpLabel
+ OpBranch %11
+ %11 = OpLabel
+ OpLoopMerge %12 %10 None
+ OpBranch %9
+ %9 = OpLabel
+ OpBranch %12
+ %10 = OpLabel
+ OpBranch %11
+ %12 = OpLabel
+ OpBranch %6
+ %6 = OpLabel
+ OpBranchConditional %true %8 %7
+ %8 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, Loop_NestedLoopInContinuing) {
auto* func = b.Function("foo", ty.void_());
+ b.With(func->Block(), [&] {
+ auto* outer_loop = b.Loop();
+ b.With(outer_loop->Body(), [&] {
+ b.Continue(outer_loop);
- auto* outer_loop = b.Loop();
- auto* inner_loop = b.Loop();
+ b.With(outer_loop->Continuing(), [&] {
+ auto* inner_loop = b.Loop();
+ b.With(inner_loop->Body(), [&] {
+ b.Continue(inner_loop);
- inner_loop->Body()->Append(b.Continue(inner_loop));
- inner_loop->Continuing()->Append(b.BreakIf(inner_loop, true));
+ b.With(inner_loop->Continuing(), [&] { //
+ b.BreakIf(inner_loop, true);
+ });
+ });
+ b.BreakIf(outer_loop, true);
+ });
+ });
+ b.Return(func);
+ });
- outer_loop->Body()->Append(b.Continue(outer_loop));
- outer_loop->Continuing()->Append(inner_loop);
- outer_loop->Continuing()->Append(b.BreakIf(outer_loop, true));
-
- func->Block()->Append(outer_loop);
- func->Block()->Append(b.Return(func));
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%14 = OpTypeBool
-%13 = OpConstantTrue %14
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpBranch %7
-%7 = OpLabel
-OpLoopMerge %8 %6 None
-OpBranch %5
-%5 = OpLabel
-OpBranch %6
-%6 = OpLabel
-OpBranch %11
-%11 = OpLabel
-OpLoopMerge %12 %10 None
-OpBranch %9
-%9 = OpLabel
-OpBranch %10
-%10 = OpLabel
-OpBranchConditional %13 %12 %11
-%12 = OpLabel
-OpBranchConditional %13 %8 %7
-%8 = OpLabel
-OpReturn
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %4 = OpLabel
+ OpBranch %7
+ %7 = OpLabel
+ OpLoopMerge %8 %6 None
+ OpBranch %5
+ %5 = OpLabel
+ OpBranch %6
+ %6 = OpLabel
+ OpBranch %11
+ %11 = OpLabel
+ OpLoopMerge %12 %10 None
+ OpBranch %9
+ %9 = OpLabel
+ OpBranch %10
+ %10 = OpLabel
+ OpBranchConditional %true %12 %11
+ %12 = OpLabel
+ OpBranchConditional %true %8 %7
+ %8 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
@@ -353,7 +329,9 @@
b.With(func->Block(), [&] {
auto* loop = b.Loop();
- b.With(loop->Initializer(), [&] { b.NextIteration(loop, 1_i, false); });
+ b.With(loop->Initializer(), [&] { //
+ b.NextIteration(loop, 1_i, false);
+ });
auto* loop_param = b.BlockParam(ty.i32());
loop->Body()->SetParams({loop_param});
@@ -373,35 +351,24 @@
b.Return(func);
});
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%10 = OpTypeInt 32 1
-%12 = OpConstant %10 1
-%16 = OpTypeBool
-%17 = OpConstant %10 5
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpBranch %5
-%5 = OpLabel
-OpBranch %8
-%8 = OpLabel
-%11 = OpPhi %10 %12 %5 %13 %7
-OpLoopMerge %9 %7 None
-OpBranch %6
-%6 = OpLabel
-%14 = OpIAdd %10 %11 %12
-OpBranch %7
-%7 = OpLabel
-%13 = OpPhi %10 %14 %6
-%15 = OpSGreaterThan %16 %13 %17
-OpBranchConditional %15 %9 %8
-%9 = OpLabel
-OpReturn
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %5 = OpLabel
+ OpBranch %8
+ %8 = OpLabel
+ %11 = OpPhi %int %int_1 %5 %13 %7
+ OpLoopMerge %9 %7 None
+ OpBranch %6
+ %6 = OpLabel
+ %14 = OpIAdd %int %11 %int_1
+ OpBranch %7
+ %7 = OpLabel
+ %13 = OpPhi %int %14 %6
+ %15 = OpSGreaterThan %bool %13 %int_5
+ OpBranchConditional %15 %9 %8
+ %9 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
@@ -411,7 +378,9 @@
b.With(func->Block(), [&] {
auto* loop = b.Loop();
- b.With(loop->Initializer(), [&] { b.NextIteration(loop, 1_i, false); });
+ b.With(loop->Initializer(), [&] { //
+ b.NextIteration(loop, 1_i, false);
+ });
auto* loop_param_a = b.BlockParam(ty.i32());
auto* loop_param_b = b.BlockParam(ty.bool_());
@@ -434,39 +403,27 @@
b.Return(func);
});
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%10 = OpTypeInt 32 1
-%12 = OpConstant %10 1
-%14 = OpTypeBool
-%16 = OpConstantFalse %14
-%21 = OpConstant %10 5
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpBranch %5
-%5 = OpLabel
-OpBranch %8
-%8 = OpLabel
-%11 = OpPhi %10 %12 %5 %13 %7
-%15 = OpPhi %14 %16 %5 %17 %7
-OpLoopMerge %9 %7 None
-OpBranch %6
-%6 = OpLabel
-%18 = OpIAdd %10 %11 %12
-OpBranch %7
-%7 = OpLabel
-%13 = OpPhi %10 %18 %6
-%19 = OpPhi %14 %15 %6
-%20 = OpSGreaterThan %14 %13 %21
-%17 = OpLogicalEqual %14 %19 %16
-OpBranchConditional %20 %9 %8
-%9 = OpLabel
-OpReturn
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %5 = OpLabel
+ OpBranch %8
+ %8 = OpLabel
+ %11 = OpPhi %int %int_1 %5 %13 %7
+ %15 = OpPhi %bool %false %5 %17 %7
+ OpLoopMerge %9 %7 None
+ OpBranch %6
+ %6 = OpLabel
+ %18 = OpIAdd %int %11 %int_1
+ OpBranch %7
+ %7 = OpLabel
+ %13 = OpPhi %int %18 %6
+ %19 = OpPhi %bool %15 %6
+ %20 = OpSGreaterThan %bool %13 %int_5
+ %17 = OpLogicalEqual %bool %19 %false
+ OpBranchConditional %20 %9 %8
+ %9 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_switch_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_switch_test.cc
index 396e0fe..d851066 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_switch_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_switch_test.cc
@@ -21,368 +21,351 @@
TEST_F(SpvGeneratorImplTest, Switch_Basic) {
auto* func = b.Function("foo", ty.void_());
+ b.With(func->Block(), [&] {
+ auto* swtch = b.Switch(42_i);
- auto* swtch = b.Switch(42_i);
+ auto* def_case = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector()});
+ b.With(def_case, [&] { //
+ b.ExitSwitch(swtch);
+ });
- auto* def_case = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector()});
- def_case->Append(b.ExitSwitch(swtch));
+ b.Return(func);
+ });
- func->Block()->Append(swtch);
- func->Block()->Append(b.Return(func));
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%7 = OpTypeInt 32 1
-%6 = OpConstant %7 42
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpSelectionMerge %8 None
-OpSwitch %6 %5
-%5 = OpLabel
-OpBranch %8
-%8 = OpLabel
-OpReturn
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %4 = OpLabel
+ OpSelectionMerge %8 None
+ OpSwitch %int_42 %5
+ %5 = OpLabel
+ OpBranch %8
+ %8 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, Switch_MultipleCases) {
auto* func = b.Function("foo", ty.void_());
+ b.With(func->Block(), [&] {
+ auto* swtch = b.Switch(42_i);
- auto* swtch = b.Switch(42_i);
+ auto* case_a = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)}});
+ b.With(case_a, [&] { //
+ b.ExitSwitch(swtch);
+ });
- auto* case_a = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)}});
- case_a->Append(b.ExitSwitch(swtch));
+ auto* case_b = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(2_i)}});
+ b.With(case_b, [&] { //
+ b.ExitSwitch(swtch);
+ });
- auto* case_b = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(2_i)}});
- case_b->Append(b.ExitSwitch(swtch));
+ auto* def_case = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector()});
+ b.With(def_case, [&] { //
+ b.ExitSwitch(swtch);
+ });
- auto* def_case = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector()});
- def_case->Append(b.ExitSwitch(swtch));
+ b.Return(func);
+ });
- func->Block()->Append(swtch);
- func->Block()->Append(b.Return(func));
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%7 = OpTypeInt 32 1
-%6 = OpConstant %7 42
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpSelectionMerge %10 None
-OpSwitch %6 %5 1 %8 2 %9
-%8 = OpLabel
-OpBranch %10
-%9 = OpLabel
-OpBranch %10
-%5 = OpLabel
-OpBranch %10
-%10 = OpLabel
-OpReturn
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %4 = OpLabel
+ OpSelectionMerge %10 None
+ OpSwitch %int_42 %5 1 %8 2 %9
+ %8 = OpLabel
+ OpBranch %10
+ %9 = OpLabel
+ OpBranch %10
+ %5 = OpLabel
+ OpBranch %10
+ %10 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, Switch_MultipleSelectorsPerCase) {
auto* func = b.Function("foo", ty.void_());
+ b.With(func->Block(), [&] {
+ auto* swtch = b.Switch(42_i);
- auto* swtch = b.Switch(42_i);
+ auto* case_a = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)},
+ ir::Switch::CaseSelector{b.Constant(3_i)}});
+ b.With(case_a, [&] { //
+ b.ExitSwitch(swtch);
+ });
- auto* case_a = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)},
- ir::Switch::CaseSelector{b.Constant(3_i)}});
- case_a->Append(b.ExitSwitch(swtch));
+ auto* case_b = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(2_i)},
+ ir::Switch::CaseSelector{b.Constant(4_i)}});
+ b.With(case_b, [&] { //
+ b.ExitSwitch(swtch);
+ });
- auto* case_b = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(2_i)},
- ir::Switch::CaseSelector{b.Constant(4_i)}});
- case_b->Append(b.ExitSwitch(swtch));
+ auto* def_case = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(5_i)},
+ ir::Switch::CaseSelector()});
+ b.With(def_case, [&] { //
+ b.ExitSwitch(swtch);
+ });
- auto* def_case = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(5_i)},
- ir::Switch::CaseSelector()});
- def_case->Append(b.ExitSwitch(swtch));
+ b.Return(func);
+ });
- func->Block()->Append(swtch);
- func->Block()->Append(b.Return(func));
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%7 = OpTypeInt 32 1
-%6 = OpConstant %7 42
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpSelectionMerge %10 None
-OpSwitch %6 %5 1 %8 3 %8 2 %9 4 %9 5 %5
-%8 = OpLabel
-OpBranch %10
-%9 = OpLabel
-OpBranch %10
-%5 = OpLabel
-OpBranch %10
-%10 = OpLabel
-OpReturn
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %4 = OpLabel
+ OpSelectionMerge %10 None
+ OpSwitch %int_42 %5 1 %8 3 %8 2 %9 4 %9 5 %5
+ %8 = OpLabel
+ OpBranch %10
+ %9 = OpLabel
+ OpBranch %10
+ %5 = OpLabel
+ OpBranch %10
+ %10 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, Switch_AllCasesReturn) {
auto* func = b.Function("foo", ty.void_());
+ b.With(func->Block(), [&] {
+ auto* swtch = b.Switch(42_i);
- auto* swtch = b.Switch(42_i);
+ auto* case_a = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)}});
+ b.With(case_a, [&] { //
+ b.Return(func);
+ });
- auto* case_a = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)}});
- case_a->Append(b.Return(func));
+ auto* case_b = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(2_i)}});
+ b.With(case_b, [&] { //
+ b.Return(func);
+ });
- auto* case_b = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(2_i)}});
- case_b->Append(b.Return(func));
+ auto* def_case = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector()});
+ b.With(def_case, [&] { //
+ b.Return(func);
+ });
- auto* def_case = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector()});
- def_case->Append(b.Return(func));
+ b.Unreachable();
+ });
- func->Block()->Append(swtch);
- func->Block()->Append(b.Unreachable());
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%7 = OpTypeInt 32 1
-%6 = OpConstant %7 42
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpSelectionMerge %10 None
-OpSwitch %6 %5 1 %8 2 %9
-%8 = OpLabel
-OpReturn
-%9 = OpLabel
-OpReturn
-%5 = OpLabel
-OpReturn
-%10 = OpLabel
-OpUnreachable
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %4 = OpLabel
+ OpSelectionMerge %10 None
+ OpSwitch %int_42 %5 1 %8 2 %9
+ %8 = OpLabel
+ OpBranch %10
+ %9 = OpLabel
+ OpBranch %10
+ %5 = OpLabel
+ OpBranch %10
+ %10 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, Switch_ConditionalBreak) {
auto* func = b.Function("foo", ty.void_());
+ b.With(func->Block(), [&] {
+ auto* swtch = b.Switch(42_i);
- auto* swtch = b.Switch(42_i);
+ auto* case_a = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)}});
+ b.With(case_a, [&] {
+ auto* cond_break = b.If(true);
+ b.With(cond_break->True(), [&] { //
+ b.ExitSwitch(swtch);
+ });
+ b.With(cond_break->False(), [&] { //
+ b.ExitIf(cond_break);
+ });
- auto* cond_break = b.If(true);
- cond_break->True()->Append(b.ExitSwitch(swtch));
- cond_break->False()->Append(b.ExitIf(cond_break));
+ b.Return(func);
+ });
- auto* case_a = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)}});
- case_a->Append(cond_break);
- case_a->Append(b.Return(func));
+ auto* def_case = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector()});
+ b.With(def_case, [&] { //
+ b.ExitSwitch(swtch);
+ });
- auto* def_case = b.Case(swtch, utils::Vector{ir::Switch::CaseSelector()});
- def_case->Append(b.ExitSwitch(swtch));
+ b.Return(func);
+ });
- func->Block()->Append(swtch);
- func->Block()->Append(b.Return(func));
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%7 = OpTypeInt 32 1
-%6 = OpConstant %7 42
-%13 = OpTypeBool
-%12 = OpConstantTrue %13
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpSelectionMerge %9 None
-OpSwitch %6 %5 1 %8
-%8 = OpLabel
-OpSelectionMerge %10 None
-OpBranchConditional %12 %11 %10
-%11 = OpLabel
-OpBranch %9
-%10 = OpLabel
-OpReturn
-%5 = OpLabel
-OpBranch %9
-%9 = OpLabel
-OpReturn
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %4 = OpLabel
+ OpSelectionMerge %9 None
+ OpSwitch %int_42 %5 1 %8
+ %8 = OpLabel
+ OpSelectionMerge %10 None
+ OpBranchConditional %true %11 %10
+ %11 = OpLabel
+ OpBranch %9
+ %10 = OpLabel
+ OpBranch %9
+ %5 = OpLabel
+ OpBranch %9
+ %9 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, Switch_Phi_SingleValue) {
auto* func = b.Function("foo", ty.i32());
+ b.With(func->Block(), [&] {
+ auto* s = b.Switch(42_i);
+ s->SetResults(b.InstructionResult(ty.i32()));
+ auto* case_a = b.Case(s, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)},
+ ir::Switch::CaseSelector{nullptr}});
+ b.With(case_a, [&] { //
+ b.ExitSwitch(s, 10_i);
+ });
- auto* s = b.Switch(42_i);
- s->SetResults(b.InstructionResult(ty.i32()));
- auto* case_a = b.Case(s, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)},
- ir::Switch::CaseSelector{nullptr}});
- case_a->Append(b.ExitSwitch(s, 10_i));
+ auto* case_b = b.Case(s, utils::Vector{ir::Switch::CaseSelector{b.Constant(2_i)}});
+ b.With(case_b, [&] { //
+ b.ExitSwitch(s, 20_i);
+ });
- auto* case_b = b.Case(s, utils::Vector{ir::Switch::CaseSelector{b.Constant(2_i)}});
- case_b->Append(b.ExitSwitch(s, 20_i));
+ b.Return(func, s);
+ });
- func->Block()->Append(s);
- func->Block()->Append(b.Return(func, s));
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeInt 32 1
-%3 = OpTypeFunction %2
-%6 = OpConstant %2 42
-%10 = OpConstant %2 10
-%11 = OpConstant %2 20
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpSelectionMerge %8 None
-OpSwitch %6 %5 1 %5 2 %7
-%5 = OpLabel
-OpBranch %8
-%7 = OpLabel
-OpBranch %8
-%8 = OpLabel
-%9 = OpPhi %2 %10 %5 %11 %7
-OpReturnValue %9
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %4 = OpLabel
+ OpSelectionMerge %8 None
+ OpSwitch %int_42 %5 1 %5 2 %7
+ %5 = OpLabel
+ OpBranch %8
+ %7 = OpLabel
+ OpBranch %8
+ %8 = OpLabel
+ %9 = OpPhi %int %int_10 %5 %int_20 %7
+ OpReturnValue %9
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, Switch_Phi_SingleValue_CaseReturn) {
auto* func = b.Function("foo", ty.i32());
+ b.With(func->Block(), [&] {
+ auto* s = b.Switch(42_i);
+ s->SetResults(b.InstructionResult(ty.i32()));
+ auto* case_a = b.Case(s, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)},
+ ir::Switch::CaseSelector{nullptr}});
+ b.With(case_a, [&] { //
+ b.Return(func, 10_i);
+ });
- auto* s = b.Switch(42_i);
- s->SetResults(b.InstructionResult(ty.i32()));
- auto* case_a = b.Case(s, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)},
- ir::Switch::CaseSelector{nullptr}});
- case_a->Append(b.Return(func, 10_i));
+ auto* case_b = b.Case(s, utils::Vector{ir::Switch::CaseSelector{b.Constant(2_i)}});
+ b.With(case_b, [&] { //
+ b.ExitSwitch(s, 20_i);
+ });
- auto* case_b = b.Case(s, utils::Vector{ir::Switch::CaseSelector{b.Constant(2_i)}});
- case_b->Append(b.ExitSwitch(s, 20_i));
+ b.Return(func, s);
+ });
- func->Block()->Append(s);
- func->Block()->Append(b.Return(func, s));
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeInt 32 1
-%3 = OpTypeFunction %2
-%6 = OpConstant %2 42
-%9 = OpConstant %2 10
-%11 = OpConstant %2 20
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpSelectionMerge %8 None
-OpSwitch %6 %5 1 %5 2 %7
-%5 = OpLabel
-OpReturnValue %9
-%7 = OpLabel
-OpBranch %8
-%8 = OpLabel
-%10 = OpPhi %2 %11 %7
-OpReturnValue %10
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %4 = OpLabel
+%return_value = OpVariable %_ptr_Function_int Function
+%continue_execution = OpVariable %_ptr_Function_bool Function
+ OpStore %continue_execution %true
+ OpSelectionMerge %14 None
+ OpSwitch %int_42 %11 1 %11 2 %13
+ %11 = OpLabel
+ OpStore %continue_execution %false
+ OpStore %return_value %int_10
+ OpBranch %14
+ %13 = OpLabel
+ OpBranch %14
+ %14 = OpLabel
+ %17 = OpPhi %int %18 %11 %int_20 %13
+ %20 = OpLoad %bool %continue_execution
+ OpSelectionMerge %21 None
+ OpBranchConditional %20 %22 %21
+ %22 = OpLabel
+ OpStore %return_value %17
+ OpBranch %21
+ %21 = OpLabel
+ %23 = OpLoad %int %return_value
+ OpReturnValue %23
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, Switch_Phi_MultipleValue_0) {
auto* func = b.Function("foo", ty.i32());
+ b.With(func->Block(), [&] {
+ auto* s = b.Switch(42_i);
+ s->SetResults(b.InstructionResult(ty.i32()), b.InstructionResult(ty.bool_()));
+ auto* case_a = b.Case(s, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)},
+ ir::Switch::CaseSelector{nullptr}});
+ b.With(case_a, [&] { //
+ b.ExitSwitch(s, 10_i, true);
+ });
- auto* s = b.Switch(42_i);
- s->SetResults(b.InstructionResult(ty.i32()), b.InstructionResult(ty.bool_()));
- auto* case_a = b.Case(s, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)},
- ir::Switch::CaseSelector{nullptr}});
- case_a->Append(b.ExitSwitch(s, 10_i, true));
+ auto* case_b = b.Case(s, utils::Vector{ir::Switch::CaseSelector{b.Constant(2_i)}});
+ b.With(case_b, [&] { //
+ b.ExitSwitch(s, 20_i, false);
+ });
- auto* case_b = b.Case(s, utils::Vector{ir::Switch::CaseSelector{b.Constant(2_i)}});
- case_b->Append(b.ExitSwitch(s, 20_i, false));
+ b.Return(func, s->Result(0));
+ });
- func->Block()->Append(s);
- func->Block()->Append(b.Return(func, s->Result(0)));
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeInt 32 1
-%3 = OpTypeFunction %2
-%6 = OpConstant %2 42
-%10 = OpConstant %2 10
-%11 = OpConstant %2 20
-%12 = OpTypeBool
-%14 = OpConstantTrue %12
-%15 = OpConstantFalse %12
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpSelectionMerge %8 None
-OpSwitch %6 %5 1 %5 2 %7
-%5 = OpLabel
-OpBranch %8
-%7 = OpLabel
-OpBranch %8
-%8 = OpLabel
-%9 = OpPhi %2 %10 %5 %11 %7
-%13 = OpPhi %12 %14 %5 %15 %7
-OpReturnValue %9
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %4 = OpLabel
+ OpSelectionMerge %8 None
+ OpSwitch %int_42 %5 1 %5 2 %7
+ %5 = OpLabel
+ OpBranch %8
+ %7 = OpLabel
+ OpBranch %8
+ %8 = OpLabel
+ %9 = OpPhi %int %int_10 %5 %int_20 %7
+ %13 = OpPhi %bool %true %5 %false %7
+ OpReturnValue %9
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, Switch_Phi_MultipleValue_1) {
auto* func = b.Function("foo", ty.bool_());
+ b.With(func->Block(), [&] {
+ auto* s = b.Switch(b.Constant(42_i));
+ s->SetResults(b.InstructionResult(ty.i32()), b.InstructionResult(ty.bool_()));
+ auto* case_a = b.Case(s, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)},
+ ir::Switch::CaseSelector{nullptr}});
+ b.With(case_a, [&] { //
+ b.ExitSwitch(s, 10_i, true);
+ });
- auto* s = b.Switch(b.Constant(42_i));
- s->SetResults(b.InstructionResult(ty.i32()), b.InstructionResult(ty.bool_()));
- auto* case_a = b.Case(s, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)},
- ir::Switch::CaseSelector{nullptr}});
- case_a->Append(b.ExitSwitch(s, 10_i, true));
+ auto* case_b = b.Case(s, utils::Vector{ir::Switch::CaseSelector{b.Constant(2_i)}});
+ b.With(case_b, [&] { //
+ b.ExitSwitch(s, 20_i, false);
+ });
- auto* case_b = b.Case(s, utils::Vector{ir::Switch::CaseSelector{b.Constant(2_i)}});
- case_b->Append(b.ExitSwitch(s, 20_i, false));
+ b.Return(func, s->Result(1));
+ });
- func->Block()->Append(s);
- func->Block()->Append(b.Return(func, s->Result(1)));
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeBool
-%3 = OpTypeFunction %2
-%7 = OpTypeInt 32 1
-%6 = OpConstant %7 42
-%11 = OpConstant %7 10
-%12 = OpConstant %7 20
-%14 = OpConstantTrue %2
-%15 = OpConstantFalse %2
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpSelectionMerge %9 None
-OpSwitch %6 %5 1 %5 2 %8
-%5 = OpLabel
-OpBranch %9
-%8 = OpLabel
-OpBranch %9
-%9 = OpLabel
-%10 = OpPhi %7 %11 %5 %12 %8
-%13 = OpPhi %2 %14 %5 %15 %8
-OpReturnValue %13
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %4 = OpLabel
+ OpSelectionMerge %9 None
+ OpSwitch %int_42 %5 1 %5 2 %8
+ %5 = OpLabel
+ OpBranch %9
+ %8 = OpLabel
+ OpBranch %9
+ %9 = OpLabel
+ %10 = OpPhi %int %int_10 %5 %int_20 %8
+ %13 = OpPhi %bool %true %5 %false %8
+ OpReturnValue %13
+ OpFunctionEnd
)");
}
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_test.cc
index 9ec2a47..08d15bd 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_test.cc
@@ -30,36 +30,48 @@
}
TEST_F(SpvGeneratorImplTest, Unreachable) {
- auto* func = b.Function("foo", ty.i32());
+ auto* func = b.Function("foo", ty.void_());
+ b.With(func->Block(), [&] {
+ auto* loop = b.Loop();
+ b.With(loop->Body(), [&] {
+ auto* ifelse = b.If(true);
+ b.With(ifelse->True(), [&] { //
+ b.Continue(loop);
+ });
+ b.With(ifelse->False(), [&] { //
+ b.Continue(loop);
+ });
+ b.Unreachable();
- auto* i = b.If(true);
- i->True()->Append(b.Return(func, 10_i));
- i->False()->Append(b.Return(func, 20_i));
+ b.With(loop->Continuing(), [&] { //
+ b.NextIteration(loop);
+ });
+ });
+ b.Return(func);
+ });
- func->Block()->Append(i);
- func->Block()->Append(b.Unreachable());
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeInt 32 1
-%3 = OpTypeFunction %2
-%9 = OpTypeBool
-%8 = OpConstantTrue %9
-%10 = OpConstant %2 10
-%11 = OpConstant %2 20
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-OpSelectionMerge %5 None
-OpBranchConditional %8 %6 %7
-%6 = OpLabel
-OpReturnValue %10
-%7 = OpLabel
-OpReturnValue %11
-%5 = OpLabel
-OpUnreachable
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %foo = OpFunction %void None %3
+ %4 = OpLabel
+ OpBranch %7
+ %7 = OpLabel
+ OpLoopMerge %8 %6 None
+ OpBranch %5
+ %5 = OpLabel
+ OpSelectionMerge %9 None
+ OpBranchConditional %true %10 %11
+ %10 = OpLabel
+ OpBranch %6
+ %11 = OpLabel
+ OpBranch %6
+ %9 = OpLabel
+ OpUnreachable
+ %6 = OpLabel
+ OpBranch %7
+ %8 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_type_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_type_test.cc
index 7cd64e4..9caa027 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_type_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_type_test.cc
@@ -25,164 +25,140 @@
namespace {
TEST_F(SpvGeneratorImplTest, Type_Void) {
- auto id = generator_.Type(ty.void_());
- EXPECT_EQ(id, 1u);
- EXPECT_EQ(DumpTypes(), "%1 = OpTypeVoid\n");
+ generator_.Type(ty.void_());
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%void = OpTypeVoid");
}
TEST_F(SpvGeneratorImplTest, Type_Bool) {
- auto id = generator_.Type(ty.bool_());
- EXPECT_EQ(id, 1u);
- EXPECT_EQ(DumpTypes(), "%1 = OpTypeBool\n");
+ generator_.Type(ty.bool_());
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%bool = OpTypeBool");
}
TEST_F(SpvGeneratorImplTest, Type_I32) {
- auto id = generator_.Type(ty.i32());
- EXPECT_EQ(id, 1u);
- EXPECT_EQ(DumpTypes(), "%1 = OpTypeInt 32 1\n");
+ generator_.Type(ty.i32());
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%int = OpTypeInt 32 1");
}
TEST_F(SpvGeneratorImplTest, Type_U32) {
- auto id = generator_.Type(ty.u32());
- EXPECT_EQ(id, 1u);
- EXPECT_EQ(DumpTypes(), "%1 = OpTypeInt 32 0\n");
+ generator_.Type(ty.u32());
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%uint = OpTypeInt 32 0");
}
TEST_F(SpvGeneratorImplTest, Type_F32) {
- auto id = generator_.Type(ty.f32());
- EXPECT_EQ(id, 1u);
- EXPECT_EQ(DumpTypes(), "%1 = OpTypeFloat 32\n");
+ generator_.Type(ty.f32());
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%float = OpTypeFloat 32");
}
TEST_F(SpvGeneratorImplTest, Type_F16) {
- auto id = generator_.Type(ty.f16());
- EXPECT_EQ(id, 1u);
- EXPECT_EQ(DumpTypes(), "%1 = OpTypeFloat 16\n");
- EXPECT_EQ(DumpInstructions(generator_.Module().Capabilities()),
- "OpCapability Float16\n"
- "OpCapability UniformAndStorageBuffer16BitAccess\n"
- "OpCapability StorageBuffer16BitAccess\n"
- "OpCapability StorageInputOutput16\n");
+ generator_.Type(ty.f16());
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("OpCapability Float16");
+ EXPECT_INST("OpCapability UniformAndStorageBuffer16BitAccess");
+ EXPECT_INST("OpCapability StorageBuffer16BitAccess");
+ EXPECT_INST("OpCapability StorageInputOutput16");
+ EXPECT_INST("%half = OpTypeFloat 16");
}
TEST_F(SpvGeneratorImplTest, Type_Vec2i) {
- auto id = generator_.Type(ty.vec2(ty.i32()));
- EXPECT_EQ(id, 1u);
- EXPECT_EQ(DumpTypes(),
- "%2 = OpTypeInt 32 1\n"
- "%1 = OpTypeVector %2 2\n");
+ generator_.Type(ty.vec2<i32>());
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%v2int = OpTypeVector %int 2");
}
TEST_F(SpvGeneratorImplTest, Type_Vec3u) {
- auto id = generator_.Type(ty.vec3(ty.u32()));
- EXPECT_EQ(id, 1u);
- EXPECT_EQ(DumpTypes(),
- "%2 = OpTypeInt 32 0\n"
- "%1 = OpTypeVector %2 3\n");
+ generator_.Type(ty.vec3<u32>());
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%v3uint = OpTypeVector %uint 3");
}
TEST_F(SpvGeneratorImplTest, Type_Vec4f) {
- auto id = generator_.Type(ty.vec4(ty.f32()));
- EXPECT_EQ(id, 1u);
- EXPECT_EQ(DumpTypes(),
- "%2 = OpTypeFloat 32\n"
- "%1 = OpTypeVector %2 4\n");
+ generator_.Type(ty.vec4<f32>());
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%v4float = OpTypeVector %float 4");
}
TEST_F(SpvGeneratorImplTest, Type_Vec2h) {
- auto id = generator_.Type(ty.vec2(ty.f16()));
- EXPECT_EQ(id, 1u);
- EXPECT_EQ(DumpTypes(),
- "%2 = OpTypeFloat 16\n"
- "%1 = OpTypeVector %2 2\n");
+ generator_.Type(ty.vec2<f16>());
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%v2half = OpTypeVector %half 2");
}
TEST_F(SpvGeneratorImplTest, Type_Vec4Bool) {
- auto id = generator_.Type(ty.vec4(ty.bool_()));
- EXPECT_EQ(id, 1u);
- EXPECT_EQ(DumpTypes(),
- "%2 = OpTypeBool\n"
- "%1 = OpTypeVector %2 4\n");
+ generator_.Type(ty.vec4<bool>());
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%v4bool = OpTypeVector %bool 4");
}
TEST_F(SpvGeneratorImplTest, Type_Mat2x3f) {
- auto* vec = ty.mat2x3(ty.f32());
- auto id = generator_.Type(vec);
- EXPECT_EQ(id, 1u);
- EXPECT_EQ(DumpTypes(),
- "%3 = OpTypeFloat 32\n"
- "%2 = OpTypeVector %3 3\n"
- "%1 = OpTypeMatrix %2 2\n");
+ generator_.Type(ty.mat2x3(ty.f32()));
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%mat2v3float = OpTypeMatrix %v3float 2");
}
TEST_F(SpvGeneratorImplTest, Type_Mat4x2h) {
- auto* vec = ty.mat4x2(ty.f16());
- auto id = generator_.Type(vec);
- EXPECT_EQ(id, 1u);
- EXPECT_EQ(DumpTypes(),
- "%3 = OpTypeFloat 16\n"
- "%2 = OpTypeVector %3 2\n"
- "%1 = OpTypeMatrix %2 4\n");
+ generator_.Type(ty.mat4x2(ty.f16()));
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%mat4v2half = OpTypeMatrix %v2half 4");
}
TEST_F(SpvGeneratorImplTest, Type_Array_DefaultStride) {
- auto* arr = ty.array(ty.f32(), 4u);
- auto id = generator_.Type(arr);
- EXPECT_EQ(id, 1u);
- EXPECT_EQ(DumpTypes(),
- "%2 = OpTypeFloat 32\n"
- "%4 = OpTypeInt 32 0\n"
- "%3 = OpConstant %4 4\n"
- "%1 = OpTypeArray %2 %3\n");
- EXPECT_EQ(DumpInstructions(generator_.Module().Annots()), "OpDecorate %1 ArrayStride 4\n");
+ generator_.Type(ty.array<f32, 4>());
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("OpDecorate %_arr_float_uint_4 ArrayStride 4");
+ EXPECT_INST("%_arr_float_uint_4 = OpTypeArray %float %uint_4");
}
TEST_F(SpvGeneratorImplTest, Type_Array_ExplicitStride) {
- auto* arr = ty.array(ty.f32(), 4u, 16);
- auto id = generator_.Type(arr);
- EXPECT_EQ(id, 1u);
- EXPECT_EQ(DumpTypes(),
- "%2 = OpTypeFloat 32\n"
- "%4 = OpTypeInt 32 0\n"
- "%3 = OpConstant %4 4\n"
- "%1 = OpTypeArray %2 %3\n");
- EXPECT_EQ(DumpInstructions(generator_.Module().Annots()), "OpDecorate %1 ArrayStride 16\n");
+ generator_.Type(ty.array<f32, 4>(16));
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("OpDecorate %_arr_float_uint_4 ArrayStride 16");
+ EXPECT_INST("%_arr_float_uint_4 = OpTypeArray %float %uint_4");
}
TEST_F(SpvGeneratorImplTest, Type_Array_NestedArray) {
- auto* arr = ty.array(ty.array(ty.f32(), 64u), 4u);
- auto id = generator_.Type(arr);
- EXPECT_EQ(id, 1u);
- EXPECT_EQ(DumpTypes(),
- "%3 = OpTypeFloat 32\n"
- "%5 = OpTypeInt 32 0\n"
- "%4 = OpConstant %5 64\n"
- "%2 = OpTypeArray %3 %4\n"
- "%6 = OpConstant %5 4\n"
- "%1 = OpTypeArray %2 %6\n");
- EXPECT_EQ(DumpInstructions(generator_.Module().Annots()),
- "OpDecorate %2 ArrayStride 4\n"
- "OpDecorate %1 ArrayStride 256\n");
+ generator_.Type(ty.array(ty.array<f32, 64u>(), 4u));
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("OpDecorate %_arr_float_uint_64 ArrayStride 4");
+ EXPECT_INST("OpDecorate %_arr__arr_float_uint_64_uint_4 ArrayStride 256");
+ EXPECT_INST("%_arr_float_uint_64 = OpTypeArray %float %uint_64");
+ EXPECT_INST("%_arr__arr_float_uint_64_uint_4 = OpTypeArray %_arr_float_uint_64 %uint_4");
}
TEST_F(SpvGeneratorImplTest, Type_RuntimeArray_DefaultStride) {
- auto* arr = ty.runtime_array(ty.f32());
- auto id = generator_.Type(arr);
- EXPECT_EQ(id, 1u);
- EXPECT_EQ(DumpTypes(),
- "%2 = OpTypeFloat 32\n"
- "%1 = OpTypeRuntimeArray %2\n");
- EXPECT_EQ(DumpInstructions(generator_.Module().Annots()), "OpDecorate %1 ArrayStride 4\n");
+ generator_.Type(ty.array<f32>());
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("OpDecorate %_runtimearr_float ArrayStride 4");
+ EXPECT_INST("%_runtimearr_float = OpTypeRuntimeArray %float");
}
TEST_F(SpvGeneratorImplTest, Type_RuntimeArray_ExplicitStride) {
- auto* arr = ty.runtime_array(ty.f32(), 16);
- auto id = generator_.Type(arr);
- EXPECT_EQ(id, 1u);
- EXPECT_EQ(DumpTypes(),
- "%2 = OpTypeFloat 32\n"
- "%1 = OpTypeRuntimeArray %2\n");
- EXPECT_EQ(DumpInstructions(generator_.Module().Annots()), "OpDecorate %1 ArrayStride 16\n");
+ generator_.Type(ty.array<f32>(16));
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("OpDecorate %_runtimearr_float ArrayStride 16");
+ EXPECT_INST("%_runtimearr_float = OpTypeRuntimeArray %float");
}
TEST_F(SpvGeneratorImplTest, Type_Struct) {
@@ -191,20 +167,15 @@
{mod.symbols.Register("a"), ty.f32()},
{mod.symbols.Register("b"), ty.vec4<i32>()},
});
- auto id = generator_.Type(str);
- EXPECT_EQ(id, 1u);
- EXPECT_EQ(DumpTypes(), R"(%2 = OpTypeFloat 32
-%4 = OpTypeInt 32 1
-%3 = OpTypeVector %4 4
-%1 = OpTypeStruct %2 %3
-)");
- EXPECT_EQ(DumpInstructions(generator_.Module().Annots()), R"(OpMemberDecorate %1 0 Offset 0
-OpMemberDecorate %1 1 Offset 16
-)");
- EXPECT_EQ(DumpInstructions(generator_.Module().Debug()), R"(OpMemberName %1 0 "a"
-OpMemberName %1 1 "b"
-OpName %1 "MyStruct"
-)");
+ generator_.Type(str);
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("OpMemberName %MyStruct 0 \"a\"");
+ EXPECT_INST("OpMemberName %MyStruct 1 \"b\"");
+ EXPECT_INST("OpName %MyStruct \"MyStruct\"");
+ EXPECT_INST("OpMemberDecorate %MyStruct 0 Offset 0");
+ EXPECT_INST("OpMemberDecorate %MyStruct 1 Offset 16");
+ EXPECT_INST("%MyStruct = OpTypeStruct %float %v4int");
}
TEST_F(SpvGeneratorImplTest, Type_Struct_MatrixLayout) {
@@ -215,56 +186,40 @@
// Matrices nested inside arrays need layout decorations on the struct member too.
{mod.symbols.Register("arr"), ty.array(ty.array(ty.mat2x4<f16>(), 4), 4)},
});
- auto id = generator_.Type(str);
- EXPECT_EQ(id, 1u);
- EXPECT_EQ(DumpTypes(), R"(%4 = OpTypeFloat 32
-%3 = OpTypeVector %4 3
-%2 = OpTypeMatrix %3 3
-%9 = OpTypeFloat 16
-%8 = OpTypeVector %9 4
-%7 = OpTypeMatrix %8 2
-%11 = OpTypeInt 32 0
-%10 = OpConstant %11 4
-%6 = OpTypeArray %7 %10
-%5 = OpTypeArray %6 %10
-%1 = OpTypeStruct %2 %5
-)");
- EXPECT_EQ(DumpInstructions(generator_.Module().Annots()), R"(OpMemberDecorate %1 0 Offset 0
-OpMemberDecorate %1 0 ColMajor
-OpMemberDecorate %1 0 MatrixStride 16
-OpDecorate %6 ArrayStride 16
-OpDecorate %5 ArrayStride 64
-OpMemberDecorate %1 1 Offset 48
-OpMemberDecorate %1 1 ColMajor
-OpMemberDecorate %1 1 MatrixStride 8
-)");
- EXPECT_EQ(DumpInstructions(generator_.Module().Debug()), R"(OpMemberName %1 0 "m"
-OpMemberName %1 1 "arr"
-OpName %1 "MyStruct"
-)");
+ generator_.Type(str);
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("OpMemberDecorate %MyStruct 0 ColMajor");
+ EXPECT_INST("OpMemberDecorate %MyStruct 0 MatrixStride 16");
+ EXPECT_INST("OpMemberDecorate %MyStruct 1 ColMajor");
+ EXPECT_INST("OpMemberDecorate %MyStruct 1 MatrixStride 8");
+ EXPECT_INST("%MyStruct = OpTypeStruct %mat3v3float %_arr__arr_mat2v4half_uint_4_uint_4");
}
// Test that we can emit multiple types.
// Includes types with the same opcode but different parameters.
TEST_F(SpvGeneratorImplTest, Type_Multiple) {
- EXPECT_EQ(generator_.Type(ty.i32()), 1u);
- EXPECT_EQ(generator_.Type(ty.u32()), 2u);
- EXPECT_EQ(generator_.Type(ty.f32()), 3u);
- EXPECT_EQ(generator_.Type(ty.f16()), 4u);
- EXPECT_EQ(DumpTypes(), R"(%1 = OpTypeInt 32 1
-%2 = OpTypeInt 32 0
-%3 = OpTypeFloat 32
-%4 = OpTypeFloat 16
+ generator_.Type(ty.i32());
+ generator_.Type(ty.u32());
+ generator_.Type(ty.f32());
+ generator_.Type(ty.f16());
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %int = OpTypeInt 32 1
+ %uint = OpTypeInt 32 0
+ %float = OpTypeFloat 32
+ %half = OpTypeFloat 16
)");
}
// Test that we do not emit the same type more than once.
TEST_F(SpvGeneratorImplTest, Type_Deduplicate) {
- auto* i32 = ty.i32();
- EXPECT_EQ(generator_.Type(i32), 1u);
- EXPECT_EQ(generator_.Type(i32), 1u);
- EXPECT_EQ(generator_.Type(i32), 1u);
- EXPECT_EQ(DumpTypes(), "%1 = OpTypeInt 32 1\n");
+ auto id = generator_.Type(ty.i32());
+ EXPECT_EQ(generator_.Type(ty.i32()), id);
+ EXPECT_EQ(generator_.Type(ty.i32()), id);
+
+ ASSERT_TRUE(Generate()) << Error() << output_;
}
} // namespace
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_var_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_var_test.cc
index a79e326..8c50131 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_var_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_var_test.cc
@@ -23,597 +23,236 @@
TEST_F(SpvGeneratorImplTest, FunctionVar_NoInit) {
auto* func = b.Function("foo", ty.void_());
-
b.With(func->Block(), [&] {
- b.Var(ty.ptr<function, i32>());
+ b.Var("v", ty.ptr<function, i32>());
b.Return(func);
});
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%7 = OpTypeInt 32 1
-%6 = OpTypePointer Function %7
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-%5 = OpVariable %6 Function
-OpReturn
-OpFunctionEnd
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%v = OpVariable %_ptr_Function_int Function");
}
TEST_F(SpvGeneratorImplTest, FunctionVar_WithInit) {
auto* func = b.Function("foo", ty.void_());
-
b.With(func->Block(), [&] {
- auto* v = b.Var(ty.ptr<function, i32>());
+ auto* v = b.Var("v", ty.ptr<function, i32>());
v->SetInitializer(b.Constant(42_i));
-
b.Return(func);
});
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%7 = OpTypeInt 32 1
-%6 = OpTypePointer Function %7
-%8 = OpConstant %7 42
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-%5 = OpVariable %6 Function
-OpStore %5 %8
-OpReturn
-OpFunctionEnd
-)");
-}
-
-TEST_F(SpvGeneratorImplTest, FunctionVar_Name) {
- auto* func = b.Function("foo", ty.void_());
-
- b.With(func->Block(), [&] {
- b.Var("myvar", ty.ptr<function, i32>());
- b.Return(func);
- });
-
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-OpName %5 "myvar"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%7 = OpTypeInt 32 1
-%6 = OpTypePointer Function %7
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-%5 = OpVariable %6 Function
-OpReturn
-OpFunctionEnd
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%v = OpVariable %_ptr_Function_int Function");
+ EXPECT_INST("OpStore %v %int_42");
}
TEST_F(SpvGeneratorImplTest, FunctionVar_DeclInsideBlock) {
auto* func = b.Function("foo", ty.void_());
-
b.With(func->Block(), [&] {
auto* i = b.If(true);
b.With(i->True(), [&] {
- auto* v = b.Var(ty.ptr<function, i32>());
+ auto* v = b.Var("v", ty.ptr<function, i32>());
v->SetInitializer(b.Constant(42_i));
b.ExitIf(i);
});
- b.With(i->False(), [&] { b.Return(func); });
-
b.Return(func);
});
- ASSERT_TRUE(IRIsValid()) << Error();
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%9 = OpTypeBool
-%8 = OpConstantTrue %9
-%12 = OpTypeInt 32 1
-%11 = OpTypePointer Function %12
-%13 = OpConstant %12 42
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-%10 = OpVariable %11 Function
-OpSelectionMerge %5 None
-OpBranchConditional %8 %6 %7
-%6 = OpLabel
-OpStore %10 %13
-OpBranch %5
-%7 = OpLabel
-OpReturn
-%5 = OpLabel
-OpReturn
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %foo = OpFunction %void None %3
+ %4 = OpLabel
+ %v = OpVariable %_ptr_Function_int Function
+ OpSelectionMerge %5 None
+ OpBranchConditional %true %6 %5
+ %6 = OpLabel
+ OpStore %v %int_42
+ OpBranch %5
+ %5 = OpLabel
+ OpReturn
+ OpFunctionEnd
)");
}
TEST_F(SpvGeneratorImplTest, FunctionVar_Load) {
auto* func = b.Function("foo", ty.void_());
-
b.With(func->Block(), [&] {
- auto* store_ty = ty.i32();
- auto* v = b.Var(ty.ptr(function, store_ty));
- b.Load(v);
+ auto* v = b.Var("v", ty.ptr<function, i32>());
+ auto* result = b.Load(v);
b.Return(func);
+ mod.SetName(result, "result");
});
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%7 = OpTypeInt 32 1
-%6 = OpTypePointer Function %7
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-%5 = OpVariable %6 Function
-%8 = OpLoad %7 %5
-OpReturn
-OpFunctionEnd
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%v = OpVariable %_ptr_Function_int Function");
+ EXPECT_INST("%result = OpLoad %int %v");
}
TEST_F(SpvGeneratorImplTest, FunctionVar_Store) {
auto* func = b.Function("foo", ty.void_());
-
b.With(func->Block(), [&] {
- auto* v = b.Var(ty.ptr<function, i32>());
+ auto* v = b.Var("v", ty.ptr<function, i32>());
b.Store(v, 42_i);
b.Return(func);
});
- ASSERT_TRUE(IRIsValid()) << Error();
-
- generator_.EmitFunction(func);
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
-%2 = OpTypeVoid
-%3 = OpTypeFunction %2
-%7 = OpTypeInt 32 1
-%6 = OpTypePointer Function %7
-%8 = OpConstant %7 42
-%1 = OpFunction %2 None %3
-%4 = OpLabel
-%5 = OpVariable %6 Function
-OpStore %5 %8
-OpReturn
-OpFunctionEnd
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%v = OpVariable %_ptr_Function_int Function");
+ EXPECT_INST("OpStore %v %int_42");
}
TEST_F(SpvGeneratorImplTest, PrivateVar_NoInit) {
- b.RootBlock()->Append(b.Var(ty.ptr<private_, i32>()));
+ b.RootBlock()->Append(b.Var("v", ty.ptr<private_, i32>()));
- ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpCapability Shader
-OpMemoryModel Logical GLSL450
-OpEntryPoint GLCompute %4 "unused_entry_point"
-OpExecutionMode %4 LocalSize 1 1 1
-OpName %4 "unused_entry_point"
-%3 = OpTypeInt 32 1
-%2 = OpTypePointer Private %3
-%1 = OpVariable %2 Private
-%5 = OpTypeVoid
-%6 = OpTypeFunction %5
-%4 = OpFunction %5 None %6
-%7 = OpLabel
-OpReturn
-OpFunctionEnd
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%v = OpVariable %_ptr_Private_int Private");
}
TEST_F(SpvGeneratorImplTest, PrivateVar_WithInit) {
- auto* v = b.Var(ty.ptr<private_, i32>());
+ auto* v = b.Var("v", ty.ptr<private_, i32>());
v->SetInitializer(b.Constant(42_i));
b.RootBlock()->Append(v);
- ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpCapability Shader
-OpMemoryModel Logical GLSL450
-OpEntryPoint GLCompute %5 "unused_entry_point"
-OpExecutionMode %5 LocalSize 1 1 1
-OpName %5 "unused_entry_point"
-%3 = OpTypeInt 32 1
-%2 = OpTypePointer Private %3
-%4 = OpConstant %3 42
-%1 = OpVariable %2 Private %4
-%6 = OpTypeVoid
-%7 = OpTypeFunction %6
-%5 = OpFunction %6 None %7
-%8 = OpLabel
-OpReturn
-OpFunctionEnd
-)");
-}
-
-TEST_F(SpvGeneratorImplTest, PrivateVar_Name) {
- auto* v = b.Var("myvar", ty.ptr<private_, i32>());
- v->SetInitializer(b.Constant(42_i));
- b.RootBlock()->Append(v);
-
- ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpCapability Shader
-OpMemoryModel Logical GLSL450
-OpEntryPoint GLCompute %5 "unused_entry_point"
-OpExecutionMode %5 LocalSize 1 1 1
-OpName %1 "myvar"
-OpName %5 "unused_entry_point"
-%3 = OpTypeInt 32 1
-%2 = OpTypePointer Private %3
-%4 = OpConstant %3 42
-%1 = OpVariable %2 Private %4
-%6 = OpTypeVoid
-%7 = OpTypeFunction %6
-%5 = OpFunction %6 None %7
-%8 = OpLabel
-OpReturn
-OpFunctionEnd
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%v = OpVariable %_ptr_Private_int Private %int_42");
}
TEST_F(SpvGeneratorImplTest, PrivateVar_LoadAndStore) {
- auto* func = b.Function("foo", ty.void_(), ir::Function::PipelineStage::kFragment);
-
- auto* store_ty = ty.i32();
- auto* v = b.Var(ty.ptr(private_, store_ty));
+ auto* v = b.Var("v", ty.ptr<private_, i32>());
v->SetInitializer(b.Constant(42_i));
b.RootBlock()->Append(v);
+ auto* func = b.Function("foo", ty.void_(), ir::Function::PipelineStage::kFragment);
b.With(func->Block(), [&] {
- b.Load(v);
- auto* add = b.Add(store_ty, v, 1_i);
+ auto* load = b.Load(v);
+ auto* add = b.Add(ty.i32(), load, 1_i);
b.Store(v, add);
b.Return(func);
+ mod.SetName(load, "load");
+ mod.SetName(add, "add");
});
- ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpCapability Shader
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %5 "foo"
-OpExecutionMode %5 OriginUpperLeft
-OpName %5 "foo"
-%3 = OpTypeInt 32 1
-%2 = OpTypePointer Private %3
-%4 = OpConstant %3 42
-%1 = OpVariable %2 Private %4
-%6 = OpTypeVoid
-%7 = OpTypeFunction %6
-%11 = OpConstant %3 1
-%5 = OpFunction %6 None %7
-%8 = OpLabel
-%9 = OpLoad %3 %1
-%10 = OpIAdd %3 %1 %11
-OpStore %1 %10
-OpReturn
-OpFunctionEnd
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%v = OpVariable %_ptr_Private_int Private %int_42");
+ EXPECT_INST("%load = OpLoad %int %v");
+ EXPECT_INST("OpStore %v %add");
}
TEST_F(SpvGeneratorImplTest, WorkgroupVar) {
- b.RootBlock()->Append(b.Var(ty.ptr<workgroup, i32>()));
+ b.RootBlock()->Append(b.Var("v", ty.ptr<workgroup, i32>()));
- ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpCapability Shader
-OpMemoryModel Logical GLSL450
-OpEntryPoint GLCompute %4 "unused_entry_point"
-OpExecutionMode %4 LocalSize 1 1 1
-OpName %4 "unused_entry_point"
-%3 = OpTypeInt 32 1
-%2 = OpTypePointer Workgroup %3
-%1 = OpVariable %2 Workgroup
-%5 = OpTypeVoid
-%6 = OpTypeFunction %5
-%4 = OpFunction %5 None %6
-%7 = OpLabel
-OpReturn
-OpFunctionEnd
-)");
-}
-
-TEST_F(SpvGeneratorImplTest, WorkgroupVar_Name) {
- b.RootBlock()->Append(b.Var("myvar", ty.ptr<workgroup, i32>()));
-
- ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpCapability Shader
-OpMemoryModel Logical GLSL450
-OpEntryPoint GLCompute %4 "unused_entry_point"
-OpExecutionMode %4 LocalSize 1 1 1
-OpName %1 "myvar"
-OpName %4 "unused_entry_point"
-%3 = OpTypeInt 32 1
-%2 = OpTypePointer Workgroup %3
-%1 = OpVariable %2 Workgroup
-%5 = OpTypeVoid
-%6 = OpTypeFunction %5
-%4 = OpFunction %5 None %6
-%7 = OpLabel
-OpReturn
-OpFunctionEnd
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%v = OpVariable %_ptr_Workgroup_int Workgroup");
}
TEST_F(SpvGeneratorImplTest, WorkgroupVar_LoadAndStore) {
+ auto* v = b.RootBlock()->Append(b.Var("v", ty.ptr<workgroup, i32>()));
+
auto* func = b.Function("foo", ty.void_(), ir::Function::PipelineStage::kCompute,
std::array{1u, 1u, 1u});
-
- auto* store_ty = ty.i32();
- auto* v = b.RootBlock()->Append(b.Var(ty.ptr(workgroup, store_ty)));
-
b.With(func->Block(), [&] {
- b.Load(v);
- auto* add = b.Add(store_ty, v, 1_i);
+ auto* load = b.Load(v);
+ auto* add = b.Add(ty.i32(), load, 1_i);
b.Store(v, add);
b.Return(func);
+ mod.SetName(load, "load");
+ mod.SetName(add, "add");
});
- ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpCapability Shader
-OpMemoryModel Logical GLSL450
-OpEntryPoint GLCompute %4 "foo"
-OpExecutionMode %4 LocalSize 1 1 1
-OpName %4 "foo"
-%3 = OpTypeInt 32 1
-%2 = OpTypePointer Workgroup %3
-%1 = OpVariable %2 Workgroup
-%5 = OpTypeVoid
-%6 = OpTypeFunction %5
-%10 = OpConstant %3 1
-%4 = OpFunction %5 None %6
-%7 = OpLabel
-%8 = OpLoad %3 %1
-%9 = OpIAdd %3 %1 %10
-OpStore %1 %9
-OpReturn
-OpFunctionEnd
-)");
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST("%v = OpVariable %_ptr_Workgroup_int Workgroup");
+ EXPECT_INST("%load = OpLoad %int %v");
+ EXPECT_INST("OpStore %v %add");
}
TEST_F(SpvGeneratorImplTest, WorkgroupVar_ZeroInitializeWithExtension) {
- b.RootBlock()->Append(b.Var(ty.ptr<workgroup, i32>()));
+ b.RootBlock()->Append(b.Var("v", ty.ptr<workgroup, i32>()));
// Create a generator with the zero_init_workgroup_memory flag set to `true`.
spirv::GeneratorImplIr gen(&mod, true);
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics().str();
- EXPECT_EQ(DumpModule(gen.Module()), R"(OpCapability Shader
-OpMemoryModel Logical GLSL450
-OpEntryPoint GLCompute %5 "unused_entry_point"
-OpExecutionMode %5 LocalSize 1 1 1
-OpName %5 "unused_entry_point"
-%3 = OpTypeInt 32 1
-%2 = OpTypePointer Workgroup %3
-%4 = OpConstantNull %3
-%1 = OpVariable %2 Workgroup %4
-%6 = OpTypeVoid
-%7 = OpTypeFunction %6
-%5 = OpFunction %6 None %7
-%8 = OpLabel
-OpReturn
-OpFunctionEnd
-)");
+ ASSERT_TRUE(Generate(gen)) << Error() << output_;
+ EXPECT_INST("%4 = OpConstantNull %int");
+ EXPECT_INST("%v = OpVariable %_ptr_Workgroup_int Workgroup %4");
}
TEST_F(SpvGeneratorImplTest, StorageVar) {
- auto* v = b.Var(ty.ptr<storage, i32>());
+ auto* v = b.Var("v", ty.ptr<storage, i32>());
v->SetBindingPoint(0, 0);
b.RootBlock()->Append(v);
- ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpCapability Shader
-OpMemoryModel Logical GLSL450
-OpEntryPoint GLCompute %5 "unused_entry_point"
-OpExecutionMode %5 LocalSize 1 1 1
-OpMemberName %3 0 "tint_symbol"
-OpName %3 "tint_symbol_1"
-OpName %5 "unused_entry_point"
-OpMemberDecorate %3 0 Offset 0
-OpDecorate %3 Block
-OpDecorate %1 DescriptorSet 0
-OpDecorate %1 Binding 0
-%4 = OpTypeInt 32 1
-%3 = OpTypeStruct %4
-%2 = OpTypePointer StorageBuffer %3
-%1 = OpVariable %2 StorageBuffer
-%6 = OpTypeVoid
-%7 = OpTypeFunction %6
-%5 = OpFunction %6 None %7
-%8 = OpLabel
-OpReturn
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ OpDecorate %tint_symbol_1 Block
+ OpDecorate %1 DescriptorSet 0
+ OpDecorate %1 Binding 0
)");
-}
-
-TEST_F(SpvGeneratorImplTest, StorageVar_Name) {
- auto* v = b.Var("myvar", ty.ptr<storage, i32>());
- v->SetBindingPoint(0, 0);
- b.RootBlock()->Append(v);
-
- ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpCapability Shader
-OpMemoryModel Logical GLSL450
-OpEntryPoint GLCompute %5 "unused_entry_point"
-OpExecutionMode %5 LocalSize 1 1 1
-OpMemberName %3 0 "tint_symbol"
-OpName %3 "tint_symbol_1"
-OpName %5 "unused_entry_point"
-OpMemberDecorate %3 0 Offset 0
-OpDecorate %3 Block
-OpDecorate %1 DescriptorSet 0
-OpDecorate %1 Binding 0
-%4 = OpTypeInt 32 1
-%3 = OpTypeStruct %4
-%2 = OpTypePointer StorageBuffer %3
-%1 = OpVariable %2 StorageBuffer
-%6 = OpTypeVoid
-%7 = OpTypeFunction %6
-%5 = OpFunction %6 None %7
-%8 = OpLabel
-OpReturn
-OpFunctionEnd
+ EXPECT_INST(R"(
+%tint_symbol_1 = OpTypeStruct %int
+%_ptr_StorageBuffer_tint_symbol_1 = OpTypePointer StorageBuffer %tint_symbol_1
+ %1 = OpVariable %_ptr_StorageBuffer_tint_symbol_1 StorageBuffer
)");
}
TEST_F(SpvGeneratorImplTest, StorageVar_LoadAndStore) {
- auto* v = b.Var(ty.ptr<storage, i32>());
+ auto* v = b.Var("v", ty.ptr<storage, i32>());
v->SetBindingPoint(0, 0);
b.RootBlock()->Append(v);
auto* func = b.Function("foo", ty.void_(), ir::Function::PipelineStage::kCompute,
std::array{1u, 1u, 1u});
-
b.With(func->Block(), [&] {
- b.Load(v);
- auto* add = b.Add(ty.i32(), v, 1_i);
+ auto* load = b.Load(v);
+ auto* add = b.Add(ty.i32(), load, 1_i);
b.Store(v, add);
b.Return(func);
+ mod.SetName(load, "load");
+ mod.SetName(add, "add");
});
- ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpCapability Shader
-OpMemoryModel Logical GLSL450
-OpEntryPoint GLCompute %5 "foo"
-OpExecutionMode %5 LocalSize 1 1 1
-OpMemberName %3 0 "tint_symbol"
-OpName %3 "tint_symbol_1"
-OpName %5 "foo"
-OpMemberDecorate %3 0 Offset 0
-OpDecorate %3 Block
-OpDecorate %1 DescriptorSet 0
-OpDecorate %1 Binding 0
-%4 = OpTypeInt 32 1
-%3 = OpTypeStruct %4
-%2 = OpTypePointer StorageBuffer %3
-%1 = OpVariable %2 StorageBuffer
-%6 = OpTypeVoid
-%7 = OpTypeFunction %6
-%10 = OpTypePointer StorageBuffer %4
-%12 = OpTypeInt 32 0
-%11 = OpConstant %12 0
-%16 = OpConstant %4 1
-%5 = OpFunction %6 None %7
-%8 = OpLabel
-%9 = OpAccessChain %10 %1 %11
-%13 = OpLoad %4 %9
-%14 = OpAccessChain %10 %1 %11
-%15 = OpIAdd %4 %14 %16
-%17 = OpAccessChain %10 %1 %11
-OpStore %17 %15
-OpReturn
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %9 = OpAccessChain %_ptr_StorageBuffer_int %1 %uint_0
+ %load = OpLoad %int %9
+ %add = OpIAdd %int %load %int_1
+ %16 = OpAccessChain %_ptr_StorageBuffer_int %1 %uint_0
+ OpStore %16 %add
)");
}
TEST_F(SpvGeneratorImplTest, UniformVar) {
- auto* v = b.Var(ty.ptr<uniform, i32>());
+ auto* v = b.Var("v", ty.ptr<uniform, i32>());
v->SetBindingPoint(0, 0);
b.RootBlock()->Append(v);
- ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpCapability Shader
-OpMemoryModel Logical GLSL450
-OpEntryPoint GLCompute %5 "unused_entry_point"
-OpExecutionMode %5 LocalSize 1 1 1
-OpMemberName %3 0 "tint_symbol"
-OpName %3 "tint_symbol_1"
-OpName %5 "unused_entry_point"
-OpMemberDecorate %3 0 Offset 0
-OpDecorate %3 Block
-OpDecorate %1 DescriptorSet 0
-OpDecorate %1 Binding 0
-%4 = OpTypeInt 32 1
-%3 = OpTypeStruct %4
-%2 = OpTypePointer Uniform %3
-%1 = OpVariable %2 Uniform
-%6 = OpTypeVoid
-%7 = OpTypeFunction %6
-%5 = OpFunction %6 None %7
-%8 = OpLabel
-OpReturn
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ OpDecorate %tint_symbol_1 Block
+ OpDecorate %1 DescriptorSet 0
+ OpDecorate %1 Binding 0
)");
-}
-
-TEST_F(SpvGeneratorImplTest, UniformVar_Name) {
- auto* v = b.Var("myvar", ty.ptr<uniform, i32>());
- v->SetBindingPoint(0, 0);
- b.RootBlock()->Append(v);
-
- ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpCapability Shader
-OpMemoryModel Logical GLSL450
-OpEntryPoint GLCompute %5 "unused_entry_point"
-OpExecutionMode %5 LocalSize 1 1 1
-OpMemberName %3 0 "tint_symbol"
-OpName %3 "tint_symbol_1"
-OpName %5 "unused_entry_point"
-OpMemberDecorate %3 0 Offset 0
-OpDecorate %3 Block
-OpDecorate %1 DescriptorSet 0
-OpDecorate %1 Binding 0
-%4 = OpTypeInt 32 1
-%3 = OpTypeStruct %4
-%2 = OpTypePointer Uniform %3
-%1 = OpVariable %2 Uniform
-%6 = OpTypeVoid
-%7 = OpTypeFunction %6
-%5 = OpFunction %6 None %7
-%8 = OpLabel
-OpReturn
-OpFunctionEnd
+ EXPECT_INST(R"(
+%tint_symbol_1 = OpTypeStruct %int
+%_ptr_Uniform_tint_symbol_1 = OpTypePointer Uniform %tint_symbol_1
+ %1 = OpVariable %_ptr_Uniform_tint_symbol_1 Uniform
)");
}
TEST_F(SpvGeneratorImplTest, UniformVar_Load) {
- auto* v = b.Var(ty.ptr<uniform, i32>());
+ auto* v = b.Var("v", ty.ptr<uniform, i32>());
v->SetBindingPoint(0, 0);
b.RootBlock()->Append(v);
auto* func = b.Function("foo", ty.void_(), ir::Function::PipelineStage::kCompute,
std::array{1u, 1u, 1u});
-
b.With(func->Block(), [&] {
- b.Load(v);
+ auto* load = b.Load(v);
b.Return(func);
+ mod.SetName(load, "load");
});
- ASSERT_TRUE(generator_.Generate()) << generator_.Diagnostics().str();
- EXPECT_EQ(DumpModule(generator_.Module()), R"(OpCapability Shader
-OpMemoryModel Logical GLSL450
-OpEntryPoint GLCompute %5 "foo"
-OpExecutionMode %5 LocalSize 1 1 1
-OpMemberName %3 0 "tint_symbol"
-OpName %3 "tint_symbol_1"
-OpName %5 "foo"
-OpMemberDecorate %3 0 Offset 0
-OpDecorate %3 Block
-OpDecorate %1 DescriptorSet 0
-OpDecorate %1 Binding 0
-%4 = OpTypeInt 32 1
-%3 = OpTypeStruct %4
-%2 = OpTypePointer Uniform %3
-%1 = OpVariable %2 Uniform
-%6 = OpTypeVoid
-%7 = OpTypeFunction %6
-%10 = OpTypePointer Uniform %4
-%12 = OpTypeInt 32 0
-%11 = OpConstant %12 0
-%5 = OpFunction %6 None %7
-%8 = OpLabel
-%9 = OpAccessChain %10 %1 %11
-%13 = OpLoad %4 %9
-OpReturn
-OpFunctionEnd
+ ASSERT_TRUE(Generate()) << Error() << output_;
+ EXPECT_INST(R"(
+ %9 = OpAccessChain %_ptr_Uniform_int %1 %uint_0
+ %load = OpLoad %int %9
)");
}
diff --git a/src/tint/writer/spirv/ir/test_helper_ir.h b/src/tint/writer/spirv/ir/test_helper_ir.h
index 27559be..5fbf6e4 100644
--- a/src/tint/writer/spirv/ir/test_helper_ir.h
+++ b/src/tint/writer/spirv/ir/test_helper_ir.h
@@ -17,7 +17,9 @@
#include <string>
#include <utility>
+#include <vector>
+#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "spirv-tools/libspirv.hpp"
#include "src/tint/ir/builder.h"
@@ -57,7 +59,7 @@
/// The SPIR-V generator.
GeneratorImplIr generator_;
- /// Validation errors
+ /// Errors produced during codegen or SPIR-V validation.
std::string err_;
/// SPIR-V output.
@@ -66,38 +68,34 @@
/// @returns the error string from the validation
std::string Error() const { return err_; }
- /// @returns true if the IR module is valid
- bool IRIsValid() {
- auto res = ir::Validate(mod);
- if (!res) {
- err_ = res.Failure().str();
+ /// Run the specified generator on the IR module and validate the result.
+ /// @param generator the generator to use for SPIR-V generation
+ /// @returns true if generation and validation succeeded
+ bool Generate(GeneratorImplIr& generator) {
+ if (!generator.Generate()) {
+ err_ = generator.Diagnostics().str();
return false;
}
+
+ output_ = Disassemble(generator.Result(), SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES |
+ SPV_BINARY_TO_TEXT_OPTION_INDENT |
+ SPV_BINARY_TO_TEXT_OPTION_COMMENT);
+
+ if (!Validate(generator.Result())) {
+ return false;
+ }
+
return true;
}
/// Run the generator on the IR module and validate the result.
/// @returns true if generation and validation succeeded
- bool Generate() {
- if (!generator_.Generate()) {
- err_ = generator_.Diagnostics().str();
- return false;
- }
- if (!Validate()) {
- return false;
- }
-
- output_ = Disassemble(generator_.Result(), SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES |
- SPV_BINARY_TO_TEXT_OPTION_INDENT |
- SPV_BINARY_TO_TEXT_OPTION_COMMENT);
- return true;
- }
+ bool Generate() { return Generate(generator_); }
/// Validate the generated SPIR-V using the SPIR-V Tools Validator.
+ /// @param binary the SPIR-V binary module to validate
/// @returns true if validation succeeded, false otherwise
- bool Validate() {
- auto binary = generator_.Result();
-
+ bool Validate(const std::vector<uint32_t>& binary) {
std::string spv_errors;
auto msg_consumer = [&spv_errors](spv_message_level_t level, const char*,
const spv_position_t& position, const char* message) {