mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.regabi] cmd/compile: add ssa.Aux tag interface for Value.Aux
It's currently hard to automate refactorings around the Value.Aux field, because we don't have any static typing information for it. Adding a tag interface will make subsequent CLs easier and safer. Passes buildall w/ toolstash -cmp. Updates #42982. Change-Id: I41ae8e411a66bda3195a0957b60c2fe8a8002893 Reviewed-on: https://go-review.googlesource.com/c/go/+/275756 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org> Trust: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
63722da46b
commit
1a98ab0e2d
20 changed files with 80 additions and 57 deletions
|
|
@ -43,6 +43,9 @@ var knownFormats = map[string]string{
|
||||||
"cmd/compile/internal/ir.Nodes %+v": "",
|
"cmd/compile/internal/ir.Nodes %+v": "",
|
||||||
"cmd/compile/internal/ir.Nodes %.v": "",
|
"cmd/compile/internal/ir.Nodes %.v": "",
|
||||||
"cmd/compile/internal/ir.Op %+v": "",
|
"cmd/compile/internal/ir.Op %+v": "",
|
||||||
|
"cmd/compile/internal/ssa.Aux %#v": "",
|
||||||
|
"cmd/compile/internal/ssa.Aux %q": "",
|
||||||
|
"cmd/compile/internal/ssa.Aux %s": "",
|
||||||
"cmd/compile/internal/ssa.BranchPrediction %d": "",
|
"cmd/compile/internal/ssa.BranchPrediction %d": "",
|
||||||
"cmd/compile/internal/ssa.ID %d": "",
|
"cmd/compile/internal/ssa.ID %d": "",
|
||||||
"cmd/compile/internal/ssa.LocalSlot %s": "",
|
"cmd/compile/internal/ssa.LocalSlot %s": "",
|
||||||
|
|
|
||||||
|
|
@ -772,7 +772,7 @@ func (s *state) newValue0(op ssa.Op, t *types.Type) *ssa.Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
// newValue0A adds a new value with no arguments and an aux value to the current block.
|
// newValue0A adds a new value with no arguments and an aux value to the current block.
|
||||||
func (s *state) newValue0A(op ssa.Op, t *types.Type, aux interface{}) *ssa.Value {
|
func (s *state) newValue0A(op ssa.Op, t *types.Type, aux ssa.Aux) *ssa.Value {
|
||||||
return s.curBlock.NewValue0A(s.peekPos(), op, t, aux)
|
return s.curBlock.NewValue0A(s.peekPos(), op, t, aux)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -787,14 +787,14 @@ func (s *state) newValue1(op ssa.Op, t *types.Type, arg *ssa.Value) *ssa.Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
// newValue1A adds a new value with one argument and an aux value to the current block.
|
// newValue1A adds a new value with one argument and an aux value to the current block.
|
||||||
func (s *state) newValue1A(op ssa.Op, t *types.Type, aux interface{}, arg *ssa.Value) *ssa.Value {
|
func (s *state) newValue1A(op ssa.Op, t *types.Type, aux ssa.Aux, arg *ssa.Value) *ssa.Value {
|
||||||
return s.curBlock.NewValue1A(s.peekPos(), op, t, aux, arg)
|
return s.curBlock.NewValue1A(s.peekPos(), op, t, aux, arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// newValue1Apos adds a new value with one argument and an aux value to the current block.
|
// newValue1Apos adds a new value with one argument and an aux value to the current block.
|
||||||
// isStmt determines whether the created values may be a statement or not
|
// isStmt determines whether the created values may be a statement or not
|
||||||
// (i.e., false means never, yes means maybe).
|
// (i.e., false means never, yes means maybe).
|
||||||
func (s *state) newValue1Apos(op ssa.Op, t *types.Type, aux interface{}, arg *ssa.Value, isStmt bool) *ssa.Value {
|
func (s *state) newValue1Apos(op ssa.Op, t *types.Type, aux ssa.Aux, arg *ssa.Value, isStmt bool) *ssa.Value {
|
||||||
if isStmt {
|
if isStmt {
|
||||||
return s.curBlock.NewValue1A(s.peekPos(), op, t, aux, arg)
|
return s.curBlock.NewValue1A(s.peekPos(), op, t, aux, arg)
|
||||||
}
|
}
|
||||||
|
|
@ -812,14 +812,14 @@ func (s *state) newValue2(op ssa.Op, t *types.Type, arg0, arg1 *ssa.Value) *ssa.
|
||||||
}
|
}
|
||||||
|
|
||||||
// newValue2A adds a new value with two arguments and an aux value to the current block.
|
// newValue2A adds a new value with two arguments and an aux value to the current block.
|
||||||
func (s *state) newValue2A(op ssa.Op, t *types.Type, aux interface{}, arg0, arg1 *ssa.Value) *ssa.Value {
|
func (s *state) newValue2A(op ssa.Op, t *types.Type, aux ssa.Aux, arg0, arg1 *ssa.Value) *ssa.Value {
|
||||||
return s.curBlock.NewValue2A(s.peekPos(), op, t, aux, arg0, arg1)
|
return s.curBlock.NewValue2A(s.peekPos(), op, t, aux, arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// newValue2Apos adds a new value with two arguments and an aux value to the current block.
|
// newValue2Apos adds a new value with two arguments and an aux value to the current block.
|
||||||
// isStmt determines whether the created values may be a statement or not
|
// isStmt determines whether the created values may be a statement or not
|
||||||
// (i.e., false means never, yes means maybe).
|
// (i.e., false means never, yes means maybe).
|
||||||
func (s *state) newValue2Apos(op ssa.Op, t *types.Type, aux interface{}, arg0, arg1 *ssa.Value, isStmt bool) *ssa.Value {
|
func (s *state) newValue2Apos(op ssa.Op, t *types.Type, aux ssa.Aux, arg0, arg1 *ssa.Value, isStmt bool) *ssa.Value {
|
||||||
if isStmt {
|
if isStmt {
|
||||||
return s.curBlock.NewValue2A(s.peekPos(), op, t, aux, arg0, arg1)
|
return s.curBlock.NewValue2A(s.peekPos(), op, t, aux, arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
@ -842,14 +842,14 @@ func (s *state) newValue3I(op ssa.Op, t *types.Type, aux int64, arg0, arg1, arg2
|
||||||
}
|
}
|
||||||
|
|
||||||
// newValue3A adds a new value with three arguments and an aux value to the current block.
|
// newValue3A adds a new value with three arguments and an aux value to the current block.
|
||||||
func (s *state) newValue3A(op ssa.Op, t *types.Type, aux interface{}, arg0, arg1, arg2 *ssa.Value) *ssa.Value {
|
func (s *state) newValue3A(op ssa.Op, t *types.Type, aux ssa.Aux, arg0, arg1, arg2 *ssa.Value) *ssa.Value {
|
||||||
return s.curBlock.NewValue3A(s.peekPos(), op, t, aux, arg0, arg1, arg2)
|
return s.curBlock.NewValue3A(s.peekPos(), op, t, aux, arg0, arg1, arg2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// newValue3Apos adds a new value with three arguments and an aux value to the current block.
|
// newValue3Apos adds a new value with three arguments and an aux value to the current block.
|
||||||
// isStmt determines whether the created values may be a statement or not
|
// isStmt determines whether the created values may be a statement or not
|
||||||
// (i.e., false means never, yes means maybe).
|
// (i.e., false means never, yes means maybe).
|
||||||
func (s *state) newValue3Apos(op ssa.Op, t *types.Type, aux interface{}, arg0, arg1, arg2 *ssa.Value, isStmt bool) *ssa.Value {
|
func (s *state) newValue3Apos(op ssa.Op, t *types.Type, aux ssa.Aux, arg0, arg1, arg2 *ssa.Value, isStmt bool) *ssa.Value {
|
||||||
if isStmt {
|
if isStmt {
|
||||||
return s.curBlock.NewValue3A(s.peekPos(), op, t, aux, arg0, arg1, arg2)
|
return s.curBlock.NewValue3A(s.peekPos(), op, t, aux, arg0, arg1, arg2)
|
||||||
}
|
}
|
||||||
|
|
@ -872,7 +872,7 @@ func (s *state) entryNewValue0(op ssa.Op, t *types.Type) *ssa.Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
// entryNewValue0A adds a new value with no arguments and an aux value to the entry block.
|
// entryNewValue0A adds a new value with no arguments and an aux value to the entry block.
|
||||||
func (s *state) entryNewValue0A(op ssa.Op, t *types.Type, aux interface{}) *ssa.Value {
|
func (s *state) entryNewValue0A(op ssa.Op, t *types.Type, aux ssa.Aux) *ssa.Value {
|
||||||
return s.f.Entry.NewValue0A(src.NoXPos, op, t, aux)
|
return s.f.Entry.NewValue0A(src.NoXPos, op, t, aux)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -887,7 +887,7 @@ func (s *state) entryNewValue1I(op ssa.Op, t *types.Type, auxint int64, arg *ssa
|
||||||
}
|
}
|
||||||
|
|
||||||
// entryNewValue1A adds a new value with one argument and an aux value to the entry block.
|
// entryNewValue1A adds a new value with one argument and an aux value to the entry block.
|
||||||
func (s *state) entryNewValue1A(op ssa.Op, t *types.Type, aux interface{}, arg *ssa.Value) *ssa.Value {
|
func (s *state) entryNewValue1A(op ssa.Op, t *types.Type, aux ssa.Aux, arg *ssa.Value) *ssa.Value {
|
||||||
return s.f.Entry.NewValue1A(src.NoXPos, op, t, aux, arg)
|
return s.f.Entry.NewValue1A(src.NoXPos, op, t, aux, arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -897,7 +897,7 @@ func (s *state) entryNewValue2(op ssa.Op, t *types.Type, arg0, arg1 *ssa.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// entryNewValue2A adds a new value with two arguments and an aux value to the entry block.
|
// entryNewValue2A adds a new value with two arguments and an aux value to the entry block.
|
||||||
func (s *state) entryNewValue2A(op ssa.Op, t *types.Type, aux interface{}, arg0, arg1 *ssa.Value) *ssa.Value {
|
func (s *state) entryNewValue2A(op ssa.Op, t *types.Type, aux ssa.Aux, arg0, arg1 *ssa.Value) *ssa.Value {
|
||||||
return s.f.Entry.NewValue2A(src.NoXPos, op, t, aux, arg0, arg1)
|
return s.f.Entry.NewValue2A(src.NoXPos, op, t, aux, arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2060,7 +2060,7 @@ func (s *state) expr(n ir.Node) *ssa.Value {
|
||||||
if i == "" {
|
if i == "" {
|
||||||
return s.constEmptyString(n.Type())
|
return s.constEmptyString(n.Type())
|
||||||
}
|
}
|
||||||
return s.entryNewValue0A(ssa.OpConstString, n.Type(), i)
|
return s.entryNewValue0A(ssa.OpConstString, n.Type(), ssa.StringToAux(i))
|
||||||
case constant.Bool:
|
case constant.Bool:
|
||||||
return s.constBool(constant.BoolVal(u))
|
return s.constBool(constant.BoolVal(u))
|
||||||
case constant.Float:
|
case constant.Float:
|
||||||
|
|
|
||||||
|
|
@ -198,5 +198,6 @@ func (n *miniNode) MarkReadonly() { panic(n.no("MarkReadonly")) }
|
||||||
func (n *miniNode) TChanDir() types.ChanDir { panic(n.no("TChanDir")) }
|
func (n *miniNode) TChanDir() types.ChanDir { panic(n.no("TChanDir")) }
|
||||||
func (n *miniNode) SetTChanDir(types.ChanDir) { panic(n.no("SetTChanDir")) }
|
func (n *miniNode) SetTChanDir(types.ChanDir) { panic(n.no("SetTChanDir")) }
|
||||||
|
|
||||||
// TODO: Delete when CanBeAnSSASym is removed from Node itself.
|
// TODO: Delete when these are removed from Node itself.
|
||||||
func (*miniNode) CanBeAnSSASym() {}
|
func (*miniNode) CanBeAnSSASym() {}
|
||||||
|
func (*miniNode) CanBeAnSSAAux() {}
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,7 @@ type Node interface {
|
||||||
// Only for SSA and should be removed when SSA starts
|
// Only for SSA and should be removed when SSA starts
|
||||||
// using a more specific type than Node.
|
// using a more specific type than Node.
|
||||||
CanBeAnSSASym()
|
CanBeAnSSASym()
|
||||||
|
CanBeAnSSAAux()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Line returns n's position as a string. If n has been inlined,
|
// Line returns n's position as a string. If n has been inlined,
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ type Block struct {
|
||||||
Controls [2]*Value
|
Controls [2]*Value
|
||||||
|
|
||||||
// Auxiliary info for the block. Its value depends on the Kind.
|
// Auxiliary info for the block. Its value depends on the Kind.
|
||||||
Aux interface{}
|
Aux Aux
|
||||||
AuxInt int64
|
AuxInt int64
|
||||||
|
|
||||||
// The unordered set of Values that define the operation of this block.
|
// The unordered set of Values that define the operation of this block.
|
||||||
|
|
|
||||||
|
|
@ -161,7 +161,7 @@ func checkFunc(f *Func) {
|
||||||
f.Fatalf("value %v has an AuxInt that encodes a NaN", v)
|
f.Fatalf("value %v has an AuxInt that encodes a NaN", v)
|
||||||
}
|
}
|
||||||
case auxString:
|
case auxString:
|
||||||
if _, ok := v.Aux.(string); !ok {
|
if _, ok := v.Aux.(stringAux); !ok {
|
||||||
f.Fatalf("value %v has Aux type %T, want string", v, v.Aux)
|
f.Fatalf("value %v has Aux type %T, want string", v, v.Aux)
|
||||||
}
|
}
|
||||||
canHaveAux = true
|
canHaveAux = true
|
||||||
|
|
|
||||||
|
|
@ -275,7 +275,7 @@ func lt2Cmp(isLt bool) types.Cmp {
|
||||||
return types.CMPgt
|
return types.CMPgt
|
||||||
}
|
}
|
||||||
|
|
||||||
type auxmap map[interface{}]int32
|
type auxmap map[Aux]int32
|
||||||
|
|
||||||
func cmpVal(v, w *Value, auxIDs auxmap) types.Cmp {
|
func cmpVal(v, w *Value, auxIDs auxmap) types.Cmp {
|
||||||
// Try to order these comparison by cost (cheaper first)
|
// Try to order these comparison by cost (cheaper first)
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ type tstAux struct {
|
||||||
s string
|
s string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (*tstAux) CanBeAnSSAAux() {}
|
||||||
|
|
||||||
// This tests for a bug found when partitioning, but not sorting by the Aux value.
|
// This tests for a bug found when partitioning, but not sorting by the Aux value.
|
||||||
func TestCSEAuxPartitionBug(t *testing.T) {
|
func TestCSEAuxPartitionBug(t *testing.T) {
|
||||||
c := testConfig(t)
|
c := testConfig(t)
|
||||||
|
|
|
||||||
|
|
@ -143,13 +143,13 @@ func (loc VarLoc) absent() bool {
|
||||||
var BlockStart = &Value{
|
var BlockStart = &Value{
|
||||||
ID: -10000,
|
ID: -10000,
|
||||||
Op: OpInvalid,
|
Op: OpInvalid,
|
||||||
Aux: "BlockStart",
|
Aux: StringToAux("BlockStart"),
|
||||||
}
|
}
|
||||||
|
|
||||||
var BlockEnd = &Value{
|
var BlockEnd = &Value{
|
||||||
ID: -20000,
|
ID: -20000,
|
||||||
Op: OpInvalid,
|
Op: OpInvalid,
|
||||||
Aux: "BlockEnd",
|
Aux: StringToAux("BlockEnd"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterSet is a bitmap of registers, indexed by Register.num.
|
// RegisterSet is a bitmap of registers, indexed by Register.num.
|
||||||
|
|
|
||||||
|
|
@ -377,13 +377,7 @@ func (b *Block) NewValue0I(pos src.XPos, op Op, t *types.Type, auxint int64) *Va
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewValue returns a new value in the block with no arguments and an aux value.
|
// NewValue returns a new value in the block with no arguments and an aux value.
|
||||||
func (b *Block) NewValue0A(pos src.XPos, op Op, t *types.Type, aux interface{}) *Value {
|
func (b *Block) NewValue0A(pos src.XPos, op Op, t *types.Type, aux Aux) *Value {
|
||||||
if _, ok := aux.(int64); ok {
|
|
||||||
// Disallow int64 aux values. They should be in the auxint field instead.
|
|
||||||
// Maybe we want to allow this at some point, but for now we disallow it
|
|
||||||
// to prevent errors like using NewValue1A instead of NewValue1I.
|
|
||||||
b.Fatalf("aux field has int64 type op=%s type=%s aux=%v", op, t, aux)
|
|
||||||
}
|
|
||||||
v := b.Func.newValue(op, t, b, pos)
|
v := b.Func.newValue(op, t, b, pos)
|
||||||
v.AuxInt = 0
|
v.AuxInt = 0
|
||||||
v.Aux = aux
|
v.Aux = aux
|
||||||
|
|
@ -392,7 +386,7 @@ func (b *Block) NewValue0A(pos src.XPos, op Op, t *types.Type, aux interface{})
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewValue returns a new value in the block with no arguments and both an auxint and aux values.
|
// NewValue returns a new value in the block with no arguments and both an auxint and aux values.
|
||||||
func (b *Block) NewValue0IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux interface{}) *Value {
|
func (b *Block) NewValue0IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux Aux) *Value {
|
||||||
v := b.Func.newValue(op, t, b, pos)
|
v := b.Func.newValue(op, t, b, pos)
|
||||||
v.AuxInt = auxint
|
v.AuxInt = auxint
|
||||||
v.Aux = aux
|
v.Aux = aux
|
||||||
|
|
@ -421,7 +415,7 @@ func (b *Block) NewValue1I(pos src.XPos, op Op, t *types.Type, auxint int64, arg
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewValue1A returns a new value in the block with one argument and an aux value.
|
// NewValue1A returns a new value in the block with one argument and an aux value.
|
||||||
func (b *Block) NewValue1A(pos src.XPos, op Op, t *types.Type, aux interface{}, arg *Value) *Value {
|
func (b *Block) NewValue1A(pos src.XPos, op Op, t *types.Type, aux Aux, arg *Value) *Value {
|
||||||
v := b.Func.newValue(op, t, b, pos)
|
v := b.Func.newValue(op, t, b, pos)
|
||||||
v.AuxInt = 0
|
v.AuxInt = 0
|
||||||
v.Aux = aux
|
v.Aux = aux
|
||||||
|
|
@ -432,7 +426,7 @@ func (b *Block) NewValue1A(pos src.XPos, op Op, t *types.Type, aux interface{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewValue1IA returns a new value in the block with one argument and both an auxint and aux values.
|
// NewValue1IA returns a new value in the block with one argument and both an auxint and aux values.
|
||||||
func (b *Block) NewValue1IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux interface{}, arg *Value) *Value {
|
func (b *Block) NewValue1IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux Aux, arg *Value) *Value {
|
||||||
v := b.Func.newValue(op, t, b, pos)
|
v := b.Func.newValue(op, t, b, pos)
|
||||||
v.AuxInt = auxint
|
v.AuxInt = auxint
|
||||||
v.Aux = aux
|
v.Aux = aux
|
||||||
|
|
@ -455,7 +449,7 @@ func (b *Block) NewValue2(pos src.XPos, op Op, t *types.Type, arg0, arg1 *Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewValue2A returns a new value in the block with two arguments and one aux values.
|
// NewValue2A returns a new value in the block with two arguments and one aux values.
|
||||||
func (b *Block) NewValue2A(pos src.XPos, op Op, t *types.Type, aux interface{}, arg0, arg1 *Value) *Value {
|
func (b *Block) NewValue2A(pos src.XPos, op Op, t *types.Type, aux Aux, arg0, arg1 *Value) *Value {
|
||||||
v := b.Func.newValue(op, t, b, pos)
|
v := b.Func.newValue(op, t, b, pos)
|
||||||
v.AuxInt = 0
|
v.AuxInt = 0
|
||||||
v.Aux = aux
|
v.Aux = aux
|
||||||
|
|
@ -480,7 +474,7 @@ func (b *Block) NewValue2I(pos src.XPos, op Op, t *types.Type, auxint int64, arg
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewValue2IA returns a new value in the block with two arguments and both an auxint and aux values.
|
// NewValue2IA returns a new value in the block with two arguments and both an auxint and aux values.
|
||||||
func (b *Block) NewValue2IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux interface{}, arg0, arg1 *Value) *Value {
|
func (b *Block) NewValue2IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux Aux, arg0, arg1 *Value) *Value {
|
||||||
v := b.Func.newValue(op, t, b, pos)
|
v := b.Func.newValue(op, t, b, pos)
|
||||||
v.AuxInt = auxint
|
v.AuxInt = auxint
|
||||||
v.Aux = aux
|
v.Aux = aux
|
||||||
|
|
@ -521,7 +515,7 @@ func (b *Block) NewValue3I(pos src.XPos, op Op, t *types.Type, auxint int64, arg
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewValue3A returns a new value in the block with three argument and an aux value.
|
// NewValue3A returns a new value in the block with three argument and an aux value.
|
||||||
func (b *Block) NewValue3A(pos src.XPos, op Op, t *types.Type, aux interface{}, arg0, arg1, arg2 *Value) *Value {
|
func (b *Block) NewValue3A(pos src.XPos, op Op, t *types.Type, aux Aux, arg0, arg1, arg2 *Value) *Value {
|
||||||
v := b.Func.newValue(op, t, b, pos)
|
v := b.Func.newValue(op, t, b, pos)
|
||||||
v.AuxInt = 0
|
v.AuxInt = 0
|
||||||
v.Aux = aux
|
v.Aux = aux
|
||||||
|
|
@ -633,7 +627,7 @@ func (f *Func) ConstNil(t *types.Type) *Value {
|
||||||
}
|
}
|
||||||
func (f *Func) ConstEmptyString(t *types.Type) *Value {
|
func (f *Func) ConstEmptyString(t *types.Type) *Value {
|
||||||
v := f.constVal(OpConstString, t, constEmptyStringMagic, false)
|
v := f.constVal(OpConstString, t, constEmptyStringMagic, false)
|
||||||
v.Aux = ""
|
v.Aux = StringToAux("")
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
func (f *Func) ConstOffPtrSP(t *types.Type, c int64, sp *Value) *Value {
|
func (f *Func) ConstOffPtrSP(t *types.Type, c int64, sp *Value) *Value {
|
||||||
|
|
|
||||||
|
|
@ -232,7 +232,7 @@ func Bloc(name string, entries ...interface{}) bloc {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Valu defines a value in a block.
|
// Valu defines a value in a block.
|
||||||
func Valu(name string, op Op, t *types.Type, auxint int64, aux interface{}, args ...string) valu {
|
func Valu(name string, op Op, t *types.Type, auxint int64, aux Aux, args ...string) valu {
|
||||||
return valu{name, op, t, auxint, aux, args}
|
return valu{name, op, t, auxint, aux, args}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -277,7 +277,7 @@ type valu struct {
|
||||||
op Op
|
op Op
|
||||||
t *types.Type
|
t *types.Type
|
||||||
auxint int64
|
auxint int64
|
||||||
aux interface{}
|
aux Aux
|
||||||
args []string
|
args []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -402,12 +402,12 @@ func TestEquiv(t *testing.T) {
|
||||||
cfg.Fun("entry",
|
cfg.Fun("entry",
|
||||||
Bloc("entry",
|
Bloc("entry",
|
||||||
Valu("mem", OpInitMem, types.TypeMem, 0, nil),
|
Valu("mem", OpInitMem, types.TypeMem, 0, nil),
|
||||||
Valu("a", OpConst64, cfg.config.Types.Int64, 0, 14),
|
Valu("a", OpConstString, cfg.config.Types.String, 0, StringToAux("foo")),
|
||||||
Exit("mem"))),
|
Exit("mem"))),
|
||||||
cfg.Fun("entry",
|
cfg.Fun("entry",
|
||||||
Bloc("entry",
|
Bloc("entry",
|
||||||
Valu("mem", OpInitMem, types.TypeMem, 0, nil),
|
Valu("mem", OpInitMem, types.TypeMem, 0, nil),
|
||||||
Valu("a", OpConst64, cfg.config.Types.Int64, 0, 26),
|
Valu("a", OpConstString, cfg.config.Types.String, 0, StringToAux("bar")),
|
||||||
Exit("mem"))),
|
Exit("mem"))),
|
||||||
},
|
},
|
||||||
// value args different
|
// value args different
|
||||||
|
|
|
||||||
|
|
@ -212,7 +212,7 @@ func TestNilcheckPhi(t *testing.T) {
|
||||||
Valu("mem", OpInitMem, types.TypeMem, 0, nil),
|
Valu("mem", OpInitMem, types.TypeMem, 0, nil),
|
||||||
Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
|
Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
|
||||||
Valu("sp", OpSP, c.config.Types.Uintptr, 0, nil),
|
Valu("sp", OpSP, c.config.Types.Uintptr, 0, nil),
|
||||||
Valu("baddr", OpLocalAddr, c.config.Types.Bool, 0, "b", "sp", "mem"),
|
Valu("baddr", OpLocalAddr, c.config.Types.Bool, 0, StringToAux("b"), "sp", "mem"),
|
||||||
Valu("bool1", OpLoad, c.config.Types.Bool, 0, nil, "baddr", "mem"),
|
Valu("bool1", OpLoad, c.config.Types.Bool, 0, nil, "baddr", "mem"),
|
||||||
If("bool1", "b1", "b2")),
|
If("bool1", "b1", "b2")),
|
||||||
Bloc("b1",
|
Bloc("b1",
|
||||||
|
|
|
||||||
|
|
@ -197,6 +197,8 @@ func ClosureAuxCall(args []Param, results []Param) *AuxCall {
|
||||||
return &AuxCall{Fn: nil, args: args, results: results}
|
return &AuxCall{Fn: nil, args: args, results: results}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (*AuxCall) CanBeAnSSAAux() {}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
auxNone auxType = iota
|
auxNone auxType = iota
|
||||||
auxBool // auxInt is 0/1 for false/true
|
auxBool // auxInt is 0/1 for false/true
|
||||||
|
|
@ -248,6 +250,7 @@ const (
|
||||||
type Sym interface {
|
type Sym interface {
|
||||||
String() string
|
String() string
|
||||||
CanBeAnSSASym()
|
CanBeAnSSASym()
|
||||||
|
CanBeAnSSAAux()
|
||||||
}
|
}
|
||||||
|
|
||||||
// A ValAndOff is used by the several opcodes. It holds
|
// A ValAndOff is used by the several opcodes. It holds
|
||||||
|
|
|
||||||
|
|
@ -678,43 +678,53 @@ func opToAuxInt(o Op) int64 {
|
||||||
return int64(o)
|
return int64(o)
|
||||||
}
|
}
|
||||||
|
|
||||||
func auxToString(i interface{}) string {
|
// Aux is an interface to hold miscellaneous data in Blocks and Values.
|
||||||
return i.(string)
|
type Aux interface {
|
||||||
|
CanBeAnSSAAux()
|
||||||
}
|
}
|
||||||
func auxToSym(i interface{}) Sym {
|
|
||||||
|
// stringAux wraps string values for use in Aux.
|
||||||
|
type stringAux string
|
||||||
|
|
||||||
|
func (stringAux) CanBeAnSSAAux() {}
|
||||||
|
|
||||||
|
func auxToString(i Aux) string {
|
||||||
|
return string(i.(stringAux))
|
||||||
|
}
|
||||||
|
func auxToSym(i Aux) Sym {
|
||||||
// TODO: kind of a hack - allows nil interface through
|
// TODO: kind of a hack - allows nil interface through
|
||||||
s, _ := i.(Sym)
|
s, _ := i.(Sym)
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
func auxToType(i interface{}) *types.Type {
|
func auxToType(i Aux) *types.Type {
|
||||||
return i.(*types.Type)
|
return i.(*types.Type)
|
||||||
}
|
}
|
||||||
func auxToCall(i interface{}) *AuxCall {
|
func auxToCall(i Aux) *AuxCall {
|
||||||
return i.(*AuxCall)
|
return i.(*AuxCall)
|
||||||
}
|
}
|
||||||
func auxToS390xCCMask(i interface{}) s390x.CCMask {
|
func auxToS390xCCMask(i Aux) s390x.CCMask {
|
||||||
return i.(s390x.CCMask)
|
return i.(s390x.CCMask)
|
||||||
}
|
}
|
||||||
func auxToS390xRotateParams(i interface{}) s390x.RotateParams {
|
func auxToS390xRotateParams(i Aux) s390x.RotateParams {
|
||||||
return i.(s390x.RotateParams)
|
return i.(s390x.RotateParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
func stringToAux(s string) interface{} {
|
func StringToAux(s string) Aux {
|
||||||
|
return stringAux(s)
|
||||||
|
}
|
||||||
|
func symToAux(s Sym) Aux {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
func symToAux(s Sym) interface{} {
|
func callToAux(s *AuxCall) Aux {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
func callToAux(s *AuxCall) interface{} {
|
func typeToAux(t *types.Type) Aux {
|
||||||
return s
|
|
||||||
}
|
|
||||||
func typeToAux(t *types.Type) interface{} {
|
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
func s390xCCMaskToAux(c s390x.CCMask) interface{} {
|
func s390xCCMaskToAux(c s390x.CCMask) Aux {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
func s390xRotateParamsToAux(r s390x.RotateParams) interface{} {
|
func s390xRotateParamsToAux(r s390x.RotateParams) Aux {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -725,7 +735,7 @@ func uaddOvf(a, b int64) bool {
|
||||||
|
|
||||||
// de-virtualize an InterCall
|
// de-virtualize an InterCall
|
||||||
// 'sym' is the symbol for the itab
|
// 'sym' is the symbol for the itab
|
||||||
func devirt(v *Value, aux interface{}, sym Sym, offset int64) *AuxCall {
|
func devirt(v *Value, aux Aux, sym Sym, offset int64) *AuxCall {
|
||||||
f := v.Block.Func
|
f := v.Block.Func
|
||||||
n, ok := sym.(*obj.LSym)
|
n, ok := sym.(*obj.LSym)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
@ -748,7 +758,7 @@ func devirt(v *Value, aux interface{}, sym Sym, offset int64) *AuxCall {
|
||||||
|
|
||||||
// de-virtualize an InterLECall
|
// de-virtualize an InterLECall
|
||||||
// 'sym' is the symbol for the itab
|
// 'sym' is the symbol for the itab
|
||||||
func devirtLESym(v *Value, aux interface{}, sym Sym, offset int64) *obj.LSym {
|
func devirtLESym(v *Value, aux Aux, sym Sym, offset int64) *obj.LSym {
|
||||||
n, ok := sym.(*obj.LSym)
|
n, ok := sym.(*obj.LSym)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ type Value struct {
|
||||||
// Users of AuxInt which interpret AuxInt as unsigned (e.g. shifts) must be careful.
|
// Users of AuxInt which interpret AuxInt as unsigned (e.g. shifts) must be careful.
|
||||||
// Use Value.AuxUnsigned to get the zero-extended value of AuxInt.
|
// Use Value.AuxUnsigned to get the zero-extended value of AuxInt.
|
||||||
AuxInt int64
|
AuxInt int64
|
||||||
Aux interface{}
|
Aux Aux
|
||||||
|
|
||||||
// Arguments of this value
|
// Arguments of this value
|
||||||
Args []*Value
|
Args []*Value
|
||||||
|
|
@ -492,3 +492,6 @@ func (v *Value) removeable() bool {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(mdempsky): Shouldn't be necessary; see discussion at golang.org/cl/275756
|
||||||
|
func (*Value) CanBeAnSSAAux() {}
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ func zcse(f *Func) {
|
||||||
type vkey struct {
|
type vkey struct {
|
||||||
op Op
|
op Op
|
||||||
ai int64 // aux int
|
ai int64 // aux int
|
||||||
ax interface{} // aux
|
ax Aux // aux
|
||||||
t *types.Type // type
|
t *types.Type // type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -164,6 +164,8 @@ type Type struct {
|
||||||
flags bitset8
|
flags bitset8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (*Type) CanBeAnSSAAux() {}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typeNotInHeap = 1 << iota // type cannot be heap allocated
|
typeNotInHeap = 1 << iota // type cannot be heap allocated
|
||||||
typeBroke // broken type definition
|
typeBroke // broken type definition
|
||||||
|
|
|
||||||
|
|
@ -723,8 +723,8 @@ func (s *LSym) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// The compiler needs *LSym to be assignable to cmd/compile/internal/ssa.Sym.
|
// The compiler needs *LSym to be assignable to cmd/compile/internal/ssa.Sym.
|
||||||
func (s *LSym) CanBeAnSSASym() {
|
func (*LSym) CanBeAnSSASym() {}
|
||||||
}
|
func (*LSym) CanBeAnSSAAux() {}
|
||||||
|
|
||||||
type Pcln struct {
|
type Pcln struct {
|
||||||
// Aux symbols for pcln
|
// Aux symbols for pcln
|
||||||
|
|
|
||||||
|
|
@ -124,3 +124,5 @@ func (c CCMask) String() string {
|
||||||
// invalid
|
// invalid
|
||||||
return fmt.Sprintf("Invalid (%#x)", c)
|
return fmt.Sprintf("Invalid (%#x)", c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (CCMask) CanBeAnSSAAux() {}
|
||||||
|
|
|
||||||
|
|
@ -113,3 +113,5 @@ func (r RotateParams) OutMerge(mask uint64) *RotateParams {
|
||||||
func (r RotateParams) InMerge(mask uint64) *RotateParams {
|
func (r RotateParams) InMerge(mask uint64) *RotateParams {
|
||||||
return r.OutMerge(bits.RotateLeft64(mask, int(r.Amount)))
|
return r.OutMerge(bits.RotateLeft64(mask, int(r.Amount)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (RotateParams) CanBeAnSSAAux() {}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue