mirror of
https://github.com/golang/go
synced 2024-11-26 08:17:59 -07:00
[dev.typeparams] cmd/compile: refactor top-level typechecking in unified IR
This CL is a first step towards incremental typechecking during IR construction within unified IR. Namely, all top-level declarations are now typechecked as they're constructed, except for assignments (which aren't really declarations anyway). Change-Id: I65763a7659bf2e0f5e89dfe9e709d60e0fa4c631 Reviewed-on: https://go-review.googlesource.com/c/go/+/332097 Trust: Matthew Dempsky <mdempsky@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
This commit is contained in:
parent
ad7e5b219e
commit
372b312735
@ -784,6 +784,8 @@ func (r *reader) funcExt(name *ir.Name) {
|
|||||||
fn.Pragma = r.pragmaFlag()
|
fn.Pragma = r.pragmaFlag()
|
||||||
r.linkname(name)
|
r.linkname(name)
|
||||||
|
|
||||||
|
typecheck.Func(fn)
|
||||||
|
|
||||||
if r.bool() {
|
if r.bool() {
|
||||||
fn.ABI = obj.ABI(r.uint64())
|
fn.ABI = obj.ABI(r.uint64())
|
||||||
|
|
||||||
@ -2124,7 +2126,7 @@ func (r *reader) methodWrapper(derefs int, tbase *types.Type, method *types.Fiel
|
|||||||
// TODO(mdempsky): Use method.Pos instead?
|
// TODO(mdempsky): Use method.Pos instead?
|
||||||
pos := base.AutogeneratedPos
|
pos := base.AutogeneratedPos
|
||||||
|
|
||||||
fn := r.newWrapperFunc(pos, sym, wrapper, method, target)
|
fn := r.newWrapperFunc(pos, sym, wrapper, method)
|
||||||
|
|
||||||
var recv ir.Node = fn.Nname.Type().Recv().Nname.(*ir.Name)
|
var recv ir.Node = fn.Nname.Type().Recv().Nname.(*ir.Name)
|
||||||
|
|
||||||
@ -2143,6 +2145,8 @@ func (r *reader) methodWrapper(derefs int, tbase *types.Type, method *types.Fiel
|
|||||||
}
|
}
|
||||||
|
|
||||||
addTailCall(pos, fn, recv, method)
|
addTailCall(pos, fn, recv, method)
|
||||||
|
|
||||||
|
r.finishWrapperFunc(fn, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *reader) methodValueWrapper(tbase *types.Type, method *types.Field, target *ir.Package) {
|
func (r *reader) methodValueWrapper(tbase *types.Type, method *types.Field, target *ir.Package) {
|
||||||
@ -2167,7 +2171,7 @@ func (r *reader) methodValueWrapper(tbase *types.Type, method *types.Field, targ
|
|||||||
// TODO(mdempsky): Use method.Pos instead?
|
// TODO(mdempsky): Use method.Pos instead?
|
||||||
pos := base.AutogeneratedPos
|
pos := base.AutogeneratedPos
|
||||||
|
|
||||||
fn := r.newWrapperFunc(pos, sym, nil, method, target)
|
fn := r.newWrapperFunc(pos, sym, nil, method)
|
||||||
fn.SetNeedctxt(true)
|
fn.SetNeedctxt(true)
|
||||||
sym.Def = fn
|
sym.Def = fn
|
||||||
|
|
||||||
@ -2181,9 +2185,11 @@ func (r *reader) methodValueWrapper(tbase *types.Type, method *types.Field, targ
|
|||||||
fn.ClosureVars = append(fn.ClosureVars, recv)
|
fn.ClosureVars = append(fn.ClosureVars, recv)
|
||||||
|
|
||||||
addTailCall(pos, fn, recv, method)
|
addTailCall(pos, fn, recv, method)
|
||||||
|
|
||||||
|
r.finishWrapperFunc(fn, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *reader) newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Type, method *types.Field, target *ir.Package) *ir.Func {
|
func (r *reader) newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Type, method *types.Field) *ir.Func {
|
||||||
fn := ir.NewFunc(pos)
|
fn := ir.NewFunc(pos)
|
||||||
fn.SetDupok(true) // TODO(mdempsky): Leave unset for local, non-generic wrappers?
|
fn.SetDupok(true) // TODO(mdempsky): Leave unset for local, non-generic wrappers?
|
||||||
|
|
||||||
@ -2214,11 +2220,19 @@ func (r *reader) newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Typ
|
|||||||
defParams(ir.PPARAM, sig.Params())
|
defParams(ir.PPARAM, sig.Params())
|
||||||
defParams(ir.PPARAMOUT, sig.Results())
|
defParams(ir.PPARAMOUT, sig.Results())
|
||||||
|
|
||||||
target.Decls = append(target.Decls, fn)
|
|
||||||
|
|
||||||
return fn
|
return fn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *reader) finishWrapperFunc(fn *ir.Func, target *ir.Package) {
|
||||||
|
typecheck.Func(fn)
|
||||||
|
|
||||||
|
ir.WithFunc(fn, func() {
|
||||||
|
typecheck.Stmts(fn.Body)
|
||||||
|
})
|
||||||
|
|
||||||
|
target.Decls = append(target.Decls, fn)
|
||||||
|
}
|
||||||
|
|
||||||
// newWrapperType returns a copy of the given signature type, but with
|
// newWrapperType returns a copy of the given signature type, but with
|
||||||
// the receiver parameter type substituted with recvType.
|
// the receiver parameter type substituted with recvType.
|
||||||
// If recvType is nil, newWrapperType returns a signature
|
// If recvType is nil, newWrapperType returns a signature
|
||||||
|
@ -109,6 +109,16 @@ func unified(noders []*noder) {
|
|||||||
r.ext = r
|
r.ext = r
|
||||||
r.pkgInit(types.LocalPkg, target)
|
r.pkgInit(types.LocalPkg, target)
|
||||||
|
|
||||||
|
// Type-check any top-level assignments. We ignore non-assignments
|
||||||
|
// here because other declarations are typechecked as they're
|
||||||
|
// constructed.
|
||||||
|
for i, ndecls := 0, len(target.Decls); i < ndecls; i++ {
|
||||||
|
switch n := target.Decls[i]; n.Op() {
|
||||||
|
case ir.OAS, ir.OAS2:
|
||||||
|
target.Decls[i] = typecheck.Stmt(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Don't use range--bodyIdx can add closures to todoBodies.
|
// Don't use range--bodyIdx can add closures to todoBodies.
|
||||||
for len(todoBodies) > 0 {
|
for len(todoBodies) > 0 {
|
||||||
// The order we expand bodies doesn't matter, so pop from the end
|
// The order we expand bodies doesn't matter, so pop from the end
|
||||||
@ -122,22 +132,12 @@ func unified(noders []*noder) {
|
|||||||
|
|
||||||
// Instantiated generic function: add to Decls for typechecking
|
// Instantiated generic function: add to Decls for typechecking
|
||||||
// and compilation.
|
// and compilation.
|
||||||
if pri.dict != nil && len(pri.dict.targs) != 0 && fn.OClosure == nil {
|
if fn.OClosure == nil && len(pri.dict.targs) != 0 {
|
||||||
target.Decls = append(target.Decls, fn)
|
target.Decls = append(target.Decls, fn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
todoBodies = nil
|
todoBodies = nil
|
||||||
|
|
||||||
if !quirksMode() {
|
|
||||||
// TODO(mdempsky): Investigate generating wrappers in quirks mode too.
|
|
||||||
r.wrapTypes(target)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't use range--typecheck can add closures to Target.Decls.
|
|
||||||
for i := 0; i < len(target.Decls); i++ {
|
|
||||||
target.Decls[i] = typecheck.Stmt(target.Decls[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't use range--typecheck can add closures to Target.Decls.
|
// Don't use range--typecheck can add closures to Target.Decls.
|
||||||
for i := 0; i < len(target.Decls); i++ {
|
for i := 0; i < len(target.Decls); i++ {
|
||||||
if fn, ok := target.Decls[i].(*ir.Func); ok {
|
if fn, ok := target.Decls[i].(*ir.Func); ok {
|
||||||
@ -145,8 +145,9 @@ func unified(noders []*noder) {
|
|||||||
s := fmt.Sprintf("\nbefore typecheck %v", fn)
|
s := fmt.Sprintf("\nbefore typecheck %v", fn)
|
||||||
ir.Dump(s, fn)
|
ir.Dump(s, fn)
|
||||||
}
|
}
|
||||||
ir.CurFunc = fn
|
ir.WithFunc(fn, func() {
|
||||||
typecheck.Stmts(fn.Body)
|
typecheck.Stmts(fn.Body)
|
||||||
|
})
|
||||||
if base.Flag.W > 1 {
|
if base.Flag.W > 1 {
|
||||||
s := fmt.Sprintf("\nafter typecheck %v", fn)
|
s := fmt.Sprintf("\nafter typecheck %v", fn)
|
||||||
ir.Dump(s, fn)
|
ir.Dump(s, fn)
|
||||||
@ -154,6 +155,26 @@ func unified(noders []*noder) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !quirksMode() {
|
||||||
|
// TODO(mdempsky): Investigate generating wrappers in quirks mode too.
|
||||||
|
r.wrapTypes(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that nothing snuck past typechecking.
|
||||||
|
for _, n := range target.Decls {
|
||||||
|
if n.Typecheck() == 0 {
|
||||||
|
base.FatalfAt(n.Pos(), "missed typecheck: %v", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// For functions, check that at least their first statement (if
|
||||||
|
// any) was typechecked too.
|
||||||
|
if fn, ok := n.(*ir.Func); ok && len(fn.Body) != 0 {
|
||||||
|
if stmt := fn.Body[0]; stmt.Typecheck() == 0 {
|
||||||
|
base.FatalfAt(stmt.Pos(), "missed typecheck: %v", stmt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
base.ExitIfErrors() // just in case
|
base.ExitIfErrors() // just in case
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user