diff options
| author | Dokyung Song <dokyungs@google.com> | 2018-09-06 15:49:23 -0700 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2018-09-11 13:01:53 +0200 |
| commit | 11c256cdcd601b67fcf5611fe8aed55b9ff00143 (patch) | |
| tree | 63bff88ba1faed749a2fddad2b22e8d56d5b9981 /pkg | |
| parent | e3d1d545d390055ca67987d27243e0d2b37feedd (diff) | |
sys/fuchsia: prune unused structs in syscall description generated by fidlgen
After generating syscall description for fidl files using fidlgen, prune
all unused structs using the exact same mechanism used by the compiler's
check for unused structs. This allows the FIDL compiler to support
modular compilation; it does not need to have global knowledge of
whether each struct is used or not.
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/ast/filter.go | 14 | ||||
| -rw-r--r-- | pkg/compiler/check.go | 75 | ||||
| -rw-r--r-- | pkg/compiler/compiler.go | 17 |
3 files changed, 71 insertions, 35 deletions
diff --git a/pkg/ast/filter.go b/pkg/ast/filter.go new file mode 100644 index 000000000..a36114e82 --- /dev/null +++ b/pkg/ast/filter.go @@ -0,0 +1,14 @@ +// Copyright 2018 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package ast + +func (desc *Description) Filter(predicate func(Node) bool) *Description { + desc1 := &Description{} + for _, n := range desc.Nodes { + if predicate(n) { + desc1.Nodes = append(desc1.Nodes, n.Clone()) + } + } + return desc1 +} diff --git a/pkg/compiler/check.go b/pkg/compiler/check.go index 7b4b63fa8..087075a12 100644 --- a/pkg/compiler/check.go +++ b/pkg/compiler/check.go @@ -11,6 +11,7 @@ import ( "github.com/google/syzkaller/pkg/ast" "github.com/google/syzkaller/prog" + "github.com/google/syzkaller/sys/targets" ) func (comp *compiler) typecheck() { @@ -371,6 +372,48 @@ func (comp *compiler) checkLenTarget(t *ast.Type, name, target string, fields [] comp.error(t.Pos, "%v target %v does not exist", t.Ident, target) } +func CollectUnused(desc *ast.Description, target *targets.Target) []ast.Node { + comp := createCompiler(desc, target, nil) + comp.typecheck() + return comp.collectUnused() +} + +func (comp *compiler) collectUnused() []ast.Node { + var unused []ast.Node + + comp.used, _, _ = comp.collectUsed(false) + structs, flags, strflags := comp.collectUsed(true) + _, _, _ = structs, flags, strflags + + for name, n := range comp.intFlags { + if !flags[name] { + unused = append(unused, n) + } + } + for name, n := range comp.strFlags { + if !strflags[name] && builtinStrFlags[name] == nil { + unused = append(unused, n) + } + } + for name, n := range comp.resources { + if !structs[name] { + unused = append(unused, n) + } + } + for name, n := range comp.structs { + if !structs[name] { + unused = append(unused, n) + } + } + for name, n := range comp.typedefs { + if !comp.usedTypedefs[name] { + unused = append(unused, n) + } + } + + return unused +} + func (comp *compiler) collectUsed(all bool) (structs, flags, strflags map[string]bool) { structs = make(map[string]bool) flags = make(map[string]bool) @@ -432,35 +475,9 @@ func (comp *compiler) collectUsedType(structs, flags, strflags map[string]bool, } func (comp *compiler) checkUnused() { - comp.used, _, _ = comp.collectUsed(false) - structs, flags, strflags := comp.collectUsed(true) - _, _, _ = structs, flags, strflags - - for name, n := range comp.intFlags { - if !flags[name] { - comp.error(n.Pos, "unused flags %v", name) - } - } - for name, n := range comp.strFlags { - if !strflags[name] && builtinStrFlags[name] == nil { - comp.error(n.Pos, "unused string flags %v", name) - } - } - for name, n := range comp.resources { - if !structs[name] { - comp.error(n.Pos, "unused resource %v", name) - } - } - for name, n := range comp.structs { - if !structs[name] { - _, typ, _ := n.Info() - comp.error(n.Pos, "unused %v %v", typ, name) - } - } - for name, n := range comp.typedefs { - if !comp.usedTypedefs[name] { - comp.error(n.Pos, "unused type %v", name) - } + for _, n := range comp.collectUnused() { + pos, typ, name := n.Info() + comp.error(pos, fmt.Sprintf("unused %v %v", typ, name)) } } diff --git a/pkg/compiler/compiler.go b/pkg/compiler/compiler.go index e66da802b..2c4e81b2b 100644 --- a/pkg/compiler/compiler.go +++ b/pkg/compiler/compiler.go @@ -43,13 +43,9 @@ type Prog struct { fileConsts map[string]*ConstInfo } -// Compile compiles sys description. -func Compile(desc *ast.Description, consts map[string]uint64, target *targets.Target, eh ast.ErrorHandler) *Prog { - if eh == nil { - eh = ast.LoggingHandler - } +func createCompiler(desc *ast.Description, target *targets.Target, eh ast.ErrorHandler) *compiler { comp := &compiler{ - desc: desc.Clone(), + desc: desc, target: target, eh: eh, ptrSize: target.PtrSize, @@ -72,6 +68,15 @@ func Compile(desc *ast.Description, consts map[string]uint64, target *targets.Ta for name, n := range builtinStrFlags { comp.strFlags[name] = n } + return comp +} + +// Compile compiles sys description. +func Compile(desc *ast.Description, consts map[string]uint64, target *targets.Target, eh ast.ErrorHandler) *Prog { + if eh == nil { + eh = ast.LoggingHandler + } + comp := createCompiler(desc.Clone(), target, eh) comp.typecheck() // The subsequent, more complex, checks expect basic validity of the tree, // in particular corrent number of type arguments. If there were errors, |
