gitee.com/wgliang/goreporter@v0.0.0-20180902115603-df1b20f7c5d0/linters/simpler/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 // +build go1.5 6 7 package ssa 8 9 // Helpers for emitting SSA instructions. 10 11 import ( 12 "fmt" 13 "go/ast" 14 "go/token" 15 "go/types" 16 ) 17 18 // emitNew emits to f a new (heap Alloc) instruction allocating an 19 // object of type typ. pos is the optional source location. 20 // 21 func emitNew(f *Function, typ types.Type, pos token.Pos) *Alloc { 22 v := &Alloc{Heap: true} 23 v.setType(types.NewPointer(typ)) 24 v.setPos(pos) 25 f.emit(v) 26 return v 27 } 28 29 // emitLoad emits to f an instruction to load the address addr into a 30 // new temporary, and returns the value so defined. 31 // 32 func emitLoad(f *Function, addr Value) *UnOp { 33 v := &UnOp{Op: token.MUL, X: addr} 34 v.setType(deref(addr.Type())) 35 f.emit(v) 36 return v 37 } 38 39 // emitDebugRef emits to f a DebugRef pseudo-instruction associating 40 // expression e with value v. 41 // 42 func emitDebugRef(f *Function, e ast.Expr, v Value, isAddr bool) { 43 if !f.debugInfo() { 44 return // debugging not enabled 45 } 46 if v == nil || e == nil { 47 panic("nil") 48 } 49 var obj types.Object 50 e = unparen(e) 51 if id, ok := e.(*ast.Ident); ok { 52 if isBlankIdent(id) { 53 return 54 } 55 obj = f.Pkg.objectOf(id) 56 switch obj.(type) { 57 case *types.Nil, *types.Const, *types.Builtin: 58 return 59 } 60 } 61 f.emit(&DebugRef{ 62 X: v, 63 Expr: e, 64 IsAddr: isAddr, 65 object: obj, 66 }) 67 } 68 69 // emitArith emits to f code to compute the binary operation op(x, y) 70 // where op is an eager shift, logical or arithmetic operation. 71 // (Use emitCompare() for comparisons and Builder.logicalBinop() for 72 // non-eager operations.) 73 // 74 func emitArith(f *Function, op token.Token, x, y Value, t types.Type, pos token.Pos) Value { 75 switch op { 76 case token.SHL, token.SHR: 77 x = emitConv(f, x, t) 78 // y may be signed or an 'untyped' constant. 79 // TODO(adonovan): whence signed values? 80 if b, ok := y.Type().Underlying().(*types.Basic); ok && b.Info()&types.IsUnsigned == 0 { 81 y = emitConv(f, y, types.Typ[types.Uint64]) 82 } 83 84 case token.ADD, token.SUB, token.MUL, token.QUO, token.REM, token.AND, token.OR, token.XOR, token.AND_NOT: 85 x = emitConv(f, x, t) 86 y = emitConv(f, y, t) 87 88 default: 89 panic("illegal op in emitArith: " + op.String()) 90 91 } 92 v := &BinOp{ 93 Op: op, 94 X: x, 95 Y: y, 96 } 97 v.setPos(pos) 98 v.setType(t) 99 return f.emit(v) 100 } 101 102 // emitCompare emits to f code compute the boolean result of 103 // comparison comparison 'x op y'. 104 // 105 func emitCompare(f *Function, op token.Token, x, y Value, pos token.Pos) Value { 106 xt := x.Type().Underlying() 107 yt := y.Type().Underlying() 108 109 // Special case to optimise a tagless SwitchStmt so that 110 // these are equivalent 111 // switch { case e: ...} 112 // switch true { case e: ... } 113 // if e==true { ... } 114 // even in the case when e's type is an interface. 115 // TODO(adonovan): opt: generalise to x==true, false!=y, etc. 116 if x == vTrue && op == token.EQL { 117 if yt, ok := yt.(*types.Basic); ok && yt.Info()&types.IsBoolean != 0 { 118 return y 119 } 120 } 121 122 if types.Identical(xt, yt) { 123 // no conversion necessary 124 } else if _, ok := xt.(*types.Interface); ok { 125 y = emitConv(f, y, x.Type()) 126 } else if _, ok := yt.(*types.Interface); ok { 127 x = emitConv(f, x, y.Type()) 128 } else if _, ok := x.(*Const); ok { 129 x = emitConv(f, x, y.Type()) 130 } else if _, ok := y.(*Const); ok { 131 y = emitConv(f, y, x.Type()) 132 } else { 133 // other cases, e.g. channels. No-op. 134 } 135 136 v := &BinOp{ 137 Op: op, 138 X: x, 139 Y: y, 140 } 141 v.setPos(pos) 142 v.setType(tBool) 143 return f.emit(v) 144 } 145 146 // isValuePreserving returns true if a conversion from ut_src to 147 // ut_dst is value-preserving, i.e. just a change of type. 148 // Precondition: neither argument is a named type. 149 // 150 func isValuePreserving(ut_src, ut_dst types.Type) bool { 151 // Identical underlying types? 152 if structTypesIdentical(ut_dst, ut_src) { 153 return true 154 } 155 156 switch ut_dst.(type) { 157 case *types.Chan: 158 // Conversion between channel types? 159 _, ok := ut_src.(*types.Chan) 160 return ok 161 162 case *types.Pointer: 163 // Conversion between pointers with identical base types? 164 _, ok := ut_src.(*types.Pointer) 165 return ok 166 } 167 return false 168 } 169 170 // emitConv emits to f code to convert Value val to exactly type typ, 171 // and returns the converted value. Implicit conversions are required 172 // by language assignability rules in assignments, parameter passing, 173 // etc. Conversions cannot fail dynamically. 174 // 175 func emitConv(f *Function, val Value, typ types.Type) Value { 176 t_src := val.Type() 177 178 // Identical types? Conversion is a no-op. 179 if types.Identical(t_src, typ) { 180 return val 181 } 182 183 ut_dst := typ.Underlying() 184 ut_src := t_src.Underlying() 185 186 // Just a change of type, but not value or representation? 187 if isValuePreserving(ut_src, ut_dst) { 188 c := &ChangeType{X: val} 189 c.setType(typ) 190 return f.emit(c) 191 } 192 193 // Conversion to, or construction of a value of, an interface type? 194 if _, ok := ut_dst.(*types.Interface); ok { 195 // Assignment from one interface type to another? 196 if _, ok := ut_src.(*types.Interface); ok { 197 c := &ChangeInterface{X: val} 198 c.setType(typ) 199 return f.emit(c) 200 } 201 202 // Untyped nil constant? Return interface-typed nil constant. 203 if ut_src == tUntypedNil { 204 return nilConst(typ) 205 } 206 207 // Convert (non-nil) "untyped" literals to their default type. 208 if t, ok := ut_src.(*types.Basic); ok && t.Info()&types.IsUntyped != 0 { 209 val = emitConv(f, val, DefaultType(ut_src)) 210 } 211 212 f.Pkg.Prog.needMethodsOf(val.Type()) 213 mi := &MakeInterface{X: val} 214 mi.setType(typ) 215 return f.emit(mi) 216 } 217 218 // Conversion of a compile-time constant value? 219 if c, ok := val.(*Const); ok { 220 if _, ok := ut_dst.(*types.Basic); ok || c.IsNil() { 221 // Conversion of a compile-time constant to 222 // another constant type results in a new 223 // constant of the destination type and 224 // (initially) the same abstract value. 225 // We don't truncate the value yet. 226 return NewConst(c.Value, typ) 227 } 228 229 // We're converting from constant to non-constant type, 230 // e.g. string -> []byte/[]rune. 231 } 232 233 // A representation-changing conversion? 234 // At least one of {ut_src,ut_dst} must be *Basic. 235 // (The other may be []byte or []rune.) 236 _, ok1 := ut_src.(*types.Basic) 237 _, ok2 := ut_dst.(*types.Basic) 238 if ok1 || ok2 { 239 c := &Convert{X: val} 240 c.setType(typ) 241 return f.emit(c) 242 } 243 244 panic(fmt.Sprintf("in %s: cannot convert %s (%s) to %s", f, val, val.Type(), typ)) 245 } 246 247 // emitStore emits to f an instruction to store value val at location 248 // addr, applying implicit conversions as required by assignability rules. 249 // 250 func emitStore(f *Function, addr, val Value, pos token.Pos) *Store { 251 s := &Store{ 252 Addr: addr, 253 Val: emitConv(f, val, deref(addr.Type())), 254 pos: pos, 255 } 256 f.emit(s) 257 return s 258 } 259 260 // emitJump emits to f a jump to target, and updates the control-flow graph. 261 // Postcondition: f.currentBlock is nil. 262 // 263 func emitJump(f *Function, target *BasicBlock) { 264 b := f.currentBlock 265 b.emit(new(Jump)) 266 addEdge(b, target) 267 f.currentBlock = nil 268 } 269 270 func (b *BasicBlock) emitJump(target *BasicBlock) { 271 b.emit(new(Jump)) 272 addEdge(b, target) 273 } 274 275 // emitIf emits to f a conditional jump to tblock or fblock based on 276 // cond, and updates the control-flow graph. 277 // Postcondition: f.currentBlock is nil. 278 // 279 func emitIf(f *Function, cond Value, tblock, fblock *BasicBlock) { 280 b := f.currentBlock 281 b.emit(&If{Cond: cond}) 282 addEdge(b, tblock) 283 addEdge(b, fblock) 284 f.currentBlock = nil 285 } 286 287 // emitExtract emits to f an instruction to extract the index'th 288 // component of tuple. It returns the extracted value. 289 // 290 func emitExtract(f *Function, tuple Value, index int) Value { 291 e := &Extract{Tuple: tuple, Index: index} 292 e.setType(tuple.Type().(*types.Tuple).At(index).Type()) 293 return f.emit(e) 294 } 295 296 // emitTypeAssert emits to f a type assertion value := x.(t) and 297 // returns the value. x.Type() must be an interface. 298 // 299 func emitTypeAssert(f *Function, x Value, t types.Type, pos token.Pos) Value { 300 a := &TypeAssert{X: x, AssertedType: t} 301 a.setPos(pos) 302 a.setType(t) 303 return f.emit(a) 304 } 305 306 // emitTypeTest emits to f a type test value,ok := x.(t) and returns 307 // a (value, ok) tuple. x.Type() must be an interface. 308 // 309 func emitTypeTest(f *Function, x Value, t types.Type, pos token.Pos) Value { 310 a := &TypeAssert{ 311 X: x, 312 AssertedType: t, 313 CommaOk: true, 314 } 315 a.setPos(pos) 316 a.setType(types.NewTuple( 317 newVar("value", t), 318 varOk, 319 )) 320 return f.emit(a) 321 } 322 323 // emitTailCall emits to f a function call in tail position. The 324 // caller is responsible for all fields of 'call' except its type. 325 // Intended for wrapper methods. 326 // Precondition: f does/will not use deferred procedure calls. 327 // Postcondition: f.currentBlock is nil. 328 // 329 func emitTailCall(f *Function, call *Call) { 330 tresults := f.Signature.Results() 331 nr := tresults.Len() 332 if nr == 1 { 333 call.typ = tresults.At(0).Type() 334 } else { 335 call.typ = tresults 336 } 337 tuple := f.emit(call) 338 var ret Return 339 switch nr { 340 case 0: 341 // no-op 342 case 1: 343 ret.Results = []Value{tuple} 344 default: 345 for i := 0; i < nr; i++ { 346 v := emitExtract(f, tuple, i) 347 // TODO(adonovan): in principle, this is required: 348 // v = emitConv(f, o.Type, f.Signature.Results[i].Type) 349 // but in practice emitTailCall is only used when 350 // the types exactly match. 351 ret.Results = append(ret.Results, v) 352 } 353 } 354 f.emit(&ret) 355 f.currentBlock = nil 356 } 357 358 // emitImplicitSelections emits to f code to apply the sequence of 359 // implicit field selections specified by indices to base value v, and 360 // returns the selected value. 361 // 362 // If v is the address of a struct, the result will be the address of 363 // a field; if it is the value of a struct, the result will be the 364 // value of a field. 365 // 366 func emitImplicitSelections(f *Function, v Value, indices []int) Value { 367 for _, index := range indices { 368 fld := deref(v.Type()).Underlying().(*types.Struct).Field(index) 369 370 if isPointer(v.Type()) { 371 instr := &FieldAddr{ 372 X: v, 373 Field: index, 374 } 375 instr.setType(types.NewPointer(fld.Type())) 376 v = f.emit(instr) 377 // Load the field's value iff indirectly embedded. 378 if isPointer(fld.Type()) { 379 v = emitLoad(f, v) 380 } 381 } else { 382 instr := &Field{ 383 X: v, 384 Field: index, 385 } 386 instr.setType(fld.Type()) 387 v = f.emit(instr) 388 } 389 } 390 return v 391 } 392 393 // emitFieldSelection emits to f code to select the index'th field of v. 394 // 395 // If wantAddr, the input must be a pointer-to-struct and the result 396 // will be the field's address; otherwise the result will be the 397 // field's value. 398 // Ident id is used for position and debug info. 399 // 400 func emitFieldSelection(f *Function, v Value, index int, wantAddr bool, id *ast.Ident) Value { 401 fld := deref(v.Type()).Underlying().(*types.Struct).Field(index) 402 if isPointer(v.Type()) { 403 instr := &FieldAddr{ 404 X: v, 405 Field: index, 406 } 407 instr.setPos(id.Pos()) 408 instr.setType(types.NewPointer(fld.Type())) 409 v = f.emit(instr) 410 // Load the field's value iff we don't want its address. 411 if !wantAddr { 412 v = emitLoad(f, v) 413 } 414 } else { 415 instr := &Field{ 416 X: v, 417 Field: index, 418 } 419 instr.setPos(id.Pos()) 420 instr.setType(fld.Type()) 421 v = f.emit(instr) 422 } 423 emitDebugRef(f, id, v, wantAddr) 424 return v 425 } 426 427 // zeroValue emits to f code to produce a zero value of type t, 428 // and returns it. 429 // 430 func zeroValue(f *Function, t types.Type) Value { 431 switch t.Underlying().(type) { 432 case *types.Struct, *types.Array: 433 return emitLoad(f, f.addLocal(t, token.NoPos)) 434 default: 435 return zeroConst(t) 436 } 437 } 438 439 // createRecoverBlock emits to f a block of code to return after a 440 // recovered panic, and sets f.Recover to it. 441 // 442 // If f's result parameters are named, the code loads and returns 443 // their current values, otherwise it returns the zero values of their 444 // type. 445 // 446 // Idempotent. 447 // 448 func createRecoverBlock(f *Function) { 449 if f.Recover != nil { 450 return // already created 451 } 452 saved := f.currentBlock 453 454 f.Recover = f.newBasicBlock("recover") 455 f.currentBlock = f.Recover 456 457 var results []Value 458 if f.namedResults != nil { 459 // Reload NRPs to form value tuple. 460 for _, r := range f.namedResults { 461 results = append(results, emitLoad(f, r)) 462 } 463 } else { 464 R := f.Signature.Results() 465 for i, n := 0, R.Len(); i < n; i++ { 466 T := R.At(i).Type() 467 468 // Return zero value of each result type. 469 results = append(results, zeroValue(f, T)) 470 } 471 } 472 f.emit(&Return{Results: results}) 473 474 f.currentBlock = saved 475 }