[ir][glsl] Skeleton of GLSL IR backend

Create the skeleton for the GLSL IR printer.

Bug: tint:1993
Change-Id: I33956516cb9ce6cbc939afc410005b4abaadd0b8
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/156560
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/cmd/test/BUILD.bazel b/src/tint/cmd/test/BUILD.bazel
index e29f649..c883c12 100644
--- a/src/tint/cmd/test/BUILD.bazel
+++ b/src/tint/cmd/test/BUILD.bazel
@@ -82,6 +82,7 @@
   ] + select({
     ":tint_build_glsl_writer": [
       "//src/tint/lang/glsl/writer/ast_printer:test",
+      "//src/tint/lang/glsl/writer/printer:test",
     ],
     "//conditions:default": [],
   }) + select({
diff --git a/src/tint/cmd/test/BUILD.cmake b/src/tint/cmd/test/BUILD.cmake
index 2edd15d..f994d98 100644
--- a/src/tint/cmd/test/BUILD.cmake
+++ b/src/tint/cmd/test/BUILD.cmake
@@ -88,6 +88,7 @@
 if(TINT_BUILD_GLSL_WRITER)
   tint_target_add_dependencies(tint_cmd_test_test_cmd test_cmd
     tint_lang_glsl_writer_ast_printer_test
+    tint_lang_glsl_writer_printer_test
   )
 endif(TINT_BUILD_GLSL_WRITER)
 
diff --git a/src/tint/cmd/test/BUILD.gn b/src/tint/cmd/test/BUILD.gn
index b7ee14c..774b68a 100644
--- a/src/tint/cmd/test/BUILD.gn
+++ b/src/tint/cmd/test/BUILD.gn
@@ -87,7 +87,10 @@
     ]
 
     if (tint_build_glsl_writer) {
-      deps += [ "${tint_src_dir}/lang/glsl/writer/ast_printer:unittests" ]
+      deps += [
+        "${tint_src_dir}/lang/glsl/writer/ast_printer:unittests",
+        "${tint_src_dir}/lang/glsl/writer/printer:unittests",
+      ]
     }
 
     if (tint_build_glsl_writer && tint_build_wgsl_reader &&
diff --git a/src/tint/lang/glsl/writer/BUILD.bazel b/src/tint/lang/glsl/writer/BUILD.bazel
index 969f112..d5272f1 100644
--- a/src/tint/lang/glsl/writer/BUILD.bazel
+++ b/src/tint/lang/glsl/writer/BUILD.bazel
@@ -51,11 +51,13 @@
     "//src/tint/api/options",
     "//src/tint/lang/core",
     "//src/tint/lang/core/constant",
+    "//src/tint/lang/core/ir",
     "//src/tint/lang/core/type",
+    "//src/tint/lang/glsl/writer/raise",
     "//src/tint/lang/wgsl",
     "//src/tint/lang/wgsl/ast",
-    "//src/tint/lang/wgsl/ast/transform",
     "//src/tint/lang/wgsl/program",
+    "//src/tint/lang/wgsl/reader/lower",
     "//src/tint/lang/wgsl/sem",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
@@ -75,6 +77,12 @@
     ":tint_build_glsl_writer": [
       "//src/tint/lang/glsl/writer/ast_printer",
       "//src/tint/lang/glsl/writer/common",
+      "//src/tint/lang/glsl/writer/printer",
+    ],
+    "//conditions:default": [],
+  }) + select({
+    ":tint_build_wgsl_reader": [
+      "//src/tint/lang/wgsl/reader/program_to_ir",
     ],
     "//conditions:default": [],
   }),
@@ -128,3 +136,8 @@
   actual = "//src/tint:tint_build_glsl_writer_true",
 )
 
+alias(
+  name = "tint_build_wgsl_reader",
+  actual = "//src/tint:tint_build_wgsl_reader_true",
+)
+
diff --git a/src/tint/lang/glsl/writer/BUILD.cmake b/src/tint/lang/glsl/writer/BUILD.cmake
index 91d7db2..f266bae 100644
--- a/src/tint/lang/glsl/writer/BUILD.cmake
+++ b/src/tint/lang/glsl/writer/BUILD.cmake
@@ -37,6 +37,8 @@
 include(lang/glsl/writer/ast_printer/BUILD.cmake)
 include(lang/glsl/writer/ast_raise/BUILD.cmake)
 include(lang/glsl/writer/common/BUILD.cmake)
+include(lang/glsl/writer/printer/BUILD.cmake)
+include(lang/glsl/writer/raise/BUILD.cmake)
 
 if(TINT_BUILD_GLSL_WRITER)
 ################################################################################
@@ -56,11 +58,13 @@
   tint_api_options
   tint_lang_core
   tint_lang_core_constant
+  tint_lang_core_ir
   tint_lang_core_type
+  tint_lang_glsl_writer_raise
   tint_lang_wgsl
   tint_lang_wgsl_ast
-  tint_lang_wgsl_ast_transform
   tint_lang_wgsl_program
+  tint_lang_wgsl_reader_lower
   tint_lang_wgsl_sem
   tint_utils_containers
   tint_utils_diagnostic
@@ -82,9 +86,16 @@
   tint_target_add_dependencies(tint_lang_glsl_writer lib
     tint_lang_glsl_writer_ast_printer
     tint_lang_glsl_writer_common
+    tint_lang_glsl_writer_printer
   )
 endif(TINT_BUILD_GLSL_WRITER)
 
+if(TINT_BUILD_WGSL_READER)
+  tint_target_add_dependencies(tint_lang_glsl_writer lib
+    tint_lang_wgsl_reader_program_to_ir
+  )
+endif(TINT_BUILD_WGSL_READER)
+
 endif(TINT_BUILD_GLSL_WRITER)
 if(TINT_BUILD_GLSL_WRITER)
 ################################################################################
diff --git a/src/tint/lang/glsl/writer/BUILD.gn b/src/tint/lang/glsl/writer/BUILD.gn
index 25eea5a..0ed5983 100644
--- a/src/tint/lang/glsl/writer/BUILD.gn
+++ b/src/tint/lang/glsl/writer/BUILD.gn
@@ -54,11 +54,13 @@
       "${tint_src_dir}/api/options",
       "${tint_src_dir}/lang/core",
       "${tint_src_dir}/lang/core/constant",
+      "${tint_src_dir}/lang/core/ir",
       "${tint_src_dir}/lang/core/type",
+      "${tint_src_dir}/lang/glsl/writer/raise",
       "${tint_src_dir}/lang/wgsl",
       "${tint_src_dir}/lang/wgsl/ast",
-      "${tint_src_dir}/lang/wgsl/ast/transform",
       "${tint_src_dir}/lang/wgsl/program",
+      "${tint_src_dir}/lang/wgsl/reader/lower",
       "${tint_src_dir}/lang/wgsl/sem",
       "${tint_src_dir}/utils/containers",
       "${tint_src_dir}/utils/diagnostic",
@@ -80,8 +82,13 @@
       deps += [
         "${tint_src_dir}/lang/glsl/writer/ast_printer",
         "${tint_src_dir}/lang/glsl/writer/common",
+        "${tint_src_dir}/lang/glsl/writer/printer",
       ]
     }
+
+    if (tint_build_wgsl_reader) {
+      deps += [ "${tint_src_dir}/lang/wgsl/reader/program_to_ir" ]
+    }
   }
 }
 if (tint_build_benchmarks) {
diff --git a/src/tint/lang/glsl/writer/common/options.h b/src/tint/lang/glsl/writer/common/options.h
index 8068595..e9de953 100644
--- a/src/tint/lang/glsl/writer/common/options.h
+++ b/src/tint/lang/glsl/writer/common/options.h
@@ -61,6 +61,9 @@
     /// Set to `true` to disable workgroup memory zero initialization
     bool disable_workgroup_init = false;
 
+    /// Set to `true` to generate GLSL via the Tint IR instead of from the AST.
+    bool use_tint_ir = false;
+
     /// The GLSL version to emit
     Version version;
 
diff --git a/src/tint/lang/glsl/writer/printer/BUILD.bazel b/src/tint/lang/glsl/writer/printer/BUILD.bazel
new file mode 100644
index 0000000..71fd245
--- /dev/null
+++ b/src/tint/lang/glsl/writer/printer/BUILD.bazel
@@ -0,0 +1,102 @@
+# Copyright 2023 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.
+
+################################################################################
+# File generated by 'tools/src/cmd/gen' using the template:
+#   tools/src/cmd/gen/build/BUILD.bazel.tmpl
+#
+# To regenerate run: './tools/run gen'
+#
+#                       Do not modify this file directly
+################################################################################
+
+load("//src/tint:flags.bzl", "COPTS")
+load("@bazel_skylib//lib:selects.bzl", "selects")
+cc_library(
+  name = "printer",
+  srcs = [
+    "printer.cc",
+  ],
+  hdrs = [
+    "printer.h",
+  ],
+  deps = [
+    "//src/tint/api/common",
+    "//src/tint/lang/core",
+    "//src/tint/lang/core/constant",
+    "//src/tint/lang/core/ir",
+    "//src/tint/lang/core/type",
+    "//src/tint/utils/containers",
+    "//src/tint/utils/diagnostic",
+    "//src/tint/utils/generator",
+    "//src/tint/utils/ice",
+    "//src/tint/utils/id",
+    "//src/tint/utils/macros",
+    "//src/tint/utils/math",
+    "//src/tint/utils/memory",
+    "//src/tint/utils/reflection",
+    "//src/tint/utils/result",
+    "//src/tint/utils/rtti",
+    "//src/tint/utils/symbol",
+    "//src/tint/utils/text",
+    "//src/tint/utils/traits",
+  ],
+  copts = COPTS,
+  visibility = ["//visibility:public"],
+)
+cc_library(
+  name = "test",
+  alwayslink = True,
+  srcs = [
+    "constant_test.cc",
+    "helper_test.h",
+  ],
+  deps = [
+    "//src/tint/api/common",
+    "//src/tint/lang/core",
+    "//src/tint/lang/core/constant",
+    "//src/tint/lang/core/intrinsic",
+    "//src/tint/lang/core/ir",
+    "//src/tint/lang/core/type",
+    "//src/tint/lang/glsl/writer/raise",
+    "//src/tint/utils/containers",
+    "//src/tint/utils/diagnostic",
+    "//src/tint/utils/generator",
+    "//src/tint/utils/ice",
+    "//src/tint/utils/id",
+    "//src/tint/utils/macros",
+    "//src/tint/utils/math",
+    "//src/tint/utils/memory",
+    "//src/tint/utils/reflection",
+    "//src/tint/utils/result",
+    "//src/tint/utils/rtti",
+    "//src/tint/utils/symbol",
+    "//src/tint/utils/text",
+    "//src/tint/utils/traits",
+    "@gtest",
+  ] + select({
+    ":tint_build_glsl_writer": [
+      "//src/tint/lang/glsl/writer/printer",
+    ],
+    "//conditions:default": [],
+  }),
+  copts = COPTS,
+  visibility = ["//visibility:public"],
+)
+
+alias(
+  name = "tint_build_glsl_writer",
+  actual = "//src/tint:tint_build_glsl_writer_true",
+)
+
diff --git a/src/tint/lang/glsl/writer/printer/BUILD.cfg b/src/tint/lang/glsl/writer/printer/BUILD.cfg
new file mode 100644
index 0000000..7459430
--- /dev/null
+++ b/src/tint/lang/glsl/writer/printer/BUILD.cfg
@@ -0,0 +1,3 @@
+{
+    "condition": "tint_build_glsl_writer"
+}
diff --git a/src/tint/lang/glsl/writer/printer/BUILD.cmake b/src/tint/lang/glsl/writer/printer/BUILD.cmake
new file mode 100644
index 0000000..197d8e5
--- /dev/null
+++ b/src/tint/lang/glsl/writer/printer/BUILD.cmake
@@ -0,0 +1,103 @@
+# Copyright 2023 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.
+
+################################################################################
+# File generated by 'tools/src/cmd/gen' using the template:
+#   tools/src/cmd/gen/build/BUILD.cmake.tmpl
+#
+# To regenerate run: './tools/run gen'
+#
+#                       Do not modify this file directly
+################################################################################
+
+if(TINT_BUILD_GLSL_WRITER)
+################################################################################
+# Target:    tint_lang_glsl_writer_printer
+# Kind:      lib
+# Condition: TINT_BUILD_GLSL_WRITER
+################################################################################
+tint_add_target(tint_lang_glsl_writer_printer lib
+  lang/glsl/writer/printer/printer.cc
+  lang/glsl/writer/printer/printer.h
+)
+
+tint_target_add_dependencies(tint_lang_glsl_writer_printer lib
+  tint_api_common
+  tint_lang_core
+  tint_lang_core_constant
+  tint_lang_core_ir
+  tint_lang_core_type
+  tint_utils_containers
+  tint_utils_diagnostic
+  tint_utils_generator
+  tint_utils_ice
+  tint_utils_id
+  tint_utils_macros
+  tint_utils_math
+  tint_utils_memory
+  tint_utils_reflection
+  tint_utils_result
+  tint_utils_rtti
+  tint_utils_symbol
+  tint_utils_text
+  tint_utils_traits
+)
+
+endif(TINT_BUILD_GLSL_WRITER)
+if(TINT_BUILD_GLSL_WRITER)
+################################################################################
+# Target:    tint_lang_glsl_writer_printer_test
+# Kind:      test
+# Condition: TINT_BUILD_GLSL_WRITER
+################################################################################
+tint_add_target(tint_lang_glsl_writer_printer_test test
+  lang/glsl/writer/printer/constant_test.cc
+  lang/glsl/writer/printer/helper_test.h
+)
+
+tint_target_add_dependencies(tint_lang_glsl_writer_printer_test test
+  tint_api_common
+  tint_lang_core
+  tint_lang_core_constant
+  tint_lang_core_intrinsic
+  tint_lang_core_ir
+  tint_lang_core_type
+  tint_lang_glsl_writer_raise
+  tint_utils_containers
+  tint_utils_diagnostic
+  tint_utils_generator
+  tint_utils_ice
+  tint_utils_id
+  tint_utils_macros
+  tint_utils_math
+  tint_utils_memory
+  tint_utils_reflection
+  tint_utils_result
+  tint_utils_rtti
+  tint_utils_symbol
+  tint_utils_text
+  tint_utils_traits
+)
+
+tint_target_add_external_dependencies(tint_lang_glsl_writer_printer_test test
+  "gtest"
+)
+
+if(TINT_BUILD_GLSL_WRITER)
+  tint_target_add_dependencies(tint_lang_glsl_writer_printer_test test
+    tint_lang_glsl_writer_printer
+  )
+endif(TINT_BUILD_GLSL_WRITER)
+
+endif(TINT_BUILD_GLSL_WRITER)
\ No newline at end of file
diff --git a/src/tint/lang/glsl/writer/printer/BUILD.gn b/src/tint/lang/glsl/writer/printer/BUILD.gn
new file mode 100644
index 0000000..86189a8
--- /dev/null
+++ b/src/tint/lang/glsl/writer/printer/BUILD.gn
@@ -0,0 +1,97 @@
+# Copyright 2023 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.
+
+################################################################################
+# File generated by 'tools/src/cmd/gen' using the template:
+#   tools/src/cmd/gen/build/BUILD.gn.tmpl
+#
+# To regenerate run: './tools/run gen'
+#
+#                       Do not modify this file directly
+################################################################################
+
+import("../../../../../../scripts/tint_overrides_with_defaults.gni")
+
+import("${tint_src_dir}/tint.gni")
+
+if (tint_build_unittests || tint_build_benchmarks) {
+  import("//testing/test.gni")
+}
+if (tint_build_glsl_writer) {
+  libtint_source_set("printer") {
+    sources = [
+      "printer.cc",
+      "printer.h",
+    ]
+    deps = [
+      "${tint_src_dir}/api/common",
+      "${tint_src_dir}/lang/core",
+      "${tint_src_dir}/lang/core/constant",
+      "${tint_src_dir}/lang/core/ir",
+      "${tint_src_dir}/lang/core/type",
+      "${tint_src_dir}/utils/containers",
+      "${tint_src_dir}/utils/diagnostic",
+      "${tint_src_dir}/utils/generator",
+      "${tint_src_dir}/utils/ice",
+      "${tint_src_dir}/utils/id",
+      "${tint_src_dir}/utils/macros",
+      "${tint_src_dir}/utils/math",
+      "${tint_src_dir}/utils/memory",
+      "${tint_src_dir}/utils/reflection",
+      "${tint_src_dir}/utils/result",
+      "${tint_src_dir}/utils/rtti",
+      "${tint_src_dir}/utils/symbol",
+      "${tint_src_dir}/utils/text",
+      "${tint_src_dir}/utils/traits",
+    ]
+  }
+}
+if (tint_build_unittests) {
+  if (tint_build_glsl_writer) {
+    tint_unittests_source_set("unittests") {
+      sources = [
+        "constant_test.cc",
+        "helper_test.h",
+      ]
+      deps = [
+        "${tint_src_dir}:gmock_and_gtest",
+        "${tint_src_dir}/api/common",
+        "${tint_src_dir}/lang/core",
+        "${tint_src_dir}/lang/core/constant",
+        "${tint_src_dir}/lang/core/intrinsic",
+        "${tint_src_dir}/lang/core/ir",
+        "${tint_src_dir}/lang/core/type",
+        "${tint_src_dir}/lang/glsl/writer/raise",
+        "${tint_src_dir}/utils/containers",
+        "${tint_src_dir}/utils/diagnostic",
+        "${tint_src_dir}/utils/generator",
+        "${tint_src_dir}/utils/ice",
+        "${tint_src_dir}/utils/id",
+        "${tint_src_dir}/utils/macros",
+        "${tint_src_dir}/utils/math",
+        "${tint_src_dir}/utils/memory",
+        "${tint_src_dir}/utils/reflection",
+        "${tint_src_dir}/utils/result",
+        "${tint_src_dir}/utils/rtti",
+        "${tint_src_dir}/utils/symbol",
+        "${tint_src_dir}/utils/text",
+        "${tint_src_dir}/utils/traits",
+      ]
+
+      if (tint_build_glsl_writer) {
+        deps += [ "${tint_src_dir}/lang/glsl/writer/printer" ]
+      }
+    }
+  }
+}
diff --git a/src/tint/lang/glsl/writer/printer/constant_test.cc b/src/tint/lang/glsl/writer/printer/constant_test.cc
new file mode 100644
index 0000000..c4c9c13
--- /dev/null
+++ b/src/tint/lang/glsl/writer/printer/constant_test.cc
@@ -0,0 +1,28 @@
+// Copyright 2023 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/tint/lang/glsl/writer/printer/helper_test.h"
+
+using namespace tint::core::number_suffixes;  // NOLINT
+using namespace tint::core::fluent_types;     // NOLINT
+
+namespace tint::glsl::writer {
+namespace {
+
+TEST_F(GlslPrinterTest, DISABLED_Constant_Bool_True) {
+    FAIL();
+}
+
+}  // namespace
+}  // namespace tint::glsl::writer
diff --git a/src/tint/lang/glsl/writer/printer/helper_test.h b/src/tint/lang/glsl/writer/printer/helper_test.h
new file mode 100644
index 0000000..fcecc3f
--- /dev/null
+++ b/src/tint/lang/glsl/writer/printer/helper_test.h
@@ -0,0 +1,78 @@
+// Copyright 2023 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_TINT_LANG_GLSL_WRITER_PRINTER_HELPER_TEST_H_
+#define SRC_TINT_LANG_GLSL_WRITER_PRINTER_HELPER_TEST_H_
+
+#include <string>
+
+#include "gtest/gtest.h"
+#include "src/tint/lang/core/ir/builder.h"
+#include "src/tint/lang/core/ir/validator.h"
+#include "src/tint/lang/glsl/writer/printer/printer.h"
+#include "src/tint/lang/glsl/writer/raise/raise.h"
+
+namespace tint::glsl::writer {
+
+/// Base helper class for testing the GLSL generator implementation.
+template <typename BASE>
+class GlslPrinterTestHelperBase : public BASE {
+  public:
+    GlslPrinterTestHelperBase() : writer_(mod) {}
+
+    /// The test module.
+    core::ir::Module mod;
+    /// The test builder.
+    core::ir::Builder b{mod};
+    /// The type manager.
+    core::type::Manager& ty{mod.Types()};
+
+  protected:
+    /// The GLSL writer.
+    Printer writer_;
+
+    /// Validation errors
+    std::string err_;
+
+    /// Generated GLSL
+    std::string output_;
+
+    /// Run the writer on the IR module and validate the result.
+    /// @returns true if generation and validation succeeded
+    bool Generate() {
+        auto raised = raise::Raise(mod);
+        if (!raised) {
+            err_ = raised.Failure().reason.str();
+            return false;
+        }
+
+        auto result = writer_.Generate();
+        if (!result) {
+            err_ = result.Failure().reason.str();
+            return false;
+        }
+        output_ = writer_.Result();
+
+        return true;
+    }
+};
+
+using GlslPrinterTest = GlslPrinterTestHelperBase<testing::Test>;
+
+template <typename T>
+using GlslPrinterTestWithParam = GlslPrinterTestHelperBase<testing::TestWithParam<T>>;
+
+}  // namespace tint::glsl::writer
+
+#endif  // SRC_TINT_LANG_GLSL_WRITER_PRINTER_HELPER_TEST_H_
diff --git a/src/tint/lang/glsl/writer/printer/printer.cc b/src/tint/lang/glsl/writer/printer/printer.cc
new file mode 100644
index 0000000..e14ea19
--- /dev/null
+++ b/src/tint/lang/glsl/writer/printer/printer.cc
@@ -0,0 +1,44 @@
+// Copyright 2023 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/tint/lang/glsl/writer/printer/printer.h"
+
+#include <utility>
+
+#include "src/tint/lang/core/ir/validator.h"
+
+using namespace tint::core::fluent_types;  // NOLINT
+
+namespace tint::glsl::writer {
+
+Printer::Printer(core::ir::Module& module) : ir_(module) {}
+
+Printer::~Printer() = default;
+
+tint::Result<SuccessType> Printer::Generate() {
+    auto valid = core::ir::ValidateAndDumpIfNeeded(ir_, "GLSL writer");
+    if (!valid) {
+        return std::move(valid.Failure());
+    }
+
+    return Success;
+}
+
+std::string Printer::Result() const {
+    StringStream ss;
+    ss << preamble_buffer_.String() << '\n' << main_buffer_.String();
+    return ss.str();
+}
+
+}  // namespace tint::glsl::writer
diff --git a/src/tint/lang/glsl/writer/printer/printer.h b/src/tint/lang/glsl/writer/printer/printer.h
new file mode 100644
index 0000000..a18a834
--- /dev/null
+++ b/src/tint/lang/glsl/writer/printer/printer.h
@@ -0,0 +1,60 @@
+// Copyright 2023 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_TINT_LANG_GLSL_WRITER_PRINTER_PRINTER_H_
+#define SRC_TINT_LANG_GLSL_WRITER_PRINTER_PRINTER_H_
+
+#include <string>
+
+#include "src/tint/lang/core/ir/module.h"
+#include "src/tint/utils/generator/text_generator.h"
+
+// Forward declarations
+namespace tint::core::ir {
+class Binary;
+class ExitIf;
+class If;
+class Let;
+class Load;
+class Return;
+class Unreachable;
+class Var;
+}  // namespace tint::core::ir
+
+namespace tint::glsl::writer {
+
+/// Implementation class for the MSL generator
+class Printer : public tint::TextGenerator {
+  public:
+    /// Constructor
+    /// @param module the Tint IR module to generate
+    explicit Printer(core::ir::Module& module);
+    ~Printer() override;
+
+    /// @returns success or failure
+    tint::Result<SuccessType> Generate();
+
+    /// @copydoc tint::TextGenerator::Result
+    std::string Result() const override;
+
+  private:
+    core::ir::Module& ir_;
+
+    /// The buffer holding preamble text
+    TextBuffer preamble_buffer_;
+};
+
+}  // namespace tint::glsl::writer
+
+#endif  // SRC_TINT_LANG_GLSL_WRITER_PRINTER_PRINTER_H_
diff --git a/src/tint/lang/glsl/writer/raise/BUILD.bazel b/src/tint/lang/glsl/writer/raise/BUILD.bazel
new file mode 100644
index 0000000..aca5d79
--- /dev/null
+++ b/src/tint/lang/glsl/writer/raise/BUILD.bazel
@@ -0,0 +1,49 @@
+# Copyright 2023 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.
+
+################################################################################
+# File generated by 'tools/src/cmd/gen' using the template:
+#   tools/src/cmd/gen/build/BUILD.bazel.tmpl
+#
+# To regenerate run: './tools/run gen'
+#
+#                       Do not modify this file directly
+################################################################################
+
+load("//src/tint:flags.bzl", "COPTS")
+load("@bazel_skylib//lib:selects.bzl", "selects")
+cc_library(
+  name = "raise",
+  srcs = [
+    "raise.cc",
+  ],
+  hdrs = [
+    "raise.h",
+  ],
+  deps = [
+    "//src/tint/utils/containers",
+    "//src/tint/utils/diagnostic",
+    "//src/tint/utils/ice",
+    "//src/tint/utils/macros",
+    "//src/tint/utils/math",
+    "//src/tint/utils/memory",
+    "//src/tint/utils/result",
+    "//src/tint/utils/rtti",
+    "//src/tint/utils/text",
+    "//src/tint/utils/traits",
+  ],
+  copts = COPTS,
+  visibility = ["//visibility:public"],
+)
+
diff --git a/src/tint/lang/glsl/writer/raise/BUILD.cmake b/src/tint/lang/glsl/writer/raise/BUILD.cmake
new file mode 100644
index 0000000..64b874d
--- /dev/null
+++ b/src/tint/lang/glsl/writer/raise/BUILD.cmake
@@ -0,0 +1,44 @@
+# Copyright 2023 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.
+
+################################################################################
+# File generated by 'tools/src/cmd/gen' using the template:
+#   tools/src/cmd/gen/build/BUILD.cmake.tmpl
+#
+# To regenerate run: './tools/run gen'
+#
+#                       Do not modify this file directly
+################################################################################
+
+################################################################################
+# Target:    tint_lang_glsl_writer_raise
+# Kind:      lib
+################################################################################
+tint_add_target(tint_lang_glsl_writer_raise lib
+  lang/glsl/writer/raise/raise.cc
+  lang/glsl/writer/raise/raise.h
+)
+
+tint_target_add_dependencies(tint_lang_glsl_writer_raise lib
+  tint_utils_containers
+  tint_utils_diagnostic
+  tint_utils_ice
+  tint_utils_macros
+  tint_utils_math
+  tint_utils_memory
+  tint_utils_result
+  tint_utils_rtti
+  tint_utils_text
+  tint_utils_traits
+)
diff --git a/src/tint/lang/glsl/writer/raise/BUILD.gn b/src/tint/lang/glsl/writer/raise/BUILD.gn
new file mode 100644
index 0000000..b03edf1
--- /dev/null
+++ b/src/tint/lang/glsl/writer/raise/BUILD.gn
@@ -0,0 +1,45 @@
+# Copyright 2023 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.
+
+################################################################################
+# File generated by 'tools/src/cmd/gen' using the template:
+#   tools/src/cmd/gen/build/BUILD.gn.tmpl
+#
+# To regenerate run: './tools/run gen'
+#
+#                       Do not modify this file directly
+################################################################################
+
+import("../../../../../../scripts/tint_overrides_with_defaults.gni")
+
+import("${tint_src_dir}/tint.gni")
+
+libtint_source_set("raise") {
+  sources = [
+    "raise.cc",
+    "raise.h",
+  ]
+  deps = [
+    "${tint_src_dir}/utils/containers",
+    "${tint_src_dir}/utils/diagnostic",
+    "${tint_src_dir}/utils/ice",
+    "${tint_src_dir}/utils/macros",
+    "${tint_src_dir}/utils/math",
+    "${tint_src_dir}/utils/memory",
+    "${tint_src_dir}/utils/result",
+    "${tint_src_dir}/utils/rtti",
+    "${tint_src_dir}/utils/text",
+    "${tint_src_dir}/utils/traits",
+  ]
+}
diff --git a/src/tint/lang/glsl/writer/raise/raise.cc b/src/tint/lang/glsl/writer/raise/raise.cc
new file mode 100644
index 0000000..c038911
--- /dev/null
+++ b/src/tint/lang/glsl/writer/raise/raise.cc
@@ -0,0 +1,31 @@
+// Copyright 2023 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/tint/lang/glsl/writer/raise/raise.h"
+
+namespace tint::glsl::raise {
+
+Result<SuccessType> Raise(core::ir::Module&) {
+    // #define RUN_TRANSFORM(name)
+    //     do {
+    //         auto result = core::ir::transform::name(module);
+    //         if (!result) {
+    //             return result;
+    //         }
+    //     } while (false)
+
+    return Success;
+}
+
+}  // namespace tint::glsl::raise
diff --git a/src/tint/lang/glsl/writer/raise/raise.h b/src/tint/lang/glsl/writer/raise/raise.h
new file mode 100644
index 0000000..137f262
--- /dev/null
+++ b/src/tint/lang/glsl/writer/raise/raise.h
@@ -0,0 +1,34 @@
+// Copyright 2023 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_TINT_LANG_GLSL_WRITER_RAISE_RAISE_H_
+#define SRC_TINT_LANG_GLSL_WRITER_RAISE_RAISE_H_
+
+#include "src/tint/utils/result/result.h"
+
+// Forward declarations
+namespace tint::core::ir {
+class Module;
+}  // namespace tint::core::ir
+
+namespace tint::glsl::raise {
+
+/// Raise a core IR module to the MSL dialect of the IR.
+/// @param mod the core IR module to raise to MSL dialect
+/// @returns success or failure
+Result<SuccessType> Raise(core::ir::Module& mod);
+
+}  // namespace tint::glsl::raise
+
+#endif  // SRC_TINT_LANG_GLSL_WRITER_RAISE_RAISE_H_
diff --git a/src/tint/lang/glsl/writer/writer.cc b/src/tint/lang/glsl/writer/writer.cc
index 0a13c7b..f5743d5 100644
--- a/src/tint/lang/glsl/writer/writer.cc
+++ b/src/tint/lang/glsl/writer/writer.cc
@@ -31,7 +31,13 @@
 #include <utility>
 
 #include "src/tint/lang/glsl/writer/ast_printer/ast_printer.h"
-#include "src/tint/lang/wgsl/ast/transform/binding_remapper.h"
+#include "src/tint/lang/glsl/writer/printer/printer.h"
+#include "src/tint/lang/glsl/writer/raise/raise.h"
+
+#if TINT_BUILD_WGSL_READER
+#include "src/tint/lang/wgsl/reader/lower/lower.h"
+#include "src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h"
+#endif  // TINT_BUILD_WGSL_REAdDER
 
 namespace tint::glsl::writer {
 
@@ -42,28 +48,61 @@
         return Failure{program.Diagnostics()};
     }
 
-    // Sanitize the program.
-    auto sanitized_result = Sanitize(program, options, entry_point);
-    if (!sanitized_result.program.IsValid()) {
-        return Failure{sanitized_result.program.Diagnostics()};
-    }
-
-    // Generate the GLSL code.
-    auto impl = std::make_unique<ASTPrinter>(sanitized_result.program, options.version);
-    if (!impl->Generate()) {
-        return Failure{impl->Diagnostics()};
-    }
-
     Output output;
-    output.glsl = impl->Result();
-    output.needs_internal_uniform_buffer = sanitized_result.needs_internal_uniform_buffer;
-    output.bindpoint_to_data = std::move(sanitized_result.bindpoint_to_data);
 
-    // Collect the list of entry points in the sanitized program.
-    for (auto* func : sanitized_result.program.AST().Functions()) {
-        if (func->IsEntryPoint()) {
-            auto name = func->name->symbol.Name();
-            output.entry_points.push_back({name, func->PipelineStage()});
+    if (options.use_tint_ir) {
+#if TINT_BUILD_WGSL_READER
+        // Convert the AST program to an IR module.
+        auto converted = wgsl::reader::ProgramToIR(program);
+        if (!converted) {
+            return converted.Failure();
+        }
+
+        auto ir = converted.Move();
+
+        // Lower from WGSL-dialect to core-dialect
+        if (auto res = wgsl::reader::Lower(ir); !res) {
+            return res.Failure();
+        }
+
+        // Raise from core-dialect to GLSL-dialect.
+        if (auto res = raise::Raise(ir); !res) {
+            return res.Failure();
+        }
+
+        // Generate the GLSL code.
+        auto impl = std::make_unique<Printer>(ir);
+        auto result = impl->Generate();
+        if (!result) {
+            return result.Failure();
+        }
+        output.glsl = impl->Result();
+#else
+        return Failure{"use_tint_ir requires building with TINT_BUILD_WGSL_READER"};
+#endif
+    } else {
+        // Sanitize the program.
+        auto sanitized_result = Sanitize(program, options, entry_point);
+        if (!sanitized_result.program.IsValid()) {
+            return Failure{sanitized_result.program.Diagnostics()};
+        }
+
+        // Generate the GLSL code.
+        auto impl = std::make_unique<ASTPrinter>(sanitized_result.program, options.version);
+        if (!impl->Generate()) {
+            return Failure{impl->Diagnostics()};
+        }
+
+        output.glsl = impl->Result();
+        output.needs_internal_uniform_buffer = sanitized_result.needs_internal_uniform_buffer;
+        output.bindpoint_to_data = std::move(sanitized_result.bindpoint_to_data);
+
+        // Collect the list of entry points in the sanitized program.
+        for (auto* func : sanitized_result.program.AST().Functions()) {
+            if (func->IsEntryPoint()) {
+                auto name = func->name->symbol.Name();
+                output.entry_points.push_back({name, func->PipelineStage()});
+            }
         }
     }
 
diff --git a/src/tint/lang/msl/writer/writer.cc b/src/tint/lang/msl/writer/writer.cc
index f13de9c..8f854df 100644
--- a/src/tint/lang/msl/writer/writer.cc
+++ b/src/tint/lang/msl/writer/writer.cc
@@ -33,9 +33,9 @@
 #include "src/tint/lang/msl/writer/ast_printer/ast_printer.h"
 #include "src/tint/lang/msl/writer/printer/printer.h"
 #include "src/tint/lang/msl/writer/raise/raise.h"
-#include "src/tint/lang/wgsl/reader/lower/lower.h"
 
 #if TINT_BUILD_WGSL_READER
+#include "src/tint/lang/wgsl/reader/lower/lower.h"
 #include "src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h"
 #endif