diff --git a/importer/source.go b/importer/source.go index 326d5d25..77890723 100644 --- a/importer/source.go +++ b/importer/source.go @@ -606,7 +606,7 @@ func NodeDescription(n ast.Node) string { case *ast.SwitchStmt: return "switch statement" case *ast.TypeAssertExpr: - return "type assertioh" + return "type assertion" case *ast.TypeSpec: return "type specification" case *ast.TypeSwitchStmt: diff --git a/ssa/builder.go b/ssa/builder.go index a7406796..7b288712 100644 --- a/ssa/builder.go +++ b/ssa/builder.go @@ -303,7 +303,9 @@ func (b *builder) builtin(fn *Function, name string, args []ast.Expr, typ types. } case "new": - return emitNew(fn, deref(typ), pos) + alloc := emitNew(fn, deref(typ), pos) + alloc.Comment = "new" + return alloc case "len", "cap": // Special case: len or cap of an array or *array is @@ -367,12 +369,13 @@ func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue { case *ast.CompositeLit: t := deref(fn.Pkg.typeOf(e)) - var v Value + var v *Alloc if escaping { v = emitNew(fn, t, e.Lbrace) } else { v = fn.addLocal(t, e.Lbrace) } + v.Comment = "complit" b.compLit(fn, v, e, t) // initialize in place return &address{addr: v, expr: e} @@ -875,6 +878,7 @@ func (b *builder) emitCallArgs(fn *Function, sig *types.Signature, e *ast.CallEx at := types.NewArray(vt, int64(len(varargs))) // Don't set pos for implicit Allocs. a := emitNew(fn, at, token.NoPos) + a.Comment = "varargs" for i, arg := range varargs { iaddr := &IndexAddr{ X: a, @@ -1186,7 +1190,9 @@ func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, typ typ switch t := t.(type) { case *types.Slice: at = types.NewArray(t.Elem(), b.arrayLen(fn, e.Elts)) - array = emitNew(fn, at, e.Lbrace) + alloc := emitNew(fn, at, e.Lbrace) + alloc.Comment = "slicelit" + array = alloc case *types.Array: at = t array = addr diff --git a/ssa/emit.go b/ssa/emit.go index 55a4af8d..d819f07b 100644 --- a/ssa/emit.go +++ b/ssa/emit.go @@ -12,12 +12,12 @@ import ( // emitNew emits to f a new (heap Alloc) instruction allocating an // object of type typ. pos is the optional source location. // -func emitNew(f *Function, typ types.Type, pos token.Pos) Value { - return f.emit(&Alloc{ - typ: types.NewPointer(typ), - Heap: true, - pos: pos, - }) +func emitNew(f *Function, typ types.Type, pos token.Pos) *Alloc { + v := &Alloc{Heap: true} + v.setType(types.NewPointer(typ)) + v.setPos(pos) + f.emit(v) + return v } // emitLoad emits to f an instruction to load the address addr into a diff --git a/ssa/example_test.go b/ssa/example_test.go index de2a1794..9aca4a45 100644 --- a/ssa/example_test.go +++ b/ssa/example_test.go @@ -97,11 +97,11 @@ func main() { // # Location: hello.go:8:6 // func main(): // .0.entry: P:0 S:0 - // a0 = new [1]interface{} *[1]interface{} - // t0 = &a0[0:untyped integer] *interface{} - // t1 = make interface{} <- string ("Hello, World!":string) interface{} - // *t0 = t1 - // t2 = slice a0[:] []interface{} - // t3 = fmt.Println(t2) (n int, err error) + // t0 = new [1]interface{} (varargs) *[1]interface{} + // t1 = &t0[0:untyped integer] *interface{} + // t2 = make interface{} <- string ("Hello, World!":string) interface{} + // *t1 = t2 + // t3 = slice t0[:] []interface{} + // t4 = fmt.Println(t3) (n int, err error) // ret } diff --git a/ssa/func.go b/ssa/func.go index 09a4c02a..ae155901 100644 --- a/ssa/func.go +++ b/ssa/func.go @@ -195,11 +195,9 @@ func (f *Function) addParamObj(obj types.Object) *Parameter { // func (f *Function) addSpilledParam(obj types.Object) { param := f.addParamObj(obj) - spill := &Alloc{ - name: obj.Name() + "~", // "~" means "spilled" - typ: types.NewPointer(obj.Type()), - pos: obj.Pos(), - } + spill := &Alloc{Comment: obj.Name()} + spill.setType(types.NewPointer(obj.Type())) + spill.setPos(obj.Pos()) f.objects[obj] = spill f.Locals = append(f.Locals, spill) f.emit(spill) @@ -266,21 +264,12 @@ func (f *Function) createSyntacticParams() { // numberRegisters assigns numbers to all SSA registers // (value-defining Instructions) in f, to aid debugging. // (Non-Instruction Values are named at construction.) -// NB: named Allocs retain their existing name. -// TODO(adonovan): when we have source position info, -// preserve names only for source locals. // func numberRegisters(f *Function) { - a, v := 0, 0 + v := 0 for _, b := range f.Blocks { for _, instr := range b.Instrs { - switch instr := instr.(type) { - case *Alloc: - // Allocs may be named at birth. - if instr.name == "" { - instr.name = fmt.Sprintf("a%d", a) - a++ - } + switch instr.(type) { case Value: instr.(interface { setNum(int) @@ -396,7 +385,7 @@ func (f *Function) debugInfo() bool { // func (f *Function) addNamedLocal(obj types.Object) *Alloc { l := f.addLocal(obj.Type(), obj.Pos()) - l.name = obj.Name() + l.Comment = obj.Name() f.objects[obj] = l return l } @@ -409,7 +398,9 @@ func (f *Function) addLocalForIdent(id *ast.Ident) *Alloc { // to function f and returns it. pos is the optional source location. // func (f *Function) addLocal(typ types.Type, pos token.Pos) *Alloc { - v := &Alloc{typ: types.NewPointer(typ), pos: pos} + v := &Alloc{} + v.setType(types.NewPointer(typ)) + v.setPos(pos) f.Locals = append(f.Locals, v) f.emit(v) return v diff --git a/ssa/print.go b/ssa/print.go index e5315325..6bdc1b5c 100644 --- a/ssa/print.go +++ b/ssa/print.go @@ -77,7 +77,7 @@ func (v *Alloc) String() string { if v.Heap { op = "new" } - return fmt.Sprintf("%s %s", op, deref(v.Type())) + return fmt.Sprintf("%s %s (%s)", op, deref(v.Type()), v.Comment) } func (v *Phi) String() string { diff --git a/ssa/ssa.go b/ssa/ssa.go index a0e7b912..07e2540d 100644 --- a/ssa/ssa.go +++ b/ssa/ssa.go @@ -437,13 +437,10 @@ type Builtin struct { // t1 = new int // type Alloc struct { - anInstruction - name string - typ types.Type - Heap bool - pos token.Pos - referrers []Instruction - index int // dense numbering; for lifting + Register + Comment string + Heap bool + index int // dense numbering; for lifting } // The Phi instruction represents an SSA φ-node, which combines values @@ -1339,7 +1336,6 @@ func (v *Parameter) Pos() token.Pos { return v.pos } func (v *Parameter) Parent() *Function { return v.parent } func (v *Alloc) Type() types.Type { return v.typ } -func (v *Alloc) Name() string { return v.name } func (v *Alloc) Referrers() *[]Instruction { return &v.referrers } func (v *Alloc) Pos() token.Pos { return v.pos }