// returns a fun containing the composed Func. entry must be a name
// supplied to one of the Bloc functions. Each of the bloc names and
// valu names should be unique across the Fun.
-func Fun(entry string, blocs ...bloc) fun {
+func Fun(c *Config, entry string, blocs ...bloc) fun {
f := new(Func)
+ f.Config = c
blocks := make(map[string]*Block)
values := make(map[string]*Value)
// Create all the blocks and values.
}
func TestArgs(t *testing.T) {
- fun := Fun("entry",
+ c := NewConfig("amd64")
+ fun := Fun(c, "entry",
Bloc("entry",
Valu("a", OpConst, TypeInt64, 14),
Valu("b", OpConst, TypeInt64, 26),
}
func TestEquiv(t *testing.T) {
+ c := NewConfig("amd64")
equivalentCases := []struct{ f, g fun }{
// simple case
{
- Fun("entry",
+ Fun(c, "entry",
Bloc("entry",
Valu("a", OpConst, TypeInt64, 14),
Valu("b", OpConst, TypeInt64, 26),
Goto("exit")),
Bloc("exit",
Exit("mem"))),
- Fun("entry",
+ Fun(c, "entry",
Bloc("entry",
Valu("a", OpConst, TypeInt64, 14),
Valu("b", OpConst, TypeInt64, 26),
},
// block order changed
{
- Fun("entry",
+ Fun(c, "entry",
Bloc("entry",
Valu("a", OpConst, TypeInt64, 14),
Valu("b", OpConst, TypeInt64, 26),
Goto("exit")),
Bloc("exit",
Exit("mem"))),
- Fun("entry",
+ Fun(c, "entry",
Bloc("exit",
Exit("mem")),
Bloc("entry",
differentCases := []struct{ f, g fun }{
// different shape
{
- Fun("entry",
+ Fun(c, "entry",
Bloc("entry",
Valu("mem", OpArg, TypeMem, ".mem"),
Goto("exit")),
Bloc("exit",
Exit("mem"))),
- Fun("entry",
+ Fun(c, "entry",
Bloc("entry",
Valu("mem", OpArg, TypeMem, ".mem"),
Exit("mem"))),
},
// value order changed
{
- Fun("entry",
+ Fun(c, "entry",
Bloc("entry",
Valu("mem", OpArg, TypeMem, ".mem"),
Valu("b", OpConst, TypeInt64, 26),
Valu("a", OpConst, TypeInt64, 14),
Exit("mem"))),
- Fun("entry",
+ Fun(c, "entry",
Bloc("entry",
Valu("mem", OpArg, TypeMem, ".mem"),
Valu("a", OpConst, TypeInt64, 14),
},
// value aux different
{
- Fun("entry",
+ Fun(c, "entry",
Bloc("entry",
Valu("mem", OpArg, TypeMem, ".mem"),
Valu("a", OpConst, TypeInt64, 14),
Exit("mem"))),
- Fun("entry",
+ Fun(c, "entry",
Bloc("entry",
Valu("mem", OpArg, TypeMem, ".mem"),
Valu("a", OpConst, TypeInt64, 26),
},
// value args different
{
- Fun("entry",
+ Fun(c, "entry",
Bloc("entry",
Valu("mem", OpArg, TypeMem, ".mem"),
Valu("a", OpConst, TypeInt64, 14),
Valu("b", OpConst, TypeInt64, 26),
Valu("sum", OpAdd, TypeInt64, nil, "a", "b"),
Exit("mem"))),
- Fun("entry",
+ Fun(c, "entry",
Bloc("entry",
Valu("mem", OpArg, TypeMem, ".mem"),
Valu("a", OpConst, TypeInt64, 0),
}
}
}
+
+// opcodeMap returns a map from opcode to the number of times that opcode
+// appears in the function.
+func opcodeMap(f *Func) map[Op]int {
+ m := map[Op]int{}
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ m[v.Op]++
+ }
+ }
+ return m
+}
+
+// opcodeCounts checks that the number of opcodes listed in m agree with the
+// number of opcodes that appear in the function.
+func checkOpcodeCounts(t *testing.T, f *Func, m map[Op]int) {
+ n := opcodeMap(f)
+ for op, cnt := range m {
+ if n[op] != cnt {
+ t.Errorf("%s appears %d times, want %d times", op, n[op], cnt)
+ }
+ }
+}