]> Cypherpunks.ru repositories - gostls13.git/blobdiff - src/cmd/internal/obj/arm64/obj7.go
cmd/internal/obj/arm64: fix frame pointer restore in epilogue
[gostls13.git] / src / cmd / internal / obj / arm64 / obj7.go
index 7d20beb5d61694022ff8ebb1593b3efa3fedaa82..0ab5939b8429106b4f74dc1c038187f813bd96ed 100644 (file)
@@ -1,5 +1,5 @@
 // cmd/7l/noop.c, cmd/7l/obj.c, cmd/ld/pass.c from Vita Nuova.
-// https://code.google.com/p/ken-cc/source/browse/
+// https://bitbucket.org/plan9-from-bell-labs/9-cc/src/master/
 //
 //     Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
 //     Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
@@ -35,18 +35,12 @@ import (
        "cmd/internal/objabi"
        "cmd/internal/src"
        "cmd/internal/sys"
+       "internal/abi"
        "internal/buildcfg"
        "log"
        "math"
 )
 
-var complements = []obj.As{
-       AADD:  ASUB,
-       AADDW: ASUBW,
-       ASUB:  AADD,
-       ASUBW: AADDW,
-}
-
 // zrReplace is the set of instructions for which $0 in the From operand
 // should be replaced with REGZERO.
 var zrReplace = map[obj.As]bool{
@@ -176,7 +170,7 @@ func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
        p = c.ctxt.StartUnsafePoint(p, c.newprog)
 
        q := (*obj.Prog)(nil)
-       if framesize <= objabi.StackSmall {
+       if framesize <= abi.StackSmall {
                // small stack: SP < stackguard
                //      CMP     stackguard, SP
 
@@ -185,7 +179,7 @@ func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
                p.From.Type = obj.TYPE_REG
                p.From.Reg = REGRT1
                p.Reg = REGSP
-       } else if framesize <= objabi.StackBig {
+       } else if framesize <= abi.StackBig {
                // large stack: SP-framesize < stackguard-StackSmall
                //      SUB     $(framesize-StackSmall), SP, RT2
                //      CMP     stackguard, RT2
@@ -193,7 +187,7 @@ func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
 
                p.As = ASUB
                p.From.Type = obj.TYPE_CONST
-               p.From.Offset = int64(framesize) - objabi.StackSmall
+               p.From.Offset = int64(framesize) - abi.StackSmall
                p.Reg = REGSP
                p.To.Type = obj.TYPE_REG
                p.To.Reg = REGRT2
@@ -219,7 +213,7 @@ func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
                p = obj.Appendp(p, c.newprog)
                p.As = ASUBS
                p.From.Type = obj.TYPE_CONST
-               p.From.Offset = int64(framesize) - objabi.StackSmall
+               p.From.Offset = int64(framesize) - abi.StackSmall
                p.Reg = REGSP
                p.To.Type = obj.TYPE_REG
                p.To.Reg = REGRT2
@@ -295,11 +289,12 @@ func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
        }
        call.To.Sym = c.ctxt.Lookup(morestack)
 
-       unspill := c.cursym.Func().UnspillRegisterArgs(call, c.newprog)
-       pcdata = c.ctxt.EndUnsafePoint(unspill, c.newprog, -1)
+       // The instructions which unspill regs should be preemptible.
+       pcdata = c.ctxt.EndUnsafePoint(call, c.newprog, -1)
+       unspill := c.cursym.Func().UnspillRegisterArgs(pcdata, c.newprog)
 
        // B    start
-       jmp := obj.Appendp(pcdata, c.newprog)
+       jmp := obj.Appendp(unspill, c.newprog)
        jmp.As = AB
        jmp.To.Type = obj.TYPE_BRANCH
        jmp.To.SetTarget(startPred.Link)
@@ -335,8 +330,33 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
                break
        }
 
-       // Rewrite float constants to values stored in memory.
+       // Rewrite float and vector constants to values stored in memory.
        switch p.As {
+       case AVMOVS:
+               if p.From.Type == obj.TYPE_CONST {
+                       p.From.Type = obj.TYPE_MEM
+                       p.From.Sym = c.ctxt.Int32Sym(p.From.Offset)
+                       p.From.Name = obj.NAME_EXTERN
+                       p.From.Offset = 0
+               }
+
+       case AVMOVD:
+               if p.From.Type == obj.TYPE_CONST {
+                       p.From.Type = obj.TYPE_MEM
+                       p.From.Sym = c.ctxt.Int64Sym(p.From.Offset)
+                       p.From.Name = obj.NAME_EXTERN
+                       p.From.Offset = 0
+               }
+
+       case AVMOVQ:
+               if p.From.Type == obj.TYPE_CONST {
+                       p.From.Type = obj.TYPE_MEM
+                       p.From.Sym = c.ctxt.Int128Sym(p.GetFrom3().Offset, p.From.Offset)
+                       p.From.Name = obj.NAME_EXTERN
+                       p.From.Offset = 0
+                       p.RestArgs = nil
+               }
+
        case AFMOVS:
                if p.From.Type == obj.TYPE_FCONST {
                        f64 := p.From.Val.(float64)
@@ -371,23 +391,6 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
                        p.From.Name = obj.NAME_EXTERN
                        p.From.Offset = 0
                }
-
-               break
-       }
-
-       // Rewrite negative immediates as positive immediates with
-       // complementary instruction.
-       switch p.As {
-       case AADD, ASUB:
-               if p.From.Type == obj.TYPE_CONST && p.From.Offset < 0 && p.From.Offset != -1<<63 {
-                       p.From.Offset = -p.From.Offset
-                       p.As = complements[p.As]
-               }
-       case AADDW, ASUBW:
-               if p.From.Type == obj.TYPE_CONST && p.From.Offset < 0 && int32(p.From.Offset) != -1<<31 {
-                       p.From.Offset = -p.From.Offset
-                       p.As = complements[p.As]
-               }
        }
 
        if c.ctxt.Flag_dynlink {
@@ -604,7 +607,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                                }
                        }
 
-                       if p.Mark&LEAF != 0 && c.autosize < objabi.StackSmall {
+                       if p.Mark&LEAF != 0 && c.autosize < abi.StackSmall {
                                // A leaf function with a small stack can be marked
                                // NOSPLIT, avoiding a stack check.
                                p.From.Sym.Set(obj.AttrNoSplit, true)
@@ -847,21 +850,24 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                        p.To = obj.Addr{}
                        if c.cursym.Func().Text.Mark&LEAF != 0 {
                                if c.autosize != 0 {
+                                       // Restore frame pointer.
+                                       // ADD $framesize-8, RSP, R29
                                        p.As = AADD
                                        p.From.Type = obj.TYPE_CONST
-                                       p.From.Offset = int64(c.autosize)
+                                       p.From.Offset = int64(c.autosize) - 8
+                                       p.Reg = REGSP
                                        p.To.Type = obj.TYPE_REG
-                                       p.To.Reg = REGSP
-                                       p.Spadj = -c.autosize
+                                       p.To.Reg = REGFP
 
-                                       // Frame pointer.
+                                       // Pop stack frame.
+                                       // ADD $framesize, RSP, RSP
                                        p = obj.Appendp(p, c.newprog)
-                                       p.As = ASUB
+                                       p.As = AADD
                                        p.From.Type = obj.TYPE_CONST
-                                       p.From.Offset = 8
-                                       p.Reg = REGSP
+                                       p.From.Offset = int64(c.autosize)
                                        p.To.Type = obj.TYPE_REG
-                                       p.To.Reg = REGFP
+                                       p.To.Reg = REGSP
+                                       p.Spadj = -c.autosize
                                }
                        } else {
                                aoffset := c.autosize
@@ -1059,8 +1065,8 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
 
                if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.Spadj == 0 {
                        f := c.cursym.Func()
-                       if f.FuncFlag&objabi.FuncFlag_SPWRITE == 0 {
-                               c.cursym.Func().FuncFlag |= objabi.FuncFlag_SPWRITE
+                       if f.FuncFlag&abi.FuncFlagSPWrite == 0 {
+                               c.cursym.Func().FuncFlag |= abi.FuncFlagSPWrite
                                if ctxt.Debugvlog || !ctxt.IsAsm {
                                        ctxt.Logf("auto-SPWRITE: %s %v\n", c.cursym.Name, p)
                                        if !ctxt.IsAsm {