mirror of
https://github.com/golang/go
synced 2024-11-26 14:46:47 -07:00
cmd/compile/internal/typecheck: refactor and simplify DeclFunc
This CL refactors typecheck.DeclFunc to require the caller to have already constructed the ir.Func and signature type using ir.NewFunc and types.NewSignature, and simplifies typecheck.DeclFunc to simply return the slices of param and results ONAMEs. typecheck.DeclFunc was the last reason that ir.Field still exists, so this CL also gets rid of that. Change-Id: Ib398420bac2fd135a235810b8af1635fa754965c Reviewed-on: https://go-review.googlesource.com/c/go/+/520977 Run-TryBot: Matthew Dempsky <mdempsky@google.com> Auto-Submit: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
This commit is contained in:
parent
b581e44739
commit
009ca22fe2
@ -8,31 +8,10 @@ import (
|
||||
"cmd/compile/internal/base"
|
||||
"cmd/compile/internal/types"
|
||||
"cmd/internal/src"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Calling TypeNode converts a *types.Type to a Node shell.
|
||||
|
||||
// A Field is a declared function parameter.
|
||||
// It is not a Node.
|
||||
type Field struct {
|
||||
Pos src.XPos
|
||||
Sym *types.Sym
|
||||
Type *types.Type
|
||||
IsDDD bool
|
||||
}
|
||||
|
||||
func NewField(pos src.XPos, sym *types.Sym, typ *types.Type) *Field {
|
||||
return &Field{Pos: pos, Sym: sym, Type: typ}
|
||||
}
|
||||
|
||||
func (f *Field) String() string {
|
||||
if f.Sym != nil {
|
||||
return fmt.Sprintf("%v %v", f.Sym, f.Type)
|
||||
}
|
||||
return fmt.Sprint(f.Type)
|
||||
}
|
||||
|
||||
// A typeNode is a Node wrapper for type t.
|
||||
type typeNode struct {
|
||||
miniNode
|
||||
|
@ -28,9 +28,13 @@ func MakeInit() {
|
||||
}
|
||||
|
||||
// Make a function that contains all the initialization statements.
|
||||
base.Pos = nf[0].Pos() // prolog/epilog gets line number of first init stmt
|
||||
initializers := typecheck.Lookup("init")
|
||||
fn := typecheck.DeclFunc(initializers, nil, nil, nil)
|
||||
pos := nf[0].Pos() // prolog/epilog gets line number of first init stmt
|
||||
base.Pos = pos
|
||||
|
||||
sym := typecheck.Lookup("init")
|
||||
fn := ir.NewFunc(pos, pos, sym, types.NewSignature(nil, nil, nil))
|
||||
typecheck.DeclFunc(fn)
|
||||
|
||||
for _, dcl := range typecheck.InitTodoFunc.Dcl {
|
||||
dcl.Curfn = fn
|
||||
}
|
||||
@ -113,9 +117,12 @@ func MakeTask() {
|
||||
ni := len(InstrumentGlobalsMap)
|
||||
if ni != 0 {
|
||||
// Make an init._ function.
|
||||
base.Pos = base.AutogeneratedPos
|
||||
name := noder.Renameinit()
|
||||
fnInit := typecheck.DeclFunc(name, nil, nil, nil)
|
||||
pos := base.AutogeneratedPos
|
||||
base.Pos = pos
|
||||
|
||||
sym := noder.Renameinit()
|
||||
fnInit := ir.NewFunc(pos, pos, sym, types.NewSignature(nil, nil, nil))
|
||||
typecheck.DeclFunc(fnInit)
|
||||
|
||||
// Get an array of instrumented global variables.
|
||||
globals := instrumentGlobals(fnInit)
|
||||
|
@ -140,21 +140,25 @@ func hashFunc(t *types.Type) *ir.Func {
|
||||
return sym.Def.(*ir.Name).Func
|
||||
}
|
||||
|
||||
base.Pos = base.AutogeneratedPos // less confusing than end of input
|
||||
pos := base.AutogeneratedPos // less confusing than end of input
|
||||
base.Pos = pos
|
||||
|
||||
// func sym(p *T, h uintptr) uintptr
|
||||
args := []*ir.Field{
|
||||
ir.NewField(base.Pos, typecheck.Lookup("p"), types.NewPtr(t)),
|
||||
ir.NewField(base.Pos, typecheck.Lookup("h"), types.Types[types.TUINTPTR]),
|
||||
}
|
||||
results := []*ir.Field{ir.NewField(base.Pos, nil, types.Types[types.TUINTPTR])}
|
||||
|
||||
fn := typecheck.DeclFunc(sym, nil, args, results)
|
||||
fn := ir.NewFunc(pos, pos, sym, types.NewSignature(nil,
|
||||
[]*types.Field{
|
||||
types.NewField(pos, typecheck.Lookup("p"), types.NewPtr(t)),
|
||||
types.NewField(pos, typecheck.Lookup("h"), types.Types[types.TUINTPTR]),
|
||||
},
|
||||
[]*types.Field{
|
||||
types.NewField(pos, nil, types.Types[types.TUINTPTR]),
|
||||
},
|
||||
))
|
||||
sym.Def = fn.Nname
|
||||
fn.Pragma |= ir.Noinline // TODO(mdempsky): We need to emit this during the unified frontend instead, to allow inlining.
|
||||
|
||||
np := fn.Type().Params().Field(0).Nname.(*ir.Name)
|
||||
nh := fn.Type().Params().Field(1).Nname.(*ir.Name)
|
||||
params, _ := typecheck.DeclFunc(fn)
|
||||
np := params[0]
|
||||
nh := params[1]
|
||||
|
||||
switch t.Kind() {
|
||||
case types.TARRAY:
|
||||
@ -365,19 +369,27 @@ func eqFunc(t *types.Type) *ir.Func {
|
||||
if sym.Def != nil {
|
||||
return sym.Def.(*ir.Name).Func
|
||||
}
|
||||
base.Pos = base.AutogeneratedPos // less confusing than end of input
|
||||
|
||||
pos := base.AutogeneratedPos // less confusing than end of input
|
||||
base.Pos = pos
|
||||
|
||||
// func sym(p, q *T) bool
|
||||
fn := typecheck.DeclFunc(sym, nil,
|
||||
[]*ir.Field{ir.NewField(base.Pos, typecheck.Lookup("p"), types.NewPtr(t)), ir.NewField(base.Pos, typecheck.Lookup("q"), types.NewPtr(t))},
|
||||
[]*ir.Field{ir.NewField(base.Pos, typecheck.Lookup("r"), types.Types[types.TBOOL])},
|
||||
)
|
||||
fn := ir.NewFunc(pos, pos, sym, types.NewSignature(nil,
|
||||
[]*types.Field{
|
||||
types.NewField(pos, typecheck.Lookup("p"), types.NewPtr(t)),
|
||||
types.NewField(pos, typecheck.Lookup("q"), types.NewPtr(t)),
|
||||
},
|
||||
[]*types.Field{
|
||||
types.NewField(pos, typecheck.Lookup("r"), types.Types[types.TBOOL]),
|
||||
},
|
||||
))
|
||||
sym.Def = fn.Nname
|
||||
fn.Pragma |= ir.Noinline // TODO(mdempsky): We need to emit this during the unified frontend instead, to allow inlining.
|
||||
|
||||
np := fn.Type().Params().Field(0).Nname.(*ir.Name)
|
||||
nq := fn.Type().Params().Field(1).Nname.(*ir.Name)
|
||||
nr := fn.Type().Results().Field(0).Nname.(*ir.Name)
|
||||
params, results := typecheck.DeclFunc(fn)
|
||||
np := params[0]
|
||||
nq := params[1]
|
||||
nr := results[0]
|
||||
|
||||
// Label to jump to if an equality test fails.
|
||||
neq := typecheck.AutoLabel(".neq")
|
||||
|
@ -239,7 +239,8 @@ func makeABIWrapper(f *ir.Func, wrapperABI obj.ABI) {
|
||||
savepos := base.Pos
|
||||
savedcurfn := ir.CurFunc
|
||||
|
||||
base.Pos = base.AutogeneratedPos
|
||||
pos := base.AutogeneratedPos
|
||||
base.Pos = pos
|
||||
|
||||
// At the moment we don't support wrapping a method, we'd need machinery
|
||||
// below to handle the receiver. Panic if we see this scenario.
|
||||
@ -250,10 +251,12 @@ func makeABIWrapper(f *ir.Func, wrapperABI obj.ABI) {
|
||||
}
|
||||
|
||||
// Reuse f's types.Sym to create a new ODCLFUNC/function.
|
||||
fn := typecheck.DeclFunc(f.Nname.Sym(), nil,
|
||||
typecheck.NewFuncParams(ft.Params(), true),
|
||||
typecheck.NewFuncParams(ft.Results(), false))
|
||||
// TODO(mdempsky): Means we can't set sym.Def in Declfunc, ugh.
|
||||
fn := ir.NewFunc(pos, pos, f.Sym(), types.NewSignature(nil,
|
||||
typecheck.NewFuncParams(ft.Params().FieldSlice(), true),
|
||||
typecheck.NewFuncParams(ft.Results().FieldSlice(), false)))
|
||||
fn.ABI = wrapperABI
|
||||
typecheck.DeclFunc(fn)
|
||||
|
||||
fn.SetABIWrapper(true)
|
||||
fn.SetDupok(true)
|
||||
|
@ -1042,7 +1042,9 @@ func tryWrapGlobalMapInit(n ir.Node) (mapvar *ir.Name, genfn *ir.Func, call ir.N
|
||||
//
|
||||
minitsym := typecheck.LookupNum("map.init.", mapinitgen)
|
||||
mapinitgen++
|
||||
newfn := typecheck.DeclFunc(minitsym, nil, nil, nil)
|
||||
|
||||
newfn := ir.NewFunc(base.Pos, base.Pos, minitsym, types.NewSignature(nil, nil, nil))
|
||||
typecheck.DeclFunc(newfn)
|
||||
if base.Debug.WrapGlobalMapDbg > 0 {
|
||||
fmt.Fprintf(os.Stderr, "=-= generated func is %v\n", newfn)
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ package typecheck
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"internal/types/errors"
|
||||
"sync"
|
||||
|
||||
"cmd/compile/internal/base"
|
||||
@ -17,32 +16,36 @@ import (
|
||||
|
||||
var funcStack []*ir.Func // stack of previous values of ir.CurFunc
|
||||
|
||||
func DeclFunc(sym *types.Sym, recv *ir.Field, params, results []*ir.Field) *ir.Func {
|
||||
fn := ir.NewFunc(base.Pos, base.Pos, sym, nil)
|
||||
// DeclFunc creates and returns ONAMEs for the parameters and results
|
||||
// of the given function. It also sets ir.CurFunc, and adds fn to
|
||||
// Target.Funcs.
|
||||
//
|
||||
// After the caller is done constructing fn, it must call
|
||||
// FinishFuncBody.
|
||||
func DeclFunc(fn *ir.Func) (params, results []*ir.Name) {
|
||||
typ := fn.Type()
|
||||
|
||||
// Currently, DeclFunc is only used to create normal functions, not
|
||||
// methods. If a use case for creating methods shows up, we can
|
||||
// extend it to support those too.
|
||||
if typ.Recv() != nil {
|
||||
base.FatalfAt(fn.Pos(), "unexpected receiver parameter")
|
||||
}
|
||||
|
||||
params = declareParams(fn, ir.PPARAM, typ.Params().FieldSlice())
|
||||
results = declareParams(fn, ir.PPARAMOUT, typ.Results().FieldSlice())
|
||||
|
||||
funcStack = append(funcStack, ir.CurFunc)
|
||||
ir.CurFunc = fn
|
||||
|
||||
var recv1 *types.Field
|
||||
if recv != nil {
|
||||
recv1 = declareParam(fn, ir.PPARAM, -1, recv)
|
||||
}
|
||||
|
||||
typ := types.NewSignature(recv1, declareParams(fn, ir.PPARAM, params), declareParams(fn, ir.PPARAMOUT, results))
|
||||
checkdupfields("argument", typ.Recvs().FieldSlice(), typ.Params().FieldSlice(), typ.Results().FieldSlice())
|
||||
|
||||
fn.Nname.SetType(typ)
|
||||
fn.Nname.SetTypecheck(1)
|
||||
|
||||
fn.Nname.Defn = fn
|
||||
Target.Funcs = append(Target.Funcs, fn)
|
||||
|
||||
return fn
|
||||
return
|
||||
}
|
||||
|
||||
// finish the body.
|
||||
// called in auto-declaration context.
|
||||
// returns in extern-declaration context.
|
||||
// FinishFuncBody restores ir.CurFunc to its state before the last
|
||||
// call to DeclFunc.
|
||||
func FinishFuncBody() {
|
||||
funcStack, ir.CurFunc = funcStack[:len(funcStack)-1], funcStack[len(funcStack)-1]
|
||||
}
|
||||
@ -53,36 +56,15 @@ func CheckFuncStack() {
|
||||
}
|
||||
}
|
||||
|
||||
// checkdupfields emits errors for duplicately named fields or methods in
|
||||
// a list of struct or interface types.
|
||||
func checkdupfields(what string, fss ...[]*types.Field) {
|
||||
seen := make(map[*types.Sym]bool)
|
||||
for _, fs := range fss {
|
||||
for _, f := range fs {
|
||||
if f.Sym == nil || f.Sym.IsBlank() {
|
||||
continue
|
||||
}
|
||||
if seen[f.Sym] {
|
||||
base.ErrorfAt(f.Pos, errors.DuplicateFieldAndMethod, "duplicate %s %s", what, f.Sym.Name)
|
||||
continue
|
||||
}
|
||||
seen[f.Sym] = true
|
||||
}
|
||||
func declareParams(fn *ir.Func, ctxt ir.Class, params []*types.Field) []*ir.Name {
|
||||
names := make([]*ir.Name, len(params))
|
||||
for i, param := range params {
|
||||
names[i] = declareParam(fn, ctxt, i, param)
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
func declareParams(fn *ir.Func, ctxt ir.Class, l []*ir.Field) []*types.Field {
|
||||
fields := make([]*types.Field, len(l))
|
||||
for i, n := range l {
|
||||
fields[i] = declareParam(fn, ctxt, i, n)
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
func declareParam(fn *ir.Func, ctxt ir.Class, i int, param *ir.Field) *types.Field {
|
||||
f := types.NewField(param.Pos, param.Sym, param.Type)
|
||||
f.SetIsDDD(param.IsDDD)
|
||||
|
||||
func declareParam(fn *ir.Func, ctxt ir.Class, i int, param *types.Field) *ir.Name {
|
||||
sym := param.Sym
|
||||
if ctxt == ir.PPARAMOUT {
|
||||
if sym == nil {
|
||||
@ -99,11 +81,13 @@ func declareParam(fn *ir.Func, ctxt ir.Class, i int, param *ir.Field) *types.Fie
|
||||
}
|
||||
}
|
||||
|
||||
if sym != nil {
|
||||
f.Nname = fn.NewLocal(param.Pos, sym, ctxt, f.Type)
|
||||
if sym == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return f
|
||||
name := fn.NewLocal(param.Pos, sym, ctxt, param.Type)
|
||||
param.Nname = name
|
||||
return name
|
||||
}
|
||||
|
||||
// make a new Node off the books.
|
||||
|
@ -26,26 +26,22 @@ func LookupNum(prefix string, n int) *types.Sym {
|
||||
}
|
||||
|
||||
// Given funarg struct list, return list of fn args.
|
||||
func NewFuncParams(tl *types.Type, mustname bool) []*ir.Field {
|
||||
var args []*ir.Field
|
||||
gen := 0
|
||||
for _, t := range tl.Fields().Slice() {
|
||||
s := t.Sym
|
||||
func NewFuncParams(origs []*types.Field, mustname bool) []*types.Field {
|
||||
res := make([]*types.Field, len(origs))
|
||||
for i, orig := range origs {
|
||||
s := orig.Sym
|
||||
if mustname && (s == nil || s.Name == "_") {
|
||||
// invent a name so that we can refer to it in the trampoline
|
||||
s = LookupNum(".anon", gen)
|
||||
gen++
|
||||
s = LookupNum(".anon", i)
|
||||
} else if s != nil && s.Pkg != types.LocalPkg {
|
||||
// TODO(mdempsky): Preserve original position, name, and package.
|
||||
s = Lookup(s.Name)
|
||||
}
|
||||
a := ir.NewField(base.Pos, s, t.Type)
|
||||
a.Pos = t.Pos
|
||||
a.IsDDD = t.IsDDD()
|
||||
args = append(args, a)
|
||||
p := types.NewField(orig.Pos, s, orig.Type)
|
||||
p.SetIsDDD(orig.IsDDD())
|
||||
res[i] = p
|
||||
}
|
||||
|
||||
return args
|
||||
return res
|
||||
}
|
||||
|
||||
// NodAddr returns a node representing &n at base.Pos.
|
||||
|
Loading…
Reference in New Issue
Block a user