aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorMichel Lespinasse <walken@google.com>2016-03-17 06:18:13 -0700
committerMichel Lespinasse <walken@google.com>2016-03-29 02:18:03 +0000
commitf00bbd5f818f0a6b5b2fcf15422ad7fc4594225f (patch)
treed9acbc080dad0f5fe9549e36638318141b714494 /src/cmd
parent7043d2bb5e8275df308abe9a2367fb1622be0313 (diff)
downloadgo-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.go4
-rw-r--r--src/cmd/compile/internal/gc/main.go9
-rw-r--r--src/cmd/compile/internal/gc/reflect.go53
-rw-r--r--src/cmd/compile/internal/gc/walk.go4
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))