Commit 7af53d98 authored by Brad Fitzpatrick's avatar Brad Fitzpatrick

[dev.ssa] cmd/compile: implement OCAP

And dependent fixes and misc cleanup.

Co-hacking with josharian at Gophercon.

Change-Id: Ib85dc13b303929017eb0a4d2fc2f603485f7479b
Reviewed-on: https://go-review.googlesource.com/12027Reviewed-by: default avatarKeith Randall <khr@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
parent 050ce439
......@@ -199,7 +199,7 @@ type Type struct {
Note *string // literal string annotation
// TARRAY
Bound int64 // negative is dynamic array
Bound int64 // negative is slice
// TMAP
Bucket *Type // internal type representing a hash bucket
......
......@@ -6,6 +6,7 @@ package gc
import (
"fmt"
"strings"
"cmd/compile/internal/ssa"
"cmd/internal/obj"
......@@ -18,7 +19,7 @@ import (
// it will never return nil, and the bool can be removed.
func buildssa(fn *Node) (ssafn *ssa.Func, usessa bool) {
name := fn.Func.Nname.Sym.Name
usessa = len(name) > 4 && name[len(name)-4:] == "_ssa"
usessa = strings.HasSuffix(name, "_ssa")
if usessa {
dumplist("buildssa-enter", fn.Func.Enter)
......@@ -293,6 +294,8 @@ func (s *state) stmt(n *Node) {
case OBLOCK:
s.stmtList(n.List)
case OEMPTY:
case ODCL:
if n.Left.Class&PHEAP == 0 {
return
......@@ -527,14 +530,18 @@ func (s *state) expr(n *Node) *ssa.Value {
return s.newValue2(ssa.OpLoad, n.Left.Type.Type, p, s.mem())
}
case OLEN:
case OLEN, OCAP:
switch {
case n.Left.Type.Bound < 0: // slice
return s.newValue1(ssa.OpSliceLen, s.config.Uintptr, s.expr(n.Left))
case n.Left.Type.IsString(): // string
return s.newValue1(ssa.OpStringLen, s.config.Uintptr, s.expr(n.Left))
case n.Left.Type.IsSlice():
op := ssa.OpSliceLen
if n.Op == OCAP {
op = ssa.OpSliceCap
}
return s.newValue1(op, s.config.Int, s.expr(n.Left))
case n.Left.Type.IsString(): // string; not reachable for OCAP
return s.newValue1(ssa.OpStringLen, s.config.Int, s.expr(n.Left))
default: // array
return s.constInt(s.config.Uintptr, n.Left.Type.Bound)
return s.constInt(s.config.Int, n.Left.Type.Bound)
}
case OCALLFUNC:
......@@ -645,19 +652,19 @@ func (s *state) addr(n *Node) *ssa.Value {
// used for storing/loading arguments/returns to/from callees
return s.entryNewValue1I(ssa.OpOffPtr, Ptrto(n.Type), n.Xoffset, s.sp)
case OINDEX:
if n.Left.Type.Bound >= 0 { // array
a := s.addr(n.Left)
i := s.expr(n.Right)
len := s.constInt(s.config.Uintptr, n.Left.Type.Bound)
s.boundsCheck(i, len)
return s.newValue2(ssa.OpPtrIndex, Ptrto(n.Left.Type.Type), a, i)
} else { // slice
if n.Left.Type.IsSlice() {
a := s.expr(n.Left)
i := s.expr(n.Right)
len := s.newValue1(ssa.OpSliceLen, s.config.Uintptr, a)
s.boundsCheck(i, len)
p := s.newValue1(ssa.OpSlicePtr, Ptrto(n.Left.Type.Type), a)
return s.newValue2(ssa.OpPtrIndex, Ptrto(n.Left.Type.Type), p, i)
} else { // array
a := s.addr(n.Left)
i := s.expr(n.Right)
len := s.constInt(s.config.Uintptr, n.Left.Type.Bound)
s.boundsCheck(i, len)
return s.newValue2(ssa.OpPtrIndex, Ptrto(n.Left.Type.Type), a, i)
}
default:
s.Unimplementedf("addr: bad op %v", Oconv(int(n.Op), 0))
......
......@@ -64,6 +64,10 @@ func (t *Type) IsString() bool {
return t.Etype == TSTRING
}
func (t *Type) IsSlice() bool {
return t.Etype == TARRAY && t.Bound < 0
}
func (t *Type) Elem() ssa.Type {
return t.Type
}
......
......@@ -8,6 +8,7 @@ type Config struct {
arch string // "amd64", etc.
ptrSize int64 // 4 or 8
Uintptr Type // pointer arithmetic type
Int Type
lowerBlock func(*Block) bool // lowering function
lowerValue func(*Value, *Config) bool // lowering function
fe Frontend // callbacks into compiler frontend
......@@ -48,10 +49,12 @@ func NewConfig(arch string, fe Frontend) *Config {
fe.Unimplementedf("arch %s not implemented", arch)
}
// cache the intptr type in the config
// cache the frequently-used types in the config
c.Uintptr = TypeUInt32
c.Int = TypeInt32
if c.ptrSize == 8 {
c.Uintptr = TypeUInt64
c.Int = TypeInt64
}
return c
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment