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 / emit.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 // Helpers for emitting IR instructions.
8
9 import (
10         "fmt"
11         "go/ast"
12         "go/constant"
13         "go/token"
14         "go/types"
15 )
16
17 // emitNew emits to f a new (heap Alloc) instruction allocating an
18 // object of type typ.  pos is the optional source location.
19 //
20 func emitNew(f *Function, typ types.Type, source ast.Node) *Alloc {
21         v := &Alloc{Heap: true}
22         v.setType(types.NewPointer(typ))
23         f.emit(v, source)
24         return v
25 }
26
27 // emitLoad emits to f an instruction to load the address addr into a
28 // new temporary, and returns the value so defined.
29 //
30 func emitLoad(f *Function, addr Value, source ast.Node) *Load {
31         v := &Load{X: addr}
32         v.setType(deref(addr.Type()))
33         f.emit(v, source)
34         return v
35 }
36
37 func emitRecv(f *Function, ch Value, commaOk bool, typ types.Type, source ast.Node) Value {
38         recv := &Recv{
39                 Chan:    ch,
40                 CommaOk: commaOk,
41         }
42         recv.setType(typ)
43         return f.emit(recv, source)
44 }
45
46 // emitDebugRef emits to f a DebugRef pseudo-instruction associating
47 // expression e with value v.
48 //
49 func emitDebugRef(f *Function, e ast.Expr, v Value, isAddr bool) {
50         if !f.debugInfo() {
51                 return // debugging not enabled
52         }
53         if v == nil || e == nil {
54                 panic("nil")
55         }
56         var obj types.Object
57         e = unparen(e)
58         if id, ok := e.(*ast.Ident); ok {
59                 if isBlankIdent(id) {
60                         return
61                 }
62                 obj = f.Pkg.objectOf(id)
63                 switch obj.(type) {
64                 case *types.Nil, *types.Const, *types.Builtin:
65                         return
66                 }
67         }
68         f.emit(&DebugRef{
69                 X:      v,
70                 Expr:   e,
71                 IsAddr: isAddr,
72                 object: obj,
73         }, nil)
74 }
75
76 // emitArith emits to f code to compute the binary operation op(x, y)
77 // where op is an eager shift, logical or arithmetic operation.
78 // (Use emitCompare() for comparisons and Builder.logicalBinop() for
79 // non-eager operations.)
80 //
81 func emitArith(f *Function, op token.Token, x, y Value, t types.Type, source ast.Node) Value {
82         switch op {
83         case token.SHL, token.SHR:
84                 x = emitConv(f, x, t, source)
85                 // y may be signed or an 'untyped' constant.
86                 // TODO(adonovan): whence signed values?
87                 if b, ok := y.Type().Underlying().(*types.Basic); ok && b.Info()&types.IsUnsigned == 0 {
88                         y = emitConv(f, y, types.Typ[types.Uint64], source)
89                 }
90
91         case token.ADD, token.SUB, token.MUL, token.QUO, token.REM, token.AND, token.OR, token.XOR, token.AND_NOT:
92                 x = emitConv(f, x, t, source)
93                 y = emitConv(f, y, t, source)
94
95         default:
96                 panic("illegal op in emitArith: " + op.String())
97
98         }
99         v := &BinOp{
100                 Op: op,
101                 X:  x,
102                 Y:  y,
103         }
104         v.setType(t)
105         return f.emit(v, source)
106 }
107
108 // emitCompare emits to f code compute the boolean result of
109 // comparison comparison 'x op y'.
110 //
111 func emitCompare(f *Function, op token.Token, x, y Value, source ast.Node) Value {
112         xt := x.Type().Underlying()
113         yt := y.Type().Underlying()
114
115         // Special case to optimise a tagless SwitchStmt so that
116         // these are equivalent
117         //   switch { case e: ...}
118         //   switch true { case e: ... }
119         //   if e==true { ... }
120         // even in the case when e's type is an interface.
121         // TODO(adonovan): opt: generalise to x==true, false!=y, etc.
122         if x, ok := x.(*Const); ok && op == token.EQL && x.Value != nil && x.Value.Kind() == constant.Bool && constant.BoolVal(x.Value) {
123                 if yt, ok := yt.(*types.Basic); ok && yt.Info()&types.IsBoolean != 0 {
124                         return y
125                 }
126         }
127
128         if types.Identical(xt, yt) {
129                 // no conversion necessary
130         } else if _, ok := xt.(*types.Interface); ok {
131                 y = emitConv(f, y, x.Type(), source)
132         } else if _, ok := yt.(*types.Interface); ok {
133                 x = emitConv(f, x, y.Type(), source)
134         } else if _, ok := x.(*Const); ok {
135                 x = emitConv(f, x, y.Type(), source)
136         } else if _, ok := y.(*Const); ok {
137                 y = emitConv(f, y, x.Type(), source)
138                 //lint:ignore SA9003 no-op
139         } else {
140                 // other cases, e.g. channels.  No-op.
141         }
142
143         v := &BinOp{
144                 Op: op,
145                 X:  x,
146                 Y:  y,
147         }
148         v.setType(tBool)
149         return f.emit(v, source)
150 }
151
152 // isValuePreserving returns true if a conversion from ut_src to
153 // ut_dst is value-preserving, i.e. just a change of type.
154 // Precondition: neither argument is a named type.
155 //
156 func isValuePreserving(ut_src, ut_dst types.Type) bool {
157         // Identical underlying types?
158         if structTypesIdentical(ut_dst, ut_src) {
159                 return true
160         }
161
162         switch ut_dst.(type) {
163         case *types.Chan:
164                 // Conversion between channel types?
165                 _, ok := ut_src.(*types.Chan)
166                 return ok
167
168         case *types.Pointer:
169                 // Conversion between pointers with identical base types?
170                 _, ok := ut_src.(*types.Pointer)
171                 return ok
172         }
173         return false
174 }
175
176 // emitConv emits to f code to convert Value val to exactly type typ,
177 // and returns the converted value.  Implicit conversions are required
178 // by language assignability rules in assignments, parameter passing,
179 // etc.  Conversions cannot fail dynamically.
180 //
181 func emitConv(f *Function, val Value, typ types.Type, source ast.Node) Value {
182         t_src := val.Type()
183
184         // Identical types?  Conversion is a no-op.
185         if types.Identical(t_src, typ) {
186                 return val
187         }
188
189         ut_dst := typ.Underlying()
190         ut_src := t_src.Underlying()
191
192         // Just a change of type, but not value or representation?
193         if isValuePreserving(ut_src, ut_dst) {
194                 c := &ChangeType{X: val}
195                 c.setType(typ)
196                 return f.emit(c, source)
197         }
198
199         // Conversion to, or construction of a value of, an interface type?
200         if _, ok := ut_dst.(*types.Interface); ok {
201                 // Assignment from one interface type to another?
202                 if _, ok := ut_src.(*types.Interface); ok {
203                         c := &ChangeInterface{X: val}
204                         c.setType(typ)
205                         return f.emit(c, source)
206                 }
207
208                 // Untyped nil constant?  Return interface-typed nil constant.
209                 if ut_src == tUntypedNil {
210                         return emitConst(f, nilConst(typ))
211                 }
212
213                 // Convert (non-nil) "untyped" literals to their default type.
214                 if t, ok := ut_src.(*types.Basic); ok && t.Info()&types.IsUntyped != 0 {
215                         val = emitConv(f, val, types.Default(ut_src), source)
216                 }
217
218                 f.Pkg.Prog.needMethodsOf(val.Type())
219                 mi := &MakeInterface{X: val}
220                 mi.setType(typ)
221                 return f.emit(mi, source)
222         }
223
224         // Conversion of a compile-time constant value?
225         if c, ok := val.(*Const); ok {
226                 if _, ok := ut_dst.(*types.Basic); ok || c.IsNil() {
227                         // Conversion of a compile-time constant to
228                         // another constant type results in a new
229                         // constant of the destination type and
230                         // (initially) the same abstract value.
231                         // We don't truncate the value yet.
232                         return emitConst(f, NewConst(c.Value, typ))
233                 }
234
235                 // We're converting from constant to non-constant type,
236                 // e.g. string -> []byte/[]rune.
237         }
238
239         // A representation-changing conversion?
240         // At least one of {ut_src,ut_dst} must be *Basic.
241         // (The other may be []byte or []rune.)
242         _, ok1 := ut_src.(*types.Basic)
243         _, ok2 := ut_dst.(*types.Basic)
244         if ok1 || ok2 {
245                 c := &Convert{X: val}
246                 c.setType(typ)
247                 return f.emit(c, source)
248         }
249
250         panic(fmt.Sprintf("in %s: cannot convert %s (%s) to %s", f, val, val.Type(), typ))
251 }
252
253 // emitStore emits to f an instruction to store value val at location
254 // addr, applying implicit conversions as required by assignability rules.
255 //
256 func emitStore(f *Function, addr, val Value, source ast.Node) *Store {
257         s := &Store{
258                 Addr: addr,
259                 Val:  emitConv(f, val, deref(addr.Type()), source),
260         }
261         // make sure we call getMem after the call to emitConv, which may
262         // itself update the memory state
263         f.emit(s, source)
264         return s
265 }
266
267 // emitJump emits to f a jump to target, and updates the control-flow graph.
268 // Postcondition: f.currentBlock is nil.
269 //
270 func emitJump(f *Function, target *BasicBlock, source ast.Node) *Jump {
271         b := f.currentBlock
272         j := new(Jump)
273         b.emit(j, source)
274         addEdge(b, target)
275         f.currentBlock = nil
276         return j
277 }
278
279 // emitIf emits to f a conditional jump to tblock or fblock based on
280 // cond, and updates the control-flow graph.
281 // Postcondition: f.currentBlock is nil.
282 //
283 func emitIf(f *Function, cond Value, tblock, fblock *BasicBlock, source ast.Node) *If {
284         b := f.currentBlock
285         stmt := &If{Cond: cond}
286         b.emit(stmt, source)
287         addEdge(b, tblock)
288         addEdge(b, fblock)
289         f.currentBlock = nil
290         return stmt
291 }
292
293 // emitExtract emits to f an instruction to extract the index'th
294 // component of tuple.  It returns the extracted value.
295 //
296 func emitExtract(f *Function, tuple Value, index int, source ast.Node) Value {
297         e := &Extract{Tuple: tuple, Index: index}
298         e.setType(tuple.Type().(*types.Tuple).At(index).Type())
299         return f.emit(e, source)
300 }
301
302 // emitTypeAssert emits to f a type assertion value := x.(t) and
303 // returns the value.  x.Type() must be an interface.
304 //
305 func emitTypeAssert(f *Function, x Value, t types.Type, source ast.Node) Value {
306         a := &TypeAssert{X: x, AssertedType: t}
307         a.setType(t)
308         return f.emit(a, source)
309 }
310
311 // emitTypeTest emits to f a type test value,ok := x.(t) and returns
312 // a (value, ok) tuple.  x.Type() must be an interface.
313 //
314 func emitTypeTest(f *Function, x Value, t types.Type, source ast.Node) Value {
315         a := &TypeAssert{
316                 X:            x,
317                 AssertedType: t,
318                 CommaOk:      true,
319         }
320         a.setType(types.NewTuple(
321                 newVar("value", t),
322                 varOk,
323         ))
324         return f.emit(a, source)
325 }
326
327 // emitTailCall emits to f a function call in tail position.  The
328 // caller is responsible for all fields of 'call' except its type.
329 // Intended for wrapper methods.
330 // Precondition: f does/will not use deferred procedure calls.
331 // Postcondition: f.currentBlock is nil.
332 //
333 func emitTailCall(f *Function, call *Call, source ast.Node) {
334         tresults := f.Signature.Results()
335         nr := tresults.Len()
336         if nr == 1 {
337                 call.typ = tresults.At(0).Type()
338         } else {
339                 call.typ = tresults
340         }
341         tuple := f.emit(call, source)
342         var ret Return
343         switch nr {
344         case 0:
345                 // no-op
346         case 1:
347                 ret.Results = []Value{tuple}
348         default:
349                 for i := 0; i < nr; i++ {
350                         v := emitExtract(f, tuple, i, source)
351                         // TODO(adonovan): in principle, this is required:
352                         //   v = emitConv(f, o.Type, f.Signature.Results[i].Type)
353                         // but in practice emitTailCall is only used when
354                         // the types exactly match.
355                         ret.Results = append(ret.Results, v)
356                 }
357         }
358
359         f.Exit = f.newBasicBlock("exit")
360         emitJump(f, f.Exit, source)
361         f.currentBlock = f.Exit
362         f.emit(&ret, source)
363         f.currentBlock = nil
364 }
365
366 // emitImplicitSelections emits to f code to apply the sequence of
367 // implicit field selections specified by indices to base value v, and
368 // returns the selected value.
369 //
370 // If v is the address of a struct, the result will be the address of
371 // a field; if it is the value of a struct, the result will be the
372 // value of a field.
373 //
374 func emitImplicitSelections(f *Function, v Value, indices []int, source ast.Node) Value {
375         for _, index := range indices {
376                 fld := deref(v.Type()).Underlying().(*types.Struct).Field(index)
377
378                 if isPointer(v.Type()) {
379                         instr := &FieldAddr{
380                                 X:     v,
381                                 Field: index,
382                         }
383                         instr.setType(types.NewPointer(fld.Type()))
384                         v = f.emit(instr, source)
385                         // Load the field's value iff indirectly embedded.
386                         if isPointer(fld.Type()) {
387                                 v = emitLoad(f, v, source)
388                         }
389                 } else {
390                         instr := &Field{
391                                 X:     v,
392                                 Field: index,
393                         }
394                         instr.setType(fld.Type())
395                         v = f.emit(instr, source)
396                 }
397         }
398         return v
399 }
400
401 // emitFieldSelection emits to f code to select the index'th field of v.
402 //
403 // If wantAddr, the input must be a pointer-to-struct and the result
404 // will be the field's address; otherwise the result will be the
405 // field's value.
406 // Ident id is used for position and debug info.
407 //
408 func emitFieldSelection(f *Function, v Value, index int, wantAddr bool, id *ast.Ident) Value {
409         fld := deref(v.Type()).Underlying().(*types.Struct).Field(index)
410         if isPointer(v.Type()) {
411                 instr := &FieldAddr{
412                         X:     v,
413                         Field: index,
414                 }
415                 instr.setSource(id)
416                 instr.setType(types.NewPointer(fld.Type()))
417                 v = f.emit(instr, id)
418                 // Load the field's value iff we don't want its address.
419                 if !wantAddr {
420                         v = emitLoad(f, v, id)
421                 }
422         } else {
423                 instr := &Field{
424                         X:     v,
425                         Field: index,
426                 }
427                 instr.setSource(id)
428                 instr.setType(fld.Type())
429                 v = f.emit(instr, id)
430         }
431         emitDebugRef(f, id, v, wantAddr)
432         return v
433 }
434
435 // zeroValue emits to f code to produce a zero value of type t,
436 // and returns it.
437 //
438 func zeroValue(f *Function, t types.Type, source ast.Node) Value {
439         switch t.Underlying().(type) {
440         case *types.Struct, *types.Array:
441                 return emitLoad(f, f.addLocal(t, source), source)
442         default:
443                 return emitConst(f, zeroConst(t))
444         }
445 }
446
447 func emitConst(f *Function, c *Const) *Const {
448         f.consts = append(f.consts, c)
449         return c
450 }