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