mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
First pass adding code for SSA backend. It is standalone for now. I've included just a few passes to make the review size manageable - I have more passes coming. cmd/internal/ssa is the library containing the ssa compiler proper. cmd/internal/ssa/ssac is a driver that loads an sexpr-based IR, converts it to SSA form, and calls the above library. It is essentially throwaway code - it will disappear once the Go compiler calls cmd/internal/ssa itself. The .goir files in ssac/ are dumps of fibonacci programs I made from a hacked-up compiler. They are just for testing. Change-Id: I5ee89356ec12c87cd916681097cd3c2cd591040c Reviewed-on: https://go-review.googlesource.com/6681 Reviewed-by: Alan Donovan <adonovan@google.com>
117 lines
2.8 KiB
Go
117 lines
2.8 KiB
Go
// 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"
|
|
"strings"
|
|
)
|
|
|
|
// 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 0. 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 (& type).
|
|
Aux interface{}
|
|
|
|
// Arguments of this value
|
|
Args []*Value
|
|
|
|
// Containing basic block
|
|
Block *Block
|
|
|
|
// Storage for the first two args
|
|
argstorage [2]*Value
|
|
}
|
|
|
|
// Examples:
|
|
// Opcode aux args
|
|
// OpAdd nil 2
|
|
// OpConstStr string 0
|
|
// OpConstInt int64 0
|
|
// OpAddcq int64 1 amd64 op: v = arg[0] + constant
|
|
|
|
// short form print. Just v#.
|
|
func (v *Value) String() string {
|
|
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, strings.TrimPrefix(v.Op.String(), "Op"))
|
|
s += " <" + v.Type.String() + ">"
|
|
if v.Aux != nil {
|
|
s += fmt.Sprintf(" [%v]", v.Aux)
|
|
}
|
|
for _, a := range v.Args {
|
|
s += fmt.Sprintf(" %v", a)
|
|
}
|
|
r := v.Block.Func.RegAlloc
|
|
if r != nil && r[v.ID] != nil {
|
|
s += " : " + r[v.ID].Name()
|
|
}
|
|
return s
|
|
}
|
|
|
|
func (v *Value) AddArg(w *Value) {
|
|
v.Args = append(v.Args, w)
|
|
}
|
|
func (v *Value) AddArgs(a ...*Value) {
|
|
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 = 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]
|
|
}
|
|
|
|
// CopyFrom converts v to be the same value as w. v and w must
|
|
// have the same type.
|
|
func (v *Value) CopyFrom(w *Value) {
|
|
if !typeIdentical(v.Type, w.Type) {
|
|
panic("copyFrom with unequal types")
|
|
}
|
|
v.Op = w.Op
|
|
v.Aux = w.Aux
|
|
v.resetArgs()
|
|
v.AddArgs(w.Args...)
|
|
}
|
|
|
|
// SetType sets the type of v. v must not have had its type
|
|
// set yet (it must be TypeInvalid).
|
|
func (v *Value) SetType() {
|
|
if v.Type != TypeInvalid {
|
|
panic("setting type when it is already set")
|
|
}
|
|
opcodeTable[v.Op].typer(v)
|
|
}
|