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