func runImage(bs []byte, dasm bool, n int) { if dasm { err := dasm8.DumpImage(bytes.NewReader(bs), os.Stdout) if err != nil { fmt.Println(err) } } if len(bs) == 0 { fmt.Println("(the image is empty)") return } m := arch8.NewMachine(new(arch8.Config)) if err := m.LoadImageBytes(bs); err != nil { fmt.Println(err) return } ncycle, exp := m.Run(n) fmt.Printf("(%d cycles)\n", ncycle) if exp != nil { if !arch8.IsHalt(exp) { fmt.Println(exp) err := arch8.FprintStack(os.Stdout, m, exp) if err != nil { fmt.Println(err) } } } else { fmt.Println("(end of time)") } }
func main() { flag.Parse() args := flag.Args() if len(args) != 1 { log.Fatal("need exactly one input file\n") } fname := args[0] if *doDasm { f, err := os.Open(fname) defer f.Close() err = dasm8.DumpImage(f, os.Stdout) if err != nil { log.Fatal(err) } } else if *printDebug { f, err := os.Open(fname) defer f.Close() secs, err := e8.Read(f) if err != nil { log.Fatal(err) } for _, sec := range secs { if sec.Type != e8.Debug { continue } tab, err := debug8.UnmarshalTable(sec.Bytes) if err != nil { log.Fatal(err) } tab.PrintTo(os.Stdout) } } else { bs, err := ioutil.ReadFile(fname) if err != nil { log.Fatal(err) } n, e := run(bs) fmt.Printf("(%d cycles)\n", n) if e != nil { if !arch8.IsHalt(e) { fmt.Println(e) } } else { fmt.Println("(end of time)") } } }
func main() { flag.Parse() args := flag.Args() if len(args) != 1 { log.Fatal("need exactly one input file\n") } fname := args[0] var bs []byte f, e := os.Open(fname) if e != nil { log.Fatalf("open: %s", e) } var es []*lex8.Error if strings.HasSuffix(fname, "_bare.s") { bs, es = asm8.BuildBareFunc(fname, f) } else { bs, es = asm8.BuildSingleFile(fname, f) } if len(es) > 0 { for _, e := range es { fmt.Println(e) } os.Exit(-1) return } if *doDasm { lines := dasm8.Dasm(bs, arch8.InitPC) for _, line := range lines { fmt.Println(line) } } else { n, e := run(bs) fmt.Printf("(%d cycles)\n", n) if e != nil { if !arch8.IsHalt(e) { fmt.Println(e) } } else { fmt.Println("(end of time)") } } }
func run(bs []byte) (int, error) { // create a single core machine m := arch8.NewMachine(uint32(*memSize), 1) secs, err := e8.Read(bytes.NewReader(bs)) if err != nil { return 0, err } if err := m.LoadSections(secs); err != nil { return 0, err } if *bootArg > math.MaxUint32 { log.Fatalf("boot arg(%d) is too large", *bootArg) } if err := m.WriteWord(arch8.AddrBootArg, uint32(*bootArg)); err != nil { return 0, err } if *romRoot != "" { m.MountROM(*romRoot) } if *randSeed != 0 { m.RandSeed(*randSeed) } ret, exp := m.Run(*ncycle) if *printStatus { m.PrintCoreStatus() } if !arch8.IsHalt(exp) { fmt.Println(exp) err := arch8.FprintStack(os.Stdout, m, exp) if err != nil { log.Fatal(err) } } if exp == nil { return ret, nil } return ret, exp }
func run(bs []byte) (int, error) { if *bootArg > math.MaxUint32 { log.Fatalf("boot arg(%d) is too large", *bootArg) } // create a single core machine m := arch8.NewMachine(&arch8.Config{ MemSize: uint32(*memSize), ROM: *romRoot, RandSeed: *randSeed, BootArg: uint32(*bootArg), }) secs, err := e8.Read(bytes.NewReader(bs)) if err != nil { return 0, err } if err := m.LoadSections(secs); err != nil { return 0, err } ret, exp := m.Run(*ncycle) if *printStatus { m.PrintCoreStatus() } if !arch8.IsHalt(exp) { fmt.Println(exp) err := arch8.FprintStack(os.Stdout, m, exp) if err != nil { log.Fatal(err) } } if exp == nil { return ret, nil } return ret, exp }
func runImage(bs []byte, dasm bool, n int) { if dasm { err := dasm8.DumpImage(bytes.NewReader(bs), os.Stdout) if err != nil { fmt.Println(err) } } if len(bs) == 0 { fmt.Println("(the image is empty)") return } ncycle, e := arch8.RunImage(bs, n) fmt.Printf("(%d cycles)\n", ncycle) if e != nil { if !arch8.IsHalt(e) { fmt.Println(e) } } else { fmt.Println("(end of time)") } }
func runTests( log lex8.Logger, tests map[string]uint32, img []byte, verbose bool, ) { report := func(name string, pass bool, err error) { if !pass { lex8.LogError(log, fmt.Errorf("%s failed: got %s", name, err)) if verbose { fmt.Println("FAILED") } return } if verbose { fmt.Println("pass") } } var testNames []string for name := range tests { testNames = append(testNames, name) } sort.Strings(testNames) for _, test := range testNames { if verbose { fmt.Printf(" - %s: ", test) } arg := tests[test] _, err := arch8.RunImageArg(img, arg) if strings.HasPrefix(test, "TestBad") { report(test, arch8.IsPanic(err), err) } else { report(test, arch8.IsHalt(err), err) } } }
func TestMultiFile(t *testing.T) { const N = 100000 o := func(fs map[string]string, output string) { out, err := multiTestRun(t, fs, N) if err == errRunFailed { t.Error(err) return } if !arch8.IsHalt(err) { t.Log(fs) t.Log(err) t.Error("did not halt gracefully") return } got := strings.TrimSpace(out) expect := strings.TrimSpace(output) if got != expect { t.Log(fs) t.Logf("expect: %s", expect) t.Errorf("got: %s", got) } } type files map[string]string o(files{ "main/m.g": "func main() { }", }, "") o(files{ "a/a.g": "func P() { printInt(33) }", "main/m.g": ` import ( "a" ) func main() { a.P() }`, }, "33") o(files{ "a/a.g": "struct A { func P() { printInt(33) } }", "b/b.g": `import ("a"); var A a.A`, "main/m.g": `import ("b"); func main() { b.A.P() }`, }, "33") o(files{ "a/a.g": "func init() { printInt(33) }", "b/b.g": `import (_ "a"); func init() { printInt(44) }`, "main/m.g": `import (_ "b"); func main() { printInt(55) }`, }, "33\n44\n55") o(files{ "a/a.g": "const A=33", "main/m.g": ` import ("a") var array [a.A]int func main() { printInt(len(array)) }`, }, "33") o(files{ "a/a.g": "const A=33+5-2", "main/m.g": ` import ("a") var array [a.A-3]int func main() { printInt(len(array)) }`, }, "33") o(files{ "asm/a/a.g": ` func F { mov pc ret }`, "main/m.g": ` import ("asm/a") func main() { a.F(); printInt(33) }`, }, "33") o(files{ "asm/a/a.g": ` func F { addi r1 r0 33 mov pc ret }`, "main/m.g": ` import ("asm/a") func f() int = a.F func main() { printInt(f()) }`, }, "33") }
func TestBareFunc_good(t *testing.T) { const N = 100000 o := func(input, output string) { out, e := bareTestRun(t, input, N) if e == errRunFailed { t.Error(e) return } if !arch8.IsHalt(e) { t.Log(input) t.Log(e) t.Error("did not halt gracefully") return } out = strings.TrimSpace(out) output = strings.TrimSpace(output) if out != output { t.Log(input) t.Logf("expect: %s", output) t.Errorf("got: %s", out) } } o(";;;;", "") o("printInt(0)", "0") o("printInt(3)", "3") o("printInt(-444)", "-444") o("printInt(2147483647)", "2147483647") o("printInt(-2147483647-1)", "-2147483648") o("printInt(-2147483648)", "-2147483648") o("printInt(300000000)", "300000000") o("printInt(4*5+3)", "23") o("printInt(3+4*5)", "23") o("printInt((3+4)*5)", "35") o("printInt((5*(3+4)))", "35") o("printInt(3^1)", "2") o("printInt(0xf)", "15") o("printInt(0xA)", "10") o("a:=3; if a==3 { printInt(5) }", "5") o("a:=5; if a==3 { printInt(5) }", "") o("a:=5; if a==3 { printInt(5) } else { printInt(10) }", "10") o("a:=3; for a>0 { printInt(a); a-- }", "3\n2\n1") o("a:=0; for a<4 { printInt(a); a++ }", "0\n1\n2\n3") o("for i:=0;i<3;i++ { printInt(i); }", "0\n1\n2") o("for i:=0;i<10;i+=3 { printInt(i); }", "0\n3\n6\n9") o("i:=3; for i:=0;i<3;i++ { printInt(i); }", "0\n1\n2") o("i:=0; for ;i<3;i++ { printInt(i); }", "0\n1\n2") o("a:=1; { a:=3; printInt(a) }", "3") o("true:=3; printInt(true)", "3") o("a,b:=3,4; printInt(a); printInt(b)", "3\n4") o("a,b:=3,4; { a,b:=b,a; printInt(a); printInt(b) }", "4\n3") o("a,b:=3,4; a,b=b,a; printInt(a); printInt(b)", "4\n3") o("var a int; printInt(a)", "0") o("var a (int); printInt(a)", "0") o("var a,b = 3,4; printInt(a); printInt(b)", "3\n4") o("var a,b = 3,4; printInt(a); printInt(b)", "3\n4") o("var a,b int = 3,4; printInt(a); printInt(b)", "3\n4") o("var a,b uint = 3,4; printUint(a); printUint(b)", "3\n4") o(` a,b:=3,4; { var a,b=b,a; printInt(a); printInt(b) } printInt(a); printInt(b) `, "4\n3\n3\n4") o("var i int; for i < 3 { printInt(i); i=i+1 }", "0\n1\n2") o("for true { break }; printInt(3)", "3") o("for true { if true break }; printInt(3)", "3") o("for { break }; printInt(33)", "33") o("i:=0; for i<3 { printInt(i); i=i+1; continue; break }", "0\n1\n2") o("printChar('x')", "x") o("var a=32; var b=*&a; printInt(b)", "32") o("var a=32; var b=&a; var c=*b; printInt(c)", "32") o("var a=32; var b int = *&*&a; printInt(b)", "32") o("var a='x'; var b = *&*&a; printChar(b)", "x") o("if nil==nil { printInt(3) }", "3") o("if nil!=nil { printInt(3) }", "") o("var a*int; if a==nil { printInt(3) }", "3") o("var a*int; if nil==a { printInt(3) }", "3") o("b:=3; a:=&b; if *a==3 { printInt(*a) }", "3") o("b:=3; a:=&b; a=nil; if a==nil { printInt(b) }", "3") o("b:=3; a:=&b; *a=4; printInt(b)", "4") o("if true==true { printChar('y') }", "y") o("if true!=true { printChar('y') }", "") o("if true==false { printChar('y') }", "") o("if true!=false { printChar('y') }", "y") o("if false==false { printChar('y') }", "y") o("if false!=false { printChar('y') }", "") o("var a [4]int; a[3] = 3; printInt(a[3]); printInt(a[2])", "3\n0") o("var a [7]int; a[3]=33; pt:=&a[3]; printInt(*pt)", "33") o("var a [7]int; printInt(len(a))", "7") o("var a [7]int; s:=a[:]; printInt(len(s))", "7") o("var a [7]int; s:=a[:3]; printInt(len(s))", "3") o("var a [7]int; s:=a[1:]; printInt(len(s))", "6") o("var a [7]int; s:=a[1:3]; printInt(len(s))", "2") o("var a [7]int; s:=a[0:0]; printInt(len(s))", "0") o("var a [7]int; s:=a[:]; a[3]=33; printInt(s[3])", "33") o("var a [7]int; s:=a[1:]; a[3]=33; printInt(s[2])", "33") o("var a [7]int; s:=a[1:4]; a[3]=33; printInt(s[2])", "33") o("var a [7]int; s:=a[:]; a[3]=33; pt:=&s[3]; printInt(*pt)", "33") o("a:=3; a++; printInt(a)", "4") o("a:=3; pt := &a; *pt++; printInt(a)", "4") o("printInt(int(byte(int(-1))))", "255") o("printInt(int(byte(3)))", "3") o("printInt(int(byte(int(256))))", "0") o("printInt(int(char(int(-1))))", "-1") o("printInt(int(char(int(255))))", "-1") o("printInt(int(char(int(256))))", "0") o("printInt(int(byte(char(int(255)))))", "255") o("printInt(int(byte(char(int(-1)))))", "255") o("printInt(33 << uint(1))", "66") o("printInt(33 << 1)", "66") o("printInt(33 >> uint(1))", "16") o("printInt(33 >> 1)", "16") o("printInt(-33 >> uint(1))", "-17") o("printInt(-1 >> uint(1))", "-1") o("printInt(int(byte(255) << uint(1)))", "254") o("printInt(int(byte(255) << 1))", "254") o("printInt(int(uint(33) >> uint(1)))", "16") o("printInt(int(uint(33) >> 1))", "16") o("a:=3; a+=4; printInt(a)", "7") o("a:=3; a-=4; printInt(a)", "-1") o("a:=3; a*=4; printInt(a)", "12") o("a:=3; a/=2; printInt(a)", "1") o("a:=uint(3); a/=2; printUint(a)", "1") o("a:=33; a<<=uint(1); printInt(a)", "66") o("a:=33; a<<=1; printInt(a)", "66") o("a:=33; a>>=uint(1); printInt(a)", "16") o("a:=33; a>>=1; printInt(a)", "16") o("a:=33; b:=(*uint)(&a); printUint(*b)", "33") o("if 0x33 == 51 { printInt(33) }", "33") o("const a = 33; printInt(a)", "33") o("const a = 33; printUint(a)", "33") o("const ( a,b=3,4; c=a+b ); printInt(a+b+c)", "14") o("const a,b=3,4; var v [a+b]int; printInt(len(v))", "7") }
func runTests( log lex8.Logger, tests map[string]uint32, img []byte, opt *Options, ) { logln := func(s string) { if opt.LogLine == nil { fmt.Println(s) } else { opt.LogLine(s) } } // TODO(h8liu): this reporting should go with JSON for better formatting. report := func( name string, ncycle int, pass bool, m *arch8.Machine, err error, ) { if pass { if opt.Verbose { logln(fmt.Sprintf( " - %s: passed (%s)", name, cycleStr(ncycle), )) } return } if err == nil { err = errTimeOut } lex8.LogError(log, fmt.Errorf("%s failed: got %s", name, err)) if opt.Verbose { logln(fmt.Sprintf( " - %s: FAILED (%s, got %s)", name, cycleStr(ncycle), err, )) // TODO(h8liu): this is too ugly here... excep, ok := err.(*arch8.CoreExcep) if !arch8.IsHalt(err) && ok { stackTrace := new(bytes.Buffer) arch8.FprintStack(stackTrace, m, excep) logln(stackTrace.String()) } } } var testNames []string for name := range tests { testNames = append(testNames, name) } sort.Strings(testNames) for _, test := range testNames { arg := tests[test] m := arch8.NewMachine(&arch8.Config{ BootArg: arg, }) if err := m.LoadImageBytes(img); err != nil { report(test, 0, false, m, err) continue } var err error n, excep := m.Run(opt.TestCycles) if excep == nil { err = errTimeOut } else { err = excep } if strings.HasPrefix(test, "TestBad") { report(test, n, arch8.IsPanic(err), m, err) } else { report(test, n, arch8.IsHalt(err), m, err) } } }
func TestSingleFile(t *testing.T) { const N = 100000 o := func(input, output string) { out, err := singleTestRun(t, input, N) if err == errRunFailed { t.Error(err) return } if !arch8.IsHalt(err) { t.Log(input) t.Log(err) t.Error("did not halt gracefully") return } got := strings.TrimSpace(out) expect := strings.TrimSpace(output) if got != expect { t.Log(input) t.Logf("expect: %s", expect) t.Errorf("got: %s", got) } } o("func main() { }", "") o("func main() { return }", "") o("func main() { printInt(3) }", "3") o(` func r() int { return 7 } func main() { printInt(r()) }`, "7") o(` func p(i int) { printInt(i) } func main() { p(33); p(44) }`, "33\n44") o(` func r() (int, int) { return 3, 4 } func main() { a, b := r(); printInt(a); printInt(b) }`, "3\n4") o(` func r() (int, int) { return 3, 4 } func p(a, b int) { printInt(a); printInt(b) } func main() { p(r()) }`, "3\n4") o(` func r() (int) { return 3 } func p(a, b int) { printInt(a); printInt(b) } func main() { p(r(), 4) }`, "3\n4") o(` func fabo(n int) int { if n == 0 return 0 if n == 1 return 1 return fabo(n-1) + fabo(n-2) } func main() { printInt(fabo(10)) }`, "55") o(` func b() bool { printInt(4); return true } func main() { if false || b() { printInt(3) } }`, "4\n3") o(` func b() bool { printInt(4); return true } func main() { if true || b() { printInt(3) } }`, "3") o(` func b() bool { printInt(4); return false } func main() { if true && b() { printInt(3) } }`, "4") o(` func b() bool { printInt(4); return true } func main() { if false && b() { printInt(3) } }`, "") o(` func b() bool { printInt(4); return true } func main() { if true && b() { printInt(3) } }`, "4\n3") o(`func f(i int) { i=33; printInt(i) }; func main() { f(44) }`, "33") o(` func f(a []int) { printInt(a[3]) } func main() { var a [8]int; a[4]=33; f(a[1:5]) }`, "33") o(`func main() { for true { printInt(33); break } }`, "33") o(`func main() { for 0==0 { printInt(33); break } }`, "33") o(`func main() { for true && true { printInt(33); break } }`, "33") o(`func main() { for true && false { printInt(33); break } }`, "") o(`func main() { for 0==0 && 0==1 { printInt(33); break } }`, "") o(`func main() { for true || false { printInt(33); break } }`, "33") o(`func main() { for false || true { printInt(33); break } }`, "33") o(`func main() { for false { printInt(33); break } }`, "") o(` func printStr(s string) { n:=len(s); for i:=0;i<n;i++ { printChar(s[i]) } } func main() { printStr("hello") }`, "hello") o(` func printStr(s string) { n:=len(s); for i:=0;i<n;i++ { printChar(s[i]) } } func main() { var a []int8; b:="hello"; a=b; printStr(a) }`, "hello") o(` func printStr(s string) { n:=len(s); for i:=0;i<n;i++ { printChar(s[i]) } } func main() { b:="hello"; var a []int8; a=b; printStr(b); _ := a }`, "hello") o(` struct A {}; func main() { var a A; pa := &a; _ := pa }`, "") o(` struct A { a int } func main() { var a A; printInt(a.a) }`, "0") o(` struct A { a int } func main() { var a A; a.a = 33; printInt(a.a) }`, "33") o(` struct A { a int } func main() { var a A; pi:=&a.a; *pi=33; printInt(a.a) }`, "33") o(` struct A { a int } func main() { var a A; (&a).a = 33; printInt(a.a) }`, "33") o(` struct A { a int } func main() { var a A; var pa=&a; pa.a = 33; printInt(pa.a) }`, "33") o(` struct A { b byte; a int } func main() { var a A; var pa=&a; pa.a = 33; pa.b = byte(7); printInt(pa.a); printInt(int(pa.b)) }`, "33\n7") o(` func p(i int) { printInt(i) } func main() { f:=p; f(33) }`, "33") o(` func p(i int) { printInt(i+2) } func c(x func(i int)) { x(33) } func main() { c(p) }`, "35") o("struct A { a *A }; func main() {}", "") o(`struct A { b B }; struct B { a *A }; func main() {}`, "") o(` struct A {}; func (p *A) p(a int) { printInt(a) } func main() { var a A; a.p(33) }`, "33") o(` struct A { a int } func (p *A) s(a int) { p.a = a } func (a *A) p() { printInt(a.a) } func main() { var a A; a.s(33); a.p() }`, "33") o(` struct A { a int } func (p *A) s(a int) { (*p).a = a } func (a *A) p() { printInt(a.a) } func main() { var a A; a.s(33); a.p() }`, "33") o(` struct A { a int } func (a *A) p() { printInt(a.a) } func (p *A) q(a int) { printInt(a) } func main() { var a A; a.p(); a.a=33; a.p(); a.q(78) }`, "0\n33\n78") o(` struct A { } func (a *A) p() { printInt(33) } func (a *A) q() { a.p() } func main() { var a A; a.q() }`, "33") o("var a int; func main() { a := 33; printInt(a) }", "33") o(` struct A { } func (a *A) p() { printInt(33) } var a A func main() { a.p() }`, "33") o(` struct A { a int } func (a *A) p() { printInt(a.a) } var a A func main() { a.a=33; a.p() }`, "33") o(` struct A { a, b int } func (a *A) p() { printInt(a.a+a.b) } var a A func main() { a.a=30; a.b=3; a.p() }`, "33") o(` var ( a []int; s [2]int ) func main() { a=s[:]; s[1]=33; printInt(a[1]) }`, "33") o(` var ( a []int ) func main() { if a == nil { printInt(33) } }`, "33") o(` var ( a []int; v [0]int ) func main() { a=v[:]; if a != nil { printInt(33) } }`, "33") o(` var ( a, b []int; v [3]int ) func main() { a=v[:2]; b = v[:3]; if a != b { printInt(33) } }`, "33") o(` var ( a, b []int; v [3]int ) func main() { a=v[:]; b = v[:]; if a == b { printInt(33) } }`, "33") o("func init() { printInt(33) }; func main() { printInt(44) }", "33\n44") o(` struct a { a int; b byte } func main() { var x,y a; x.a=33; y.a=44; printInt(x.a); printInt(y.a) }`, "33\n44") o(` struct a { a int; b,c byte } func main() { var as [4]a printUint(uint(&as[1])-uint(&as[0])) printUint(uint(&as[0].c)-uint(&as[0].a)) }`, "8\n5") o(` struct a { a [4]byte; b byte } func main() { var as [4]a printUint(uint(&as[1])-uint(&as[0])) }`, "5") o("import(); func main() {}", "") o("import(); func main() { printInt(33) }", "33") o("const a=33; func main() { printInt(a) }", "33") o("const a=33; func main() { const a=34; printInt(a) }", "34") o(` const a, b = 1, a; const c, d = d, 3 func main() { printInt(a); printInt(b); printInt(c); printInt(d) }`, "1\n1\n3\n3\n") o(`const a, b = b + 3, 30; func main() { printInt(a) }`, "33") o(` var a [4]int func main() { s := make([]int, 2, &a[1]) s[0] = 33; s[1] = 47 printInt(a[1]); printInt(a[2]) }`, "33\n47") o(`func f() int { for {} }; func main() { }`, "") o(` func f() int { if true { return 1 } else { return 0 } } func main() { }`, "") o(`func f() int { for { if true { return 0 } } }; func main() { }`, "") // Bugs found by the fuzzer in the past o("func main() { a := 0==0; if a { printInt(33) } }", "33") o(` func n()[(4-3)*1]string { var a [1]string; return a } func main() { printInt(len(n())) }`, "1") o(` func n()[1<<1]string { var a [2]string; return a } func main() { printInt(len(n())) }`, "2") o(` func n()[1>>1]string { var a [0]string; return a } func main() { printInt(len(n())) }`, "0") o("func main() { r:=+'0'; printChar(r) }", "0") o("func n(b**bool) { **b=**b }; func main() {}", "") o("func n(b****bool) { ****b=****b }; func main() {}", "") o(` struct A { } func (p *A) n() (a int) { return 33 } func main() { var a A; printInt(a.n()) }`, "33") o(` func main() {printInt(33)} func _(){} func _(){} var _, _ int`, "33") // Bugs found when writing OS8 o(` func main() { a, b := f(); printInt(a); printInt(len(b)) } var dat [5]int func f() (int, []int) { return 33, dat[:] }`, "33\n5") o(` func p(a []uint) {} func main() { var t [10]uint; t2:=t[:]; before := uint(&t2[0]); p(t2[2:5]); after := uint(&t2[0]) if before != after { panic() } }`, "") }