]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.ssa] cmd/compile/internal/ssa: implement ORETJMP
authorKeith Randall <khr@golang.org>
Wed, 9 Sep 2015 04:28:44 +0000 (21:28 -0700)
committerKeith Randall <khr@golang.org>
Wed, 9 Sep 2015 20:33:35 +0000 (20:33 +0000)
Change-Id: I352c7b9aab053959bc74c15861339e1dbe545ddc
Reviewed-on: https://go-review.googlesource.com/14404
Reviewed-by: David Chase <drchase@google.com>
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/ssa/block.go
src/cmd/compile/internal/ssa/check.go
src/cmd/compile/internal/ssa/gen/genericOps.go
src/cmd/compile/internal/ssa/html.go
src/cmd/compile/internal/ssa/opGen.go

index e3a71a9f3f8205d584dbc65e5ac27a44f07b0d0f..9d87f38ea190f1f4c258f46945bdffb74f3c00a5 100644 (file)
@@ -583,6 +583,14 @@ func (s *state) stmt(n *Node) {
                b.Kind = ssa.BlockRet
                b.Control = m
                b.AddEdgeTo(s.exit)
+       case ORETJMP:
+               s.stmtList(n.List)
+               m := s.mem()
+               b := s.endBlock()
+               b.Kind = ssa.BlockRetJmp
+               b.Aux = n.Left.Sym
+               b.Control = m
+               b.AddEdgeTo(s.exit)
 
        case OCONTINUE, OBREAK:
                var op string
@@ -2054,6 +2062,11 @@ func canSSA(n *Node) bool {
        case PEXTERN, PPARAMOUT, PPARAMREF:
                return false
        }
+       if n.Class == PPARAM && n.String() == ".this" {
+               // wrappers generated by genwrapper need to update
+               // the .this pointer in place.
+               return false
+       }
        return canSSAType(n.Type)
        // TODO: try to make more variables SSAable?
 }
@@ -3475,6 +3488,11 @@ func (s *genState) genBlock(b, next *ssa.Block) {
                        s.deferReturn()
                }
                Prog(obj.ARET)
+       case ssa.BlockRetJmp:
+               p := Prog(obj.AJMP)
+               p.To.Type = obj.TYPE_MEM
+               p.To.Name = obj.NAME_EXTERN
+               p.To.Sym = Linksym(b.Aux.(*Sym))
        case ssa.BlockCall:
                if b.Succs[0] != next {
                        p := Prog(obj.AJMP)
index 1d5e617c551ee02ae82b623d4e937fdd28f7b22d..5fb93cd5a7b47c5d2866707aa2942b7dbede4590 100644 (file)
@@ -30,6 +30,9 @@ type Block struct {
        // has a memory control value.
        Control *Value
 
+       // Auxiliary info for the block.  Its value depends on the Kind.
+       Aux interface{}
+
        // The unordered set of Values that define the operation of this block.
        // The list must include the control value, if any. (TODO: need this last condition?)
        // After the scheduling pass, this list is ordered.
@@ -65,6 +68,9 @@ func (b *Block) String() string {
 // long form print
 func (b *Block) LongString() string {
        s := b.Kind.String()
+       if b.Aux != nil {
+               s += fmt.Sprintf(" %s", b.Aux)
+       }
        if b.Control != nil {
                s += fmt.Sprintf(" %s", b.Control)
        }
index b860f633ef1f22c1b13babd9e578214dedc24472..9747585f4a90f389f90100444d9abb2e63fd4e7c 100644 (file)
@@ -72,6 +72,22 @@ func checkFunc(f *Func) {
                        if b.Succs[0].Kind != BlockExit {
                                f.Fatalf("ret block %s has successor %s, not Exit", b, b.Succs[0].Kind)
                        }
+               case BlockRetJmp:
+                       if len(b.Succs) != 1 {
+                               f.Fatalf("retjmp block %s len(Succs)==%d, want 1", b, len(b.Succs))
+                       }
+                       if b.Control == nil {
+                               f.Fatalf("retjmp block %s has nil control %s", b)
+                       }
+                       if !b.Control.Type.IsMemory() {
+                               f.Fatalf("retjmp block %s has non-memory control value %s", b, b.Control.LongString())
+                       }
+                       if b.Succs[0].Kind != BlockExit {
+                               f.Fatalf("retjmp block %s has successor %s, not Exit", b, b.Succs[0].Kind)
+                       }
+                       if b.Aux == nil {
+                               f.Fatalf("retjmp block %s has nil Aux field", b)
+                       }
                case BlockDead:
                        if len(b.Succs) != 0 {
                                f.Fatalf("dead block %s has successors", b)
index 9bc77909b51f3469c499ff11c8623fb794427200..1c26946781e7c2b63b8ec8c3597561434db4f5cc 100644 (file)
@@ -376,13 +376,14 @@ var genericOps = []opData{
 //    First               nil    [always,never]
 
 var genericBlocks = []blockData{
-       {name: "Exit"},  // no successors.  There should only be 1 of these.
-       {name: "Dead"},  // no successors; determined to be dead but not yet removed
-       {name: "Plain"}, // a single successor
-       {name: "If"},    // 2 successors, if control goto Succs[0] else goto Succs[1]
-       {name: "Call"},  // 2 successors, normal return and panic
-       {name: "First"}, // 2 successors, always takes the first one (second is dead)
-       {name: "Ret"},   // 1 successor, branches to exit
+       {name: "Exit"},   // no successors.  There should only be 1 of these.
+       {name: "Dead"},   // no successors; determined to be dead but not yet removed
+       {name: "Plain"},  // a single successor
+       {name: "If"},     // 2 successors, if control goto Succs[0] else goto Succs[1]
+       {name: "Call"},   // 2 successors, normal return and panic
+       {name: "First"},  // 2 successors, always takes the first one (second is dead)
+       {name: "Ret"},    // 1 successor, branches to exit
+       {name: "RetJmp"}, // 1 successor, branches to exit.  Jumps to b.Aux.(*gc.Sym)
 }
 
 func init() {
index c84dccf793cf5e9ab589d047179da067143c9eb8..68a432c676365443b73d98afee30ee6f4542696d 100644 (file)
@@ -384,6 +384,9 @@ func (b *Block) HTML() string {
 func (b *Block) LongHTML() string {
        // TODO: improve this for HTML?
        s := fmt.Sprintf("<span class=\"%s ssa-block\">%s</span>", html.EscapeString(b.String()), html.EscapeString(b.Kind.String()))
+       if b.Aux != nil {
+               s += html.EscapeString(fmt.Sprintf(" {%v}", b.Aux))
+       }
        if b.Control != nil {
                s += fmt.Sprintf(" %s", b.Control.HTML())
        }
index 0d7343c8aaeeb3d488a000ef8d3a3f18b11b65d8..bca665415854a0c5f0234e77a6d5c4d1f59fcc82 100644 (file)
@@ -29,6 +29,7 @@ const (
        BlockCall
        BlockFirst
        BlockRet
+       BlockRetJmp
 )
 
 var blockString = [...]string{
@@ -49,13 +50,14 @@ var blockString = [...]string{
        BlockAMD64ORD: "ORD",
        BlockAMD64NAN: "NAN",
 
-       BlockExit:  "Exit",
-       BlockDead:  "Dead",
-       BlockPlain: "Plain",
-       BlockIf:    "If",
-       BlockCall:  "Call",
-       BlockFirst: "First",
-       BlockRet:   "Ret",
+       BlockExit:   "Exit",
+       BlockDead:   "Dead",
+       BlockPlain:  "Plain",
+       BlockIf:     "If",
+       BlockCall:   "Call",
+       BlockFirst:  "First",
+       BlockRet:    "Ret",
+       BlockRetJmp: "RetJmp",
 }
 
 func (k BlockKind) String() string { return blockString[k] }