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

cmd/compile: thread Curfn through SSA

This is a first step towards eliminating the
Curfn global in the backend.
There's more to do.

Passes toolstash -cmp. No compiler performance impact.

Updates #15756

Change-Id: Ib09f550a001e279a5aeeed0f85698290f890939c
Reviewed-on: https://go-review.googlesource.com/38232
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-by: default avatarMatthew Dempsky <mdempsky@google.com>
parent ce584e51
......@@ -13,11 +13,11 @@ import (
// no floating point in note handlers on Plan 9
var isPlan9 = obj.GOOS == "plan9"
func defframe(ptxt *obj.Prog) {
func defframe(ptxt *obj.Prog, fn *gc.Node) {
// fill in argument size, stack size
ptxt.To.Type = obj.TYPE_TEXTSIZE
ptxt.To.Val = int32(gc.Rnd(gc.Curfn.Type.ArgWidth(), int64(gc.Widthptr)))
ptxt.To.Val = int32(gc.Rnd(fn.Type.ArgWidth(), int64(gc.Widthptr)))
frame := uint32(gc.Rnd(gc.Stksize+gc.Maxarg, int64(gc.Widthreg)))
ptxt.To.Offset = int64(frame)
......@@ -32,7 +32,7 @@ func defframe(ptxt *obj.Prog) {
x0 := uint32(0)
// iterate through declarations - they are sorted in decreasing xoffset order.
for _, n := range gc.Curfn.Func.Dcl {
for _, n := range fn.Func.Dcl {
if !n.Name.Needzero() {
continue
}
......
......@@ -10,11 +10,11 @@ import (
"cmd/internal/obj/arm"
)
func defframe(ptxt *obj.Prog) {
func defframe(ptxt *obj.Prog, fn *gc.Node) {
// fill in argument size, stack size
ptxt.To.Type = obj.TYPE_TEXTSIZE
ptxt.To.Val = int32(gc.Rnd(gc.Curfn.Type.ArgWidth(), int64(gc.Widthptr)))
ptxt.To.Val = int32(gc.Rnd(fn.Type.ArgWidth(), int64(gc.Widthptr)))
frame := uint32(gc.Rnd(gc.Stksize+gc.Maxarg, int64(gc.Widthreg)))
ptxt.To.Offset = int64(frame)
......@@ -26,7 +26,7 @@ func defframe(ptxt *obj.Prog) {
hi := int64(0)
lo := hi
r0 := uint32(0)
for _, n := range gc.Curfn.Func.Dcl {
for _, n := range fn.Func.Dcl {
if !n.Name.Needzero() {
continue
}
......
......@@ -10,11 +10,11 @@ import (
"cmd/internal/obj/arm64"
)
func defframe(ptxt *obj.Prog) {
func defframe(ptxt *obj.Prog, fn *gc.Node) {
// fill in argument size, stack size
ptxt.To.Type = obj.TYPE_TEXTSIZE
ptxt.To.Val = int32(gc.Rnd(gc.Curfn.Type.ArgWidth(), int64(gc.Widthptr)))
ptxt.To.Val = int32(gc.Rnd(fn.Type.ArgWidth(), int64(gc.Widthptr)))
frame := uint32(gc.Rnd(gc.Stksize+gc.Maxarg, int64(gc.Widthreg)))
// arm64 requires that the frame size (not counting saved LR)
......@@ -34,7 +34,7 @@ func defframe(ptxt *obj.Prog) {
lo := hi
// iterate through declarations - they are sorted in decreasing xoffset order.
for _, n := range gc.Curfn.Func.Dcl {
for _, n := range fn.Func.Dcl {
if !n.Name.Needzero() {
continue
}
......
......@@ -365,7 +365,7 @@ type Arch struct {
MAXWIDTH int64
Use387 bool // should 386 backend use 387 FP instructions instead of sse2.
Defframe func(*obj.Prog)
Defframe func(*obj.Prog, *Node)
Ginsnop func()
Proginfo func(*obj.Prog) ProgInfo
......
......@@ -220,12 +220,13 @@ func (s byStackVar) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
var scratchFpMem *Node
func (s *ssaExport) AllocFrame(f *ssa.Func) {
func (s *ssafn) AllocFrame(f *ssa.Func) {
Stksize = 0
stkptrsize = 0
fn := s.curfn.Func
// Mark the PAUTO's unused.
for _, ln := range Curfn.Func.Dcl {
for _, ln := range fn.Dcl {
if ln.Class == PAUTO {
ln.SetUsed(false)
}
......@@ -259,15 +260,15 @@ func (s *ssaExport) AllocFrame(f *ssa.Func) {
scratchFpMem.SetUsed(scratchUsed)
}
sort.Sort(byStackVar(Curfn.Func.Dcl))
sort.Sort(byStackVar(fn.Dcl))
// Reassign stack offsets of the locals that are used.
for i, n := range Curfn.Func.Dcl {
for i, n := range fn.Dcl {
if n.Op != ONAME || n.Class != PAUTO {
continue
}
if !n.Used() {
Curfn.Func.Dcl = Curfn.Func.Dcl[:i]
fn.Dcl = fn.Dcl[:i]
break
}
......@@ -285,8 +286,7 @@ func (s *ssaExport) AllocFrame(f *ssa.Func) {
Stksize = Rnd(Stksize, int64(Widthptr))
}
if Stksize >= 1<<31 {
setlineno(Curfn)
yyerror("stack frame too large (>2GB)")
yyerrorl(s.curfn.Pos, "stack frame too large (>2GB)")
}
n.Xoffset = -Stksize
......
......@@ -19,7 +19,6 @@ import (
)
var ssaConfig *ssa.Config
var ssaExp ssaExport
var ssaCache *ssa.Cache
func initssaconfig() {
......@@ -50,9 +49,12 @@ func buildssa(fn *Node) *ssa.Func {
s.cgoUnsafeArgs = true
}
ssaExp.log = printssa
fe := ssafn{
curfn: fn,
log: printssa,
}
s.f = ssa.NewFunc(&ssaExp)
s.f = ssa.NewFunc(&fe)
s.config = ssaConfig
s.f.Config = ssaConfig
s.f.Cache = ssaCache
......@@ -4219,7 +4221,7 @@ func (s *SSAGenState) SetPos(pos src.XPos) {
func genssa(f *ssa.Func, ptxt *obj.Prog, gcargs, gclocals *Sym) {
var s SSAGenState
e := f.Frontend().(*ssaExport)
e := f.Frontend().(*ssafn)
// Remember where each block starts.
s.bstart = make([]*obj.Prog, f.NumBlocks())
......@@ -4350,10 +4352,10 @@ func genssa(f *ssa.Func, ptxt *obj.Prog, gcargs, gclocals *Sym) {
}
// Generate gc bitmaps.
liveness(Curfn, ptxt, gcargs, gclocals)
liveness(e.curfn, ptxt, gcargs, gclocals)
// Add frame prologue. Zero ambiguously live variables.
thearch.Defframe(ptxt)
thearch.Defframe(ptxt, e.curfn)
if Debug['f'] != 0 {
frame(0)
}
......@@ -4660,41 +4662,43 @@ func fieldIdx(n *Node) int {
// so we don't have to recompute it each time we need it.
}
// ssaExport exports a bunch of compiler services for the ssa backend.
type ssaExport struct {
log bool
}
func (s *ssaExport) TypeBool() ssa.Type { return Types[TBOOL] }
func (s *ssaExport) TypeInt8() ssa.Type { return Types[TINT8] }
func (s *ssaExport) TypeInt16() ssa.Type { return Types[TINT16] }
func (s *ssaExport) TypeInt32() ssa.Type { return Types[TINT32] }
func (s *ssaExport) TypeInt64() ssa.Type { return Types[TINT64] }
func (s *ssaExport) TypeUInt8() ssa.Type { return Types[TUINT8] }
func (s *ssaExport) TypeUInt16() ssa.Type { return Types[TUINT16] }
func (s *ssaExport) TypeUInt32() ssa.Type { return Types[TUINT32] }
func (s *ssaExport) TypeUInt64() ssa.Type { return Types[TUINT64] }
func (s *ssaExport) TypeFloat32() ssa.Type { return Types[TFLOAT32] }
func (s *ssaExport) TypeFloat64() ssa.Type { return Types[TFLOAT64] }
func (s *ssaExport) TypeInt() ssa.Type { return Types[TINT] }
func (s *ssaExport) TypeUintptr() ssa.Type { return Types[TUINTPTR] }
func (s *ssaExport) TypeString() ssa.Type { return Types[TSTRING] }
func (s *ssaExport) TypeBytePtr() ssa.Type { return ptrto(Types[TUINT8]) }
// ssafn holds frontend information about a function that the backend is processing.
// It also exports a bunch of compiler services for the ssa backend.
type ssafn struct {
curfn *Node
log bool
}
func (s *ssafn) TypeBool() ssa.Type { return Types[TBOOL] }
func (s *ssafn) TypeInt8() ssa.Type { return Types[TINT8] }
func (s *ssafn) TypeInt16() ssa.Type { return Types[TINT16] }
func (s *ssafn) TypeInt32() ssa.Type { return Types[TINT32] }
func (s *ssafn) TypeInt64() ssa.Type { return Types[TINT64] }
func (s *ssafn) TypeUInt8() ssa.Type { return Types[TUINT8] }
func (s *ssafn) TypeUInt16() ssa.Type { return Types[TUINT16] }
func (s *ssafn) TypeUInt32() ssa.Type { return Types[TUINT32] }
func (s *ssafn) TypeUInt64() ssa.Type { return Types[TUINT64] }
func (s *ssafn) TypeFloat32() ssa.Type { return Types[TFLOAT32] }
func (s *ssafn) TypeFloat64() ssa.Type { return Types[TFLOAT64] }
func (s *ssafn) TypeInt() ssa.Type { return Types[TINT] }
func (s *ssafn) TypeUintptr() ssa.Type { return Types[TUINTPTR] }
func (s *ssafn) TypeString() ssa.Type { return Types[TSTRING] }
func (s *ssafn) TypeBytePtr() ssa.Type { return ptrto(Types[TUINT8]) }
// StringData returns a symbol (a *Sym wrapped in an interface) which
// is the data component of a global string constant containing s.
func (*ssaExport) StringData(s string) interface{} {
func (*ssafn) StringData(s string) interface{} {
// TODO: is idealstring correct? It might not matter...
data := stringsym(s)
return &ssa.ExternSymbol{Typ: idealstring, Sym: data}
}
func (e *ssaExport) Auto(t ssa.Type) ssa.GCNode {
func (e *ssafn) Auto(t ssa.Type) ssa.GCNode {
n := temp(t.(*Type)) // Note: adds new auto to Curfn.Func.Dcl list
return n
}
func (e *ssaExport) SplitString(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot) {
func (e *ssafn) SplitString(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot) {
n := name.N.(*Node)
ptrType := ptrto(Types[TUINT8])
lenType := Types[TINT]
......@@ -4708,7 +4712,7 @@ func (e *ssaExport) SplitString(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlo
return ssa.LocalSlot{N: n, Type: ptrType, Off: name.Off}, ssa.LocalSlot{N: n, Type: lenType, Off: name.Off + int64(Widthptr)}
}
func (e *ssaExport) SplitInterface(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot) {
func (e *ssafn) SplitInterface(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot) {
n := name.N.(*Node)
t := ptrto(Types[TUINT8])
if n.Class == PAUTO && !n.Addrtaken() {
......@@ -4725,7 +4729,7 @@ func (e *ssaExport) SplitInterface(name ssa.LocalSlot) (ssa.LocalSlot, ssa.Local
return ssa.LocalSlot{N: n, Type: t, Off: name.Off}, ssa.LocalSlot{N: n, Type: t, Off: name.Off + int64(Widthptr)}
}
func (e *ssaExport) SplitSlice(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot, ssa.LocalSlot) {
func (e *ssafn) SplitSlice(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot, ssa.LocalSlot) {
n := name.N.(*Node)
ptrType := ptrto(name.Type.ElemType().(*Type))
lenType := Types[TINT]
......@@ -4742,7 +4746,7 @@ func (e *ssaExport) SplitSlice(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot
ssa.LocalSlot{N: n, Type: lenType, Off: name.Off + int64(2*Widthptr)}
}
func (e *ssaExport) SplitComplex(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot) {
func (e *ssafn) SplitComplex(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot) {
n := name.N.(*Node)
s := name.Type.Size() / 2
var t *Type
......@@ -4761,7 +4765,7 @@ func (e *ssaExport) SplitComplex(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSl
return ssa.LocalSlot{N: n, Type: t, Off: name.Off}, ssa.LocalSlot{N: n, Type: t, Off: name.Off + s}
}
func (e *ssaExport) SplitInt64(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot) {
func (e *ssafn) SplitInt64(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot) {
n := name.N.(*Node)
var t *Type
if name.Type.IsSigned() {
......@@ -4782,7 +4786,7 @@ func (e *ssaExport) SplitInt64(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot
return ssa.LocalSlot{N: n, Type: t, Off: name.Off + 4}, ssa.LocalSlot{N: n, Type: Types[TUINT32], Off: name.Off}
}
func (e *ssaExport) SplitStruct(name ssa.LocalSlot, i int) ssa.LocalSlot {
func (e *ssafn) SplitStruct(name ssa.LocalSlot, i int) ssa.LocalSlot {
n := name.N.(*Node)
st := name.Type
ft := st.FieldType(i)
......@@ -4796,7 +4800,7 @@ func (e *ssaExport) SplitStruct(name ssa.LocalSlot, i int) ssa.LocalSlot {
return ssa.LocalSlot{N: n, Type: ft, Off: name.Off + st.FieldOff(i)}
}
func (e *ssaExport) SplitArray(name ssa.LocalSlot) ssa.LocalSlot {
func (e *ssafn) SplitArray(name ssa.LocalSlot) ssa.LocalSlot {
n := name.N.(*Node)
at := name.Type
if at.NumElem() != 1 {
......@@ -4810,13 +4814,13 @@ func (e *ssaExport) SplitArray(name ssa.LocalSlot) ssa.LocalSlot {
return ssa.LocalSlot{N: n, Type: et, Off: name.Off}
}
func (e *ssaExport) DerefItab(it *obj.LSym, offset int64) *obj.LSym {
func (e *ssafn) DerefItab(it *obj.LSym, offset int64) *obj.LSym {
return itabsym(it, offset)
}
// namedAuto returns a new AUTO variable with the given name and type.
// These are exposed to the debugger.
func (e *ssaExport) namedAuto(name string, typ ssa.Type) ssa.GCNode {
func (e *ssafn) namedAuto(name string, typ ssa.Type) ssa.GCNode {
t := typ.(*Type)
s := &Sym{Name: name, Pkg: localpkg}
n := nod(ONAME, nil, nil)
......@@ -4828,62 +4832,62 @@ func (e *ssaExport) namedAuto(name string, typ ssa.Type) ssa.GCNode {
n.SetAddable(true)
n.Esc = EscNever
n.Xoffset = 0
n.Name.Curfn = Curfn
Curfn.Func.Dcl = append(Curfn.Func.Dcl, n)
n.Name.Curfn = e.curfn
e.curfn.Func.Dcl = append(e.curfn.Func.Dcl, n)
dowidth(t)
return n
}
func (e *ssaExport) CanSSA(t ssa.Type) bool {
func (e *ssafn) CanSSA(t ssa.Type) bool {
return canSSAType(t.(*Type))
}
func (e *ssaExport) Line(pos src.XPos) string {
func (e *ssafn) Line(pos src.XPos) string {
return linestr(pos)
}
// Log logs a message from the compiler.
func (e *ssaExport) Logf(msg string, args ...interface{}) {
func (e *ssafn) Logf(msg string, args ...interface{}) {
if e.log {
fmt.Printf(msg, args...)
}
}
func (e *ssaExport) Log() bool {
func (e *ssafn) Log() bool {
return e.log
}
// Fatal reports a compiler error and exits.
func (e *ssaExport) Fatalf(pos src.XPos, msg string, args ...interface{}) {
func (e *ssafn) Fatalf(pos src.XPos, msg string, args ...interface{}) {
lineno = pos
Fatalf(msg, args...)
}
// Error reports a compiler error but keep going.
func (e *ssaExport) Error(pos src.XPos, msg string, args ...interface{}) {
func (e *ssafn) Error(pos src.XPos, msg string, args ...interface{}) {
yyerrorl(pos, msg, args...)
}
// Warnl reports a "warning", which is usually flag-triggered
// logging output for the benefit of tests.
func (e *ssaExport) Warnl(pos src.XPos, fmt_ string, args ...interface{}) {
func (e *ssafn) Warnl(pos src.XPos, fmt_ string, args ...interface{}) {
Warnl(pos, fmt_, args...)
}
func (e *ssaExport) Debug_checknil() bool {
func (e *ssafn) Debug_checknil() bool {
return Debug_checknil != 0
}
func (e *ssaExport) Debug_wb() bool {
func (e *ssafn) Debug_wb() bool {
return Debug_wb != 0
}
func (e *ssaExport) UseWriteBarrier() bool {
func (e *ssafn) UseWriteBarrier() bool {
return use_writebarrier
}
func (e *ssaExport) Syslook(name string) *obj.LSym {
func (e *ssafn) Syslook(name string) *obj.LSym {
return Linksym(syslook(name).Sym)
}
......
......@@ -10,11 +10,11 @@ import (
"cmd/internal/obj/mips"
)
func defframe(ptxt *obj.Prog) {
func defframe(ptxt *obj.Prog, fn *gc.Node) {
// fill in argument size, stack size
ptxt.To.Type = obj.TYPE_TEXTSIZE
ptxt.To.Val = int32(gc.Rnd(gc.Curfn.Type.ArgWidth(), int64(gc.Widthptr)))
ptxt.To.Val = int32(gc.Rnd(fn.Type.ArgWidth(), int64(gc.Widthptr)))
frame := uint32(gc.Rnd(gc.Stksize+gc.Maxarg, int64(gc.Widthreg)))
ptxt.To.Offset = int64(frame)
......@@ -27,7 +27,7 @@ func defframe(ptxt *obj.Prog) {
lo := hi
// iterate through declarations - they are sorted in decreasing xoffset order.
for _, n := range gc.Curfn.Func.Dcl {
for _, n := range fn.Func.Dcl {
if !n.Name.Needzero() {
continue
}
......
......@@ -10,11 +10,11 @@ import (
"cmd/internal/obj/mips"
)
func defframe(ptxt *obj.Prog) {
func defframe(ptxt *obj.Prog, fn *gc.Node) {
// fill in argument size, stack size
ptxt.To.Type = obj.TYPE_TEXTSIZE
ptxt.To.Val = int32(gc.Rnd(gc.Curfn.Type.ArgWidth(), int64(gc.Widthptr)))
ptxt.To.Val = int32(gc.Rnd(fn.Type.ArgWidth(), int64(gc.Widthptr)))
frame := uint32(gc.Rnd(gc.Stksize+gc.Maxarg, int64(gc.Widthreg)))
ptxt.To.Offset = int64(frame)
......@@ -27,7 +27,7 @@ func defframe(ptxt *obj.Prog) {
lo := hi
// iterate through declarations - they are sorted in decreasing xoffset order.
for _, n := range gc.Curfn.Func.Dcl {
for _, n := range fn.Func.Dcl {
if !n.Name.Needzero() {
continue
}
......
......@@ -10,11 +10,11 @@ import (
"cmd/internal/obj/ppc64"
)
func defframe(ptxt *obj.Prog) {
func defframe(ptxt *obj.Prog, fn *gc.Node) {
// fill in argument size, stack size
ptxt.To.Type = obj.TYPE_TEXTSIZE
ptxt.To.Val = int32(gc.Rnd(gc.Curfn.Type.ArgWidth(), int64(gc.Widthptr)))
ptxt.To.Val = int32(gc.Rnd(fn.Type.ArgWidth(), int64(gc.Widthptr)))
frame := uint32(gc.Rnd(gc.Stksize+gc.Maxarg, int64(gc.Widthreg)))
ptxt.To.Offset = int64(frame)
......@@ -27,7 +27,7 @@ func defframe(ptxt *obj.Prog) {
lo := hi
// iterate through declarations - they are sorted in decreasing xoffset order.
for _, n := range gc.Curfn.Func.Dcl {
for _, n := range fn.Func.Dcl {
if !n.Name.Needzero() {
continue
}
......
......@@ -16,11 +16,11 @@ import (
// Must be between 256 and 4096.
const clearLoopCutoff = 1024
func defframe(ptxt *obj.Prog) {
func defframe(ptxt *obj.Prog, fn *gc.Node) {
// fill in argument size, stack size
ptxt.To.Type = obj.TYPE_TEXTSIZE
ptxt.To.Val = int32(gc.Rnd(gc.Curfn.Type.ArgWidth(), int64(gc.Widthptr)))
ptxt.To.Val = int32(gc.Rnd(fn.Type.ArgWidth(), int64(gc.Widthptr)))
frame := uint32(gc.Rnd(gc.Stksize+gc.Maxarg, int64(gc.Widthreg)))
ptxt.To.Offset = int64(frame)
......@@ -33,7 +33,7 @@ func defframe(ptxt *obj.Prog) {
lo := hi
// iterate through declarations - they are sorted in decreasing xoffset order.
for _, n := range gc.Curfn.Func.Dcl {
for _, n := range fn.Func.Dcl {
if !n.Name.Needzero() {
continue
}
......
......@@ -10,11 +10,11 @@ import (
"cmd/internal/obj/x86"
)
func defframe(ptxt *obj.Prog) {
func defframe(ptxt *obj.Prog, fn *gc.Node) {
// fill in argument size, stack size
ptxt.To.Type = obj.TYPE_TEXTSIZE
ptxt.To.Val = int32(gc.Rnd(gc.Curfn.Type.ArgWidth(), int64(gc.Widthptr)))
ptxt.To.Val = int32(gc.Rnd(fn.Type.ArgWidth(), int64(gc.Widthptr)))
frame := uint32(gc.Rnd(gc.Stksize+gc.Maxarg, int64(gc.Widthreg)))
ptxt.To.Offset = int64(frame)
......@@ -26,7 +26,7 @@ func defframe(ptxt *obj.Prog) {
hi := int64(0)
lo := hi
ax := uint32(0)
for _, n := range gc.Curfn.Func.Dcl {
for _, n := range fn.Func.Dcl {
if !n.Name.Needzero() {
continue
}
......
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