aboutsummaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2016-09-03 12:36:49 +0200
committerDmitry Vyukov <dvyukov@google.com>2016-09-05 12:49:47 +0200
commit852e3d2eae98a913b7ec91822ba4dc61059a6955 (patch)
tree537da37cf1243927b86c2636746dc4520f2dcf87 /sys
parentc7aabee44051ae26b6dd7f5214557ed805391c25 (diff)
sys: support recursive structs
A struct can have a pointer to itself directly or indirectly. Currently it leads to inifinite recursion when generating descriptions. Fix this.
Diffstat (limited to 'sys')
-rw-r--r--sys/align.go6
-rw-r--r--sys/decl.go34
-rw-r--r--sys/sndseq.txt6
3 files changed, 30 insertions, 16 deletions
diff --git a/sys/align.go b/sys/align.go
index fdcbb5444..5e67f6175 100644
--- a/sys/align.go
+++ b/sys/align.go
@@ -17,12 +17,12 @@ func initAlign() {
case ArrayType:
t1.Type = rec(t1.Type)
t = t1
- case StructType:
+ case *StructType:
for i, f := range t1.Fields {
t1.Fields[i] = rec(f)
}
t = addAlignment(t1)
- case UnionType:
+ case *UnionType:
opts := make(map[string]bool)
for i, opt := range t1.Options {
if opts[opt.Name()] {
@@ -44,7 +44,7 @@ func initAlign() {
}
}
-func addAlignment(t StructType) Type {
+func addAlignment(t *StructType) Type {
if t.packed {
t.padded = true
return t
diff --git a/sys/decl.go b/sys/decl.go
index 41527e91f..a447948bc 100644
--- a/sys/decl.go
+++ b/sys/decl.go
@@ -275,7 +275,7 @@ type StructType struct {
align uintptr
}
-func (t StructType) Size() uintptr {
+func (t *StructType) Size() uintptr {
if !t.padded {
panic("struct is not padded yet")
}
@@ -286,7 +286,7 @@ func (t StructType) Size() uintptr {
return size
}
-func (t StructType) Align() uintptr {
+func (t *StructType) Align() uintptr {
if t.align != 0 {
return t.align // overrided by user attribute
}
@@ -305,7 +305,7 @@ type UnionType struct {
varlen bool
}
-func (t UnionType) Size() uintptr {
+func (t *UnionType) Size() uintptr {
if t.varlen {
panic("union size is not statically known")
}
@@ -318,7 +318,7 @@ func (t UnionType) Size() uintptr {
return size
}
-func (t UnionType) Align() uintptr {
+func (t *UnionType) Align() uintptr {
var align uintptr
for _, opt := range t.Options {
if a1 := opt.Align(); align < a1 {
@@ -353,6 +353,7 @@ func resourceCtors(kind []string, precise bool) []*Call {
// Find calls that produce the necessary resources.
var metas []*Call
// Recurse into arguments to see if there is an out/inout arg of necessary type.
+ seen := make(map[Type]bool)
var checkArg func(typ Type, dir Dir) bool
checkArg = func(typ Type, dir Dir) bool {
if resarg, ok := typ.(ResourceType); ok && dir != DirIn && isCompatibleResource(kind, resarg.Desc.Kind, precise) {
@@ -363,13 +364,21 @@ func resourceCtors(kind []string, precise bool) []*Call {
if checkArg(typ1.Type, dir) {
return true
}
- case StructType:
+ case *StructType:
+ if seen[typ1] {
+ return false // prune recursion via pointers to structs/unions
+ }
+ seen[typ1] = true
for _, fld := range typ1.Fields {
if checkArg(fld, dir) {
return true
}
}
- case UnionType:
+ case *UnionType:
+ if seen[typ1] {
+ return false // prune recursion via pointers to structs/unions
+ }
+ seen[typ1] = true
for _, opt := range typ1.Options {
if checkArg(opt, dir) {
return true
@@ -438,6 +447,7 @@ func isCompatibleResource(dst, src []string, precise bool) bool {
func (c *Call) InputResources() []ResourceType {
var resources []ResourceType
+ seen := make(map[Type]bool)
var checkArg func(typ Type, dir Dir)
checkArg = func(typ Type, dir Dir) {
switch typ1 := typ.(type) {
@@ -449,11 +459,19 @@ func (c *Call) InputResources() []ResourceType {
checkArg(typ1.Type, dir)
case PtrType:
checkArg(typ1.Type, typ1.Dir)
- case StructType:
+ case *StructType:
+ if seen[typ1] {
+ return // prune recursion via pointers to structs/unions
+ }
+ seen[typ1] = true
for _, fld := range typ1.Fields {
checkArg(fld, dir)
}
- case UnionType:
+ case *UnionType:
+ if seen[typ1] {
+ return // prune recursion via pointers to structs/unions
+ }
+ seen[typ1] = true
for _, opt := range typ1.Options {
checkArg(opt, dir)
}
diff --git a/sys/sndseq.txt b/sys/sndseq.txt
index 551e736ef..cffc3ae93 100644
--- a/sys/sndseq.txt
+++ b/sys/sndseq.txt
@@ -210,7 +210,6 @@ snd_seq_event_data [
quote snd_seq_ev_quote
]
-
snd_seq_ev_note {
chan int8
note int8
@@ -256,10 +255,7 @@ snd_seq_result {
snd_seq_ev_quote {
origin snd_seq_addr
val int16
-# TODO: this should be:
-# event ptr[in, snd_seq_event, opt]
-# but sysgen goes into inifite recursion.
- event buffer[in]
+ event ptr[in, snd_seq_event, opt]
} [packed]
snd_seq_queue_skew {