go/src/cmd/compile/internal/ssa/value.go

169 lines
4.5 KiB
Go
Raw Normal View History

// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ssa
import (
"fmt"
"math"
)
// A Value represents a value in the SSA representation of the program.
// The ID and Type fields must not be modified. The remainder may be modified
// if they preserve the value of the Value (e.g. changing a (mul 2 x) to an (add x x)).
type Value struct {
// A unique identifier for the value. For performance we allocate these IDs
// densely starting at 1. There is no guarantee that there won't be occasional holes, though.
ID ID
// The operation that computes this value. See op.go.
Op Op
// The type of this value. Normally this will be a Go type, but there
// are a few other pseudo-types, see type.go.
Type Type
// Auxiliary info for this value. The type of this information depends on the opcode and type.
// AuxInt is used for integer values, Aux is used for other values.
AuxInt int64
Aux interface{}
// Arguments of this value
Args []*Value
// Containing basic block
Block *Block
// Source line number
Line int32
// Storage for the first two args
argstorage [2]*Value
}
// Examples:
// Opcode aux args
// OpAdd nil 2
// OpConst string 0 string constant
// OpConst int64 0 int64 constant
// OpAddcq int64 1 amd64 op: v = arg[0] + constant
// short form print. Just v#.
func (v *Value) String() string {
if v == nil {
return "nil" // should never happen, but not panicking helps with debugging
}
return fmt.Sprintf("v%d", v.ID)
}
// long form print. v# = opcode <type> [aux] args [: reg]
func (v *Value) LongString() string {
s := fmt.Sprintf("v%d = %s", v.ID, v.Op.String())
s += " <" + v.Type.String() + ">"
if v.AuxInt != 0 {
s += fmt.Sprintf(" [%d]", v.AuxInt)
switch {
case v.Op == OpConst32F || v.Op == OpConst64F:
s += fmt.Sprintf("(%g)", math.Float64frombits(uint64(v.AuxInt)))
case v.Op == OpConstBool && v.AuxInt == 0:
s += " (false)"
case v.Op == OpConstBool && v.AuxInt == 1:
s += " (true)"
}
}
if v.Aux != nil {
if _, ok := v.Aux.(string); ok {
s += fmt.Sprintf(" {%q}", v.Aux)
} else {
s += fmt.Sprintf(" {%v}", v.Aux)
}
}
for _, a := range v.Args {
s += fmt.Sprintf(" %v", a)
}
r := v.Block.Func.RegAlloc
if int(v.ID) < len(r) && r[v.ID] != nil {
s += " : " + r[v.ID].Name()
}
return s
}
func (v *Value) AddArg(w *Value) {
if v.Args == nil {
v.resetArgs() // use argstorage
}
v.Args = append(v.Args, w)
}
func (v *Value) AddArgs(a ...*Value) {
if v.Args == nil {
v.resetArgs() // use argstorage
}
v.Args = append(v.Args, a...)
}
func (v *Value) SetArg(i int, w *Value) {
v.Args[i] = w
}
func (v *Value) RemoveArg(i int) {
copy(v.Args[i:], v.Args[i+1:])
v.Args[len(v.Args)-1] = nil // aid GC
v.Args = v.Args[:len(v.Args)-1]
}
func (v *Value) SetArgs1(a *Value) {
v.resetArgs()
v.AddArg(a)
}
func (v *Value) SetArgs2(a *Value, b *Value) {
v.resetArgs()
v.AddArg(a)
v.AddArg(b)
}
func (v *Value) resetArgs() {
v.argstorage[0] = nil
v.argstorage[1] = nil
v.Args = v.argstorage[:0]
}
[dev.ssa] cmd/compile/ssa: separate logging, work in progress, and fatal errors The SSA implementation logs for three purposes: * debug logging * fatal errors * unimplemented features Separating these three uses lets us attempt an SSA implementation for all functions, not just _ssa functions. This turns the entire standard library into a compilation test, and makes it easy to figure out things like "how much coverage does SSA have now" and "what should we do next to get more coverage?". Functions called _ssa are still special. They log profusely by default and the output of the SSA implementation is used. For all other functions, logging is off, and the implementation is built and discarded, due to lack of support for the runtime. While we're here, fix a few minor bugs and add some extra Unimplementeds to allow all.bash to pass. As of now, SSA handles 20.79% of the functions in the standard library (689 of 3314). The top missing features are: 10.03% 2597 SSA unimplemented: zero for type error not implemented 7.79% 2016 SSA unimplemented: addr: bad op DOTPTR 7.33% 1898 SSA unimplemented: unhandled expr EQ 6.10% 1579 SSA unimplemented: unhandled expr OROR 4.91% 1271 SSA unimplemented: unhandled expr NE 4.49% 1163 SSA unimplemented: unhandled expr LROT 4.00% 1036 SSA unimplemented: unhandled expr LEN 3.56% 923 SSA unimplemented: unhandled stmt CALLFUNC 2.37% 615 SSA unimplemented: zero for type []byte not implemented 1.90% 492 SSA unimplemented: unhandled stmt CALLMETH 1.74% 450 SSA unimplemented: unhandled expr CALLINTER 1.74% 450 SSA unimplemented: unhandled expr DOT 1.71% 444 SSA unimplemented: unhandled expr ANDAND 1.65% 426 SSA unimplemented: unhandled expr CLOSUREVAR 1.54% 400 SSA unimplemented: unhandled expr CALLMETH 1.51% 390 SSA unimplemented: unhandled stmt SWITCH 1.47% 380 SSA unimplemented: unhandled expr CONV 1.33% 345 SSA unimplemented: addr: bad op * 1.30% 336 SSA unimplemented: unhandled OLITERAL 6 Change-Id: I4ca07951e276714dc13c31de28640aead17a1be7 Reviewed-on: https://go-review.googlesource.com/11160 Reviewed-by: Keith Randall <khr@golang.org>
2015-06-12 11:01:13 -07:00
func (v *Value) Logf(msg string, args ...interface{}) { v.Block.Logf(msg, args...) }
func (v *Value) Fatalf(msg string, args ...interface{}) { v.Block.Fatalf(msg, args...) }
func (v *Value) Unimplementedf(msg string, args ...interface{}) { v.Block.Unimplementedf(msg, args...) }
// ExternSymbol is an aux value that encodes a variable's
// constant offset from the static base pointer.
type ExternSymbol struct {
Typ Type // Go type
Sym fmt.Stringer // A *gc.Sym referring to a global variable
// Note: the offset for an external symbol is not
// calculated until link time.
}
// ArgSymbol is an aux value that encodes an argument or result
// variable's constant offset from FP (FP = SP + framesize).
type ArgSymbol struct {
Typ Type // Go type
Offset int64 // Distance above frame pointer
Sym fmt.Stringer // A *gc.Sym referring to the argument/result variable.
}
// AutoSymbol is an aux value that encodes a local variable's
// constant offset from SP.
type AutoSymbol struct {
Typ Type // Go type
Offset int64 // Distance above stack pointer. Set by stackalloc in SSA.
Sym fmt.Stringer // A *gc.Sym referring to a local (auto) variable.
}
func (s *ExternSymbol) String() string {
return s.Sym.String()
}
func (s *ArgSymbol) String() string {
return s.Sym.String()
}
func (s *AutoSymbol) String() string {
return s.Sym.String()
}