From 7af53d98cf720b97f9f941b6747405c5a924eb55 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Fri, 10 Jul 2015 10:47:28 -0600 Subject: [PATCH] [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/12027 Reviewed-by: Keith Randall Run-TryBot: Brad Fitzpatrick --- src/cmd/compile/internal/gc/go.go | 2 +- src/cmd/compile/internal/gc/ssa.go | 35 +++++++++++++++----------- src/cmd/compile/internal/gc/type.go | 4 +++ src/cmd/compile/internal/ssa/config.go | 11 +++++--- 4 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/cmd/compile/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go index 0aa0e289ec..fabe325c38 100644 --- a/src/cmd/compile/internal/gc/go.go +++ b/src/cmd/compile/internal/gc/go.go @@ -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 diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index ab16a33510..90c1e0a25e 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -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)) diff --git a/src/cmd/compile/internal/gc/type.go b/src/cmd/compile/internal/gc/type.go index 11635d8929..7f7b6635e0 100644 --- a/src/cmd/compile/internal/gc/type.go +++ b/src/cmd/compile/internal/gc/type.go @@ -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 } diff --git a/src/cmd/compile/internal/ssa/config.go b/src/cmd/compile/internal/ssa/config.go index 53eb5e8eb5..c6c7bf36e9 100644 --- a/src/cmd/compile/internal/ssa/config.go +++ b/src/cmd/compile/internal/ssa/config.go @@ -5,9 +5,10 @@ package ssa type Config struct { - arch string // "amd64", etc. - ptrSize int64 // 4 or 8 - Uintptr Type // pointer arithmetic type + 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 -- 2.48.1