[wgsl-writer] Add ProgramOptions for IR->AST

This is used to convey information about allowed language features and
whether non-uniform derivatives should be permitted.

This is needed for the new SPIR-V to WGSL flow, which will be two
separate steps.

Bug: tint:1907
Change-Id: I065247e784f50a90b9b2f30e03fdbb124e94153e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/165301
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/api/BUILD.bazel b/src/tint/api/BUILD.bazel
index 22d06eb..32a7773 100644
--- a/src/tint/api/BUILD.bazel
+++ b/src/tint/api/BUILD.bazel
@@ -59,6 +59,7 @@
     "//src/tint/lang/wgsl/features",
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
diff --git a/src/tint/api/BUILD.cmake b/src/tint/api/BUILD.cmake
index dea891a..af664e6 100644
--- a/src/tint/api/BUILD.cmake
+++ b/src/tint/api/BUILD.cmake
@@ -61,6 +61,7 @@
   tint_lang_wgsl_features
   tint_lang_wgsl_program
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_containers
   tint_utils_diagnostic
   tint_utils_ice
diff --git a/src/tint/api/BUILD.gn b/src/tint/api/BUILD.gn
index 4c3586f..ff3f483 100644
--- a/src/tint/api/BUILD.gn
+++ b/src/tint/api/BUILD.gn
@@ -58,6 +58,7 @@
     "${tint_src_dir}/lang/wgsl/features",
     "${tint_src_dir}/lang/wgsl/program",
     "${tint_src_dir}/lang/wgsl/sem",
+    "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
     "${tint_src_dir}/utils/containers",
     "${tint_src_dir}/utils/diagnostic",
     "${tint_src_dir}/utils/ice",
diff --git a/src/tint/cmd/bench/BUILD.bazel b/src/tint/cmd/bench/BUILD.bazel
index df4a15f..48b45c3 100644
--- a/src/tint/cmd/bench/BUILD.bazel
+++ b/src/tint/cmd/bench/BUILD.bazel
@@ -56,6 +56,7 @@
     "//src/tint/lang/wgsl/features",
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
diff --git a/src/tint/cmd/bench/BUILD.cmake b/src/tint/cmd/bench/BUILD.cmake
index 0af9aa2..9df1c7a 100644
--- a/src/tint/cmd/bench/BUILD.cmake
+++ b/src/tint/cmd/bench/BUILD.cmake
@@ -132,6 +132,7 @@
   tint_lang_wgsl_features
   tint_lang_wgsl_program
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_containers
   tint_utils_diagnostic
   tint_utils_ice
diff --git a/src/tint/cmd/bench/BUILD.gn b/src/tint/cmd/bench/BUILD.gn
index 5143ce9..8697f0c 100644
--- a/src/tint/cmd/bench/BUILD.gn
+++ b/src/tint/cmd/bench/BUILD.gn
@@ -61,6 +61,7 @@
       "${tint_src_dir}/lang/wgsl/features",
       "${tint_src_dir}/lang/wgsl/program",
       "${tint_src_dir}/lang/wgsl/sem",
+      "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
       "${tint_src_dir}/utils/containers",
       "${tint_src_dir}/utils/diagnostic",
       "${tint_src_dir}/utils/ice",
diff --git a/src/tint/cmd/common/BUILD.bazel b/src/tint/cmd/common/BUILD.bazel
index acade5c..c768f73 100644
--- a/src/tint/cmd/common/BUILD.bazel
+++ b/src/tint/cmd/common/BUILD.bazel
@@ -61,6 +61,7 @@
     "//src/tint/lang/wgsl/inspector",
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
diff --git a/src/tint/cmd/common/BUILD.cmake b/src/tint/cmd/common/BUILD.cmake
index b795733..43d472f 100644
--- a/src/tint/cmd/common/BUILD.cmake
+++ b/src/tint/cmd/common/BUILD.cmake
@@ -60,6 +60,7 @@
   tint_lang_wgsl_inspector
   tint_lang_wgsl_program
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_containers
   tint_utils_diagnostic
   tint_utils_ice
diff --git a/src/tint/cmd/common/BUILD.gn b/src/tint/cmd/common/BUILD.gn
index 99229d6..4b1f5e3 100644
--- a/src/tint/cmd/common/BUILD.gn
+++ b/src/tint/cmd/common/BUILD.gn
@@ -64,6 +64,7 @@
     "${tint_src_dir}/lang/wgsl/inspector",
     "${tint_src_dir}/lang/wgsl/program",
     "${tint_src_dir}/lang/wgsl/sem",
+    "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
     "${tint_src_dir}/utils/containers",
     "${tint_src_dir}/utils/diagnostic",
     "${tint_src_dir}/utils/ice",
diff --git a/src/tint/cmd/loopy/BUILD.bazel b/src/tint/cmd/loopy/BUILD.bazel
index 7d42293..e0b4ebe 100644
--- a/src/tint/cmd/loopy/BUILD.bazel
+++ b/src/tint/cmd/loopy/BUILD.bazel
@@ -60,6 +60,7 @@
     "//src/tint/lang/wgsl/inspector",
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
diff --git a/src/tint/cmd/loopy/BUILD.cmake b/src/tint/cmd/loopy/BUILD.cmake
index f72d122..abf2e07 100644
--- a/src/tint/cmd/loopy/BUILD.cmake
+++ b/src/tint/cmd/loopy/BUILD.cmake
@@ -61,6 +61,7 @@
   tint_lang_wgsl_inspector
   tint_lang_wgsl_program
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_containers
   tint_utils_diagnostic
   tint_utils_ice
diff --git a/src/tint/cmd/loopy/BUILD.gn b/src/tint/cmd/loopy/BUILD.gn
index 4879c29..3241429 100644
--- a/src/tint/cmd/loopy/BUILD.gn
+++ b/src/tint/cmd/loopy/BUILD.gn
@@ -60,6 +60,7 @@
     "${tint_src_dir}/lang/wgsl/inspector",
     "${tint_src_dir}/lang/wgsl/program",
     "${tint_src_dir}/lang/wgsl/sem",
+    "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
     "${tint_src_dir}/utils/containers",
     "${tint_src_dir}/utils/diagnostic",
     "${tint_src_dir}/utils/ice",
diff --git a/src/tint/cmd/tint/BUILD.bazel b/src/tint/cmd/tint/BUILD.bazel
index b6fb729..934ff47 100644
--- a/src/tint/cmd/tint/BUILD.bazel
+++ b/src/tint/cmd/tint/BUILD.bazel
@@ -61,6 +61,7 @@
     "//src/tint/lang/wgsl/inspector",
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/cli",
     "//src/tint/utils/command",
     "//src/tint/utils/containers",
diff --git a/src/tint/cmd/tint/BUILD.cmake b/src/tint/cmd/tint/BUILD.cmake
index 9f35d05..3924e7d 100644
--- a/src/tint/cmd/tint/BUILD.cmake
+++ b/src/tint/cmd/tint/BUILD.cmake
@@ -62,6 +62,7 @@
   tint_lang_wgsl_inspector
   tint_lang_wgsl_program
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_cli
   tint_utils_command
   tint_utils_containers
diff --git a/src/tint/cmd/tint/BUILD.gn b/src/tint/cmd/tint/BUILD.gn
index c5b628c..b9fca30 100644
--- a/src/tint/cmd/tint/BUILD.gn
+++ b/src/tint/cmd/tint/BUILD.gn
@@ -61,6 +61,7 @@
     "${tint_src_dir}/lang/wgsl/inspector",
     "${tint_src_dir}/lang/wgsl/program",
     "${tint_src_dir}/lang/wgsl/sem",
+    "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
     "${tint_src_dir}/utils/cli",
     "${tint_src_dir}/utils/command",
     "${tint_src_dir}/utils/containers",
diff --git a/src/tint/lang/core/ir/transform/direct_variable_access_wgsl_test.cc b/src/tint/lang/core/ir/transform/direct_variable_access_wgsl_test.cc
index 7b8a407..e1d77c1 100644
--- a/src/tint/lang/core/ir/transform/direct_variable_access_wgsl_test.cc
+++ b/src/tint/lang/core/ir/transform/direct_variable_access_wgsl_test.cc
@@ -77,7 +77,10 @@
             return "DirectVariableAccess failed:\n" + res.Failure().reason.str();
         }
 
-        auto transformed = wgsl::writer::IRToProgram(module.Get());
+        wgsl::writer::ProgramOptions program_options;
+        program_options.allowed_features.extensions.insert(
+            wgsl::Extension::kChromiumExperimentalFullPtrParameters);
+        auto transformed = wgsl::writer::IRToProgram(module.Get(), program_options);
         if (!transformed.IsValid()) {
             return "wgsl::writer::IRToProgram() failed: \n" + transformed.Diagnostics().str() +
                    "\n\nIR:\n" + ir::Disassemble(module.Get()) +  //
diff --git a/src/tint/lang/glsl/writer/ast_raise/BUILD.bazel b/src/tint/lang/glsl/writer/ast_raise/BUILD.bazel
index 8e05047..540f314 100644
--- a/src/tint/lang/glsl/writer/ast_raise/BUILD.bazel
+++ b/src/tint/lang/glsl/writer/ast_raise/BUILD.bazel
@@ -104,6 +104,7 @@
     "//src/tint/lang/wgsl/features",
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
diff --git a/src/tint/lang/glsl/writer/ast_raise/BUILD.cmake b/src/tint/lang/glsl/writer/ast_raise/BUILD.cmake
index 8fd03ab..0ca869d 100644
--- a/src/tint/lang/glsl/writer/ast_raise/BUILD.cmake
+++ b/src/tint/lang/glsl/writer/ast_raise/BUILD.cmake
@@ -108,6 +108,7 @@
   tint_lang_wgsl_features
   tint_lang_wgsl_program
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_containers
   tint_utils_diagnostic
   tint_utils_ice
diff --git a/src/tint/lang/glsl/writer/ast_raise/BUILD.gn b/src/tint/lang/glsl/writer/ast_raise/BUILD.gn
index 38e3359..23c0067 100644
--- a/src/tint/lang/glsl/writer/ast_raise/BUILD.gn
+++ b/src/tint/lang/glsl/writer/ast_raise/BUILD.gn
@@ -108,6 +108,7 @@
         "${tint_src_dir}/lang/wgsl/features",
         "${tint_src_dir}/lang/wgsl/program",
         "${tint_src_dir}/lang/wgsl/sem",
+        "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
         "${tint_src_dir}/utils/containers",
         "${tint_src_dir}/utils/diagnostic",
         "${tint_src_dir}/utils/ice",
diff --git a/src/tint/lang/hlsl/writer/ast_raise/BUILD.bazel b/src/tint/lang/hlsl/writer/ast_raise/BUILD.bazel
index 1af1d58..dea6056 100644
--- a/src/tint/lang/hlsl/writer/ast_raise/BUILD.bazel
+++ b/src/tint/lang/hlsl/writer/ast_raise/BUILD.bazel
@@ -111,6 +111,7 @@
     "//src/tint/lang/wgsl/features",
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
diff --git a/src/tint/lang/hlsl/writer/ast_raise/BUILD.cmake b/src/tint/lang/hlsl/writer/ast_raise/BUILD.cmake
index ad2de08..71a814c 100644
--- a/src/tint/lang/hlsl/writer/ast_raise/BUILD.cmake
+++ b/src/tint/lang/hlsl/writer/ast_raise/BUILD.cmake
@@ -115,6 +115,7 @@
   tint_lang_wgsl_features
   tint_lang_wgsl_program
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_containers
   tint_utils_diagnostic
   tint_utils_ice
diff --git a/src/tint/lang/hlsl/writer/ast_raise/BUILD.gn b/src/tint/lang/hlsl/writer/ast_raise/BUILD.gn
index c009305..8ac7972 100644
--- a/src/tint/lang/hlsl/writer/ast_raise/BUILD.gn
+++ b/src/tint/lang/hlsl/writer/ast_raise/BUILD.gn
@@ -115,6 +115,7 @@
         "${tint_src_dir}/lang/wgsl/features",
         "${tint_src_dir}/lang/wgsl/program",
         "${tint_src_dir}/lang/wgsl/sem",
+        "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
         "${tint_src_dir}/utils/containers",
         "${tint_src_dir}/utils/diagnostic",
         "${tint_src_dir}/utils/ice",
diff --git a/src/tint/lang/msl/writer/ast_raise/BUILD.bazel b/src/tint/lang/msl/writer/ast_raise/BUILD.bazel
index 8b2b905..3764a2a 100644
--- a/src/tint/lang/msl/writer/ast_raise/BUILD.bazel
+++ b/src/tint/lang/msl/writer/ast_raise/BUILD.bazel
@@ -103,6 +103,7 @@
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/resolver",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
diff --git a/src/tint/lang/msl/writer/ast_raise/BUILD.cmake b/src/tint/lang/msl/writer/ast_raise/BUILD.cmake
index 93fb394..4366d7c 100644
--- a/src/tint/lang/msl/writer/ast_raise/BUILD.cmake
+++ b/src/tint/lang/msl/writer/ast_raise/BUILD.cmake
@@ -107,6 +107,7 @@
   tint_lang_wgsl_program
   tint_lang_wgsl_resolver
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_containers
   tint_utils_diagnostic
   tint_utils_ice
diff --git a/src/tint/lang/msl/writer/ast_raise/BUILD.gn b/src/tint/lang/msl/writer/ast_raise/BUILD.gn
index f5d025c..c3f0123 100644
--- a/src/tint/lang/msl/writer/ast_raise/BUILD.gn
+++ b/src/tint/lang/msl/writer/ast_raise/BUILD.gn
@@ -107,6 +107,7 @@
         "${tint_src_dir}/lang/wgsl/program",
         "${tint_src_dir}/lang/wgsl/resolver",
         "${tint_src_dir}/lang/wgsl/sem",
+        "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
         "${tint_src_dir}/utils/containers",
         "${tint_src_dir}/utils/diagnostic",
         "${tint_src_dir}/utils/ice",
diff --git a/src/tint/lang/spirv/reader/ast_lower/BUILD.bazel b/src/tint/lang/spirv/reader/ast_lower/BUILD.bazel
index 0fdbcd1..b89ad46 100644
--- a/src/tint/lang/spirv/reader/ast_lower/BUILD.bazel
+++ b/src/tint/lang/spirv/reader/ast_lower/BUILD.bazel
@@ -106,6 +106,7 @@
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/resolver",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
diff --git a/src/tint/lang/spirv/reader/ast_lower/BUILD.cmake b/src/tint/lang/spirv/reader/ast_lower/BUILD.cmake
index 1f1a04c..53e39c3 100644
--- a/src/tint/lang/spirv/reader/ast_lower/BUILD.cmake
+++ b/src/tint/lang/spirv/reader/ast_lower/BUILD.cmake
@@ -110,6 +110,7 @@
   tint_lang_wgsl_program
   tint_lang_wgsl_resolver
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_containers
   tint_utils_diagnostic
   tint_utils_ice
diff --git a/src/tint/lang/spirv/reader/ast_lower/BUILD.gn b/src/tint/lang/spirv/reader/ast_lower/BUILD.gn
index 9381efc..e6703a4 100644
--- a/src/tint/lang/spirv/reader/ast_lower/BUILD.gn
+++ b/src/tint/lang/spirv/reader/ast_lower/BUILD.gn
@@ -110,6 +110,7 @@
         "${tint_src_dir}/lang/wgsl/program",
         "${tint_src_dir}/lang/wgsl/resolver",
         "${tint_src_dir}/lang/wgsl/sem",
+        "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
         "${tint_src_dir}/utils/containers",
         "${tint_src_dir}/utils/diagnostic",
         "${tint_src_dir}/utils/ice",
diff --git a/src/tint/lang/spirv/writer/ast_raise/BUILD.bazel b/src/tint/lang/spirv/writer/ast_raise/BUILD.bazel
index ac25dcc..e13d946 100644
--- a/src/tint/lang/spirv/writer/ast_raise/BUILD.bazel
+++ b/src/tint/lang/spirv/writer/ast_raise/BUILD.bazel
@@ -108,6 +108,7 @@
     "//src/tint/lang/wgsl/features",
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
diff --git a/src/tint/lang/spirv/writer/ast_raise/BUILD.cmake b/src/tint/lang/spirv/writer/ast_raise/BUILD.cmake
index b79c8bb..9cd1d16 100644
--- a/src/tint/lang/spirv/writer/ast_raise/BUILD.cmake
+++ b/src/tint/lang/spirv/writer/ast_raise/BUILD.cmake
@@ -112,6 +112,7 @@
   tint_lang_wgsl_features
   tint_lang_wgsl_program
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_containers
   tint_utils_diagnostic
   tint_utils_ice
diff --git a/src/tint/lang/spirv/writer/ast_raise/BUILD.gn b/src/tint/lang/spirv/writer/ast_raise/BUILD.gn
index ba17c58..b18ddb5 100644
--- a/src/tint/lang/spirv/writer/ast_raise/BUILD.gn
+++ b/src/tint/lang/spirv/writer/ast_raise/BUILD.gn
@@ -112,6 +112,7 @@
         "${tint_src_dir}/lang/wgsl/features",
         "${tint_src_dir}/lang/wgsl/program",
         "${tint_src_dir}/lang/wgsl/sem",
+        "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
         "${tint_src_dir}/utils/containers",
         "${tint_src_dir}/utils/diagnostic",
         "${tint_src_dir}/utils/ice",
diff --git a/src/tint/lang/wgsl/ast/BUILD.bazel b/src/tint/lang/wgsl/ast/BUILD.bazel
index c44c746..6eca7ad 100644
--- a/src/tint/lang/wgsl/ast/BUILD.bazel
+++ b/src/tint/lang/wgsl/ast/BUILD.bazel
@@ -318,6 +318,7 @@
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/resolver",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
diff --git a/src/tint/lang/wgsl/ast/BUILD.cmake b/src/tint/lang/wgsl/ast/BUILD.cmake
index 3664cd7..767496f 100644
--- a/src/tint/lang/wgsl/ast/BUILD.cmake
+++ b/src/tint/lang/wgsl/ast/BUILD.cmake
@@ -310,6 +310,7 @@
   tint_lang_wgsl_program
   tint_lang_wgsl_resolver
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_containers
   tint_utils_diagnostic
   tint_utils_ice
diff --git a/src/tint/lang/wgsl/ast/BUILD.gn b/src/tint/lang/wgsl/ast/BUILD.gn
index fe2138f..f42bd86 100644
--- a/src/tint/lang/wgsl/ast/BUILD.gn
+++ b/src/tint/lang/wgsl/ast/BUILD.gn
@@ -310,6 +310,7 @@
       "${tint_src_dir}/lang/wgsl/program",
       "${tint_src_dir}/lang/wgsl/resolver",
       "${tint_src_dir}/lang/wgsl/sem",
+      "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
       "${tint_src_dir}/utils/containers",
       "${tint_src_dir}/utils/diagnostic",
       "${tint_src_dir}/utils/ice",
diff --git a/src/tint/lang/wgsl/ast/transform/BUILD.bazel b/src/tint/lang/wgsl/ast/transform/BUILD.bazel
index c8ff399..cb9c9b1 100644
--- a/src/tint/lang/wgsl/ast/transform/BUILD.bazel
+++ b/src/tint/lang/wgsl/ast/transform/BUILD.bazel
@@ -192,6 +192,7 @@
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/resolver",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
diff --git a/src/tint/lang/wgsl/ast/transform/BUILD.cmake b/src/tint/lang/wgsl/ast/transform/BUILD.cmake
index 35b0dcc..c432f09 100644
--- a/src/tint/lang/wgsl/ast/transform/BUILD.cmake
+++ b/src/tint/lang/wgsl/ast/transform/BUILD.cmake
@@ -193,6 +193,7 @@
   tint_lang_wgsl_program
   tint_lang_wgsl_resolver
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_containers
   tint_utils_diagnostic
   tint_utils_ice
diff --git a/src/tint/lang/wgsl/ast/transform/BUILD.gn b/src/tint/lang/wgsl/ast/transform/BUILD.gn
index e0af19e..1214968 100644
--- a/src/tint/lang/wgsl/ast/transform/BUILD.gn
+++ b/src/tint/lang/wgsl/ast/transform/BUILD.gn
@@ -194,6 +194,7 @@
         "${tint_src_dir}/lang/wgsl/program",
         "${tint_src_dir}/lang/wgsl/resolver",
         "${tint_src_dir}/lang/wgsl/sem",
+        "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
         "${tint_src_dir}/utils/containers",
         "${tint_src_dir}/utils/diagnostic",
         "${tint_src_dir}/utils/ice",
diff --git a/src/tint/lang/wgsl/ir_roundtrip_test.cc b/src/tint/lang/wgsl/ir_roundtrip_test.cc
index 305beab47..8e430d3 100644
--- a/src/tint/lang/wgsl/ir_roundtrip_test.cc
+++ b/src/tint/lang/wgsl/ir_roundtrip_test.cc
@@ -51,7 +51,9 @@
 
         auto disassembly = tint::core::ir::Disassemble(ir_module.Get());
 
-        auto output = wgsl::writer::WgslFromIR(ir_module.Get());
+        writer::ProgramOptions program_options;
+        program_options.allowed_features = AllowedFeatures::Everything();
+        auto output = wgsl::writer::WgslFromIR(ir_module.Get(), program_options);
         if (!output) {
             FAIL() << output.Failure() << std::endl  //
                    << "IR:" << std::endl             //
diff --git a/src/tint/lang/wgsl/program/BUILD.cmake b/src/tint/lang/wgsl/program/BUILD.cmake
index c55fc5a..75e0236 100644
--- a/src/tint/lang/wgsl/program/BUILD.cmake
+++ b/src/tint/lang/wgsl/program/BUILD.cmake
@@ -132,6 +132,7 @@
   tint_lang_wgsl_program
   tint_lang_wgsl_resolver
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_bytes
   tint_utils_containers
   tint_utils_diagnostic
diff --git a/src/tint/lang/wgsl/program/BUILD.gn b/src/tint/lang/wgsl/program/BUILD.gn
index f3e03fd..98ce8db 100644
--- a/src/tint/lang/wgsl/program/BUILD.gn
+++ b/src/tint/lang/wgsl/program/BUILD.gn
@@ -127,6 +127,7 @@
     "${tint_src_dir}/lang/wgsl/program",
     "${tint_src_dir}/lang/wgsl/resolver",
     "${tint_src_dir}/lang/wgsl/sem",
+    "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
     "${tint_src_dir}/utils/bytes",
     "${tint_src_dir}/utils/containers",
     "${tint_src_dir}/utils/diagnostic",
diff --git a/src/tint/lang/wgsl/writer/BUILD.bazel b/src/tint/lang/wgsl/writer/BUILD.bazel
index 2c39c85..ff06810 100644
--- a/src/tint/lang/wgsl/writer/BUILD.bazel
+++ b/src/tint/lang/wgsl/writer/BUILD.bazel
@@ -56,6 +56,8 @@
     "//src/tint/lang/core/type",
     "//src/tint/lang/wgsl",
     "//src/tint/lang/wgsl/ast",
+    "//src/tint/lang/wgsl/common",
+    "//src/tint/lang/wgsl/features",
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/sem",
     "//src/tint/lang/wgsl/writer/ir_to_program",
@@ -97,8 +99,11 @@
     "//src/tint/lang/core/type",
     "//src/tint/lang/wgsl",
     "//src/tint/lang/wgsl/ast",
+    "//src/tint/lang/wgsl/common",
+    "//src/tint/lang/wgsl/features",
     "//src/tint/lang/wgsl/program",
     "//src/tint/lang/wgsl/sem",
+    "//src/tint/lang/wgsl/writer/ir_to_program",
     "//src/tint/utils/containers",
     "//src/tint/utils/diagnostic",
     "//src/tint/utils/ice",
diff --git a/src/tint/lang/wgsl/writer/BUILD.cmake b/src/tint/lang/wgsl/writer/BUILD.cmake
index 3add0aa..4e172c8 100644
--- a/src/tint/lang/wgsl/writer/BUILD.cmake
+++ b/src/tint/lang/wgsl/writer/BUILD.cmake
@@ -62,6 +62,8 @@
   tint_lang_core_type
   tint_lang_wgsl
   tint_lang_wgsl_ast
+  tint_lang_wgsl_common
+  tint_lang_wgsl_features
   tint_lang_wgsl_program
   tint_lang_wgsl_sem
   tint_lang_wgsl_writer_ir_to_program
@@ -107,8 +109,11 @@
   tint_lang_core_type
   tint_lang_wgsl
   tint_lang_wgsl_ast
+  tint_lang_wgsl_common
+  tint_lang_wgsl_features
   tint_lang_wgsl_program
   tint_lang_wgsl_sem
+  tint_lang_wgsl_writer_ir_to_program
   tint_utils_containers
   tint_utils_diagnostic
   tint_utils_ice
diff --git a/src/tint/lang/wgsl/writer/BUILD.gn b/src/tint/lang/wgsl/writer/BUILD.gn
index 95966a3..107e29b 100644
--- a/src/tint/lang/wgsl/writer/BUILD.gn
+++ b/src/tint/lang/wgsl/writer/BUILD.gn
@@ -59,6 +59,8 @@
       "${tint_src_dir}/lang/core/type",
       "${tint_src_dir}/lang/wgsl",
       "${tint_src_dir}/lang/wgsl/ast",
+      "${tint_src_dir}/lang/wgsl/common",
+      "${tint_src_dir}/lang/wgsl/features",
       "${tint_src_dir}/lang/wgsl/program",
       "${tint_src_dir}/lang/wgsl/sem",
       "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
@@ -97,8 +99,11 @@
         "${tint_src_dir}/lang/core/type",
         "${tint_src_dir}/lang/wgsl",
         "${tint_src_dir}/lang/wgsl/ast",
+        "${tint_src_dir}/lang/wgsl/common",
+        "${tint_src_dir}/lang/wgsl/features",
         "${tint_src_dir}/lang/wgsl/program",
         "${tint_src_dir}/lang/wgsl/sem",
+        "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
         "${tint_src_dir}/utils/containers",
         "${tint_src_dir}/utils/diagnostic",
         "${tint_src_dir}/utils/ice",
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/BUILD.bazel b/src/tint/lang/wgsl/writer/ir_to_program/BUILD.bazel
index 812a463..1c5947a 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/BUILD.bazel
+++ b/src/tint/lang/wgsl/writer/ir_to_program/BUILD.bazel
@@ -43,6 +43,7 @@
   ],
   hdrs = [
     "ir_to_program.h",
+    "program_options.h",
   ],
   deps = [
     "//src/tint/api/common",
@@ -99,6 +100,8 @@
     "//src/tint/lang/core/type",
     "//src/tint/lang/wgsl",
     "//src/tint/lang/wgsl/ast",
+    "//src/tint/lang/wgsl/common",
+    "//src/tint/lang/wgsl/features",
     "//src/tint/lang/wgsl/intrinsic",
     "//src/tint/lang/wgsl/ir",
     "//src/tint/lang/wgsl/program",
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/BUILD.cmake b/src/tint/lang/wgsl/writer/ir_to_program/BUILD.cmake
index 6fd9f71..9828bc9 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/BUILD.cmake
+++ b/src/tint/lang/wgsl/writer/ir_to_program/BUILD.cmake
@@ -41,6 +41,7 @@
 tint_add_target(tint_lang_wgsl_writer_ir_to_program lib
   lang/wgsl/writer/ir_to_program/ir_to_program.cc
   lang/wgsl/writer/ir_to_program/ir_to_program.h
+  lang/wgsl/writer/ir_to_program/program_options.h
 )
 
 tint_target_add_dependencies(tint_lang_wgsl_writer_ir_to_program lib
@@ -92,6 +93,8 @@
   tint_lang_core_type
   tint_lang_wgsl
   tint_lang_wgsl_ast
+  tint_lang_wgsl_common
+  tint_lang_wgsl_features
   tint_lang_wgsl_intrinsic
   tint_lang_wgsl_ir
   tint_lang_wgsl_program
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/BUILD.gn b/src/tint/lang/wgsl/writer/ir_to_program/BUILD.gn
index ed032db..3f9583c 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/BUILD.gn
+++ b/src/tint/lang/wgsl/writer/ir_to_program/BUILD.gn
@@ -46,6 +46,7 @@
   sources = [
     "ir_to_program.cc",
     "ir_to_program.h",
+    "program_options.h",
   ]
   deps = [
     "${tint_src_dir}/api/common",
@@ -92,6 +93,8 @@
       "${tint_src_dir}/lang/core/type",
       "${tint_src_dir}/lang/wgsl",
       "${tint_src_dir}/lang/wgsl/ast",
+      "${tint_src_dir}/lang/wgsl/common",
+      "${tint_src_dir}/lang/wgsl/features",
       "${tint_src_dir}/lang/wgsl/intrinsic",
       "${tint_src_dir}/lang/wgsl/ir",
       "${tint_src_dir}/lang/wgsl/program",
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
index 9f83536..2d6b415 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
@@ -103,7 +103,7 @@
   public:
     explicit State(const core::ir::Module& m) : mod(m) {}
 
-    Program Run() {
+    Program Run(const ProgramOptions& options) {
         if (auto res = core::ir::Validate(mod); !res) {
             // IR module failed validation.
             b.Diagnostics() = res.Failure().reason;
@@ -116,7 +116,14 @@
         for (auto& fn : mod.functions) {
             Fn(fn);
         }
-        return Program{resolver::Resolve(b)};
+
+        if (options.allow_non_uniform_derivatives) {
+            // Suppress errors regarding non-uniform derivative operations if requested, by adding a
+            // diagnostic directive to the module.
+            b.DiagnosticDirective(wgsl::DiagnosticSeverity::kOff, "derivative_uniformity");
+        }
+
+        return Program{resolver::Resolve(b, options.allowed_features)};
     }
 
   private:
@@ -1230,8 +1237,8 @@
 
 }  // namespace
 
-Program IRToProgram(const core::ir::Module& i) {
-    return State{i}.Run();
+Program IRToProgram(const core::ir::Module& i, const ProgramOptions& options) {
+    return State{i}.Run(options);
 }
 
 }  // namespace tint::wgsl::writer
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h
index 089a1e7..cf53fb6 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h
@@ -29,6 +29,7 @@
 #define SRC_TINT_LANG_WGSL_WRITER_IR_TO_PROGRAM_IR_TO_PROGRAM_H_
 
 #include "src/tint/lang/wgsl/program/program.h"
+#include "src/tint/lang/wgsl/writer/ir_to_program/program_options.h"
 
 namespace tint::core::ir {
 class Module;
@@ -38,9 +39,10 @@
 
 /// Builds a tint::Program from an core::ir::Module
 /// @param module the IR module
+/// @param options the configuration options
 /// @return the tint::Program.
 /// @note Check the returned Program::Diagnostics() for any errors.
-Program IRToProgram(const core::ir::Module& module);
+Program IRToProgram(const core::ir::Module& module, const ProgramOptions& options = {});
 
 }  // namespace tint::wgsl::writer
 
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
index d034c0d..8dc95e1 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
@@ -48,7 +48,9 @@
 
     result.ir = tint::core::ir::Disassemble(mod);
 
-    auto output_program = IRToProgram(mod);
+    ProgramOptions options;
+    options.allowed_features = AllowedFeatures::Everything();
+    auto output_program = IRToProgram(mod, options);
     if (!output_program.IsValid()) {
         result.err = output_program.Diagnostics().str();
         result.ast = Program::printer(output_program);
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/program_options.h b/src/tint/lang/wgsl/writer/ir_to_program/program_options.h
new file mode 100644
index 0000000..1b6ed6f
--- /dev/null
+++ b/src/tint/lang/wgsl/writer/ir_to_program/program_options.h
@@ -0,0 +1,45 @@
+// Copyright 2023 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef SRC_TINT_LANG_WGSL_WRITER_IR_TO_PROGRAM_PROGRAM_OPTIONS_H_
+#define SRC_TINT_LANG_WGSL_WRITER_IR_TO_PROGRAM_PROGRAM_OPTIONS_H_
+
+#include "src/tint/lang/wgsl/common/allowed_features.h"
+
+namespace tint::wgsl::writer {
+
+/// Configuration options used for producing a WGSL program from an IR module.
+struct ProgramOptions {
+    /// Set to `true` to allow calls to derivative builtins in non-uniform control flow.
+    bool allow_non_uniform_derivatives = false;
+    /// The extensions and language features that are allowed to be used in the generated WGSL.
+    wgsl::AllowedFeatures allowed_features = {};
+};
+
+}  // namespace tint::wgsl::writer
+
+#endif  // SRC_TINT_LANG_WGSL_WRITER_IR_TO_PROGRAM_PROGRAM_OPTIONS_H_
diff --git a/src/tint/lang/wgsl/writer/writer.cc b/src/tint/lang/wgsl/writer/writer.cc
index a9ef260..6cc8422 100644
--- a/src/tint/lang/wgsl/writer/writer.cc
+++ b/src/tint/lang/wgsl/writer/writer.cc
@@ -67,13 +67,13 @@
     return output;
 }
 
-Result<Output> WgslFromIR(core::ir::Module& module) {
+Result<Output> WgslFromIR(core::ir::Module& module, const ProgramOptions& options) {
     // core-dialect -> WGSL-dialect
     if (auto res = Raise(module); !res) {
         return res.Failure();
     }
 
-    auto program = IRToProgram(module);
+    auto program = IRToProgram(module, options);
     if (!program.IsValid()) {
         return Failure{program.Diagnostics()};
     }
diff --git a/src/tint/lang/wgsl/writer/writer.h b/src/tint/lang/wgsl/writer/writer.h
index cb9124b..64a1525 100644
--- a/src/tint/lang/wgsl/writer/writer.h
+++ b/src/tint/lang/wgsl/writer/writer.h
@@ -30,6 +30,7 @@
 
 #include <string>
 
+#include "src/tint/lang/wgsl/writer/ir_to_program/program_options.h"
 #include "src/tint/lang/wgsl/writer/options.h"
 #include "src/tint/lang/wgsl/writer/output.h"
 #include "src/tint/utils/diagnostic/diagnostic.h"
@@ -54,8 +55,9 @@
 
 /// Generate WGSL from a core-dialect ir::Module.
 /// @param module the core-dialect ir::Module.
+/// @param options the configuration options to use when generating WGSL
 /// @returns the resulting WGSL, or failure
-Result<Output> WgslFromIR(core::ir::Module& module);
+Result<Output> WgslFromIR(core::ir::Module& module, const ProgramOptions& options);
 
 }  // namespace tint::wgsl::writer