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  }