Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / go / ssa / print.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 package ssa
6
7 // This file implements the String() methods for all Value and
8 // Instruction types.
9
10 import (
11         "bytes"
12         "fmt"
13         "go/types"
14         "io"
15         "reflect"
16         "sort"
17
18         "golang.org/x/tools/go/types/typeutil"
19 )
20
21 // relName returns the name of v relative to i.
22 // In most cases, this is identical to v.Name(), but references to
23 // Functions (including methods) and Globals use RelString and
24 // all types are displayed with relType, so that only cross-package
25 // references are package-qualified.
26 //
27 func relName(v Value, i Instruction) string {
28         var from *types.Package
29         if i != nil {
30                 from = i.Parent().pkg()
31         }
32         switch v := v.(type) {
33         case Member: // *Function or *Global
34                 return v.RelString(from)
35         case *Const:
36                 return v.RelString(from)
37         }
38         return v.Name()
39 }
40
41 func relType(t types.Type, from *types.Package) string {
42         return types.TypeString(t, types.RelativeTo(from))
43 }
44
45 func relString(m Member, from *types.Package) string {
46         // NB: not all globals have an Object (e.g. init$guard),
47         // so use Package().Object not Object.Package().
48         if pkg := m.Package().Pkg; pkg != nil && pkg != from {
49                 return fmt.Sprintf("%s.%s", pkg.Path(), m.Name())
50         }
51         return m.Name()
52 }
53
54 // Value.String()
55 //
56 // This method is provided only for debugging.
57 // It never appears in disassembly, which uses Value.Name().
58
59 func (v *Parameter) String() string {
60         from := v.Parent().pkg()
61         return fmt.Sprintf("parameter %s : %s", v.Name(), relType(v.Type(), from))
62 }
63
64 func (v *FreeVar) String() string {
65         from := v.Parent().pkg()
66         return fmt.Sprintf("freevar %s : %s", v.Name(), relType(v.Type(), from))
67 }
68
69 func (v *Builtin) String() string {
70         return fmt.Sprintf("builtin %s", v.Name())
71 }
72
73 // Instruction.String()
74
75 func (v *Alloc) String() string {
76         op := "local"
77         if v.Heap {
78                 op = "new"
79         }
80         from := v.Parent().pkg()
81         return fmt.Sprintf("%s %s (%s)", op, relType(deref(v.Type()), from), v.Comment)
82 }
83
84 func (v *Phi) String() string {
85         var b bytes.Buffer
86         b.WriteString("phi [")
87         for i, edge := range v.Edges {
88                 if i > 0 {
89                         b.WriteString(", ")
90                 }
91                 // Be robust against malformed CFG.
92                 if v.block == nil {
93                         b.WriteString("??")
94                         continue
95                 }
96                 block := -1
97                 if i < len(v.block.Preds) {
98                         block = v.block.Preds[i].Index
99                 }
100                 fmt.Fprintf(&b, "%d: ", block)
101                 edgeVal := "<nil>" // be robust
102                 if edge != nil {
103                         edgeVal = relName(edge, v)
104                 }
105                 b.WriteString(edgeVal)
106         }
107         b.WriteString("]")
108         if v.Comment != "" {
109                 b.WriteString(" #")
110                 b.WriteString(v.Comment)
111         }
112         return b.String()
113 }
114
115 func printCall(v *CallCommon, prefix string, instr Instruction) string {
116         var b bytes.Buffer
117         b.WriteString(prefix)
118         if !v.IsInvoke() {
119                 b.WriteString(relName(v.Value, instr))
120         } else {
121                 fmt.Fprintf(&b, "invoke %s.%s", relName(v.Value, instr), v.Method.Name())
122         }
123         b.WriteString("(")
124         for i, arg := range v.Args {
125                 if i > 0 {
126                         b.WriteString(", ")
127                 }
128                 b.WriteString(relName(arg, instr))
129         }
130         if v.Signature().Variadic() {
131                 b.WriteString("...")
132         }
133         b.WriteString(")")
134         return b.String()
135 }
136
137 func (c *CallCommon) String() string {
138         return printCall(c, "", nil)
139 }
140
141 func (v *Call) String() string {
142         return printCall(&v.Call, "", v)
143 }
144
145 func (v *BinOp) String() string {
146         return fmt.Sprintf("%s %s %s", relName(v.X, v), v.Op.String(), relName(v.Y, v))
147 }
148
149 func (v *UnOp) String() string {
150         return fmt.Sprintf("%s%s%s", v.Op, relName(v.X, v), commaOk(v.CommaOk))
151 }
152
153 func printConv(prefix string, v, x Value) string {
154         from := v.Parent().pkg()
155         return fmt.Sprintf("%s %s <- %s (%s)",
156                 prefix,
157                 relType(v.Type(), from),
158                 relType(x.Type(), from),
159                 relName(x, v.(Instruction)))
160 }
161
162 func (v *ChangeType) String() string      { return printConv("changetype", v, v.X) }
163 func (v *Convert) String() string         { return printConv("convert", v, v.X) }
164 func (v *ChangeInterface) String() string { return printConv("change interface", v, v.X) }
165 func (v *MakeInterface) String() string   { return printConv("make", v, v.X) }
166
167 func (v *MakeClosure) String() string {
168         var b bytes.Buffer
169         fmt.Fprintf(&b, "make closure %s", relName(v.Fn, v))
170         if v.Bindings != nil {
171                 b.WriteString(" [")
172                 for i, c := range v.Bindings {
173                         if i > 0 {
174                                 b.WriteString(", ")
175                         }
176                         b.WriteString(relName(c, v))
177                 }
178                 b.WriteString("]")
179         }
180         return b.String()
181 }
182
183 func (v *MakeSlice) String() string {
184         from := v.Parent().pkg()
185         return fmt.Sprintf("make %s %s %s",
186                 relType(v.Type(), from),
187                 relName(v.Len, v),
188                 relName(v.Cap, v))
189 }
190
191 func (v *Slice) String() string {
192         var b bytes.Buffer
193         b.WriteString("slice ")
194         b.WriteString(relName(v.X, v))
195         b.WriteString("[")
196         if v.Low != nil {
197                 b.WriteString(relName(v.Low, v))
198         }
199         b.WriteString(":")
200         if v.High != nil {
201                 b.WriteString(relName(v.High, v))
202         }
203         if v.Max != nil {
204                 b.WriteString(":")
205                 b.WriteString(relName(v.Max, v))
206         }
207         b.WriteString("]")
208         return b.String()
209 }
210
211 func (v *MakeMap) String() string {
212         res := ""
213         if v.Reserve != nil {
214                 res = relName(v.Reserve, v)
215         }
216         from := v.Parent().pkg()
217         return fmt.Sprintf("make %s %s", relType(v.Type(), from), res)
218 }
219
220 func (v *MakeChan) String() string {
221         from := v.Parent().pkg()
222         return fmt.Sprintf("make %s %s", relType(v.Type(), from), relName(v.Size, v))
223 }
224
225 func (v *FieldAddr) String() string {
226         st := deref(v.X.Type()).Underlying().(*types.Struct)
227         // Be robust against a bad index.
228         name := "?"
229         if 0 <= v.Field && v.Field < st.NumFields() {
230                 name = st.Field(v.Field).Name()
231         }
232         return fmt.Sprintf("&%s.%s [#%d]", relName(v.X, v), name, v.Field)
233 }
234
235 func (v *Field) String() string {
236         st := v.X.Type().Underlying().(*types.Struct)
237         // Be robust against a bad index.
238         name := "?"
239         if 0 <= v.Field && v.Field < st.NumFields() {
240                 name = st.Field(v.Field).Name()
241         }
242         return fmt.Sprintf("%s.%s [#%d]", relName(v.X, v), name, v.Field)
243 }
244
245 func (v *IndexAddr) String() string {
246         return fmt.Sprintf("&%s[%s]", relName(v.X, v), relName(v.Index, v))
247 }
248
249 func (v *Index) String() string {
250         return fmt.Sprintf("%s[%s]", relName(v.X, v), relName(v.Index, v))
251 }
252
253 func (v *Lookup) String() string {
254         return fmt.Sprintf("%s[%s]%s", relName(v.X, v), relName(v.Index, v), commaOk(v.CommaOk))
255 }
256
257 func (v *Range) String() string {
258         return "range " + relName(v.X, v)
259 }
260
261 func (v *Next) String() string {
262         return "next " + relName(v.Iter, v)
263 }
264
265 func (v *TypeAssert) String() string {
266         from := v.Parent().pkg()
267         return fmt.Sprintf("typeassert%s %s.(%s)", commaOk(v.CommaOk), relName(v.X, v), relType(v.AssertedType, from))
268 }
269
270 func (v *Extract) String() string {
271         return fmt.Sprintf("extract %s #%d", relName(v.Tuple, v), v.Index)
272 }
273
274 func (s *Jump) String() string {
275         // Be robust against malformed CFG.
276         block := -1
277         if s.block != nil && len(s.block.Succs) == 1 {
278                 block = s.block.Succs[0].Index
279         }
280         return fmt.Sprintf("jump %d", block)
281 }
282
283 func (s *If) String() string {
284         // Be robust against malformed CFG.
285         tblock, fblock := -1, -1
286         if s.block != nil && len(s.block.Succs) == 2 {
287                 tblock = s.block.Succs[0].Index
288                 fblock = s.block.Succs[1].Index
289         }
290         return fmt.Sprintf("if %s goto %d else %d", relName(s.Cond, s), tblock, fblock)
291 }
292
293 func (s *Go) String() string {
294         return printCall(&s.Call, "go ", s)
295 }
296
297 func (s *Panic) String() string {
298         return "panic " + relName(s.X, s)
299 }
300
301 func (s *Return) String() string {
302         var b bytes.Buffer
303         b.WriteString("return")
304         for i, r := range s.Results {
305                 if i == 0 {
306                         b.WriteString(" ")
307                 } else {
308                         b.WriteString(", ")
309                 }
310                 b.WriteString(relName(r, s))
311         }
312         return b.String()
313 }
314
315 func (*RunDefers) String() string {
316         return "rundefers"
317 }
318
319 func (s *Send) String() string {
320         return fmt.Sprintf("send %s <- %s", relName(s.Chan, s), relName(s.X, s))
321 }
322
323 func (s *Defer) String() string {
324         return printCall(&s.Call, "defer ", s)
325 }
326
327 func (s *Select) String() string {
328         var b bytes.Buffer
329         for i, st := range s.States {
330                 if i > 0 {
331                         b.WriteString(", ")
332                 }
333                 if st.Dir == types.RecvOnly {
334                         b.WriteString("<-")
335                         b.WriteString(relName(st.Chan, s))
336                 } else {
337                         b.WriteString(relName(st.Chan, s))
338                         b.WriteString("<-")
339                         b.WriteString(relName(st.Send, s))
340                 }
341         }
342         non := ""
343         if !s.Blocking {
344                 non = "non"
345         }
346         return fmt.Sprintf("select %sblocking [%s]", non, b.String())
347 }
348
349 func (s *Store) String() string {
350         return fmt.Sprintf("*%s = %s", relName(s.Addr, s), relName(s.Val, s))
351 }
352
353 func (s *MapUpdate) String() string {
354         return fmt.Sprintf("%s[%s] = %s", relName(s.Map, s), relName(s.Key, s), relName(s.Value, s))
355 }
356
357 func (s *DebugRef) String() string {
358         p := s.Parent().Prog.Fset.Position(s.Pos())
359         var descr interface{}
360         if s.object != nil {
361                 descr = s.object // e.g. "var x int"
362         } else {
363                 descr = reflect.TypeOf(s.Expr) // e.g. "*ast.CallExpr"
364         }
365         var addr string
366         if s.IsAddr {
367                 addr = "address of "
368         }
369         return fmt.Sprintf("; %s%s @ %d:%d is %s", addr, descr, p.Line, p.Column, s.X.Name())
370 }
371
372 func (p *Package) String() string {
373         return "package " + p.Pkg.Path()
374 }
375
376 var _ io.WriterTo = (*Package)(nil) // *Package implements io.Writer
377
378 func (p *Package) WriteTo(w io.Writer) (int64, error) {
379         var buf bytes.Buffer
380         WritePackage(&buf, p)
381         n, err := w.Write(buf.Bytes())
382         return int64(n), err
383 }
384
385 // WritePackage writes to buf a human-readable summary of p.
386 func WritePackage(buf *bytes.Buffer, p *Package) {
387         fmt.Fprintf(buf, "%s:\n", p)
388
389         var names []string
390         maxname := 0
391         for name := range p.Members {
392                 if l := len(name); l > maxname {
393                         maxname = l
394                 }
395                 names = append(names, name)
396         }
397
398         from := p.Pkg
399         sort.Strings(names)
400         for _, name := range names {
401                 switch mem := p.Members[name].(type) {
402                 case *NamedConst:
403                         fmt.Fprintf(buf, "  const %-*s %s = %s\n",
404                                 maxname, name, mem.Name(), mem.Value.RelString(from))
405
406                 case *Function:
407                         fmt.Fprintf(buf, "  func  %-*s %s\n",
408                                 maxname, name, relType(mem.Type(), from))
409
410                 case *Type:
411                         fmt.Fprintf(buf, "  type  %-*s %s\n",
412                                 maxname, name, relType(mem.Type().Underlying(), from))
413                         for _, meth := range typeutil.IntuitiveMethodSet(mem.Type(), &p.Prog.MethodSets) {
414                                 fmt.Fprintf(buf, "    %s\n", types.SelectionString(meth, types.RelativeTo(from)))
415                         }
416
417                 case *Global:
418                         fmt.Fprintf(buf, "  var   %-*s %s\n",
419                                 maxname, name, relType(mem.Type().(*types.Pointer).Elem(), from))
420                 }
421         }
422
423         fmt.Fprintf(buf, "\n")
424 }
425
426 func commaOk(x bool) string {
427         if x {
428                 return ",ok"
429         }
430         return ""
431 }