+++ /dev/null
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// ssadump: a tool for displaying and interpreting the SSA form of Go programs.
-package main // import "golang.org/x/tools/cmd/ssadump"
-
-import (
- "flag"
- "fmt"
- "go/build"
- "go/types"
- "os"
- "runtime"
- "runtime/pprof"
-
- "golang.org/x/tools/go/buildutil"
- "golang.org/x/tools/go/packages"
- "golang.org/x/tools/go/ssa"
- "golang.org/x/tools/go/ssa/interp"
- "golang.org/x/tools/go/ssa/ssautil"
-)
-
-// flags
-var (
- mode = ssa.BuilderMode(0)
-
- testFlag = flag.Bool("test", false, "include implicit test packages and executables")
-
- runFlag = flag.Bool("run", false, "interpret the SSA program")
-
- interpFlag = flag.String("interp", "", `Options controlling the SSA test interpreter.
-The value is a sequence of zero or more more of these letters:
-R disable [R]ecover() from panic; show interpreter crash instead.
-T [T]race execution of the program. Best for single-threaded programs!
-`)
-
- cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
-
- args stringListValue
-)
-
-func init() {
- flag.Var(&mode, "build", ssa.BuilderModeDoc)
- flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
- flag.Var(&args, "arg", "add argument to interpreted program")
-}
-
-const usage = `SSA builder and interpreter.
-Usage: ssadump [-build=[DBCSNFL]] [-test] [-run] [-interp=[TR]] [-arg=...] package...
-Use -help flag to display options.
-
-Examples:
-% ssadump -build=F hello.go # dump SSA form of a single package
-% ssadump -build=F -test fmt # dump SSA form of a package and its tests
-% ssadump -run -interp=T hello.go # interpret a program, with tracing
-
-The -run flag causes ssadump to run the first package named main.
-
-Interpretation of the standard "testing" package is no longer supported.
-`
-
-func main() {
- if err := doMain(); err != nil {
- fmt.Fprintf(os.Stderr, "ssadump: %s\n", err)
- os.Exit(1)
- }
-}
-
-func doMain() error {
- flag.Parse()
- if len(flag.Args()) == 0 {
- fmt.Fprint(os.Stderr, usage)
- os.Exit(1)
- }
-
- cfg := &packages.Config{
- Mode: packages.LoadSyntax,
- Tests: *testFlag,
- }
-
- // Choose types.Sizes from conf.Build.
- // TODO(adonovan): remove this when go/packages provides a better way.
- var wordSize int64 = 8
- switch build.Default.GOARCH {
- case "386", "arm":
- wordSize = 4
- }
- sizes := &types.StdSizes{
- MaxAlign: 8,
- WordSize: wordSize,
- }
-
- var interpMode interp.Mode
- for _, c := range *interpFlag {
- switch c {
- case 'T':
- interpMode |= interp.EnableTracing
- case 'R':
- interpMode |= interp.DisableRecover
- default:
- return fmt.Errorf("unknown -interp option: '%c'", c)
- }
- }
-
- // 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()
- }
-
- // Load, parse and type-check the initial packages,
- // and, if -run, their dependencies.
- if *runFlag {
- cfg.Mode = packages.LoadAllSyntax
- }
- initial, err := packages.Load(cfg, flag.Args()...)
- if err != nil {
- return err
- }
- if len(initial) == 0 {
- return fmt.Errorf("no packages")
- }
- if packages.PrintErrors(initial) > 0 {
- return fmt.Errorf("packages contain errors")
- }
-
- // Create SSA-form program representation.
- prog, pkgs := ssautil.AllPackages(initial, mode)
-
- for i, p := range pkgs {
- if p == nil {
- return fmt.Errorf("cannot build SSA for package %s", initial[i])
- }
- }
-
- if !*runFlag {
- // Build and display only the initial packages
- // (and synthetic wrappers).
- for _, p := range pkgs {
- p.Build()
- }
-
- } else {
- // Run the interpreter.
- // Build SSA for all packages.
- prog.Build()
-
- // The interpreter needs the runtime package.
- // It is a limitation of go/packages that
- // we cannot add "runtime" to its initial set,
- // we can only check that it is present.
- if prog.ImportedPackage("runtime") == nil {
- return fmt.Errorf("-run: program does not depend on runtime")
- }
-
- if runtime.GOARCH != build.Default.GOARCH {
- return fmt.Errorf("cross-interpretation is not supported (target has GOARCH %s, interpreter has %s)",
- build.Default.GOARCH, runtime.GOARCH)
- }
-
- // Run first main package.
- for _, main := range ssautil.MainPackages(pkgs) {
- fmt.Fprintf(os.Stderr, "Running: %s\n", main.Pkg.Path())
- os.Exit(interp.Interpret(main, interpMode, sizes, main.Pkg.Path(), args))
- }
- return fmt.Errorf("no main package")
- }
- return nil
-}
-
-// stringListValue is a flag.Value that accumulates strings.
-// e.g. --flag=one --flag=two would produce []string{"one", "two"}.
-type stringListValue []string
-
-func newStringListValue(val []string, p *[]string) *stringListValue {
- *p = val
- return (*stringListValue)(p)
-}
-
-func (ss *stringListValue) Get() interface{} { return []string(*ss) }
-
-func (ss *stringListValue) String() string { return fmt.Sprintf("%q", *ss) }
-
-func (ss *stringListValue) Set(s string) error { *ss = append(*ss, s); return nil }