a.Offset = v
}
-// nodarg returns a Node for the function argument denoted by t,
-// which is either the entire function argument or result struct (t is a struct *types.Type)
-// or a specific argument (t is a *types.Field within a struct *types.Type).
-//
-// If fp is 0, the node is for use by a caller invoking the given
-// function, preparing the arguments before the call
-// or retrieving the results after the call.
-// In this case, the node will correspond to an outgoing argument
-// slot like 8(SP).
-//
-// If fp is 1, the node is for use by the function itself
-// (the callee), to retrieve its arguments or write its results.
-// In this case the node will be an ONAME with an appropriate
-// type and offset.
-func nodarg(t interface{}, fp int) *Node {
- var n *Node
-
- var funarg types.Funarg
- switch t := t.(type) {
- default:
- Fatalf("bad nodarg %T(%v)", t, t)
-
- case *types.Type:
- // Entire argument struct, not just one arg
- if !t.IsFuncArgStruct() {
- Fatalf("nodarg: bad type %v", t)
- }
- funarg = t.StructType().Funarg
-
- // Build fake variable name for whole arg struct.
- n = newname(lookup(".args"))
- n.Type = t
- first := t.Field(0)
- if first == nil {
- Fatalf("nodarg: bad struct")
- }
- if first.Offset == BADWIDTH {
- Fatalf("nodarg: offset not computed for %v", t)
- }
- n.Xoffset = first.Offset
-
- case *types.Field:
- funarg = t.Funarg
- if fp == 1 {
- // NOTE(rsc): This should be using t.Nname directly,
- // except in the case where t.Nname.Sym is the blank symbol and
- // so the assignment would be discarded during code generation.
- // In that case we need to make a new node, and there is no harm
- // in optimization passes to doing so. But otherwise we should
- // definitely be using the actual declaration and not a newly built node.
- // The extra Fatalf checks here are verifying that this is the case,
- // without changing the actual logic (at time of writing, it's getting
- // toward time for the Go 1.7 beta).
- // At some quieter time (assuming we've never seen these Fatalfs happen)
- // we could change this code to use "expect" directly.
- expect := asNode(t.Nname)
- if expect.isParamHeapCopy() {
- expect = expect.Name.Param.Stackcopy
- }
-
- for _, n := range Curfn.Func.Dcl {
- if (n.Class() == PPARAM || n.Class() == PPARAMOUT) && !t.Sym.IsBlank() && n.Sym == t.Sym {
- if n != expect {
- Fatalf("nodarg: unexpected node: %v (%p %v) vs %v (%p %v)", n, n, n.Op, asNode(t.Nname), asNode(t.Nname), asNode(t.Nname).Op)
- }
- return n
- }
- }
-
- if !expect.Sym.IsBlank() {
- Fatalf("nodarg: did not find node in dcl list: %v", expect)
- }
- }
-
- // Build fake name for individual variable.
- // This is safe because if there was a real declared name
- // we'd have used it above.
- n = newname(lookup("__"))
- n.Type = t.Type
- if t.Offset == BADWIDTH {
- Fatalf("nodarg: offset not computed for %v", t)
- }
- n.Xoffset = t.Offset
- n.Orig = asNode(t.Nname)
- }
-
- // Rewrite argument named _ to __,
- // or else the assignment to _ will be
- // discarded during code generation.
- if isblank(n) {
- n.Sym = lookup("__")
- }
-
- switch fp {
- default:
- Fatalf("bad fp")
-
- case 0: // preparing arguments for call
- n.Op = OINDREGSP
- n.Xoffset += Ctxt.FixedFrameSize()
-
- case 1: // reading arguments inside call
- n.SetClass(PPARAM)
- if funarg == types.FunargResults {
- n.SetClass(PPARAMOUT)
- }
- }
-
- n.SetTypecheck(1)
- n.SetAddrtaken(true) // keep optimizers at bay
- return n
-}
-
func Patch(p *obj.Prog, to *obj.Prog) {
if p.To.Type != obj.TYPE_BRANCH {
Fatalf("patch: not a branch")
return append(nn.Slice(), mm.Slice()...)
}
+// nodarg returns a Node for the function argument denoted by t,
+// which is either the entire function argument or result struct (t is a struct *types.Type)
+// or a specific argument (t is a *types.Field within a struct *types.Type).
+//
+// If fp is 0, the node is for use by a caller invoking the given
+// function, preparing the arguments before the call
+// or retrieving the results after the call.
+// In this case, the node will correspond to an outgoing argument
+// slot like 8(SP).
+//
+// If fp is 1, the node is for use by the function itself
+// (the callee), to retrieve its arguments or write its results.
+// In this case the node will be an ONAME with an appropriate
+// type and offset.
+func nodarg(t interface{}, fp int) *Node {
+ var n *Node
+
+ var funarg types.Funarg
+ switch t := t.(type) {
+ default:
+ Fatalf("bad nodarg %T(%v)", t, t)
+
+ case *types.Type:
+ // Entire argument struct, not just one arg
+ if !t.IsFuncArgStruct() {
+ Fatalf("nodarg: bad type %v", t)
+ }
+ funarg = t.StructType().Funarg
+
+ // Build fake variable name for whole arg struct.
+ n = newname(lookup(".args"))
+ n.Type = t
+ first := t.Field(0)
+ if first == nil {
+ Fatalf("nodarg: bad struct")
+ }
+ if first.Offset == BADWIDTH {
+ Fatalf("nodarg: offset not computed for %v", t)
+ }
+ n.Xoffset = first.Offset
+
+ case *types.Field:
+ funarg = t.Funarg
+ if fp == 1 {
+ // NOTE(rsc): This should be using t.Nname directly,
+ // except in the case where t.Nname.Sym is the blank symbol and
+ // so the assignment would be discarded during code generation.
+ // In that case we need to make a new node, and there is no harm
+ // in optimization passes to doing so. But otherwise we should
+ // definitely be using the actual declaration and not a newly built node.
+ // The extra Fatalf checks here are verifying that this is the case,
+ // without changing the actual logic (at time of writing, it's getting
+ // toward time for the Go 1.7 beta).
+ // At some quieter time (assuming we've never seen these Fatalfs happen)
+ // we could change this code to use "expect" directly.
+ expect := asNode(t.Nname)
+ if expect.isParamHeapCopy() {
+ expect = expect.Name.Param.Stackcopy
+ }
+
+ for _, n := range Curfn.Func.Dcl {
+ if (n.Class() == PPARAM || n.Class() == PPARAMOUT) && !t.Sym.IsBlank() && n.Sym == t.Sym {
+ if n != expect {
+ Fatalf("nodarg: unexpected node: %v (%p %v) vs %v (%p %v)", n, n, n.Op, asNode(t.Nname), asNode(t.Nname), asNode(t.Nname).Op)
+ }
+ return n
+ }
+ }
+
+ if !expect.Sym.IsBlank() {
+ Fatalf("nodarg: did not find node in dcl list: %v", expect)
+ }
+ }
+
+ // Build fake name for individual variable.
+ // This is safe because if there was a real declared name
+ // we'd have used it above.
+ n = newname(lookup("__"))
+ n.Type = t.Type
+ if t.Offset == BADWIDTH {
+ Fatalf("nodarg: offset not computed for %v", t)
+ }
+ n.Xoffset = t.Offset
+ n.Orig = asNode(t.Nname)
+ }
+
+ // Rewrite argument named _ to __,
+ // or else the assignment to _ will be
+ // discarded during code generation.
+ if isblank(n) {
+ n.Sym = lookup("__")
+ }
+
+ switch fp {
+ default:
+ Fatalf("bad fp")
+
+ case 0: // preparing arguments for call
+ n.Op = OINDREGSP
+ n.Xoffset += Ctxt.FixedFrameSize()
+
+ case 1: // reading arguments inside call
+ n.SetClass(PPARAM)
+ if funarg == types.FunargResults {
+ n.SetClass(PPARAMOUT)
+ }
+ }
+
+ n.SetTypecheck(1)
+ n.SetAddrtaken(true) // keep optimizers at bay
+ return n
+}
+
// package all the arguments that match a ... T parameter into a []T.
func mkdotargslice(typ *types.Type, args []*Node, init *Nodes, ddd *Node) *Node {
esc := uint16(EscUnknown)