"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
// the size of a pointer, set in betypeinit (see ../amd64/galign.go).
var defercalc int
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) {
if Widthptr == 0 {
Fatalf("dowidth without betypeinit")
return
}
+ if sizeCalculationDisabled {
+ Fatalf("width not calculated: %v", t)
+ }
+
// break infinite recursion if the broken recursive type
// is referenced again
if t.Broke() && t.Width == 0 {
// and waits for them to complete.
func compileFunctions() {
if len(compilequeue) != 0 {
+ sizeCalculationDisabled = true // not safe to calculate sizes concurrently
if raceEnabled {
// Randomize compilation order to try to shake out races.
tmp := make([]*Node, len(compilequeue))
close(c)
compilequeue = nil
wg.Wait()
+ sizeCalculationDisabled = false
}
}
return v
}
- from.AssertWidthCalculated()
- to.AssertWidthCalculated()
+ dowidth(from)
+ dowidth(to)
if from.Width != to.Width {
s.Fatalf("CONVNOP width mismatch %v (%d) -> %v (%d)\n", from, from.Width, to, to.Width)
return nil
return
}
t := left.Type
- t.AssertWidthCalculated()
+ dowidth(t)
if s.canSSA(left) {
if deref {
s.Fatalf("can SSA LHS %v but not RHS %s", left, right)
}
rcvr = s.newValue1(ssa.OpIData, types.Types[TUINTPTR], i)
}
- fn.Type.AssertWidthCalculated()
+ dowidth(fn.Type)
stksize := fn.Type.ArgWidth() // includes receiver
// Run all argument assignments. The arg slots have already
// canSSA reports whether variables of type t are SSA-able.
func canSSAType(t *types.Type) bool {
- t.AssertWidthCalculated()
+ dowidth(t)
if t.Width > int64(4*Widthptr) {
// 4*Widthptr is an arbitrary constant. We want it
// to be at least 3*Widthptr so slices can be registerized.
n.Esc = EscNever
n.Name.Curfn = e.curfn
e.curfn.Func.Dcl = append(e.curfn.Func.Dcl, n)
- t.AssertWidthCalculated()
+ dowidth(t)
return n
}
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.
// It includes the receiver, parameters, and results.
func (t *Type) ArgWidth() int64 {
}
func (t *Type) Size() int64 {
- t.AssertWidthCalculated()
+ Dowidth(t)
return t.Width
}
func (t *Type) Alignment() int64 {
- t.AssertWidthCalculated()
+ Dowidth(t)
return int64(t.Align)
}