[tint][ir][val] Check for input ptr to workgroup in entry points

Also adds capability for MSL to bypass this check

Fixes: 415190405
Change-Id: I896d43043bc69a9fb71f21dd1471075ee8901ff4
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/240836
Auto-Submit: Ryan Harrison <rharrison@chromium.org>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: Ryan Harrison <rharrison@chromium.org>
diff --git a/src/tint/lang/core/ir/transform/remove_terminator_args.h b/src/tint/lang/core/ir/transform/remove_terminator_args.h
index e23a23d..42c948d 100644
--- a/src/tint/lang/core/ir/transform/remove_terminator_args.h
+++ b/src/tint/lang/core/ir/transform/remove_terminator_args.h
@@ -49,6 +49,7 @@
     core::ir::Capability::kAllowClipDistancesOnF32,
     core::ir::Capability::kAllowPrivateVarsInFunctions,
     core::ir::Capability::kAllowAnyLetType,
+    core::ir::Capability::kAllowWorkspacePointerInputToEntryPoint,
 };
 
 /// RemoveTerminatorArgs is a transform that removes all arguments from terminator instructions and
diff --git a/src/tint/lang/core/ir/transform/rename_conflicts.h b/src/tint/lang/core/ir/transform/rename_conflicts.h
index fd93e05..a5c02e5 100644
--- a/src/tint/lang/core/ir/transform/rename_conflicts.h
+++ b/src/tint/lang/core/ir/transform/rename_conflicts.h
@@ -49,6 +49,7 @@
     core::ir::Capability::kAllowClipDistancesOnF32,
     core::ir::Capability::kAllowPrivateVarsInFunctions,
     core::ir::Capability::kAllowAnyLetType,
+    core::ir::Capability::kAllowWorkspacePointerInputToEntryPoint,
 };
 
 /// RenameConflicts is a transform that renames declarations which prevent identifiers from
diff --git a/src/tint/lang/core/ir/transform/value_to_let.h b/src/tint/lang/core/ir/transform/value_to_let.h
index ac20d1d..105a3e1 100644
--- a/src/tint/lang/core/ir/transform/value_to_let.h
+++ b/src/tint/lang/core/ir/transform/value_to_let.h
@@ -49,6 +49,7 @@
     core::ir::Capability::kAllowClipDistancesOnF32,
     core::ir::Capability::kAllowPrivateVarsInFunctions,
     core::ir::Capability::kAllowAnyLetType,
+    core::ir::Capability::kAllowWorkspacePointerInputToEntryPoint,
 };
 
 /// Configuration for ValueToLet transform.
diff --git a/src/tint/lang/core/ir/validator.cc b/src/tint/lang/core/ir/validator.cc
index c759052..05b29da 100644
--- a/src/tint/lang/core/ir/validator.cc
+++ b/src/tint/lang/core/ir/validator.cc
@@ -2157,6 +2157,14 @@
             }
         }
 
+        if (!capabilities_.Contains(Capability::kAllowWorkspacePointerInputToEntryPoint) &&
+            func->IsEntryPoint()) {
+            if (mv && mv->Is<core::type::Pointer>() && address_space == AddressSpace::kWorkgroup) {
+                AddError(param) << "input param to entry point cannot be a ptr in the 'workgroup' "
+                                   "address space";
+            }
+        }
+
         scope_stack_.Add(param);
     }
 
diff --git a/src/tint/lang/core/ir/validator.h b/src/tint/lang/core/ir/validator.h
index 1ec3087..5cab735 100644
--- a/src/tint/lang/core/ir/validator.h
+++ b/src/tint/lang/core/ir/validator.h
@@ -67,6 +67,9 @@
     /// Allows input_attachment_index to be associated with any type, used by
     /// SPIRV backend for spirv.image.
     kAllowAnyInputAttachmentIndexType,
+    /// Allows workgroup address space pointers as entry point inputs. Used by
+    /// the MSL backend.
+    kAllowWorkspacePointerInputToEntryPoint,
 };
 
 /// Capabilities is a set of Capability
diff --git a/src/tint/lang/core/ir/validator_function_test.cc b/src/tint/lang/core/ir/validator_function_test.cc
index ce53b0c..0eafdec 100644
--- a/src/tint/lang/core/ir/validator_function_test.cc
+++ b/src/tint/lang/core/ir/validator_function_test.cc
@@ -330,7 +330,7 @@
 
     b.Append(f->Block(), [&] { b.Return(f); });
 
-    auto res = ir::Validate(mod);
+    auto res = ir::Validate(mod, Capabilities{Capability::kAllowWorkspacePointerInputToEntryPoint});
     ASSERT_NE(res, Success);
     EXPECT_THAT(
         res.Failure().reason,
@@ -1103,4 +1103,22 @@
 )")) << res.Failure();
 }
 
+TEST_F(IR_ValidatorTest, Function_EntryPoint_PtrToWorkgroup) {
+    auto* f = FragmentEntryPoint();
+    auto* p = b.FunctionParam("invalid", ty.ptr<workgroup, i32>());
+    f->AppendParam(p);
+
+    b.Append(f->Block(), [&] { b.Unreachable(); });
+
+    auto res = ir::Validate(mod);
+    ASSERT_NE(res, Success);
+    EXPECT_THAT(
+        res.Failure().reason,
+        testing::HasSubstr(
+            R"(:1:21 error: input param to entry point cannot be a ptr in the 'workgroup' address space
+%f = @fragment func(%invalid:ptr<workgroup, i32, read_write>):void {
+                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+)")) << res.Failure();
+}
+
 }  // namespace tint::core::ir
diff --git a/src/tint/lang/msl/writer/printer/printer.cc b/src/tint/lang/msl/writer/printer/printer.cc
index da02455..4c30a13 100644
--- a/src/tint/lang/msl/writer/printer/printer.cc
+++ b/src/tint/lang/msl/writer/printer/printer.cc
@@ -133,6 +133,7 @@
                 core::ir::Capability::kAllowPointersAndHandlesInStructures,
                 core::ir::Capability::kAllowPrivateVarsInFunctions,
                 core::ir::Capability::kAllowAnyLetType,
+                core::ir::Capability::kAllowWorkspacePointerInputToEntryPoint,
             });
         if (valid != Success) {
             return std::move(valid.Failure());
diff --git a/src/tint/lang/msl/writer/raise/binary_polyfill.cc b/src/tint/lang/msl/writer/raise/binary_polyfill.cc
index 2a60aad..3844a78 100644
--- a/src/tint/lang/msl/writer/raise/binary_polyfill.cc
+++ b/src/tint/lang/msl/writer/raise/binary_polyfill.cc
@@ -161,6 +161,7 @@
                                     core::ir::Capability::kAllowPointersAndHandlesInStructures,
                                     core::ir::Capability::kAllowPrivateVarsInFunctions,
                                     core::ir::Capability::kAllowAnyLetType,
+                                    core::ir::Capability::kAllowWorkspacePointerInputToEntryPoint,
                                 });
     if (result != Success) {
         return result.Failure();
diff --git a/src/tint/lang/msl/writer/raise/builtin_polyfill.cc b/src/tint/lang/msl/writer/raise/builtin_polyfill.cc
index e050824..26b2d09 100644
--- a/src/tint/lang/msl/writer/raise/builtin_polyfill.cc
+++ b/src/tint/lang/msl/writer/raise/builtin_polyfill.cc
@@ -1065,6 +1065,7 @@
                                     core::ir::Capability::kAllowPointersAndHandlesInStructures,
                                     core::ir::Capability::kAllowPrivateVarsInFunctions,
                                     core::ir::Capability::kAllowAnyLetType,
+                                    core::ir::Capability::kAllowWorkspacePointerInputToEntryPoint,
                                 });
     if (result != Success) {
         return result.Failure();
diff --git a/src/tint/lang/msl/writer/raise/module_scope_vars.cc b/src/tint/lang/msl/writer/raise/module_scope_vars.cc
index 8585fa6..b17f8ba 100644
--- a/src/tint/lang/msl/writer/raise/module_scope_vars.cc
+++ b/src/tint/lang/msl/writer/raise/module_scope_vars.cc
@@ -341,7 +341,9 @@
 }  // namespace
 
 Result<SuccessType> ModuleScopeVars(core::ir::Module& ir) {
-    auto result = ValidateAndDumpIfNeeded(ir, "msl.ModuleScopeVars");
+    auto result = ValidateAndDumpIfNeeded(
+        ir, "msl.ModuleScopeVars",
+        core::ir::Capabilities{core::ir::Capability::kAllowWorkspacePointerInputToEntryPoint});
     if (result != Success) {
         return result.Failure();
     }
diff --git a/src/tint/lang/msl/writer/raise/module_scope_vars_test.cc b/src/tint/lang/msl/writer/raise/module_scope_vars_test.cc
index 5a98729..37cc4f2 100644
--- a/src/tint/lang/msl/writer/raise/module_scope_vars_test.cc
+++ b/src/tint/lang/msl/writer/raise/module_scope_vars_test.cc
@@ -45,7 +45,8 @@
     void SetUp() override {
         capabilities.Add(core::ir::Capability::kAllowPointersAndHandlesInStructures,
                          core::ir::Capability::kAllowPrivateVarsInFunctions,
-                         core::ir::Capability::kAllowAnyLetType);
+                         core::ir::Capability::kAllowAnyLetType,
+                         core::ir::Capability::kAllowWorkspacePointerInputToEntryPoint);
     }
 };
 
@@ -494,7 +495,6 @@
   }
 }
 )";
-
     Run(ModuleScopeVars);
 
     EXPECT_EQ(expect, str());
diff --git a/src/tint/lang/msl/writer/raise/unary_polyfill.cc b/src/tint/lang/msl/writer/raise/unary_polyfill.cc
index c28fab3..2261207 100644
--- a/src/tint/lang/msl/writer/raise/unary_polyfill.cc
+++ b/src/tint/lang/msl/writer/raise/unary_polyfill.cc
@@ -92,6 +92,7 @@
                                     core::ir::Capability::kAllowPointersAndHandlesInStructures,
                                     core::ir::Capability::kAllowPrivateVarsInFunctions,
                                     core::ir::Capability::kAllowAnyLetType,
+                                    core::ir::Capability::kAllowWorkspacePointerInputToEntryPoint,
                                 });
     if (result != Success) {
         return result.Failure();
diff --git a/src/tint/lang/msl/writer/writer_fuzz.cc b/src/tint/lang/msl/writer/writer_fuzz.cc
index 3cc687e..aa5a905 100644
--- a/src/tint/lang/msl/writer/writer_fuzz.cc
+++ b/src/tint/lang/msl/writer/writer_fuzz.cc
@@ -77,4 +77,6 @@
 }  // namespace
 }  // namespace tint::msl::writer
 
-TINT_IR_MODULE_FUZZER(tint::msl::writer::IRFuzzer, tint::core::ir::Capabilities{});
+TINT_IR_MODULE_FUZZER(tint::msl::writer::IRFuzzer,
+                      tint::core::ir::Capabilities{
+                          tint::core::ir::Capability::kAllowWorkspacePointerInputToEntryPoint});