Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / cmd / ssadump / main.go
1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // ssadump: a tool for displaying and interpreting the SSA form of Go programs.
6 package main // import "golang.org/x/tools/cmd/ssadump"
7
8 import (
9         "flag"
10         "fmt"
11         "go/build"
12         "go/types"
13         "os"
14         "runtime"
15         "runtime/pprof"
16
17         "golang.org/x/tools/go/buildutil"
18         "golang.org/x/tools/go/packages"
19         "golang.org/x/tools/go/ssa"
20         "golang.org/x/tools/go/ssa/interp"
21         "golang.org/x/tools/go/ssa/ssautil"
22 )
23
24 // flags
25 var (
26         mode = ssa.BuilderMode(0)
27
28         testFlag = flag.Bool("test", false, "include implicit test packages and executables")
29
30         runFlag = flag.Bool("run", false, "interpret the SSA program")
31
32         interpFlag = flag.String("interp", "", `Options controlling the SSA test interpreter.
33 The value is a sequence of zero or more more of these letters:
34 R       disable [R]ecover() from panic; show interpreter crash instead.
35 T       [T]race execution of the program.  Best for single-threaded programs!
36 `)
37
38         cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
39
40         args stringListValue
41 )
42
43 func init() {
44         flag.Var(&mode, "build", ssa.BuilderModeDoc)
45         flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
46         flag.Var(&args, "arg", "add argument to interpreted program")
47 }
48
49 const usage = `SSA builder and interpreter.
50 Usage: ssadump [-build=[DBCSNFL]] [-test] [-run] [-interp=[TR]] [-arg=...] package...
51 Use -help flag to display options.
52
53 Examples:
54 % ssadump -build=F hello.go              # dump SSA form of a single package
55 % ssadump -build=F -test fmt             # dump SSA form of a package and its tests
56 % ssadump -run -interp=T hello.go        # interpret a program, with tracing
57
58 The -run flag causes ssadump to run the first package named main.
59
60 Interpretation of the standard "testing" package is no longer supported.
61 `
62
63 func main() {
64         if err := doMain(); err != nil {
65                 fmt.Fprintf(os.Stderr, "ssadump: %s\n", err)
66                 os.Exit(1)
67         }
68 }
69
70 func doMain() error {
71         flag.Parse()
72         if len(flag.Args()) == 0 {
73                 fmt.Fprint(os.Stderr, usage)
74                 os.Exit(1)
75         }
76
77         cfg := &packages.Config{
78                 Mode:  packages.LoadSyntax,
79                 Tests: *testFlag,
80         }
81
82         // Choose types.Sizes from conf.Build.
83         // TODO(adonovan): remove this when go/packages provides a better way.
84         var wordSize int64 = 8
85         switch build.Default.GOARCH {
86         case "386", "arm":
87                 wordSize = 4
88         }
89         sizes := &types.StdSizes{
90                 MaxAlign: 8,
91                 WordSize: wordSize,
92         }
93
94         var interpMode interp.Mode
95         for _, c := range *interpFlag {
96                 switch c {
97                 case 'T':
98                         interpMode |= interp.EnableTracing
99                 case 'R':
100                         interpMode |= interp.DisableRecover
101                 default:
102                         return fmt.Errorf("unknown -interp option: '%c'", c)
103                 }
104         }
105
106         // Profiling support.
107         if *cpuprofile != "" {
108                 f, err := os.Create(*cpuprofile)
109                 if err != nil {
110                         fmt.Fprintln(os.Stderr, err)
111                         os.Exit(1)
112                 }
113                 pprof.StartCPUProfile(f)
114                 defer pprof.StopCPUProfile()
115         }
116
117         // Load, parse and type-check the initial packages,
118         // and, if -run, their dependencies.
119         if *runFlag {
120                 cfg.Mode = packages.LoadAllSyntax
121         }
122         initial, err := packages.Load(cfg, flag.Args()...)
123         if err != nil {
124                 return err
125         }
126         if len(initial) == 0 {
127                 return fmt.Errorf("no packages")
128         }
129         if packages.PrintErrors(initial) > 0 {
130                 return fmt.Errorf("packages contain errors")
131         }
132
133         // Create SSA-form program representation.
134         prog, pkgs := ssautil.AllPackages(initial, mode)
135
136         for i, p := range pkgs {
137                 if p == nil {
138                         return fmt.Errorf("cannot build SSA for package %s", initial[i])
139                 }
140         }
141
142         if !*runFlag {
143                 // Build and display only the initial packages
144                 // (and synthetic wrappers).
145                 for _, p := range pkgs {
146                         p.Build()
147                 }
148
149         } else {
150                 // Run the interpreter.
151                 // Build SSA for all packages.
152                 prog.Build()
153
154                 // The interpreter needs the runtime package.
155                 // It is a limitation of go/packages that
156                 // we cannot add "runtime" to its initial set,
157                 // we can only check that it is present.
158                 if prog.ImportedPackage("runtime") == nil {
159                         return fmt.Errorf("-run: program does not depend on runtime")
160                 }
161
162                 if runtime.GOARCH != build.Default.GOARCH {
163                         return fmt.Errorf("cross-interpretation is not supported (target has GOARCH %s, interpreter has %s)",
164                                 build.Default.GOARCH, runtime.GOARCH)
165                 }
166
167                 // Run first main package.
168                 for _, main := range ssautil.MainPackages(pkgs) {
169                         fmt.Fprintf(os.Stderr, "Running: %s\n", main.Pkg.Path())
170                         os.Exit(interp.Interpret(main, interpMode, sizes, main.Pkg.Path(), args))
171                 }
172                 return fmt.Errorf("no main package")
173         }
174         return nil
175 }
176
177 // stringListValue is a flag.Value that accumulates strings.
178 // e.g. --flag=one --flag=two would produce []string{"one", "two"}.
179 type stringListValue []string
180
181 func newStringListValue(val []string, p *[]string) *stringListValue {
182         *p = val
183         return (*stringListValue)(p)
184 }
185
186 func (ss *stringListValue) Get() interface{} { return []string(*ss) }
187
188 func (ss *stringListValue) String() string { return fmt.Sprintf("%q", *ss) }
189
190 func (ss *stringListValue) Set(s string) error { *ss = append(*ss, s); return nil }