[spirv-reader] Add OpCompositeConstruct
Bug: tint:3
Change-Id: Ibb1a4124e7e7b7a5b95bdd4e7c7e7f1c570e641c
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/23127
Reviewed-by: dan sinclair <dsinclair@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index 9dbeb92..c938abb 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -644,6 +644,7 @@
"src/reader/spirv/function_arithmetic_test.cc",
"src/reader/spirv/function_bit_test.cc",
"src/reader/spirv/function_cfg_test.cc",
+ "src/reader/spirv/function_composite_test.cc",
"src/reader/spirv/function_conversion_test.cc",
"src/reader/spirv/function_decl_test.cc",
"src/reader/spirv/function_glsl_std_450_test.cc",
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 55a24a6..9fa9927 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -320,6 +320,7 @@
reader/spirv/function_arithmetic_test.cc
reader/spirv/function_bit_test.cc
reader/spirv/function_cfg_test.cc
+ reader/spirv/function_composite_test.cc
reader/spirv/function_conversion_test.cc
reader/spirv/function_decl_test.cc
reader/spirv/function_glsl_std_450_test.cc
diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc
index f9aca7e..05a9c9e 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -45,6 +45,7 @@
#include "src/ast/sint_literal.h"
#include "src/ast/storage_class.h"
#include "src/ast/switch_statement.h"
+#include "src/ast/type_constructor_expression.h"
#include "src/ast/uint_literal.h"
#include "src/ast/unary_op.h"
#include "src/ast/unary_op_expression.h"
@@ -2390,6 +2391,15 @@
return EmitGlslStd450ExtInst(inst);
}
+ if (opcode == SpvOpCompositeConstruct) {
+ ast::ExpressionList operands;
+ for (uint32_t iarg = 0; iarg < inst.NumInOperands(); ++iarg) {
+ operands.emplace_back(MakeOperand(inst, iarg).expr);
+ }
+ return {ast_type, std::make_unique<ast::TypeConstructorExpression>(
+ ast_type, std::move(operands))};
+ }
+
// builtin readonly function
// glsl.std.450 readonly function
diff --git a/src/reader/spirv/function_composite_test.cc b/src/reader/spirv/function_composite_test.cc
new file mode 100644
index 0000000..6030a90
--- /dev/null
+++ b/src/reader/spirv/function_composite_test.cc
@@ -0,0 +1,235 @@
+// Copyright 2020 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <string>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "src/reader/spirv/fail_stream.h"
+#include "src/reader/spirv/function.h"
+#include "src/reader/spirv/parser_impl.h"
+#include "src/reader/spirv/parser_impl_test_helper.h"
+#include "src/reader/spirv/spirv_tools_helpers_test.h"
+
+namespace tint {
+namespace reader {
+namespace spirv {
+namespace {
+
+using ::testing::HasSubstr;
+
+std::string Preamble() {
+ return R"(
+ %void = OpTypeVoid
+ %voidfn = OpTypeFunction %void
+
+ %uint = OpTypeInt 32 0
+ %int = OpTypeInt 32 1
+ %float = OpTypeFloat 32
+
+ %uint_10 = OpConstant %uint 10
+ %uint_20 = OpConstant %uint 20
+ %uint_3 = OpConstant %uint 3
+ %uint_4 = OpConstant %uint 4
+ %uint_5 = OpConstant %uint 5
+ %int_30 = OpConstant %int 30
+ %int_40 = OpConstant %int 40
+ %float_50 = OpConstant %float 50
+ %float_60 = OpConstant %float 60
+ %float_70 = OpConstant %float 70
+
+ %v2uint = OpTypeVector %uint 2
+ %v2int = OpTypeVector %int 2
+ %v2float = OpTypeVector %float 2
+
+ %m3v2float = OpTypeMatrix %v2float 3
+
+ %s_v2f_u_i = OpTypeStruct %v2float %uint %int
+ %a_u_5 = OpTypeArray %uint %uint_5
+
+ %v2float_50_60 = OpConstantComposite %v2float %float_50 %float_60
+ %v2float_60_50 = OpConstantComposite %v2float %float_60 %float_50
+ %v2float_70_70 = OpConstantComposite %v2float %float_70 %float_70
+)";
+}
+
+using SpvParserTest_Composite_Construct = SpvParserTest;
+
+TEST_F(SpvParserTest_Composite_Construct, Vector) {
+ const auto assembly = Preamble() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %1 = OpCompositeConstruct %v2uint %uint_10 %uint_20
+ %2 = OpCompositeConstruct %v2int %int_30 %int_40
+ %3 = OpCompositeConstruct %v2float %float_50 %float_60
+ OpReturn
+ OpFunctionEnd
+ )";
+ auto* p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
+ FunctionEmitter fe(p, *spirv_function(100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(VariableDeclStatement{
+ Variable{
+ x_1
+ none
+ __vec_2__u32
+ {
+ TypeConstructor{
+ __vec_2__u32
+ ScalarConstructor{10}
+ ScalarConstructor{20}
+ }
+ }
+ }
+}
+VariableDeclStatement{
+ Variable{
+ x_2
+ none
+ __vec_2__i32
+ {
+ TypeConstructor{
+ __vec_2__i32
+ ScalarConstructor{30}
+ ScalarConstructor{40}
+ }
+ }
+ }
+}
+VariableDeclStatement{
+ Variable{
+ x_3
+ none
+ __vec_2__f32
+ {
+ TypeConstructor{
+ __vec_2__f32
+ ScalarConstructor{50.000000}
+ ScalarConstructor{60.000000}
+ }
+ }
+ }
+})")) << ToString(fe.ast_body());
+}
+
+TEST_F(SpvParserTest_Composite_Construct, Matrix) {
+ const auto assembly = Preamble() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %1 = OpCompositeConstruct %m3v2float %v2float_50_60 %v2float_60_50 %v2float_70_70
+ OpReturn
+ OpFunctionEnd
+ )";
+ auto* p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
+ FunctionEmitter fe(p, *spirv_function(100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
+ Variable{
+ x_1
+ none
+ __mat_2_3__f32
+ {
+ TypeConstructor{
+ __mat_2_3__f32
+ TypeConstructor{
+ __vec_2__f32
+ ScalarConstructor{50.000000}
+ ScalarConstructor{60.000000}
+ }
+ TypeConstructor{
+ __vec_2__f32
+ ScalarConstructor{60.000000}
+ ScalarConstructor{50.000000}
+ }
+ TypeConstructor{
+ __vec_2__f32
+ ScalarConstructor{70.000000}
+ ScalarConstructor{70.000000}
+ }
+ }
+ }
+ })"))
+ << ToString(fe.ast_body());
+}
+
+TEST_F(SpvParserTest_Composite_Construct, Array) {
+ const auto assembly = Preamble() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %1 = OpCompositeConstruct %a_u_5 %uint_10 %uint_20 %uint_3 %uint_4 %uint_5
+ OpReturn
+ OpFunctionEnd
+ )";
+ auto* p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
+ FunctionEmitter fe(p, *spirv_function(100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
+ Variable{
+ x_1
+ none
+ __array__u32_5
+ {
+ TypeConstructor{
+ __array__u32_5
+ ScalarConstructor{10}
+ ScalarConstructor{20}
+ ScalarConstructor{3}
+ ScalarConstructor{4}
+ ScalarConstructor{5}
+ }
+ }
+ })"))
+ << ToString(fe.ast_body());
+}
+
+TEST_F(SpvParserTest_Composite_Construct, Struct) {
+ const auto assembly = Preamble() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %1 = OpCompositeConstruct %s_v2f_u_i %v2float_50_60 %uint_5 %int_30
+ OpReturn
+ OpFunctionEnd
+ )";
+ auto* p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
+ FunctionEmitter fe(p, *spirv_function(100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
+ Variable{
+ x_1
+ none
+ __struct_S
+ {
+ TypeConstructor{
+ __struct_S
+ TypeConstructor{
+ __vec_2__f32
+ ScalarConstructor{50.000000}
+ ScalarConstructor{60.000000}
+ }
+ ScalarConstructor{5}
+ ScalarConstructor{30}
+ }
+ }
+ })"))
+ << ToString(fe.ast_body());
+}
+
+} // namespace
+} // namespace spirv
+} // namespace reader
+} // namespace tint