aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/compiler
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-09-15 14:15:52 +0200
committerDmitry Vyukov <dvyukov@google.com>2017-09-15 16:02:37 +0200
commit66393d1884cb6a6d36dcbe5ad772ae9cf8f2adad (patch)
treea8747f057372ed2e2a451a0c0988b99f70a012dc /pkg/compiler
parent4f60e46e498eedc0d9407d11d1078208c37d19f1 (diff)
pkg/compiler: don't genererate missing syscalls
We used to generate them only because manager had no idea what arch it is testing. So syscalls numbers had to match between all arches. This is not needed anymore. Also don't generate unreferenced structs/resources.
Diffstat (limited to 'pkg/compiler')
-rw-r--r--pkg/compiler/check.go52
-rw-r--r--pkg/compiler/compiler.go2
-rw-r--r--pkg/compiler/consts.go21
-rw-r--r--pkg/compiler/gen.go19
-rw-r--r--pkg/compiler/testdata/errors2.txt3
5 files changed, 70 insertions, 27 deletions
diff --git a/pkg/compiler/check.go b/pkg/compiler/check.go
index 99ac1d447..5fefeaf68 100644
--- a/pkg/compiler/check.go
+++ b/pkg/compiler/check.go
@@ -22,6 +22,7 @@ func (comp *compiler) check() {
if comp.errors != 0 {
return
}
+ comp.checkUsed()
comp.checkRecursion()
comp.checkLenTargets()
comp.checkConstructors()
@@ -230,6 +231,52 @@ 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 (comp *compiler) checkUsed() {
+ for _, decl := range comp.desc.Nodes {
+ switch n := decl.(type) {
+ case *ast.Call:
+ if n.NR == ^uint64(0) {
+ break
+ }
+ for _, arg := range n.Args {
+ comp.checkUsedType(arg.Type, true)
+ }
+ if n.Ret != nil {
+ comp.checkUsedType(n.Ret, true)
+ }
+ }
+ }
+}
+
+func (comp *compiler) checkUsedType(t *ast.Type, isArg bool) {
+ if comp.used[t.Ident] {
+ return
+ }
+ desc := comp.getTypeDesc(t)
+ if desc == typeResource {
+ r := comp.resources[t.Ident]
+ for r != nil && !comp.used[r.Name.Name] {
+ comp.used[r.Name.Name] = true
+ r = comp.resources[r.Base.Ident]
+ }
+ return
+ }
+ if desc == typeStruct {
+ comp.used[t.Ident] = true
+ s := comp.structs[t.Ident]
+ for _, fld := range s.Fields {
+ comp.checkUsedType(fld.Type, false)
+ }
+ return
+ }
+ _, args, _ := comp.getArgsBase(t, "", prog.DirIn, isArg)
+ for i, arg := range args {
+ if desc.Args[i].Type == typeArgType {
+ comp.checkUsedType(arg, false)
+ }
+ }
+}
+
type structDir struct {
Struct string
Dir prog.Dir
@@ -252,10 +299,11 @@ func (comp *compiler) checkConstructors() {
for _, decl := range comp.desc.Nodes {
switch n := decl.(type) {
case *ast.Resource:
- if !ctors[n.Name.Name] {
+ name := n.Name.Name
+ if !ctors[name] && comp.used[name] {
comp.error(n.Pos, "resource %v can't be created"+
" (never mentioned as a syscall return value or output argument/field)",
- n.Name.Name)
+ name)
}
}
}
diff --git a/pkg/compiler/compiler.go b/pkg/compiler/compiler.go
index f6641f9c9..d54ac4678 100644
--- a/pkg/compiler/compiler.go
+++ b/pkg/compiler/compiler.go
@@ -54,6 +54,7 @@ func Compile(desc *ast.Description, consts map[string]uint64, ptrSize uint64, eh
structs: make(map[string]*ast.Struct),
intFlags: make(map[string]*ast.IntFlags),
strFlags: make(map[string]*ast.StrFlags),
+ used: make(map[string]bool),
structDescs: make(map[prog.StructKey]*prog.StructDesc),
structNodes: make(map[*prog.StructDesc]*ast.Struct),
structVarlen: make(map[string]bool),
@@ -88,6 +89,7 @@ type compiler struct {
structs map[string]*ast.Struct
intFlags map[string]*ast.IntFlags
strFlags map[string]*ast.StrFlags
+ used map[string]bool // contains used structs/resources
structDescs map[prog.StructKey]*prog.StructDesc
structNodes map[*prog.StructDesc]*ast.Struct
diff --git a/pkg/compiler/consts.go b/pkg/compiler/consts.go
index 44c0c4f18..f64f4ed7f 100644
--- a/pkg/compiler/consts.go
+++ b/pkg/compiler/consts.go
@@ -128,26 +128,18 @@ func (comp *compiler) assignSyscallNumbers(consts map[string]uint64) {
// Lookup in consts.
str := "__NR_" + c.CallName
nr, ok := consts[str]
+ top = append(top, decl)
if ok {
c.NR = nr
- top = append(top, decl)
continue
}
+ c.NR = ^uint64(0) // mark as unused to not generate it
name := "syscall " + c.CallName
if !comp.unsupported[name] {
comp.unsupported[name] = true
comp.warning(c.Pos, "unsupported syscall: %v due to missing const %v",
c.CallName, str)
}
- // TODO: we still have to preserve the syscall.
- // The problem is that manager and fuzzer use syscall indexes
- // to communicate enabled syscalls. If manager is built for
- // amd64 and fuzzer for arm64, then they would have different
- // sets of syscalls and would not agree on syscall indexes.
- // Remove this once we have proper cross-OS/arch support.
- // The same happens in patchConsts.
- c.NR = ^uint64(0)
- top = append(top, decl)
case *ast.IntFlags, *ast.Resource, *ast.Struct, *ast.StrFlags:
top = append(top, decl)
case *ast.NewLine, *ast.Comment, *ast.Include, *ast.Incdir, *ast.Define:
@@ -214,12 +206,9 @@ func (comp *compiler) patchConsts(consts map[string]uint64) {
}
// We have to keep partially broken resources and structs,
// because otherwise their usages will error.
- if c, ok := decl.(*ast.Call); !ok {
- top = append(top, decl)
- } else {
- // See comment in assignSyscallNumbers.
- c.NR = ^uint64(0)
- top = append(top, decl)
+ top = append(top, decl)
+ if c, ok := decl.(*ast.Call); ok {
+ c.NR = ^uint64(0) // mark as unused to not generate it
}
}
}
diff --git a/pkg/compiler/gen.go b/pkg/compiler/gen.go
index eeeed011c..b91080db2 100644
--- a/pkg/compiler/gen.go
+++ b/pkg/compiler/gen.go
@@ -15,10 +15,11 @@ const sizeUnassigned = ^uint64(0)
func (comp *compiler) genResources() []*prog.ResourceDesc {
var resources []*prog.ResourceDesc
- for _, decl := range comp.desc.Nodes {
- if n, ok := decl.(*ast.Resource); ok {
- resources = append(resources, comp.genResource(n))
+ for name, n := range comp.resources {
+ if !comp.used[name] {
+ continue
}
+ resources = append(resources, comp.genResource(n))
}
sort.Slice(resources, func(i, j int) bool {
return resources[i].Name < resources[j].Name
@@ -47,7 +48,7 @@ func (comp *compiler) genResource(n *ast.Resource) *prog.ResourceDesc {
func (comp *compiler) genSyscalls() []*prog.Syscall {
var calls []*prog.Syscall
for _, decl := range comp.desc.Nodes {
- if n, ok := decl.(*ast.Call); ok {
+ if n, ok := decl.(*ast.Call); ok && n.NR != ^uint64(0) {
calls = append(calls, comp.genSyscall(n))
}
}
@@ -101,10 +102,12 @@ func (comp *compiler) genStructDescs(syscalls []*prog.Syscall) []*prog.KeyedStru
return false
}
}
- structs = append(structs, &prog.KeyedStruct{
- Key: key,
- Desc: desc,
- })
+ if comp.used[key.Name] {
+ structs = append(structs, &prog.KeyedStruct{
+ Key: key,
+ Desc: desc,
+ })
+ }
return true
}
rec = func(t0 prog.Type) {
diff --git a/pkg/compiler/testdata/errors2.txt b/pkg/compiler/testdata/errors2.txt
index 30dd728a2..0292aca5e 100644
--- a/pkg/compiler/testdata/errors2.txt
+++ b/pkg/compiler/testdata/errors2.txt
@@ -75,7 +75,8 @@ resource r105[int8]
resource r106[int8] ### resource r106 can't be created (never mentioned as a syscall return value or output argument/field)
resource r107[int8] ### resource r107 can't be created (never mentioned as a syscall return value or output argument/field)
-foo$300(a ptr[out, array[r103]], b ptr[in, s300], c r107) r104
+foo$300(a r100)
+foo$301(a ptr[out, array[r103]], b ptr[in, s300], c r107) r104
s300 {
f1 ptr[inout, s301]