intrinsics.def: Support [[stage()]] decorations on overloads
Specifies that the overload can only be used in the specific stages.
Actually validating this with the IntrinsicTable is TODO.
Bug: tint:657
Bug: tint:832
Change-Id: I11ffefee22e5f26103f008b23d16066a2a3ba90d
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/53050
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@chromium.org>
Reviewed-by: David Neto <dneto@google.com>
diff --git a/tools/src/cmd/intrinsic-gen/ast/ast.go b/tools/src/cmd/intrinsic-gen/ast/ast.go
index e7000f3..8d1da0e 100644
--- a/tools/src/cmd/intrinsic-gen/ast/ast.go
+++ b/tools/src/cmd/intrinsic-gen/ast/ast.go
@@ -102,6 +102,7 @@
type FunctionDecl struct {
Source tok.Source
Name string
+ Decorations Decorations
TemplateParams TemplateParams
Parameters Parameters
ReturnType *TemplatedName
diff --git a/tools/src/cmd/intrinsic-gen/parser/parser.go b/tools/src/cmd/intrinsic-gen/parser/parser.go
index 8434305..4ab3516 100644
--- a/tools/src/cmd/intrinsic-gen/parser/parser.go
+++ b/tools/src/cmd/intrinsic-gen/parser/parser.go
@@ -43,20 +43,31 @@
func (p *parser) parse() (*ast.AST, error) {
out := ast.AST{}
+ var decorations ast.Decorations
for p.err == nil {
t := p.peek(0)
if t == nil {
break
}
switch t.Kind {
+ case tok.Ldeco:
+ decorations = append(decorations, p.decorations()...)
case tok.Enum:
+ if len(decorations) > 0 {
+ p.err = fmt.Errorf("%v unexpected decoration", decorations[0].Source)
+ }
out.Enums = append(out.Enums, p.enumDecl())
case tok.Match:
+ if len(decorations) > 0 {
+ p.err = fmt.Errorf("%v unexpected decoration", decorations[0].Source)
+ }
out.Matchers = append(out.Matchers, p.matcherDecl())
- case tok.Type, tok.Ldeco:
- out.Types = append(out.Types, p.typeDecl())
+ case tok.Type:
+ out.Types = append(out.Types, p.typeDecl(decorations))
+ decorations = nil
case tok.Function:
- out.Functions = append(out.Functions, p.functionDecl())
+ out.Functions = append(out.Functions, p.functionDecl(decorations))
+ decorations = nil
default:
p.err = fmt.Errorf("%v unexpected token '%v'", t.Source, t.Kind)
}
@@ -98,8 +109,7 @@
return m
}
-func (p *parser) typeDecl() ast.TypeDecl {
- decos := p.decorations()
+func (p *parser) typeDecl(decos ast.Decorations) ast.TypeDecl {
p.expect(tok.Type, "type declaration")
name := p.expect(tok.Identifier, "type name")
m := ast.TypeDecl{
@@ -143,10 +153,14 @@
return out
}
-func (p *parser) functionDecl() ast.FunctionDecl {
+func (p *parser) functionDecl(decos ast.Decorations) ast.FunctionDecl {
p.expect(tok.Function, "function declaration")
name := p.expect(tok.Identifier, "function name")
- f := ast.FunctionDecl{Source: name.Source, Name: string(name.Runes)}
+ f := ast.FunctionDecl{
+ Source: name.Source,
+ Decorations: decos,
+ Name: string(name.Runes),
+ }
if p.peekIs(0, tok.Lt) {
f.TemplateParams = p.templateParams()
}
diff --git a/tools/src/cmd/intrinsic-gen/parser/parser_test.go b/tools/src/cmd/intrinsic-gen/parser/parser_test.go
index 774dc0d..fdc884b 100644
--- a/tools/src/cmd/intrinsic-gen/parser/parser_test.go
+++ b/tools/src/cmd/intrinsic-gen/parser/parser_test.go
@@ -95,6 +95,14 @@
Name: "F",
}},
}},
+ {"[[deco]] fn F()", ast.AST{
+ Functions: []ast.FunctionDecl{{
+ Name: "F",
+ Decorations: ast.Decorations{
+ {Name: "deco"},
+ },
+ }},
+ }},
{"fn F(a)", ast.AST{
Functions: []ast.FunctionDecl{{
Name: "F",
diff --git a/tools/src/cmd/intrinsic-gen/resolver/resolve.go b/tools/src/cmd/intrinsic-gen/resolver/resolve.go
index 0f1a1e9..4f76f31 100644
--- a/tools/src/cmd/intrinsic-gen/resolver/resolve.go
+++ b/tools/src/cmd/intrinsic-gen/resolver/resolve.go
@@ -243,13 +243,43 @@
return err
}
- // Construct the semantic overload and append it to the function
+ // Construct the semantic overload
overload := &sem.Overload{
Decl: a,
Function: f,
Parameters: make([]sem.Parameter, len(a.Parameters)),
TemplateParams: templateParams,
}
+
+ // Process overload decorations
+ if stageDeco := a.Decorations.Take("stage"); stageDeco != nil {
+ for stageDeco != nil {
+ for _, stage := range stageDeco.Values {
+ switch stage {
+ case "vertex":
+ overload.CanBeUsedInStage.Vertex = true
+ case "fragment":
+ overload.CanBeUsedInStage.Fragment = true
+ case "compute":
+ overload.CanBeUsedInStage.Compute = true
+ default:
+ return fmt.Errorf("%v unknown stage '%v'", stageDeco.Source, stage)
+ }
+ }
+ stageDeco = a.Decorations.Take("stage")
+ }
+ } else {
+ overload.CanBeUsedInStage = sem.StageUses{
+ Vertex: true,
+ Fragment: true,
+ Compute: true,
+ }
+ }
+ if len(a.Decorations) != 0 {
+ return fmt.Errorf("%v unknown decoration", a.Decorations[0].Source)
+ }
+
+ // Append the overload to the function
f.Overloads = append(f.Overloads, overload)
// Sort the template parameters by resolved type. Append these to
diff --git a/tools/src/cmd/intrinsic-gen/sem/sem.go b/tools/src/cmd/intrinsic-gen/sem/sem.go
index b7b49c5..36548ae 100644
--- a/tools/src/cmd/intrinsic-gen/sem/sem.go
+++ b/tools/src/cmd/intrinsic-gen/sem/sem.go
@@ -129,13 +129,21 @@
// Overload describes a single overload of a function
type Overload struct {
- Decl ast.FunctionDecl
- Function *Function
- TemplateParams []TemplateParam
- OpenTypes []*TemplateTypeParam
- OpenNumbers []TemplateParam
- ReturnType *FullyQualifiedName
- Parameters []Parameter
+ Decl ast.FunctionDecl
+ Function *Function
+ TemplateParams []TemplateParam
+ OpenTypes []*TemplateTypeParam
+ OpenNumbers []TemplateParam
+ ReturnType *FullyQualifiedName
+ Parameters []Parameter
+ CanBeUsedInStage StageUses
+}
+
+// StageUses describes the stages an overload can be used in
+type StageUses struct {
+ Vertex bool
+ Fragment bool
+ Compute bool
}
// Format implements the fmt.Formatter interface