github.com/pankona/gometalinter@v2.0.11+incompatible/_linters/src/golang.org/x/tools/go/ssa/emit.go (about) 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 5 package ssa 6 7 // Helpers for emitting SSA instructions. 8 9 import ( 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 // 19 func 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 // 30 func 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 // 40 func 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 // 72 func 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 // 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() 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 // 148 func 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 // 173 func 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, DefaultType(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 // 248 func 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 // 261 func 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 // 272 func 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 // 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()) 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 // 292 func 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 // 302 func 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 // 322 func 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 // 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) 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 // 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()) { 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 // 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)) 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 // 441 func 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 }