]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/s390x: make assembler almost concurrency-safe
authorJosh Bleecher Snyder <josharian@gmail.com>
Tue, 11 Apr 2017 13:06:34 +0000 (06:06 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Tue, 11 Apr 2017 15:02:28 +0000 (15:02 +0000)
CL 39922 made the arm assembler concurrency-safe.
This CL does the same, but for s390x.
The approach is similar: introduce ctxtz to hold
function-local state and thread it through
the assembler as necessary.

One race remains after this CL, similar to CL 40252.

That race is conceptually unrelated to this refactoring,
and will be addressed in a separate CL.

Passes toolstash-check -all.

Updates #15756

Change-Id: Iabf17aa242b70c0b078c2e85dae3d93a5e512372
Reviewed-on: https://go-review.googlesource.com/40371
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Michael Munday <munday@ca.ibm.com>
src/cmd/internal/obj/link.go
src/cmd/internal/obj/s390x/asmz.go
src/cmd/internal/obj/s390x/objz.go

index 232ae241dd9cb1484ad3f1e3d9edf97f834fbea3..59a32d989482d3a36c02748dbff42f948afbe4d3 100644 (file)
@@ -727,7 +727,6 @@ type Link struct {
        InlTree       InlTree // global inlining tree used by gc/inl.go
        Imports       []string
        Plan9privates *LSym
-       Printp        *Prog
        Instoffset    int64
        Autosize      int32
        Pc            int64
index a7dafdffa086859eb6060f74effd4ae289ade03b..3b550355e8c3a7018a130c9ff39609f588454aa1 100644 (file)
@@ -36,6 +36,18 @@ import (
        "sort"
 )
 
+// ctxtz holds state while assembling a single function.
+// Each function gets a fresh ctxtz.
+// This allows for multiple functions to be safely concurrently assembled.
+type ctxtz struct {
+       ctxt       *obj.Link
+       newprog    obj.ProgAlloc
+       cursym     *obj.LSym
+       autosize   int32
+       instoffset int64
+       pc         int64
+}
+
 // instruction layout.
 const (
        funcAlign = 16
@@ -390,50 +402,50 @@ func spanz(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
        if p == nil || p.Link == nil { // handle external functions and ELF section symbols
                return
        }
-       ctxt.Cursym = cursym
-       ctxt.Autosize = int32(p.To.Offset)
 
        if oprange[AORW&obj.AMask] == nil {
                ctxt.Diag("s390x ops not initialized, call s390x.buildop first")
        }
 
+       c := ctxtz{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: int32(p.To.Offset)}
+
        buffer := make([]byte, 0)
        changed := true
        loop := 0
        for changed {
                if loop > 10 {
-                       ctxt.Diag("stuck in spanz loop")
+                       c.ctxt.Diag("stuck in spanz loop")
                        break
                }
                changed = false
                buffer = buffer[:0]
-               ctxt.Cursym.R = make([]obj.Reloc, 0)
-               for p := cursym.Text; p != nil; p = p.Link {
+               c.cursym.R = make([]obj.Reloc, 0)
+               for p := c.cursym.Text; p != nil; p = p.Link {
                        pc := int64(len(buffer))
                        if pc != p.Pc {
                                changed = true
                        }
                        p.Pc = pc
-                       ctxt.Pc = p.Pc
-                       asmout(ctxt, p, &buffer)
+                       c.pc = p.Pc
+                       c.asmout(p, &buffer)
                        if pc == int64(len(buffer)) {
                                switch p.As {
                                case obj.ANOP, obj.AFUNCDATA, obj.APCDATA, obj.ATEXT:
                                        // ok
                                default:
-                                       ctxt.Diag("zero-width instruction\n%v", p)
+                                       c.ctxt.Diag("zero-width instruction\n%v", p)
                                }
                        }
                }
                loop++
        }
 
-       cursym.Size = int64(len(buffer))
-       if cursym.Size%funcAlign != 0 {
-               cursym.Size += funcAlign - (cursym.Size % funcAlign)
+       c.cursym.Size = int64(len(buffer))
+       if c.cursym.Size%funcAlign != 0 {
+               c.cursym.Size += funcAlign - (c.cursym.Size % funcAlign)
        }
-       cursym.Grow(cursym.Size)
-       copy(cursym.P, buffer)
+       c.cursym.Grow(c.cursym.Size)
+       copy(c.cursym.P, buffer)
 }
 
 func isint32(v int64) bool {
@@ -444,7 +456,7 @@ func isuint32(v uint64) bool {
        return uint64(uint32(v)) == v
 }
 
-func aclass(ctxt *obj.Link, a *obj.Addr) int {
+func (c *ctxtz) aclass(a *obj.Addr) int {
        switch a.Type {
        case obj.TYPE_NONE:
                return C_NONE
@@ -472,9 +484,9 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
                                // must have a symbol
                                break
                        }
-                       ctxt.Instoffset = a.Offset
+                       c.instoffset = a.Offset
                        if a.Sym.Type == obj.STLSBSS {
-                               if ctxt.Flag_shared {
+                               if c.ctxt.Flag_shared {
                                        return C_TLS_IE // initial exec model
                                }
                                return C_TLS_LE // local exec model
@@ -485,25 +497,25 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
                        return C_GOTADDR
 
                case obj.NAME_AUTO:
-                       ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset
-                       if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
+                       c.instoffset = int64(c.autosize) + a.Offset
+                       if c.instoffset >= -BIG && c.instoffset < BIG {
                                return C_SAUTO
                        }
                        return C_LAUTO
 
                case obj.NAME_PARAM:
-                       ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + ctxt.FixedFrameSize()
-                       if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
+                       c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
+                       if c.instoffset >= -BIG && c.instoffset < BIG {
                                return C_SAUTO
                        }
                        return C_LAUTO
 
                case obj.NAME_NONE:
-                       ctxt.Instoffset = a.Offset
-                       if ctxt.Instoffset == 0 {
+                       c.instoffset = a.Offset
+                       if c.instoffset == 0 {
                                return C_ZOREG
                        }
-                       if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
+                       if c.instoffset >= -BIG && c.instoffset < BIG {
                                return C_SOREG
                        }
                        return C_LOREG
@@ -518,18 +530,18 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
                if f64, ok := a.Val.(float64); ok && math.Float64bits(f64) == 0 {
                        return C_ZCON
                }
-               ctxt.Diag("cannot handle the floating point constant %v", a.Val)
+               c.ctxt.Diag("cannot handle the floating point constant %v", a.Val)
 
        case obj.TYPE_CONST,
                obj.TYPE_ADDR:
                switch a.Name {
                case obj.NAME_NONE:
-                       ctxt.Instoffset = a.Offset
+                       c.instoffset = a.Offset
                        if a.Reg != 0 {
-                               if -BIG <= ctxt.Instoffset && ctxt.Instoffset <= BIG {
+                               if -BIG <= c.instoffset && c.instoffset <= BIG {
                                        return C_SACON
                                }
-                               if isint32(ctxt.Instoffset) {
+                               if isint32(c.instoffset) {
                                        return C_LACON
                                }
                                return C_DACON
@@ -542,7 +554,7 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
                        if s == nil {
                                break
                        }
-                       ctxt.Instoffset = a.Offset
+                       c.instoffset = a.Offset
                        if s.Type == obj.SCONST {
                                goto consize
                        }
@@ -550,15 +562,15 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
                        return C_SYMADDR
 
                case obj.NAME_AUTO:
-                       ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset
-                       if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
+                       c.instoffset = int64(c.autosize) + a.Offset
+                       if c.instoffset >= -BIG && c.instoffset < BIG {
                                return C_SACON
                        }
                        return C_LACON
 
                case obj.NAME_PARAM:
-                       ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + ctxt.FixedFrameSize()
-                       if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
+                       c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
+                       if c.instoffset >= -BIG && c.instoffset < BIG {
                                return C_SACON
                        }
                        return C_LACON
@@ -567,32 +579,32 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
                return C_GOK
 
        consize:
-               if ctxt.Instoffset == 0 {
+               if c.instoffset == 0 {
                        return C_ZCON
                }
-               if ctxt.Instoffset >= 0 {
-                       if ctxt.Instoffset <= 0x7fff {
+               if c.instoffset >= 0 {
+                       if c.instoffset <= 0x7fff {
                                return C_SCON
                        }
-                       if ctxt.Instoffset <= 0xffff {
+                       if c.instoffset <= 0xffff {
                                return C_ANDCON
                        }
-                       if ctxt.Instoffset&0xffff == 0 && isuint32(uint64(ctxt.Instoffset)) { /* && (instoffset & (1<<31)) == 0) */
+                       if c.instoffset&0xffff == 0 && isuint32(uint64(c.instoffset)) { /* && (instoffset & (1<<31)) == 0) */
                                return C_UCON
                        }
-                       if isint32(ctxt.Instoffset) || isuint32(uint64(ctxt.Instoffset)) {
+                       if isint32(c.instoffset) || isuint32(uint64(c.instoffset)) {
                                return C_LCON
                        }
                        return C_DCON
                }
 
-               if ctxt.Instoffset >= -0x8000 {
+               if c.instoffset >= -0x8000 {
                        return C_ADDCON
                }
-               if ctxt.Instoffset&0xffff == 0 && isint32(ctxt.Instoffset) {
+               if c.instoffset&0xffff == 0 && isint32(c.instoffset) {
                        return C_UCON
                }
-               if isint32(ctxt.Instoffset) {
+               if isint32(c.instoffset) {
                        return C_LCON
                }
                return C_DCON
@@ -604,14 +616,14 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
        return C_GOK
 }
 
-func oplook(ctxt *obj.Link, p *obj.Prog) *Optab {
+func (c *ctxtz) oplook(p *obj.Prog) *Optab {
        a1 := int(p.Optab)
        if a1 != 0 {
                return &optab[a1-1]
        }
        a1 = int(p.From.Class)
        if a1 == 0 {
-               a1 = aclass(ctxt, &p.From) + 1
+               a1 = c.aclass(&p.From) + 1
                p.From.Class = int8(a1)
        }
 
@@ -620,7 +632,7 @@ func oplook(ctxt *obj.Link, p *obj.Prog) *Optab {
        if p.From3 != nil {
                a3 = int(p.From3.Class)
                if a3 == 0 {
-                       a3 = aclass(ctxt, p.From3) + 1
+                       a3 = c.aclass(p.From3) + 1
                        p.From3.Class = int8(a3)
                }
        }
@@ -628,7 +640,7 @@ func oplook(ctxt *obj.Link, p *obj.Prog) *Optab {
        a3--
        a4 := int(p.To.Class)
        if a4 == 0 {
-               a4 = aclass(ctxt, &p.To) + 1
+               a4 = c.aclass(&p.To) + 1
                p.To.Class = int8(a4)
        }
 
@@ -660,8 +672,8 @@ func oplook(ctxt *obj.Link, p *obj.Prog) *Optab {
        }
 
        // cannot find a case; abort
-       ctxt.Diag("illegal combination %v %v %v %v %v\n", p.As, DRconv(a1), DRconv(a2), DRconv(a3), DRconv(a4))
-       ctxt.Diag("prog: %v\n", p)
+       c.ctxt.Diag("illegal combination %v %v %v %v %v\n", p.As, DRconv(a1), DRconv(a2), DRconv(a3), DRconv(a4))
+       c.ctxt.Diag("prog: %v\n", p)
        return nil
 }
 
@@ -2484,13 +2496,13 @@ func oclass(a *obj.Addr) int {
 
 // Add a relocation for the immediate in a RIL style instruction.
 // The addend will be adjusted as required.
-func addrilreloc(ctxt *obj.Link, sym *obj.LSym, add int64) *obj.Reloc {
+func (c *ctxtz) addrilreloc(sym *obj.LSym, add int64) *obj.Reloc {
        if sym == nil {
-               ctxt.Diag("require symbol to apply relocation")
+               c.ctxt.Diag("require symbol to apply relocation")
        }
        offset := int64(2) // relocation offset from start of instruction
-       rel := obj.Addrel(ctxt.Cursym)
-       rel.Off = int32(ctxt.Pc + offset)
+       rel := obj.Addrel(c.cursym)
+       rel.Off = int32(c.pc + offset)
        rel.Siz = 4
        rel.Sym = sym
        rel.Add = add + offset + int64(rel.Siz)
@@ -2498,13 +2510,13 @@ func addrilreloc(ctxt *obj.Link, sym *obj.LSym, add int64) *obj.Reloc {
        return rel
 }
 
-func addrilrelocoffset(ctxt *obj.Link, sym *obj.LSym, add, offset int64) *obj.Reloc {
+func (c *ctxtz) addrilrelocoffset(sym *obj.LSym, add, offset int64) *obj.Reloc {
        if sym == nil {
-               ctxt.Diag("require symbol to apply relocation")
+               c.ctxt.Diag("require symbol to apply relocation")
        }
        offset += int64(2) // relocation offset from start of instruction
-       rel := obj.Addrel(ctxt.Cursym)
-       rel.Off = int32(ctxt.Pc + offset)
+       rel := obj.Addrel(c.cursym)
+       rel.Off = int32(c.pc + offset)
        rel.Siz = 4
        rel.Sym = sym
        rel.Add = add + offset + int64(rel.Siz)
@@ -2514,13 +2526,13 @@ func addrilrelocoffset(ctxt *obj.Link, sym *obj.LSym, add, offset int64) *obj.Re
 
 // Add a CALL relocation for the immediate in a RIL style instruction.
 // The addend will be adjusted as required.
-func addcallreloc(ctxt *obj.Link, sym *obj.LSym, add int64) *obj.Reloc {
+func (c *ctxtz) addcallreloc(sym *obj.LSym, add int64) *obj.Reloc {
        if sym == nil {
-               ctxt.Diag("require symbol to apply relocation")
+               c.ctxt.Diag("require symbol to apply relocation")
        }
        offset := int64(2) // relocation offset from start of instruction
-       rel := obj.Addrel(ctxt.Cursym)
-       rel.Off = int32(ctxt.Pc + offset)
+       rel := obj.Addrel(c.cursym)
+       rel.Off = int32(c.pc + offset)
        rel.Siz = 4
        rel.Sym = sym
        rel.Add = add + offset + int64(rel.Siz)
@@ -2528,7 +2540,7 @@ func addcallreloc(ctxt *obj.Link, sym *obj.LSym, add int64) *obj.Reloc {
        return rel
 }
 
-func branchMask(ctxt *obj.Link, p *obj.Prog) uint32 {
+func (c *ctxtz) branchMask(p *obj.Prog) uint32 {
        switch p.As {
        case ABEQ, ACMPBEQ, ACMPUBEQ, AMOVDEQ:
                return 0x8
@@ -2551,17 +2563,16 @@ func branchMask(ctxt *obj.Link, p *obj.Prog) uint32 {
        case ABVS:
                return 0x1 // unordered
        }
-       ctxt.Diag("unknown conditional branch %v", p.As)
+       c.ctxt.Diag("unknown conditional branch %v", p.As)
        return 0xF
 }
 
-func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
-       o := oplook(ctxt, p)
-       ctxt.Printp = p
+func (c *ctxtz) asmout(p *obj.Prog, asm *[]byte) {
+       o := c.oplook(p)
 
        switch o.type_ {
        default:
-               ctxt.Diag("unknown type %d", o.type_)
+               c.ctxt.Diag("unknown type %d", o.type_)
 
        case 0: // PSEUDO OPS
                break
@@ -2569,7 +2580,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
        case 1: // mov reg reg
                switch p.As {
                default:
-                       ctxt.Diag("unhandled operation: %v", p.As)
+                       c.ctxt.Diag("unhandled operation: %v", p.As)
                case AMOVD:
                        zRRE(op_LGR, uint32(p.To.Reg), uint32(p.From.Reg), asm)
                // sign extend
@@ -2606,7 +2617,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
 
                switch p.As {
                default:
-                       ctxt.Diag("invalid opcode")
+                       c.ctxt.Diag("invalid opcode")
                case AADD:
                        opcode = op_AGRK
                case AADDC:
@@ -2668,7 +2679,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                }
 
        case 3: // mov $constant reg
-               v := vregoff(ctxt, &p.From)
+               v := c.vregoff(&p.From)
                switch p.As {
                case AMOVBZ:
                        v = int64(uint8(v))
@@ -2760,7 +2771,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                }
 
        case 7: // shift/rotate reg [reg] reg
-               d2 := vregoff(ctxt, &p.From)
+               d2 := c.vregoff(&p.From)
                b2 := p.From.Reg
                r3 := p.Reg
                if r3 == 0 {
@@ -2791,7 +2802,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
 
        case 8: // find leftmost one
                if p.To.Reg&1 != 0 {
-                       ctxt.Diag("target must be an even-numbered register")
+                       c.ctxt.Diag("target must be an even-numbered register")
                }
                // FLOGR also writes a mask to p.To.Reg+1.
                zRRE(op_FLOGR, uint32(p.To.Reg), uint32(p.From.Reg), asm)
@@ -2851,13 +2862,13 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                                zRIL(_c, op_BRCL, 0xF, uint32(v), asm)
                        }
                        if p.To.Sym != nil {
-                               addcallreloc(ctxt, p.To.Sym, p.To.Offset)
+                               c.addcallreloc(p.To.Sym, p.To.Offset)
                        }
                }
 
        case 12:
                r1 := p.To.Reg
-               d2 := vregoff(ctxt, &p.From)
+               d2 := c.vregoff(&p.From)
                b2 := p.From.Reg
                if b2 == 0 {
                        b2 = o.param
@@ -2929,18 +2940,18 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                if p.Pcond != nil {
                        v = int32((p.Pcond.Pc - p.Pc) >> 1)
                }
-               mask := branchMask(ctxt, p)
+               mask := c.branchMask(p)
                if p.To.Sym == nil && int32(int16(v)) == v {
                        zRI(op_BRC, mask, uint32(v), asm)
                } else {
                        zRIL(_c, op_BRCL, mask, uint32(v), asm)
                }
                if p.To.Sym != nil {
-                       addrilreloc(ctxt, p.To.Sym, p.To.Offset)
+                       c.addrilreloc(p.To.Sym, p.To.Offset)
                }
 
        case 17: // move on condition
-               m3 := branchMask(ctxt, p)
+               m3 := c.branchMask(p)
                zRRF(op_LOCGR, m3, 0, uint32(p.To.Reg), uint32(p.From.Reg), asm)
 
        case 18: // br/bl reg
@@ -2951,16 +2962,16 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                }
 
        case 19: // mov $sym+n(SB) reg
-               d := vregoff(ctxt, &p.From)
+               d := c.vregoff(&p.From)
                zRIL(_b, op_LARL, uint32(p.To.Reg), 0, asm)
                if d&1 != 0 {
                        zRX(op_LA, uint32(p.To.Reg), uint32(p.To.Reg), 0, 1, asm)
                        d -= 1
                }
-               addrilreloc(ctxt, p.From.Sym, d)
+               c.addrilreloc(p.From.Sym, d)
 
        case 21: // subtract $constant [reg] reg
-               v := vregoff(ctxt, &p.From)
+               v := c.vregoff(&p.From)
                r := p.Reg
                if r == 0 {
                        r = p.To.Reg
@@ -2982,7 +2993,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                }
 
        case 22: // add/multiply $constant [reg] reg
-               v := vregoff(ctxt, &p.From)
+               v := c.vregoff(&p.From)
                r := p.Reg
                if r == 0 {
                        r = p.To.Reg
@@ -3028,10 +3039,10 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
 
        case 23: // 64-bit logical op $constant reg
                // TODO(mundaym): merge with case 24.
-               v := vregoff(ctxt, &p.From)
+               v := c.vregoff(&p.From)
                switch p.As {
                default:
-                       ctxt.Diag("%v is not supported", p)
+                       c.ctxt.Diag("%v is not supported", p)
                case AAND:
                        if v >= 0 { // needs zero extend
                                zRIL(_a, op_LGFI, REGTMP, uint32(v), asm)
@@ -3060,7 +3071,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                }
 
        case 24: // 32-bit logical op $constant reg
-               v := vregoff(ctxt, &p.From)
+               v := c.vregoff(&p.From)
                switch p.As {
                case AANDW:
                        if uint32(v&0xffff0000) == 0xffff0000 {
@@ -3083,7 +3094,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                }
 
        case 26: // MOVD $offset(base)(index), reg
-               v := regoff(ctxt, &p.From)
+               v := c.regoff(&p.From)
                r := p.From.Reg
                if r == 0 {
                        r = o.param
@@ -3099,7 +3110,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                }
 
        case 31: // dword
-               wd := uint64(vregoff(ctxt, &p.From))
+               wd := uint64(c.vregoff(&p.From))
                *asm = append(*asm,
                        uint8(wd>>56),
                        uint8(wd>>48),
@@ -3114,7 +3125,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                var opcode uint32
                switch p.As {
                default:
-                       ctxt.Diag("invalid opcode")
+                       c.ctxt.Diag("invalid opcode")
                case AFADD:
                        opcode = op_ADBR
                case AFADDS:
@@ -3165,7 +3176,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                var opcode uint32
                switch p.As {
                default:
-                       ctxt.Diag("invalid opcode")
+                       c.ctxt.Diag("invalid opcode")
                case AFMADD:
                        opcode = op_MADBR
                case AFMADDS:
@@ -3178,7 +3189,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                zRRD(opcode, uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), asm)
 
        case 35: // mov reg mem (no relocation)
-               d2 := regoff(ctxt, &p.To)
+               d2 := c.regoff(&p.To)
                b2 := p.To.Reg
                if b2 == 0 {
                        b2 = o.param
@@ -3192,10 +3203,10 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                        x2 = REGTMP
                        d2 = 0
                }
-               zRXY(zopstore(ctxt, p.As), uint32(p.From.Reg), uint32(x2), uint32(b2), uint32(d2), asm)
+               zRXY(c.zopstore(p.As), uint32(p.From.Reg), uint32(x2), uint32(b2), uint32(d2), asm)
 
        case 36: // mov mem reg (no relocation)
-               d2 := regoff(ctxt, &p.From)
+               d2 := c.regoff(&p.From)
                b2 := p.From.Reg
                if b2 == 0 {
                        b2 = o.param
@@ -3209,10 +3220,10 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                        x2 = REGTMP
                        d2 = 0
                }
-               zRXY(zopload(ctxt, p.As), uint32(p.To.Reg), uint32(x2), uint32(b2), uint32(d2), asm)
+               zRXY(c.zopload(p.As), uint32(p.To.Reg), uint32(x2), uint32(b2), uint32(d2), asm)
 
        case 40: // word/byte
-               wd := uint32(regoff(ctxt, &p.From))
+               wd := uint32(c.regoff(&p.From))
                if p.As == AWORD { //WORD
                        *asm = append(*asm, uint8(wd>>24), uint8(wd>>16), uint8(wd>>8), uint8(wd))
                } else { //BYTE
@@ -3232,9 +3243,9 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                }
 
        case 48: // floating-point round to integer
-               m3 := vregoff(ctxt, &p.From)
+               m3 := c.vregoff(&p.From)
                if 0 > m3 || m3 > 7 {
-                       ctxt.Diag("mask (%v) must be in the range [0, 7]", m3)
+                       c.ctxt.Diag("mask (%v) must be in the range [0, 7]", m3)
                }
                var opcode uint32
                switch p.As {
@@ -3263,21 +3274,21 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
 
        case 70: // cmp reg reg
                if p.As == ACMPW || p.As == ACMPWU {
-                       zRR(zoprr(ctxt, p.As), uint32(p.From.Reg), uint32(p.To.Reg), asm)
+                       zRR(c.zoprr(p.As), uint32(p.From.Reg), uint32(p.To.Reg), asm)
                } else {
-                       zRRE(zoprre(ctxt, p.As), uint32(p.From.Reg), uint32(p.To.Reg), asm)
+                       zRRE(c.zoprre(p.As), uint32(p.From.Reg), uint32(p.To.Reg), asm)
                }
 
        case 71: // cmp reg $constant
-               v := vregoff(ctxt, &p.To)
+               v := c.vregoff(&p.To)
                switch p.As {
                case ACMP, ACMPW:
                        if int64(int32(v)) != v {
-                               ctxt.Diag("%v overflows an int32", v)
+                               c.ctxt.Diag("%v overflows an int32", v)
                        }
                case ACMPU, ACMPWU:
                        if int64(uint32(v)) != v {
-                               ctxt.Diag("%v overflows a uint32", v)
+                               c.ctxt.Diag("%v overflows a uint32", v)
                        }
                }
                if p.As == ACMP && int64(int16(v)) == v {
@@ -3285,12 +3296,12 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                } else if p.As == ACMPW && int64(int16(v)) == v {
                        zRI(op_CHI, uint32(p.From.Reg), uint32(v), asm)
                } else {
-                       zRIL(_a, zopril(ctxt, p.As), uint32(p.From.Reg), uint32(v), asm)
+                       zRIL(_a, c.zopril(p.As), uint32(p.From.Reg), uint32(v), asm)
                }
 
        case 72: // mov $constant mem
-               v := regoff(ctxt, &p.From)
-               d := regoff(ctxt, &p.To)
+               v := c.regoff(&p.From)
+               d := c.regoff(&p.To)
                r := p.To.Reg
                x := p.To.Index
                if r == 0 {
@@ -3337,19 +3348,19 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                                }
                                d = 0
                        }
-                       zRXY(zopstore(ctxt, p.As), REGTMP2, uint32(x), uint32(r), uint32(d), asm)
+                       zRXY(c.zopstore(p.As), REGTMP2, uint32(x), uint32(r), uint32(d), asm)
                }
 
        case 73: // mov $constant addr (including relocation)
-               v := regoff(ctxt, &p.From)
-               d := regoff(ctxt, &p.To)
+               v := c.regoff(&p.From)
+               d := c.regoff(&p.To)
                a := uint32(0)
                if d&1 != 0 {
                        d -= 1
                        a = 1
                }
                zRIL(_b, op_LARL, REGTMP, uint32(d), asm)
-               addrilreloc(ctxt, p.To.Sym, int64(d))
+               c.addrilreloc(p.To.Sym, int64(d))
                if int32(int16(v)) == v {
                        var opcode uint32
                        switch p.As {
@@ -3369,11 +3380,11 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                        }
                } else {
                        zRIL(_a, op_LGFI, REGTMP2, uint32(v), asm)
-                       zRXY(zopstore(ctxt, p.As), REGTMP2, 0, REGTMP, a, asm)
+                       zRXY(c.zopstore(p.As), REGTMP2, 0, REGTMP, a, asm)
                }
 
        case 74: // mov reg addr (including relocation)
-               i2 := regoff(ctxt, &p.To)
+               i2 := c.regoff(&p.To)
                switch p.As {
                case AMOVD:
                        zRIL(_b, op_STGRL, uint32(p.From.Reg), 0, asm)
@@ -3396,10 +3407,10 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                        zRIL(_b, op_LARL, REGTMP, 0, asm)
                        zRX(op_STE, uint32(p.From.Reg), 0, REGTMP, 0, asm)
                }
-               addrilreloc(ctxt, p.To.Sym, int64(i2))
+               c.addrilreloc(p.To.Sym, int64(i2))
 
        case 75: // mov addr reg (including relocation)
-               i2 := regoff(ctxt, &p.From)
+               i2 := c.regoff(&p.From)
                switch p.As {
                case AMOVD:
                        if i2&1 != 0 {
@@ -3437,11 +3448,11 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                        zRIL(_a, op_LARL, REGTMP, 0, asm)
                        zRX(op_LE, uint32(p.To.Reg), 0, REGTMP, 0, asm)
                }
-               addrilreloc(ctxt, p.From.Sym, int64(i2))
+               c.addrilreloc(p.From.Sym, int64(i2))
 
        case 77: // syscall $constant
                if p.From.Offset > 255 || p.From.Offset < 1 {
-                       ctxt.Diag("illegal system call; system call number out of range: %v", p)
+                       c.ctxt.Diag("illegal system call; system call number out of range: %v", p)
                        zE(op_TRAP2, asm) // trap always
                } else {
                        zI(op_SVC, uint32(p.From.Offset), asm)
@@ -3453,7 +3464,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                *asm = append(*asm, 0, 0, 0, 0)
 
        case 79: // compare and swap reg reg reg
-               v := regoff(ctxt, &p.To)
+               v := c.regoff(&p.To)
                if v < 0 {
                        v = 0
                }
@@ -3521,12 +3532,12 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                zRRF(opcode, 5, 0, uint32(p.To.Reg), uint32(p.From.Reg), asm)
 
        case 84: // storage-and-storage operations $length mem mem (length in From3)
-               l := regoff(ctxt, p.From3)
+               l := c.regoff(p.From3)
                if l < 1 || l > 256 {
-                       ctxt.Diag("number of bytes (%v) not in range [1,256]", l)
+                       c.ctxt.Diag("number of bytes (%v) not in range [1,256]", l)
                }
                if p.From.Index != 0 || p.To.Index != 0 {
-                       ctxt.Diag("cannot use index reg")
+                       c.ctxt.Diag("cannot use index reg")
                }
                b1 := p.To.Reg
                b2 := p.From.Reg
@@ -3536,11 +3547,11 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                if b2 == 0 {
                        b2 = o.param
                }
-               d1 := regoff(ctxt, &p.To)
-               d2 := regoff(ctxt, &p.From)
+               d1 := c.regoff(&p.To)
+               d2 := c.regoff(&p.From)
                if d1 < 0 || d1 >= DISP12 {
                        if b2 == REGTMP {
-                               ctxt.Diag("REGTMP conflict")
+                               c.ctxt.Diag("REGTMP conflict")
                        }
                        if b1 != REGTMP {
                                zRRE(op_LGR, REGTMP, uint32(b1), asm)
@@ -3555,7 +3566,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                }
                if d2 < 0 || d2 >= DISP12 {
                        if b1 == REGTMP2 {
-                               ctxt.Diag("REGTMP2 conflict")
+                               c.ctxt.Diag("REGTMP2 conflict")
                        }
                        if b2 != REGTMP2 {
                                zRRE(op_LGR, REGTMP2, uint32(b2), asm)
@@ -3567,7 +3578,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                var opcode uint32
                switch p.As {
                default:
-                       ctxt.Diag("unexpected opcode %v", p.As)
+                       c.ctxt.Diag("unexpected opcode %v", p.As)
                case AMVC:
                        opcode = op_MVC
                case ACLC:
@@ -3585,19 +3596,19 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                zSS(_a, opcode, uint32(l-1), 0, uint32(b1), uint32(d1), uint32(b2), uint32(d2), asm)
 
        case 85: // load address relative long
-               v := regoff(ctxt, &p.From)
+               v := c.regoff(&p.From)
                if p.From.Sym == nil {
                        if (v & 1) != 0 {
-                               ctxt.Diag("cannot use LARL with odd offset: %v", v)
+                               c.ctxt.Diag("cannot use LARL with odd offset: %v", v)
                        }
                } else {
-                       addrilreloc(ctxt, p.From.Sym, int64(v))
+                       c.addrilreloc(p.From.Sym, int64(v))
                        v = 0
                }
                zRIL(_b, op_LARL, uint32(p.To.Reg), uint32(v>>1), asm)
 
        case 86: // load address
-               d := vregoff(ctxt, &p.From)
+               d := c.vregoff(&p.From)
                x := p.From.Index
                b := p.From.Reg
                if b == 0 {
@@ -3611,13 +3622,13 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                }
 
        case 87: // execute relative long
-               v := vregoff(ctxt, &p.From)
+               v := c.vregoff(&p.From)
                if p.From.Sym == nil {
                        if v&1 != 0 {
-                               ctxt.Diag("cannot use EXRL with odd offset: %v", v)
+                               c.ctxt.Diag("cannot use EXRL with odd offset: %v", v)
                        }
                } else {
-                       addrilreloc(ctxt, p.From.Sym, v)
+                       c.addrilreloc(p.From.Sym, v)
                        v = 0
                }
                zRIL(_b, op_EXRL, uint32(p.To.Reg), uint32(v>>1), asm)
@@ -3634,7 +3645,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                case ASTCKF:
                        opcode = op_STCKF
                }
-               v := vregoff(ctxt, &p.To)
+               v := c.vregoff(&p.To)
                r := int(p.To.Reg)
                if r == 0 {
                        r = int(o.param)
@@ -3655,7 +3666,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                        opcode = op_CLGRJ
                        opcode2 = op_CLGR
                }
-               mask := branchMask(ctxt, p)
+               mask := c.branchMask(p)
                if int32(int16(v)) != v {
                        zRRE(opcode2, uint32(p.From.Reg), uint32(p.Reg), asm)
                        zRIL(_c, op_BRCL, mask, uint32(v-sizeRRE/2), asm)
@@ -3677,22 +3688,22 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                        opcode = op_CLGIJ
                        opcode2 = op_CLGFI
                }
-               mask := branchMask(ctxt, p)
+               mask := c.branchMask(p)
                if int32(int16(v)) != v {
-                       zRIL(_a, opcode2, uint32(p.From.Reg), uint32(regoff(ctxt, p.From3)), asm)
+                       zRIL(_a, opcode2, uint32(p.From.Reg), uint32(c.regoff(p.From3)), asm)
                        zRIL(_c, op_BRCL, mask, uint32(v-sizeRIL/2), asm)
                } else {
-                       zRIE(_c, opcode, uint32(p.From.Reg), mask, uint32(v), 0, 0, 0, uint32(regoff(ctxt, p.From3)), asm)
+                       zRIE(_c, opcode, uint32(p.From.Reg), mask, uint32(v), 0, 0, 0, uint32(c.regoff(p.From3)), asm)
                }
 
        case 93: // GOT lookup
-               v := vregoff(ctxt, &p.To)
+               v := c.vregoff(&p.To)
                if v != 0 {
-                       ctxt.Diag("invalid offset against GOT slot %v", p)
+                       c.ctxt.Diag("invalid offset against GOT slot %v", p)
                }
                zRIL(_b, op_LGRL, uint32(p.To.Reg), 0, asm)
-               rel := obj.Addrel(ctxt.Cursym)
-               rel.Off = int32(ctxt.Pc + 2)
+               rel := obj.Addrel(c.cursym)
+               rel.Off = int32(c.pc + 2)
                rel.Siz = 4
                rel.Sym = p.From.Sym
                rel.Type = obj.R_GOTPCREL
@@ -3703,8 +3714,8 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                zRXY(op_LG, uint32(p.To.Reg), REGTMP, 0, 0, asm)
                zRI(op_BRC, 0xF, (sizeRI+8)>>1, asm)
                *asm = append(*asm, 0, 0, 0, 0, 0, 0, 0, 0)
-               rel := obj.Addrel(ctxt.Cursym)
-               rel.Off = int32(ctxt.Pc + sizeRIL + sizeRXY + sizeRI)
+               rel := obj.Addrel(c.cursym)
+               rel.Off = int32(c.pc + sizeRIL + sizeRXY + sizeRI)
                rel.Siz = 8
                rel.Sym = p.From.Sym
                rel.Type = obj.R_TLS_LE
@@ -3723,8 +3734,8 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
 
                // R_390_TLS_IEENT
                zRIL(_b, op_LARL, REGTMP, 0, asm)
-               ieent := obj.Addrel(ctxt.Cursym)
-               ieent.Off = int32(ctxt.Pc + 2)
+               ieent := obj.Addrel(c.cursym)
+               ieent.Off = int32(c.pc + 2)
                ieent.Siz = 4
                ieent.Sym = p.From.Sym
                ieent.Type = obj.R_TLS_IE
@@ -3736,14 +3747,14 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                // not strictly required but might allow the linker to optimize
 
        case 96: // clear macro
-               length := vregoff(ctxt, &p.From)
-               offset := vregoff(ctxt, &p.To)
+               length := c.vregoff(&p.From)
+               offset := c.vregoff(&p.To)
                reg := p.To.Reg
                if reg == 0 {
                        reg = o.param
                }
                if length <= 0 {
-                       ctxt.Diag("cannot CLEAR %d bytes, must be greater than 0", length)
+                       c.ctxt.Diag("cannot CLEAR %d bytes, must be greater than 0", length)
                }
                for length > 0 {
                        if offset < 0 || offset >= DISP12 {
@@ -3783,7 +3794,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
        case 97: // store multiple
                rstart := p.From.Reg
                rend := p.Reg
-               offset := regoff(ctxt, &p.To)
+               offset := c.regoff(&p.To)
                reg := p.To.Reg
                if reg == 0 {
                        reg = o.param
@@ -3810,7 +3821,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
        case 98: // load multiple
                rstart := p.Reg
                rend := p.To.Reg
-               offset := regoff(ctxt, &p.From)
+               offset := c.regoff(&p.From)
                reg := p.From.Reg
                if reg == 0 {
                        reg = o.param
@@ -3836,11 +3847,11 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
 
        case 99: // interlocked load and op
                if p.To.Index != 0 {
-                       ctxt.Diag("cannot use indexed address")
+                       c.ctxt.Diag("cannot use indexed address")
                }
-               offset := regoff(ctxt, &p.To)
+               offset := c.regoff(&p.To)
                if offset < -DISP20/2 || offset >= DISP20/2 {
-                       ctxt.Diag("%v does not fit into 20-bit signed integer", offset)
+                       c.ctxt.Diag("%v does not fit into 20-bit signed integer", offset)
                }
                var opcode uint32
                switch p.As {
@@ -3870,49 +3881,49 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
        case 100: // VRX STORE
                op, m3, _ := vop(p.As)
                if p.From3 != nil {
-                       m3 = uint32(vregoff(ctxt, p.From3))
+                       m3 = uint32(c.vregoff(p.From3))
                }
                b2 := p.To.Reg
                if b2 == 0 {
                        b2 = o.param
                }
-               d2 := uint32(vregoff(ctxt, &p.To))
+               d2 := uint32(c.vregoff(&p.To))
                zVRX(op, uint32(p.From.Reg), uint32(p.To.Index), uint32(b2), d2, m3, asm)
 
        case 101: // VRX LOAD
                op, m3, _ := vop(p.As)
                if p.From3 != nil {
-                       m3 = uint32(vregoff(ctxt, p.From3))
+                       m3 = uint32(c.vregoff(p.From3))
                }
                b2 := p.From.Reg
                if b2 == 0 {
                        b2 = o.param
                }
-               d2 := uint32(vregoff(ctxt, &p.From))
+               d2 := uint32(c.vregoff(&p.From))
                zVRX(op, uint32(p.To.Reg), uint32(p.From.Index), uint32(b2), d2, m3, asm)
 
        case 102: // VRV SCATTER
                op, m3, _ := vop(p.As)
                if p.From3 != nil {
-                       m3 = uint32(vregoff(ctxt, p.From3))
+                       m3 = uint32(c.vregoff(p.From3))
                }
                b2 := p.To.Reg
                if b2 == 0 {
                        b2 = o.param
                }
-               d2 := uint32(vregoff(ctxt, &p.To))
+               d2 := uint32(c.vregoff(&p.To))
                zVRV(op, uint32(p.From.Reg), uint32(p.To.Index), uint32(b2), d2, m3, asm)
 
        case 103: // VRV GATHER
                op, m3, _ := vop(p.As)
                if p.From3 != nil {
-                       m3 = uint32(vregoff(ctxt, p.From3))
+                       m3 = uint32(c.vregoff(p.From3))
                }
                b2 := p.From.Reg
                if b2 == 0 {
                        b2 = o.param
                }
-               d2 := uint32(vregoff(ctxt, &p.From))
+               d2 := uint32(c.vregoff(&p.From))
                zVRV(op, uint32(p.To.Reg), uint32(p.From.Index), uint32(b2), d2, m3, asm)
 
        case 104: // VRS SHIFT/ROTATE and LOAD GR FROM VR ELEMENT
@@ -3921,12 +3932,12 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                if fr == 0 {
                        fr = p.To.Reg
                }
-               bits := uint32(vregoff(ctxt, &p.From))
+               bits := uint32(c.vregoff(&p.From))
                zVRS(op, uint32(p.To.Reg), uint32(fr), uint32(p.From.Reg), bits, m4, asm)
 
        case 105: // VRS STORE MULTIPLE
                op, _, _ := vop(p.As)
-               offset := uint32(vregoff(ctxt, &p.To))
+               offset := uint32(c.vregoff(&p.To))
                reg := p.To.Reg
                if reg == 0 {
                        reg = o.param
@@ -3935,7 +3946,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
 
        case 106: // VRS LOAD MULTIPLE
                op, _, _ := vop(p.As)
-               offset := uint32(vregoff(ctxt, &p.From))
+               offset := uint32(c.vregoff(&p.From))
                reg := p.From.Reg
                if reg == 0 {
                        reg = o.param
@@ -3944,7 +3955,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
 
        case 107: // VRS STORE WITH LENGTH
                op, _, _ := vop(p.As)
-               offset := uint32(vregoff(ctxt, &p.To))
+               offset := uint32(c.vregoff(&p.To))
                reg := p.To.Reg
                if reg == 0 {
                        reg = o.param
@@ -3953,7 +3964,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
 
        case 108: // VRS LOAD WITH LENGTH
                op, _, _ := vop(p.As)
-               offset := uint32(vregoff(ctxt, &p.From))
+               offset := uint32(c.vregoff(&p.From))
                reg := p.From.Reg
                if reg == 0 {
                        reg = o.param
@@ -3962,7 +3973,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
 
        case 109: // VRI-a
                op, m3, _ := vop(p.As)
-               i2 := uint32(vregoff(ctxt, &p.From))
+               i2 := uint32(c.vregoff(&p.From))
                switch p.As {
                case AVZERO:
                        i2 = 0
@@ -3970,30 +3981,30 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
                        i2 = 0xffff
                }
                if p.From3 != nil {
-                       m3 = uint32(vregoff(ctxt, p.From3))
+                       m3 = uint32(c.vregoff(p.From3))
                }
                zVRIa(op, uint32(p.To.Reg), i2, m3, asm)
 
        case 110:
                op, m4, _ := vop(p.As)
-               i2 := uint32(vregoff(ctxt, p.From3))
-               i3 := uint32(vregoff(ctxt, &p.From))
+               i2 := uint32(c.vregoff(p.From3))
+               i3 := uint32(c.vregoff(&p.From))
                zVRIb(op, uint32(p.To.Reg), i2, i3, m4, asm)
 
        case 111:
                op, m4, _ := vop(p.As)
-               i2 := uint32(vregoff(ctxt, &p.From))
+               i2 := uint32(c.vregoff(&p.From))
                zVRIc(op, uint32(p.To.Reg), uint32(p.Reg), i2, m4, asm)
 
        case 112:
                op, m5, _ := vop(p.As)
-               i4 := uint32(vregoff(ctxt, p.From3))
+               i4 := uint32(c.vregoff(p.From3))
                zVRId(op, uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), i4, m5, asm)
 
        case 113:
                op, m4, _ := vop(p.As)
                m5 := singleElementMask(p.As)
-               i3 := uint32(vregoff(ctxt, &p.From))
+               i3 := uint32(c.vregoff(&p.From))
                zVRIe(op, uint32(p.To.Reg), uint32(p.Reg), i3, m5, m4, asm)
 
        case 114: // VRR-a
@@ -4054,25 +4065,25 @@ func asmout(ctxt *obj.Link, p *obj.Prog, asm *[]byte) {
 
        case 123: // VPDI $m4, V2, V3, V1
                op, _, _ := vop(p.As)
-               m4 := regoff(ctxt, p.From3)
+               m4 := c.regoff(p.From3)
                zVRRc(op, uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), 0, 0, uint32(m4), asm)
        }
 }
 
-func vregoff(ctxt *obj.Link, a *obj.Addr) int64 {
-       ctxt.Instoffset = 0
+func (c *ctxtz) vregoff(a *obj.Addr) int64 {
+       c.instoffset = 0
        if a != nil {
-               aclass(ctxt, a)
+               c.aclass(a)
        }
-       return ctxt.Instoffset
+       return c.instoffset
 }
 
-func regoff(ctxt *obj.Link, a *obj.Addr) int32 {
-       return int32(vregoff(ctxt, a))
+func (c *ctxtz) regoff(a *obj.Addr) int32 {
+       return int32(c.vregoff(a))
 }
 
 // zopload returns the RXY op for the given load
-func zopload(ctxt *obj.Link, a obj.As) uint32 {
+func (c *ctxtz) zopload(a obj.As) uint32 {
        switch a {
        // fixed point load
        case AMOVD:
@@ -4105,12 +4116,12 @@ func zopload(ctxt *obj.Link, a obj.As) uint32 {
                return op_LRVH
        }
 
-       ctxt.Diag("unknown store opcode %v", a)
+       c.ctxt.Diag("unknown store opcode %v", a)
        return 0
 }
 
 // zopstore returns the RXY op for the given store
-func zopstore(ctxt *obj.Link, a obj.As) uint32 {
+func (c *ctxtz) zopstore(a obj.As) uint32 {
        switch a {
        // fixed point store
        case AMOVD:
@@ -4137,12 +4148,12 @@ func zopstore(ctxt *obj.Link, a obj.As) uint32 {
                return op_STRVH
        }
 
-       ctxt.Diag("unknown store opcode %v", a)
+       c.ctxt.Diag("unknown store opcode %v", a)
        return 0
 }
 
 // zoprre returns the RRE op for the given a
-func zoprre(ctxt *obj.Link, a obj.As) uint32 {
+func (c *ctxtz) zoprre(a obj.As) uint32 {
        switch a {
        case ACMP:
                return op_CGR
@@ -4155,24 +4166,24 @@ func zoprre(ctxt *obj.Link, a obj.As) uint32 {
        case ACEBR:
                return op_CEBR
        }
-       ctxt.Diag("unknown rre opcode %v", a)
+       c.ctxt.Diag("unknown rre opcode %v", a)
        return 0
 }
 
 // zoprr returns the RR op for the given a
-func zoprr(ctxt *obj.Link, a obj.As) uint32 {
+func (c *ctxtz) zoprr(a obj.As) uint32 {
        switch a {
        case ACMPW:
                return op_CR
        case ACMPWU:
                return op_CLR
        }
-       ctxt.Diag("unknown rr opcode %v", a)
+       c.ctxt.Diag("unknown rr opcode %v", a)
        return 0
 }
 
 // zopril returns the RIL op for the given a
-func zopril(ctxt *obj.Link, a obj.As) uint32 {
+func (c *ctxtz) zopril(a obj.As) uint32 {
        switch a {
        case ACMP:
                return op_CGFI
@@ -4183,7 +4194,7 @@ func zopril(ctxt *obj.Link, a obj.As) uint32 {
        case ACMPWU:
                return op_CLFI
        }
-       ctxt.Diag("unknown ril opcode %v", a)
+       c.ctxt.Diag("unknown ril opcode %v", a)
        return 0
 }
 
index b39d94e9d0dfae2687eed6138f33b3556498bc89..8b86dbb4045ab5d7d2cdb9a9de7af1f1e0efedb7 100644 (file)
@@ -39,13 +39,11 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
        p.From.Class = 0
        p.To.Class = 0
 
+       c := ctxtz{ctxt: ctxt, newprog: newprog}
+
        // Rewrite BR/BL to symbol as TYPE_BRANCH.
        switch p.As {
-       case ABR,
-               ABL,
-               obj.ARET,
-               obj.ADUFFZERO,
-               obj.ADUFFCOPY:
+       case ABR, ABL, obj.ARET, obj.ADUFFZERO, obj.ADUFFCOPY:
                if p.To.Sym != nil {
                        p.To.Type = obj.TYPE_BRANCH
                }
@@ -107,13 +105,13 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
                }
        }
 
-       if ctxt.Flag_dynlink {
-               rewriteToUseGot(ctxt, p, newprog)
+       if c.ctxt.Flag_dynlink {
+               c.rewriteToUseGot(p)
        }
 }
 
 // Rewrite p, if necessary, to access global data via the global offset table.
-func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
+func (c *ctxtz) rewriteToUseGot(p *obj.Prog) {
        // At the moment EXRL instructions are not emitted by the compiler and only reference local symbols in
        // assembly code.
        if p.As == AEXRL {
@@ -127,13 +125,13 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
                // MOVD $sym, Rx becomes MOVD sym@GOT, Rx
                // MOVD $sym+<off>, Rx becomes MOVD sym@GOT, Rx; ADD <off>, Rx
                if p.To.Type != obj.TYPE_REG || p.As != AMOVD {
-                       ctxt.Diag("do not know how to handle LEA-type insn to non-register in %v with -dynlink", p)
+                       c.ctxt.Diag("do not know how to handle LEA-type insn to non-register in %v with -dynlink", p)
                }
                p.From.Type = obj.TYPE_MEM
                p.From.Name = obj.NAME_GOTREF
                q := p
                if p.From.Offset != 0 {
-                       q = obj.Appendp(p, newprog)
+                       q = obj.Appendp(p, c.newprog)
                        q.As = AADD
                        q.From.Type = obj.TYPE_CONST
                        q.From.Offset = p.From.Offset
@@ -142,7 +140,7 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
                }
        }
        if p.From3 != nil && p.From3.Name == obj.NAME_EXTERN {
-               ctxt.Diag("don't know how to handle %v with -dynlink", p)
+               c.ctxt.Diag("don't know how to handle %v with -dynlink", p)
        }
        var source *obj.Addr
        // MOVD sym, Ry becomes MOVD sym@GOT, REGTMP; MOVD (REGTMP), Ry
@@ -150,7 +148,7 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
        // An addition may be inserted between the two MOVs if there is an offset.
        if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
                if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
-                       ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
+                       c.ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
                }
                source = &p.From
        } else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
@@ -165,10 +163,10 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
                return
        }
        if source.Type != obj.TYPE_MEM {
-               ctxt.Diag("don't know how to handle %v with -dynlink", p)
+               c.ctxt.Diag("don't know how to handle %v with -dynlink", p)
        }
-       p1 := obj.Appendp(p, newprog)
-       p2 := obj.Appendp(p1, newprog)
+       p1 := obj.Appendp(p, c.newprog)
+       p2 := obj.Appendp(p1, c.newprog)
 
        p1.As = AMOVD
        p1.From.Type = obj.TYPE_MEM
@@ -196,13 +194,13 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
 
 func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
        // TODO(minux): add morestack short-cuts with small fixed frame-size.
-       ctxt.Cursym = cursym
-
        if cursym.Text == nil || cursym.Text.Link == nil {
                return
        }
 
-       p := cursym.Text
+       c := ctxtz{ctxt: ctxt, cursym: cursym, newprog: newprog}
+
+       p := c.cursym.Text
        textstksiz := p.To.Offset
        if textstksiz == -8 {
                // Compatibility hack.
@@ -210,16 +208,16 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                textstksiz = 0
        }
        if textstksiz%8 != 0 {
-               ctxt.Diag("frame size %d not a multiple of 8", textstksiz)
+               c.ctxt.Diag("frame size %d not a multiple of 8", textstksiz)
        }
        if p.From3.Offset&obj.NOFRAME != 0 {
                if textstksiz != 0 {
-                       ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", textstksiz)
+                       c.ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", textstksiz)
                }
        }
 
-       cursym.Args = p.To.Val.(int32)
-       cursym.Locals = int32(textstksiz)
+       c.cursym.Args = p.To.Val.(int32)
+       c.cursym.Locals = int32(textstksiz)
 
        /*
         * find leaf subroutines
@@ -228,7 +226,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
         */
 
        var q *obj.Prog
-       for p := cursym.Text; p != nil; p = p.Link {
+       for p := c.cursym.Text; p != nil; p = p.Link {
                switch p.As {
                case obj.ATEXT:
                        q = p
@@ -236,7 +234,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
 
                case ABL, ABCL:
                        q = p
-                       cursym.Text.Mark &^= LEAF
+                       c.cursym.Text.Mark &^= LEAF
                        fallthrough
 
                case ABC,
@@ -287,7 +285,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
        var pPre *obj.Prog
        var pPreempt *obj.Prog
        wasSplit := false
-       for p := cursym.Text; p != nil; p = p.Link {
+       for p := c.cursym.Text; p != nil; p = p.Link {
                pLast = p
                switch p.As {
                case obj.ATEXT:
@@ -301,7 +299,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                        if p.From3.Offset&obj.NOFRAME == 0 {
                                // If there is a stack frame at all, it includes
                                // space to save the LR.
-                               autosize += int32(ctxt.FixedFrameSize())
+                               autosize += int32(c.ctxt.FixedFrameSize())
                        }
 
                        if p.Mark&LEAF != 0 && autosize < obj.StackSmall {
@@ -315,7 +313,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                        q := p
 
                        if p.From3.Offset&obj.NOSPLIT == 0 {
-                               p, pPreempt = stacksplitPre(ctxt, p, newprog, autosize) // emit pre part of split check
+                               p, pPreempt = c.stacksplitPre(p, autosize) // emit pre part of split check
                                pPre = p
                                wasSplit = true //need post part of split
                        }
@@ -326,7 +324,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                                // Store link register before decrementing SP, so if a signal comes
                                // during the execution of the function prologue, the traceback
                                // code will not see a half-updated stack frame.
-                               q = obj.Appendp(p, newprog)
+                               q = obj.Appendp(p, c.newprog)
                                q.As = AMOVD
                                q.From.Type = obj.TYPE_REG
                                q.From.Reg = REG_LR
@@ -334,7 +332,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                                q.To.Reg = REGSP
                                q.To.Offset = int64(-autosize)
 
-                               q = obj.Appendp(q, newprog)
+                               q = obj.Appendp(q, c.newprog)
                                q.As = AMOVD
                                q.From.Type = obj.TYPE_ADDR
                                q.From.Offset = int64(-autosize)
@@ -342,19 +340,19 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                                q.To.Type = obj.TYPE_REG
                                q.To.Reg = REGSP
                                q.Spadj = autosize
-                       } else if cursym.Text.Mark&LEAF == 0 {
+                       } else if c.cursym.Text.Mark&LEAF == 0 {
                                // A very few functions that do not return to their caller
                                // (e.g. gogo) are not identified as leaves but still have
                                // no frame.
-                               cursym.Text.Mark |= LEAF
+                               c.cursym.Text.Mark |= LEAF
                        }
 
-                       if cursym.Text.Mark&LEAF != 0 {
-                               cursym.Set(obj.AttrLeaf, true)
+                       if c.cursym.Text.Mark&LEAF != 0 {
+                               c.cursym.Set(obj.AttrLeaf, true)
                                break
                        }
 
-                       if cursym.Text.From3.Offset&obj.WRAPPER != 0 {
+                       if c.cursym.Text.From3.Offset&obj.WRAPPER != 0 {
                                // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
                                //
                                //      MOVD g_panic(g), R3
@@ -372,28 +370,28 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                                // The NOP is needed to give the jumps somewhere to land.
                                // It is a liblink NOP, not a s390x NOP: it encodes to 0 instruction bytes.
 
-                               q = obj.Appendp(q, newprog)
+                               q = obj.Appendp(q, c.newprog)
 
                                q.As = AMOVD
                                q.From.Type = obj.TYPE_MEM
                                q.From.Reg = REGG
-                               q.From.Offset = 4 * int64(ctxt.Arch.PtrSize) // G.panic
+                               q.From.Offset = 4 * int64(c.ctxt.Arch.PtrSize) // G.panic
                                q.To.Type = obj.TYPE_REG
                                q.To.Reg = REG_R3
 
-                               q = obj.Appendp(q, newprog)
+                               q = obj.Appendp(q, c.newprog)
                                q.As = ACMP
                                q.From.Type = obj.TYPE_REG
                                q.From.Reg = REG_R3
                                q.To.Type = obj.TYPE_CONST
                                q.To.Offset = 0
 
-                               q = obj.Appendp(q, newprog)
+                               q = obj.Appendp(q, c.newprog)
                                q.As = ABEQ
                                q.To.Type = obj.TYPE_BRANCH
                                p1 := q
 
-                               q = obj.Appendp(q, newprog)
+                               q = obj.Appendp(q, c.newprog)
                                q.As = AMOVD
                                q.From.Type = obj.TYPE_MEM
                                q.From.Reg = REG_R3
@@ -401,35 +399,35 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                                q.To.Type = obj.TYPE_REG
                                q.To.Reg = REG_R4
 
-                               q = obj.Appendp(q, newprog)
+                               q = obj.Appendp(q, c.newprog)
                                q.As = AADD
                                q.From.Type = obj.TYPE_CONST
-                               q.From.Offset = int64(autosize) + ctxt.FixedFrameSize()
+                               q.From.Offset = int64(autosize) + c.ctxt.FixedFrameSize()
                                q.Reg = REGSP
                                q.To.Type = obj.TYPE_REG
                                q.To.Reg = REG_R5
 
-                               q = obj.Appendp(q, newprog)
+                               q = obj.Appendp(q, c.newprog)
                                q.As = ACMP
                                q.From.Type = obj.TYPE_REG
                                q.From.Reg = REG_R4
                                q.To.Type = obj.TYPE_REG
                                q.To.Reg = REG_R5
 
-                               q = obj.Appendp(q, newprog)
+                               q = obj.Appendp(q, c.newprog)
                                q.As = ABNE
                                q.To.Type = obj.TYPE_BRANCH
                                p2 := q
 
-                               q = obj.Appendp(q, newprog)
+                               q = obj.Appendp(q, c.newprog)
                                q.As = AADD
                                q.From.Type = obj.TYPE_CONST
-                               q.From.Offset = ctxt.FixedFrameSize()
+                               q.From.Offset = c.ctxt.FixedFrameSize()
                                q.Reg = REGSP
                                q.To.Type = obj.TYPE_REG
                                q.To.Reg = REG_R6
 
-                               q = obj.Appendp(q, newprog)
+                               q = obj.Appendp(q, c.newprog)
                                q.As = AMOVD
                                q.From.Type = obj.TYPE_REG
                                q.From.Reg = REG_R6
@@ -437,7 +435,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                                q.To.Reg = REG_R3
                                q.To.Offset = 0 // Panic.argp
 
-                               q = obj.Appendp(q, newprog)
+                               q = obj.Appendp(q, c.newprog)
 
                                q.As = obj.ANOP
                                p1.Pcond = q
@@ -447,7 +445,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                case obj.ARET:
                        retTarget := p.To.Sym
 
-                       if cursym.Text.Mark&LEAF != 0 {
+                       if c.cursym.Text.Mark&LEAF != 0 {
                                if autosize == 0 {
                                        p.As = ABR
                                        p.From = obj.Addr{}
@@ -469,7 +467,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                                p.To.Reg = REGSP
                                p.Spadj = -autosize
 
-                               q = obj.Appendp(p, newprog)
+                               q = obj.Appendp(p, c.newprog)
                                q.As = ABR
                                q.From = obj.Addr{}
                                q.To.Type = obj.TYPE_REG
@@ -489,7 +487,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                        q = p
 
                        if autosize != 0 {
-                               q = obj.Appendp(q, newprog)
+                               q = obj.Appendp(q, c.newprog)
                                q.As = AADD
                                q.From.Type = obj.TYPE_CONST
                                q.From.Offset = int64(autosize)
@@ -498,7 +496,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                                q.Spadj = -autosize
                        }
 
-                       q = obj.Appendp(q, newprog)
+                       q = obj.Appendp(q, c.newprog)
                        q.As = ABR
                        q.From = obj.Addr{}
                        if retTarget == nil {
@@ -518,22 +516,22 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                }
        }
        if wasSplit {
-               stacksplitPost(ctxt, pLast, pPre, pPreempt, newprog, autosize) // emit post part of split check
+               c.stacksplitPost(pLast, pPre, pPreempt, autosize) // emit post part of split check
        }
 }
 
-func stacksplitPre(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize int32) (*obj.Prog, *obj.Prog) {
+func (c *ctxtz) stacksplitPre(p *obj.Prog, framesize int32) (*obj.Prog, *obj.Prog) {
        var q *obj.Prog
 
        // MOVD g_stackguard(g), R3
-       p = obj.Appendp(p, newprog)
+       p = obj.Appendp(p, c.newprog)
 
        p.As = AMOVD
        p.From.Type = obj.TYPE_MEM
        p.From.Reg = REGG
-       p.From.Offset = 2 * int64(ctxt.Arch.PtrSize) // G.stackguard0
-       if ctxt.Cursym.CFunc() {
-               p.From.Offset = 3 * int64(ctxt.Arch.PtrSize) // G.stackguard1
+       p.From.Offset = 2 * int64(c.ctxt.Arch.PtrSize) // G.stackguard0
+       if c.cursym.CFunc() {
+               p.From.Offset = 3 * int64(c.ctxt.Arch.PtrSize) // G.stackguard1
        }
        p.To.Type = obj.TYPE_REG
        p.To.Reg = REG_R3
@@ -548,7 +546,7 @@ func stacksplitPre(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize
 
                // q1: BLT      done
 
-               p = obj.Appendp(p, newprog)
+               p = obj.Appendp(p, c.newprog)
                //q1 = p
                p.From.Type = obj.TYPE_REG
                p.From.Reg = REG_R3
@@ -571,7 +569,7 @@ func stacksplitPre(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize
                // large stack: SP-framesize < stackguard-StackSmall
                //      ADD $-(framesize-StackSmall), SP, R4
                //      CMP stackguard, R4
-               p = obj.Appendp(p, newprog)
+               p = obj.Appendp(p, c.newprog)
 
                p.As = AADD
                p.From.Type = obj.TYPE_CONST
@@ -580,7 +578,7 @@ func stacksplitPre(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize
                p.To.Type = obj.TYPE_REG
                p.To.Reg = REG_R4
 
-               p = obj.Appendp(p, newprog)
+               p = obj.Appendp(p, c.newprog)
                p.From.Type = obj.TYPE_REG
                p.From.Reg = REG_R3
                p.Reg = REG_R4
@@ -603,7 +601,7 @@ func stacksplitPre(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize
                //      SUB     R3, R4
                //      MOVD    $(framesize+(StackGuard-StackSmall)), TEMP
                //      CMPUBGE TEMP, R4
-               p = obj.Appendp(p, newprog)
+               p = obj.Appendp(p, c.newprog)
 
                p.As = ACMP
                p.From.Type = obj.TYPE_REG
@@ -611,12 +609,12 @@ func stacksplitPre(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize
                p.To.Type = obj.TYPE_CONST
                p.To.Offset = obj.StackPreempt
 
-               p = obj.Appendp(p, newprog)
+               p = obj.Appendp(p, c.newprog)
                q = p
                p.As = ABEQ
                p.To.Type = obj.TYPE_BRANCH
 
-               p = obj.Appendp(p, newprog)
+               p = obj.Appendp(p, c.newprog)
                p.As = AADD
                p.From.Type = obj.TYPE_CONST
                p.From.Offset = obj.StackGuard
@@ -624,21 +622,21 @@ func stacksplitPre(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize
                p.To.Type = obj.TYPE_REG
                p.To.Reg = REG_R4
 
-               p = obj.Appendp(p, newprog)
+               p = obj.Appendp(p, c.newprog)
                p.As = ASUB
                p.From.Type = obj.TYPE_REG
                p.From.Reg = REG_R3
                p.To.Type = obj.TYPE_REG
                p.To.Reg = REG_R4
 
-               p = obj.Appendp(p, newprog)
+               p = obj.Appendp(p, c.newprog)
                p.As = AMOVD
                p.From.Type = obj.TYPE_CONST
                p.From.Offset = int64(framesize) + obj.StackGuard - obj.StackSmall
                p.To.Type = obj.TYPE_REG
                p.To.Reg = REGTMP
 
-               p = obj.Appendp(p, newprog)
+               p = obj.Appendp(p, c.newprog)
                p.From.Type = obj.TYPE_REG
                p.From.Reg = REGTMP
                p.Reg = REG_R4
@@ -649,16 +647,16 @@ func stacksplitPre(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize
        return p, q
 }
 
-func stacksplitPost(ctxt *obj.Link, p *obj.Prog, pPre *obj.Prog, pPreempt *obj.Prog, newprog obj.ProgAlloc, framesize int32) *obj.Prog {
+func (c *ctxtz) stacksplitPost(p *obj.Prog, pPre *obj.Prog, pPreempt *obj.Prog, framesize int32) *obj.Prog {
        // Now we are at the end of the function, but logically
        // we are still in function prologue. We need to fix the
        // SP data and PCDATA.
-       spfix := obj.Appendp(p, newprog)
+       spfix := obj.Appendp(p, c.newprog)
        spfix.As = obj.ANOP
        spfix.Spadj = -framesize
 
-       pcdata := obj.Appendp(spfix, newprog)
-       pcdata.Pos = ctxt.Cursym.Text.Pos
+       pcdata := obj.Appendp(spfix, c.newprog)
+       pcdata.Pos = c.cursym.Text.Pos
        pcdata.As = obj.APCDATA
        pcdata.From.Type = obj.TYPE_CONST
        pcdata.From.Offset = obj.PCDATA_StackMapIndex
@@ -666,7 +664,7 @@ func stacksplitPost(ctxt *obj.Link, p *obj.Prog, pPre *obj.Prog, pPreempt *obj.P
        pcdata.To.Offset = -1 // pcdata starts at -1 at function entry
 
        // MOVD LR, R5
-       p = obj.Appendp(pcdata, newprog)
+       p = obj.Appendp(pcdata, c.newprog)
        pPre.Pcond = p
        p.As = AMOVD
        p.From.Type = obj.TYPE_REG
@@ -678,24 +676,24 @@ func stacksplitPost(ctxt *obj.Link, p *obj.Prog, pPre *obj.Prog, pPreempt *obj.P
        }
 
        // BL   runtime.morestack(SB)
-       p = obj.Appendp(p, newprog)
+       p = obj.Appendp(p, c.newprog)
 
        p.As = ABL
        p.To.Type = obj.TYPE_BRANCH
-       if ctxt.Cursym.CFunc() {
-               p.To.Sym = ctxt.Lookup("runtime.morestackc", 0)
-       } else if ctxt.Cursym.Text.From3.Offset&obj.NEEDCTXT == 0 {
-               p.To.Sym = ctxt.Lookup("runtime.morestack_noctxt", 0)
+       if c.cursym.CFunc() {
+               p.To.Sym = c.ctxt.Lookup("runtime.morestackc", 0)
+       } else if c.cursym.Text.From3.Offset&obj.NEEDCTXT == 0 {
+               p.To.Sym = c.ctxt.Lookup("runtime.morestack_noctxt", 0)
        } else {
-               p.To.Sym = ctxt.Lookup("runtime.morestack", 0)
+               p.To.Sym = c.ctxt.Lookup("runtime.morestack", 0)
        }
 
        // BR   start
-       p = obj.Appendp(p, newprog)
+       p = obj.Appendp(p, c.newprog)
 
        p.As = ABR
        p.To.Type = obj.TYPE_BRANCH
-       p.Pcond = ctxt.Cursym.Text.Link
+       p.Pcond = c.cursym.Text.Link
        return p
 }