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