]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.ssa] initial implementation of PAUTO|PHEAP variables
authorDaniel Morsing <daniel.morsing@gmail.com>
Fri, 12 Jun 2015 13:23:29 +0000 (14:23 +0100)
committerDaniel Morsing <daniel.morsing@gmail.com>
Sun, 14 Jun 2015 20:01:03 +0000 (20:01 +0000)
Call to the runtime to generate escaping variables and use the returned
address when accessing these variables.

Fix a couple of errors on the way. The rule for CALLstatic was missed
during the Aux refactor and OCONVNOP wasn't converted.

Change-Id: I2096beff92cca92d648bfb6e8ec0b120f02f44af
Reviewed-on: https://go-review.googlesource.com/11072
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/ssa/gen/AMD64.rules
src/cmd/compile/internal/ssa/rewriteAMD64.go

index dec4de0e10196fecbc3ff65094bb3538ceb48100..1d7cb287a78ad6f70231f560ff3c5b1955eb72f5 100644 (file)
@@ -226,8 +226,23 @@ func (s *state) stmt(n *Node) {
                s.stmtList(n.List)
 
        case ODCL:
-               // TODO: old gen pass uses dcl node as the point where
-               // escaping variables' new functions are called. Do that here
+               if n.Left.Class&PHEAP == 0 {
+                       return
+               }
+               if compiling_runtime != 0 {
+                       log.Fatalf("%v escapes to heap, not allowed in runtime.", n)
+               }
+
+               // TODO: the old pass hides the details of PHEAP
+               // variables behind ONAME nodes. Figure out if it's better
+               // to rewrite the tree and make the heapaddr construct explicit
+               // or to keep this detail hidden behind the scenes.
+               palloc := prealloc[n.Left]
+               if palloc == nil {
+                       palloc = callnew(n.Left.Type)
+                       prealloc[n.Left] = palloc
+               }
+               s.assign(OAS, n.Left.Name.Heapaddr, palloc)
 
        case OLABEL, OGOTO:
                // get block at label, or make one
@@ -247,32 +262,8 @@ func (s *state) stmt(n *Node) {
                }
 
        case OAS, OASWB:
-               // TODO: do write barrier
-               var val *ssa.Value
-               if n.Right == nil {
-                       // n.Right == nil means use the zero value of the assigned type.
-                       t := n.Left.Type
-                       switch {
-                       case t.IsString():
-                               val = s.entryNewValue0(ssa.OpConst, n.Left.Type)
-                       case t.IsInteger():
-                               val = s.entryNewValue0(ssa.OpConst, n.Left.Type)
-                       case t.IsBoolean():
-                               val = s.entryNewValue0A(ssa.OpConst, n.Left.Type, false) // TODO: store bools as 0/1 in AuxInt?
-                       default:
-                               log.Fatalf("zero for type %v not implemented", t)
-                       }
-               } else {
-                       val = s.expr(n.Right)
-               }
-               if n.Left.Op == ONAME && canSSA(n.Left) {
-                       // Update variable assignment.
-                       s.vars[n.Left.Sym.Name] = val
-                       return
-               }
-               // not ssa-able.  Treat as a store.
-               addr := s.addr(n.Left)
-               s.vars[".mem"] = s.newValue3(ssa.OpStore, ssa.TypeMem, addr, val, s.mem())
+               s.assign(n.Op, n.Left, n.Right)
+
        case OIF:
                cond := s.expr(n.Left)
                b := s.endBlock()
@@ -478,6 +469,36 @@ func (s *state) expr(n *Node) *ssa.Value {
        }
 }
 
+func (s *state) assign(op uint8, left *Node, right *Node) {
+       // TODO: do write barrier
+       // if op == OASWB
+       var val *ssa.Value
+       if right == nil {
+               // right == nil means use the zero value of the assigned type.
+               t := left.Type
+               switch {
+               case t.IsString():
+                       val = s.entryNewValue0(ssa.OpConst, left.Type)
+               case t.IsInteger():
+                       val = s.entryNewValue0(ssa.OpConst, left.Type)
+               case t.IsBoolean():
+                       val = s.entryNewValue0A(ssa.OpConst, left.Type, false) // TODO: store bools as 0/1 in AuxInt?
+               default:
+                       log.Fatalf("zero for type %v not implemented", t)
+               }
+       } else {
+               val = s.expr(right)
+       }
+       if left.Op == ONAME && canSSA(left) {
+               // Update variable assignment.
+               s.vars[left.Sym.Name] = val
+               return
+       }
+       // not ssa-able.  Treat as a store.
+       addr := s.addr(left)
+       s.vars[".mem"] = s.newValue3(ssa.OpStore, ssa.TypeMem, addr, val, s.mem())
+}
+
 // addr converts the address of the expression n to SSA, adds it to s and returns the SSA result.
 func (s *state) addr(n *Node) *ssa.Value {
        switch n.Op {
@@ -489,6 +510,8 @@ func (s *state) addr(n *Node) *ssa.Value {
                case PPARAMOUT:
                        // store to parameter slot
                        return s.entryNewValue1I(ssa.OpOffPtr, Ptrto(n.Type), n.Xoffset, s.fp)
+               case PAUTO | PHEAP:
+                       return s.expr(n.Name.Heapaddr)
                default:
                        // TODO: address of locals
                        log.Fatalf("variable address of %v not implemented", n)
index 58ab25b392d64643946a5cc09162c5724f9c6f2f..b62c8767d1eb7764a5a1cc0427088356ed9ff473 100644 (file)
@@ -58,7 +58,7 @@
 (If (SETB cmp) yes no) -> (ULT cmp yes no)
 (If cond yes no) && cond.Op == OpAMD64MOVBload -> (NE (TESTB <TypeFlags> cond cond) yes no)
 
-(StaticCall [target] mem) -> (CALLstatic [target] mem)
+(StaticCall {target} mem) -> (CALLstatic {target} mem)
 (ClosureCall entry closure mem) -> (CALLclosure entry closure mem)
 
 // Rules below here apply some simple optimizations after lowering.
index d466e154e77e8dfd09e27dc89c92043e1a85585e..a3ec3e7cc1a7b792e9d3c77042a5fd725651087a 100644 (file)
@@ -1093,22 +1093,22 @@ func rewriteValueAMD64(v *Value, config *Config) bool {
        end78e66b6fc298684ff4ac8aec5ce873c9:
                ;
        case OpStaticCall:
-               // match: (StaticCall [target] mem)
+               // match: (StaticCall {target} mem)
                // cond:
-               // result: (CALLstatic [target] mem)
+               // result: (CALLstatic {target} mem)
                {
-                       target := v.AuxInt
+                       target := v.Aux
                        mem := v.Args[0]
                        v.Op = OpAMD64CALLstatic
                        v.AuxInt = 0
                        v.Aux = nil
                        v.resetArgs()
-                       v.AuxInt = target
+                       v.Aux = target
                        v.AddArg(mem)
                        return true
                }
-               goto endcf02eb60d90086f6c42bfdc5842b145d
-       endcf02eb60d90086f6c42bfdc5842b145d:
+               goto end1948857a7cfc2a4f905045e58d3b9ec1
+       end1948857a7cfc2a4f905045e58d3b9ec1:
                ;
        case OpStore:
                // match: (Store ptr val mem)