return pl
}
+// nodarg does something that depends on the value of
+// fp (this was previously completely undocumented).
+//
+// fp=1 corresponds to input args
+// fp=0 corresponds to output args
+// fp=-1 is a special case of output args for a
+// specific call from walk that previously (and
+// incorrectly) passed a 1; the behavior is exactly
+// the same as it is for 1, except that PARAMOUT is
+// generated instead of PARAM.
func nodarg(t *Type, fp int) *Node {
var n *Node
Fatalf("nodarg: not field %v", t)
}
- if fp == 1 {
+ if fp == 1 || fp == -1 {
var n *Node
for l := Curfn.Func.Dcl; l != nil; l = l.Next {
n = l.N
case 1: // input arg
n.Class = PPARAM
+ case -1: // output arg from paramstoheap
+ n.Class = PPARAMOUT
+
case 2: // offset output arg
Fatalf("shouldn't be used")
}
fmt.Println("generating SSA for", name)
dumplist("buildssa-enter", fn.Func.Enter)
dumplist("buildssa-body", fn.Nbody)
+ dumplist("buildssa-exit", fn.Func.Exit)
}
var s state
s.config = ssa.NewConfig(Thearch.Thestring, &e)
s.f = s.config.NewFunc()
s.f.Name = name
+ s.exitCode = fn.Func.Exit
if name == os.Getenv("GOSSAFUNC") {
// TODO: tempfile? it is handy to have the location
// TODO this looks wrong for PAUTO|PHEAP, no vardef, but also no definition
aux := &ssa.AutoSymbol{Typ: n.Type, Node: n}
s.decladdrs[n] = s.entryNewValue1A(ssa.OpAddr, Ptrto(n.Type), aux, s.sp)
- case PPARAM | PHEAP: // PPARAMOUT | PHEAP seems to not occur
- // This ends up wrong, have to do it at the PARAM node instead.
+ case PPARAM | PHEAP, PPARAMOUT | PHEAP:
+ // This ends up wrong, have to do it at the PARAM node instead.
case PAUTO, PPARAMOUT:
// processed at each use, to prevent Addr coming
// before the decl.
// fallthrough to exit
if s.curBlock != nil {
+ s.stmtList(s.exitCode)
m := s.mem()
b := s.endBlock()
b.Kind = ssa.BlockRet
// Link up variable uses to variable definitions
s.linkForwardReferences()
+ // Don't carry reference this around longer than necessary
+ s.exitCode = nil
+
// Main call to ssa package to compile function
ssa.Compile(s.f)
// gotos that jump forward; required for deferred checkgoto calls
fwdGotos []*Node
+ // Code that must precede any return
+ // (e.g., copying value of heap-escaped paramout back to true paramout)
+ exitCode *NodeList
// unlabeled break and continue statement tracking
breakTo *ssa.Block // current target for plain break statement
case ORETURN:
s.stmtList(n.List)
+ s.stmtList(s.exitCode)
m := s.mem()
b := s.endBlock()
b.Kind = ssa.BlockRet
b.Control = m
case ORETJMP:
s.stmtList(n.List)
+ s.stmtList(s.exitCode)
m := s.mem()
b := s.endBlock()
b.Kind = ssa.BlockRetJmp
// Defer might stop a panic and show the
// return values as they exist at the time of panic.
// Make sure to zero them on entry to the function.
- nn = list(nn, Nod(OAS, nodarg(t, 1), nil))
+ nn = list(nn, Nod(OAS, nodarg(t, -1), nil))
}
if v == nil || v.Class&PHEAP == 0 {