diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2016-09-03 12:36:49 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2016-09-05 12:49:47 +0200 |
| commit | 852e3d2eae98a913b7ec91822ba4dc61059a6955 (patch) | |
| tree | 537da37cf1243927b86c2636746dc4520f2dcf87 /sys | |
| parent | c7aabee44051ae26b6dd7f5214557ed805391c25 (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.go | 6 | ||||
| -rw-r--r-- | sys/decl.go | 34 | ||||
| -rw-r--r-- | sys/sndseq.txt | 6 |
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 { |
