diff options
| author | Michel Lespinasse <walken@google.com> | 2016-03-17 06:18:13 -0700 |
|---|---|---|
| committer | Michel Lespinasse <walken@google.com> | 2016-03-29 02:18:03 +0000 |
| commit | f00bbd5f818f0a6b5b2fcf15422ad7fc4594225f (patch) | |
| tree | d9acbc080dad0f5fe9549e36638318141b714494 /src/cmd | |
| parent | 7043d2bb5e8275df308abe9a2367fb1622be0313 (diff) | |
| download | go-f00bbd5f818f0a6b5b2fcf15422ad7fc4594225f.tar.xz | |
cmd/compile: emit itabs and itablinks
See #14874
This change tells the compiler to emit itab and itablink symbols in
situations where they could be useful; however the compiled code does
not actually make use of the new symbols yet.
Change-Id: I0db3e6ec0cb1f3b7cebd4c60229e4a48372fe586
Reviewed-on: https://go-review.googlesource.com/20888
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Run-TryBot: Michel Lespinasse <walken@google.com>
Diffstat (limited to 'src/cmd')
| -rw-r--r-- | src/cmd/compile/internal/gc/go.go | 4 | ||||
| -rw-r--r-- | src/cmd/compile/internal/gc/main.go | 9 | ||||
| -rw-r--r-- | src/cmd/compile/internal/gc/reflect.go | 53 | ||||
| -rw-r--r-- | src/cmd/compile/internal/gc/walk.go | 4 |
4 files changed, 64 insertions, 6 deletions
diff --git a/src/cmd/compile/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go index 448a0fd322..5925208514 100644 --- a/src/cmd/compile/internal/gc/go.go +++ b/src/cmd/compile/internal/gc/go.go @@ -250,6 +250,10 @@ var importpkg *Pkg // package being imported var itabpkg *Pkg // fake pkg for itab cache +var itab2pkg *Pkg // fake pkg for itab entries + +var itablinkpkg *Pkg // fake package for runtime itab entries + var Runtimepkg *Pkg // package runtime var racepkg *Pkg // package runtime/race diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 09b433d7f2..5c5e5acdff 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -124,14 +124,21 @@ func Main() { // pseudo-packages used in symbol tables itabpkg = mkpkg("go.itab") - itabpkg.Name = "go.itab" itabpkg.Prefix = "go.itab" // not go%2eitab + itab2pkg = mkpkg("go.itab2") + itab2pkg.Name = "go.itab2" + itab2pkg.Prefix = "go.itab2" // not go%2eitab2 + typelinkpkg = mkpkg("go.typelink") typelinkpkg.Name = "go.typelink" typelinkpkg.Prefix = "go.typelink" // not go%2etypelink + itablinkpkg = mkpkg("go.itablink") + itablinkpkg.Name = "go.itablink" + itablinkpkg.Prefix = "go.itablink" // not go%2eitablink + trackpkg = mkpkg("go.track") trackpkg.Name = "go.track" diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go index 4239d4068a..ecf98b9388 100644 --- a/src/cmd/compile/internal/gc/reflect.go +++ b/src/cmd/compile/internal/gc/reflect.go @@ -13,8 +13,14 @@ import ( "strings" ) +type itabEntry struct { + t, itype *Type + sym *Sym +} + // runtime interface and reflection data structures var signatlist []*Node +var itabs []itabEntry // byMethodNameAndPackagePath sorts method signatures by name, then package path. type byMethodNameAndPackagePath []*Sig @@ -919,13 +925,9 @@ func typenamesym(t *Type) *Sym { } s := typesym(t) if s.Def == nil { - n := Nod(ONAME, nil, nil) - n.Sym = s + n := newname(s) n.Type = Types[TUINT8] - n.Addable = true - n.Ullman = 1 n.Class = PEXTERN - n.Xoffset = 0 n.Typecheck = 1 s.Def = n @@ -945,6 +947,23 @@ func typename(t *Type) *Node { return n } +func itabnamesym(t, itype *Type) *Sym { + if t == nil || (Isptr[t.Etype] && t.Type == nil) || isideal(t) { + Fatalf("itabname %v", t) + } + s := Pkglookup(Tconv(t, FmtLeft)+","+Tconv(itype, FmtLeft), itab2pkg) + if s.Def == nil { + n := newname(s) + n.Type = Types[TUINT8] + n.Class = PEXTERN + n.Typecheck = 1 + s.Def = n + + itabs = append(itabs, itabEntry{t: t, itype: itype, sym: s}) + } + return s.Def.Sym +} + // isreflexive reports whether t has a reflexive equality operator. // That is, if x==x for all x of type t. func isreflexive(t *Type) bool { @@ -1320,6 +1339,30 @@ func dumptypestructs() { } } + // process itabs + for _, i := range itabs { + // dump empty itab symbol into i.sym + // type itab struct { + // inter *interfacetype + // _type *_type + // link *itab + // bad int32 + // unused int32 + // fun [1]uintptr // variable sized + // } + o := dsymptr(i.sym, 0, dtypesym(i.itype), 0) + o = dsymptr(i.sym, o, dtypesym(i.t), 0) + o += Widthptr + 8 // skip link/bad/unused fields + o += len(imethods(i.itype)) * Widthptr // skip fun method pointers + // at runtime the itab will contain pointers to types, other itabs and + // method functions. None are allocated on heap, so we can use obj.NOPTR. + ggloblsym(i.sym, int32(o), int16(obj.DUPOK|obj.NOPTR)) + + ilink := Pkglookup(Tconv(i.t, FmtLeft)+","+Tconv(i.itype, FmtLeft), itablinkpkg) + dsymptr(ilink, 0, i.sym, 0) + ggloblsym(ilink, int32(Widthptr), int16(obj.DUPOK|obj.RODATA)) + } + // generate import strings for imported packages for _, p := range pkgs { if p.Direct { diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 6d077d5890..90ed401a43 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -996,6 +996,10 @@ opswitch: break } + if isdirectiface(n.Left.Type) { + itabnamesym(n.Left.Type, n.Type) + } + var ll []*Node if !Isinter(n.Left.Type) { ll = append(ll, typename(n.Left.Type)) |
