1
0
mirror of https://github.com/golang/go synced 2024-11-24 10:30:10 -07:00

cmd/compile: cleanup compile function

Make more idiomatic with a defer cleanup, which allows declaring
variables closer to their first use, rather than up front before the
first goto statement.

Also, split the legacy code generation code path into a separate
genlegacy function, analogous to the new genssa.

Passes toolstash -cmp.

Change-Id: I86c22838704f6861b75716ae64ba103b0e73b12f
Reviewed-on: https://go-review.googlesource.com/20353
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Matthew Dempsky 2016-03-07 22:05:49 -08:00
parent 4fc02d175b
commit e806cd9f95

View File

@ -350,31 +350,24 @@ func compile(fn *Node) {
panicdottype = Sysfunc("panicdottype") panicdottype = Sysfunc("panicdottype")
} }
lno := setlineno(fn) defer func(lno int32) {
lineno = lno
}(setlineno(fn))
Curfn = fn Curfn = fn
dowidth(Curfn.Type) dowidth(Curfn.Type)
var nod1 Node
var ptxt *obj.Prog
var pl *obj.Plist
var p *obj.Prog
var n *Node
var nam *Node
var gcargs *Sym
var gclocals *Sym
var ssafn *ssa.Func
if len(fn.Nbody.Slice()) == 0 { if len(fn.Nbody.Slice()) == 0 {
if pure_go != 0 || strings.HasPrefix(fn.Func.Nname.Sym.Name, "init.") { if pure_go != 0 || strings.HasPrefix(fn.Func.Nname.Sym.Name, "init.") {
Yyerror("missing function body for %q", fn.Func.Nname.Sym.Name) Yyerror("missing function body for %q", fn.Func.Nname.Sym.Name)
goto ret return
} }
if Debug['A'] != 0 { if Debug['A'] != 0 {
goto ret return
} }
emitptrargsmap() emitptrargsmap()
goto ret return
} }
saveerrors() saveerrors()
@ -385,37 +378,34 @@ func compile(fn *Node) {
if Curfn.Type.Outnamed { if Curfn.Type.Outnamed {
// add clearing of the output parameters // add clearing of the output parameters
var save Iter var save Iter
t := Structfirst(&save, Getoutarg(Curfn.Type)) for t := Structfirst(&save, Getoutarg(Curfn.Type)); t != nil; t = structnext(&save) {
for t != nil {
if t.Nname != nil { if t.Nname != nil {
n = Nod(OAS, t.Nname, nil) n := Nod(OAS, t.Nname, nil)
typecheck(&n, Etop) typecheck(&n, Etop)
Curfn.Nbody.Set(append([]*Node{n}, Curfn.Nbody.Slice()...)) Curfn.Nbody.Set(append([]*Node{n}, Curfn.Nbody.Slice()...))
} }
t = structnext(&save)
} }
} }
order(Curfn) order(Curfn)
if nerrors != 0 { if nerrors != 0 {
goto ret return
} }
hasdefer = false hasdefer = false
walk(Curfn) walk(Curfn)
if nerrors != 0 { if nerrors != 0 {
goto ret return
} }
if instrumenting { if instrumenting {
instrument(Curfn) instrument(Curfn)
} }
if nerrors != 0 { if nerrors != 0 {
goto ret return
} }
// Build an SSA backend function. // Build an SSA backend function.
var ssafn *ssa.Func
if shouldssa(Curfn) { if shouldssa(Curfn) {
ssafn = buildssa(Curfn) ssafn = buildssa(Curfn)
} }
@ -423,17 +413,18 @@ func compile(fn *Node) {
continpc = nil continpc = nil
breakpc = nil breakpc = nil
pl = newplist() pl := newplist()
pl.Name = Linksym(Curfn.Func.Nname.Sym) pl.Name = Linksym(Curfn.Func.Nname.Sym)
setlineno(Curfn) setlineno(Curfn)
var nod1 Node
Nodconst(&nod1, Types[TINT32], 0) Nodconst(&nod1, Types[TINT32], 0)
nam = Curfn.Func.Nname nam := Curfn.Func.Nname
if isblank(nam) { if isblank(nam) {
nam = nil nam = nil
} }
ptxt = Thearch.Gins(obj.ATEXT, nam, &nod1) ptxt := Thearch.Gins(obj.ATEXT, nam, &nod1)
Afunclit(&ptxt.From, Curfn.Func.Nname) Afunclit(&ptxt.From, Curfn.Func.Nname)
ptxt.From3 = new(obj.Addr) ptxt.From3 = new(obj.Addr)
if fn.Func.Dupok { if fn.Func.Dupok {
@ -455,7 +446,7 @@ func compile(fn *Node) {
// Clumsy but important. // Clumsy but important.
// See test/recover.go for test cases and src/reflect/value.go // See test/recover.go for test cases and src/reflect/value.go
// for the actual functions being considered. // for the actual functions being considered.
if myimportpath != "" && myimportpath == "reflect" { if myimportpath == "reflect" {
if Curfn.Func.Nname.Sym.Name == "callReflect" || Curfn.Func.Nname.Sym.Name == "callMethod" { if Curfn.Func.Nname.Sym.Name == "callReflect" || Curfn.Func.Nname.Sym.Name == "callMethod" {
ptxt.From3.Offset |= obj.WRAPPER ptxt.From3.Offset |= obj.WRAPPER
} }
@ -463,8 +454,8 @@ func compile(fn *Node) {
ginit() ginit()
gcargs = makefuncdatasym("gcargs·%d", obj.FUNCDATA_ArgsPointerMaps) gcargs := makefuncdatasym("gcargs·%d", obj.FUNCDATA_ArgsPointerMaps)
gclocals = makefuncdatasym("gclocals·%d", obj.FUNCDATA_LocalsPointerMaps) gclocals := makefuncdatasym("gclocals·%d", obj.FUNCDATA_LocalsPointerMaps)
for _, t := range Curfn.Func.Fieldtrack { for _, t := range Curfn.Func.Fieldtrack {
gtrack(tracksym(t)) gtrack(tracksym(t))
@ -477,7 +468,7 @@ func compile(fn *Node) {
switch n.Class { switch n.Class {
case PAUTO, PPARAM, PPARAMOUT: case PAUTO, PPARAM, PPARAMOUT:
Nodconst(&nod1, Types[TUINTPTR], n.Type.Width) Nodconst(&nod1, Types[TUINTPTR], n.Type.Width)
p = Thearch.Gins(obj.ATYPE, n, &nod1) p := Thearch.Gins(obj.ATYPE, n, &nod1)
p.From.Gotype = Linksym(ngotype(n)) p.From.Gotype = Linksym(ngotype(n))
} }
} }
@ -485,14 +476,19 @@ func compile(fn *Node) {
if ssafn != nil { if ssafn != nil {
genssa(ssafn, ptxt, gcargs, gclocals) genssa(ssafn, ptxt, gcargs, gclocals)
ssafn.Free() ssafn.Free()
goto ret } else {
genlegacy(ptxt, gcargs, gclocals)
} }
}
// genlegacy compiles Curfn using the legacy non-SSA code generator.
func genlegacy(ptxt *obj.Prog, gcargs, gclocals *Sym) {
Genlist(Curfn.Func.Enter) Genlist(Curfn.Func.Enter)
Genlist(Curfn.Nbody) Genlist(Curfn.Nbody)
gclean() gclean()
checklabels() checklabels()
if nerrors != 0 { if nerrors != 0 {
goto ret return
} }
if Curfn.Func.Endlineno != 0 { if Curfn.Func.Endlineno != 0 {
lineno = Curfn.Func.Endlineno lineno = Curfn.Func.Endlineno
@ -517,7 +513,7 @@ func compile(fn *Node) {
gclean() gclean()
if nerrors != 0 { if nerrors != 0 {
goto ret return
} }
Pc.As = obj.ARET // overwrite AEND Pc.As = obj.ARET // overwrite AEND
@ -536,7 +532,7 @@ func compile(fn *Node) {
setlineno(Curfn) setlineno(Curfn)
if Stksize+Maxarg > 1<<31 { if Stksize+Maxarg > 1<<31 {
Yyerror("stack frame too large (>2GB)") Yyerror("stack frame too large (>2GB)")
goto ret return
} }
// Emit garbage collection symbols. // Emit garbage collection symbols.
@ -553,7 +549,4 @@ func compile(fn *Node) {
// Remove leftover instrumentation from the instruction stream. // Remove leftover instrumentation from the instruction stream.
removevardef(ptxt) removevardef(ptxt)
ret:
lineno = lno
} }