func doTestable(args []string) error { conf := loader.Config{ Build: &build.Default, SourceImports: true, } // TODO(adonovan): make go/types choose its default Sizes from // build.Default or a specified *build.Context. var wordSize int64 = 8 switch conf.Build.GOARCH { case "386", "arm": wordSize = 4 } wordSize = 4 // TARDIS Go addition to force default int size to 32 bits //conf.Build.GOARCH = "tardisgo" // TARDIS Go addition to ensure no architecure-specific code will compile //conf.Build.GOOS = "tardisgo" // TARDIS Go addition to ensure no OS-specific code will compile conf.TypeChecker.Sizes = &types.StdSizes{ MaxAlign: 8, WordSize: wordSize, } var mode ssa.BuilderMode for _, c := range *buildFlag { switch c { case 'D': mode |= ssa.GlobalDebug case 'P': mode |= ssa.LogPackages | ssa.BuildSerially case 'F': mode |= ssa.LogFunctions | ssa.BuildSerially case 'S': mode |= ssa.LogSource | ssa.BuildSerially case 'C': mode |= ssa.SanityCheckFunctions case 'N': mode |= ssa.NaiveForm case 'G': conf.SourceImports = false case 'L': mode |= ssa.BuildSerially default: log.Fatalf("Unknown -build option: '%c'.", c) } } var interpMode interp.Mode for _, c := range *interpFlag { switch c { case 'T': interpMode |= interp.EnableTracing case 'R': interpMode |= interp.DisableRecover default: log.Fatalf("Unknown -interp option: '%c'.", c) } } if len(args) == 0 { //fmt.Fprint(os.Stderr, usage) return fmt.Errorf("%v", usage) } // Profiling support. if *cpuprofile != "" { f, err := os.Create(*cpuprofile) if err != nil { return err } pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() } // TARDIS Go TEST // Really need to find a way to replace entire packages, this experiment did not work... /* conf.Fset = token.NewFileSet() f, err := parser.ParseFile(conf.Fset, conf.Build.GOPATH+"/src/github.com/tardisgo/tardisgo/golibruntime/runtime/runtime.go", nil, 0) if err != nil { fmt.Println(err) return err } conf.CreateFromFiles("", f) fmt.Printf("DEBUG %s %s\n", f.Name.Name, "") //, f.Name.Obj.Name) */ // end TARDIS Go TEST // Use the initial packages from the command line. args, err := conf.FromArgs(args, *testFlag) if err != nil { return err } // The interpreter needs the runtime package. if *runFlag { conf.Import("runtime") conf.Import("github.com/tardisgo/tardisgo/golibruntime/runtime") // This required for TARDIS go to run runtime } // TARDIS GO additional line to add the language specific go runtime code conf.Import(pogo.LanguageList[pogo.TargetLang].Goruntime) // TODO add code to set pogo.TargetLang when more than one of them // Load, parse and type-check the whole program. iprog, err := conf.Load() if err != nil { return err } // Create and build SSA-form program representation. prog := ssa.Create(iprog, mode) prog.BuildAll() // Run the interpreter. if *runFlag { var main *ssa.Package pkgs := prog.AllPackages() if *testFlag { // If -test, run all packages' tests. if len(pkgs) > 0 { main = prog.CreateTestMainPackage(pkgs...) } if main == nil { return fmt.Errorf("no tests") } } else { // Otherwise, run main.main. for _, pkg := range pkgs { if pkg.Object.Name() == "main" { main = pkg if main.Func("main") == nil { return fmt.Errorf("no func main() in main package") } break } } if main == nil { return fmt.Errorf("no main package") } } // NOTE TARDIS Go removal of this test required if we alter the GOARCH to stop architecture-specific code if runtime.GOARCH != build.Default.GOARCH { return fmt.Errorf("cross-interpretation is not yet supported (target has GOARCH %s, interpreter has %s)", build.Default.GOARCH, runtime.GOARCH) } interp.Interpret(main, interpMode, conf.TypeChecker.Sizes, main.Object.Path(), args) } // TARDIS Go additions: copy run interpreter code above, but call pogo class if true { var main *ssa.Package pkgs := prog.AllPackages() if *testFlag { // If -test, run all packages' tests. if len(pkgs) > 0 { main = prog.CreateTestMainPackage(pkgs...) } if main == nil { return fmt.Errorf("no tests") } } else { // Otherwise, run main.main. for _, pkg := range pkgs { if pkg.Object.Name() == "main" { main = pkg if main.Func("main") == nil { return fmt.Errorf("no func main() in main package") } break } } if main == nil { return fmt.Errorf("no main package") } } /* if runtime.GOARCH != build.Default.GOARCH { return fmt.Errorf("cross-interpretation is not yet supported (target has GOARCH %s, interpreter has %s)", build.Default.GOARCH, runtime.GOARCH) } interp.Interpret(main, interpMode, conf.TypeChecker.Sizes, main.Object.Path(), args) */ err = pogo.EntryPoint(main) // TARDIS Go entry point, returns an error if err != nil { return err } if *allFlag { targets := [][][]string{ [][]string{ []string{"haxe", "-main", "tardis.Go", "-dce", "full", "-cpp", "cpp"}, []string{"echo", `"CPP:"`}, []string{"./cpp/Go"}, }, [][]string{ []string{"haxe", "-main", "tardis.Go", "-dce", "full", "-java", "java"}, []string{"echo", `"Java:"`}, []string{"java", "-jar", "java/Go.jar"}, }, [][]string{ []string{"haxe", "-main", "tardis.Go", "-dce", "full", "-cs", "cs"}, []string{"echo", `"CS:"`}, []string{"mono", "./cs/bin/Go.exe"}, }, [][]string{ []string{"haxe", "-main", "tardis.Go", "-dce", "full", "-neko", "tardisgo.n"}, []string{"echo", `"Neko:"`}, []string{"neko", "tardisgo.n"}, }, [][]string{ []string{"haxe", "-main", "tardis.Go", "-dce", "full", "-js", "tardisgo.js"}, []string{"echo", `"Node/JS:"`}, []string{"node", "tardisgo.js"}, }, [][]string{ []string{"haxe", "-main", "tardis.Go", "-dce", "full", "-swf", "tardisgo.swf"}, []string{"echo", `"Opening swf file (Chrome as a file association for swf works to test on OSX):"` + "\n"}, []string{"open", "tardisgo.swf"}, }, [][]string{ []string{"haxe", "-main", "tardis.Go", "-dce", "full", "-php", "php", "--php-prefix", "tgo"}, []string{"echo", `"PHP:"`}, []string{"php", "php/index.php"}, }, [][]string{ []string{"echo", ``}, // Output from this line is ignored []string{"echo", `"Neko (haxe --interp):"`}, []string{"haxe", "-main", "tardis.Go", "--interp"}, }, } results := make(chan string, len(targets)) for id, cmd := range targets { go func(i int, cl [][]string) { res := "" for j, c := range cl { exe := c[0] if exe == "echo" { res += c[1] } else { _, err := exec.LookPath(exe) if err != nil { switch exe { case "node": exe = "nodejs" // for Ubuntu default: res += "TARDISgo error - executable not found: " + exe + "\n" exe = "" // nothing to execute } } if exe != "" { out, err := exec.Command(exe, c[1:]...).CombinedOutput() if err != nil { out = append(out, []byte(err.Error())...) } if j > 0 { // ignore the output from the compile phase res += string(out) } } } } results <- res }(id, cmd) } for t := 0; t < len(targets); t++ { fmt.Println(<-results) } } } return nil }
func doMain() error { flag.Parse() args := flag.Args() conf := loader.Config{ Build: &build.Default, SourceImports: true, } // TODO(adonovan): make go/types choose its default Sizes from // build.Default or a specified *build.Context. var wordSize int64 = 8 switch conf.Build.GOARCH { case "386", "arm": wordSize = 4 } conf.TypeChecker.Sizes = &types.StdSizes{ MaxAlign: 8, WordSize: wordSize, } var mode ssa.BuilderMode for _, c := range *buildFlag { switch c { case 'D': mode |= ssa.GlobalDebug case 'P': mode |= ssa.LogPackages | ssa.BuildSerially case 'F': mode |= ssa.LogFunctions | ssa.BuildSerially case 'S': mode |= ssa.LogSource | ssa.BuildSerially case 'C': mode |= ssa.SanityCheckFunctions case 'N': mode |= ssa.NaiveForm case 'G': conf.SourceImports = false case 'L': mode |= ssa.BuildSerially default: return fmt.Errorf("unknown -build option: '%c'", c) } } var interpMode interp.Mode for _, c := range *interpFlag { switch c { case 'T': interpMode |= interp.EnableTracing case 'R': interpMode |= interp.DisableRecover default: fmt.Fprintf(os.Stderr, "ssadump: unknown -interp option: '%c'.", c) os.Exit(1) } } if len(args) == 0 { fmt.Fprint(os.Stderr, usage) os.Exit(1) } // Profiling support. if *cpuprofile != "" { f, err := os.Create(*cpuprofile) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() } // Use the initial packages from the command line. args, err := conf.FromArgs(args, *testFlag) if err != nil { return err } // The interpreter needs the runtime package. if *runFlag { conf.Import("runtime") } // Load, parse and type-check the whole program. iprog, err := conf.Load() if err != nil { return err } // Create and build SSA-form program representation. prog := ssa.Create(iprog, mode) prog.BuildAll() // Run the interpreter. if *runFlag { var main *ssa.Package pkgs := prog.AllPackages() if *testFlag { // If -test, run all packages' tests. if len(pkgs) > 0 { main = prog.CreateTestMainPackage(pkgs...) } if main == nil { return fmt.Errorf("no tests") } } else { // Otherwise, run main.main. for _, pkg := range pkgs { if pkg.Object.Name() == "main" { main = pkg if main.Func("main") == nil { return fmt.Errorf("no func main() in main package") } break } } if main == nil { return fmt.Errorf("no main package") } } if runtime.GOARCH != build.Default.GOARCH { return fmt.Errorf("cross-interpretation is not yet supported (target has GOARCH %s, interpreter has %s)", build.Default.GOARCH, runtime.GOARCH) } interp.Interpret(main, interpMode, conf.TypeChecker.Sizes, main.Object.Path(), args) } return nil }
func TestStdlib(t *testing.T) { // Load, parse and type-check the program. t0 := time.Now() var conf loader.Config conf.SourceImports = true if _, err := conf.FromArgs(allPackages(), true); err != nil { t.Errorf("FromArgs failed: %v", err) return } iprog, err := conf.Load() if err != nil { t.Fatalf("Load failed: %v", err) } t1 := time.Now() runtime.GC() var memstats runtime.MemStats runtime.ReadMemStats(&memstats) alloc := memstats.Alloc // Create SSA packages. var mode ssa.BuilderMode // Comment out these lines during benchmarking. Approx SSA build costs are noted. mode |= ssa.SanityCheckFunctions // + 2% space, + 4% time mode |= ssa.GlobalDebug // +30% space, +18% time prog := ssa.Create(iprog, mode) t2 := time.Now() // Build SSA. prog.BuildAll() t3 := time.Now() runtime.GC() runtime.ReadMemStats(&memstats) numPkgs := len(prog.AllPackages()) if want := 140; numPkgs < want { t.Errorf("Loaded only %d packages, want at least %d", numPkgs, want) } allFuncs := ssautil.AllFunctions(prog) // Check that all non-synthetic functions have distinct names. byName := make(map[string]*ssa.Function) for fn := range allFuncs { if fn.Synthetic == "" { str := fn.String() prev := byName[str] byName[str] = fn if prev != nil { t.Errorf("%s: duplicate function named %s", prog.Fset.Position(fn.Pos()), str) t.Errorf("%s: (previously defined here)", prog.Fset.Position(prev.Pos())) } } } // Dump some statistics. var numInstrs int for fn := range allFuncs { for _, b := range fn.Blocks { numInstrs += len(b.Instrs) } } // determine line count var lineCount int prog.Fset.Iterate(func(f *token.File) bool { lineCount += f.LineCount() return true }) // NB: when benchmarking, don't forget to clear the debug + // sanity builder flags for better performance. t.Log("GOMAXPROCS: ", runtime.GOMAXPROCS(0)) t.Log("#Source lines: ", lineCount) t.Log("Load/parse/typecheck: ", t1.Sub(t0)) t.Log("SSA create: ", t2.Sub(t1)) t.Log("SSA build: ", t3.Sub(t2)) // SSA stats: t.Log("#Packages: ", numPkgs) t.Log("#Functions: ", len(allFuncs)) t.Log("#Instructions: ", numInstrs) t.Log("#MB: ", int64(memstats.Alloc-alloc)/1000000) }
func TestStdlib(t *testing.T) { if !*runStdlibTest { t.Skip("skipping (slow) stdlib test (use --stdlib)") } // Load, parse and type-check the program. var conf loader.Config conf.SourceImports = true if _, err := conf.FromArgs(allPackages(), true); err != nil { t.Errorf("FromArgs failed: %v", err) return } iprog, err := conf.Load() if err != nil { t.Fatalf("Load failed: %v", err) } // Create SSA packages. prog := ssa.Create(iprog, 0) prog.BuildAll() numPkgs := len(prog.AllPackages()) if want := 140; numPkgs < want { t.Errorf("Loaded only %d packages, want at least %d", numPkgs, want) } // Determine the set of packages/tests to analyze. var testPkgs []*ssa.Package for _, info := range iprog.InitialPackages() { testPkgs = append(testPkgs, prog.Package(info.Pkg)) } testmain := prog.CreateTestMainPackage(testPkgs...) if testmain == nil { t.Fatal("analysis scope has tests") } // Run the analysis. config := &Config{ Reflection: false, // TODO(adonovan): fix remaining bug in rVCallConstraint, then enable. BuildCallGraph: true, Mains: []*ssa.Package{testmain}, } // TODO(adonovan): add some query values (affects track bits). t0 := time.Now() result, err := Analyze(config) if err != nil { t.Fatal(err) // internal error in pointer analysis } _ = result // TODO(adonovan): measure something t1 := time.Now() // Dump some statistics. allFuncs := ssautil.AllFunctions(prog) var numInstrs int for fn := range allFuncs { for _, b := range fn.Blocks { numInstrs += len(b.Instrs) } } // determine line count var lineCount int prog.Fset.Iterate(func(f *token.File) bool { lineCount += f.LineCount() return true }) t.Log("#Source lines: ", lineCount) t.Log("#Instructions: ", numInstrs) t.Log("Pointer analysis: ", t1.Sub(t0)) }