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 IR instructions.
17 // emitNew emits to f a new (heap Alloc) instruction allocating an
18 // object of type typ. pos is the optional source location.
20 func emitNew(f *Function, typ types.Type, source ast.Node) *Alloc {
21 v := &Alloc{Heap: true}
22 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, source ast.Node) *Load {
32 v.setType(deref(addr.Type()))
37 func emitRecv(f *Function, ch Value, commaOk bool, typ types.Type, source ast.Node) Value {
43 return f.emit(recv, source)
46 // emitDebugRef emits to f a DebugRef pseudo-instruction associating
47 // expression e with value v.
49 func emitDebugRef(f *Function, e ast.Expr, v Value, isAddr bool) {
51 return // debugging not enabled
53 if v == nil || e == nil {
58 if id, ok := e.(*ast.Ident); ok {
62 obj = f.Pkg.objectOf(id)
64 case *types.Nil, *types.Const, *types.Builtin:
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.)
81 func emitArith(f *Function, op token.Token, x, y Value, t types.Type, source ast.Node) Value {
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)
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)
96 panic("illegal op in emitArith: " + op.String())
105 return f.emit(v, source)
108 // emitCompare emits to f code compute the boolean result of
109 // comparison comparison 'x op y'.
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()
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 {
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
140 // other cases, e.g. channels. No-op.
149 return f.emit(v, source)
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.
156 func isValuePreserving(ut_src, ut_dst types.Type) bool {
157 // Identical underlying types?
158 if structTypesIdentical(ut_dst, ut_src) {
162 switch ut_dst.(type) {
164 // Conversion between channel types?
165 _, ok := ut_src.(*types.Chan)
169 // Conversion between pointers with identical base types?
170 _, ok := ut_src.(*types.Pointer)
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.
181 func emitConv(f *Function, val Value, typ types.Type, source ast.Node) Value {
184 // Identical types? Conversion is a no-op.
185 if types.Identical(t_src, typ) {
189 ut_dst := typ.Underlying()
190 ut_src := t_src.Underlying()
192 // Just a change of type, but not value or representation?
193 if isValuePreserving(ut_src, ut_dst) {
194 c := &ChangeType{X: val}
196 return f.emit(c, source)
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}
205 return f.emit(c, source)
208 // Untyped nil constant? Return interface-typed nil constant.
209 if ut_src == tUntypedNil {
210 return emitConst(f, nilConst(typ))
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)
218 f.Pkg.Prog.needMethodsOf(val.Type())
219 mi := &MakeInterface{X: val}
221 return f.emit(mi, source)
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))
235 // We're converting from constant to non-constant type,
236 // e.g. string -> []byte/[]rune.
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)
245 c := &Convert{X: val}
247 return f.emit(c, source)
250 panic(fmt.Sprintf("in %s: cannot convert %s (%s) to %s", f, val, val.Type(), typ))
253 // emitStore emits to f an instruction to store value val at location
254 // addr, applying implicit conversions as required by assignability rules.
256 func emitStore(f *Function, addr, val Value, source ast.Node) *Store {
259 Val: emitConv(f, val, deref(addr.Type()), source),
261 // make sure we call getMem after the call to emitConv, which may
262 // itself update the memory state
267 // emitJump emits to f a jump to target, and updates the control-flow graph.
268 // Postcondition: f.currentBlock is nil.
270 func emitJump(f *Function, target *BasicBlock, source ast.Node) *Jump {
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.
283 func emitIf(f *Function, cond Value, tblock, fblock *BasicBlock, source ast.Node) *If {
285 stmt := &If{Cond: cond}
293 // emitExtract emits to f an instruction to extract the index'th
294 // component of tuple. It returns the extracted value.
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)
302 // emitTypeAssert emits to f a type assertion value := x.(t) and
303 // returns the value. x.Type() must be an interface.
305 func emitTypeAssert(f *Function, x Value, t types.Type, source ast.Node) Value {
306 a := &TypeAssert{X: x, AssertedType: t}
308 return f.emit(a, source)
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.
314 func emitTypeTest(f *Function, x Value, t types.Type, source ast.Node) Value {
320 a.setType(types.NewTuple(
324 return f.emit(a, source)
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.
333 func emitTailCall(f *Function, call *Call, source ast.Node) {
334 tresults := f.Signature.Results()
337 call.typ = tresults.At(0).Type()
341 tuple := f.emit(call, source)
347 ret.Results = []Value{tuple}
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)
359 f.Exit = f.newBasicBlock("exit")
360 emitJump(f, f.Exit, source)
361 f.currentBlock = f.Exit
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.
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
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)
378 if isPointer(v.Type()) {
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)
394 instr.setType(fld.Type())
395 v = f.emit(instr, source)
401 // emitFieldSelection emits to f code to select the index'th field of v.
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
406 // Ident id is used for position and debug info.
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()) {
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.
420 v = emitLoad(f, v, id)
428 instr.setType(fld.Type())
429 v = f.emit(instr, id)
431 emitDebugRef(f, id, v, wantAddr)
435 // zeroValue emits to f code to produce a zero value of type t,
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)
443 return emitConst(f, zeroConst(t))
447 func emitConst(f *Function, c *Const) *Const {
448 f.consts = append(f.consts, c)