go.tools/ssa: cosmetic changes to ssa.Alloc.
Remove its 'name' field and treat it just like any other ssa.Register: it gets a temp name like "t1". Instead, give it a comment field holding its purpose, e.g, "x" for a source-level vare, or "new", "slicelit", "complit" or "varargs". This improves usability of tools whose UI needs to refer to a particular allocation site. R=gri CC=golang-dev https://golang.org/cl/12273043
This commit is contained in:
parent
8d55039560
commit
5cc33ea5a7
|
|
@ -606,7 +606,7 @@ func NodeDescription(n ast.Node) string {
|
||||||
case *ast.SwitchStmt:
|
case *ast.SwitchStmt:
|
||||||
return "switch statement"
|
return "switch statement"
|
||||||
case *ast.TypeAssertExpr:
|
case *ast.TypeAssertExpr:
|
||||||
return "type assertioh"
|
return "type assertion"
|
||||||
case *ast.TypeSpec:
|
case *ast.TypeSpec:
|
||||||
return "type specification"
|
return "type specification"
|
||||||
case *ast.TypeSwitchStmt:
|
case *ast.TypeSwitchStmt:
|
||||||
|
|
|
||||||
|
|
@ -303,7 +303,9 @@ func (b *builder) builtin(fn *Function, name string, args []ast.Expr, typ types.
|
||||||
}
|
}
|
||||||
|
|
||||||
case "new":
|
case "new":
|
||||||
return emitNew(fn, deref(typ), pos)
|
alloc := emitNew(fn, deref(typ), pos)
|
||||||
|
alloc.Comment = "new"
|
||||||
|
return alloc
|
||||||
|
|
||||||
case "len", "cap":
|
case "len", "cap":
|
||||||
// Special case: len or cap of an array or *array is
|
// 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:
|
case *ast.CompositeLit:
|
||||||
t := deref(fn.Pkg.typeOf(e))
|
t := deref(fn.Pkg.typeOf(e))
|
||||||
var v Value
|
var v *Alloc
|
||||||
if escaping {
|
if escaping {
|
||||||
v = emitNew(fn, t, e.Lbrace)
|
v = emitNew(fn, t, e.Lbrace)
|
||||||
} else {
|
} else {
|
||||||
v = fn.addLocal(t, e.Lbrace)
|
v = fn.addLocal(t, e.Lbrace)
|
||||||
}
|
}
|
||||||
|
v.Comment = "complit"
|
||||||
b.compLit(fn, v, e, t) // initialize in place
|
b.compLit(fn, v, e, t) // initialize in place
|
||||||
return &address{addr: v, expr: e}
|
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)))
|
at := types.NewArray(vt, int64(len(varargs)))
|
||||||
// Don't set pos for implicit Allocs.
|
// Don't set pos for implicit Allocs.
|
||||||
a := emitNew(fn, at, token.NoPos)
|
a := emitNew(fn, at, token.NoPos)
|
||||||
|
a.Comment = "varargs"
|
||||||
for i, arg := range varargs {
|
for i, arg := range varargs {
|
||||||
iaddr := &IndexAddr{
|
iaddr := &IndexAddr{
|
||||||
X: a,
|
X: a,
|
||||||
|
|
@ -1186,7 +1190,9 @@ func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, typ typ
|
||||||
switch t := t.(type) {
|
switch t := t.(type) {
|
||||||
case *types.Slice:
|
case *types.Slice:
|
||||||
at = types.NewArray(t.Elem(), b.arrayLen(fn, e.Elts))
|
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:
|
case *types.Array:
|
||||||
at = t
|
at = t
|
||||||
array = addr
|
array = addr
|
||||||
|
|
|
||||||
12
ssa/emit.go
12
ssa/emit.go
|
|
@ -12,12 +12,12 @@ import (
|
||||||
// emitNew emits to f a new (heap Alloc) instruction allocating an
|
// emitNew emits to f a new (heap Alloc) instruction allocating an
|
||||||
// object of type typ. pos is the optional source location.
|
// object of type typ. pos is the optional source location.
|
||||||
//
|
//
|
||||||
func emitNew(f *Function, typ types.Type, pos token.Pos) Value {
|
func emitNew(f *Function, typ types.Type, pos token.Pos) *Alloc {
|
||||||
return f.emit(&Alloc{
|
v := &Alloc{Heap: true}
|
||||||
typ: types.NewPointer(typ),
|
v.setType(types.NewPointer(typ))
|
||||||
Heap: true,
|
v.setPos(pos)
|
||||||
pos: pos,
|
f.emit(v)
|
||||||
})
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// emitLoad emits to f an instruction to load the address addr into a
|
// emitLoad emits to f an instruction to load the address addr into a
|
||||||
|
|
|
||||||
|
|
@ -97,11 +97,11 @@ func main() {
|
||||||
// # Location: hello.go:8:6
|
// # Location: hello.go:8:6
|
||||||
// func main():
|
// func main():
|
||||||
// .0.entry: P:0 S:0
|
// .0.entry: P:0 S:0
|
||||||
// a0 = new [1]interface{} *[1]interface{}
|
// t0 = new [1]interface{} (varargs) *[1]interface{}
|
||||||
// t0 = &a0[0:untyped integer] *interface{}
|
// t1 = &t0[0:untyped integer] *interface{}
|
||||||
// t1 = make interface{} <- string ("Hello, World!":string) interface{}
|
// t2 = make interface{} <- string ("Hello, World!":string) interface{}
|
||||||
// *t0 = t1
|
// *t1 = t2
|
||||||
// t2 = slice a0[:] []interface{}
|
// t3 = slice t0[:] []interface{}
|
||||||
// t3 = fmt.Println(t2) (n int, err error)
|
// t4 = fmt.Println(t3) (n int, err error)
|
||||||
// ret
|
// ret
|
||||||
}
|
}
|
||||||
|
|
|
||||||
27
ssa/func.go
27
ssa/func.go
|
|
@ -195,11 +195,9 @@ func (f *Function) addParamObj(obj types.Object) *Parameter {
|
||||||
//
|
//
|
||||||
func (f *Function) addSpilledParam(obj types.Object) {
|
func (f *Function) addSpilledParam(obj types.Object) {
|
||||||
param := f.addParamObj(obj)
|
param := f.addParamObj(obj)
|
||||||
spill := &Alloc{
|
spill := &Alloc{Comment: obj.Name()}
|
||||||
name: obj.Name() + "~", // "~" means "spilled"
|
spill.setType(types.NewPointer(obj.Type()))
|
||||||
typ: types.NewPointer(obj.Type()),
|
spill.setPos(obj.Pos())
|
||||||
pos: obj.Pos(),
|
|
||||||
}
|
|
||||||
f.objects[obj] = spill
|
f.objects[obj] = spill
|
||||||
f.Locals = append(f.Locals, spill)
|
f.Locals = append(f.Locals, spill)
|
||||||
f.emit(spill)
|
f.emit(spill)
|
||||||
|
|
@ -266,21 +264,12 @@ func (f *Function) createSyntacticParams() {
|
||||||
// numberRegisters assigns numbers to all SSA registers
|
// numberRegisters assigns numbers to all SSA registers
|
||||||
// (value-defining Instructions) in f, to aid debugging.
|
// (value-defining Instructions) in f, to aid debugging.
|
||||||
// (Non-Instruction Values are named at construction.)
|
// (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) {
|
func numberRegisters(f *Function) {
|
||||||
a, v := 0, 0
|
v := 0
|
||||||
for _, b := range f.Blocks {
|
for _, b := range f.Blocks {
|
||||||
for _, instr := range b.Instrs {
|
for _, instr := range b.Instrs {
|
||||||
switch instr := instr.(type) {
|
switch instr.(type) {
|
||||||
case *Alloc:
|
|
||||||
// Allocs may be named at birth.
|
|
||||||
if instr.name == "" {
|
|
||||||
instr.name = fmt.Sprintf("a%d", a)
|
|
||||||
a++
|
|
||||||
}
|
|
||||||
case Value:
|
case Value:
|
||||||
instr.(interface {
|
instr.(interface {
|
||||||
setNum(int)
|
setNum(int)
|
||||||
|
|
@ -396,7 +385,7 @@ func (f *Function) debugInfo() bool {
|
||||||
//
|
//
|
||||||
func (f *Function) addNamedLocal(obj types.Object) *Alloc {
|
func (f *Function) addNamedLocal(obj types.Object) *Alloc {
|
||||||
l := f.addLocal(obj.Type(), obj.Pos())
|
l := f.addLocal(obj.Type(), obj.Pos())
|
||||||
l.name = obj.Name()
|
l.Comment = obj.Name()
|
||||||
f.objects[obj] = l
|
f.objects[obj] = l
|
||||||
return 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.
|
// to function f and returns it. pos is the optional source location.
|
||||||
//
|
//
|
||||||
func (f *Function) addLocal(typ types.Type, pos token.Pos) *Alloc {
|
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.Locals = append(f.Locals, v)
|
||||||
f.emit(v)
|
f.emit(v)
|
||||||
return v
|
return v
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ func (v *Alloc) String() string {
|
||||||
if v.Heap {
|
if v.Heap {
|
||||||
op = "new"
|
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 {
|
func (v *Phi) String() string {
|
||||||
|
|
|
||||||
12
ssa/ssa.go
12
ssa/ssa.go
|
|
@ -437,13 +437,10 @@ type Builtin struct {
|
||||||
// t1 = new int
|
// t1 = new int
|
||||||
//
|
//
|
||||||
type Alloc struct {
|
type Alloc struct {
|
||||||
anInstruction
|
Register
|
||||||
name string
|
Comment string
|
||||||
typ types.Type
|
Heap bool
|
||||||
Heap bool
|
index int // dense numbering; for lifting
|
||||||
pos token.Pos
|
|
||||||
referrers []Instruction
|
|
||||||
index int // dense numbering; for lifting
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Phi instruction represents an SSA φ-node, which combines values
|
// 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 *Parameter) Parent() *Function { return v.parent }
|
||||||
|
|
||||||
func (v *Alloc) Type() types.Type { return v.typ }
|
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) Referrers() *[]Instruction { return &v.referrers }
|
||||||
func (v *Alloc) Pos() token.Pos { return v.pos }
|
func (v *Alloc) Pos() token.Pos { return v.pos }
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue