Commit c5155981 authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

cmd/compile: add sizeCalculationDisabled flag

Use it to ensure that dowidth is not called
from the backend on a type whose size
has not yet been calculated.

This is an alternative to CL 42016.

Change-Id: I8c7b4410ee4c2a68573102f6b9b635f4fdcf392e
Reviewed-on: https://go-review.googlesource.com/42018
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarMatthew Dempsky <mdempsky@google.com>
parent dae5389d
...@@ -9,6 +9,10 @@ import ( ...@@ -9,6 +9,10 @@ import (
"sort" "sort"
) )
// sizeCalculationDisabled indicates whether it is safe
// to calculate Types' widths and alignments. See dowidth.
var sizeCalculationDisabled bool
// machine size and rounding alignment is dictated around // machine size and rounding alignment is dictated around
// the size of a pointer, set in betypeinit (see ../amd64/galign.go). // the size of a pointer, set in betypeinit (see ../amd64/galign.go).
var defercalc int var defercalc int
...@@ -151,6 +155,10 @@ func widstruct(errtype *types.Type, t *types.Type, o int64, flag int) int64 { ...@@ -151,6 +155,10 @@ func widstruct(errtype *types.Type, t *types.Type, o int64, flag int) int64 {
return o return o
} }
// 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.
func dowidth(t *types.Type) { func dowidth(t *types.Type) {
if Widthptr == 0 { if Widthptr == 0 {
Fatalf("dowidth without betypeinit") Fatalf("dowidth without betypeinit")
...@@ -174,6 +182,10 @@ func dowidth(t *types.Type) { ...@@ -174,6 +182,10 @@ func dowidth(t *types.Type) {
return return
} }
if sizeCalculationDisabled {
Fatalf("width not calculated: %v", t)
}
// break infinite recursion if the broken recursive type // break infinite recursion if the broken recursive type
// is referenced again // is referenced again
if t.Broke() && t.Width == 0 { if t.Broke() && t.Width == 0 {
......
...@@ -254,6 +254,7 @@ func compileSSA(fn *Node, worker int) { ...@@ -254,6 +254,7 @@ func compileSSA(fn *Node, worker int) {
// and waits for them to complete. // and waits for them to complete.
func compileFunctions() { func compileFunctions() {
if len(compilequeue) != 0 { if len(compilequeue) != 0 {
sizeCalculationDisabled = true // not safe to calculate sizes concurrently
if raceEnabled { if raceEnabled {
// Randomize compilation order to try to shake out races. // Randomize compilation order to try to shake out races.
tmp := make([]*Node, len(compilequeue)) tmp := make([]*Node, len(compilequeue))
...@@ -287,6 +288,7 @@ func compileFunctions() { ...@@ -287,6 +288,7 @@ func compileFunctions() {
close(c) close(c)
compilequeue = nil compilequeue = nil
wg.Wait() wg.Wait()
sizeCalculationDisabled = false
} }
} }
......
...@@ -1519,8 +1519,8 @@ func (s *state) expr(n *Node) *ssa.Value { ...@@ -1519,8 +1519,8 @@ func (s *state) expr(n *Node) *ssa.Value {
return v return v
} }
from.AssertWidthCalculated() dowidth(from)
to.AssertWidthCalculated() dowidth(to)
if from.Width != to.Width { if from.Width != to.Width {
s.Fatalf("CONVNOP width mismatch %v (%d) -> %v (%d)\n", from, from.Width, to, to.Width) s.Fatalf("CONVNOP width mismatch %v (%d) -> %v (%d)\n", from, from.Width, to, to.Width)
return nil return nil
...@@ -2321,7 +2321,7 @@ func (s *state) assign(left *Node, right *ssa.Value, deref bool, skip skipMask) ...@@ -2321,7 +2321,7 @@ func (s *state) assign(left *Node, right *ssa.Value, deref bool, skip skipMask)
return return
} }
t := left.Type t := left.Type
t.AssertWidthCalculated() dowidth(t)
if s.canSSA(left) { if s.canSSA(left) {
if deref { if deref {
s.Fatalf("can SSA LHS %v but not RHS %s", left, right) s.Fatalf("can SSA LHS %v but not RHS %s", left, right)
...@@ -3095,7 +3095,7 @@ func (s *state) call(n *Node, k callKind) *ssa.Value { ...@@ -3095,7 +3095,7 @@ func (s *state) call(n *Node, k callKind) *ssa.Value {
} }
rcvr = s.newValue1(ssa.OpIData, types.Types[TUINTPTR], i) rcvr = s.newValue1(ssa.OpIData, types.Types[TUINTPTR], i)
} }
fn.Type.AssertWidthCalculated() dowidth(fn.Type)
stksize := fn.Type.ArgWidth() // includes receiver stksize := fn.Type.ArgWidth() // includes receiver
// Run all argument assignments. The arg slots have already // Run all argument assignments. The arg slots have already
...@@ -3351,7 +3351,7 @@ func (s *state) canSSA(n *Node) bool { ...@@ -3351,7 +3351,7 @@ func (s *state) canSSA(n *Node) bool {
// canSSA reports whether variables of type t are SSA-able. // canSSA reports whether variables of type t are SSA-able.
func canSSAType(t *types.Type) bool { func canSSAType(t *types.Type) bool {
t.AssertWidthCalculated() dowidth(t)
if t.Width > int64(4*Widthptr) { if t.Width > int64(4*Widthptr) {
// 4*Widthptr is an arbitrary constant. We want it // 4*Widthptr is an arbitrary constant. We want it
// to be at least 3*Widthptr so slices can be registerized. // to be at least 3*Widthptr so slices can be registerized.
...@@ -4972,7 +4972,7 @@ func (e *ssafn) namedAuto(name string, typ ssa.Type, pos src.XPos) ssa.GCNode { ...@@ -4972,7 +4972,7 @@ func (e *ssafn) namedAuto(name string, typ ssa.Type, pos src.XPos) ssa.GCNode {
n.Esc = EscNever n.Esc = EscNever
n.Name.Curfn = e.curfn n.Name.Curfn = e.curfn
e.curfn.Func.Dcl = append(e.curfn.Func.Dcl, n) e.curfn.Func.Dcl = append(e.curfn.Func.Dcl, n)
t.AssertWidthCalculated() dowidth(t)
return n return n
} }
......
...@@ -849,13 +849,6 @@ func (t *Type) WidthCalculated() bool { ...@@ -849,13 +849,6 @@ func (t *Type) WidthCalculated() bool {
return t.Align > 0 return t.Align > 0
} }
// AssertWidthCalculated calls Fatalf if t's width has not yet been calculated.
func (t *Type) AssertWidthCalculated() {
if !t.WidthCalculated() {
Fatalf("width not calculated: %v", t)
}
}
// ArgWidth returns the total aligned argument size for a function. // ArgWidth returns the total aligned argument size for a function.
// It includes the receiver, parameters, and results. // It includes the receiver, parameters, and results.
func (t *Type) ArgWidth() int64 { func (t *Type) ArgWidth() int64 {
...@@ -864,12 +857,12 @@ func (t *Type) ArgWidth() int64 { ...@@ -864,12 +857,12 @@ func (t *Type) ArgWidth() int64 {
} }
func (t *Type) Size() int64 { func (t *Type) Size() int64 {
t.AssertWidthCalculated() Dowidth(t)
return t.Width return t.Width
} }
func (t *Type) Alignment() int64 { func (t *Type) Alignment() int64 {
t.AssertWidthCalculated() Dowidth(t)
return int64(t.Align) return int64(t.Align)
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment