1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
|
package pass
import (
"reflect"
"strconv"
"testing"
"github.com/mmcloughlin/addchain/acc/ir"
)
func TestAllocator(t *testing.T) {
// Generate a program that will need n live variables.
n := 13
p := &ir.Program{}
// Create n indexes that will be used later.
for i := 1; i <= n; i++ {
p.AddInstruction(&ir.Instruction{
Output: ir.Index(i),
Op: ir.Add{
X: ir.One,
Y: ir.Index(i - 1),
},
})
}
// Consume the n indicies. This ensures we'll have n live variables at some
// point.
for i := n + 1; i <= 2*n; i++ {
p.AddInstruction(&ir.Instruction{
Output: ir.Index(i),
Op: ir.Add{
X: ir.Index(i - n),
Y: ir.Index(i - 1),
},
})
}
// Execute allocation pass.
t.Logf("pre:\n%s", p)
a := Allocator{
Input: "in",
Output: "out",
Format: "tmp%d",
}
if err := a.Execute(p); err != nil {
t.Fatal(err)
}
t.Logf("post:\n%s", p)
// Every operand should have a name.
for _, operand := range p.Operands {
if operand.Identifier == "" {
t.Errorf("operand %s does not have a name", operand)
}
}
// We expect to have n-1 temporaries. Note we do not expect n, since the output
// variable will be used as a temporary.
expect := make([]string, n-1)
for i := 0; i < n-1; i++ {
expect[i] = "tmp" + strconv.Itoa(i)
}
if !reflect.DeepEqual(expect, p.Temporaries) {
t.Fatalf("got temporaries %v; expect %v", p.Temporaries, expect)
}
// Confirm input and output variables are used.
if p.Operands[0].Identifier != a.Input {
t.Errorf("unexpected input name: got %q expect %q", p.Operands[0].Identifier, a.Input)
}
if p.Output().Identifier != a.Output {
t.Errorf("unexpected output name: got %q expect %q", p.Output().Identifier, a.Output)
}
}
|