[spirv-reader] Handle OpLoad
Bug: tint:3
Change-Id: I25fdf086e49426240a771b70306b417cd8012777
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/19140
Reviewed-by: dan sinclair <dsinclair@google.com>
diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc
index b92c64f..e807415 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -23,6 +23,7 @@
#include "src/ast/assignment_statement.h"
#include "src/ast/identifier_expression.h"
#include "src/ast/scalar_constructor_expression.h"
+#include "src/ast/storage_class.h"
#include "src/ast/uint_literal.h"
#include "src/ast/variable.h"
#include "src/ast/variable_decl_statement.h"
@@ -166,6 +167,8 @@
auto var_decl_stmt =
std::make_unique<ast::VariableDeclStatement>(std::move(var));
ast_body_.emplace_back(std::move(var_decl_stmt));
+ // Save this as an already-named value.
+ identifier_values_.insert(inst.result_id());
}
return success();
}
@@ -174,6 +177,9 @@
if (failed()) {
return nullptr;
}
+ if (identifier_values_.count(id)) {
+ return std::make_unique<ast::IdentifierExpression>(namer_.Name(id));
+ }
const auto* spirv_constant = constant_mgr_->FindDeclaredConstant(id);
if (spirv_constant) {
return parser_impl_.MakeConstantExpression(id);
@@ -184,13 +190,10 @@
return nullptr;
}
switch (inst->opcode()) {
- case SpvOpVariable:
- // This is not a declaration, but a use of an identifier.
- return std::make_unique<ast::IdentifierExpression>(namer_.Name(id));
default:
break;
}
- Fail() << "unhandled expression for ID " << id;
+ Fail() << "unhandled expression for ID " << id << "\n" << inst->PrettyPrint();
return nullptr;
}
@@ -229,6 +232,27 @@
std::move(lhs), std::move(rhs)));
return success();
}
+ case SpvOpLoad: {
+ // Memory accesses must be issued in SPIR-V program order.
+ // So represent a load by a new const definition.
+ auto ast_initializer = MakeExpression(inst.GetSingleWordInOperand(0));
+ if (!ast_initializer) {
+ return false;
+ }
+ auto ast_const =
+ parser_impl_.MakeVariable(inst.result_id(), ast::StorageClass::kNone,
+ parser_impl_.ConvertType(inst.type_id()));
+ if (!ast_const) {
+ return false;
+ }
+ ast_const->set_constructor(std::move(ast_initializer));
+ ast_const->set_is_const(true);
+ ast_body_.emplace_back(
+ std::make_unique<ast::VariableDeclStatement>(std::move(ast_const)));
+ // Save this as an already-named value.
+ identifier_values_.insert(inst.result_id());
+ return success();
+ }
case SpvOpFunctionCall:
// TODO(dneto): Fill this out. Make this pass, for existing tests
return success();
diff --git a/src/reader/spirv/function.h b/src/reader/spirv/function.h
index dd4c85a..86f518d 100644
--- a/src/reader/spirv/function.h
+++ b/src/reader/spirv/function.h
@@ -111,6 +111,8 @@
Namer& namer_;
const spvtools::opt::Function& function_;
ast::StatementList ast_body_;
+ // The set of IDs that have already had an identifier name generated for it.
+ std::unordered_set<uint32_t> identifier_values_;
};
} // namespace spirv
diff --git a/src/reader/spirv/function_memory_test.cc b/src/reader/spirv/function_memory_test.cc
index 6f43419..1067fa2 100644
--- a/src/reader/spirv/function_memory_test.cc
+++ b/src/reader/spirv/function_memory_test.cc
@@ -29,7 +29,7 @@
using ::testing::HasSubstr;
-TEST_F(SpvParserTest, EmitFunctionVariables_StoreBoolConst) {
+TEST_F(SpvParserTest, EmitStatement_StoreBoolConst) {
auto p = parser(test::Assemble(R"(
%void = OpTypeVoid
%voidfn = OpTypeFunction %void
@@ -64,7 +64,7 @@
})"));
}
-TEST_F(SpvParserTest, EmitFunctionVariables_StoreUintConst) {
+TEST_F(SpvParserTest, EmitStatement_StoreUintConst) {
auto p = parser(test::Assemble(R"(
%void = OpTypeVoid
%voidfn = OpTypeFunction %void
@@ -92,7 +92,7 @@
})"));
}
-TEST_F(SpvParserTest, EmitFunctionVariables_StoreIntConst) {
+TEST_F(SpvParserTest, EmitStatement_StoreIntConst) {
auto p = parser(test::Assemble(R"(
%void = OpTypeVoid
%voidfn = OpTypeFunction %void
@@ -120,7 +120,7 @@
})"));
}
-TEST_F(SpvParserTest, EmitFunctionVariables_StoreFloatConst) {
+TEST_F(SpvParserTest, EmitStatement_StoreFloatConst) {
auto p = parser(test::Assemble(R"(
%void = OpTypeVoid
%voidfn = OpTypeFunction %void
@@ -148,6 +148,116 @@
})"));
}
+TEST_F(SpvParserTest, EmitStatement_LoadBool) {
+ auto p = parser(test::Assemble(R"(
+ %void = OpTypeVoid
+ %voidfn = OpTypeFunction %void
+ %ty = OpTypeBool
+ %true = OpConstantTrue %ty
+ %false = OpConstantFalse %ty
+ %null = OpConstantNull %ty
+ %ptr_ty = OpTypePointer Function %ty
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %1 = OpVariable %ptr_ty Function %true
+ %2 = OpLoad %ty %1
+ OpReturn
+ OpFunctionEnd
+ )"));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
+ FunctionEmitter fe(p, *spirv_function(100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
+ Variable{
+ x_2
+ none
+ __bool
+ {
+ Identifier{x_1}
+ }
+ })"));
+}
+
+TEST_F(SpvParserTest, EmitStatement_LoadScalar) {
+ auto p = parser(test::Assemble(R"(
+ %void = OpTypeVoid
+ %voidfn = OpTypeFunction %void
+ %ty = OpTypeInt 32 0
+ %ty_42 = OpConstant %ty 42
+ %ptr_ty = OpTypePointer Function %ty
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %1 = OpVariable %ptr_ty Function %ty_42
+ %2 = OpLoad %ty %1
+ %3 = OpLoad %ty %1
+ OpReturn
+ OpFunctionEnd
+ )"));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
+ FunctionEmitter fe(p, *spirv_function(100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(VariableDeclStatement{
+ Variable{
+ x_2
+ none
+ __u32
+ {
+ Identifier{x_1}
+ }
+ }
+}
+VariableDeclStatement{
+ Variable{
+ x_3
+ none
+ __u32
+ {
+ Identifier{x_1}
+ }
+ }
+})"));
+}
+
+TEST_F(SpvParserTest, EmitStatement_UseLoadedScalarTwice) {
+ auto p = parser(test::Assemble(R"(
+ %void = OpTypeVoid
+ %voidfn = OpTypeFunction %void
+ %ty = OpTypeInt 32 0
+ %ty_42 = OpConstant %ty 42
+ %ptr_ty = OpTypePointer Function %ty
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %1 = OpVariable %ptr_ty Function %ty_42
+ %2 = OpLoad %ty %1
+ OpStore %1 %2
+ OpStore %1 %2
+ OpReturn
+ OpFunctionEnd
+ )"));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
+ FunctionEmitter fe(p, *spirv_function(100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(VariableDeclStatement{
+ Variable{
+ x_2
+ none
+ __u32
+ {
+ Identifier{x_1}
+ }
+ }
+}
+Assignment{
+ Identifier{x_1}
+ Identifier{x_2}
+}
+Assignment{
+ Identifier{x_1}
+ Identifier{x_2}
+}
+)"));
+}
+
} // namespace
} // namespace spirv
} // namespace reader