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
5package ir
6
7// Helpers for emitting IR instructions.
8
9import (
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//
20func 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//
30func 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
37func 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//
49func 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//
81func 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//
111func 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//
156func 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//
181func 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//
256func 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//
270func 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//
283func 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//
296func 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//
305func 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//
314func 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//
333func 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//
374func 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//
408func 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//
438func 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
447func emitConst(f *Function, c *Const) *Const {
448	f.consts = append(f.consts, c)
449	return c
450}
451