Parse num_workgroups builtin and reject it

We have chosen not to implement this for origin trial, so just parse
it and produce an error in the validator.

Bug: tint:752
Change-Id: I40ebf0b4051fb0b8bab9d4c733e555b836320cd4
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/58780
Auto-Submit: James Price <jrprice@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/ast/builtin.cc b/src/ast/builtin.cc
index 3e49d14..e0f8ecc 100644
--- a/src/ast/builtin.cc
+++ b/src/ast/builtin.cc
@@ -59,6 +59,10 @@
       out << "workgroup_id";
       break;
     }
+    case Builtin::kNumWorkgroups: {
+      out << "num_workgroups";
+      break;
+    }
     case Builtin::kSampleIndex: {
       out << "sample_index";
       break;
diff --git a/src/ast/builtin.h b/src/ast/builtin.h
index e5092c8..3e03148 100644
--- a/src/ast/builtin.h
+++ b/src/ast/builtin.h
@@ -32,6 +32,7 @@
   kLocalInvocationIndex,
   kGlobalInvocationId,
   kWorkgroupId,
+  kNumWorkgroups,
   kSampleIndex,
   kSampleMask,
 
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index 7318b37..99e5de9 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -98,6 +98,9 @@
   if (str == "workgroup_id") {
     return ast::Builtin::kWorkgroupId;
   }
+  if (str == "num_workgroups") {
+    return ast::Builtin::kNumWorkgroups;
+  }
   if (str == "sample_index") {
     return ast::Builtin::kSampleIndex;
   }
diff --git a/src/reader/wgsl/parser_impl_variable_decoration_test.cc b/src/reader/wgsl/parser_impl_variable_decoration_test.cc
index b3fd05a..a805f6b 100644
--- a/src/reader/wgsl/parser_impl_variable_decoration_test.cc
+++ b/src/reader/wgsl/parser_impl_variable_decoration_test.cc
@@ -119,6 +119,7 @@
                     ast::Builtin::kLocalInvocationIndex},
         BuiltinData{"global_invocation_id", ast::Builtin::kGlobalInvocationId},
         BuiltinData{"workgroup_id", ast::Builtin::kWorkgroupId},
+        BuiltinData{"num_workgroups", ast::Builtin::kNumWorkgroups},
         BuiltinData{"sample_index", ast::Builtin::kSampleIndex},
         BuiltinData{"sample_mask", ast::Builtin::kSampleMask}));
 
diff --git a/src/resolver/resolver.cc b/src/resolver/resolver.cc
index 492026c..374f99b 100644
--- a/src/resolver/resolver.cc
+++ b/src/resolver/resolver.cc
@@ -1333,6 +1333,10 @@
         return false;
       }
       break;
+    case ast::Builtin::kNumWorkgroups:
+      // TODO(crbug.com/tint/752): Backend support (needs extra work for HLSL).
+      AddError("num_workgroups builtin is not yet implemented", deco->source());
+      return false;
     default:
       break;
   }
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc
index 039269f..b666345 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -4075,6 +4075,8 @@
       return SpvBuiltInPointSize;
     case ast::Builtin::kWorkgroupId:
       return SpvBuiltInWorkgroupId;
+    case ast::Builtin::kNumWorkgroups:
+      return SpvBuiltInNumWorkgroups;
     case ast::Builtin::kSampleIndex:
       push_capability(SpvCapabilitySampleRateShading);
       return SpvBuiltInSampleId;
diff --git a/src/writer/spirv/builder_global_variable_test.cc b/src/writer/spirv/builder_global_variable_test.cc
index d744996..d3e111e 100644
--- a/src/writer/spirv/builder_global_variable_test.cc
+++ b/src/writer/spirv/builder_global_variable_test.cc
@@ -329,6 +329,8 @@
                     ast::StorageClass::kInput, SpvBuiltInGlobalInvocationId},
         BuiltinData{ast::Builtin::kWorkgroupId, ast::StorageClass::kInput,
                     SpvBuiltInWorkgroupId},
+        BuiltinData{ast::Builtin::kNumWorkgroups, ast::StorageClass::kInput,
+                    SpvBuiltInNumWorkgroups},
         BuiltinData{ast::Builtin::kSampleIndex, ast::StorageClass::kInput,
                     SpvBuiltInSampleId},
         BuiltinData{ast::Builtin::kSampleMask, ast::StorageClass::kInput,