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