Commit 7b5df0c1 authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

cmd/compile: document sinit ctxt and pass/kind arguments

No functional changes. Passes toolstash -cmp.

Change-Id: I1ad467e574fd2ea80ab1459c0c943d9ff66c23ec
Reviewed-on: https://go-review.googlesource.com/26755
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarDavid Crawshaw <crawshaw@golang.org>
parent cd2d5ee0
...@@ -400,7 +400,7 @@ func staticassign(l *Node, r *Node, out *[]*Node) bool { ...@@ -400,7 +400,7 @@ func staticassign(l *Node, r *Node, out *[]*Node) bool {
switch r.Left.Op { switch r.Left.Op {
case OARRAYLIT, OSLICELIT, OMAPLIT, OSTRUCTLIT: case OARRAYLIT, OSLICELIT, OMAPLIT, OSTRUCTLIT:
// Init pointer. // Init pointer.
a := staticname(r.Left.Type, 1) a := staticname(r.Left.Type, inNonInitFunction)
inittemps[r] = a inittemps[r] = a
gdata(l, Nod(OADDR, a, nil), int(l.Type.Width)) gdata(l, Nod(OADDR, a, nil), int(l.Type.Width))
...@@ -425,7 +425,7 @@ func staticassign(l *Node, r *Node, out *[]*Node) bool { ...@@ -425,7 +425,7 @@ func staticassign(l *Node, r *Node, out *[]*Node) bool {
// Init slice. // Init slice.
bound := r.Right.Int64() bound := r.Right.Int64()
ta := typArray(r.Type.Elem(), bound) ta := typArray(r.Type.Elem(), bound)
a := staticname(ta, 1) a := staticname(ta, inNonInitFunction)
inittemps[r] = a inittemps[r] = a
n := *l n := *l
n.Xoffset = l.Xoffset + int64(Array_array) n.Xoffset = l.Xoffset + int64(Array_array)
...@@ -485,15 +485,32 @@ func staticassign(l *Node, r *Node, out *[]*Node) bool { ...@@ -485,15 +485,32 @@ func staticassign(l *Node, r *Node, out *[]*Node) bool {
return false return false
} }
// initContext is the context in which static data is populated.
// It is either in an init function or in any other function.
// Static data populated in an init function will be written either
// zero times (as a readonly, static data symbol) or
// one time (during init function execution).
// Either way, there is no opportunity for races or further modification,
// so the data can be written to a (possibly readonly) data symbol.
// Static data populated in any other function needs to be local to
// that function to allow multiple instances of that function
// to execute concurrently without clobbering each others' data.
type initContext uint8
const (
inInitFunction initContext = iota
inNonInitFunction
)
// from here down is the walk analysis // from here down is the walk analysis
// of composite literals. // of composite literals.
// most of the work is to generate // most of the work is to generate
// data statements for the constant // data statements for the constant
// part of the composite literal. // part of the composite literal.
func staticname(t *Type, ctxt int) *Node { func staticname(t *Type, ctxt initContext) *Node {
n := newname(LookupN("statictmp_", statuniqgen)) n := newname(LookupN("statictmp_", statuniqgen))
statuniqgen++ statuniqgen++
if ctxt == 0 { if ctxt == inInitFunction {
n.Name.Readonly = true n.Name.Readonly = true
} }
addvar(n, t, PEXTERN) addvar(n, t, PEXTERN)
...@@ -579,9 +596,26 @@ func isStaticCompositeLiteral(n *Node) bool { ...@@ -579,9 +596,26 @@ func isStaticCompositeLiteral(n *Node) bool {
return false return false
} }
// initKind is a kind of static initialization: static, dynamic, or local.
// Static initialization represents literals and
// literal components of composite literals.
// Dynamic initialization represents non-literals and
// non-literal components of composite literals.
// LocalCode initializion represents initialization
// that occurs purely in generated code local to the function of use.
// Initialization code is sometimes generated in passes,
// first static then dynamic.
type initKind uint8
const (
initKindStatic initKind = iota + 1
initKindDynamic
initKindLocalCode
)
// fixedlit handles struct, array, and slice literals. // fixedlit handles struct, array, and slice literals.
// TODO: expand documentation. // TODO: expand documentation.
func fixedlit(ctxt int, pass int, n *Node, var_ *Node, init *Nodes) { func fixedlit(ctxt initContext, kind initKind, n *Node, var_ *Node, init *Nodes) {
var indexnode func(*Node) *Node var indexnode func(*Node) *Node
switch n.Op { switch n.Op {
case OARRAYLIT, OSLICELIT: case OARRAYLIT, OSLICELIT:
...@@ -601,7 +635,7 @@ func fixedlit(ctxt int, pass int, n *Node, var_ *Node, init *Nodes) { ...@@ -601,7 +635,7 @@ func fixedlit(ctxt int, pass int, n *Node, var_ *Node, init *Nodes) {
switch value.Op { switch value.Op {
case OSLICELIT: case OSLICELIT:
if (pass == 1 && ctxt != 0) || (pass == 2 && ctxt == 0) { if (kind == initKindStatic && ctxt == inNonInitFunction) || (kind == initKindDynamic && ctxt == inInitFunction) {
a := indexnode(index) a := indexnode(index)
slicelit(ctxt, value, a, init) slicelit(ctxt, value, a, init)
continue continue
...@@ -609,7 +643,7 @@ func fixedlit(ctxt int, pass int, n *Node, var_ *Node, init *Nodes) { ...@@ -609,7 +643,7 @@ func fixedlit(ctxt int, pass int, n *Node, var_ *Node, init *Nodes) {
case OARRAYLIT, OSTRUCTLIT: case OARRAYLIT, OSTRUCTLIT:
a := indexnode(index) a := indexnode(index)
fixedlit(ctxt, pass, value, a, init) fixedlit(ctxt, kind, value, a, init)
continue continue
} }
...@@ -617,7 +651,7 @@ func fixedlit(ctxt int, pass int, n *Node, var_ *Node, init *Nodes) { ...@@ -617,7 +651,7 @@ func fixedlit(ctxt int, pass int, n *Node, var_ *Node, init *Nodes) {
if n.Op == OARRAYLIT { if n.Op == OARRAYLIT {
islit = islit && isliteral(index) islit = islit && isliteral(index)
} }
if (pass == 1 && !islit) || (pass == 2 && islit) { if (kind == initKindStatic && !islit) || (kind == initKindDynamic && islit) {
continue continue
} }
...@@ -625,32 +659,35 @@ func fixedlit(ctxt int, pass int, n *Node, var_ *Node, init *Nodes) { ...@@ -625,32 +659,35 @@ func fixedlit(ctxt int, pass int, n *Node, var_ *Node, init *Nodes) {
setlineno(value) setlineno(value)
a := Nod(OAS, indexnode(index), value) a := Nod(OAS, indexnode(index), value)
a = typecheck(a, Etop) a = typecheck(a, Etop)
if pass == 1 { switch kind {
case initKindStatic:
a = walkexpr(a, init) // add any assignments in r to top a = walkexpr(a, init) // add any assignments in r to top
if a.Op != OAS { if a.Op != OAS {
Fatalf("fixedlit: not as") Fatalf("fixedlit: not as")
} }
a.IsStatic = true a.IsStatic = true
} else { case initKindDynamic, initKindLocalCode:
a = orderstmtinplace(a) a = orderstmtinplace(a)
a = walkstmt(a) a = walkstmt(a)
default:
Fatalf("fixedlit: bad kind %d", kind)
} }
init.Append(a) init.Append(a)
} }
} }
func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) { func slicelit(ctxt initContext, n *Node, var_ *Node, init *Nodes) {
// make an array type corresponding the number of elements we have // make an array type corresponding the number of elements we have
t := typArray(n.Type.Elem(), n.Right.Int64()) t := typArray(n.Type.Elem(), n.Right.Int64())
dowidth(t) dowidth(t)
if ctxt != 0 { if ctxt == inNonInitFunction {
// put everything into static array // put everything into static array
vstat := staticname(t, ctxt) vstat := staticname(t, ctxt)
fixedlit(ctxt, 1, n, vstat, init) fixedlit(ctxt, initKindStatic, n, vstat, init)
fixedlit(ctxt, 2, n, vstat, init) fixedlit(ctxt, initKindDynamic, n, vstat, init)
// copy static to slice // copy static to slice
a := Nod(OSLICE, vstat, nil) a := Nod(OSLICE, vstat, nil)
...@@ -688,7 +725,7 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -688,7 +725,7 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) {
mode := getdyn(n, true) mode := getdyn(n, true)
if mode&initConst != 0 { if mode&initConst != 0 {
vstat = staticname(t, ctxt) vstat = staticname(t, ctxt)
fixedlit(ctxt, 1, n, vstat, init) fixedlit(ctxt, initKindStatic, n, vstat, init)
} }
// make new auto *array (3 declare) // make new auto *array (3 declare)
...@@ -754,7 +791,7 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -754,7 +791,7 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) {
break break
case OARRAYLIT, OSTRUCTLIT: case OARRAYLIT, OSTRUCTLIT:
fixedlit(ctxt, 2, value, a, init) fixedlit(ctxt, initKindDynamic, value, a, init)
continue continue
} }
...@@ -781,8 +818,8 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -781,8 +818,8 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) {
init.Append(a) init.Append(a)
} }
func maplit(ctxt int, n *Node, m *Node, init *Nodes) { func maplit(ctxt initContext, n *Node, m *Node, init *Nodes) {
ctxt = 0 ctxt = inInitFunction
// make the map var // make the map var
nerr := nerrors nerr := nerrors
...@@ -928,7 +965,7 @@ func maplit(ctxt int, n *Node, m *Node, init *Nodes) { ...@@ -928,7 +965,7 @@ func maplit(ctxt int, n *Node, m *Node, init *Nodes) {
} }
} }
func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) { func anylit(ctxt initContext, n *Node, var_ *Node, init *Nodes) {
t := n.Type t := n.Type
switch n.Op { switch n.Op {
default: default:
...@@ -966,15 +1003,15 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -966,15 +1003,15 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) {
} }
if var_.isSimpleName() && n.List.Len() > 4 { if var_.isSimpleName() && n.List.Len() > 4 {
if ctxt == 0 { if ctxt == inInitFunction {
// lay out static data // lay out static data
vstat := staticname(t, ctxt) vstat := staticname(t, ctxt)
pass1ctxt := ctxt litctxt := ctxt
if n.Op == OARRAYLIT { if n.Op == OARRAYLIT {
pass1ctxt = 1 litctxt = inNonInitFunction
} }
fixedlit(pass1ctxt, 1, n, vstat, init) fixedlit(litctxt, initKindStatic, n, vstat, init)
// copy static to var // copy static to var
a := Nod(OAS, var_, vstat) a := Nod(OAS, var_, vstat)
...@@ -984,13 +1021,13 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -984,13 +1021,13 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) {
init.Append(a) init.Append(a)
// add expressions to automatic // add expressions to automatic
fixedlit(ctxt, 2, n, var_, init) fixedlit(ctxt, initKindDynamic, n, var_, init)
break break
} }
fixedlit(ctxt, 1, n, var_, init) fixedlit(ctxt, initKindStatic, n, var_, init)
fixedlit(ctxt, 2, n, var_, init) fixedlit(ctxt, initKindDynamic, n, var_, init)
break break
} }
...@@ -1008,7 +1045,7 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -1008,7 +1045,7 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) {
init.Append(a) init.Append(a)
} }
fixedlit(ctxt, 3, n, var_, init) fixedlit(ctxt, initKindLocalCode, n, var_, init)
case OSLICELIT: case OSLICELIT:
slicelit(ctxt, n, var_, init) slicelit(ctxt, n, var_, init)
...@@ -1039,14 +1076,6 @@ func oaslit(n *Node, init *Nodes) bool { ...@@ -1039,14 +1076,6 @@ func oaslit(n *Node, init *Nodes) bool {
return false return false
} }
// context is init() function.
// implies generated data executed
// exactly once and not subject to races.
ctxt := 0
// if(n->dodata == 1)
// ctxt = 1;
switch n.Right.Op { switch n.Right.Op {
default: default:
// not a special composit literal assignment // not a special composit literal assignment
...@@ -1057,7 +1086,7 @@ func oaslit(n *Node, init *Nodes) bool { ...@@ -1057,7 +1086,7 @@ func oaslit(n *Node, init *Nodes) bool {
// not a special composit literal assignment // not a special composit literal assignment
return false return false
} }
anylit(ctxt, n.Right, n.Left, init) anylit(inInitFunction, n.Right, n.Left, init)
} }
n.Op = OEMPTY n.Op = OEMPTY
......
...@@ -1636,14 +1636,14 @@ opswitch: ...@@ -1636,14 +1636,14 @@ opswitch:
if isStaticCompositeLiteral(n) { if isStaticCompositeLiteral(n) {
// n can be directly represented in the read-only data section. // n can be directly represented in the read-only data section.
// Make direct reference to the static data. See issue 12841. // Make direct reference to the static data. See issue 12841.
vstat := staticname(n.Type, 0) vstat := staticname(n.Type, inInitFunction)
fixedlit(0, 1, n, vstat, init) fixedlit(inInitFunction, initKindStatic, n, vstat, init)
n = vstat n = vstat
n = typecheck(n, Erv) n = typecheck(n, Erv)
break break
} }
var_ := temp(n.Type) var_ := temp(n.Type)
anylit(0, n, var_, init) anylit(inInitFunction, n, var_, init)
n = var_ n = var_
case OSEND: case OSEND:
......
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