Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
go/ssa: Move BasicBlock operations into block.go
Move the BasicBlock related functions and methods into their own file. Miscellaneous cleanup. Updates golang/go#48525 Change-Id: If1c89cf53a4dba25d0c8b703e53c79eb27957f9c Reviewed-on: https://go-review.googlesource.com/c/tools/+/386316 Reviewed-by: Zvonimir Pavlinovic <zpavlinovic@google.com> Reviewed-by: Robert Findley <rfindley@google.com> Trust: Tim King <taking@google.com> Run-TryBot: Tim King <taking@google.com> gopls-CI: kokoro <noreply+kokoro@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
- Loading branch information
1 parent
7103138
commit fc47946
Showing
2 changed files
with
119 additions
and
110 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
// Copyright 2022 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" | ||
|
||
// This file implements the BasicBlock type. | ||
|
||
// addEdge adds a control-flow graph edge from from to to. | ||
func addEdge(from, to *BasicBlock) { | ||
from.Succs = append(from.Succs, to) | ||
to.Preds = append(to.Preds, from) | ||
} | ||
|
||
// Parent returns the function that contains block b. | ||
func (b *BasicBlock) Parent() *Function { return b.parent } | ||
|
||
// String returns a human-readable label of this block. | ||
// It is not guaranteed unique within the function. | ||
// | ||
func (b *BasicBlock) String() string { | ||
return fmt.Sprintf("%d", b.Index) | ||
} | ||
|
||
// emit appends an instruction to the current basic block. | ||
// If the instruction defines a Value, it is returned. | ||
// | ||
func (b *BasicBlock) emit(i Instruction) Value { | ||
i.setBlock(b) | ||
b.Instrs = append(b.Instrs, i) | ||
v, _ := i.(Value) | ||
return v | ||
} | ||
|
||
// predIndex returns the i such that b.Preds[i] == c or panics if | ||
// there is none. | ||
func (b *BasicBlock) predIndex(c *BasicBlock) int { | ||
for i, pred := range b.Preds { | ||
if pred == c { | ||
return i | ||
} | ||
} | ||
panic(fmt.Sprintf("no edge %s -> %s", c, b)) | ||
} | ||
|
||
// hasPhi returns true if b.Instrs contains φ-nodes. | ||
func (b *BasicBlock) hasPhi() bool { | ||
_, ok := b.Instrs[0].(*Phi) | ||
return ok | ||
} | ||
|
||
// phis returns the prefix of b.Instrs containing all the block's φ-nodes. | ||
func (b *BasicBlock) phis() []Instruction { | ||
for i, instr := range b.Instrs { | ||
if _, ok := instr.(*Phi); !ok { | ||
return b.Instrs[:i] | ||
} | ||
} | ||
return nil // unreachable in well-formed blocks | ||
} | ||
|
||
// replacePred replaces all occurrences of p in b's predecessor list with q. | ||
// Ordinarily there should be at most one. | ||
// | ||
func (b *BasicBlock) replacePred(p, q *BasicBlock) { | ||
for i, pred := range b.Preds { | ||
if pred == p { | ||
b.Preds[i] = q | ||
} | ||
} | ||
} | ||
|
||
// replaceSucc replaces all occurrences of p in b's successor list with q. | ||
// Ordinarily there should be at most one. | ||
// | ||
func (b *BasicBlock) replaceSucc(p, q *BasicBlock) { | ||
for i, succ := range b.Succs { | ||
if succ == p { | ||
b.Succs[i] = q | ||
} | ||
} | ||
} | ||
|
||
// removePred removes all occurrences of p in b's | ||
// predecessor list and φ-nodes. | ||
// Ordinarily there should be at most one. | ||
// | ||
func (b *BasicBlock) removePred(p *BasicBlock) { | ||
phis := b.phis() | ||
|
||
// We must preserve edge order for φ-nodes. | ||
j := 0 | ||
for i, pred := range b.Preds { | ||
if pred != p { | ||
b.Preds[j] = b.Preds[i] | ||
// Strike out φ-edge too. | ||
for _, instr := range phis { | ||
phi := instr.(*Phi) | ||
phi.Edges[j] = phi.Edges[i] | ||
} | ||
j++ | ||
} | ||
} | ||
// Nil out b.Preds[j:] and φ-edges[j:] to aid GC. | ||
for i := j; i < len(b.Preds); i++ { | ||
b.Preds[i] = nil | ||
for _, instr := range phis { | ||
instr.(*Phi).Edges[i] = nil | ||
} | ||
} | ||
b.Preds = b.Preds[:j] | ||
for _, instr := range phis { | ||
phi := instr.(*Phi) | ||
phi.Edges = phi.Edges[:j] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters