intrinsic-gen: Support decorations on enum entries

Add `[[internal]]` decoration on `storage_class.handle` - its not an entry that should ever appear in WGSL.

Bug: tint:832
Change-Id: I210f64c495bf37a8f48422919248806e7b096638
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/53045
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: David Neto <dneto@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/intrinsics.def b/src/intrinsics.def
index bb5d08e..40a9d88 100644
--- a/src/intrinsics.def
+++ b/src/intrinsics.def
@@ -30,7 +30,7 @@
   workgroup
   uniform
   storage
-  handle
+  [[internal]] handle
 }
 
 // https://gpuweb.github.io/gpuweb/wgsl/#memory-access-mode
diff --git a/tools/src/cmd/intrinsic-gen/ast/ast.go b/tools/src/cmd/intrinsic-gen/ast/ast.go
index 75133d4..e7000f3 100644
--- a/tools/src/cmd/intrinsic-gen/ast/ast.go
+++ b/tools/src/cmd/intrinsic-gen/ast/ast.go
@@ -56,18 +56,34 @@
 type EnumDecl struct {
 	Source  tok.Source
 	Name    string
-	Entries []string
+	Entries []EnumEntry
 }
 
 // Format implements the fmt.Formatter interface
 func (e EnumDecl) Format(w fmt.State, verb rune) {
 	fmt.Fprintf(w, "enum %v {\n", e.Name)
 	for _, e := range e.Entries {
-		fmt.Fprintf(w, "  %s\n", e)
+		fmt.Fprintf(w, "  %v\n", e)
 	}
 	fmt.Fprintf(w, "}\n")
 }
 
+// EnumEntry describes an entry in a enumerator
+type EnumEntry struct {
+	Source      tok.Source
+	Name        string
+	Decorations Decorations
+}
+
+// Format implements the fmt.Formatter interface
+func (e EnumEntry) Format(w fmt.State, verb rune) {
+	if len(e.Decorations) > 0 {
+		fmt.Fprintf(w, "%v %v", e.Decorations, e.Name)
+	} else {
+		fmt.Fprint(w, e.Name)
+	}
+}
+
 // MatcherDecl describes a matcher declaration
 type MatcherDecl struct {
 	Source  tok.Source
diff --git a/tools/src/cmd/intrinsic-gen/parser/parser.go b/tools/src/cmd/intrinsic-gen/parser/parser.go
index 861e6f4..8434305 100644
--- a/tools/src/cmd/intrinsic-gen/parser/parser.go
+++ b/tools/src/cmd/intrinsic-gen/parser/parser.go
@@ -73,11 +73,17 @@
 	e := ast.EnumDecl{Source: name.Source, Name: string(name.Runes)}
 	p.expect(tok.Lbrace, "enum declaration")
 	for p.err == nil && p.match(tok.Rbrace) == nil {
-		e.Entries = append(e.Entries, p.ident("enumerator value"))
+		e.Entries = append(e.Entries, p.enumEntry())
 	}
 	return e
 }
 
+func (p *parser) enumEntry() ast.EnumEntry {
+	decos := p.decorations()
+	name := p.expect(tok.Identifier, "enum entry")
+	return ast.EnumEntry{Source: name.Source, Decorations: decos, Name: string(name.Runes)}
+}
+
 func (p *parser) matcherDecl() ast.MatcherDecl {
 	p.expect(tok.Match, "matcher declaration")
 	name := p.expect(tok.Identifier, "matcher name")
diff --git a/tools/src/cmd/intrinsic-gen/parser/parser_test.go b/tools/src/cmd/intrinsic-gen/parser/parser_test.go
index dddb166..774dc0d 100644
--- a/tools/src/cmd/intrinsic-gen/parser/parser_test.go
+++ b/tools/src/cmd/intrinsic-gen/parser/parser_test.go
@@ -31,10 +31,17 @@
 		{"enum E {}", ast.AST{
 			Enums: []ast.EnumDecl{{Name: "E"}},
 		}},
-		{"enum E { A B C }", ast.AST{
+		{"enum E { A [[deco]] B C }", ast.AST{
 			Enums: []ast.EnumDecl{{
-				Name:    "E",
-				Entries: []string{"A", "B", "C"},
+				Name: "E",
+				Entries: []ast.EnumEntry{
+					{Name: "A"},
+					{
+						Decorations: ast.Decorations{{Name: "deco"}},
+						Name:        "B",
+					},
+					{Name: "C"},
+				},
 			}},
 		}},
 		{"type T", ast.AST{
diff --git a/tools/src/cmd/intrinsic-gen/resolver/resolve.go b/tools/src/cmd/intrinsic-gen/resolver/resolve.go
index 1798d0d..05d14e1 100644
--- a/tools/src/cmd/intrinsic-gen/resolver/resolve.go
+++ b/tools/src/cmd/intrinsic-gen/resolver/resolve.go
@@ -90,9 +90,18 @@
 	// Register each of the enum entries
 	for _, ast := range e.Entries {
 		entry := &sem.EnumEntry{
-			Name: ast,
+			Name: ast.Name,
 			Enum: s,
 		}
+		if internal := ast.Decorations.Take("internal"); internal != nil {
+			entry.IsInternal = true
+			if len(internal.Values) != 0 {
+				return fmt.Errorf("%v unexpected value for internal decoration", ast.Source)
+			}
+		}
+		if len(ast.Decorations) != 0 {
+			return fmt.Errorf("%v unknown decoration", ast.Decorations[0].Source)
+		}
 		if err := r.globals.declare(entry, e.Source); err != nil {
 			return err
 		}
diff --git a/tools/src/cmd/intrinsic-gen/sem/sem.go b/tools/src/cmd/intrinsic-gen/sem/sem.go
index 1a615fe..cb8f383 100644
--- a/tools/src/cmd/intrinsic-gen/sem/sem.go
+++ b/tools/src/cmd/intrinsic-gen/sem/sem.go
@@ -63,8 +63,9 @@
 
 // EnumEntry is an entry in an enumerator
 type EnumEntry struct {
-	Enum *Enum
-	Name string
+	Enum       *Enum
+	Name       string
+	IsInternal bool // True if this entry is not part of the WGSL grammar
 }
 
 // Type declares a type