36533f7c3f
Fixes for new geth version
86 lines
1.7 KiB
Go
86 lines
1.7 KiB
Go
package pass
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/mmcloughlin/avo/ir"
|
|
)
|
|
|
|
// LabelTarget populates the LabelTarget of the given function. This maps from
|
|
// label name to the following instruction.
|
|
func LabelTarget(fn *ir.Function) error {
|
|
target := map[ir.Label]*ir.Instruction{}
|
|
var empty ir.Label
|
|
pending := empty
|
|
for _, node := range fn.Nodes {
|
|
switch n := node.(type) {
|
|
case ir.Label:
|
|
if pending != empty {
|
|
return errors.New("instruction should follow a label")
|
|
}
|
|
pending = n
|
|
if _, found := target[pending]; found {
|
|
return fmt.Errorf("duplicate label \"%s\"", pending)
|
|
}
|
|
case *ir.Instruction:
|
|
if pending != empty {
|
|
target[pending] = n
|
|
pending = empty
|
|
}
|
|
}
|
|
}
|
|
if pending != empty {
|
|
return errors.New("function ends with label")
|
|
}
|
|
fn.LabelTarget = target
|
|
return nil
|
|
}
|
|
|
|
// CFG constructs the call-flow-graph for the function.
|
|
func CFG(fn *ir.Function) error {
|
|
is := fn.Instructions()
|
|
n := len(is)
|
|
|
|
// Populate successors.
|
|
for i := 0; i < n; i++ {
|
|
cur := is[i]
|
|
var nxt *ir.Instruction
|
|
if i+1 < n {
|
|
nxt = is[i+1]
|
|
}
|
|
|
|
// If it's a branch, locate the target.
|
|
if cur.IsBranch {
|
|
lbl := cur.TargetLabel()
|
|
if lbl == nil {
|
|
return errors.New("no label for branch instruction")
|
|
}
|
|
target, found := fn.LabelTarget[*lbl]
|
|
if !found {
|
|
return fmt.Errorf("unknown label %q", *lbl)
|
|
}
|
|
cur.Succ = append(cur.Succ, target)
|
|
}
|
|
|
|
// Otherwise, could continue to the following instruction.
|
|
switch {
|
|
case cur.IsTerminal:
|
|
case cur.IsBranch && !cur.IsConditional:
|
|
default:
|
|
cur.Succ = append(cur.Succ, nxt)
|
|
}
|
|
}
|
|
|
|
// Populate predecessors.
|
|
for _, i := range is {
|
|
for _, s := range i.Succ {
|
|
if s != nil {
|
|
s.Pred = append(s.Pred, i)
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|