[dev.ssa] cmd/internal/ssa: add string operations
Add ops to load, store, select ptr & len, and build constant strings.
A few other minor cleanups.
Change-Id: I6f0f7419d641b119b613ed44561cd308a466051c
Reviewed-on: https://go-review.googlesource.com/10449
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index 7f78fce..3c95266 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -13,12 +13,13 @@
)
func buildssa(fn *Node) *ssa.Func {
- dumplist("buildssa", Curfn.Nbody)
+ dumplist("buildssa-enter", fn.Func.Enter)
+ dumplist("buildssa-body", fn.Nbody)
var s state
// TODO(khr): build config just once at the start of the compiler binary
- s.config = ssa.NewConfig(Thearch.Thestring)
+ s.config = ssa.NewConfig(Thearch.Thestring, ssaExport{})
s.f = s.config.NewFunc()
s.f.Name = fn.Nname.Sym.Name
@@ -44,6 +45,7 @@
// Convert the AST-based IR to the SSA-based IR
s.startBlock(s.f.Entry)
+ s.stmtList(fn.Func.Enter)
s.stmtList(fn.Nbody)
// fallthrough to exit
@@ -159,7 +161,23 @@
case OAS:
// TODO(khr): colas?
- val := s.expr(n.Right)
+ 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.f.Entry.NewValue(ssa.OpConst, n.Left.Type, "")
+ case t.IsInteger():
+ val = s.f.Entry.NewValue(ssa.OpConst, n.Left.Type, int64(0))
+ case t.IsBoolean():
+ val = s.f.Entry.NewValue(ssa.OpConst, n.Left.Type, false)
+ default:
+ log.Fatalf("zero for type %v not implemented", t)
+ }
+ } else {
+ val = s.expr(n.Right)
+ }
if n.Left.Op == ONAME && !n.Left.Addrtaken && n.Left.Class&PHEAP == 0 && n.Left.Class != PEXTERN && n.Left.Class != PPARAMOUT {
// ssa-able variable.
s.vars[n.Left.Sym.Name] = val
@@ -250,10 +268,6 @@
// expr converts the expression n to ssa, adds it to s and returns the ssa result.
func (s *state) expr(n *Node) *ssa.Value {
- if n == nil {
- // TODO(khr): is this nil???
- return s.f.Entry.NewValue(ssa.OpConst, n.Type, nil)
- }
switch n.Op {
case ONAME:
// TODO: remember offsets for PPARAM names
@@ -268,6 +282,8 @@
switch n.Val.Ctype {
case CTINT:
return s.f.ConstInt(n.Type, Mpgetfix(n.Val.U.(*Mpint)))
+ case CTSTR:
+ return s.f.Entry.NewValue(ssa.OpConst, n.Type, n.Val.U)
default:
log.Fatalf("unhandled OLITERAL %v", n.Val.Ctype)
return nil
@@ -573,7 +589,11 @@
// TODO: dump frame if -f
// Emit garbage collection symbols. TODO: put something in them
- liveness(Curfn, ptxt, gcargs, gclocals)
+ //liveness(Curfn, ptxt, gcargs, gclocals)
+ duint32(gcargs, 0, 0)
+ ggloblsym(gcargs, 4, obj.RODATA|obj.DUPOK)
+ duint32(gclocals, 0, 0)
+ ggloblsym(gclocals, 4, obj.RODATA|obj.DUPOK)
}
func genValue(v *ssa.Value) {
@@ -703,7 +723,10 @@
p.To.Type = obj.TYPE_MEM
p.To.Reg = regnum(v.Args[0])
p.To.Offset = v.Aux.(int64)
- case ssa.OpCopy:
+ case ssa.OpCopy: // TODO: lower to MOVQ earlier?
+ if v.Type.IsMemory() {
+ return
+ }
x := regnum(v.Args[0])
y := regnum(v)
if x != y {
@@ -907,3 +930,12 @@
func localOffset(v *ssa.Value) int64 {
return v.Block.Func.RegAlloc[v.ID].(*ssa.LocalSlot).Idx
}
+
+// ssaExport exports a bunch of compiler services for the ssa backend.
+type ssaExport struct{}
+
+// StringSym returns a symbol (a *Sym wrapped in an interface) which
+// is a global string constant containing s.
+func (serv ssaExport) StringSym(s string) interface{} {
+ return stringsym(s)
+}