]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/gc: refactor ACALL Prog creation
authorMatthew Dempsky <mdempsky@google.com>
Sat, 11 Mar 2017 02:34:41 +0000 (18:34 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Mon, 13 Mar 2017 21:04:16 +0000 (21:04 +0000)
This abstracts creation of ACALL Progs into package gc. The main
benefit of this today is we can refactor away a lot of common
boilerplate code.

Later, once liveness analysis happens on the SSA graph, this will also
provide an easy insertion point for emitting the PCDATA Progs
immediately before call instructions.

Passes toolstash-check -all.

Change-Id: Ia15108ace97201cd84314f1ca916dfeb4f09d61c
Reviewed-on: https://go-review.googlesource.com/38081
Reviewed-by: Keith Randall <khr@golang.org>
19 files changed:
src/cmd/compile/internal/amd64/galign.go
src/cmd/compile/internal/amd64/ssa.go
src/cmd/compile/internal/arm/galign.go
src/cmd/compile/internal/arm/ssa.go
src/cmd/compile/internal/arm64/galign.go
src/cmd/compile/internal/arm64/ssa.go
src/cmd/compile/internal/gc/go.go
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/mips/galign.go
src/cmd/compile/internal/mips/ssa.go
src/cmd/compile/internal/mips64/galign.go
src/cmd/compile/internal/mips64/ssa.go
src/cmd/compile/internal/ppc64/galign.go
src/cmd/compile/internal/ppc64/ggen.go
src/cmd/compile/internal/ppc64/ssa.go
src/cmd/compile/internal/s390x/galign.go
src/cmd/compile/internal/s390x/ssa.go
src/cmd/compile/internal/x86/galign.go
src/cmd/compile/internal/x86/ssa.go

index bb3830bca548ce2c15645d9971bbed5fe8862193..8ced62fe0fd1679b935db0daaa775c80dd6ea164 100644 (file)
@@ -22,6 +22,7 @@ func Init() {
        gc.Thearch.MAXWIDTH = 1 << 50
 
        gc.Thearch.Defframe = defframe
+       gc.Thearch.Ginsnop = ginsnop
        gc.Thearch.Proginfo = proginfo
 
        gc.Thearch.SSAMarkMoves = ssaMarkMoves
index 68de874d32e6a9817b84b5b45db2e80508e5f76c..c0de90b7a70e0011ce0878c3a7d343b36d07d0ee 100644 (file)
@@ -743,39 +743,8 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
                        q.To.Type = obj.TYPE_REG
                        q.To.Reg = r
                }
-       case ssa.OpAMD64CALLstatic:
-               if v.Aux.(*obj.LSym) == gc.Deferreturn {
-                       // Deferred calls will appear to be returning to
-                       // the CALL deferreturn(SB) that we are about to emit.
-                       // However, the stack trace code will show the line
-                       // of the instruction byte before the return PC.
-                       // To avoid that being an unrelated instruction,
-                       // insert an actual hardware NOP that will have the right line number.
-                       // This is different from obj.ANOP, which is a virtual no-op
-                       // that doesn't make it into the instruction stream.
-                       ginsnop()
-               }
-               p := gc.Prog(obj.ACALL)
-               p.To.Type = obj.TYPE_MEM
-               p.To.Name = obj.NAME_EXTERN
-               p.To.Sym = v.Aux.(*obj.LSym)
-               if gc.Maxarg < v.AuxInt {
-                       gc.Maxarg = v.AuxInt
-               }
-       case ssa.OpAMD64CALLclosure:
-               p := gc.Prog(obj.ACALL)
-               p.To.Type = obj.TYPE_REG
-               p.To.Reg = v.Args[0].Reg()
-               if gc.Maxarg < v.AuxInt {
-                       gc.Maxarg = v.AuxInt
-               }
-       case ssa.OpAMD64CALLinter:
-               p := gc.Prog(obj.ACALL)
-               p.To.Type = obj.TYPE_REG
-               p.To.Reg = v.Args[0].Reg()
-               if gc.Maxarg < v.AuxInt {
-                       gc.Maxarg = v.AuxInt
-               }
+       case ssa.OpAMD64CALLstatic, ssa.OpAMD64CALLclosure, ssa.OpAMD64CALLinter:
+               s.Call(v)
        case ssa.OpAMD64NEGQ, ssa.OpAMD64NEGL,
                ssa.OpAMD64BSWAPQ, ssa.OpAMD64BSWAPL,
                ssa.OpAMD64NOTQ, ssa.OpAMD64NOTL:
index 308b016026df5b15e419d73768c5ed2c4bf32edf..5d9555a246f36e67d02cf79d2fcbcb6642e5577f 100644 (file)
@@ -16,6 +16,7 @@ func Init() {
        gc.Thearch.MAXWIDTH = (1 << 32) - 1
 
        gc.Thearch.Defframe = defframe
+       gc.Thearch.Ginsnop = ginsnop
        gc.Thearch.Proginfo = proginfo
 
        gc.Thearch.SSAMarkMoves = func(s *gc.SSAGenState, b *ssa.Block) {}
index 5160a32ab817d904d0303966fc9a50f81a646433..932c35fc3cd442ad2af836b84a713fd64ed76ffb 100644 (file)
@@ -625,41 +625,8 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
                p.From.Offset = v.AuxInt
                p.To.Type = obj.TYPE_REG
                p.To.Reg = v.Reg()
-       case ssa.OpARMCALLstatic:
-               if v.Aux.(*obj.LSym) == gc.Deferreturn {
-                       // Deferred calls will appear to be returning to
-                       // the CALL deferreturn(SB) that we are about to emit.
-                       // However, the stack trace code will show the line
-                       // of the instruction byte before the return PC.
-                       // To avoid that being an unrelated instruction,
-                       // insert an actual hardware NOP that will have the right line number.
-                       // This is different from obj.ANOP, which is a virtual no-op
-                       // that doesn't make it into the instruction stream.
-                       ginsnop()
-               }
-               p := gc.Prog(obj.ACALL)
-               p.To.Type = obj.TYPE_MEM
-               p.To.Name = obj.NAME_EXTERN
-               p.To.Sym = v.Aux.(*obj.LSym)
-               if gc.Maxarg < v.AuxInt {
-                       gc.Maxarg = v.AuxInt
-               }
-       case ssa.OpARMCALLclosure:
-               p := gc.Prog(obj.ACALL)
-               p.To.Type = obj.TYPE_MEM
-               p.To.Offset = 0
-               p.To.Reg = v.Args[0].Reg()
-               if gc.Maxarg < v.AuxInt {
-                       gc.Maxarg = v.AuxInt
-               }
-       case ssa.OpARMCALLinter:
-               p := gc.Prog(obj.ACALL)
-               p.To.Type = obj.TYPE_MEM
-               p.To.Offset = 0
-               p.To.Reg = v.Args[0].Reg()
-               if gc.Maxarg < v.AuxInt {
-                       gc.Maxarg = v.AuxInt
-               }
+       case ssa.OpARMCALLstatic, ssa.OpARMCALLclosure, ssa.OpARMCALLinter:
+               s.Call(v)
        case ssa.OpARMDUFFZERO:
                p := gc.Prog(obj.ADUFFZERO)
                p.To.Type = obj.TYPE_MEM
index 20a67e398d6924f4ed9ad7e13504116297aec477..6a8953af362ad90503a2aa2a95d529f4eb38fb3c 100644 (file)
@@ -16,6 +16,7 @@ func Init() {
        gc.Thearch.MAXWIDTH = 1 << 50
 
        gc.Thearch.Defframe = defframe
+       gc.Thearch.Ginsnop = ginsnop
        gc.Thearch.Proginfo = proginfo
 
        gc.Thearch.SSAMarkMoves = func(s *gc.SSAGenState, b *ssa.Block) {}
index 8954bebb100813f0a5032a4bf8fc7c6fc7bb391c..1b5c913df10a572f8ee8186df6474b8951add97c 100644 (file)
@@ -622,41 +622,8 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
                p4 := gc.Prog(arm64.ABLE)
                p4.To.Type = obj.TYPE_BRANCH
                gc.Patch(p4, p)
-       case ssa.OpARM64CALLstatic:
-               if v.Aux.(*obj.LSym) == gc.Deferreturn {
-                       // Deferred calls will appear to be returning to
-                       // the CALL deferreturn(SB) that we are about to emit.
-                       // However, the stack trace code will show the line
-                       // of the instruction byte before the return PC.
-                       // To avoid that being an unrelated instruction,
-                       // insert an actual hardware NOP that will have the right line number.
-                       // This is different from obj.ANOP, which is a virtual no-op
-                       // that doesn't make it into the instruction stream.
-                       ginsnop()
-               }
-               p := gc.Prog(obj.ACALL)
-               p.To.Type = obj.TYPE_MEM
-               p.To.Name = obj.NAME_EXTERN
-               p.To.Sym = v.Aux.(*obj.LSym)
-               if gc.Maxarg < v.AuxInt {
-                       gc.Maxarg = v.AuxInt
-               }
-       case ssa.OpARM64CALLclosure:
-               p := gc.Prog(obj.ACALL)
-               p.To.Type = obj.TYPE_MEM
-               p.To.Offset = 0
-               p.To.Reg = v.Args[0].Reg()
-               if gc.Maxarg < v.AuxInt {
-                       gc.Maxarg = v.AuxInt
-               }
-       case ssa.OpARM64CALLinter:
-               p := gc.Prog(obj.ACALL)
-               p.To.Type = obj.TYPE_MEM
-               p.To.Offset = 0
-               p.To.Reg = v.Args[0].Reg()
-               if gc.Maxarg < v.AuxInt {
-                       gc.Maxarg = v.AuxInt
-               }
+       case ssa.OpARM64CALLstatic, ssa.OpARM64CALLclosure, ssa.OpARM64CALLinter:
+               s.Call(v)
        case ssa.OpARM64LoweredNilCheck:
                // Issue a load which will fault if arg is nil.
                p := gc.Prog(arm64.AMOVB)
index 5b12aad6847a8380f95520171ce86e1a37b93ae6..95c7dabc454b29bd55034fd71cc3a7403e8073cc 100644 (file)
@@ -365,10 +365,11 @@ type Arch struct {
 
        REGSP    int
        MAXWIDTH int64
+       Use387   bool // should 386 backend use 387 FP instructions instead of sse2.
 
        Defframe func(*obj.Prog)
+       Ginsnop  func()
        Proginfo func(*obj.Prog) ProgInfo
-       Use387   bool // should 8g use 387 FP instructions instead of sse2.
 
        // SSAMarkMoves marks any MOVXconst ops that need to avoid clobbering flags.
        SSAMarkMoves func(*SSAGenState, *ssa.Block)
index 4fc5f320677a7bace7bca8b8f3dc92ab423cb5b2..450be95e06650ce0baa28d371a75bce3a52ba066 100644 (file)
@@ -4756,6 +4756,42 @@ func (s *SSAGenState) AddrScratch(a *obj.Addr) {
        a.Offset = s.ScratchFpMem.Xoffset
 }
 
+func (s *SSAGenState) Call(v *ssa.Value) *obj.Prog {
+       if sym, _ := v.Aux.(*obj.LSym); sym == Deferreturn {
+               // Deferred calls will appear to be returning to
+               // the CALL deferreturn(SB) that we are about to emit.
+               // However, the stack trace code will show the line
+               // of the instruction byte before the return PC.
+               // To avoid that being an unrelated instruction,
+               // insert an actual hardware NOP that will have the right line number.
+               // This is different from obj.ANOP, which is a virtual no-op
+               // that doesn't make it into the instruction stream.
+               Thearch.Ginsnop()
+       }
+
+       p := Prog(obj.ACALL)
+       if sym, ok := v.Aux.(*obj.LSym); ok {
+               p.To.Type = obj.TYPE_MEM
+               p.To.Name = obj.NAME_EXTERN
+               p.To.Sym = sym
+       } else {
+               // TODO(mdempsky): Can these differences be eliminated?
+               switch Thearch.LinkArch.Family {
+               case sys.AMD64, sys.I386, sys.PPC64, sys.S390X:
+                       p.To.Type = obj.TYPE_REG
+               case sys.ARM, sys.ARM64, sys.MIPS, sys.MIPS64:
+                       p.To.Type = obj.TYPE_MEM
+               default:
+                       Fatalf("unknown indirect call family")
+               }
+               p.To.Reg = v.Args[0].Reg()
+       }
+       if Maxarg < v.AuxInt {
+               Maxarg = v.AuxInt
+       }
+       return p
+}
+
 // fieldIdx finds the index of the field referred to by the ODOT node n.
 func fieldIdx(n *Node) int {
        t := n.Left.Type
index 39f5d2bf641516d92cb81a26cd77cb6af70680f1..9c7791740ae5ca23b707efe65c17413a0fc699bc 100644 (file)
@@ -19,6 +19,7 @@ func Init() {
        gc.Thearch.REGSP = mips.REGSP
        gc.Thearch.MAXWIDTH = (1 << 31) - 1
        gc.Thearch.Defframe = defframe
+       gc.Thearch.Ginsnop = ginsnop
        gc.Thearch.Proginfo = proginfo
        gc.Thearch.SSAMarkMoves = func(s *gc.SSAGenState, b *ssa.Block) {}
        gc.Thearch.SSAGenValue = ssaGenValue
index 0d5a2a2bc8d5f5507a1c94e757e91335511c10ee..8ef39b5f6033c7f80cf57bec8b8db23572900b5c 100644 (file)
@@ -477,41 +477,8 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
                p6.Reg = mips.REG_R1
                p6.To.Type = obj.TYPE_BRANCH
                gc.Patch(p6, p2)
-       case ssa.OpMIPSCALLstatic:
-               if v.Aux.(*obj.LSym) == gc.Deferreturn {
-                       // Deferred calls will appear to be returning to
-                       // the CALL deferreturn(SB) that we are about to emit.
-                       // However, the stack trace code will show the line
-                       // of the instruction byte before the return PC.
-                       // To avoid that being an unrelated instruction,
-                       // insert an actual hardware NOP that will have the right line number.
-                       // This is different from obj.ANOP, which is a virtual no-op
-                       // that doesn't make it into the instruction stream.
-                       ginsnop()
-               }
-               p := gc.Prog(obj.ACALL)
-               p.To.Type = obj.TYPE_MEM
-               p.To.Name = obj.NAME_EXTERN
-               p.To.Sym = v.Aux.(*obj.LSym)
-               if gc.Maxarg < v.AuxInt {
-                       gc.Maxarg = v.AuxInt
-               }
-       case ssa.OpMIPSCALLclosure:
-               p := gc.Prog(obj.ACALL)
-               p.To.Type = obj.TYPE_MEM
-               p.To.Offset = 0
-               p.To.Reg = v.Args[0].Reg()
-               if gc.Maxarg < v.AuxInt {
-                       gc.Maxarg = v.AuxInt
-               }
-       case ssa.OpMIPSCALLinter:
-               p := gc.Prog(obj.ACALL)
-               p.To.Type = obj.TYPE_MEM
-               p.To.Offset = 0
-               p.To.Reg = v.Args[0].Reg()
-               if gc.Maxarg < v.AuxInt {
-                       gc.Maxarg = v.AuxInt
-               }
+       case ssa.OpMIPSCALLstatic, ssa.OpMIPSCALLclosure, ssa.OpMIPSCALLinter:
+               s.Call(v)
        case ssa.OpMIPSLoweredAtomicLoad:
                gc.Prog(mips.ASYNC)
 
index 4a36a4ce5b44fac87b335a5b750af3f0241fc309..6392a38793e901ef510521be55fa9ec75f4b0d90 100644 (file)
@@ -20,6 +20,7 @@ func Init() {
        gc.Thearch.MAXWIDTH = 1 << 50
 
        gc.Thearch.Defframe = defframe
+       gc.Thearch.Ginsnop = ginsnop
        gc.Thearch.Proginfo = proginfo
 
        gc.Thearch.SSAMarkMoves = func(s *gc.SSAGenState, b *ssa.Block) {}
index cc97f6865f540eacbb738579055729c008e52d3b..42f16be85c46422fbefcf5544ed10a998b58d53b 100644 (file)
@@ -480,41 +480,8 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
                p6.Reg = mips.REG_R1
                p6.To.Type = obj.TYPE_BRANCH
                gc.Patch(p6, p2)
-       case ssa.OpMIPS64CALLstatic:
-               if v.Aux.(*obj.LSym) == gc.Deferreturn {
-                       // Deferred calls will appear to be returning to
-                       // the CALL deferreturn(SB) that we are about to emit.
-                       // However, the stack trace code will show the line
-                       // of the instruction byte before the return PC.
-                       // To avoid that being an unrelated instruction,
-                       // insert an actual hardware NOP that will have the right line number.
-                       // This is different from obj.ANOP, which is a virtual no-op
-                       // that doesn't make it into the instruction stream.
-                       ginsnop()
-               }
-               p := gc.Prog(obj.ACALL)
-               p.To.Type = obj.TYPE_MEM
-               p.To.Name = obj.NAME_EXTERN
-               p.To.Sym = v.Aux.(*obj.LSym)
-               if gc.Maxarg < v.AuxInt {
-                       gc.Maxarg = v.AuxInt
-               }
-       case ssa.OpMIPS64CALLclosure:
-               p := gc.Prog(obj.ACALL)
-               p.To.Type = obj.TYPE_MEM
-               p.To.Offset = 0
-               p.To.Reg = v.Args[0].Reg()
-               if gc.Maxarg < v.AuxInt {
-                       gc.Maxarg = v.AuxInt
-               }
-       case ssa.OpMIPS64CALLinter:
-               p := gc.Prog(obj.ACALL)
-               p.To.Type = obj.TYPE_MEM
-               p.To.Offset = 0
-               p.To.Reg = v.Args[0].Reg()
-               if gc.Maxarg < v.AuxInt {
-                       gc.Maxarg = v.AuxInt
-               }
+       case ssa.OpMIPS64CALLstatic, ssa.OpMIPS64CALLclosure, ssa.OpMIPS64CALLinter:
+               s.Call(v)
        case ssa.OpMIPS64LoweredNilCheck:
                // Issue a load which will fault if arg is nil.
                p := gc.Prog(mips.AMOVB)
index 186aa2946a892e4c689fe49a4bfe654d90f93368..7586dd3d99333b48ffd4c1255b7200d319789a61 100644 (file)
@@ -19,6 +19,7 @@ func Init() {
        gc.Thearch.MAXWIDTH = 1 << 50
 
        gc.Thearch.Defframe = defframe
+       gc.Thearch.Ginsnop = ginsnop2
        gc.Thearch.Proginfo = proginfo
 
        gc.Thearch.SSAMarkMoves = ssaMarkMoves
index 33686e503f98b04567db264257383bcc7a4495d6..b9a218d6d4f6616b79d59abbd4a56931d7478586 100644 (file)
@@ -98,3 +98,29 @@ func ginsnop() {
        p.To.Type = obj.TYPE_REG
        p.To.Reg = ppc64.REG_R0
 }
+
+func ginsnop2() {
+       // PPC64 is unusual because TWO nops are required
+       // (see gc/cgen.go, gc/plive.go -- copy of comment below)
+       //
+       // On ppc64, when compiling Go into position
+       // independent code on ppc64le we insert an
+       // instruction to reload the TOC pointer from the
+       // stack as well. See the long comment near
+       // jmpdefer in runtime/asm_ppc64.s for why.
+       // If the MOVD is not needed, insert a hardware NOP
+       // so that the same number of instructions are used
+       // on ppc64 in both shared and non-shared modes.
+
+       ginsnop()
+       if gc.Ctxt.Flag_shared {
+               p := gc.Prog(ppc64.AMOVD)
+               p.From.Type = obj.TYPE_MEM
+               p.From.Offset = 24
+               p.From.Reg = ppc64.REGSP
+               p.To.Type = obj.TYPE_REG
+               p.To.Reg = ppc64.REG_R2
+       } else {
+               ginsnop()
+       }
+}
index 7a6bed4f852d6aaf2c6993ea620473be35859f82..dabf0c15e4d533a74408c4863d150bc2eafc129b 100644 (file)
@@ -941,45 +941,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
                gc.Patch(p4, p)
 
        case ssa.OpPPC64CALLstatic:
-               if v.Aux.(*obj.LSym) == gc.Deferreturn {
-                       // Deferred calls will appear to be returning to
-                       // the CALL deferreturn(SB) that we are about to emit.
-                       // However, the stack trace code will show the line
-                       // of the instruction byte before the return PC.
-                       // To avoid that being an unrelated instruction,
-                       // insert two actual hardware NOPs that will have the right line number.
-                       // This is different from obj.ANOP, which is a virtual no-op
-                       // that doesn't make it into the instruction stream.
-                       // PPC64 is unusual because TWO nops are required
-                       // (see gc/cgen.go, gc/plive.go -- copy of comment below)
-                       //
-                       // On ppc64, when compiling Go into position
-                       // independent code on ppc64le we insert an
-                       // instruction to reload the TOC pointer from the
-                       // stack as well. See the long comment near
-                       // jmpdefer in runtime/asm_ppc64.s for why.
-                       // If the MOVD is not needed, insert a hardware NOP
-                       // so that the same number of instructions are used
-                       // on ppc64 in both shared and non-shared modes.
-                       ginsnop()
-                       if gc.Ctxt.Flag_shared {
-                               p := gc.Prog(ppc64.AMOVD)
-                               p.From.Type = obj.TYPE_MEM
-                               p.From.Offset = 24
-                               p.From.Reg = ppc64.REGSP
-                               p.To.Type = obj.TYPE_REG
-                               p.To.Reg = ppc64.REG_R2
-                       } else {
-                               ginsnop()
-                       }
-               }
-               p := gc.Prog(obj.ACALL)
-               p.To.Type = obj.TYPE_MEM
-               p.To.Name = obj.NAME_EXTERN
-               p.To.Sym = v.Aux.(*obj.LSym)
-               if gc.Maxarg < v.AuxInt {
-                       gc.Maxarg = v.AuxInt
-               }
+               s.Call(v)
 
        case ssa.OpPPC64CALLclosure, ssa.OpPPC64CALLinter:
                p := gc.Prog(ppc64.AMOVD)
@@ -1001,8 +963,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
                        q.To.Reg = ppc64.REG_R12
                }
 
-               pp := gc.Prog(obj.ACALL)
-               pp.To.Type = obj.TYPE_REG
+               pp := s.Call(v)
                pp.To.Reg = ppc64.REG_CTR
 
                if gc.Ctxt.Flag_shared {
@@ -1018,10 +979,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
                        q.To.Reg = ppc64.REG_R2
                }
 
-               if gc.Maxarg < v.AuxInt {
-                       gc.Maxarg = v.AuxInt
-               }
-
        case ssa.OpPPC64LoweredNilCheck:
                // Issue a load which will fault if arg is nil.
                p := gc.Prog(ppc64.AMOVBZ)
index 91b9ed07775984b0f08929db935c0f367d85bd93..ba653c8d2114eb723855fd90487145b78f879646 100644 (file)
@@ -15,6 +15,7 @@ func Init() {
        gc.Thearch.MAXWIDTH = 1 << 50
 
        gc.Thearch.Defframe = defframe
+       gc.Thearch.Ginsnop = ginsnop
        gc.Thearch.Proginfo = proginfo
 
        gc.Thearch.SSAMarkMoves = ssaMarkMoves
index bce63c550bdc0c5b13557e3bfe19b41a39f7f854..c17106d709fd473f5f34be24f2cc8fdfcf73c796 100644 (file)
@@ -481,39 +481,8 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
                p.From.Reg = s390x.REGG
                p.To.Type = obj.TYPE_REG
                p.To.Reg = r
-       case ssa.OpS390XCALLstatic:
-               if v.Aux.(*obj.LSym) == gc.Deferreturn {
-                       // Deferred calls will appear to be returning to
-                       // the CALL deferreturn(SB) that we are about to emit.
-                       // However, the stack trace code will show the line
-                       // of the instruction byte before the return PC.
-                       // To avoid that being an unrelated instruction,
-                       // insert an actual hardware NOP that will have the right line number.
-                       // This is different from obj.ANOP, which is a virtual no-op
-                       // that doesn't make it into the instruction stream.
-                       ginsnop()
-               }
-               p := gc.Prog(obj.ACALL)
-               p.To.Type = obj.TYPE_MEM
-               p.To.Name = obj.NAME_EXTERN
-               p.To.Sym = v.Aux.(*obj.LSym)
-               if gc.Maxarg < v.AuxInt {
-                       gc.Maxarg = v.AuxInt
-               }
-       case ssa.OpS390XCALLclosure:
-               p := gc.Prog(obj.ACALL)
-               p.To.Type = obj.TYPE_REG
-               p.To.Reg = v.Args[0].Reg()
-               if gc.Maxarg < v.AuxInt {
-                       gc.Maxarg = v.AuxInt
-               }
-       case ssa.OpS390XCALLinter:
-               p := gc.Prog(obj.ACALL)
-               p.To.Type = obj.TYPE_REG
-               p.To.Reg = v.Args[0].Reg()
-               if gc.Maxarg < v.AuxInt {
-                       gc.Maxarg = v.AuxInt
-               }
+       case ssa.OpS390XCALLstatic, ssa.OpS390XCALLclosure, ssa.OpS390XCALLinter:
+               s.Call(v)
        case ssa.OpS390XFLOGR, ssa.OpS390XNEG, ssa.OpS390XNEGW,
                ssa.OpS390XMOVWBR, ssa.OpS390XMOVDBR:
                p := gc.Prog(v.Op.Asm())
index edac6a002abe2a72cb315785da6c503b740430db..ca28f1a6abffe3a9e4c3243243c5dee1b560253e 100644 (file)
@@ -26,6 +26,7 @@ func Init() {
        gc.Thearch.MAXWIDTH = (1 << 32) - 1
 
        gc.Thearch.Defframe = defframe
+       gc.Thearch.Ginsnop = ginsnop
        gc.Thearch.Proginfo = proginfo
 
        gc.Thearch.SSAMarkMoves = ssaMarkMoves
index 4cd908a94a0d8eb18f962a99eddcd478b95e9579..73c654cdd4aa616400f84149ae0d97d9e382db5b 100644 (file)
@@ -669,39 +669,8 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
                        q.To.Type = obj.TYPE_REG
                        q.To.Reg = r
                }
-       case ssa.Op386CALLstatic:
-               if v.Aux.(*obj.LSym) == gc.Deferreturn {
-                       // Deferred calls will appear to be returning to
-                       // the CALL deferreturn(SB) that we are about to emit.
-                       // However, the stack trace code will show the line
-                       // of the instruction byte before the return PC.
-                       // To avoid that being an unrelated instruction,
-                       // insert an actual hardware NOP that will have the right line number.
-                       // This is different from obj.ANOP, which is a virtual no-op
-                       // that doesn't make it into the instruction stream.
-                       ginsnop()
-               }
-               p := gc.Prog(obj.ACALL)
-               p.To.Type = obj.TYPE_MEM
-               p.To.Name = obj.NAME_EXTERN
-               p.To.Sym = v.Aux.(*obj.LSym)
-               if gc.Maxarg < v.AuxInt {
-                       gc.Maxarg = v.AuxInt
-               }
-       case ssa.Op386CALLclosure:
-               p := gc.Prog(obj.ACALL)
-               p.To.Type = obj.TYPE_REG
-               p.To.Reg = v.Args[0].Reg()
-               if gc.Maxarg < v.AuxInt {
-                       gc.Maxarg = v.AuxInt
-               }
-       case ssa.Op386CALLinter:
-               p := gc.Prog(obj.ACALL)
-               p.To.Type = obj.TYPE_REG
-               p.To.Reg = v.Args[0].Reg()
-               if gc.Maxarg < v.AuxInt {
-                       gc.Maxarg = v.AuxInt
-               }
+       case ssa.Op386CALLstatic, ssa.Op386CALLclosure, ssa.Op386CALLinter:
+               s.Call(v)
        case ssa.Op386NEGL,
                ssa.Op386BSWAPL,
                ssa.Op386NOTL: