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
|
|
|
|
|
|
2017-03-20 11:56:15 -07:00
|
|
|
import (
|
2020-09-29 02:11:10 -07:00
|
|
|
"bytes"
|
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"
|
2020-09-29 02:11:10 -07:00
|
|
|
"fmt"
|
2017-03-20 11:56:15 -07:00
|
|
|
"sort"
|
|
|
|
|
)
|
|
|
|
|
|
2017-04-27 16:37:25 -07:00
|
|
|
// sizeCalculationDisabled indicates whether it is safe
|
|
|
|
|
// to calculate Types' widths and alignments. See dowidth.
|
|
|
|
|
var sizeCalculationDisabled bool
|
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// machine size and rounding alignment is dictated around
|
|
|
|
|
// the size of a pointer, set in betypeinit (see ../amd64/galign.go).
|
2015-02-13 14:40:36 -05:00
|
|
|
var defercalc int
|
|
|
|
|
|
|
|
|
|
func Rnd(o int64, r int64) int64 {
|
|
|
|
|
if r < 1 || r > 8 || r&(r-1) != 0 {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("rnd %d", r)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
return (o + r - 1) &^ (r - 1)
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-20 11:56:15 -07:00
|
|
|
// expandiface computes the method set for interface type t by
|
|
|
|
|
// expanding embedded interfaces.
|
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 expandiface(t *types.Type) {
|
2019-07-24 17:43:31 -07:00
|
|
|
seen := make(map[*types.Sym]*types.Field)
|
|
|
|
|
var methods []*types.Field
|
|
|
|
|
|
|
|
|
|
addMethod := func(m *types.Field, explicit bool) {
|
|
|
|
|
switch prev := seen[m.Sym]; {
|
|
|
|
|
case prev == nil:
|
|
|
|
|
seen[m.Sym] = m
|
2019-11-07 15:54:59 -08:00
|
|
|
case langSupported(1, 14, t.Pkg()) && !explicit && types.Identical(m.Type, prev.Type):
|
2019-07-24 17:43:31 -07:00
|
|
|
return
|
|
|
|
|
default:
|
|
|
|
|
yyerrorl(m.Pos, "duplicate method %s", m.Sym.Name)
|
|
|
|
|
}
|
|
|
|
|
methods = append(methods, m)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, m := range t.Methods().Slice() {
|
|
|
|
|
if m.Sym == nil {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
checkwidth(m.Type)
|
|
|
|
|
addMethod(m, true)
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-20 11:56:15 -07:00
|
|
|
for _, m := range t.Methods().Slice() {
|
|
|
|
|
if m.Sym != nil {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !m.Type.IsInterface() {
|
cmd/compile: replace Field.Nname.Pos with Field.Pos
For struct fields and methods, Field.Nname was only used to store
position information, which means we're allocating an entire ONAME
Node+Name+Param structure just for one field. We can optimize away
these ONAME allocations by instead adding a Field.Pos field.
Unfortunately, we can't get rid of Field.Nname, because it's needed
for function parameters, so Field grows a little bit and now has more
redundant information in those cases. However, that was already the
case (e.g., Field.Sym and Field.Nname.Sym), and it's still a net win
for allocations as demonstrated by the benchmarks below.
Additionally, by moving the ONAME allocation for function parameters
to funcargs, we can avoid allocating them for function parameters that
aren't used in corresponding function bodies (e.g., interface methods,
function-typed variables, and imported functions/methods without
inline bodies).
name old time/op new time/op delta
Template 254ms ± 6% 251ms ± 6% -1.04% (p=0.000 n=487+488)
Unicode 128ms ± 7% 128ms ± 7% ~ (p=0.294 n=482+467)
GoTypes 862ms ± 5% 860ms ± 4% ~ (p=0.075 n=488+471)
Compiler 3.91s ± 4% 3.90s ± 4% -0.39% (p=0.000 n=468+473)
name old user-time/op new user-time/op delta
Template 339ms ±14% 336ms ±14% -1.02% (p=0.001 n=498+494)
Unicode 176ms ±18% 176ms ±25% ~ (p=0.940 n=491+499)
GoTypes 1.13s ± 8% 1.13s ± 9% ~ (p=0.157 n=496+493)
Compiler 5.24s ± 6% 5.21s ± 6% -0.57% (p=0.000 n=485+489)
name old alloc/op new alloc/op delta
Template 38.3MB ± 0% 37.3MB ± 0% -2.58% (p=0.000 n=499+497)
Unicode 29.1MB ± 0% 29.1MB ± 0% -0.03% (p=0.000 n=500+493)
GoTypes 116MB ± 0% 115MB ± 0% -0.65% (p=0.000 n=498+499)
Compiler 492MB ± 0% 487MB ± 0% -1.00% (p=0.000 n=497+498)
name old allocs/op new allocs/op delta
Template 364k ± 0% 360k ± 0% -1.15% (p=0.000 n=499+499)
Unicode 336k ± 0% 336k ± 0% -0.01% (p=0.000 n=500+493)
GoTypes 1.16M ± 0% 1.16M ± 0% -0.30% (p=0.000 n=499+499)
Compiler 4.54M ± 0% 4.51M ± 0% -0.58% (p=0.000 n=494+495)
Passes toolstash-check -gcflags=-dwarf=false. Changes DWARF output
because position information is now tracked more precisely for
function parameters.
Change-Id: Ib8077d70d564cc448c5e4290baceab3a4396d712
Reviewed-on: https://go-review.googlesource.com/108217
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-04-18 22:57:10 -07:00
|
|
|
yyerrorl(m.Pos, "interface contains embedded non-interface %v", m.Type)
|
2017-03-20 11:56:15 -07:00
|
|
|
m.SetBroke(true)
|
|
|
|
|
t.SetBroke(true)
|
|
|
|
|
// Add to fields so that error messages
|
|
|
|
|
// include the broken embedded type when
|
|
|
|
|
// printing t.
|
|
|
|
|
// TODO(mdempsky): Revisit this.
|
2019-07-24 17:43:31 -07:00
|
|
|
methods = append(methods, m)
|
2017-03-20 11:56:15 -07:00
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Embedded interface: duplicate all methods
|
|
|
|
|
// (including broken ones, if any) and add to t's
|
|
|
|
|
// method set.
|
|
|
|
|
for _, t1 := range m.Type.Fields().Slice() {
|
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
|
|
|
f := types.NewField()
|
cmd/compile: replace Field.Nname.Pos with Field.Pos
For struct fields and methods, Field.Nname was only used to store
position information, which means we're allocating an entire ONAME
Node+Name+Param structure just for one field. We can optimize away
these ONAME allocations by instead adding a Field.Pos field.
Unfortunately, we can't get rid of Field.Nname, because it's needed
for function parameters, so Field grows a little bit and now has more
redundant information in those cases. However, that was already the
case (e.g., Field.Sym and Field.Nname.Sym), and it's still a net win
for allocations as demonstrated by the benchmarks below.
Additionally, by moving the ONAME allocation for function parameters
to funcargs, we can avoid allocating them for function parameters that
aren't used in corresponding function bodies (e.g., interface methods,
function-typed variables, and imported functions/methods without
inline bodies).
name old time/op new time/op delta
Template 254ms ± 6% 251ms ± 6% -1.04% (p=0.000 n=487+488)
Unicode 128ms ± 7% 128ms ± 7% ~ (p=0.294 n=482+467)
GoTypes 862ms ± 5% 860ms ± 4% ~ (p=0.075 n=488+471)
Compiler 3.91s ± 4% 3.90s ± 4% -0.39% (p=0.000 n=468+473)
name old user-time/op new user-time/op delta
Template 339ms ±14% 336ms ±14% -1.02% (p=0.001 n=498+494)
Unicode 176ms ±18% 176ms ±25% ~ (p=0.940 n=491+499)
GoTypes 1.13s ± 8% 1.13s ± 9% ~ (p=0.157 n=496+493)
Compiler 5.24s ± 6% 5.21s ± 6% -0.57% (p=0.000 n=485+489)
name old alloc/op new alloc/op delta
Template 38.3MB ± 0% 37.3MB ± 0% -2.58% (p=0.000 n=499+497)
Unicode 29.1MB ± 0% 29.1MB ± 0% -0.03% (p=0.000 n=500+493)
GoTypes 116MB ± 0% 115MB ± 0% -0.65% (p=0.000 n=498+499)
Compiler 492MB ± 0% 487MB ± 0% -1.00% (p=0.000 n=497+498)
name old allocs/op new allocs/op delta
Template 364k ± 0% 360k ± 0% -1.15% (p=0.000 n=499+499)
Unicode 336k ± 0% 336k ± 0% -0.01% (p=0.000 n=500+493)
GoTypes 1.16M ± 0% 1.16M ± 0% -0.30% (p=0.000 n=499+499)
Compiler 4.54M ± 0% 4.51M ± 0% -0.58% (p=0.000 n=494+495)
Passes toolstash-check -gcflags=-dwarf=false. Changes DWARF output
because position information is now tracked more precisely for
function parameters.
Change-Id: Ib8077d70d564cc448c5e4290baceab3a4396d712
Reviewed-on: https://go-review.googlesource.com/108217
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-04-18 22:57:10 -07:00
|
|
|
f.Pos = m.Pos // preserve embedding position
|
|
|
|
|
f.Sym = t1.Sym
|
2017-03-20 11:56:15 -07:00
|
|
|
f.Type = t1.Type
|
|
|
|
|
f.SetBroke(t1.Broke())
|
2019-07-24 17:43:31 -07:00
|
|
|
addMethod(f, false)
|
2017-03-20 11:56:15 -07:00
|
|
|
}
|
|
|
|
|
}
|
2019-07-24 17:09:15 -07:00
|
|
|
|
2019-07-24 17:43:31 -07:00
|
|
|
sort.Sort(methcmp(methods))
|
2019-07-24 17:09:15 -07:00
|
|
|
|
2019-07-24 17:43:31 -07:00
|
|
|
if int64(len(methods)) >= thearch.MAXWIDTH/int64(Widthptr) {
|
2019-07-24 17:09:15 -07:00
|
|
|
yyerror("interface too large")
|
|
|
|
|
}
|
2019-07-24 17:43:31 -07:00
|
|
|
for i, m := range methods {
|
|
|
|
|
m.Offset = int64(i) * int64(Widthptr)
|
2019-07-24 17:09:15 -07:00
|
|
|
}
|
2017-03-20 11:56:15 -07:00
|
|
|
|
|
|
|
|
// Access fields directly to avoid recursively calling dowidth
|
|
|
|
|
// within Type.Fields().
|
2019-07-24 17:43:31 -07:00
|
|
|
t.Extra.(*types.Interface).Fields.Set(methods)
|
2017-03-20 11:56:15 -07: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 widstruct(errtype *types.Type, t *types.Type, o int64, flag int) int64 {
|
2015-02-23 16:07:24 -05:00
|
|
|
starto := o
|
|
|
|
|
maxalign := int32(flag)
|
2015-02-13 14:40:36 -05:00
|
|
|
if maxalign < 1 {
|
|
|
|
|
maxalign = 1
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
lastzero := int64(0)
|
2016-03-17 01:32:18 -07:00
|
|
|
for _, f := range t.Fields().Slice() {
|
2015-02-13 14:40:36 -05:00
|
|
|
if f.Type == nil {
|
|
|
|
|
// broken field, just skip it so that other valid fields
|
|
|
|
|
// get a width.
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dowidth(f.Type)
|
|
|
|
|
if int32(f.Type.Align) > maxalign {
|
|
|
|
|
maxalign = int32(f.Type.Align)
|
|
|
|
|
}
|
|
|
|
|
if f.Type.Align > 0 {
|
|
|
|
|
o = Rnd(o, int64(f.Type.Align))
|
|
|
|
|
}
|
2016-03-28 09:40:53 -07:00
|
|
|
f.Offset = o
|
cmd/compile: replace Field.Nname.Pos with Field.Pos
For struct fields and methods, Field.Nname was only used to store
position information, which means we're allocating an entire ONAME
Node+Name+Param structure just for one field. We can optimize away
these ONAME allocations by instead adding a Field.Pos field.
Unfortunately, we can't get rid of Field.Nname, because it's needed
for function parameters, so Field grows a little bit and now has more
redundant information in those cases. However, that was already the
case (e.g., Field.Sym and Field.Nname.Sym), and it's still a net win
for allocations as demonstrated by the benchmarks below.
Additionally, by moving the ONAME allocation for function parameters
to funcargs, we can avoid allocating them for function parameters that
aren't used in corresponding function bodies (e.g., interface methods,
function-typed variables, and imported functions/methods without
inline bodies).
name old time/op new time/op delta
Template 254ms ± 6% 251ms ± 6% -1.04% (p=0.000 n=487+488)
Unicode 128ms ± 7% 128ms ± 7% ~ (p=0.294 n=482+467)
GoTypes 862ms ± 5% 860ms ± 4% ~ (p=0.075 n=488+471)
Compiler 3.91s ± 4% 3.90s ± 4% -0.39% (p=0.000 n=468+473)
name old user-time/op new user-time/op delta
Template 339ms ±14% 336ms ±14% -1.02% (p=0.001 n=498+494)
Unicode 176ms ±18% 176ms ±25% ~ (p=0.940 n=491+499)
GoTypes 1.13s ± 8% 1.13s ± 9% ~ (p=0.157 n=496+493)
Compiler 5.24s ± 6% 5.21s ± 6% -0.57% (p=0.000 n=485+489)
name old alloc/op new alloc/op delta
Template 38.3MB ± 0% 37.3MB ± 0% -2.58% (p=0.000 n=499+497)
Unicode 29.1MB ± 0% 29.1MB ± 0% -0.03% (p=0.000 n=500+493)
GoTypes 116MB ± 0% 115MB ± 0% -0.65% (p=0.000 n=498+499)
Compiler 492MB ± 0% 487MB ± 0% -1.00% (p=0.000 n=497+498)
name old allocs/op new allocs/op delta
Template 364k ± 0% 360k ± 0% -1.15% (p=0.000 n=499+499)
Unicode 336k ± 0% 336k ± 0% -0.01% (p=0.000 n=500+493)
GoTypes 1.16M ± 0% 1.16M ± 0% -0.30% (p=0.000 n=499+499)
Compiler 4.54M ± 0% 4.51M ± 0% -0.58% (p=0.000 n=494+495)
Passes toolstash-check -gcflags=-dwarf=false. Changes DWARF output
because position information is now tracked more precisely for
function parameters.
Change-Id: Ib8077d70d564cc448c5e4290baceab3a4396d712
Reviewed-on: https://go-review.googlesource.com/108217
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-04-18 22:57:10 -07:00
|
|
|
if n := asNode(f.Nname); n != nil {
|
cmd/compile: fix liveness computation for heap-escaped parameters
The liveness computation of parameters generally was never
correct, but forcing all parameters to be live throughout the
function covered up that problem. The new SSA back end is
too clever: even though it currently keeps the parameter values live
throughout the function, it may find optimizations that mean
the current values are not written back to the original parameter
stack slots immediately or ever (for example if a parameter is set
to nil, SSA constant propagation may replace all later uses of the
parameter with a constant nil, eliminating the need to write the nil
value back to the stack slot), so the liveness code must now
track the actual operations on the stack slots, exposing these
problems.
One small problem in the handling of arguments is that nodarg
can return ONAME PPARAM nodes with adjusted offsets, so that
there are actually multiple *Node pointers for the same parameter
in the instruction stream. This might be possible to correct, but
not in this CL. For now, we fix this by using n.Orig instead of n
when considering PPARAM and PPARAMOUT nodes.
The major problem in the handling of arguments is general
confusion in the liveness code about the meaning of PPARAM|PHEAP
and PPARAMOUT|PHEAP nodes, especially as contrasted with PAUTO|PHEAP.
The difference between these two is that when a local variable "moves"
to the heap, it's really just allocated there to start with; in contrast,
when an argument moves to the heap, the actual data has to be copied
there from the stack at the beginning of the function, and when a
result "moves" to the heap the value in the heap has to be copied
back to the stack when the function returns
This general confusion is also present in the SSA back end.
The PHEAP bit worked decently when I first introduced it 7 years ago (!)
in 391425ae. The back end did nothing sophisticated, and in particular
there was no analysis at all: no escape analysis, no liveness analysis,
and certainly no SSA back end. But the complications caused in the
various downstream consumers suggest that this should be a detail
kept mainly in the front end.
This CL therefore eliminates both the PHEAP bit and even the idea of
"heap variables" from the back ends.
First, it replaces the PPARAM|PHEAP, PPARAMOUT|PHEAP, and PAUTO|PHEAP
variable classes with the single PAUTOHEAP, a pseudo-class indicating
a variable maintained on the heap and available by indirecting a
local variable kept on the stack (a plain PAUTO).
Second, walkexpr replaces all references to PAUTOHEAP variables
with indirections of the corresponding PAUTO variable.
The back ends and the liveness code now just see plain indirected
variables. This may actually produce better code, but the real goal
here is to eliminate these little-used and somewhat suspect code
paths in the back end analyses.
The OPARAM node type goes away too.
A followup CL will do the same to PPARAMREF. I'm not sure that
the back ends (SSA in particular) are handling those right either,
and with the framework established in this CL that change is trivial
and the result clearly more correct.
Fixes #15747.
Change-Id: I2770b1ce3cbc93981bfc7166be66a9da12013d74
Reviewed-on: https://go-review.googlesource.com/23393
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-05-25 01:33:24 -04:00
|
|
|
// addrescapes has similar code to update these offsets.
|
|
|
|
|
// Usually addrescapes runs after widstruct,
|
|
|
|
|
// in which case we could drop this,
|
2015-02-13 14:40:36 -05:00
|
|
|
// but function closure functions are the exception.
|
cmd/compile: fix liveness computation for heap-escaped parameters
The liveness computation of parameters generally was never
correct, but forcing all parameters to be live throughout the
function covered up that problem. The new SSA back end is
too clever: even though it currently keeps the parameter values live
throughout the function, it may find optimizations that mean
the current values are not written back to the original parameter
stack slots immediately or ever (for example if a parameter is set
to nil, SSA constant propagation may replace all later uses of the
parameter with a constant nil, eliminating the need to write the nil
value back to the stack slot), so the liveness code must now
track the actual operations on the stack slots, exposing these
problems.
One small problem in the handling of arguments is that nodarg
can return ONAME PPARAM nodes with adjusted offsets, so that
there are actually multiple *Node pointers for the same parameter
in the instruction stream. This might be possible to correct, but
not in this CL. For now, we fix this by using n.Orig instead of n
when considering PPARAM and PPARAMOUT nodes.
The major problem in the handling of arguments is general
confusion in the liveness code about the meaning of PPARAM|PHEAP
and PPARAMOUT|PHEAP nodes, especially as contrasted with PAUTO|PHEAP.
The difference between these two is that when a local variable "moves"
to the heap, it's really just allocated there to start with; in contrast,
when an argument moves to the heap, the actual data has to be copied
there from the stack at the beginning of the function, and when a
result "moves" to the heap the value in the heap has to be copied
back to the stack when the function returns
This general confusion is also present in the SSA back end.
The PHEAP bit worked decently when I first introduced it 7 years ago (!)
in 391425ae. The back end did nothing sophisticated, and in particular
there was no analysis at all: no escape analysis, no liveness analysis,
and certainly no SSA back end. But the complications caused in the
various downstream consumers suggest that this should be a detail
kept mainly in the front end.
This CL therefore eliminates both the PHEAP bit and even the idea of
"heap variables" from the back ends.
First, it replaces the PPARAM|PHEAP, PPARAMOUT|PHEAP, and PAUTO|PHEAP
variable classes with the single PAUTOHEAP, a pseudo-class indicating
a variable maintained on the heap and available by indirecting a
local variable kept on the stack (a plain PAUTO).
Second, walkexpr replaces all references to PAUTOHEAP variables
with indirections of the corresponding PAUTO variable.
The back ends and the liveness code now just see plain indirected
variables. This may actually produce better code, but the real goal
here is to eliminate these little-used and somewhat suspect code
paths in the back end analyses.
The OPARAM node type goes away too.
A followup CL will do the same to PPARAMREF. I'm not sure that
the back ends (SSA in particular) are handling those right either,
and with the framework established in this CL that change is trivial
and the result clearly more correct.
Fixes #15747.
Change-Id: I2770b1ce3cbc93981bfc7166be66a9da12013d74
Reviewed-on: https://go-review.googlesource.com/23393
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-05-25 01:33:24 -04:00
|
|
|
// NOTE(rsc): This comment may be stale.
|
|
|
|
|
// It's possible the ordering has changed and this is
|
|
|
|
|
// now the common case. I'm not sure.
|
cmd/compile: replace Field.Nname.Pos with Field.Pos
For struct fields and methods, Field.Nname was only used to store
position information, which means we're allocating an entire ONAME
Node+Name+Param structure just for one field. We can optimize away
these ONAME allocations by instead adding a Field.Pos field.
Unfortunately, we can't get rid of Field.Nname, because it's needed
for function parameters, so Field grows a little bit and now has more
redundant information in those cases. However, that was already the
case (e.g., Field.Sym and Field.Nname.Sym), and it's still a net win
for allocations as demonstrated by the benchmarks below.
Additionally, by moving the ONAME allocation for function parameters
to funcargs, we can avoid allocating them for function parameters that
aren't used in corresponding function bodies (e.g., interface methods,
function-typed variables, and imported functions/methods without
inline bodies).
name old time/op new time/op delta
Template 254ms ± 6% 251ms ± 6% -1.04% (p=0.000 n=487+488)
Unicode 128ms ± 7% 128ms ± 7% ~ (p=0.294 n=482+467)
GoTypes 862ms ± 5% 860ms ± 4% ~ (p=0.075 n=488+471)
Compiler 3.91s ± 4% 3.90s ± 4% -0.39% (p=0.000 n=468+473)
name old user-time/op new user-time/op delta
Template 339ms ±14% 336ms ±14% -1.02% (p=0.001 n=498+494)
Unicode 176ms ±18% 176ms ±25% ~ (p=0.940 n=491+499)
GoTypes 1.13s ± 8% 1.13s ± 9% ~ (p=0.157 n=496+493)
Compiler 5.24s ± 6% 5.21s ± 6% -0.57% (p=0.000 n=485+489)
name old alloc/op new alloc/op delta
Template 38.3MB ± 0% 37.3MB ± 0% -2.58% (p=0.000 n=499+497)
Unicode 29.1MB ± 0% 29.1MB ± 0% -0.03% (p=0.000 n=500+493)
GoTypes 116MB ± 0% 115MB ± 0% -0.65% (p=0.000 n=498+499)
Compiler 492MB ± 0% 487MB ± 0% -1.00% (p=0.000 n=497+498)
name old allocs/op new allocs/op delta
Template 364k ± 0% 360k ± 0% -1.15% (p=0.000 n=499+499)
Unicode 336k ± 0% 336k ± 0% -0.01% (p=0.000 n=500+493)
GoTypes 1.16M ± 0% 1.16M ± 0% -0.30% (p=0.000 n=499+499)
Compiler 4.54M ± 0% 4.51M ± 0% -0.58% (p=0.000 n=494+495)
Passes toolstash-check -gcflags=-dwarf=false. Changes DWARF output
because position information is now tracked more precisely for
function parameters.
Change-Id: Ib8077d70d564cc448c5e4290baceab3a4396d712
Reviewed-on: https://go-review.googlesource.com/108217
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-04-18 22:57:10 -07:00
|
|
|
if n.Name.Param.Stackcopy != nil {
|
|
|
|
|
n.Name.Param.Stackcopy.Xoffset = o
|
|
|
|
|
n.Xoffset = 0
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
cmd/compile: replace Field.Nname.Pos with Field.Pos
For struct fields and methods, Field.Nname was only used to store
position information, which means we're allocating an entire ONAME
Node+Name+Param structure just for one field. We can optimize away
these ONAME allocations by instead adding a Field.Pos field.
Unfortunately, we can't get rid of Field.Nname, because it's needed
for function parameters, so Field grows a little bit and now has more
redundant information in those cases. However, that was already the
case (e.g., Field.Sym and Field.Nname.Sym), and it's still a net win
for allocations as demonstrated by the benchmarks below.
Additionally, by moving the ONAME allocation for function parameters
to funcargs, we can avoid allocating them for function parameters that
aren't used in corresponding function bodies (e.g., interface methods,
function-typed variables, and imported functions/methods without
inline bodies).
name old time/op new time/op delta
Template 254ms ± 6% 251ms ± 6% -1.04% (p=0.000 n=487+488)
Unicode 128ms ± 7% 128ms ± 7% ~ (p=0.294 n=482+467)
GoTypes 862ms ± 5% 860ms ± 4% ~ (p=0.075 n=488+471)
Compiler 3.91s ± 4% 3.90s ± 4% -0.39% (p=0.000 n=468+473)
name old user-time/op new user-time/op delta
Template 339ms ±14% 336ms ±14% -1.02% (p=0.001 n=498+494)
Unicode 176ms ±18% 176ms ±25% ~ (p=0.940 n=491+499)
GoTypes 1.13s ± 8% 1.13s ± 9% ~ (p=0.157 n=496+493)
Compiler 5.24s ± 6% 5.21s ± 6% -0.57% (p=0.000 n=485+489)
name old alloc/op new alloc/op delta
Template 38.3MB ± 0% 37.3MB ± 0% -2.58% (p=0.000 n=499+497)
Unicode 29.1MB ± 0% 29.1MB ± 0% -0.03% (p=0.000 n=500+493)
GoTypes 116MB ± 0% 115MB ± 0% -0.65% (p=0.000 n=498+499)
Compiler 492MB ± 0% 487MB ± 0% -1.00% (p=0.000 n=497+498)
name old allocs/op new allocs/op delta
Template 364k ± 0% 360k ± 0% -1.15% (p=0.000 n=499+499)
Unicode 336k ± 0% 336k ± 0% -0.01% (p=0.000 n=500+493)
GoTypes 1.16M ± 0% 1.16M ± 0% -0.30% (p=0.000 n=499+499)
Compiler 4.54M ± 0% 4.51M ± 0% -0.58% (p=0.000 n=494+495)
Passes toolstash-check -gcflags=-dwarf=false. Changes DWARF output
because position information is now tracked more precisely for
function parameters.
Change-Id: Ib8077d70d564cc448c5e4290baceab3a4396d712
Reviewed-on: https://go-review.googlesource.com/108217
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-04-18 22:57:10 -07:00
|
|
|
n.Xoffset = o
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-23 10:59:41 -07:00
|
|
|
w := f.Type.Width
|
|
|
|
|
if w < 0 {
|
|
|
|
|
Fatalf("invalid width %d", f.Type.Width)
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
if w == 0 {
|
|
|
|
|
lastzero = o
|
|
|
|
|
}
|
|
|
|
|
o += w
|
2017-03-17 13:35:36 -07:00
|
|
|
maxwidth := thearch.MAXWIDTH
|
2017-01-25 10:19:33 -05:00
|
|
|
// On 32-bit systems, reflect tables impose an additional constraint
|
|
|
|
|
// that each field start offset must fit in 31 bits.
|
|
|
|
|
if maxwidth < 1<<32 {
|
|
|
|
|
maxwidth = 1<<31 - 1
|
|
|
|
|
}
|
|
|
|
|
if o >= maxwidth {
|
2016-09-15 15:45:10 +10:00
|
|
|
yyerror("type %L too large", errtype)
|
2015-02-13 14:40:36 -05:00
|
|
|
o = 8 // small but nonzero
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// For nonzero-sized structs which end in a zero-sized thing, we add
|
2016-03-01 23:21:55 +00:00
|
|
|
// an extra byte of padding to the type. This padding ensures that
|
2015-02-13 14:40:36 -05:00
|
|
|
// taking the address of the zero-sized thing can't manufacture a
|
2016-03-01 23:21:55 +00:00
|
|
|
// pointer to the next object in the heap. See issue 9401.
|
2015-02-13 14:40:36 -05:00
|
|
|
if flag == 1 && o > starto && o == lastzero {
|
|
|
|
|
o++
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// final width is rounded
|
|
|
|
|
if flag != 0 {
|
|
|
|
|
o = Rnd(o, int64(maxalign))
|
|
|
|
|
}
|
|
|
|
|
t.Align = uint8(maxalign)
|
|
|
|
|
|
|
|
|
|
// type width only includes back to first field's offset
|
|
|
|
|
t.Width = o - starto
|
|
|
|
|
|
|
|
|
|
return o
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-29 02:11:10 -07:00
|
|
|
// findTypeLoop searches for an invalid type declaration loop involving
|
|
|
|
|
// type t and reports whether one is found. If so, path contains the
|
|
|
|
|
// loop.
|
|
|
|
|
//
|
|
|
|
|
// path points to a slice used for tracking the sequence of types
|
|
|
|
|
// visited. Using a pointer to a slice allows the slice capacity to
|
|
|
|
|
// grow and limit reallocations.
|
|
|
|
|
func findTypeLoop(t *types.Type, path *[]*types.Type) bool {
|
|
|
|
|
// We implement a simple DFS loop-finding algorithm. This
|
|
|
|
|
// could be faster, but type cycles are rare.
|
|
|
|
|
|
|
|
|
|
if t.Sym != nil {
|
|
|
|
|
// Declared type. Check for loops and otherwise
|
|
|
|
|
// recurse on the type expression used in the type
|
|
|
|
|
// declaration.
|
|
|
|
|
|
|
|
|
|
for i, x := range *path {
|
|
|
|
|
if x == t {
|
|
|
|
|
*path = (*path)[i:]
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*path = append(*path, t)
|
|
|
|
|
if findTypeLoop(asNode(t.Nod).Name.Param.Ntype.Type, path) {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
*path = (*path)[:len(*path)-1]
|
|
|
|
|
} else {
|
|
|
|
|
// Anonymous type. Recurse on contained types.
|
|
|
|
|
|
|
|
|
|
switch t.Etype {
|
|
|
|
|
case TARRAY:
|
|
|
|
|
if findTypeLoop(t.Elem(), path) {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
case TSTRUCT:
|
|
|
|
|
for _, f := range t.Fields().Slice() {
|
|
|
|
|
if findTypeLoop(f.Type, path) {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
case TINTER:
|
|
|
|
|
for _, m := range t.Methods().Slice() {
|
|
|
|
|
if m.Type.IsInterface() { // embedded interface
|
|
|
|
|
if findTypeLoop(m.Type, path) {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func reportTypeLoop(t *types.Type) {
|
|
|
|
|
if t.Broke() {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var l []*types.Type
|
|
|
|
|
if !findTypeLoop(t, &l) {
|
|
|
|
|
Fatalf("failed to find type loop for: %v", t)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Rotate loop so that the earliest type declaration is first.
|
|
|
|
|
i := 0
|
|
|
|
|
for j, t := range l[1:] {
|
|
|
|
|
if typePos(t).Before(typePos(l[i])) {
|
|
|
|
|
i = j + 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
l = append(l[i:], l[:i]...)
|
|
|
|
|
|
|
|
|
|
var msg bytes.Buffer
|
|
|
|
|
fmt.Fprintf(&msg, "invalid recursive type %v\n", l[0])
|
|
|
|
|
for _, t := range l {
|
|
|
|
|
fmt.Fprintf(&msg, "\t%v: %v refers to\n", linestr(typePos(t)), t)
|
|
|
|
|
t.SetBroke(true)
|
|
|
|
|
}
|
|
|
|
|
fmt.Fprintf(&msg, "\t%v: %v", linestr(typePos(l[0])), l[0])
|
|
|
|
|
yyerrorl(typePos(l[0]), msg.String())
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-27 16:37:25 -07:00
|
|
|
// dowidth calculates and stores the size and alignment for t.
|
|
|
|
|
// If sizeCalculationDisabled is set, and the size/alignment
|
|
|
|
|
// have not already been calculated, it calls Fatal.
|
|
|
|
|
// This is used to prevent data races in the back end.
|
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 dowidth(t *types.Type) {
|
2019-08-16 16:05:10 +07:00
|
|
|
// Calling dowidth when typecheck tracing enabled is not safe.
|
|
|
|
|
// See issue #33658.
|
|
|
|
|
if enableTrace && skipDowidthForTracing {
|
|
|
|
|
return
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
if Widthptr == 0 {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("dowidth without betypeinit")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if t == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if t.Width == -2 {
|
2020-09-29 02:11:10 -07:00
|
|
|
reportTypeLoop(t)
|
2015-02-13 14:40:36 -05:00
|
|
|
t.Width = 0
|
2017-09-18 11:54:03 -07:00
|
|
|
t.Align = 1
|
2015-02-13 14:40:36 -05:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-23 11:29:37 -07:00
|
|
|
if t.WidthCalculated() {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-27 16:37:25 -07:00
|
|
|
if sizeCalculationDisabled {
|
2017-04-28 07:23:26 -07:00
|
|
|
if t.Broke() {
|
|
|
|
|
// break infinite recursion from Fatal call below
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
t.SetBroke(true)
|
2017-04-27 16:37:25 -07:00
|
|
|
Fatalf("width not calculated: %v", t)
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
// break infinite recursion if the broken recursive type
|
|
|
|
|
// is referenced again
|
2017-02-27 19:56:38 +02:00
|
|
|
if t.Broke() && t.Width == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// defer checkwidth calls until after we're done
|
2019-08-30 14:54:21 -07:00
|
|
|
defercheckwidth()
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-03-02 17:34:42 -08:00
|
|
|
lno := lineno
|
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
|
|
|
if asNode(t.Nod) != nil {
|
|
|
|
|
lineno = asNode(t.Nod).Pos
|
2017-03-20 02:21:50 -07:00
|
|
|
}
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
t.Width = -2
|
2018-10-29 13:44:44 -07:00
|
|
|
t.Align = 0 // 0 means use t.Width, below
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-09-24 23:21:18 +02:00
|
|
|
et := t.Etype
|
2015-02-13 14:40:36 -05:00
|
|
|
switch et {
|
2015-04-01 09:38:44 -07:00
|
|
|
case TFUNC, TCHAN, TMAP, TSTRING:
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// simtype == 0 during bootstrap
|
2015-02-13 14:40:36 -05:00
|
|
|
default:
|
2016-09-16 00:33:29 +10:00
|
|
|
if simtype[t.Etype] != 0 {
|
|
|
|
|
et = simtype[t.Etype]
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-29 13:44:44 -07:00
|
|
|
var w int64
|
2015-02-13 14:40:36 -05:00
|
|
|
switch et {
|
|
|
|
|
default:
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("dowidth: unknown type: %v", t)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// compiler-specific stuff
|
2015-04-01 09:38:44 -07:00
|
|
|
case TINT8, TUINT8, TBOOL:
|
2015-02-13 14:40:36 -05:00
|
|
|
// bool is int8
|
|
|
|
|
w = 1
|
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case TINT16, TUINT16:
|
2015-02-13 14:40:36 -05:00
|
|
|
w = 2
|
|
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case TINT32, TUINT32, TFLOAT32:
|
2015-02-13 14:40:36 -05:00
|
|
|
w = 4
|
|
|
|
|
|
2016-02-21 02:28:37 -08:00
|
|
|
case TINT64, TUINT64, TFLOAT64:
|
2015-02-13 14:40:36 -05:00
|
|
|
w = 8
|
|
|
|
|
t.Align = uint8(Widthreg)
|
|
|
|
|
|
2016-02-21 02:28:37 -08:00
|
|
|
case TCOMPLEX64:
|
|
|
|
|
w = 8
|
|
|
|
|
t.Align = 4
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
case TCOMPLEX128:
|
|
|
|
|
w = 16
|
|
|
|
|
t.Align = uint8(Widthreg)
|
|
|
|
|
|
2017-11-06 14:50:30 -08:00
|
|
|
case TPTR:
|
|
|
|
|
w = int64(Widthptr)
|
2016-03-30 10:57:47 -07:00
|
|
|
checkwidth(t.Elem())
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case TUNSAFEPTR:
|
|
|
|
|
w = int64(Widthptr)
|
|
|
|
|
|
|
|
|
|
case TINTER: // implemented as 2 pointers
|
|
|
|
|
w = 2 * int64(Widthptr)
|
|
|
|
|
t.Align = uint8(Widthptr)
|
2017-03-20 11:56:15 -07:00
|
|
|
expandiface(t)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case TCHAN: // implemented as pointer
|
|
|
|
|
w = int64(Widthptr)
|
|
|
|
|
|
2016-03-30 10:57:47 -07:00
|
|
|
checkwidth(t.Elem())
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// make fake type to check later to
|
|
|
|
|
// trigger channel argument check.
|
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
|
|
|
t1 := types.NewChanArgs(t)
|
2015-02-13 14:40:36 -05:00
|
|
|
checkwidth(t1)
|
|
|
|
|
|
|
|
|
|
case TCHANARGS:
|
2016-04-01 20:11:30 -07:00
|
|
|
t1 := t.ChanArgs()
|
2016-03-29 10:15:02 -07:00
|
|
|
dowidth(t1) // just in case
|
2016-03-30 10:57:47 -07:00
|
|
|
if t1.Elem().Width >= 1<<16 {
|
2016-09-15 15:45:10 +10:00
|
|
|
yyerror("channel element type too large (>64kB)")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2017-03-23 11:29:37 -07:00
|
|
|
w = 1 // anything will do
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case TMAP: // implemented as pointer
|
|
|
|
|
w = int64(Widthptr)
|
2018-04-24 13:53:35 -07:00
|
|
|
checkwidth(t.Elem())
|
2016-03-10 05:22:14 -08:00
|
|
|
checkwidth(t.Key())
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case TFORW: // should have been filled in
|
2020-09-29 02:11:10 -07:00
|
|
|
reportTypeLoop(t)
|
2015-02-13 14:40:36 -05:00
|
|
|
w = 1 // anything will do
|
|
|
|
|
|
|
|
|
|
case TANY:
|
2016-10-19 12:58:16 -07:00
|
|
|
// dummy type; should be replaced before use.
|
|
|
|
|
Fatalf("dowidth any")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case TSTRING:
|
2020-04-08 12:36:35 -07:00
|
|
|
if sizeofString == 0 {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("early dowidth string")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-04-08 12:36:35 -07:00
|
|
|
w = sizeofString
|
2015-02-13 14:40:36 -05:00
|
|
|
t.Align = uint8(Widthptr)
|
|
|
|
|
|
|
|
|
|
case TARRAY:
|
2016-03-30 10:57:47 -07:00
|
|
|
if t.Elem() == nil {
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
}
|
2016-04-18 14:02:08 -07:00
|
|
|
|
|
|
|
|
dowidth(t.Elem())
|
|
|
|
|
if t.Elem().Width != 0 {
|
2017-03-17 13:35:36 -07:00
|
|
|
cap := (uint64(thearch.MAXWIDTH) - 1) / uint64(t.Elem().Width)
|
2016-04-18 14:02:08 -07:00
|
|
|
if uint64(t.NumElem()) > cap {
|
2016-09-15 15:45:10 +10:00
|
|
|
yyerror("type %L larger than address space", t)
|
2016-04-18 14:02:08 -07:00
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-04-18 14:02:08 -07:00
|
|
|
w = t.NumElem() * t.Elem().Width
|
|
|
|
|
t.Align = t.Elem().Align
|
|
|
|
|
|
|
|
|
|
case TSLICE:
|
|
|
|
|
if t.Elem() == nil {
|
|
|
|
|
break
|
|
|
|
|
}
|
2020-04-08 12:36:35 -07:00
|
|
|
w = sizeofSlice
|
2016-04-18 14:02:08 -07:00
|
|
|
checkwidth(t.Elem())
|
|
|
|
|
t.Align = uint8(Widthptr)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case TSTRUCT:
|
2016-04-05 16:44:07 -07:00
|
|
|
if t.IsFuncArgStruct() {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("dowidth fn struct %v", t)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
w = widstruct(t, t, 0, 1)
|
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// make fake type to check later to
|
2015-02-13 14:40:36 -05:00
|
|
|
// trigger function argument computation.
|
|
|
|
|
case TFUNC:
|
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
|
|
|
t1 := types.NewFuncArgs(t)
|
2015-02-13 14:40:36 -05:00
|
|
|
checkwidth(t1)
|
2016-03-29 10:15:02 -07:00
|
|
|
w = int64(Widthptr) // width of func type is pointer
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// function is 3 cated structures;
|
2015-02-13 14:40:36 -05:00
|
|
|
// compute their widths as side-effect.
|
|
|
|
|
case TFUNCARGS:
|
2016-04-01 20:11:30 -07:00
|
|
|
t1 := t.FuncArgs()
|
2016-03-29 10:15:02 -07:00
|
|
|
w = widstruct(t1, t1.Recvs(), 0, 0)
|
|
|
|
|
w = widstruct(t1, t1.Params(), w, Widthreg)
|
|
|
|
|
w = widstruct(t1, t1.Results(), w, Widthreg)
|
2017-04-06 20:27:33 -07:00
|
|
|
t1.Extra.(*types.Func).Argwid = w
|
2015-02-13 14:40:36 -05:00
|
|
|
if w%int64(Widthreg) != 0 {
|
2015-04-17 12:03:22 -04:00
|
|
|
Warn("bad type %v %d\n", t1, w)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
t.Align = 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if Widthptr == 4 && w != int64(int32(w)) {
|
2016-09-15 15:45:10 +10:00
|
|
|
yyerror("type %v too large", t)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
t.Width = w
|
|
|
|
|
if t.Align == 0 {
|
2018-10-29 13:44:44 -07:00
|
|
|
if w == 0 || w > 8 || w&(w-1) != 0 {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("invalid alignment for %v", t)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
t.Align = uint8(w)
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-02 17:34:42 -08:00
|
|
|
lineno = lno
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2019-08-30 14:54:21 -07:00
|
|
|
resumecheckwidth()
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-10-22 09:51:12 +09:00
|
|
|
// when a type's width should be known, we call checkwidth
|
|
|
|
|
// to compute it. during a declaration like
|
|
|
|
|
//
|
|
|
|
|
// type T *struct { next T }
|
|
|
|
|
//
|
|
|
|
|
// it is necessary to defer the calculation of the struct width
|
|
|
|
|
// until after T has been initialized to be a pointer to that struct.
|
|
|
|
|
// similarly, during import processing structs may be used
|
|
|
|
|
// before their definition. in those situations, calling
|
|
|
|
|
// defercheckwidth() stops width calculations until
|
|
|
|
|
// resumecheckwidth() is called, at which point all the
|
|
|
|
|
// checkwidths that were deferred are executed.
|
|
|
|
|
// dowidth should only be called when the type's size
|
|
|
|
|
// is needed immediately. checkwidth makes sure the
|
|
|
|
|
// size is evaluated eventually.
|
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
|
|
|
var deferredTypeStack []*types.Type
|
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 checkwidth(t *types.Type) {
|
2015-02-13 14:40:36 -05:00
|
|
|
if t == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// function arg structs should not be checked
|
|
|
|
|
// outside of the enclosing function.
|
2016-04-05 16:44:07 -07:00
|
|
|
if t.IsFuncArgStruct() {
|
2015-08-30 23:10:03 +02:00
|
|
|
Fatalf("checkwidth %v", t)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if defercalc == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
dowidth(t)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-29 13:44:44 -07:00
|
|
|
// if type has not yet been pushed on deferredTypeStack yet, do it now
|
|
|
|
|
if !t.Deferwidth() {
|
|
|
|
|
t.SetDeferwidth(true)
|
|
|
|
|
deferredTypeStack = append(deferredTypeStack, t)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func defercheckwidth() {
|
2019-08-30 14:54:21 -07:00
|
|
|
defercalc++
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func resumecheckwidth() {
|
2019-08-30 14:54:21 -07:00
|
|
|
if defercalc == 1 {
|
|
|
|
|
for len(deferredTypeStack) > 0 {
|
|
|
|
|
t := deferredTypeStack[len(deferredTypeStack)-1]
|
|
|
|
|
deferredTypeStack = deferredTypeStack[:len(deferredTypeStack)-1]
|
|
|
|
|
t.SetDeferwidth(false)
|
|
|
|
|
dowidth(t)
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2019-08-30 14:54:21 -07:00
|
|
|
defercalc--
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|