2015-02-13 14:40:36 -05:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
|
|
package gc
|
|
|
|
|
|
|
|
|
|
import (
|
2017-05-02 16:46:01 +02:00
|
|
|
"cmd/compile/internal/syntax"
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
"cmd/compile/internal/types"
|
2015-02-13 14:40:36 -05:00
|
|
|
"fmt"
|
|
|
|
|
)
|
|
|
|
|
|
2017-05-02 16:46:01 +02:00
|
|
|
func (p *noder) funcLit(expr *syntax.FuncLit) *Node {
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
xtype := p.typeExpr(expr.Type)
|
2017-05-02 16:46:01 +02:00
|
|
|
ntype := p.typeExpr(expr.Type)
|
|
|
|
|
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
xfunc := p.nod(expr, ODCLFUNC, nil, nil)
|
|
|
|
|
xfunc.Func.SetIsHiddenClosure(Curfn != nil)
|
2018-10-31 11:38:37 -07:00
|
|
|
xfunc.Func.Nname = newfuncnamel(p.pos(expr), nblank.Sym) // filled in by typecheckclosure
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
xfunc.Func.Nname.Name.Param.Ntype = xtype
|
|
|
|
|
xfunc.Func.Nname.Name.Defn = xfunc
|
2015-02-13 14:40:36 -05:00
|
|
|
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
clo := p.nod(expr, OCLOSURE, nil, nil)
|
|
|
|
|
clo.Func.Ntype = ntype
|
2017-05-02 16:46:01 +02:00
|
|
|
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
xfunc.Func.Closure = clo
|
|
|
|
|
clo.Func.Closure = xfunc
|
|
|
|
|
|
2018-03-14 16:53:30 -07:00
|
|
|
p.funcBody(xfunc, expr.Body)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// closure-specific variables are hanging off the
|
|
|
|
|
// ordinary ones in the symbol table; see oldname.
|
|
|
|
|
// unhook them.
|
|
|
|
|
// make the list of pointers for the closure call.
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
for _, v := range xfunc.Func.Cvars.Slice() {
|
2016-05-27 00:56:19 -04:00
|
|
|
// Unlink from v1; see comment in syntax.go type Param for these fields.
|
|
|
|
|
v1 := v.Name.Defn
|
|
|
|
|
v1.Name.Param.Innermost = v.Name.Param.Outer
|
2016-05-27 14:24:26 -04:00
|
|
|
|
2016-05-27 00:56:19 -04:00
|
|
|
// If the closure usage of v is not dense,
|
|
|
|
|
// we need to make it dense; now that we're out
|
|
|
|
|
// of the function in which v appeared,
|
|
|
|
|
// look up v.Sym in the enclosing function
|
|
|
|
|
// and keep it around for use in the compiled code.
|
|
|
|
|
//
|
|
|
|
|
// That is, suppose we just finished parsing the innermost
|
|
|
|
|
// closure f4 in this code:
|
|
|
|
|
//
|
|
|
|
|
// func f() {
|
|
|
|
|
// v := 1
|
|
|
|
|
// func() { // f2
|
|
|
|
|
// use(v)
|
|
|
|
|
// func() { // f3
|
|
|
|
|
// func() { // f4
|
|
|
|
|
// use(v)
|
|
|
|
|
// }()
|
|
|
|
|
// }()
|
|
|
|
|
// }()
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// At this point v.Outer is f2's v; there is no f3's v.
|
|
|
|
|
// To construct the closure f4 from within f3,
|
|
|
|
|
// we need to use f3's v and in this case we need to create f3's v.
|
|
|
|
|
// We are now in the context of f3, so calling oldname(v.Sym)
|
|
|
|
|
// obtains f3's v, creating it if necessary (as it is in the example).
|
|
|
|
|
//
|
|
|
|
|
// capturevars will decide whether to use v directly or &v.
|
|
|
|
|
v.Name.Param.Outer = oldname(v.Sym)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
return clo
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2020-11-12 09:33:34 -08:00
|
|
|
// typecheckclosure typechecks an OCLOSURE node. It also creates the named
|
|
|
|
|
// function associated with the closure.
|
|
|
|
|
// TODO: This creation of the named function should probably really be done in a
|
|
|
|
|
// separate pass from type-checking.
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
func typecheckclosure(clo *Node, top int) {
|
|
|
|
|
xfunc := clo.Func.Closure
|
2019-09-11 13:25:29 +07:00
|
|
|
// Set current associated iota value, so iota can be used inside
|
|
|
|
|
// function in ConstSpec, see issue #22344
|
|
|
|
|
if x := getIotaValue(); x >= 0 {
|
|
|
|
|
xfunc.SetIota(x)
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-06 12:26:57 -07:00
|
|
|
clo.Func.Ntype = typecheck(clo.Func.Ntype, ctxType)
|
2019-04-16 20:32:31 +07:00
|
|
|
clo.Type = clo.Func.Ntype.Type
|
|
|
|
|
clo.Func.Top = top
|
|
|
|
|
|
|
|
|
|
// Do not typecheck xfunc twice, otherwise, we will end up pushing
|
|
|
|
|
// xfunc to xtop multiple times, causing initLSym called twice.
|
|
|
|
|
// See #30709
|
|
|
|
|
if xfunc.Typecheck() == 1 {
|
|
|
|
|
return
|
|
|
|
|
}
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
|
|
|
|
|
for _, ln := range xfunc.Func.Cvars.Slice() {
|
2016-05-27 00:56:19 -04:00
|
|
|
n := ln.Name.Defn
|
2017-02-27 19:56:38 +02:00
|
|
|
if !n.Name.Captured() {
|
|
|
|
|
n.Name.SetCaptured(true)
|
2015-05-15 10:02:19 -07:00
|
|
|
if n.Name.Decldepth == 0 {
|
2016-09-09 21:08:46 -07:00
|
|
|
Fatalf("typecheckclosure: var %S does not have decldepth assigned", n)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Ignore assignments to the variable in straightline code
|
|
|
|
|
// preceding the first capturing by a closure.
|
2015-05-15 10:02:19 -07:00
|
|
|
if n.Name.Decldepth == decldepth {
|
cmd/compile: move some ONAME-specific flags from Node to Name
The IsClosureVar, IsOutputParamHeapAddr, Assigned, Addrtaken,
InlFormal, and InlLocal flags are only interesting for ONAME nodes, so
it's better to set these flags on Name.flags instead of Node.flags.
Two caveats though:
1. Previously, we would set Assigned and Addrtaken on the entire
expression tree involved in an assignment or addressing operation.
However, the rest of the compiler only actually cares about knowing
whether the underlying ONAME (if any) was assigned/addressed.
2. This actually requires bumping Name.flags from bitset8 to bitset16,
whereas it doesn't allow shrinking Node.flags any. However, Name has
some trailing padding bytes, so expanding Name.flags doesn't cost any
memory.
Passes toolstash-check.
Change-Id: I7775d713566a38d5b9723360b1659b79391744c2
Reviewed-on: https://go-review.googlesource.com/c/go/+/200898
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2019-10-12 16:21:55 -07:00
|
|
|
n.Name.SetAssigned(false)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
xfunc.Func.Nname.Sym = closurename(Curfn)
|
2020-08-19 16:05:02 +07:00
|
|
|
setNodeNameFunc(xfunc.Func.Nname)
|
2018-11-18 08:34:38 -08:00
|
|
|
xfunc = typecheck(xfunc, ctxStmt)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// Type check the body now, but only if we're inside a function.
|
|
|
|
|
// At top level (in a variable initialization: curfn==nil) we're not
|
|
|
|
|
// ready to type check code yet; we'll check it later, because the
|
|
|
|
|
// underlying closure function we create is added to xtop.
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
if Curfn != nil && clo.Type != nil {
|
|
|
|
|
oldfn := Curfn
|
|
|
|
|
Curfn = xfunc
|
2015-02-23 16:07:24 -05:00
|
|
|
olddd := decldepth
|
2015-02-13 14:40:36 -05:00
|
|
|
decldepth = 1
|
2018-11-18 08:34:38 -08:00
|
|
|
typecheckslice(xfunc.Nbody.Slice(), ctxStmt)
|
2015-02-13 14:40:36 -05:00
|
|
|
decldepth = olddd
|
|
|
|
|
Curfn = oldfn
|
|
|
|
|
}
|
|
|
|
|
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
xtop = append(xtop, xfunc)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
// globClosgen is like Func.Closgen, but for the global scope.
|
|
|
|
|
var globClosgen int
|
2015-02-20 13:54:45 -05:00
|
|
|
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
// closurename generates a new unique name for a closure within
|
|
|
|
|
// outerfunc.
|
|
|
|
|
func closurename(outerfunc *Node) *types.Sym {
|
|
|
|
|
outer := "glob."
|
|
|
|
|
prefix := "func"
|
|
|
|
|
gen := &globClosgen
|
2015-02-20 13:54:45 -05:00
|
|
|
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
if outerfunc != nil {
|
|
|
|
|
if outerfunc.Func.Closure != nil {
|
|
|
|
|
prefix = ""
|
2015-02-20 13:54:45 -05:00
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
outer = outerfunc.funcname()
|
2015-02-13 14:40:36 -05:00
|
|
|
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
// There may be multiple functions named "_". In those
|
|
|
|
|
// cases, we can't use their individual Closgens as it
|
|
|
|
|
// would lead to name clashes.
|
2018-04-08 13:39:10 +01:00
|
|
|
if !outerfunc.Func.Nname.isBlank() {
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
gen = &outerfunc.Func.Closgen
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
*gen++
|
|
|
|
|
return lookup(fmt.Sprintf("%s.%s%d", outer, prefix, *gen))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
cmd/compile: don't update outer variables after capturevars is complete
When compiling concurrently, we walk all functions before compiling
any of them. Walking functions can cause variables to switch from
being non-addrtaken to addrtaken, e.g. to prepare for a runtime call.
Typechecking propagates addrtaken-ness of closure variables to
their outer variables, so that capturevars can decide whether to
pass the variable's value or a pointer to it.
When all functions are compiled immediately, as long as the containing
function is compiled prior to the closure, this propagation has no effect.
When compilation is deferred, though, in rare cases, this results in
a change in the addrtaken-ness of a variable in the outer function,
which in turn changes the compiler's output.
(This is rare because in a great many cases, a temporary has been
introduced, insulating the outer variable from modification.)
But concurrent compilation must generate identical results.
To fix this, track whether capturevars has run.
If it has, there is no need to update outer variables
when closure variables change.
Capturevars always runs before any functions are walked or compiled.
The remainder of the changes in this CL are to support the test.
In particular, -d=compilelater forces the compiler to walk all
functions before compiling any of them, despite being non-concurrent.
This is useful because -live is fundamentally incompatible with
concurrent compilation, but we want -c=1 to have no behavior changes.
Fixes #20250
Change-Id: I89bcb54268a41e8588af1ac8cc37fbef856a90c2
Reviewed-on: https://go-review.googlesource.com/42853
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2017-05-05 15:22:59 -07:00
|
|
|
// capturevarscomplete is set to true when the capturevars phase is done.
|
|
|
|
|
var capturevarscomplete bool
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
// capturevars is called in a separate phase after all typechecking is done.
|
|
|
|
|
// It decides whether each variable captured by a closure should be captured
|
|
|
|
|
// by value or by reference.
|
|
|
|
|
// We use value capturing for values <= 128 bytes that are never reassigned
|
|
|
|
|
// after capturing (effectively constant).
|
|
|
|
|
func capturevars(xfunc *Node) {
|
2016-03-02 17:34:42 -08:00
|
|
|
lno := lineno
|
2016-12-07 17:40:46 -08:00
|
|
|
lineno = xfunc.Pos
|
2015-02-13 14:40:36 -05:00
|
|
|
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
clo := xfunc.Func.Closure
|
|
|
|
|
cvars := xfunc.Func.Cvars.Slice()
|
|
|
|
|
out := cvars[:0]
|
|
|
|
|
for _, v := range cvars {
|
2015-02-13 14:40:36 -05:00
|
|
|
if v.Type == nil {
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
// If v.Type is nil, it means v looked like it
|
|
|
|
|
// was going to be used in the closure, but
|
|
|
|
|
// isn't. This happens in struct literals like
|
|
|
|
|
// s{f: x} where we can't distinguish whether
|
|
|
|
|
// f is a field identifier or expression until
|
|
|
|
|
// resolving s.
|
2015-02-13 14:40:36 -05:00
|
|
|
continue
|
|
|
|
|
}
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
out = append(out, v)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// type check the & of closed variables outside the closure,
|
|
|
|
|
// so that the outer frame also grabs them and knows they escape.
|
|
|
|
|
dowidth(v.Type)
|
|
|
|
|
|
2016-05-27 00:56:19 -04:00
|
|
|
outer := v.Name.Param.Outer
|
|
|
|
|
outermost := v.Name.Defn
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// out parameters will be assigned to implicitly upon return.
|
cmd/compile: move some ONAME-specific flags from Node to Name
The IsClosureVar, IsOutputParamHeapAddr, Assigned, Addrtaken,
InlFormal, and InlLocal flags are only interesting for ONAME nodes, so
it's better to set these flags on Name.flags instead of Node.flags.
Two caveats though:
1. Previously, we would set Assigned and Addrtaken on the entire
expression tree involved in an assignment or addressing operation.
However, the rest of the compiler only actually cares about knowing
whether the underlying ONAME (if any) was assigned/addressed.
2. This actually requires bumping Name.flags from bitset8 to bitset16,
whereas it doesn't allow shrinking Node.flags any. However, Name has
some trailing padding bytes, so expanding Name.flags doesn't cost any
memory.
Passes toolstash-check.
Change-Id: I7775d713566a38d5b9723360b1659b79391744c2
Reviewed-on: https://go-review.googlesource.com/c/go/+/200898
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2019-10-12 16:21:55 -07:00
|
|
|
if outermost.Class() != PPARAMOUT && !outermost.Name.Addrtaken() && !outermost.Name.Assigned() && v.Type.Width <= 128 {
|
2017-02-27 19:56:38 +02:00
|
|
|
v.Name.SetByval(true)
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
cmd/compile: move some ONAME-specific flags from Node to Name
The IsClosureVar, IsOutputParamHeapAddr, Assigned, Addrtaken,
InlFormal, and InlLocal flags are only interesting for ONAME nodes, so
it's better to set these flags on Name.flags instead of Node.flags.
Two caveats though:
1. Previously, we would set Assigned and Addrtaken on the entire
expression tree involved in an assignment or addressing operation.
However, the rest of the compiler only actually cares about knowing
whether the underlying ONAME (if any) was assigned/addressed.
2. This actually requires bumping Name.flags from bitset8 to bitset16,
whereas it doesn't allow shrinking Node.flags any. However, Name has
some trailing padding bytes, so expanding Name.flags doesn't cost any
memory.
Passes toolstash-check.
Change-Id: I7775d713566a38d5b9723360b1659b79391744c2
Reviewed-on: https://go-review.googlesource.com/c/go/+/200898
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2019-10-12 16:21:55 -07:00
|
|
|
outermost.Name.SetAddrtaken(true)
|
2016-09-16 11:00:54 +10:00
|
|
|
outer = nod(OADDR, outer, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2020-10-19 11:31:10 +02:00
|
|
|
if Debug.m > 1 {
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
var name *types.Sym
|
2015-05-27 10:42:55 -04:00
|
|
|
if v.Name.Curfn != nil && v.Name.Curfn.Func.Nname != nil {
|
|
|
|
|
name = v.Name.Curfn.Func.Nname.Sym
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
how := "ref"
|
2017-02-27 19:56:38 +02:00
|
|
|
if v.Name.Byval() {
|
2015-02-13 14:40:36 -05:00
|
|
|
how = "value"
|
|
|
|
|
}
|
cmd/compile: move some ONAME-specific flags from Node to Name
The IsClosureVar, IsOutputParamHeapAddr, Assigned, Addrtaken,
InlFormal, and InlLocal flags are only interesting for ONAME nodes, so
it's better to set these flags on Name.flags instead of Node.flags.
Two caveats though:
1. Previously, we would set Assigned and Addrtaken on the entire
expression tree involved in an assignment or addressing operation.
However, the rest of the compiler only actually cares about knowing
whether the underlying ONAME (if any) was assigned/addressed.
2. This actually requires bumping Name.flags from bitset8 to bitset16,
whereas it doesn't allow shrinking Node.flags any. However, Name has
some trailing padding bytes, so expanding Name.flags doesn't cost any
memory.
Passes toolstash-check.
Change-Id: I7775d713566a38d5b9723360b1659b79391744c2
Reviewed-on: https://go-review.googlesource.com/c/go/+/200898
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2019-10-12 16:21:55 -07:00
|
|
|
Warnl(v.Pos, "%v capturing by %s: %v (addr=%v assign=%v width=%d)", name, how, v.Sym, outermost.Name.Addrtaken(), outermost.Name.Assigned(), int32(v.Type.Width))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2018-11-18 08:34:38 -08:00
|
|
|
outer = typecheck(outer, ctxExpr)
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
clo.Func.Enter.Append(outer)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
xfunc.Func.Cvars.Set(out)
|
2016-03-02 17:34:42 -08:00
|
|
|
lineno = lno
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// transformclosure is called in a separate phase after escape analysis.
|
|
|
|
|
// It transform closure bodies to properly reference captured variables.
|
|
|
|
|
func transformclosure(xfunc *Node) {
|
2016-03-02 17:34:42 -08:00
|
|
|
lno := lineno
|
2016-12-07 17:40:46 -08:00
|
|
|
lineno = xfunc.Pos
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
clo := xfunc.Func.Closure
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2018-11-18 08:34:38 -08:00
|
|
|
if clo.Func.Top&ctxCallee != 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
// If the closure is directly called, we transform it to a plain function call
|
|
|
|
|
// with variables passed as args. This avoids allocation of a closure object.
|
|
|
|
|
// Here we do only a part of the transformation. Walk of OCALLFUNC(OCLOSURE)
|
|
|
|
|
// will complete the transformation later.
|
|
|
|
|
// For illustration, the following closure:
|
|
|
|
|
// func(a int) {
|
|
|
|
|
// println(byval)
|
|
|
|
|
// byref++
|
|
|
|
|
// }(42)
|
|
|
|
|
// becomes:
|
2017-04-24 14:30:31 +09:00
|
|
|
// func(byval int, &byref *int, a int) {
|
2015-02-13 14:40:36 -05:00
|
|
|
// println(byval)
|
|
|
|
|
// (*&byref)++
|
2015-07-23 14:17:07 -04:00
|
|
|
// }(byval, &byref, 42)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// f is ONAME of the actual function.
|
2015-05-27 10:42:55 -04:00
|
|
|
f := xfunc.Func.Nname
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-07-23 14:17:07 -04:00
|
|
|
// We are going to insert captured variables before input args.
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
var params []*types.Field
|
2016-03-10 19:05:45 -08:00
|
|
|
var decls []*Node
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
for _, v := range xfunc.Func.Cvars.Slice() {
|
|
|
|
|
if !v.Name.Byval() {
|
2015-02-13 14:40:36 -05:00
|
|
|
// If v of type T is captured by reference,
|
|
|
|
|
// we introduce function param &v *T
|
2016-05-25 10:29:50 -04:00
|
|
|
// and v remains PAUTOHEAP with &v heapaddr
|
2015-02-13 14:40:36 -05:00
|
|
|
// (accesses will implicitly deref &v).
|
2017-03-30 15:44:12 -07:00
|
|
|
addr := newname(lookup("&" + v.Sym.Name))
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
addr.Type = types.NewPtr(v.Type)
|
2016-10-28 11:42:40 -07:00
|
|
|
v.Name.Param.Heapaddr = addr
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
v = addr
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
v.SetClass(PPARAM)
|
|
|
|
|
decls = append(decls, v)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
fld := types.NewField()
|
|
|
|
|
fld.Nname = asTypesNode(v)
|
|
|
|
|
fld.Type = v.Type
|
|
|
|
|
fld.Sym = v.Sym
|
2016-03-10 19:05:45 -08:00
|
|
|
params = append(params, fld)
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-03-10 19:05:45 -08:00
|
|
|
if len(params) > 0 {
|
|
|
|
|
// Prepend params and decls.
|
|
|
|
|
f.Type.Params().SetFields(append(params, f.Type.Params().FieldSlice()...))
|
|
|
|
|
xfunc.Func.Dcl = append(decls, xfunc.Func.Dcl...)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dowidth(f.Type)
|
|
|
|
|
xfunc.Type = f.Type // update type of ODCLFUNC
|
|
|
|
|
} else {
|
|
|
|
|
// The closure is not called, so it is going to stay as closure.
|
2016-02-26 14:28:48 -08:00
|
|
|
var body []*Node
|
2015-02-23 16:07:24 -05:00
|
|
|
offset := int64(Widthptr)
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
for _, v := range xfunc.Func.Cvars.Slice() {
|
2015-02-13 14:40:36 -05:00
|
|
|
// cv refers to the field inside of closure OSTRUCTLIT.
|
2016-09-16 11:00:54 +10:00
|
|
|
cv := nod(OCLOSUREVAR, nil, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
cv.Type = v.Type
|
2017-02-27 19:56:38 +02:00
|
|
|
if !v.Name.Byval() {
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
cv.Type = types.NewPtr(v.Type)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
offset = Rnd(offset, int64(cv.Type.Align))
|
|
|
|
|
cv.Xoffset = offset
|
|
|
|
|
offset += cv.Type.Width
|
|
|
|
|
|
2017-02-27 19:56:38 +02:00
|
|
|
if v.Name.Byval() && v.Type.Width <= int64(2*Widthptr) {
|
2015-06-29 13:56:27 -04:00
|
|
|
// If it is a small variable captured by value, downgrade it to PAUTO.
|
2017-04-25 18:14:12 -07:00
|
|
|
v.SetClass(PAUTO)
|
2016-02-25 10:35:19 -08:00
|
|
|
xfunc.Func.Dcl = append(xfunc.Func.Dcl, v)
|
2016-09-16 11:00:54 +10:00
|
|
|
body = append(body, nod(OAS, v, cv))
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
|
|
|
|
// Declare variable holding addresses taken from closure
|
|
|
|
|
// and initialize in entry prologue.
|
2017-03-30 15:44:12 -07:00
|
|
|
addr := newname(lookup("&" + v.Sym.Name))
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
addr.Type = types.NewPtr(v.Type)
|
2017-04-25 18:14:12 -07:00
|
|
|
addr.SetClass(PAUTO)
|
2017-04-27 15:17:57 -07:00
|
|
|
addr.Name.SetUsed(true)
|
2015-05-27 07:31:56 -04:00
|
|
|
addr.Name.Curfn = xfunc
|
2016-02-25 10:35:19 -08:00
|
|
|
xfunc.Func.Dcl = append(xfunc.Func.Dcl, addr)
|
2016-10-28 11:42:40 -07:00
|
|
|
v.Name.Param.Heapaddr = addr
|
2017-02-27 19:56:38 +02:00
|
|
|
if v.Name.Byval() {
|
2016-09-16 11:00:54 +10:00
|
|
|
cv = nod(OADDR, cv, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-09-16 11:00:54 +10:00
|
|
|
body = append(body, nod(OAS, addr, cv))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-26 14:28:48 -08:00
|
|
|
if len(body) > 0 {
|
2018-11-18 08:34:38 -08:00
|
|
|
typecheckslice(body, ctxStmt)
|
2016-02-26 14:28:48 -08:00
|
|
|
xfunc.Func.Enter.Set(body)
|
2017-02-27 19:56:38 +02:00
|
|
|
xfunc.Func.SetNeedctxt(true)
|
2016-02-26 14:28:48 -08:00
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-02 17:34:42 -08:00
|
|
|
lineno = lno
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2018-11-02 15:18:43 +00:00
|
|
|
// hasemptycvars reports whether closure clo has an
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
// empty list of captured vars.
|
|
|
|
|
func hasemptycvars(clo *Node) bool {
|
|
|
|
|
xfunc := clo.Func.Closure
|
|
|
|
|
return xfunc.Func.Cvars.Len() == 0
|
cmd/compile: ignore OXXX nodes in closure captured vars list
Added a debug flag "-d closure" to explain compilation of
closures (should this be done some other way? Should we
rewrite the "-m" flag to "-d escapes"?) Used this to
discover that cause was an OXXX node in the captured vars
list, and in turn noticed that OXXX nodes are explicitly
ignored in all other processing of captured variables.
Couldn't figure out a reproducer, did verify that this OXXX
was not caused by an unnamed return value (which is one use
of these). Verified lack of heap allocation by examining -S
output.
Assembly:
(runtime/mgc.go:1371) PCDATA $0, $2
(runtime/mgc.go:1371) CALL "".notewakeup(SB)
(runtime/mgc.go:1377) LEAQ "".gcBgMarkWorker.func1·f(SB), AX
(runtime/mgc.go:1404) MOVQ AX, (SP)
(runtime/mgc.go:1404) MOVQ "".autotmp_2242+88(SP), CX
(runtime/mgc.go:1404) MOVQ CX, 8(SP)
(runtime/mgc.go:1404) LEAQ go.string."GC worker (idle)"(SB), AX
(runtime/mgc.go:1404) MOVQ AX, 16(SP)
(runtime/mgc.go:1404) MOVQ $16, 24(SP)
(runtime/mgc.go:1404) MOVB $20, 32(SP)
(runtime/mgc.go:1404) MOVQ $0, 40(SP)
(runtime/mgc.go:1404) PCDATA $0, $2
(runtime/mgc.go:1404) CALL "".gopark(SB)
Added a check for compiling_runtime to ensure that this is
caught in the future. Added a test to test the check.
Verified that 1.5.3 did NOT reject the test case when
compiled with -+ flag, so this is not a recently added bug.
Cause of bug is two-part -- there was no leaking closure
detection ever, and instead it relied on capture-of-variables
to trigger compiling_runtime test, but closures improved in
1.5.3 so that mere capture of a value did not also capture
the variable, which thus allowed closures to escape, as well
as this case where the escape was spurious. In
fixedbugs/issue14999.go, compare messages for f and g;
1.5.3 would reject g, but not f. 1.4 rejects both because
1.4 heap-allocates parameter x for both.
Fixes #14999.
Change-Id: I40bcdd27056810628e96763a44f2acddd503aee1
Reviewed-on: https://go-review.googlesource.com/21322
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2016-03-30 14:14:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// closuredebugruntimecheck applies boilerplate checks for debug flags
|
|
|
|
|
// and compiling runtime
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
func closuredebugruntimecheck(clo *Node) {
|
cmd/compile: ignore OXXX nodes in closure captured vars list
Added a debug flag "-d closure" to explain compilation of
closures (should this be done some other way? Should we
rewrite the "-m" flag to "-d escapes"?) Used this to
discover that cause was an OXXX node in the captured vars
list, and in turn noticed that OXXX nodes are explicitly
ignored in all other processing of captured variables.
Couldn't figure out a reproducer, did verify that this OXXX
was not caused by an unnamed return value (which is one use
of these). Verified lack of heap allocation by examining -S
output.
Assembly:
(runtime/mgc.go:1371) PCDATA $0, $2
(runtime/mgc.go:1371) CALL "".notewakeup(SB)
(runtime/mgc.go:1377) LEAQ "".gcBgMarkWorker.func1·f(SB), AX
(runtime/mgc.go:1404) MOVQ AX, (SP)
(runtime/mgc.go:1404) MOVQ "".autotmp_2242+88(SP), CX
(runtime/mgc.go:1404) MOVQ CX, 8(SP)
(runtime/mgc.go:1404) LEAQ go.string."GC worker (idle)"(SB), AX
(runtime/mgc.go:1404) MOVQ AX, 16(SP)
(runtime/mgc.go:1404) MOVQ $16, 24(SP)
(runtime/mgc.go:1404) MOVB $20, 32(SP)
(runtime/mgc.go:1404) MOVQ $0, 40(SP)
(runtime/mgc.go:1404) PCDATA $0, $2
(runtime/mgc.go:1404) CALL "".gopark(SB)
Added a check for compiling_runtime to ensure that this is
caught in the future. Added a test to test the check.
Verified that 1.5.3 did NOT reject the test case when
compiled with -+ flag, so this is not a recently added bug.
Cause of bug is two-part -- there was no leaking closure
detection ever, and instead it relied on capture-of-variables
to trigger compiling_runtime test, but closures improved in
1.5.3 so that mere capture of a value did not also capture
the variable, which thus allowed closures to escape, as well
as this case where the escape was spurious. In
fixedbugs/issue14999.go, compare messages for f and g;
1.5.3 would reject g, but not f. 1.4 rejects both because
1.4 heap-allocates parameter x for both.
Fixes #14999.
Change-Id: I40bcdd27056810628e96763a44f2acddd503aee1
Reviewed-on: https://go-review.googlesource.com/21322
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2016-03-30 14:14:00 -04:00
|
|
|
if Debug_closure > 0 {
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
xfunc := clo.Func.Closure
|
|
|
|
|
if clo.Esc == EscHeap {
|
|
|
|
|
Warnl(clo.Pos, "heap closure, captured vars = %v", xfunc.Func.Cvars)
|
cmd/compile: ignore OXXX nodes in closure captured vars list
Added a debug flag "-d closure" to explain compilation of
closures (should this be done some other way? Should we
rewrite the "-m" flag to "-d escapes"?) Used this to
discover that cause was an OXXX node in the captured vars
list, and in turn noticed that OXXX nodes are explicitly
ignored in all other processing of captured variables.
Couldn't figure out a reproducer, did verify that this OXXX
was not caused by an unnamed return value (which is one use
of these). Verified lack of heap allocation by examining -S
output.
Assembly:
(runtime/mgc.go:1371) PCDATA $0, $2
(runtime/mgc.go:1371) CALL "".notewakeup(SB)
(runtime/mgc.go:1377) LEAQ "".gcBgMarkWorker.func1·f(SB), AX
(runtime/mgc.go:1404) MOVQ AX, (SP)
(runtime/mgc.go:1404) MOVQ "".autotmp_2242+88(SP), CX
(runtime/mgc.go:1404) MOVQ CX, 8(SP)
(runtime/mgc.go:1404) LEAQ go.string."GC worker (idle)"(SB), AX
(runtime/mgc.go:1404) MOVQ AX, 16(SP)
(runtime/mgc.go:1404) MOVQ $16, 24(SP)
(runtime/mgc.go:1404) MOVB $20, 32(SP)
(runtime/mgc.go:1404) MOVQ $0, 40(SP)
(runtime/mgc.go:1404) PCDATA $0, $2
(runtime/mgc.go:1404) CALL "".gopark(SB)
Added a check for compiling_runtime to ensure that this is
caught in the future. Added a test to test the check.
Verified that 1.5.3 did NOT reject the test case when
compiled with -+ flag, so this is not a recently added bug.
Cause of bug is two-part -- there was no leaking closure
detection ever, and instead it relied on capture-of-variables
to trigger compiling_runtime test, but closures improved in
1.5.3 so that mere capture of a value did not also capture
the variable, which thus allowed closures to escape, as well
as this case where the escape was spurious. In
fixedbugs/issue14999.go, compare messages for f and g;
1.5.3 would reject g, but not f. 1.4 rejects both because
1.4 heap-allocates parameter x for both.
Fixes #14999.
Change-Id: I40bcdd27056810628e96763a44f2acddd503aee1
Reviewed-on: https://go-review.googlesource.com/21322
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2016-03-30 14:14:00 -04:00
|
|
|
} else {
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
Warnl(clo.Pos, "stack closure, captured vars = %v", xfunc.Func.Cvars)
|
cmd/compile: ignore OXXX nodes in closure captured vars list
Added a debug flag "-d closure" to explain compilation of
closures (should this be done some other way? Should we
rewrite the "-m" flag to "-d escapes"?) Used this to
discover that cause was an OXXX node in the captured vars
list, and in turn noticed that OXXX nodes are explicitly
ignored in all other processing of captured variables.
Couldn't figure out a reproducer, did verify that this OXXX
was not caused by an unnamed return value (which is one use
of these). Verified lack of heap allocation by examining -S
output.
Assembly:
(runtime/mgc.go:1371) PCDATA $0, $2
(runtime/mgc.go:1371) CALL "".notewakeup(SB)
(runtime/mgc.go:1377) LEAQ "".gcBgMarkWorker.func1·f(SB), AX
(runtime/mgc.go:1404) MOVQ AX, (SP)
(runtime/mgc.go:1404) MOVQ "".autotmp_2242+88(SP), CX
(runtime/mgc.go:1404) MOVQ CX, 8(SP)
(runtime/mgc.go:1404) LEAQ go.string."GC worker (idle)"(SB), AX
(runtime/mgc.go:1404) MOVQ AX, 16(SP)
(runtime/mgc.go:1404) MOVQ $16, 24(SP)
(runtime/mgc.go:1404) MOVB $20, 32(SP)
(runtime/mgc.go:1404) MOVQ $0, 40(SP)
(runtime/mgc.go:1404) PCDATA $0, $2
(runtime/mgc.go:1404) CALL "".gopark(SB)
Added a check for compiling_runtime to ensure that this is
caught in the future. Added a test to test the check.
Verified that 1.5.3 did NOT reject the test case when
compiled with -+ flag, so this is not a recently added bug.
Cause of bug is two-part -- there was no leaking closure
detection ever, and instead it relied on capture-of-variables
to trigger compiling_runtime test, but closures improved in
1.5.3 so that mere capture of a value did not also capture
the variable, which thus allowed closures to escape, as well
as this case where the escape was spurious. In
fixedbugs/issue14999.go, compare messages for f and g;
1.5.3 would reject g, but not f. 1.4 rejects both because
1.4 heap-allocates parameter x for both.
Fixes #14999.
Change-Id: I40bcdd27056810628e96763a44f2acddd503aee1
Reviewed-on: https://go-review.googlesource.com/21322
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2016-03-30 14:14:00 -04:00
|
|
|
}
|
|
|
|
|
}
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
if compiling_runtime && clo.Esc == EscHeap {
|
2019-10-14 12:16:52 -07:00
|
|
|
yyerrorl(clo.Pos, "heap-allocated closure, not allowed in runtime")
|
cmd/compile: ignore OXXX nodes in closure captured vars list
Added a debug flag "-d closure" to explain compilation of
closures (should this be done some other way? Should we
rewrite the "-m" flag to "-d escapes"?) Used this to
discover that cause was an OXXX node in the captured vars
list, and in turn noticed that OXXX nodes are explicitly
ignored in all other processing of captured variables.
Couldn't figure out a reproducer, did verify that this OXXX
was not caused by an unnamed return value (which is one use
of these). Verified lack of heap allocation by examining -S
output.
Assembly:
(runtime/mgc.go:1371) PCDATA $0, $2
(runtime/mgc.go:1371) CALL "".notewakeup(SB)
(runtime/mgc.go:1377) LEAQ "".gcBgMarkWorker.func1·f(SB), AX
(runtime/mgc.go:1404) MOVQ AX, (SP)
(runtime/mgc.go:1404) MOVQ "".autotmp_2242+88(SP), CX
(runtime/mgc.go:1404) MOVQ CX, 8(SP)
(runtime/mgc.go:1404) LEAQ go.string."GC worker (idle)"(SB), AX
(runtime/mgc.go:1404) MOVQ AX, 16(SP)
(runtime/mgc.go:1404) MOVQ $16, 24(SP)
(runtime/mgc.go:1404) MOVB $20, 32(SP)
(runtime/mgc.go:1404) MOVQ $0, 40(SP)
(runtime/mgc.go:1404) PCDATA $0, $2
(runtime/mgc.go:1404) CALL "".gopark(SB)
Added a check for compiling_runtime to ensure that this is
caught in the future. Added a test to test the check.
Verified that 1.5.3 did NOT reject the test case when
compiled with -+ flag, so this is not a recently added bug.
Cause of bug is two-part -- there was no leaking closure
detection ever, and instead it relied on capture-of-variables
to trigger compiling_runtime test, but closures improved in
1.5.3 so that mere capture of a value did not also capture
the variable, which thus allowed closures to escape, as well
as this case where the escape was spurious. In
fixedbugs/issue14999.go, compare messages for f and g;
1.5.3 would reject g, but not f. 1.4 rejects both because
1.4 heap-allocates parameter x for both.
Fixes #14999.
Change-Id: I40bcdd27056810628e96763a44f2acddd503aee1
Reviewed-on: https://go-review.googlesource.com/21322
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2016-03-30 14:14:00 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-06 14:31:08 -07:00
|
|
|
// closureType returns the struct type used to hold all the information
|
|
|
|
|
// needed in the closure for clo (clo must be a OCLOSURE node).
|
|
|
|
|
// The address of a variable of the returned type can be cast to a func.
|
|
|
|
|
func closureType(clo *Node) *types.Type {
|
2015-02-13 14:40:36 -05:00
|
|
|
// Create closure in the form of a composite literal.
|
|
|
|
|
// supposing the closure captures an int i and a string s
|
|
|
|
|
// and has one float64 argument and no results,
|
|
|
|
|
// the generated code looks like:
|
|
|
|
|
//
|
2015-02-20 13:54:45 -05:00
|
|
|
// clos = &struct{.F uintptr; i *int; s *string}{func.1, &i, &s}
|
2015-02-13 14:40:36 -05:00
|
|
|
//
|
|
|
|
|
// The use of the struct provides type information to the garbage
|
|
|
|
|
// collector so that it can walk the closure. We could use (in this case)
|
|
|
|
|
// [3]unsafe.Pointer instead, but that would leave the gc in the dark.
|
|
|
|
|
// The information appears in the binary in the form of type descriptors;
|
|
|
|
|
// the struct is unnamed so that closures in multiple packages with the
|
|
|
|
|
// same struct type can share the descriptor.
|
2017-09-27 12:55:23 -07:00
|
|
|
fields := []*Node{
|
|
|
|
|
namedfield(".F", types.Types[TUINTPTR]),
|
|
|
|
|
}
|
2018-10-06 14:31:08 -07:00
|
|
|
for _, v := range clo.Func.Closure.Func.Cvars.Slice() {
|
2017-09-27 12:55:23 -07:00
|
|
|
typ := v.Type
|
2017-02-27 19:56:38 +02:00
|
|
|
if !v.Name.Byval() {
|
2017-09-27 12:55:23 -07:00
|
|
|
typ = types.NewPtr(typ)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2017-09-27 12:55:23 -07:00
|
|
|
fields = append(fields, symfield(v.Sym, typ))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2017-09-27 12:55:23 -07:00
|
|
|
typ := tostruct(fields)
|
|
|
|
|
typ.SetNoalg(true)
|
2018-10-06 14:31:08 -07:00
|
|
|
return typ
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func walkclosure(clo *Node, init *Nodes) *Node {
|
|
|
|
|
xfunc := clo.Func.Closure
|
|
|
|
|
|
|
|
|
|
// If no closure vars, don't bother wrapping.
|
|
|
|
|
if hasemptycvars(clo) {
|
|
|
|
|
if Debug_closure > 0 {
|
|
|
|
|
Warnl(clo.Pos, "closure converted to global")
|
|
|
|
|
}
|
|
|
|
|
return xfunc.Func.Nname
|
|
|
|
|
}
|
|
|
|
|
closuredebugruntimecheck(clo)
|
|
|
|
|
|
|
|
|
|
typ := closureType(clo)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2019-09-25 00:21:23 -07:00
|
|
|
clos := nod(OCOMPLIT, nil, typenod(typ))
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
clos.Esc = clo.Esc
|
|
|
|
|
clos.List.Set(append([]*Node{nod(OCFUNC, xfunc.Func.Nname, nil)}, clo.Func.Enter.Slice()...))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2019-09-25 00:21:23 -07:00
|
|
|
clos = nod(OADDR, clos, nil)
|
|
|
|
|
clos.Esc = clo.Esc
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
// Force type conversion from *struct to the func type.
|
2018-05-10 13:25:39 +02:00
|
|
|
clos = convnop(clos, clo.Type)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// non-escaping temp to use, if any.
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
if x := prealloc[clo]; x != nil {
|
2018-10-18 15:24:50 -07:00
|
|
|
if !types.Identical(typ, x.Type) {
|
2018-10-06 14:31:08 -07:00
|
|
|
panic("closure type does not match order's assigned type")
|
|
|
|
|
}
|
2015-05-26 23:05:35 -04:00
|
|
|
clos.Left.Right = x
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
delete(prealloc, clo)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-23 08:51:38 -07:00
|
|
|
return walkexpr(clos, init)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
func typecheckpartialcall(fn *Node, sym *types.Sym) {
|
2015-02-13 14:40:36 -05:00
|
|
|
switch fn.Op {
|
2015-04-01 09:38:44 -07:00
|
|
|
case ODOTINTER, ODOTMETH:
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
|
|
|
|
|
default:
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("invalid typecheckpartialcall")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create top-level function.
|
2015-05-27 10:42:55 -04:00
|
|
|
xfunc := makepartialcall(fn, fn.Type, sym)
|
|
|
|
|
fn.Func = xfunc.Func
|
2020-07-21 15:53:30 -04:00
|
|
|
fn.Func.SetWrapper(true)
|
cmd/compile: change ODOT and friends to use Sym, not Right
The Node type ODOT and its variants all represent a selector, with a
simple name to the right of the dot. Before this change this was
represented by using an ONAME Node in the Right field. This ONAME node
served no useful purpose. This CL changes these Node types to store the
symbol in the Sym field instead, thus not requiring allocating a Node
for each selector.
When compiling x/tools/go/types this CL eliminates nearly 5000 calls to
newname and reduces the total number of Nodes allocated by about 6.6%.
It seems to cut compilation time by 1 to 2 percent.
Getting this right was somewhat subtle, and I added two dubious changes
to produce the exact same output as before. One is to ishairy in
inl.go: the ONAME node increased the cost of ODOT and friends by 1, and
I retained that, although really ODOT is not more expensive than any
other node. The other is to varexpr in walk.go: because the ONAME in
the Right field of an ODOT has no class, varexpr would always return
false for an ODOT, although in fact for some ODOT's it seemingly ought
to return true; I added an && false for now. I will send separate CLs,
that will break toolstash -cmp, to clean these up.
This CL passes toolstash -cmp.
Change-Id: I4af8a10cc59078c436130ce472f25abc3a9b2f80
Reviewed-on: https://go-review.googlesource.com/20890
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-03-18 16:52:30 -07:00
|
|
|
fn.Right = newname(sym)
|
2015-02-13 14:40:36 -05:00
|
|
|
fn.Op = OCALLPART
|
2015-05-27 10:42:55 -04:00
|
|
|
fn.Type = xfunc.Type
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2020-10-19 13:09:55 -07:00
|
|
|
// makepartialcall returns a DCLFUNC node representing the wrapper function (*-fm) needed
|
|
|
|
|
// for partial calls.
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
func makepartialcall(fn *Node, t0 *types.Type, meth *types.Sym) *Node {
|
2015-02-23 16:07:24 -05:00
|
|
|
rcvrtype := fn.Left.Type
|
2018-04-04 18:42:39 -07:00
|
|
|
sym := methodSymSuffix(rcvrtype, meth, "-fm")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2017-03-06 20:00:54 +02:00
|
|
|
if sym.Uniq() {
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
return asNode(sym.Def)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2017-03-06 20:00:54 +02:00
|
|
|
sym.SetUniq(true)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
savecurfn := Curfn
|
2018-12-10 14:19:33 -08:00
|
|
|
saveLineNo := lineno
|
2015-02-13 14:40:36 -05:00
|
|
|
Curfn = nil
|
|
|
|
|
|
2018-12-10 14:19:33 -08:00
|
|
|
// Set line number equal to the line number where the method is declared.
|
|
|
|
|
var m *types.Field
|
2018-12-21 15:41:28 -08:00
|
|
|
if lookdot0(meth, rcvrtype, &m, false) == 1 && m.Pos.IsKnown() {
|
2018-12-10 14:19:33 -08:00
|
|
|
lineno = m.Pos
|
|
|
|
|
}
|
2018-12-21 15:41:28 -08:00
|
|
|
// Note: !m.Pos.IsKnown() happens for method expressions where
|
|
|
|
|
// the method is implicitly declared. The Error method of the
|
|
|
|
|
// built-in error type is one such method. We leave the line
|
|
|
|
|
// number at the use of the method expression in this
|
|
|
|
|
// case. See issue 29389.
|
2018-12-10 14:19:33 -08:00
|
|
|
|
2018-04-18 23:22:26 -07:00
|
|
|
tfn := nod(OTFUNC, nil, nil)
|
|
|
|
|
tfn.List.Set(structargs(t0.Params(), true))
|
|
|
|
|
tfn.Rlist.Set(structargs(t0.Results(), false))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2018-04-18 23:22:26 -07:00
|
|
|
xfunc := dclfunc(sym, tfn)
|
2017-02-27 19:56:38 +02:00
|
|
|
xfunc.Func.SetDupok(true)
|
2018-04-18 23:22:26 -07:00
|
|
|
xfunc.Func.SetNeedctxt(true)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2018-04-01 01:55:55 -07:00
|
|
|
tfn.Type.SetPkg(t0.Pkg())
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
// Declare and initialize variable holding receiver.
|
|
|
|
|
|
2016-09-16 11:00:54 +10:00
|
|
|
cv := nod(OCLOSUREVAR, nil, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
cv.Type = rcvrtype
|
cmd/compile: cleanup closure.go
The main thing is we now eagerly create the ODCLFUNC node for
closures, immediately cross-link them, and assign fields (e.g., Nbody,
Dcl, Parents, Marks) directly on the ODCLFUNC (previously they were
assigned on the OCLOSURE and later moved to the ODCLFUNC).
This allows us to set Curfn to the ODCLFUNC instead of the OCLOSURE,
which makes things more consistent with normal function declarations.
(Notably, this means Cvars now hang off the ODCLFUNC instead of the
OCLOSURE.)
Assignment of xfunc symbol names also now happens before typechecking
their body, which means debugging output now provides a more helpful
name than "<S>".
In golang.org/cl/66810, we changed "x := y" statements to avoid
creating false closure variables for x, but we still create them for
struct literals like "s{f: x}". Update comment in capturevars
accordingly.
More opportunity for cleanups still, but this makes some substantial
progress, IMO.
Passes toolstash-check.
Change-Id: I65a4efc91886e3dcd1000561348af88297775cd7
Reviewed-on: https://go-review.googlesource.com/100197
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-08 06:25:04 -08:00
|
|
|
cv.Xoffset = Rnd(int64(Widthptr), int64(cv.Type.Align))
|
|
|
|
|
|
2018-04-18 23:22:26 -07:00
|
|
|
ptr := newname(lookup(".this"))
|
|
|
|
|
declare(ptr, PAUTO)
|
2017-04-27 15:17:57 -07:00
|
|
|
ptr.Name.SetUsed(true)
|
2016-02-27 14:31:33 -08:00
|
|
|
var body []*Node
|
2016-03-30 15:09:25 -07:00
|
|
|
if rcvrtype.IsPtr() || rcvrtype.IsInterface() {
|
2017-04-05 18:52:33 -07:00
|
|
|
ptr.Type = rcvrtype
|
2016-09-16 11:00:54 +10:00
|
|
|
body = append(body, nod(OAS, ptr, cv))
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
ptr.Type = types.NewPtr(rcvrtype)
|
2016-09-16 11:00:54 +10:00
|
|
|
body = append(body, nod(OAS, ptr, nod(OADDR, cv, nil)))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-09-16 11:00:54 +10:00
|
|
|
call := nod(OCALL, nodSym(OXDOT, ptr, meth), nil)
|
2018-04-18 23:22:26 -07:00
|
|
|
call.List.Set(paramNnames(tfn.Type))
|
2018-11-18 08:34:38 -08:00
|
|
|
call.SetIsDDD(tfn.Type.IsVariadic())
|
2018-04-18 23:22:26 -07:00
|
|
|
if t0.NumResults() != 0 {
|
|
|
|
|
n := nod(ORETURN, nil, nil)
|
|
|
|
|
n.List.Set1(call)
|
|
|
|
|
call = n
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2018-04-18 23:22:26 -07:00
|
|
|
body = append(body, call)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-02-27 14:31:33 -08:00
|
|
|
xfunc.Nbody.Set(body)
|
2018-04-18 23:22:26 -07:00
|
|
|
funcbody()
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2018-11-18 08:34:38 -08:00
|
|
|
xfunc = typecheck(xfunc, ctxStmt)
|
2020-10-19 13:09:55 -07:00
|
|
|
// Need to typecheck the body of the just-generated wrapper.
|
|
|
|
|
// typecheckslice() requires that Curfn is set when processing an ORETURN.
|
|
|
|
|
Curfn = xfunc
|
|
|
|
|
typecheckslice(xfunc.Nbody.Slice(), ctxStmt)
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
sym.Def = asTypesNode(xfunc)
|
2016-03-09 20:29:21 -08:00
|
|
|
xtop = append(xtop, xfunc)
|
2015-02-13 14:40:36 -05:00
|
|
|
Curfn = savecurfn
|
2018-12-10 14:19:33 -08:00
|
|
|
lineno = saveLineNo
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
return xfunc
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-06 14:31:08 -07:00
|
|
|
// partialCallType returns the struct type used to hold all the information
|
|
|
|
|
// needed in the closure for n (n must be a OCALLPART node).
|
|
|
|
|
// The address of a variable of the returned type can be cast to a func.
|
|
|
|
|
func partialCallType(n *Node) *types.Type {
|
|
|
|
|
t := tostruct([]*Node{
|
|
|
|
|
namedfield("F", types.Types[TUINTPTR]),
|
|
|
|
|
namedfield("R", n.Left.Type),
|
|
|
|
|
})
|
|
|
|
|
t.SetNoalg(true)
|
|
|
|
|
return t
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-07 22:54:46 -08:00
|
|
|
func walkpartialcall(n *Node, init *Nodes) *Node {
|
2015-02-13 14:40:36 -05:00
|
|
|
// Create closure in the form of a composite literal.
|
|
|
|
|
// For x.M with receiver (x) type T, the generated code looks like:
|
|
|
|
|
//
|
2020-07-27 12:08:56 +07:00
|
|
|
// clos = &struct{F uintptr; R T}{T.M·f, x}
|
2015-02-13 14:40:36 -05:00
|
|
|
//
|
|
|
|
|
// Like walkclosure above.
|
|
|
|
|
|
2016-03-30 14:45:47 -07:00
|
|
|
if n.Left.Type.IsInterface() {
|
2015-02-13 14:40:36 -05:00
|
|
|
// Trigger panic for method on nil interface now.
|
|
|
|
|
// Otherwise it happens in the wrapper and is confusing.
|
|
|
|
|
n.Left = cheapexpr(n.Left, init)
|
2018-11-10 07:00:32 -08:00
|
|
|
n.Left = walkexpr(n.Left, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2018-11-10 07:00:32 -08:00
|
|
|
tab := nod(OITAB, n.Left, nil)
|
|
|
|
|
tab = typecheck(tab, ctxExpr)
|
|
|
|
|
|
|
|
|
|
c := nod(OCHECKNIL, tab, nil)
|
|
|
|
|
c.SetTypecheck(1)
|
|
|
|
|
init.Append(c)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2018-10-06 14:31:08 -07:00
|
|
|
typ := partialCallType(n)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2019-09-25 00:21:23 -07:00
|
|
|
clos := nod(OCOMPLIT, nil, typenod(typ))
|
2015-02-13 14:40:36 -05:00
|
|
|
clos.Esc = n.Esc
|
2018-10-06 14:31:08 -07:00
|
|
|
clos.List.Set2(nod(OCFUNC, n.Func.Nname, nil), n.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2019-09-25 00:21:23 -07:00
|
|
|
clos = nod(OADDR, clos, nil)
|
|
|
|
|
clos.Esc = n.Esc
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
// Force type conversion from *struct to the func type.
|
2018-05-10 13:25:39 +02:00
|
|
|
clos = convnop(clos, n.Type)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// non-escaping temp to use, if any.
|
2015-05-26 23:05:35 -04:00
|
|
|
if x := prealloc[n]; x != nil {
|
2018-10-18 15:24:50 -07:00
|
|
|
if !types.Identical(typ, x.Type) {
|
2018-10-06 14:31:08 -07:00
|
|
|
panic("partial call type does not match order's assigned type")
|
|
|
|
|
}
|
2015-05-26 23:05:35 -04:00
|
|
|
clos.Left.Right = x
|
|
|
|
|
delete(prealloc, n)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-23 08:51:38 -07:00
|
|
|
return walkexpr(clos, init)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-04-20 11:14:36 -07:00
|
|
|
|
|
|
|
|
// callpartMethod returns the *types.Field representing the method
|
|
|
|
|
// referenced by method value n.
|
|
|
|
|
func callpartMethod(n *Node) *types.Field {
|
|
|
|
|
if n.Op != OCALLPART {
|
|
|
|
|
Fatalf("expected OCALLPART, got %v", n)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO(mdempsky): Optimize this. If necessary,
|
|
|
|
|
// makepartialcall could save m for us somewhere.
|
|
|
|
|
var m *types.Field
|
|
|
|
|
if lookdot0(n.Right.Sym, n.Left.Type, &m, false) != 1 {
|
|
|
|
|
Fatalf("failed to find field for OCALLPART")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return m
|
|
|
|
|
}
|