Skip to content

Commit 9e9b63d

Browse files
committed
ssa2pal: some work on tuples
tuples are weird, because they are not there at runtime and so should not occupy memory like structs do (which have their own distinct address). Previously, I had tried to make tuples not be associated with memory.Loc's nor objects. This is too complicated. This commit gives tuples their own address again. It also adds some safety code in objects.Builder: in order to ensure that the creation of a root compound object triggers object creation (and not just typed memory locations), we re-walk the object after creation and reconstruct the object from the pal representation. This walkObj method is still incomplete.
1 parent eb21ac3 commit 9e9b63d

File tree

7 files changed

+182
-8
lines changed

7 files changed

+182
-8
lines changed

memory/model.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,13 +234,14 @@ func (mod *Model) p_add(gp *GenParams, p, r Loc, sum *int) Loc {
234234
}
235235

236236
case typeset.Tuple:
237+
mod.locs = append(mod.locs, l)
238+
*sum++
237239
tn := gp.ts.NumFields(gp.typ)
238240
ttyp := gp.typ
239241
for i := 0; i < tn; i++ {
240242
_, gp.typ, _ = gp.ts.Field(ttyp, i)
241243
mod.p_add(gp, n, r, sum)
242244
}
243-
added = false
244245
case typeset.Named:
245246
gp.typ = gp.ts.Underlying(gp.typ)
246247
mod.p_add(gp, n, r, sum)

objects/builder.go

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package objects
1616

1717
import (
18+
"fmt"
1819
"go/token"
1920
"go/types"
2021

@@ -111,14 +112,16 @@ func (b *Builder) Struct(gty *types.Struct) *Struct {
111112
s.fields = make([]memory.Loc, 0, gty.NumFields())
112113
for i := memory.Loc(1); i < n; i++ {
113114
pfloc := b.mmod.Parent(s.loc + i)
114-
if pfloc == s.loc {
115-
s.fields = append(s.fields, s.loc+i)
115+
if pfloc != s.loc {
116+
continue
116117
}
118+
s.fields = append(s.fields, s.loc+i)
117119
}
118120
if len(s.fields) != gty.NumFields() {
119121
panic("internal error")
120122
}
121123
b.omap[s.loc] = s
124+
b.walkObj(s.loc)
122125
return s
123126
}
124127

@@ -130,6 +133,7 @@ func (b *Builder) Array(gty *types.Array) *Array {
130133
a.n = gty.Len()
131134
a.elemSize = int64(b.ts.Lsize(b.ts.Elem(a.typ)))
132135
b.omap[a.loc] = a
136+
b.walkObj(a.loc)
133137
return a
134138
}
135139

@@ -228,5 +232,86 @@ func (b *Builder) Func(sig *types.Signature, declName string, opaque memory.Attr
228232
// TBD: FreeVars
229233
b.omap[fn.loc] = fn
230234
return fn
235+
}
236+
237+
// second pass to associate objects with all object like memory locations...
238+
// the input is likely to just create roots at variables, but we need objects
239+
// everywhere...
240+
func (b *Builder) walkObj(m memory.Loc) {
241+
ty := b.mmod.Type(m)
242+
ki := b.ts.Kind(ty)
243+
switch ki {
244+
case typeset.Basic:
245+
switch ty {
246+
case typeset.Pointer:
247+
if b.omap[m] == nil {
248+
fmt.Printf("walk ptr\n")
249+
ptr := &Pointer{}
250+
ptr.loc = m
251+
ptr.typ = ty
252+
b.omap[m] = ptr
253+
}
254+
}
255+
case typeset.Array:
256+
var arr *Array
257+
obj := b.omap[m]
258+
if obj == nil {
259+
fmt.Printf("walk arr\n")
260+
arr = &Array{}
261+
arr.loc = m
262+
arr.typ = ty
263+
arr.n = int64(b.ts.ArrayLen(ty))
264+
arr.elemSize = int64(b.ts.Lsize(b.ts.Elem(ty)))
265+
b.omap[m] = arr
266+
} else {
267+
arr = obj.(*Array)
268+
}
269+
n := b.ts.ArrayLen(ty)
270+
for i := 0; i < n; i++ {
271+
elt := arr.At(i)
272+
b.walkObj(elt)
273+
}
231274

275+
case typeset.Struct:
276+
var strukt *Struct
277+
obj := b.omap[m]
278+
if obj == nil {
279+
fmt.Printf("walk str\n")
280+
strukt = &Struct{}
281+
strukt.loc = m
282+
strukt.typ = ty
283+
n := b.ts.NumFields(ty)
284+
strukt.fields = make([]memory.Loc, 0, n)
285+
for i := 0; i < n; i++ {
286+
_, _, foff := b.ts.Field(ty, i)
287+
strukt.fields[i] = m + memory.Loc(foff)
288+
b.walkObj(m + memory.Loc(foff))
289+
}
290+
b.omap[m] = strukt
291+
} else {
292+
strukt = obj.(*Struct)
293+
}
294+
295+
case typeset.Chan:
296+
case typeset.Map:
297+
var ma *Map
298+
obj := b.omap[m]
299+
if obj == nil {
300+
fmt.Printf("walk map\n")
301+
ma := &Map{}
302+
ma.loc = m
303+
ma.typ = ty
304+
b.omap[m] = ma
305+
} else {
306+
ma = obj.(*Map)
307+
}
308+
b.walkObj(ma.key)
309+
b.walkObj(ma.elem)
310+
case typeset.Slice:
311+
case typeset.Interface:
312+
case typeset.Func:
313+
case typeset.Named:
314+
case typeset.Tuple:
315+
316+
}
232317
}

objects/doc.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,13 @@
3838
// The second set of methods relates to creating locations, objects
3939
// and constraints. These are
4040
//
41-
// 1. Gen() generate a memory location.
42-
// 2. Add{Load,Store,Transfer,PointsTo}(dst, src)
41+
// 1. Builder.Gen() generate a memory location.
42+
// 2. Builder.Add{Load,Store,Transfer,PointsTo}(dst, src)
43+
// 3. Builder.{Struct,Array,Slice,Map,Func,Interface,Chan}
4344
//
4445
// The last set of methods gives access to the build results
4546
//
4647
// 1. Builder.Memory() *memory.Model
4748
// 2. Builder.TypeSet() *typeset.TypeSet
48-
//
49+
// 3. Builder.Object(m memory.Loc) Object (one of Struct,Array,Slice,Map,...)
4950
package objects

objects/tuple.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Copyright 2021 The pal authors (see AUTHORS)
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package objects
16+
17+
import (
18+
"io"
19+
20+
"github.com/go-air/pal/internal/plain"
21+
"github.com/go-air/pal/memory"
22+
)
23+
24+
type Tuple struct {
25+
object
26+
fields []memory.Loc
27+
}
28+
29+
func (t *Tuple) NumFields(i int) int {
30+
return len(t.fields)
31+
}
32+
33+
func (t *Tuple) Field(i int) memory.Loc {
34+
return t.fields[i]
35+
}
36+
37+
func (t *Tuple) PlainEncode(w io.Writer) error {
38+
var err error
39+
err = t.object.plainEncode(w)
40+
if err != nil {
41+
return err
42+
}
43+
for i := range t.fields {
44+
err = plain.Put(w, " ")
45+
if err != nil {
46+
return err
47+
}
48+
f := &t.fields[i]
49+
err = f.PlainEncode(w)
50+
if err != nil {
51+
return err
52+
}
53+
}
54+
return nil
55+
}
56+
57+
func (t *Tuple) PlainDecode(r io.Reader) error {
58+
obj := &t.object
59+
err := obj.plainDecode(r)
60+
if err != nil {
61+
return err
62+
}
63+
for i := range t.fields {
64+
err = plain.Expect(r, " ")
65+
if err != nil {
66+
return err
67+
}
68+
f := &t.fields[i]
69+
err = f.PlainDecode(r)
70+
if err != nil {
71+
return err
72+
}
73+
}
74+
return nil
75+
}

ssa2pal/t.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ func (p *T) genBlockValues(name string, blk *ssa.BasicBlock) {
215215
// genValueLoc may need to work recursively on struct and
216216
// array typed structured data.
217217
func (p *T) genValueLoc(v ssa.Value) memory.Loc {
218+
fmt.Printf("genValueLoc(%s)\n", v)
218219
p.buildr.Pos(v.Pos()).GoType(v.Type()).Class(memory.Local).Attrs(memory.NoAttrs)
219220
var res memory.Loc
220221
switch v := v.(type) {
@@ -274,6 +275,16 @@ func (p *T) genValueLoc(v ssa.Value) memory.Loc {
274275
p.buildr.AddLoad(res, qelt)
275276
}
276277
case *ssa.Extract:
278+
tloc := p.vmap[v.Tuple]
279+
if tloc == memory.NoLoc {
280+
tloc = p.genValueLoc(v.Tuple)
281+
// reset bld cfg for genLoc below
282+
p.buildr.Pos(v.Pos()).GoType(v.Type()).Class(memory.Local).Attrs(memory.NoAttrs)
283+
}
284+
t := p.buildr.Object(tloc).(*objects.Tuple)
285+
res = t.Field(v.Index)
286+
287+
//v.Tuple, v.Index
277288

278289
case *ssa.Const:
279290
return memory.NoLoc
@@ -451,6 +462,7 @@ func (p *T) invoke(c ssa.CallCommon) {
451462
func (p *T) putResults() {
452463
if debugLogModel {
453464
fmt.Printf("built pal model for %s\n", p.pkgres.PkgPath)
465+
p.buildr.TypeSet().PlainEncode(os.Stdout)
454466
p.buildr.Memory().PlainEncode(os.Stdout)
455467
}
456468
p.results.Put(p.pass.Pkg.Path(), p.pkgres)

typeset/gotypes.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ func (t *TypeSet) FromGoType(gotype types.Type) Type {
141141
case *types.Tuple:
142142
N := ty.Len()
143143
res := make([]named, N)
144-
off := 0
144+
off := 1
145145
for i := 0; i < N; i++ {
146146
at := ty.At(i)
147147
res[i].name = at.Name()

typeset/typeset.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ func (t *TypeSet) getSignature(recv Type, params, results []named, variadic bool
203203
func (t *TypeSet) getTuple(elts []named) Type {
204204
ty, node := t.newNode()
205205
node.kind = Tuple
206-
node.lsize = 0
206+
node.lsize = 1
207207
node.fields = elts
208208
for _, field := range elts {
209209
node.lsize += t.nodes[field.typ].lsize

0 commit comments

Comments
 (0)