[hlsl-writer] Scaffold the HLSL backend.

This CL adds the scaffolding for the HLSL backend.

Bug: tint:7
Change-Id: Iaf9f5159bc409f3ac71fcec281229258bdfa021b
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/25000
Reviewed-by: David Neto <dneto@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index 9bd4307..67d7557 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -62,6 +62,12 @@
     defines += [ "TINT_BUILD_MSL_WRITER=0" ]
   }
 
+  if (tint_build_hlsl_writer) {
+    defines += [ "TINT_BUILD_HLSL_WRITER=1" ]
+  } else {
+    defines += [ "TINT_BUILD_HLSL_WRITER=0" ]
+  }
+
   include_dirs = [
     "${tint_root_dir}/",
     "${tint_root_dir}/include/",
@@ -513,6 +519,23 @@
   public_deps = [ ":libtint_core_src" ]
 }
 
+source_set("libtint_hlsl_writer_src") {
+  sources = [
+    "src/writer/hlsl/generator.cc",
+    "src/writer/hlsl/generator.h",
+    "src/writer/hlsl/generator_impl.cc",
+    "src/writer/hlsl/generator_impl.h",
+  ]
+
+  configs += [ ":tint_common_config" ]
+  public_configs = [ ":tint_public_config" ]
+
+  if (build_with_chromium) {
+    configs -= [ "//build/config/compiler:chromium_code" ]
+    configs += [ "//build/config/compiler:no_chromium_code" ]
+  }
+}
+
 source_set("libtint") {
   deps = [ ":libtint_core_src" ]
 
@@ -536,6 +559,10 @@
     deps += [ ":libtint_msl_writer_src" ]
   }
 
+  if (tint_build_hlsl_writer) {
+    deps += [ ":libtint_hlsl_writer_src" ]
+  }
+
   configs += [ ":tint_common_config" ]
   public_configs = [ ":tint_public_config" ]
 
@@ -982,6 +1009,21 @@
   ]
 }
 
+source_set("tint_unittests_hlsl_writer_src") {
+  sources = [ "src/writer/hlsl/generator_impl_test.cc" ]
+
+  configs += [
+    ":tint_common_config",
+    ":tint_unittests_config",
+  ]
+  public_configs = [ ":tint_public_config" ]
+
+  if (build_with_chromium) {
+    configs -= [ "//build/config/compiler:chromium_code" ]
+    configs += [ "//build/config/compiler:no_chromium_code" ]
+  }
+}
+
 source_set("tint_unittests_src") {
   testonly = true
 
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4586ee4..a3cb4f8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -29,6 +29,7 @@
 option(TINT_BUILD_DOCS "Build documentation" ON)
 option(TINT_BUILD_SPV_READER "Build the SPIR-V input reader" ON)
 option(TINT_BUILD_WGSL_READER "Builde the WGSL input reader" ON)
+option(TINT_BUILD_HLSL_WRITER "Build the HLSL output writer" ON)
 option(TINT_BUILD_MSL_WRITER "Build the MSL output writer" ON)
 option(TINT_BUILD_SPV_WRITER "Build the SPIR-V output writer" ON)
 option(TINT_BUILD_WGSL_WRITER "Build the WGSL output writer" ON)
@@ -51,6 +52,7 @@
 message(STATUS "Tint build docs: ${TINT_BUILD_DOCS}")
 message(STATUS "Tint build SPIR-V reader: ${TINT_BUILD_SPV_READER}")
 message(STATUS "Tint build WGSL reader: ${TINT_BUILD_WGSL_READER}")
+message(STATUS "Tint build HLSL writer: ${TINT_BUILD_HLSL_WRITER}")
 message(STATUS "Tint build MSL writer: ${TINT_BUILD_MSL_WRITER}")
 message(STATUS "Tint build SPIR-V writer: ${TINT_BUILD_SPV_WRITER}")
 message(STATUS "Tint build WGSL writer: ${TINT_BUILD_WGSL_WRITER}")
@@ -121,6 +123,8 @@
   target_compile_definitions(${TARGET} PRIVATE
       -DTINT_BUILD_WGSL_READER=$<BOOL:${TINT_BUILD_WGSL_READER}>)
   target_compile_definitions(${TARGET} PRIVATE
+      -DTINT_BUILD_HLSL_WRITER=$<BOOL:${TINT_BUILD_HLSL_WRITER}>)
+  target_compile_definitions(${TARGET} PRIVATE
     -DTINT_BUILD_MSL_WRITER=$<BOOL:${TINT_BUILD_MSL_WRITER}>)
   target_compile_definitions(${TARGET} PRIVATE
       -DTINT_BUILD_SPV_WRITER=$<BOOL:${TINT_BUILD_SPV_WRITER}>)
diff --git a/include/tint/tint.h b/include/tint/tint.h
index 6ff5947..8873612 100644
--- a/include/tint/tint.h
+++ b/include/tint/tint.h
@@ -46,4 +46,8 @@
 #include "src/writer/msl/generator.h"
 #endif  // TINT_BUILD_MSL_WRITER
 
+#if TINT_BUILD_HLSL_WRITER
+#include "src/writer/hlsl/generator.h"
+#endif  // TINT_BUILD_HLSL_WRITER
+
 #endif  // INCLUDE_TINT_TINT_H_
diff --git a/samples/main.cc b/samples/main.cc
index 674f3c4..d472b8e 100644
--- a/samples/main.cc
+++ b/samples/main.cc
@@ -33,6 +33,7 @@
   kSpvAsm,
   kWgsl,
   kMsl,
+  kHlsl,
 };
 
 struct Options {
@@ -50,13 +51,14 @@
 const char kUsage[] = R"(Usage: tint [options] <input-file>
 
  options:
-  --format <spirv|spvasm|wgsl|msl>  -- Output format.
+  --format <spirv|spvasm|wgsl|msl|hlsl>  -- Output format.
                                If not provided, will be inferred from output
                                filename extension:
                                    .spvasm -> spvasm
-                                   .spv -> spirv
-                                   .wgsl -> wgsl
-                                   .metal -> msl
+                                   .spv    -> spirv
+                                   .wgsl   -> wgsl
+                                   .metal  -> msl
+                                   .hlsl   -> hlsl
                                If none matches, then default to SPIR-V assembly.
   --output-file <name>      -- Output file name.  Use "-" for standard output
   -o <name>                 -- Output file name.  Use "-" for standard output
@@ -86,6 +88,11 @@
     return Format::kMsl;
 #endif  // TINT_BUILD_MSL_WRITER
 
+#if TINT_BUILD_HLSL_WRITER
+  if (fmt == "hlsl")
+    return Format::kHlsl;
+#endif  // TINT_BUILD_HLSL_WRITER
+
   return Format::kNone;
 }
 
@@ -453,7 +460,13 @@
   if (options.format == Format::kMsl) {
     writer = std::make_unique<tint::writer::msl::Generator>(std::move(mod));
   }
-#endif  // TINT_BUILDER_MSL_WRITER
+#endif  // TINT_BUILD_MSL_WRITER
+
+#if TINT_BUILD_HLSL_WRITER
+  if (options.format == Format::kHlsl) {
+    writer = std::make_unique<tint::writer::hlsl::Generator>(std::move(mod));
+  }
+#endif  // TINT_BUILD_HLSL_WRITER
 
   if (!writer) {
     std::cerr << "Unknown output format specified" << std::endl;
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index fe9486d..23f3988 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -260,6 +260,15 @@
   )
 endif()
 
+if(${TINT_BUILD_HLSL_WRITER})
+  list(APPEND TINT_LIB_SRCS
+    writer/hlsl/generator.cc
+    writer/hlsl/generator.h
+    writer/hlsl/generator_impl.cc
+    writer/hlsl/generator_impl.h
+  )
+endif()
+
 set(TINT_TEST_SRCS
   ast/array_accessor_expression_test.cc
   ast/as_expression_test.cc
@@ -524,6 +533,12 @@
   )
 endif()
 
+if (${TINT_BUILD_HLSL_WRITER})
+  list(APPEND TINT_TEST_SRCS
+    writer/hlsl/generator_impl_test.cc
+  )
+endif()
+
 add_executable(tint_unittests ${TINT_TEST_SRCS})
 
 if(NOT MSVC)
diff --git a/src/writer/hlsl/generator.cc b/src/writer/hlsl/generator.cc
new file mode 100644
index 0000000..b0f1566
--- /dev/null
+++ b/src/writer/hlsl/generator.cc
@@ -0,0 +1,45 @@
+// 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 "src/writer/hlsl/generator.h"
+
+#include <utility>
+
+namespace tint {
+namespace writer {
+namespace hlsl {
+
+Generator::Generator(ast::Module module) : Text(std::move(module)) {}
+
+Generator::~Generator() = default;
+
+bool Generator::Generate() {
+  auto ret = impl_.Generate(module_);
+  if (!ret) {
+    error_ = impl_.error();
+  }
+  return ret;
+}
+
+std::string Generator::result() const {
+  return impl_.result();
+}
+
+std::string Generator::error() const {
+  return impl_.error();
+}
+
+}  // namespace hlsl
+}  // namespace writer
+}  // namespace tint
diff --git a/src/writer/hlsl/generator.h b/src/writer/hlsl/generator.h
new file mode 100644
index 0000000..c3cf473
--- /dev/null
+++ b/src/writer/hlsl/generator.h
@@ -0,0 +1,53 @@
+// 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.
+
+#ifndef SRC_WRITER_HLSL_GENERATOR_H_
+#define SRC_WRITER_HLSL_GENERATOR_H_
+
+#include <string>
+
+#include "src/writer/hlsl/generator_impl.h"
+#include "src/writer/text.h"
+
+namespace tint {
+namespace writer {
+namespace hlsl {
+
+/// Class to generate HLSL source
+class Generator : public Text {
+ public:
+  /// Constructor
+  /// @param module the module to convert
+  explicit Generator(ast::Module module);
+  ~Generator() override;
+
+  /// Generates the result data
+  /// @returns true on successful generation; false otherwise
+  bool Generate() override;
+
+  /// @returns the result data
+  std::string result() const override;
+
+  /// @returns the error
+  std::string error() const;
+
+ private:
+  GeneratorImpl impl_;
+};
+
+}  // namespace hlsl
+}  // namespace writer
+}  // namespace tint
+
+#endif  // SRC_WRITER_HLSL_GENERATOR_H_
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc
new file mode 100644
index 0000000..7bcabcd
--- /dev/null
+++ b/src/writer/hlsl/generator_impl.cc
@@ -0,0 +1,31 @@
+// 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 "src/writer/hlsl/generator_impl.h"
+
+namespace tint {
+namespace writer {
+namespace hlsl {
+
+GeneratorImpl::GeneratorImpl() = default;
+
+GeneratorImpl::~GeneratorImpl() = default;
+
+bool GeneratorImpl::Generate(const ast::Module&) {
+  return true;
+}
+
+}  // namespace hlsl
+}  // namespace writer
+}  // namespace tint
diff --git a/src/writer/hlsl/generator_impl.h b/src/writer/hlsl/generator_impl.h
new file mode 100644
index 0000000..2c78a01
--- /dev/null
+++ b/src/writer/hlsl/generator_impl.h
@@ -0,0 +1,42 @@
+// 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.
+
+#ifndef SRC_WRITER_HLSL_GENERATOR_IMPL_H_
+#define SRC_WRITER_HLSL_GENERATOR_IMPL_H_
+
+#include "src/ast/module.h"
+#include "src/writer/text_generator.h"
+
+namespace tint {
+namespace writer {
+namespace hlsl {
+
+/// Implementation class for HLSL generator
+class GeneratorImpl : public TextGenerator {
+ public:
+  /// Constructor
+  GeneratorImpl();
+  ~GeneratorImpl();
+
+  /// Generates the result data
+  /// @param module the module to generate
+  /// @returns true on successful generation; false otherwise
+  bool Generate(const ast::Module& module);
+};
+
+}  // namespace hlsl
+}  // namespace writer
+}  // namespace tint
+
+#endif  // SRC_WRITER_HLSL_GENERATOR_IMPL_H_
diff --git a/src/writer/hlsl/generator_impl_test.cc b/src/writer/hlsl/generator_impl_test.cc
new file mode 100644
index 0000000..0b68755
--- /dev/null
+++ b/src/writer/hlsl/generator_impl_test.cc
@@ -0,0 +1,53 @@
+// 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 "src/writer/hlsl/generator_impl.h"
+
+#include <memory>
+
+#include "gtest/gtest.h"
+#include "src/ast/entry_point.h"
+#include "src/ast/function.h"
+#include "src/ast/module.h"
+#include "src/ast/type/void_type.h"
+
+namespace tint {
+namespace writer {
+namespace hlsl {
+namespace {
+
+using HlslGeneratorImplTest = testing::Test;
+
+TEST_F(HlslGeneratorImplTest, DISABLED_Generate) {
+  ast::type::VoidType void_type;
+  ast::Module m;
+  m.AddFunction(std::make_unique<ast::Function>("my_func", ast::VariableList{},
+                                                &void_type));
+  m.AddEntryPoint(std::make_unique<ast::EntryPoint>(
+      ast::PipelineStage::kFragment, "my_func", ""));
+
+  GeneratorImpl g;
+
+  ASSERT_TRUE(g.Generate(m)) << g.error();
+  EXPECT_EQ(g.result(), R"(#import <metal_lib>
+
+void my_func() {
+}
+)");
+}
+
+}  // namespace
+}  // namespace hlsl
+}  // namespace writer
+}  // namespace tint
diff --git a/src/writer/msl/generator.h b/src/writer/msl/generator.h
index c062b3d..fcee316 100644
--- a/src/writer/msl/generator.h
+++ b/src/writer/msl/generator.h
@@ -24,7 +24,7 @@
 namespace writer {
 namespace msl {
 
-/// Class to generate WGSL source from a WGSL module
+/// Class to generate MSL source
 class Generator : public Text {
  public:
   /// Constructor
diff --git a/src/writer/msl/generator_impl.h b/src/writer/msl/generator_impl.h
index cc7d33a..3176394 100644
--- a/src/writer/msl/generator_impl.h
+++ b/src/writer/msl/generator_impl.h
@@ -32,7 +32,7 @@
 namespace writer {
 namespace msl {
 
-/// Implementation class for WGSL generator
+/// Implementation class for MSL generator
 class GeneratorImpl : public TextGenerator {
  public:
   /// Constructor
diff --git a/src/writer/wgsl/generator.h b/src/writer/wgsl/generator.h
index a9d170a..400d855 100644
--- a/src/writer/wgsl/generator.h
+++ b/src/writer/wgsl/generator.h
@@ -24,7 +24,7 @@
 namespace writer {
 namespace wgsl {
 
-/// Class to generate WGSL source from a WGSL module
+/// Class to generate WGSL source
 class Generator : public Text {
  public:
   /// Constructor