Skip to content

Commit

Permalink
cmd/compile: add ptototype of the types need synthesized to builtin
Browse files Browse the repository at this point in the history
To synthesize dwarf type in compiler, the prototype of string, map, slice, channel is needed. It can't be easily got when compile the code out of runtime. So use add them to builtin so we can get the prototype information.

More detailed explanation:
When a map(eg: map[int]int) is used, we need more dwarf type info than we can see in language level. The pseudo type hash<int,int>, bucket<int,int>, []val<int> and []key<int> will be generated for debug more easy. They are "template" type, we need to fill them when a map is instantiated. And we can't define these type directly by exist go runtime type. So they should be added to buitin for filling the "template" when generating the dwarf type info of them.
So does others.

See golang#52209 (comment)

For golang#52209

Change-Id: Ifcb1e15d2300323980b320673adb67df2ee07956
  • Loading branch information
zhouguangyuan0718 committed Apr 20, 2022
1 parent a07757c commit 3acfa36
Show file tree
Hide file tree
Showing 4 changed files with 192 additions and 12 deletions.
54 changes: 53 additions & 1 deletion src/cmd/compile/internal/typecheck/builtin.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

98 changes: 98 additions & 0 deletions src/cmd/compile/internal/typecheck/builtin/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,3 +269,101 @@ var x86HasSSE41 bool
var x86HasFMA bool
var armHasVFPv4 bool
var arm64HasATOMICS bool

// the type below is for dwarf type info generation in compiler.
type stringStructDWARF struct {
str *byte
len int
}

type slice struct {
array unsafe.Pointer
len int
cap int
}

type hmap struct {
count int
flags uint8
B uint8
noverflow uint16
hash0 uint32

buckets unsafe.Pointer
oldbuckets unsafe.Pointer
nevacuate uintptr

extra *mapextra
}

type bmap struct {
tophash [8]uint8
}

// can't handle recursive now,
type sudog struct {
g *g
next *byte // *byte is really *runtime.sudog
prev *byte // *byte is really *runtime.sudog
elem unsafe.Pointer
acquiretime int64
releasetime int64
ticket uint32
isSelect bool
success bool
parent *byte // *byte is really *runtime.sudog
waitlink *byte // *byte is really *runtime.sudog
waittail *byte // *byte is really *runtime.sudog
c *hchan
}

type waitq struct {
first *byte // *byte is really *runtime.sudog
last *byte // *byte is really *runtime.sudog
}

type mutex struct {
lockRankStruct
key uintptr
}

type hchan struct {
qcount uint
dataqsiz uint
buf unsafe.Pointer
elemsize uint16
closed uint32
elemtype *_type
sendx uint
recvx uint
recvq waitq
sendq waitq
lock mutex
}

type eface struct {
_type *_type
data unsafe.Pointer
}

type iface struct {
tab *itab
data unsafe.Pointer
}

type itab byte

type mapextra byte

type _type byte

type g byte

type lockRankStruct struct{}

type lockRankStruct_on struct {
rank lockRank
pad int
}

type lockRank int
41 changes: 31 additions & 10 deletions src/cmd/compile/internal/typecheck/mkbuiltin.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ func main() {
fmt.Fprintln(&b, `import (`)
fmt.Fprintln(&b, ` "cmd/compile/internal/types"`)
fmt.Fprintln(&b, ` "cmd/internal/src"`)
fmt.Fprintln(&b, ` "cmd/compile/internal/ir"`)
fmt.Fprintln(&b, `)`)

mkbuiltin(&b, "runtime")
Expand Down Expand Up @@ -84,18 +85,24 @@ func mkbuiltin(w io.Writer, name string) {
}
continue
}
if decl.Tok != token.VAR {
log.Fatal("unhandled declaration kind", decl.Tok)
if decl.Tok != token.VAR && decl.Tok != token.TYPE {
log.Fatal("unhandled declaration kind ", decl.Tok)
}
for _, spec := range decl.Specs {
spec := spec.(*ast.ValueSpec)
if len(spec.Values) != 0 {
log.Fatal("unexpected values")
if spec, ok := spec.(*ast.ValueSpec); ok {
if len(spec.Values) != 0 {
log.Fatal("unexpected values")
}
idx := interner.intern(spec.Type)
for _, name := range spec.Names {
fmt.Fprintf(w, "{%q,varTag, %d},\n", name.Name, idx)
}
}
typ := interner.intern(spec.Type)
for _, name := range spec.Names {
fmt.Fprintf(w, "{%q, varTag, %d},\n", name.Name, typ)
if spec, ok := spec.(*ast.TypeSpec); ok {
typ := interner.intern(spec.Type)
fmt.Fprintf(w, "{%q, typeTag, %d},\n", spec.Name.Name, typ)
}

}
default:
log.Fatal("unhandled decl type", decl)
Expand All @@ -110,6 +117,13 @@ func newSig(params, results []*types.Field) *types.Type {
return types.NewSignature(types.NoPkg, nil, nil, params, results)
}
func newNamed(name string, typ *types.Type) *types.Type {
n := importtype(ir.Pkgs.Runtime, src.NoXPos, ir.Pkgs.Runtime.Lookup(name))
n.Type().SetUnderlying(typ)
types.CalcSize(n.Type())
return n.Type()
}
func params(tlist ...*types.Type) []*types.Field {
flist := make([]*types.Field, len(tlist))
for i, typ := range tlist {
Expand Down Expand Up @@ -163,7 +177,10 @@ func (i *typeInterner) mktype(t ast.Expr) string {
case "rune":
return "types.RuneType"
}
return fmt.Sprintf("types.Types[types.T%s]", strings.ToUpper(t.Name))
if t.Obj == nil {
return fmt.Sprintf("types.Types[types.T%s]", strings.ToUpper(t.Name))
}
return fmt.Sprintf("newNamed(%q,%s)", t.Name, i.subtype(t.Obj.Decl.(*ast.TypeSpec).Type))
case *ast.SelectorExpr:
if t.X.(*ast.Ident).Name != "unsafe" || t.Sel.Name != "Pointer" {
log.Fatalf("unhandled type: %#v", t)
Expand Down Expand Up @@ -213,7 +230,11 @@ func (i *typeInterner) fields(fl *ast.FieldList, keepNames bool) string {
for _, f := range fl.List {
typ := i.subtype(f.Type)
if len(f.Names) == 0 {
res = append(res, typ)
if keepNames {
res = append(res, fmt.Sprintf("types.NewField(src.NoXPos, Lookup(%q), %s)", f.Type, typ))
} else {
res = append(res, typ)
}
} else {
for _, name := range f.Names {
if keepNames {
Expand Down
11 changes: 10 additions & 1 deletion src/cmd/compile/internal/typecheck/syms.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ func LookupRuntime(name string) *ir.Name {
// successive occurrences of the "any" placeholder in the
// type syntax expression n.Type.
// The result of SubstArgTypes MUST be assigned back to old, e.g.
// n.Left = SubstArgTypes(n.Left, t1, t2)
//
// n.Left = SubstArgTypes(n.Left, t1, t2)
func SubstArgTypes(old *ir.Name, types_ ...*types.Type) *ir.Name {
for _, t := range types_ {
types.CalcSize(t)
Expand Down Expand Up @@ -78,6 +79,14 @@ func InitRuntime() {
importfunc(ir.Pkgs.Runtime, src.NoXPos, sym, typ)
case varTag:
importvar(ir.Pkgs.Runtime, src.NoXPos, sym, typ)
case typeTag:
if sym.PkgDef() != nil {
// already imported in runtimeTypes()
continue
}
n := importtype(ir.Pkgs.Runtime, src.NoXPos, sym)
n.Type().SetUnderlying(typ)
types.CalcSize(n.Type())
default:
base.Fatalf("unhandled declaration tag %v", d.tag)
}
Expand Down

0 comments on commit 3acfa36

Please sign in to comment.