[dev.ssa] initial implementation of PAUTO|PHEAP variables
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>
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index dec4de0..1d7cb28 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -226,8 +226,23 @@
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 @@
}
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) 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 @@
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)