[spirv-reader] Convert storage class

Bug: tint:3
Change-Id: Ifb543228a6b32f9afb6c61718a168a0bca4aed14
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/18402
Reviewed-by: dan sinclair <dsinclair@google.com>
diff --git a/src/reader/spirv/enum_converter.cc b/src/reader/spirv/enum_converter.cc
index ebbde75..40606cf 100644
--- a/src/reader/spirv/enum_converter.cc
+++ b/src/reader/spirv/enum_converter.cc
@@ -38,6 +38,36 @@
   return ast::PipelineStage::kNone;
 }
 
+ast::StorageClass EnumConverter::ToStorageClass(SpvStorageClass sc) {
+  switch (sc) {
+    case SpvStorageClassInput:
+      return ast::StorageClass::kInput;
+    case SpvStorageClassOutput:
+      return ast::StorageClass::kOutput;
+    case SpvStorageClassUniform:
+      return ast::StorageClass::kUniform;
+    case SpvStorageClassWorkgroup:
+      return ast::StorageClass::kWorkgroup;
+    case SpvStorageClassUniformConstant:
+      return ast::StorageClass::kUniformConstant;
+    case SpvStorageClassStorageBuffer:
+      return ast::StorageClass::kStorageBuffer;
+    case SpvStorageClassImage:
+      return ast::StorageClass::kImage;
+    case SpvStorageClassPushConstant:
+      return ast::StorageClass::kPushConstant;
+    case SpvStorageClassPrivate:
+      return ast::StorageClass::kPrivate;
+    case SpvStorageClassFunction:
+      return ast::StorageClass::kFunction;
+    default:
+      break;
+  }
+
+  Fail() << "unknown SPIR-V storage class: " << uint32_t(sc);
+  return ast::StorageClass::kNone;
+}
+
 }  // namespace spirv
 }  // namespace reader
 }  // namespace tint
diff --git a/src/reader/spirv/enum_converter.h b/src/reader/spirv/enum_converter.h
index 7014e03..c910307 100644
--- a/src/reader/spirv/enum_converter.h
+++ b/src/reader/spirv/enum_converter.h
@@ -17,6 +17,7 @@
 
 #include "spirv/unified1/spirv.h"
 #include "src/ast/pipeline_stage.h"
+#include "src/ast/storage_class.h"
 #include "src/reader/spirv/fail_stream.h"
 
 namespace tint {
@@ -38,6 +39,12 @@
   /// @returns a Tint AST pipeline stage
   ast::PipelineStage ToPipelineStage(SpvExecutionModel model);
 
+  /// Converts a SPIR-V storage class to a Tint storage class.
+  /// On failure, logs an error and returns kNone
+  /// @param sc the SPIR-V storage class
+  /// @returns a Tint AST pipeline stage
+  ast::StorageClass ToStorageClass(SpvStorageClass sc);
+
  private:
   /// Registers a failure and returns a stream for log diagnostics.
   /// @returns a failure stream
diff --git a/src/reader/spirv/enum_converter_test.cc b/src/reader/spirv/enum_converter_test.cc
index b4450d6..ee3aaa3 100644
--- a/src/reader/spirv/enum_converter_test.cc
+++ b/src/reader/spirv/enum_converter_test.cc
@@ -26,6 +26,8 @@
 namespace spirv {
 namespace {
 
+// Pipeline stage
+
 struct PipelineStageCase {
   SpvExecutionModel model;
   bool expect_success;
@@ -87,6 +89,80 @@
                     PipelineStageCase{SpvExecutionModelTessellationControl,
                                       false, ast::PipelineStage::kNone}));
 
+// Storage class
+
+struct StorageClassCase {
+  SpvStorageClass sc;
+  bool expect_success;
+  ast::StorageClass expected;
+};
+inline std::ostream& operator<<(std::ostream& out, StorageClassCase scc) {
+  out << "StorageClassCase{ SpvStorageClass:" << int(scc.sc)
+      << " expect_success?:" << int(scc.expect_success)
+      << " expected:" << int(scc.expected) << "}";
+  return out;
+}
+
+class SpvStorageClassTest : public testing::TestWithParam<StorageClassCase> {
+ public:
+  SpvStorageClassTest()
+      : success_(true),
+        fail_stream_(&success_, &errors_),
+        converter_(fail_stream_) {}
+
+  std::string error() const { return errors_.str(); }
+
+ protected:
+  bool success_ = true;
+  std::stringstream errors_;
+  FailStream fail_stream_;
+  EnumConverter converter_;
+};
+
+TEST_P(SpvStorageClassTest, Samples) {
+  const auto params = GetParam();
+
+  const auto result = converter_.ToStorageClass(params.sc);
+  EXPECT_EQ(success_, params.expect_success);
+  if (params.expect_success) {
+    EXPECT_EQ(result, params.expected);
+    EXPECT_TRUE(error().empty());
+  } else {
+    EXPECT_EQ(result, params.expected);
+    EXPECT_THAT(error(),
+                ::testing::StartsWith("unknown SPIR-V storage class: "));
+  }
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    EnumConverterGood,
+    SpvStorageClassTest,
+    testing::Values(
+        StorageClassCase{SpvStorageClassInput, true, ast::StorageClass::kInput},
+        StorageClassCase{SpvStorageClassOutput, true,
+                         ast::StorageClass::kOutput},
+        StorageClassCase{SpvStorageClassUniform, true,
+                         ast::StorageClass::kUniform},
+        StorageClassCase{SpvStorageClassWorkgroup, true,
+                         ast::StorageClass::kWorkgroup},
+        StorageClassCase{SpvStorageClassUniformConstant, true,
+                         ast::StorageClass::kUniformConstant},
+        StorageClassCase{SpvStorageClassStorageBuffer, true,
+                         ast::StorageClass::kStorageBuffer},
+        StorageClassCase{SpvStorageClassImage, true, ast::StorageClass::kImage},
+        StorageClassCase{SpvStorageClassPushConstant, true,
+                         ast::StorageClass::kPushConstant},
+        StorageClassCase{SpvStorageClassPrivate, true,
+                         ast::StorageClass::kPrivate},
+        StorageClassCase{SpvStorageClassFunction, true,
+                         ast::StorageClass::kFunction}));
+
+INSTANTIATE_TEST_SUITE_P(EnumConverterBad,
+                         SpvStorageClassTest,
+                         testing::Values(StorageClassCase{
+                             SpvStorageClass(9999), false,
+                             ast::StorageClass::kNone}));
+
 }  // namespace
 }  // namespace spirv
 }  // namespace reader