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