mirror of
https://github.com/golang/go
synced 2024-10-05 20:31:20 -06:00
[dev.ssa] cmd/compile/internal/ssa: implement ORETJMP
Change-Id: I352c7b9aab053959bc74c15861339e1dbe545ddc Reviewed-on: https://go-review.googlesource.com/14404 Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
parent
fd8c71be86
commit
8a1f6217c5
@ -583,6 +583,14 @@ func (s *state) stmt(n *Node) {
|
|||||||
b.Kind = ssa.BlockRet
|
b.Kind = ssa.BlockRet
|
||||||
b.Control = m
|
b.Control = m
|
||||||
b.AddEdgeTo(s.exit)
|
b.AddEdgeTo(s.exit)
|
||||||
|
case ORETJMP:
|
||||||
|
s.stmtList(n.List)
|
||||||
|
m := s.mem()
|
||||||
|
b := s.endBlock()
|
||||||
|
b.Kind = ssa.BlockRetJmp
|
||||||
|
b.Aux = n.Left.Sym
|
||||||
|
b.Control = m
|
||||||
|
b.AddEdgeTo(s.exit)
|
||||||
|
|
||||||
case OCONTINUE, OBREAK:
|
case OCONTINUE, OBREAK:
|
||||||
var op string
|
var op string
|
||||||
@ -2054,6 +2062,11 @@ func canSSA(n *Node) bool {
|
|||||||
case PEXTERN, PPARAMOUT, PPARAMREF:
|
case PEXTERN, PPARAMOUT, PPARAMREF:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if n.Class == PPARAM && n.String() == ".this" {
|
||||||
|
// wrappers generated by genwrapper need to update
|
||||||
|
// the .this pointer in place.
|
||||||
|
return false
|
||||||
|
}
|
||||||
return canSSAType(n.Type)
|
return canSSAType(n.Type)
|
||||||
// TODO: try to make more variables SSAable?
|
// TODO: try to make more variables SSAable?
|
||||||
}
|
}
|
||||||
@ -3475,6 +3488,11 @@ func (s *genState) genBlock(b, next *ssa.Block) {
|
|||||||
s.deferReturn()
|
s.deferReturn()
|
||||||
}
|
}
|
||||||
Prog(obj.ARET)
|
Prog(obj.ARET)
|
||||||
|
case ssa.BlockRetJmp:
|
||||||
|
p := Prog(obj.AJMP)
|
||||||
|
p.To.Type = obj.TYPE_MEM
|
||||||
|
p.To.Name = obj.NAME_EXTERN
|
||||||
|
p.To.Sym = Linksym(b.Aux.(*Sym))
|
||||||
case ssa.BlockCall:
|
case ssa.BlockCall:
|
||||||
if b.Succs[0] != next {
|
if b.Succs[0] != next {
|
||||||
p := Prog(obj.AJMP)
|
p := Prog(obj.AJMP)
|
||||||
|
@ -30,6 +30,9 @@ type Block struct {
|
|||||||
// has a memory control value.
|
// has a memory control value.
|
||||||
Control *Value
|
Control *Value
|
||||||
|
|
||||||
|
// Auxiliary info for the block. Its value depends on the Kind.
|
||||||
|
Aux interface{}
|
||||||
|
|
||||||
// The unordered set of Values that define the operation of this block.
|
// The unordered set of Values that define the operation of this block.
|
||||||
// The list must include the control value, if any. (TODO: need this last condition?)
|
// The list must include the control value, if any. (TODO: need this last condition?)
|
||||||
// After the scheduling pass, this list is ordered.
|
// After the scheduling pass, this list is ordered.
|
||||||
@ -65,6 +68,9 @@ func (b *Block) String() string {
|
|||||||
// long form print
|
// long form print
|
||||||
func (b *Block) LongString() string {
|
func (b *Block) LongString() string {
|
||||||
s := b.Kind.String()
|
s := b.Kind.String()
|
||||||
|
if b.Aux != nil {
|
||||||
|
s += fmt.Sprintf(" %s", b.Aux)
|
||||||
|
}
|
||||||
if b.Control != nil {
|
if b.Control != nil {
|
||||||
s += fmt.Sprintf(" %s", b.Control)
|
s += fmt.Sprintf(" %s", b.Control)
|
||||||
}
|
}
|
||||||
|
@ -72,6 +72,22 @@ func checkFunc(f *Func) {
|
|||||||
if b.Succs[0].Kind != BlockExit {
|
if b.Succs[0].Kind != BlockExit {
|
||||||
f.Fatalf("ret block %s has successor %s, not Exit", b, b.Succs[0].Kind)
|
f.Fatalf("ret block %s has successor %s, not Exit", b, b.Succs[0].Kind)
|
||||||
}
|
}
|
||||||
|
case BlockRetJmp:
|
||||||
|
if len(b.Succs) != 1 {
|
||||||
|
f.Fatalf("retjmp block %s len(Succs)==%d, want 1", b, len(b.Succs))
|
||||||
|
}
|
||||||
|
if b.Control == nil {
|
||||||
|
f.Fatalf("retjmp block %s has nil control %s", b)
|
||||||
|
}
|
||||||
|
if !b.Control.Type.IsMemory() {
|
||||||
|
f.Fatalf("retjmp block %s has non-memory control value %s", b, b.Control.LongString())
|
||||||
|
}
|
||||||
|
if b.Succs[0].Kind != BlockExit {
|
||||||
|
f.Fatalf("retjmp block %s has successor %s, not Exit", b, b.Succs[0].Kind)
|
||||||
|
}
|
||||||
|
if b.Aux == nil {
|
||||||
|
f.Fatalf("retjmp block %s has nil Aux field", b)
|
||||||
|
}
|
||||||
case BlockDead:
|
case BlockDead:
|
||||||
if len(b.Succs) != 0 {
|
if len(b.Succs) != 0 {
|
||||||
f.Fatalf("dead block %s has successors", b)
|
f.Fatalf("dead block %s has successors", b)
|
||||||
|
@ -383,6 +383,7 @@ var genericBlocks = []blockData{
|
|||||||
{name: "Call"}, // 2 successors, normal return and panic
|
{name: "Call"}, // 2 successors, normal return and panic
|
||||||
{name: "First"}, // 2 successors, always takes the first one (second is dead)
|
{name: "First"}, // 2 successors, always takes the first one (second is dead)
|
||||||
{name: "Ret"}, // 1 successor, branches to exit
|
{name: "Ret"}, // 1 successor, branches to exit
|
||||||
|
{name: "RetJmp"}, // 1 successor, branches to exit. Jumps to b.Aux.(*gc.Sym)
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -384,6 +384,9 @@ func (b *Block) HTML() string {
|
|||||||
func (b *Block) LongHTML() string {
|
func (b *Block) LongHTML() string {
|
||||||
// TODO: improve this for HTML?
|
// TODO: improve this for HTML?
|
||||||
s := fmt.Sprintf("<span class=\"%s ssa-block\">%s</span>", html.EscapeString(b.String()), html.EscapeString(b.Kind.String()))
|
s := fmt.Sprintf("<span class=\"%s ssa-block\">%s</span>", html.EscapeString(b.String()), html.EscapeString(b.Kind.String()))
|
||||||
|
if b.Aux != nil {
|
||||||
|
s += html.EscapeString(fmt.Sprintf(" {%v}", b.Aux))
|
||||||
|
}
|
||||||
if b.Control != nil {
|
if b.Control != nil {
|
||||||
s += fmt.Sprintf(" %s", b.Control.HTML())
|
s += fmt.Sprintf(" %s", b.Control.HTML())
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ const (
|
|||||||
BlockCall
|
BlockCall
|
||||||
BlockFirst
|
BlockFirst
|
||||||
BlockRet
|
BlockRet
|
||||||
|
BlockRetJmp
|
||||||
)
|
)
|
||||||
|
|
||||||
var blockString = [...]string{
|
var blockString = [...]string{
|
||||||
@ -56,6 +57,7 @@ var blockString = [...]string{
|
|||||||
BlockCall: "Call",
|
BlockCall: "Call",
|
||||||
BlockFirst: "First",
|
BlockFirst: "First",
|
||||||
BlockRet: "Ret",
|
BlockRet: "Ret",
|
||||||
|
BlockRetJmp: "RetJmp",
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k BlockKind) String() string { return blockString[k] }
|
func (k BlockKind) String() string { return blockString[k] }
|
||||||
|
Loading…
Reference in New Issue
Block a user