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