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  }