github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/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 // +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 types.Identical(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 // emitIf emits to f a conditional jump to tblock or fblock based on 271 // cond, and updates the control-flow graph. 272 // Postcondition: f.currentBlock is nil. 273 // 274 func emitIf(f *Function, cond Value, tblock, fblock *BasicBlock) { 275 b := f.currentBlock 276 b.emit(&If{Cond: cond}) 277 addEdge(b, tblock) 278 addEdge(b, fblock) 279 f.currentBlock = nil 280 } 281 282 // emitExtract emits to f an instruction to extract the index'th 283 // component of tuple. It returns the extracted value. 284 // 285 func emitExtract(f *Function, tuple Value, index int) Value { 286 e := &Extract{Tuple: tuple, Index: index} 287 e.setType(tuple.Type().(*types.Tuple).At(index).Type()) 288 return f.emit(e) 289 } 290 291 // emitTypeAssert emits to f a type assertion value := x.(t) and 292 // returns the value. x.Type() must be an interface. 293 // 294 func emitTypeAssert(f *Function, x Value, t types.Type, pos token.Pos) Value { 295 a := &TypeAssert{X: x, AssertedType: t} 296 a.setPos(pos) 297 a.setType(t) 298 return f.emit(a) 299 } 300 301 // emitTypeTest emits to f a type test value,ok := x.(t) and returns 302 // a (value, ok) tuple. x.Type() must be an interface. 303 // 304 func emitTypeTest(f *Function, x Value, t types.Type, pos token.Pos) Value { 305 a := &TypeAssert{ 306 X: x, 307 AssertedType: t, 308 CommaOk: true, 309 } 310 a.setPos(pos) 311 a.setType(types.NewTuple( 312 newVar("value", t), 313 varOk, 314 )) 315 return f.emit(a) 316 } 317 318 // emitTailCall emits to f a function call in tail position. The 319 // caller is responsible for all fields of 'call' except its type. 320 // Intended for wrapper methods. 321 // Precondition: f does/will not use deferred procedure calls. 322 // Postcondition: f.currentBlock is nil. 323 // 324 func emitTailCall(f *Function, call *Call) { 325 tresults := f.Signature.Results() 326 nr := tresults.Len() 327 if nr == 1 { 328 call.typ = tresults.At(0).Type() 329 } else { 330 call.typ = tresults 331 } 332 tuple := f.emit(call) 333 var ret Return 334 switch nr { 335 case 0: 336 // no-op 337 case 1: 338 ret.Results = []Value{tuple} 339 default: 340 for i := 0; i < nr; i++ { 341 v := emitExtract(f, tuple, i) 342 // TODO(adonovan): in principle, this is required: 343 // v = emitConv(f, o.Type, f.Signature.Results[i].Type) 344 // but in practice emitTailCall is only used when 345 // the types exactly match. 346 ret.Results = append(ret.Results, v) 347 } 348 } 349 f.emit(&ret) 350 f.currentBlock = nil 351 } 352 353 // emitImplicitSelections emits to f code to apply the sequence of 354 // implicit field selections specified by indices to base value v, and 355 // returns the selected value. 356 // 357 // If v is the address of a struct, the result will be the address of 358 // a field; if it is the value of a struct, the result will be the 359 // value of a field. 360 // 361 func emitImplicitSelections(f *Function, v Value, indices []int) Value { 362 for _, index := range indices { 363 fld := deref(v.Type()).Underlying().(*types.Struct).Field(index) 364 365 if isPointer(v.Type()) { 366 instr := &FieldAddr{ 367 X: v, 368 Field: index, 369 } 370 instr.setType(types.NewPointer(fld.Type())) 371 v = f.emit(instr) 372 // Load the field's value iff indirectly embedded. 373 if isPointer(fld.Type()) { 374 v = emitLoad(f, v) 375 } 376 } else { 377 instr := &Field{ 378 X: v, 379 Field: index, 380 } 381 instr.setType(fld.Type()) 382 v = f.emit(instr) 383 } 384 } 385 return v 386 } 387 388 // emitFieldSelection emits to f code to select the index'th field of v. 389 // 390 // If wantAddr, the input must be a pointer-to-struct and the result 391 // will be the field's address; otherwise the result will be the 392 // field's value. 393 // Ident id is used for position and debug info. 394 // 395 func emitFieldSelection(f *Function, v Value, index int, wantAddr bool, id *ast.Ident) Value { 396 fld := deref(v.Type()).Underlying().(*types.Struct).Field(index) 397 if isPointer(v.Type()) { 398 instr := &FieldAddr{ 399 X: v, 400 Field: index, 401 } 402 instr.setPos(id.Pos()) 403 instr.setType(types.NewPointer(fld.Type())) 404 v = f.emit(instr) 405 // Load the field's value iff we don't want its address. 406 if !wantAddr { 407 v = emitLoad(f, v) 408 } 409 } else { 410 instr := &Field{ 411 X: v, 412 Field: index, 413 } 414 instr.setPos(id.Pos()) 415 instr.setType(fld.Type()) 416 v = f.emit(instr) 417 } 418 emitDebugRef(f, id, v, wantAddr) 419 return v 420 } 421 422 // zeroValue emits to f code to produce a zero value of type t, 423 // and returns it. 424 // 425 func zeroValue(f *Function, t types.Type) Value { 426 switch t.Underlying().(type) { 427 case *types.Struct, *types.Array: 428 return emitLoad(f, f.addLocal(t, token.NoPos)) 429 default: 430 return zeroConst(t) 431 } 432 } 433 434 // createRecoverBlock emits to f a block of code to return after a 435 // recovered panic, and sets f.Recover to it. 436 // 437 // If f's result parameters are named, the code loads and returns 438 // their current values, otherwise it returns the zero values of their 439 // type. 440 // 441 // Idempotent. 442 // 443 func createRecoverBlock(f *Function) { 444 if f.Recover != nil { 445 return // already created 446 } 447 saved := f.currentBlock 448 449 f.Recover = f.newBasicBlock("recover") 450 f.currentBlock = f.Recover 451 452 var results []Value 453 if f.namedResults != nil { 454 // Reload NRPs to form value tuple. 455 for _, r := range f.namedResults { 456 results = append(results, emitLoad(f, r)) 457 } 458 } else { 459 R := f.Signature.Results() 460 for i, n := 0, R.Len(); i < n; i++ { 461 T := R.At(i).Type() 462 463 // Return zero value of each result type. 464 results = append(results, zeroValue(f, T)) 465 } 466 } 467 f.emit(&Return{Results: results}) 468 469 f.currentBlock = saved 470 }