[spirv-reader] Convert pointer type
Bug: tint:3
Change-Id: Ibba1472a1aa3f1399e9596ee6662a29121d88eca
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/18420
Reviewed-by: dan sinclair <dsinclair@google.com>
diff --git a/src/reader/spirv/parser_impl.cc b/src/reader/spirv/parser_impl.cc
index 2480a34..efa2d3e 100644
--- a/src/reader/spirv/parser_impl.cc
+++ b/src/reader/spirv/parser_impl.cc
@@ -38,6 +38,7 @@
#include "src/ast/type/f32_type.h"
#include "src/ast/type/i32_type.h"
#include "src/ast/type/matrix_type.h"
+#include "src/ast/type/pointer_type.h"
#include "src/ast/type/struct_type.h"
#include "src/ast/type/type.h"
#include "src/ast/type/u32_type.h"
@@ -164,10 +165,10 @@
return save(ConvertType(spirv_type->AsArray()));
case spvtools::opt::analysis::Type::kStruct:
return save(ConvertType(spirv_type->AsStruct()));
- case spvtools::opt::analysis::Type::kFunction:
case spvtools::opt::analysis::Type::kPointer:
- // For now, just return null without erroring out.
- // TODO(dneto)
+ return save(ConvertType(spirv_type->AsPointer()));
+ case spvtools::opt::analysis::Type::kFunction:
+ // TODO(dneto). For now return null without erroring out.
return nullptr;
default:
break;
@@ -520,6 +521,27 @@
return ctx_.type_mgr().Get(std::move(ast_struct_type));
}
+ast::type::Type* ParserImpl::ConvertType(
+ const spvtools::opt::analysis::Pointer* ptr_ty) {
+ auto* ast_elem_ty = ConvertType(type_mgr_->GetId(ptr_ty->pointee_type()));
+ if (ast_elem_ty == nullptr) {
+ Fail() << "SPIR-V pointer type with ID " << type_mgr_->GetId(ptr_ty)
+ << " has invalid pointee type "
+ << type_mgr_->GetId(ptr_ty->pointee_type());
+ return nullptr;
+ }
+ auto ast_storage_class =
+ enum_converter_.ToStorageClass(ptr_ty->storage_class());
+ if (ast_storage_class == ast::StorageClass::kNone) {
+ Fail() << "SPIR-V pointer type with ID " << type_mgr_->GetId(ptr_ty)
+ << " has invalid storage class "
+ << static_cast<uint32_t>(ptr_ty->storage_class());
+ return nullptr;
+ }
+ return ctx_.type_mgr().Get(
+ std::make_unique<ast::type::PointerType>(ast_elem_ty, ast_storage_class));
+}
+
bool ParserImpl::RegisterTypes() {
if (!success_) {
return false;
diff --git a/src/reader/spirv/parser_impl.h b/src/reader/spirv/parser_impl.h
index a38ddaf..4ddcf19 100644
--- a/src/reader/spirv/parser_impl.h
+++ b/src/reader/spirv/parser_impl.h
@@ -190,6 +190,8 @@
/// Converts a specific SPIR-V type to a Tint type. Struct case
ast::type::Type* ConvertType(
const spvtools::opt::analysis::Struct* struct_ty);
+ /// Converts a specific SPIR-V type to a Tint type. Pointer case
+ ast::type::Type* ConvertType(const spvtools::opt::analysis::Pointer* ptr_ty);
// The SPIR-V binary we're parsing
std::vector<uint32_t> spv_binary_;
diff --git a/src/reader/spirv/parser_impl_convert_type_test.cc b/src/reader/spirv/parser_impl_convert_type_test.cc
index f5daed0..aa0fe09 100644
--- a/src/reader/spirv/parser_impl_convert_type_test.cc
+++ b/src/reader/spirv/parser_impl_convert_type_test.cc
@@ -20,7 +20,9 @@
#include "src/ast/struct.h"
#include "src/ast/type/array_type.h"
#include "src/ast/type/matrix_type.h"
+#include "src/ast/type/pointer_type.h"
#include "src/ast/type/struct_type.h"
+#include "src/ast/type/type.h"
#include "src/ast/type/vector_type.h"
#include "src/reader/spirv/parser_impl.h"
#include "src/reader/spirv/parser_impl_test_helper.h"
@@ -484,11 +486,222 @@
)"));
}
-// TODO(dneto): Demonstrate other member deocrations. Blocked on
+// TODO(dneto): Demonstrate other member decorations. Blocked on
// crbug.com/tint/30
// TODO(dneto): Demonstrate multiple member deocrations. Blocked on
// crbug.com/tint/30
+TEST_F(SpvParserTest, ConvertType_InvalidPointeetype) {
+ // Disallow pointer-to-function
+ auto p = parser(test::Assemble(R"(
+ %void = OpTypeVoid
+ %42 = OpTypeFunction %void
+ %3 = OpTypePointer Input %42
+ )"));
+ EXPECT_TRUE(p->BuildInternalModule()) << p->error();
+
+ auto* type = p->ConvertType(3);
+ EXPECT_EQ(type, nullptr);
+ EXPECT_THAT(p->error(),
+ Eq("SPIR-V pointer type with ID 3 has invalid pointee type 42"));
+}
+
+TEST_F(SpvParserTest, DISABLED_ConvertType_InvalidStorageClass) {
+ // Disallow invalid storage class
+ auto p = parser(test::Assemble(R"(
+ %1 = OpTypeFloat 32
+ %3 = OpTypePointer !999 %1 ; Special syntax to inject 999 as the storage class
+ )"));
+ // TODO(dneto): I can't get it past module building.
+ EXPECT_FALSE(p->BuildInternalModule()) << p->error();
+}
+
+TEST_F(SpvParserTest, ConvertType_PointerInput) {
+ auto p = parser(test::Assemble(R"(
+ %float = OpTypeFloat 32
+ %3 = OpTypePointer Input %float
+ )"));
+ EXPECT_TRUE(p->BuildInternalModule());
+
+ auto* type = p->ConvertType(3);
+ EXPECT_TRUE(type->IsPointer());
+ auto* ptr_ty = type->AsPointer();
+ EXPECT_NE(ptr_ty, nullptr);
+ EXPECT_TRUE(ptr_ty->type()->IsF32());
+ EXPECT_EQ(ptr_ty->storage_class(), ast::StorageClass::kInput);
+ EXPECT_TRUE(p->error().empty());
+}
+
+TEST_F(SpvParserTest, ConvertType_PointerOutput) {
+ auto p = parser(test::Assemble(R"(
+ %float = OpTypeFloat 32
+ %3 = OpTypePointer Output %float
+ )"));
+ EXPECT_TRUE(p->BuildInternalModule());
+
+ auto* type = p->ConvertType(3);
+ EXPECT_TRUE(type->IsPointer());
+ auto* ptr_ty = type->AsPointer();
+ EXPECT_NE(ptr_ty, nullptr);
+ EXPECT_TRUE(ptr_ty->type()->IsF32());
+ EXPECT_EQ(ptr_ty->storage_class(), ast::StorageClass::kOutput);
+ EXPECT_TRUE(p->error().empty());
+}
+
+TEST_F(SpvParserTest, ConvertType_PointerUniform) {
+ auto p = parser(test::Assemble(R"(
+ %float = OpTypeFloat 32
+ %3 = OpTypePointer Uniform %float
+ )"));
+ EXPECT_TRUE(p->BuildInternalModule());
+
+ auto* type = p->ConvertType(3);
+ EXPECT_TRUE(type->IsPointer());
+ auto* ptr_ty = type->AsPointer();
+ EXPECT_NE(ptr_ty, nullptr);
+ EXPECT_TRUE(ptr_ty->type()->IsF32());
+ EXPECT_EQ(ptr_ty->storage_class(), ast::StorageClass::kUniform);
+ EXPECT_TRUE(p->error().empty());
+}
+
+TEST_F(SpvParserTest, ConvertType_PointerWorkgroup) {
+ auto p = parser(test::Assemble(R"(
+ %float = OpTypeFloat 32
+ %3 = OpTypePointer Workgroup %float
+ )"));
+ EXPECT_TRUE(p->BuildInternalModule());
+
+ auto* type = p->ConvertType(3);
+ EXPECT_TRUE(type->IsPointer());
+ auto* ptr_ty = type->AsPointer();
+ EXPECT_NE(ptr_ty, nullptr);
+ EXPECT_TRUE(ptr_ty->type()->IsF32());
+ EXPECT_EQ(ptr_ty->storage_class(), ast::StorageClass::kWorkgroup);
+ EXPECT_TRUE(p->error().empty());
+}
+
+TEST_F(SpvParserTest, ConvertType_PointerUniformConstant) {
+ auto p = parser(test::Assemble(R"(
+ %float = OpTypeFloat 32
+ %3 = OpTypePointer UniformConstant %float
+ )"));
+ EXPECT_TRUE(p->BuildInternalModule());
+
+ auto* type = p->ConvertType(3);
+ EXPECT_TRUE(type->IsPointer());
+ auto* ptr_ty = type->AsPointer();
+ EXPECT_NE(ptr_ty, nullptr);
+ EXPECT_TRUE(ptr_ty->type()->IsF32());
+ EXPECT_EQ(ptr_ty->storage_class(), ast::StorageClass::kUniformConstant);
+ EXPECT_TRUE(p->error().empty());
+}
+
+TEST_F(SpvParserTest, ConvertType_PointerStorageBuffer) {
+ auto p = parser(test::Assemble(R"(
+ %float = OpTypeFloat 32
+ %3 = OpTypePointer StorageBuffer %float
+ )"));
+ EXPECT_TRUE(p->BuildInternalModule());
+
+ auto* type = p->ConvertType(3);
+ EXPECT_TRUE(type->IsPointer());
+ auto* ptr_ty = type->AsPointer();
+ EXPECT_NE(ptr_ty, nullptr);
+ EXPECT_TRUE(ptr_ty->type()->IsF32());
+ EXPECT_EQ(ptr_ty->storage_class(), ast::StorageClass::kStorageBuffer);
+ EXPECT_TRUE(p->error().empty());
+}
+
+TEST_F(SpvParserTest, ConvertType_PointerImage) {
+ auto p = parser(test::Assemble(R"(
+ %float = OpTypeFloat 32
+ %3 = OpTypePointer Image %float
+ )"));
+ EXPECT_TRUE(p->BuildInternalModule());
+
+ auto* type = p->ConvertType(3);
+ EXPECT_TRUE(type->IsPointer());
+ auto* ptr_ty = type->AsPointer();
+ EXPECT_NE(ptr_ty, nullptr);
+ EXPECT_TRUE(ptr_ty->type()->IsF32());
+ EXPECT_EQ(ptr_ty->storage_class(), ast::StorageClass::kImage);
+ EXPECT_TRUE(p->error().empty());
+}
+
+TEST_F(SpvParserTest, ConvertType_PointerPushConstant) {
+ auto p = parser(test::Assemble(R"(
+ %float = OpTypeFloat 32
+ %3 = OpTypePointer PushConstant %float
+ )"));
+ EXPECT_TRUE(p->BuildInternalModule());
+
+ auto* type = p->ConvertType(3);
+ EXPECT_TRUE(type->IsPointer());
+ auto* ptr_ty = type->AsPointer();
+ EXPECT_NE(ptr_ty, nullptr);
+ EXPECT_TRUE(ptr_ty->type()->IsF32());
+ EXPECT_EQ(ptr_ty->storage_class(), ast::StorageClass::kPushConstant);
+ EXPECT_TRUE(p->error().empty());
+}
+
+TEST_F(SpvParserTest, ConvertType_PointerPrivate) {
+ auto p = parser(test::Assemble(R"(
+ %float = OpTypeFloat 32
+ %3 = OpTypePointer Private %float
+ )"));
+ EXPECT_TRUE(p->BuildInternalModule());
+
+ auto* type = p->ConvertType(3);
+ EXPECT_TRUE(type->IsPointer());
+ auto* ptr_ty = type->AsPointer();
+ EXPECT_NE(ptr_ty, nullptr);
+ EXPECT_TRUE(ptr_ty->type()->IsF32());
+ EXPECT_EQ(ptr_ty->storage_class(), ast::StorageClass::kPrivate);
+ EXPECT_TRUE(p->error().empty());
+}
+
+TEST_F(SpvParserTest, ConvertType_PointerFunction) {
+ auto p = parser(test::Assemble(R"(
+ %float = OpTypeFloat 32
+ %3 = OpTypePointer Function %float
+ )"));
+ EXPECT_TRUE(p->BuildInternalModule());
+
+ auto* type = p->ConvertType(3);
+ EXPECT_TRUE(type->IsPointer());
+ auto* ptr_ty = type->AsPointer();
+ EXPECT_NE(ptr_ty, nullptr);
+ EXPECT_TRUE(ptr_ty->type()->IsF32());
+ EXPECT_EQ(ptr_ty->storage_class(), ast::StorageClass::kFunction);
+ EXPECT_TRUE(p->error().empty());
+}
+
+TEST_F(SpvParserTest, ConvertType_PointerToPointer) {
+ // FYI: The reader suports pointer-to-pointer even while WebGPU does not.
+ auto p = parser(test::Assemble(R"(
+ %float = OpTypeFloat 32
+ %42 = OpTypePointer Output %float
+ %3 = OpTypePointer Input %42
+ )"));
+ EXPECT_TRUE(p->BuildInternalModule());
+
+ auto* type = p->ConvertType(3);
+ EXPECT_NE(type, nullptr);
+ EXPECT_TRUE(type->IsPointer());
+
+ auto* ptr_ty = type->AsPointer();
+ EXPECT_NE(ptr_ty, nullptr);
+ EXPECT_EQ(ptr_ty->storage_class(), ast::StorageClass::kInput);
+ EXPECT_TRUE(ptr_ty->type()->IsPointer());
+
+ auto* ptr_ptr_ty = ptr_ty->type()->AsPointer();
+ EXPECT_NE(ptr_ptr_ty, nullptr);
+ EXPECT_EQ(ptr_ptr_ty->storage_class(), ast::StorageClass::kOutput);
+ EXPECT_TRUE(ptr_ptr_ty->type()->IsF32());
+
+ EXPECT_TRUE(p->error().empty());
+}
+
} // namespace
} // namespace spirv
} // namespace reader