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.
7 // Helpers for emitting SSA instructions.
16 // emitNew emits to f a new (heap Alloc) instruction allocating an
17 // object of type typ. pos is the optional source location.
19 func emitNew(f *Function, typ types.Type, pos token.Pos) *Alloc {
20 v := &Alloc{Heap: true}
21 v.setType(types.NewPointer(typ))
27 // emitLoad emits to f an instruction to load the address addr into a
28 // new temporary, and returns the value so defined.
30 func emitLoad(f *Function, addr Value) *UnOp {
31 v := &UnOp{Op: token.MUL, X: addr}
32 v.setType(deref(addr.Type()))
37 // emitDebugRef emits to f a DebugRef pseudo-instruction associating
38 // expression e with value v.
40 func emitDebugRef(f *Function, e ast.Expr, v Value, isAddr bool) {
42 return // debugging not enabled
44 if v == nil || e == nil {
49 if id, ok := e.(*ast.Ident); ok {
53 obj = f.Pkg.objectOf(id)
55 case *types.Nil, *types.Const, *types.Builtin:
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.)
72 func emitArith(f *Function, op token.Token, x, y Value, t types.Type, pos token.Pos) Value {
74 case token.SHL, token.SHR:
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])
82 case token.ADD, token.SUB, token.MUL, token.QUO, token.REM, token.AND, token.OR, token.XOR, token.AND_NOT:
87 panic("illegal op in emitArith: " + op.String())
100 // emitCompare emits to f code compute the boolean result of
101 // comparison comparison 'x op y'.
103 func emitCompare(f *Function, op token.Token, x, y Value, pos token.Pos) Value {
104 xt := x.Type().Underlying()
105 yt := y.Type().Underlying()
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 {
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())
131 // other cases, e.g. channels. No-op.
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.
148 func isValuePreserving(ut_src, ut_dst types.Type) bool {
149 // Identical underlying types?
150 if structTypesIdentical(ut_dst, ut_src) {
154 switch ut_dst.(type) {
156 // Conversion between channel types?
157 _, ok := ut_src.(*types.Chan)
161 // Conversion between pointers with identical base types?
162 _, ok := ut_src.(*types.Pointer)
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.
173 func emitConv(f *Function, val Value, typ types.Type) Value {
176 // Identical types? Conversion is a no-op.
177 if types.Identical(t_src, typ) {
181 ut_dst := typ.Underlying()
182 ut_src := t_src.Underlying()
184 // Just a change of type, but not value or representation?
185 if isValuePreserving(ut_src, ut_dst) {
186 c := &ChangeType{X: val}
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}
200 // Untyped nil constant? Return interface-typed nil constant.
201 if ut_src == tUntypedNil {
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))
210 f.Pkg.Prog.needMethodsOf(val.Type())
211 mi := &MakeInterface{X: val}
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)
227 // We're converting from constant to non-constant type,
228 // e.g. string -> []byte/[]rune.
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)
237 c := &Convert{X: val}
242 panic(fmt.Sprintf("in %s: cannot convert %s (%s) to %s", f, val, val.Type(), typ))
245 // emitStore emits to f an instruction to store value val at location
246 // addr, applying implicit conversions as required by assignability rules.
248 func emitStore(f *Function, addr, val Value, pos token.Pos) *Store {
251 Val: emitConv(f, val, deref(addr.Type())),
258 // emitJump emits to f a jump to target, and updates the control-flow graph.
259 // Postcondition: f.currentBlock is nil.
261 func emitJump(f *Function, target *BasicBlock) {
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.
272 func emitIf(f *Function, cond Value, tblock, fblock *BasicBlock) {
274 b.emit(&If{Cond: cond})
280 // emitExtract emits to f an instruction to extract the index'th
281 // component of tuple. It returns the extracted value.
283 func 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())
289 // emitTypeAssert emits to f a type assertion value := x.(t) and
290 // returns the value. x.Type() must be an interface.
292 func emitTypeAssert(f *Function, x Value, t types.Type, pos token.Pos) Value {
293 a := &TypeAssert{X: x, AssertedType: t}
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.
302 func emitTypeTest(f *Function, x Value, t types.Type, pos token.Pos) Value {
309 a.setType(types.NewTuple(
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.
322 func emitTailCall(f *Function, call *Call) {
323 tresults := f.Signature.Results()
326 call.typ = tresults.At(0).Type()
330 tuple := f.emit(call)
336 ret.Results = []Value{tuple}
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)
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.
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
359 func emitImplicitSelections(f *Function, v Value, indices []int) Value {
360 for _, index := range indices {
361 fld := deref(v.Type()).Underlying().(*types.Struct).Field(index)
363 if isPointer(v.Type()) {
368 instr.setType(types.NewPointer(fld.Type()))
370 // Load the field's value iff indirectly embedded.
371 if isPointer(fld.Type()) {
379 instr.setType(fld.Type())
386 // emitFieldSelection emits to f code to select the index'th field of v.
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
391 // Ident id is used for position and debug info.
393 func 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()) {
400 instr.setPos(id.Pos())
401 instr.setType(types.NewPointer(fld.Type()))
403 // Load the field's value iff we don't want its address.
412 instr.setPos(id.Pos())
413 instr.setType(fld.Type())
416 emitDebugRef(f, id, v, wantAddr)
420 // zeroValue emits to f code to produce a zero value of type t,
423 func 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))
432 // createRecoverBlock emits to f a block of code to return after a
433 // recovered panic, and sets f.Recover to it.
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
441 func createRecoverBlock(f *Function) {
442 if f.Recover != nil {
443 return // already created
445 saved := f.currentBlock
447 f.Recover = f.newBasicBlock("recover")
448 f.currentBlock = f.Recover
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))
457 R := f.Signature.Results()
458 for i, n := 0, R.Len(); i < n; i++ {
461 // Return zero value of each result type.
462 results = append(results, zeroValue(f, T))
465 f.emit(&Return{Results: results})
467 f.currentBlock = saved