Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / honnef.co / go / tools@v0.0.1-2020.1.5 / ir / 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 ir
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         if v == nil {
29                 return "<nil>"
30         }
31         var from *types.Package
32         if i != nil {
33                 from = i.Parent().pkg()
34         }
35         switch v := v.(type) {
36         case Member: // *Function or *Global
37                 return v.RelString(from)
38         }
39         return v.Name()
40 }
41
42 func relType(t types.Type, from *types.Package) string {
43         return types.TypeString(t, types.RelativeTo(from))
44 }
45
46 func relString(m Member, from *types.Package) string {
47         // NB: not all globals have an Object (e.g. init$guard),
48         // so use Package().Object not Object.Package().
49         if pkg := m.Package().Pkg; pkg != nil && pkg != from {
50                 return fmt.Sprintf("%s.%s", pkg.Path(), m.Name())
51         }
52         return m.Name()
53 }
54
55 // Value.String()
56 //
57 // This method is provided only for debugging.
58 // It never appears in disassembly, which uses Value.Name().
59
60 func (v *Parameter) String() string {
61         from := v.Parent().pkg()
62         return fmt.Sprintf("Parameter <%s> {%s}", relType(v.Type(), from), v.name)
63 }
64
65 func (v *FreeVar) String() string {
66         from := v.Parent().pkg()
67         return fmt.Sprintf("FreeVar <%s> %s", relType(v.Type(), from), v.Name())
68 }
69
70 func (v *Builtin) String() string {
71         return fmt.Sprintf("Builtin %s", v.Name())
72 }
73
74 // Instruction.String()
75
76 func (v *Alloc) String() string {
77         from := v.Parent().pkg()
78         storage := "Stack"
79         if v.Heap {
80                 storage = "Heap"
81         }
82         return fmt.Sprintf("%sAlloc <%s>", storage, relType(v.Type(), from))
83 }
84
85 func (v *Sigma) String() string {
86         from := v.Parent().pkg()
87         s := fmt.Sprintf("Sigma <%s> [b%d] %s", relType(v.Type(), from), v.From.Index, v.X.Name())
88         return s
89 }
90
91 func (v *Phi) String() string {
92         var b bytes.Buffer
93         fmt.Fprintf(&b, "Phi <%s>", v.Type())
94         for i, edge := range v.Edges {
95                 b.WriteString(" ")
96                 // Be robust against malformed CFG.
97                 if v.block == nil {
98                         b.WriteString("??")
99                         continue
100                 }
101                 block := -1
102                 if i < len(v.block.Preds) {
103                         block = v.block.Preds[i].Index
104                 }
105                 fmt.Fprintf(&b, "%d:", block)
106                 edgeVal := "<nil>" // be robust
107                 if edge != nil {
108                         edgeVal = relName(edge, v)
109                 }
110                 b.WriteString(edgeVal)
111         }
112         return b.String()
113 }
114
115 func printCall(v *CallCommon, prefix string, instr Instruction) string {
116         var b bytes.Buffer
117         if !v.IsInvoke() {
118                 if value, ok := instr.(Value); ok {
119                         fmt.Fprintf(&b, "%s <%s> %s", prefix, relType(value.Type(), instr.Parent().pkg()), relName(v.Value, instr))
120                 } else {
121                         fmt.Fprintf(&b, "%s %s", prefix, relName(v.Value, instr))
122                 }
123         } else {
124                 if value, ok := instr.(Value); ok {
125                         fmt.Fprintf(&b, "%sInvoke <%s> %s.%s", prefix, relType(value.Type(), instr.Parent().pkg()), relName(v.Value, instr), v.Method.Name())
126                 } else {
127                         fmt.Fprintf(&b, "%sInvoke %s.%s", prefix, relName(v.Value, instr), v.Method.Name())
128                 }
129         }
130         for _, arg := range v.Args {
131                 b.WriteString(" ")
132                 b.WriteString(relName(arg, instr))
133         }
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, "Call", v)
143 }
144
145 func (v *BinOp) String() string {
146         return fmt.Sprintf("BinOp <%s> {%s} %s %s", relType(v.Type(), v.Parent().pkg()), v.Op.String(), relName(v.X, v), relName(v.Y, v))
147 }
148
149 func (v *UnOp) String() string {
150         return fmt.Sprintf("UnOp <%s> {%s} %s", relType(v.Type(), v.Parent().pkg()), v.Op.String(), relName(v.X, v))
151 }
152
153 func (v *Load) String() string {
154         return fmt.Sprintf("Load <%s> %s", relType(v.Type(), v.Parent().pkg()), relName(v.X, v))
155 }
156
157 func printConv(prefix string, v, x Value) string {
158         from := v.Parent().pkg()
159         return fmt.Sprintf("%s <%s> %s",
160                 prefix,
161                 relType(v.Type(), from),
162                 relName(x, v.(Instruction)))
163 }
164
165 func (v *ChangeType) String() string      { return printConv("ChangeType", v, v.X) }
166 func (v *Convert) String() string         { return printConv("Convert", v, v.X) }
167 func (v *ChangeInterface) String() string { return printConv("ChangeInterface", v, v.X) }
168 func (v *MakeInterface) String() string   { return printConv("MakeInterface", v, v.X) }
169
170 func (v *MakeClosure) String() string {
171         from := v.Parent().pkg()
172         var b bytes.Buffer
173         fmt.Fprintf(&b, "MakeClosure <%s> %s", relType(v.Type(), from), relName(v.Fn, v))
174         if v.Bindings != nil {
175                 for _, c := range v.Bindings {
176                         b.WriteString(" ")
177                         b.WriteString(relName(c, v))
178                 }
179         }
180         return b.String()
181 }
182
183 func (v *MakeSlice) String() string {
184         from := v.Parent().pkg()
185         return fmt.Sprintf("MakeSlice <%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         from := v.Parent().pkg()
193         return fmt.Sprintf("Slice <%s> %s %s %s %s",
194                 relType(v.Type(), from), relName(v.X, v), relName(v.Low, v), relName(v.High, v), relName(v.Max, v))
195 }
196
197 func (v *MakeMap) String() string {
198         res := ""
199         if v.Reserve != nil {
200                 res = relName(v.Reserve, v)
201         }
202         from := v.Parent().pkg()
203         return fmt.Sprintf("MakeMap <%s> %s", relType(v.Type(), from), res)
204 }
205
206 func (v *MakeChan) String() string {
207         from := v.Parent().pkg()
208         return fmt.Sprintf("MakeChan <%s> %s", relType(v.Type(), from), relName(v.Size, v))
209 }
210
211 func (v *FieldAddr) String() string {
212         from := v.Parent().pkg()
213         st := deref(v.X.Type()).Underlying().(*types.Struct)
214         // Be robust against a bad index.
215         name := "?"
216         if 0 <= v.Field && v.Field < st.NumFields() {
217                 name = st.Field(v.Field).Name()
218         }
219         return fmt.Sprintf("FieldAddr <%s> [%d] (%s) %s", relType(v.Type(), from), v.Field, name, relName(v.X, v))
220 }
221
222 func (v *Field) String() string {
223         st := v.X.Type().Underlying().(*types.Struct)
224         // Be robust against a bad index.
225         name := "?"
226         if 0 <= v.Field && v.Field < st.NumFields() {
227                 name = st.Field(v.Field).Name()
228         }
229         from := v.Parent().pkg()
230         return fmt.Sprintf("Field <%s> [%d] (%s) %s", relType(v.Type(), from), v.Field, name, relName(v.X, v))
231 }
232
233 func (v *IndexAddr) String() string {
234         from := v.Parent().pkg()
235         return fmt.Sprintf("IndexAddr <%s> %s %s", relType(v.Type(), from), relName(v.X, v), relName(v.Index, v))
236 }
237
238 func (v *Index) String() string {
239         from := v.Parent().pkg()
240         return fmt.Sprintf("Index <%s> %s %s", relType(v.Type(), from), relName(v.X, v), relName(v.Index, v))
241 }
242
243 func (v *MapLookup) String() string {
244         from := v.Parent().pkg()
245         return fmt.Sprintf("MapLookup <%s> %s %s", relType(v.Type(), from), relName(v.X, v), relName(v.Index, v))
246 }
247
248 func (v *StringLookup) String() string {
249         from := v.Parent().pkg()
250         return fmt.Sprintf("StringLookup <%s> %s %s", relType(v.Type(), from), relName(v.X, v), relName(v.Index, v))
251 }
252
253 func (v *Range) String() string {
254         from := v.Parent().pkg()
255         return fmt.Sprintf("Range <%s> %s", relType(v.Type(), from), relName(v.X, v))
256 }
257
258 func (v *Next) String() string {
259         from := v.Parent().pkg()
260         return fmt.Sprintf("Next <%s> %s", relType(v.Type(), from), relName(v.Iter, v))
261 }
262
263 func (v *TypeAssert) String() string {
264         from := v.Parent().pkg()
265         return fmt.Sprintf("TypeAssert <%s> %s", relType(v.Type(), from), relName(v.X, v))
266 }
267
268 func (v *Extract) String() string {
269         from := v.Parent().pkg()
270         name := v.Tuple.Type().(*types.Tuple).At(v.Index).Name()
271         return fmt.Sprintf("Extract <%s> [%d] (%s) %s", relType(v.Type(), from), v.Index, name, relName(v.Tuple, v))
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         str := fmt.Sprintf("Jump → b%d", block)
281         if s.Comment != "" {
282                 str = fmt.Sprintf("%s # %s", str, s.Comment)
283         }
284         return str
285 }
286
287 func (s *Unreachable) String() string {
288         // Be robust against malformed CFG.
289         block := -1
290         if s.block != nil && len(s.block.Succs) == 1 {
291                 block = s.block.Succs[0].Index
292         }
293         return fmt.Sprintf("Unreachable → b%d", block)
294 }
295
296 func (s *If) String() string {
297         // Be robust against malformed CFG.
298         tblock, fblock := -1, -1
299         if s.block != nil && len(s.block.Succs) == 2 {
300                 tblock = s.block.Succs[0].Index
301                 fblock = s.block.Succs[1].Index
302         }
303         return fmt.Sprintf("If %s → b%d b%d", relName(s.Cond, s), tblock, fblock)
304 }
305
306 func (s *ConstantSwitch) String() string {
307         var b bytes.Buffer
308         fmt.Fprintf(&b, "ConstantSwitch %s", relName(s.Tag, s))
309         for _, cond := range s.Conds {
310                 fmt.Fprintf(&b, " %s", relName(cond, s))
311         }
312         fmt.Fprint(&b, " →")
313         for _, succ := range s.block.Succs {
314                 fmt.Fprintf(&b, " b%d", succ.Index)
315         }
316         return b.String()
317 }
318
319 func (s *TypeSwitch) String() string {
320         from := s.Parent().pkg()
321         var b bytes.Buffer
322         fmt.Fprintf(&b, "TypeSwitch <%s> %s", relType(s.typ, from), relName(s.Tag, s))
323         for _, cond := range s.Conds {
324                 fmt.Fprintf(&b, " %q", relType(cond, s.block.parent.pkg()))
325         }
326         return b.String()
327 }
328
329 func (s *Go) String() string {
330         return printCall(&s.Call, "Go", s)
331 }
332
333 func (s *Panic) String() string {
334         // Be robust against malformed CFG.
335         block := -1
336         if s.block != nil && len(s.block.Succs) == 1 {
337                 block = s.block.Succs[0].Index
338         }
339         return fmt.Sprintf("Panic %s → b%d", relName(s.X, s), block)
340 }
341
342 func (s *Return) String() string {
343         var b bytes.Buffer
344         b.WriteString("Return")
345         for _, r := range s.Results {
346                 b.WriteString(" ")
347                 b.WriteString(relName(r, s))
348         }
349         return b.String()
350 }
351
352 func (*RunDefers) String() string {
353         return "RunDefers"
354 }
355
356 func (s *Send) String() string {
357         return fmt.Sprintf("Send %s %s", relName(s.Chan, s), relName(s.X, s))
358 }
359
360 func (recv *Recv) String() string {
361         from := recv.Parent().pkg()
362         return fmt.Sprintf("Recv <%s> %s", relType(recv.Type(), from), relName(recv.Chan, recv))
363 }
364
365 func (s *Defer) String() string {
366         return printCall(&s.Call, "Defer", s)
367 }
368
369 func (s *Select) String() string {
370         var b bytes.Buffer
371         for i, st := range s.States {
372                 if i > 0 {
373                         b.WriteString(", ")
374                 }
375                 if st.Dir == types.RecvOnly {
376                         b.WriteString("<-")
377                         b.WriteString(relName(st.Chan, s))
378                 } else {
379                         b.WriteString(relName(st.Chan, s))
380                         b.WriteString("<-")
381                         b.WriteString(relName(st.Send, s))
382                 }
383         }
384         non := ""
385         if !s.Blocking {
386                 non = "Non"
387         }
388         from := s.Parent().pkg()
389         return fmt.Sprintf("Select%sBlocking <%s> [%s]", non, relType(s.Type(), from), b.String())
390 }
391
392 func (s *Store) String() string {
393         return fmt.Sprintf("Store {%s} %s %s",
394                 s.Val.Type(), relName(s.Addr, s), relName(s.Val, s))
395 }
396
397 func (s *BlankStore) String() string {
398         return fmt.Sprintf("BlankStore %s", relName(s.Val, s))
399 }
400
401 func (s *MapUpdate) String() string {
402         return fmt.Sprintf("MapUpdate %s %s %s", relName(s.Map, s), relName(s.Key, s), relName(s.Value, s))
403 }
404
405 func (s *DebugRef) String() string {
406         p := s.Parent().Prog.Fset.Position(s.Pos())
407         var descr interface{}
408         if s.object != nil {
409                 descr = s.object // e.g. "var x int"
410         } else {
411                 descr = reflect.TypeOf(s.Expr) // e.g. "*ast.CallExpr"
412         }
413         var addr string
414         if s.IsAddr {
415                 addr = "address of "
416         }
417         return fmt.Sprintf("; %s%s @ %d:%d is %s", addr, descr, p.Line, p.Column, s.X.Name())
418 }
419
420 func (p *Package) String() string {
421         return "package " + p.Pkg.Path()
422 }
423
424 var _ io.WriterTo = (*Package)(nil) // *Package implements io.Writer
425
426 func (p *Package) WriteTo(w io.Writer) (int64, error) {
427         var buf bytes.Buffer
428         WritePackage(&buf, p)
429         n, err := w.Write(buf.Bytes())
430         return int64(n), err
431 }
432
433 // WritePackage writes to buf a human-readable summary of p.
434 func WritePackage(buf *bytes.Buffer, p *Package) {
435         fmt.Fprintf(buf, "%s:\n", p)
436
437         var names []string
438         maxname := 0
439         for name := range p.Members {
440                 if l := len(name); l > maxname {
441                         maxname = l
442                 }
443                 names = append(names, name)
444         }
445
446         from := p.Pkg
447         sort.Strings(names)
448         for _, name := range names {
449                 switch mem := p.Members[name].(type) {
450                 case *NamedConst:
451                         fmt.Fprintf(buf, "  const %-*s %s = %s\n",
452                                 maxname, name, mem.Name(), mem.Value.RelString(from))
453
454                 case *Function:
455                         fmt.Fprintf(buf, "  func  %-*s %s\n",
456                                 maxname, name, relType(mem.Type(), from))
457
458                 case *Type:
459                         fmt.Fprintf(buf, "  type  %-*s %s\n",
460                                 maxname, name, relType(mem.Type().Underlying(), from))
461                         for _, meth := range typeutil.IntuitiveMethodSet(mem.Type(), &p.Prog.MethodSets) {
462                                 fmt.Fprintf(buf, "    %s\n", types.SelectionString(meth, types.RelativeTo(from)))
463                         }
464
465                 case *Global:
466                         fmt.Fprintf(buf, "  var   %-*s %s\n",
467                                 maxname, name, relType(mem.Type().(*types.Pointer).Elem(), from))
468                 }
469         }
470
471         fmt.Fprintf(buf, "\n")
472 }