github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/compile/typecheck/func.go (about)

     1  // Copyright 2009 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 typecheck
     6  
     7  import (
     8  	"github.com/go-asm/go/cmd/compile/base"
     9  	"github.com/go-asm/go/cmd/compile/ir"
    10  	"github.com/go-asm/go/cmd/compile/types"
    11  	"github.com/go-asm/go/cmd/src"
    12  
    13  	"fmt"
    14  	"go/constant"
    15  	"go/token"
    16  )
    17  
    18  // MakeDotArgs package all the arguments that match a ... T parameter into a []T.
    19  func MakeDotArgs(pos src.XPos, typ *types.Type, args []ir.Node) ir.Node {
    20  	if len(args) == 0 {
    21  		return ir.NewNilExpr(pos, typ)
    22  	}
    23  
    24  	args = append([]ir.Node(nil), args...)
    25  	lit := ir.NewCompLitExpr(pos, ir.OCOMPLIT, typ, args)
    26  	lit.SetImplicit(true)
    27  
    28  	n := Expr(lit)
    29  	if n.Type() == nil {
    30  		base.FatalfAt(pos, "mkdotargslice: typecheck failed")
    31  	}
    32  	return n
    33  }
    34  
    35  // FixVariadicCall rewrites calls to variadic functions to use an
    36  // explicit ... argument if one is not already present.
    37  func FixVariadicCall(call *ir.CallExpr) {
    38  	fntype := call.Fun.Type()
    39  	if !fntype.IsVariadic() || call.IsDDD {
    40  		return
    41  	}
    42  
    43  	vi := fntype.NumParams() - 1
    44  	vt := fntype.Param(vi).Type
    45  
    46  	args := call.Args
    47  	extra := args[vi:]
    48  	slice := MakeDotArgs(call.Pos(), vt, extra)
    49  	for i := range extra {
    50  		extra[i] = nil // allow GC
    51  	}
    52  
    53  	call.Args = append(args[:vi], slice)
    54  	call.IsDDD = true
    55  }
    56  
    57  // FixMethodCall rewrites a method call t.M(...) into a function call T.M(t, ...).
    58  func FixMethodCall(call *ir.CallExpr) {
    59  	if call.Fun.Op() != ir.ODOTMETH {
    60  		return
    61  	}
    62  
    63  	dot := call.Fun.(*ir.SelectorExpr)
    64  
    65  	fn := NewMethodExpr(dot.Pos(), dot.X.Type(), dot.Selection.Sym)
    66  
    67  	args := make([]ir.Node, 1+len(call.Args))
    68  	args[0] = dot.X
    69  	copy(args[1:], call.Args)
    70  
    71  	call.SetOp(ir.OCALLFUNC)
    72  	call.Fun = fn
    73  	call.Args = args
    74  }
    75  
    76  func AssertFixedCall(call *ir.CallExpr) {
    77  	if call.Fun.Type().IsVariadic() && !call.IsDDD {
    78  		base.FatalfAt(call.Pos(), "missed FixVariadicCall")
    79  	}
    80  	if call.Op() == ir.OCALLMETH {
    81  		base.FatalfAt(call.Pos(), "missed FixMethodCall")
    82  	}
    83  }
    84  
    85  // ClosureType returns the struct type used to hold all the information
    86  // needed in the closure for clo (clo must be a OCLOSURE node).
    87  // The address of a variable of the returned type can be cast to a func.
    88  func ClosureType(clo *ir.ClosureExpr) *types.Type {
    89  	// Create closure in the form of a composite literal.
    90  	// supposing the closure captures an int i and a string s
    91  	// and has one float64 argument and no results,
    92  	// the generated code looks like:
    93  	//
    94  	//	clos = &struct{F uintptr; X0 *int; X1 *string}{func.1, &i, &s}
    95  	//
    96  	// The use of the struct provides type information to the garbage
    97  	// collector so that it can walk the closure. We could use (in this
    98  	// case) [3]unsafe.Pointer instead, but that would leave the gc in
    99  	// the dark. The information appears in the binary in the form of
   100  	// type descriptors; the struct is unnamed and uses exported field
   101  	// names so that closures in multiple packages with the same struct
   102  	// type can share the descriptor.
   103  
   104  	fields := make([]*types.Field, 1+len(clo.Func.ClosureVars))
   105  	fields[0] = types.NewField(base.AutogeneratedPos, types.LocalPkg.Lookup("F"), types.Types[types.TUINTPTR])
   106  	for i, v := range clo.Func.ClosureVars {
   107  		typ := v.Type()
   108  		if !v.Byval() {
   109  			typ = types.NewPtr(typ)
   110  		}
   111  		fields[1+i] = types.NewField(base.AutogeneratedPos, types.LocalPkg.LookupNum("X", i), typ)
   112  	}
   113  	typ := types.NewStruct(fields)
   114  	typ.SetNoalg(true)
   115  	return typ
   116  }
   117  
   118  // MethodValueType returns the struct type used to hold all the information
   119  // needed in the closure for a OMETHVALUE node. The address of a variable of
   120  // the returned type can be cast to a func.
   121  func MethodValueType(n *ir.SelectorExpr) *types.Type {
   122  	t := types.NewStruct([]*types.Field{
   123  		types.NewField(base.Pos, Lookup("F"), types.Types[types.TUINTPTR]),
   124  		types.NewField(base.Pos, Lookup("R"), n.X.Type()),
   125  	})
   126  	t.SetNoalg(true)
   127  	return t
   128  }
   129  
   130  // type check function definition
   131  // To be called by typecheck, not directly.
   132  // (Call typecheck.Func instead.)
   133  func tcFunc(n *ir.Func) {
   134  	if base.EnableTrace && base.Flag.LowerT {
   135  		defer tracePrint("tcFunc", n)(nil)
   136  	}
   137  
   138  	if name := n.Nname; name.Typecheck() == 0 {
   139  		base.AssertfAt(name.Type() != nil, n.Pos(), "missing type: %v", name)
   140  		name.SetTypecheck(1)
   141  	}
   142  }
   143  
   144  // tcCall typechecks an OCALL node.
   145  func tcCall(n *ir.CallExpr, top int) ir.Node {
   146  	Stmts(n.Init()) // imported rewritten f(g()) calls (#30907)
   147  	n.Fun = typecheck(n.Fun, ctxExpr|ctxType|ctxCallee)
   148  
   149  	l := n.Fun
   150  
   151  	if l.Op() == ir.ONAME && l.(*ir.Name).BuiltinOp != 0 {
   152  		l := l.(*ir.Name)
   153  		if n.IsDDD && l.BuiltinOp != ir.OAPPEND {
   154  			base.Errorf("invalid use of ... with builtin %v", l)
   155  		}
   156  
   157  		// builtin: OLEN, OCAP, etc.
   158  		switch l.BuiltinOp {
   159  		default:
   160  			base.Fatalf("unknown builtin %v", l)
   161  
   162  		case ir.OAPPEND, ir.ODELETE, ir.OMAKE, ir.OMAX, ir.OMIN, ir.OPRINT, ir.OPRINTLN, ir.ORECOVER:
   163  			n.SetOp(l.BuiltinOp)
   164  			n.Fun = nil
   165  			n.SetTypecheck(0) // re-typechecking new op is OK, not a loop
   166  			return typecheck(n, top)
   167  
   168  		case ir.OCAP, ir.OCLEAR, ir.OCLOSE, ir.OIMAG, ir.OLEN, ir.OPANIC, ir.OREAL, ir.OUNSAFESTRINGDATA, ir.OUNSAFESLICEDATA:
   169  			typecheckargs(n)
   170  			fallthrough
   171  		case ir.ONEW:
   172  			arg, ok := needOneArg(n, "%v", n.Op())
   173  			if !ok {
   174  				n.SetType(nil)
   175  				return n
   176  			}
   177  			u := ir.NewUnaryExpr(n.Pos(), l.BuiltinOp, arg)
   178  			return typecheck(ir.InitExpr(n.Init(), u), top) // typecheckargs can add to old.Init
   179  
   180  		case ir.OCOMPLEX, ir.OCOPY, ir.OUNSAFEADD, ir.OUNSAFESLICE, ir.OUNSAFESTRING:
   181  			typecheckargs(n)
   182  			arg1, arg2, ok := needTwoArgs(n)
   183  			if !ok {
   184  				n.SetType(nil)
   185  				return n
   186  			}
   187  			b := ir.NewBinaryExpr(n.Pos(), l.BuiltinOp, arg1, arg2)
   188  			return typecheck(ir.InitExpr(n.Init(), b), top) // typecheckargs can add to old.Init
   189  		}
   190  		panic("unreachable")
   191  	}
   192  
   193  	n.Fun = DefaultLit(n.Fun, nil)
   194  	l = n.Fun
   195  	if l.Op() == ir.OTYPE {
   196  		if n.IsDDD {
   197  			base.Fatalf("invalid use of ... in type conversion to %v", l.Type())
   198  		}
   199  
   200  		// pick off before type-checking arguments
   201  		arg, ok := needOneArg(n, "conversion to %v", l.Type())
   202  		if !ok {
   203  			n.SetType(nil)
   204  			return n
   205  		}
   206  
   207  		n := ir.NewConvExpr(n.Pos(), ir.OCONV, nil, arg)
   208  		n.SetType(l.Type())
   209  		return tcConv(n)
   210  	}
   211  
   212  	RewriteNonNameCall(n)
   213  	typecheckargs(n)
   214  	t := l.Type()
   215  	if t == nil {
   216  		n.SetType(nil)
   217  		return n
   218  	}
   219  	types.CheckSize(t)
   220  
   221  	switch l.Op() {
   222  	case ir.ODOTINTER:
   223  		n.SetOp(ir.OCALLINTER)
   224  
   225  	case ir.ODOTMETH:
   226  		l := l.(*ir.SelectorExpr)
   227  		n.SetOp(ir.OCALLMETH)
   228  
   229  		// typecheckaste was used here but there wasn't enough
   230  		// information further down the call chain to know if we
   231  		// were testing a method receiver for unexported fields.
   232  		// It isn't necessary, so just do a sanity check.
   233  		tp := t.Recv().Type
   234  
   235  		if l.X == nil || !types.Identical(l.X.Type(), tp) {
   236  			base.Fatalf("method receiver")
   237  		}
   238  
   239  	default:
   240  		n.SetOp(ir.OCALLFUNC)
   241  		if t.Kind() != types.TFUNC {
   242  			if o := l; o.Name() != nil && types.BuiltinPkg.Lookup(o.Sym().Name).Def != nil {
   243  				// be more specific when the non-function
   244  				// name matches a predeclared function
   245  				base.Errorf("cannot call non-function %L, declared at %s",
   246  					l, base.FmtPos(o.Name().Pos()))
   247  			} else {
   248  				base.Errorf("cannot call non-function %L", l)
   249  			}
   250  			n.SetType(nil)
   251  			return n
   252  		}
   253  	}
   254  
   255  	typecheckaste(ir.OCALL, n.Fun, n.IsDDD, t.Params(), n.Args, func() string { return fmt.Sprintf("argument to %v", n.Fun) })
   256  	FixVariadicCall(n)
   257  	FixMethodCall(n)
   258  	if t.NumResults() == 0 {
   259  		return n
   260  	}
   261  	if t.NumResults() == 1 {
   262  		n.SetType(l.Type().Result(0).Type)
   263  
   264  		if n.Op() == ir.OCALLFUNC && n.Fun.Op() == ir.ONAME {
   265  			if sym := n.Fun.(*ir.Name).Sym(); types.RuntimeSymName(sym) == "getg" {
   266  				// Emit code for runtime.getg() directly instead of calling function.
   267  				// Most such rewrites (for example the similar one for math.Sqrt) should be done in walk,
   268  				// so that the ordering pass can make sure to preserve the semantics of the original code
   269  				// (in particular, the exact time of the function call) by introducing temporaries.
   270  				// In this case, we know getg() always returns the same result within a given function
   271  				// and we want to avoid the temporaries, so we do the rewrite earlier than is typical.
   272  				n.SetOp(ir.OGETG)
   273  			}
   274  		}
   275  		return n
   276  	}
   277  
   278  	// multiple return
   279  	if top&(ctxMultiOK|ctxStmt) == 0 {
   280  		base.Errorf("multiple-value %v() in single-value context", l)
   281  		return n
   282  	}
   283  
   284  	n.SetType(l.Type().ResultsTuple())
   285  	return n
   286  }
   287  
   288  // tcAppend typechecks an OAPPEND node.
   289  func tcAppend(n *ir.CallExpr) ir.Node {
   290  	typecheckargs(n)
   291  	args := n.Args
   292  	if len(args) == 0 {
   293  		base.Errorf("missing arguments to append")
   294  		n.SetType(nil)
   295  		return n
   296  	}
   297  
   298  	t := args[0].Type()
   299  	if t == nil {
   300  		n.SetType(nil)
   301  		return n
   302  	}
   303  
   304  	n.SetType(t)
   305  	if !t.IsSlice() {
   306  		if ir.IsNil(args[0]) {
   307  			base.Errorf("first argument to append must be typed slice; have untyped nil")
   308  			n.SetType(nil)
   309  			return n
   310  		}
   311  
   312  		base.Errorf("first argument to append must be slice; have %L", t)
   313  		n.SetType(nil)
   314  		return n
   315  	}
   316  
   317  	if n.IsDDD {
   318  		if len(args) == 1 {
   319  			base.Errorf("cannot use ... on first argument to append")
   320  			n.SetType(nil)
   321  			return n
   322  		}
   323  
   324  		if len(args) != 2 {
   325  			base.Errorf("too many arguments to append")
   326  			n.SetType(nil)
   327  			return n
   328  		}
   329  
   330  		// AssignConv is of args[1] not required here, as the
   331  		// types of args[0] and args[1] don't need to match
   332  		// (They will both have an underlying type which are
   333  		// slices of identical base types, or be []byte and string.)
   334  		// See issue 53888.
   335  		return n
   336  	}
   337  
   338  	as := args[1:]
   339  	for i, n := range as {
   340  		if n.Type() == nil {
   341  			continue
   342  		}
   343  		as[i] = AssignConv(n, t.Elem(), "append")
   344  		types.CheckSize(as[i].Type()) // ensure width is calculated for backend
   345  	}
   346  	return n
   347  }
   348  
   349  // tcClear typechecks an OCLEAR node.
   350  func tcClear(n *ir.UnaryExpr) ir.Node {
   351  	n.X = Expr(n.X)
   352  	n.X = DefaultLit(n.X, nil)
   353  	l := n.X
   354  	t := l.Type()
   355  	if t == nil {
   356  		n.SetType(nil)
   357  		return n
   358  	}
   359  
   360  	switch {
   361  	case t.IsMap(), t.IsSlice():
   362  	default:
   363  		base.Errorf("invalid operation: %v (argument must be a map or slice)", n)
   364  		n.SetType(nil)
   365  		return n
   366  	}
   367  
   368  	return n
   369  }
   370  
   371  // tcClose typechecks an OCLOSE node.
   372  func tcClose(n *ir.UnaryExpr) ir.Node {
   373  	n.X = Expr(n.X)
   374  	n.X = DefaultLit(n.X, nil)
   375  	l := n.X
   376  	t := l.Type()
   377  	if t == nil {
   378  		n.SetType(nil)
   379  		return n
   380  	}
   381  	if !t.IsChan() {
   382  		base.Errorf("invalid operation: %v (non-chan type %v)", n, t)
   383  		n.SetType(nil)
   384  		return n
   385  	}
   386  
   387  	if !t.ChanDir().CanSend() {
   388  		base.Errorf("invalid operation: %v (cannot close receive-only channel)", n)
   389  		n.SetType(nil)
   390  		return n
   391  	}
   392  	return n
   393  }
   394  
   395  // tcComplex typechecks an OCOMPLEX node.
   396  func tcComplex(n *ir.BinaryExpr) ir.Node {
   397  	l := Expr(n.X)
   398  	r := Expr(n.Y)
   399  	if l.Type() == nil || r.Type() == nil {
   400  		n.SetType(nil)
   401  		return n
   402  	}
   403  	l, r = defaultlit2(l, r, false)
   404  	if l.Type() == nil || r.Type() == nil {
   405  		n.SetType(nil)
   406  		return n
   407  	}
   408  	n.X = l
   409  	n.Y = r
   410  
   411  	if !types.Identical(l.Type(), r.Type()) {
   412  		base.Errorf("invalid operation: %v (mismatched types %v and %v)", n, l.Type(), r.Type())
   413  		n.SetType(nil)
   414  		return n
   415  	}
   416  
   417  	var t *types.Type
   418  	switch l.Type().Kind() {
   419  	default:
   420  		base.Errorf("invalid operation: %v (arguments have type %v, expected floating-point)", n, l.Type())
   421  		n.SetType(nil)
   422  		return n
   423  
   424  	case types.TIDEAL:
   425  		t = types.UntypedComplex
   426  
   427  	case types.TFLOAT32:
   428  		t = types.Types[types.TCOMPLEX64]
   429  
   430  	case types.TFLOAT64:
   431  		t = types.Types[types.TCOMPLEX128]
   432  	}
   433  	n.SetType(t)
   434  	return n
   435  }
   436  
   437  // tcCopy typechecks an OCOPY node.
   438  func tcCopy(n *ir.BinaryExpr) ir.Node {
   439  	n.SetType(types.Types[types.TINT])
   440  	n.X = Expr(n.X)
   441  	n.X = DefaultLit(n.X, nil)
   442  	n.Y = Expr(n.Y)
   443  	n.Y = DefaultLit(n.Y, nil)
   444  	if n.X.Type() == nil || n.Y.Type() == nil {
   445  		n.SetType(nil)
   446  		return n
   447  	}
   448  
   449  	// copy([]byte, string)
   450  	if n.X.Type().IsSlice() && n.Y.Type().IsString() {
   451  		if types.Identical(n.X.Type().Elem(), types.ByteType) {
   452  			return n
   453  		}
   454  		base.Errorf("arguments to copy have different element types: %L and string", n.X.Type())
   455  		n.SetType(nil)
   456  		return n
   457  	}
   458  
   459  	if !n.X.Type().IsSlice() || !n.Y.Type().IsSlice() {
   460  		if !n.X.Type().IsSlice() && !n.Y.Type().IsSlice() {
   461  			base.Errorf("arguments to copy must be slices; have %L, %L", n.X.Type(), n.Y.Type())
   462  		} else if !n.X.Type().IsSlice() {
   463  			base.Errorf("first argument to copy should be slice; have %L", n.X.Type())
   464  		} else {
   465  			base.Errorf("second argument to copy should be slice or string; have %L", n.Y.Type())
   466  		}
   467  		n.SetType(nil)
   468  		return n
   469  	}
   470  
   471  	if !types.Identical(n.X.Type().Elem(), n.Y.Type().Elem()) {
   472  		base.Errorf("arguments to copy have different element types: %L and %L", n.X.Type(), n.Y.Type())
   473  		n.SetType(nil)
   474  		return n
   475  	}
   476  	return n
   477  }
   478  
   479  // tcDelete typechecks an ODELETE node.
   480  func tcDelete(n *ir.CallExpr) ir.Node {
   481  	typecheckargs(n)
   482  	args := n.Args
   483  	if len(args) == 0 {
   484  		base.Errorf("missing arguments to delete")
   485  		n.SetType(nil)
   486  		return n
   487  	}
   488  
   489  	if len(args) == 1 {
   490  		base.Errorf("missing second (key) argument to delete")
   491  		n.SetType(nil)
   492  		return n
   493  	}
   494  
   495  	if len(args) != 2 {
   496  		base.Errorf("too many arguments to delete")
   497  		n.SetType(nil)
   498  		return n
   499  	}
   500  
   501  	l := args[0]
   502  	r := args[1]
   503  	if l.Type() != nil && !l.Type().IsMap() {
   504  		base.Errorf("first argument to delete must be map; have %L", l.Type())
   505  		n.SetType(nil)
   506  		return n
   507  	}
   508  
   509  	args[1] = AssignConv(r, l.Type().Key(), "delete")
   510  	return n
   511  }
   512  
   513  // tcMake typechecks an OMAKE node.
   514  func tcMake(n *ir.CallExpr) ir.Node {
   515  	args := n.Args
   516  	if len(args) == 0 {
   517  		base.Errorf("missing argument to make")
   518  		n.SetType(nil)
   519  		return n
   520  	}
   521  
   522  	n.Args = nil
   523  	l := args[0]
   524  	l = typecheck(l, ctxType)
   525  	t := l.Type()
   526  	if t == nil {
   527  		n.SetType(nil)
   528  		return n
   529  	}
   530  
   531  	i := 1
   532  	var nn ir.Node
   533  	switch t.Kind() {
   534  	default:
   535  		base.Errorf("cannot make type %v", t)
   536  		n.SetType(nil)
   537  		return n
   538  
   539  	case types.TSLICE:
   540  		if i >= len(args) {
   541  			base.Errorf("missing len argument to make(%v)", t)
   542  			n.SetType(nil)
   543  			return n
   544  		}
   545  
   546  		l = args[i]
   547  		i++
   548  		l = Expr(l)
   549  		var r ir.Node
   550  		if i < len(args) {
   551  			r = args[i]
   552  			i++
   553  			r = Expr(r)
   554  		}
   555  
   556  		if l.Type() == nil || (r != nil && r.Type() == nil) {
   557  			n.SetType(nil)
   558  			return n
   559  		}
   560  		if !checkmake(t, "len", &l) || r != nil && !checkmake(t, "cap", &r) {
   561  			n.SetType(nil)
   562  			return n
   563  		}
   564  		if ir.IsConst(l, constant.Int) && r != nil && ir.IsConst(r, constant.Int) && constant.Compare(l.Val(), token.GTR, r.Val()) {
   565  			base.Errorf("len larger than cap in make(%v)", t)
   566  			n.SetType(nil)
   567  			return n
   568  		}
   569  		nn = ir.NewMakeExpr(n.Pos(), ir.OMAKESLICE, l, r)
   570  
   571  	case types.TMAP:
   572  		if i < len(args) {
   573  			l = args[i]
   574  			i++
   575  			l = Expr(l)
   576  			l = DefaultLit(l, types.Types[types.TINT])
   577  			if l.Type() == nil {
   578  				n.SetType(nil)
   579  				return n
   580  			}
   581  			if !checkmake(t, "size", &l) {
   582  				n.SetType(nil)
   583  				return n
   584  			}
   585  		} else {
   586  			l = ir.NewInt(base.Pos, 0)
   587  		}
   588  		nn = ir.NewMakeExpr(n.Pos(), ir.OMAKEMAP, l, nil)
   589  		nn.SetEsc(n.Esc())
   590  
   591  	case types.TCHAN:
   592  		l = nil
   593  		if i < len(args) {
   594  			l = args[i]
   595  			i++
   596  			l = Expr(l)
   597  			l = DefaultLit(l, types.Types[types.TINT])
   598  			if l.Type() == nil {
   599  				n.SetType(nil)
   600  				return n
   601  			}
   602  			if !checkmake(t, "buffer", &l) {
   603  				n.SetType(nil)
   604  				return n
   605  			}
   606  		} else {
   607  			l = ir.NewInt(base.Pos, 0)
   608  		}
   609  		nn = ir.NewMakeExpr(n.Pos(), ir.OMAKECHAN, l, nil)
   610  	}
   611  
   612  	if i < len(args) {
   613  		base.Errorf("too many arguments to make(%v)", t)
   614  		n.SetType(nil)
   615  		return n
   616  	}
   617  
   618  	nn.SetType(t)
   619  	return nn
   620  }
   621  
   622  // tcMakeSliceCopy typechecks an OMAKESLICECOPY node.
   623  func tcMakeSliceCopy(n *ir.MakeExpr) ir.Node {
   624  	// Errors here are Fatalf instead of Errorf because only the compiler
   625  	// can construct an OMAKESLICECOPY node.
   626  	// Components used in OMAKESCLICECOPY that are supplied by parsed source code
   627  	// have already been typechecked in OMAKE and OCOPY earlier.
   628  	t := n.Type()
   629  
   630  	if t == nil {
   631  		base.Fatalf("no type specified for OMAKESLICECOPY")
   632  	}
   633  
   634  	if !t.IsSlice() {
   635  		base.Fatalf("invalid type %v for OMAKESLICECOPY", n.Type())
   636  	}
   637  
   638  	if n.Len == nil {
   639  		base.Fatalf("missing len argument for OMAKESLICECOPY")
   640  	}
   641  
   642  	if n.Cap == nil {
   643  		base.Fatalf("missing slice argument to copy for OMAKESLICECOPY")
   644  	}
   645  
   646  	n.Len = Expr(n.Len)
   647  	n.Cap = Expr(n.Cap)
   648  
   649  	n.Len = DefaultLit(n.Len, types.Types[types.TINT])
   650  
   651  	if !n.Len.Type().IsInteger() && n.Type().Kind() != types.TIDEAL {
   652  		base.Errorf("non-integer len argument in OMAKESLICECOPY")
   653  	}
   654  
   655  	if ir.IsConst(n.Len, constant.Int) {
   656  		if ir.ConstOverflow(n.Len.Val(), types.Types[types.TINT]) {
   657  			base.Fatalf("len for OMAKESLICECOPY too large")
   658  		}
   659  		if constant.Sign(n.Len.Val()) < 0 {
   660  			base.Fatalf("len for OMAKESLICECOPY must be non-negative")
   661  		}
   662  	}
   663  	return n
   664  }
   665  
   666  // tcNew typechecks an ONEW node.
   667  func tcNew(n *ir.UnaryExpr) ir.Node {
   668  	if n.X == nil {
   669  		// Fatalf because the OCALL above checked for us,
   670  		// so this must be an internally-generated mistake.
   671  		base.Fatalf("missing argument to new")
   672  	}
   673  	l := n.X
   674  	l = typecheck(l, ctxType)
   675  	t := l.Type()
   676  	if t == nil {
   677  		n.SetType(nil)
   678  		return n
   679  	}
   680  	n.X = l
   681  	n.SetType(types.NewPtr(t))
   682  	return n
   683  }
   684  
   685  // tcPanic typechecks an OPANIC node.
   686  func tcPanic(n *ir.UnaryExpr) ir.Node {
   687  	n.X = Expr(n.X)
   688  	n.X = AssignConv(n.X, types.Types[types.TINTER], "argument to panic")
   689  	if n.X.Type() == nil {
   690  		n.SetType(nil)
   691  		return n
   692  	}
   693  	return n
   694  }
   695  
   696  // tcPrint typechecks an OPRINT or OPRINTN node.
   697  func tcPrint(n *ir.CallExpr) ir.Node {
   698  	typecheckargs(n)
   699  	ls := n.Args
   700  	for i1, n1 := range ls {
   701  		// Special case for print: int constant is int64, not int.
   702  		if ir.IsConst(n1, constant.Int) {
   703  			ls[i1] = DefaultLit(ls[i1], types.Types[types.TINT64])
   704  		} else {
   705  			ls[i1] = DefaultLit(ls[i1], nil)
   706  		}
   707  	}
   708  	return n
   709  }
   710  
   711  // tcMinMax typechecks an OMIN or OMAX node.
   712  func tcMinMax(n *ir.CallExpr) ir.Node {
   713  	typecheckargs(n)
   714  	arg0 := n.Args[0]
   715  	for _, arg := range n.Args[1:] {
   716  		if !types.Identical(arg.Type(), arg0.Type()) {
   717  			base.FatalfAt(n.Pos(), "mismatched arguments: %L and %L", arg0, arg)
   718  		}
   719  	}
   720  	n.SetType(arg0.Type())
   721  	return n
   722  }
   723  
   724  // tcRealImag typechecks an OREAL or OIMAG node.
   725  func tcRealImag(n *ir.UnaryExpr) ir.Node {
   726  	n.X = Expr(n.X)
   727  	l := n.X
   728  	t := l.Type()
   729  	if t == nil {
   730  		n.SetType(nil)
   731  		return n
   732  	}
   733  
   734  	// Determine result type.
   735  	switch t.Kind() {
   736  	case types.TIDEAL:
   737  		n.SetType(types.UntypedFloat)
   738  	case types.TCOMPLEX64:
   739  		n.SetType(types.Types[types.TFLOAT32])
   740  	case types.TCOMPLEX128:
   741  		n.SetType(types.Types[types.TFLOAT64])
   742  	default:
   743  		base.Errorf("invalid argument %L for %v", l, n.Op())
   744  		n.SetType(nil)
   745  		return n
   746  	}
   747  	return n
   748  }
   749  
   750  // tcRecover typechecks an ORECOVER node.
   751  func tcRecover(n *ir.CallExpr) ir.Node {
   752  	if len(n.Args) != 0 {
   753  		base.Errorf("too many arguments to recover")
   754  		n.SetType(nil)
   755  		return n
   756  	}
   757  
   758  	// FP is equal to caller's SP plus FixedFrameSize.
   759  	var fp ir.Node = ir.NewCallExpr(n.Pos(), ir.OGETCALLERSP, nil, nil)
   760  	if off := base.Ctxt.Arch.FixedFrameSize; off != 0 {
   761  		fp = ir.NewBinaryExpr(n.Pos(), ir.OADD, fp, ir.NewInt(base.Pos, off))
   762  	}
   763  	// TODO(mdempsky): Replace *int32 with unsafe.Pointer, without upsetting checkptr.
   764  	fp = ir.NewConvExpr(n.Pos(), ir.OCONVNOP, types.NewPtr(types.Types[types.TINT32]), fp)
   765  
   766  	n.SetOp(ir.ORECOVERFP)
   767  	n.SetType(types.Types[types.TINTER])
   768  	n.Args = []ir.Node{Expr(fp)}
   769  	return n
   770  }
   771  
   772  // tcUnsafeAdd typechecks an OUNSAFEADD node.
   773  func tcUnsafeAdd(n *ir.BinaryExpr) *ir.BinaryExpr {
   774  	n.X = AssignConv(Expr(n.X), types.Types[types.TUNSAFEPTR], "argument to unsafe.Add")
   775  	n.Y = DefaultLit(Expr(n.Y), types.Types[types.TINT])
   776  	if n.X.Type() == nil || n.Y.Type() == nil {
   777  		n.SetType(nil)
   778  		return n
   779  	}
   780  	if !n.Y.Type().IsInteger() {
   781  		n.SetType(nil)
   782  		return n
   783  	}
   784  	n.SetType(n.X.Type())
   785  	return n
   786  }
   787  
   788  // tcUnsafeSlice typechecks an OUNSAFESLICE node.
   789  func tcUnsafeSlice(n *ir.BinaryExpr) *ir.BinaryExpr {
   790  	n.X = Expr(n.X)
   791  	n.Y = Expr(n.Y)
   792  	if n.X.Type() == nil || n.Y.Type() == nil {
   793  		n.SetType(nil)
   794  		return n
   795  	}
   796  	t := n.X.Type()
   797  	if !t.IsPtr() {
   798  		base.Errorf("first argument to unsafe.Slice must be pointer; have %L", t)
   799  	} else if t.Elem().NotInHeap() {
   800  		// TODO(mdempsky): This can be relaxed, but should only affect the
   801  		// Go runtime itself. End users should only see not-in-heap
   802  		// types due to incomplete C structs in cgo, and those types don't
   803  		// have a meaningful size anyway.
   804  		base.Errorf("unsafe.Slice of incomplete (or unallocatable) type not allowed")
   805  	}
   806  
   807  	if !checkunsafesliceorstring(n.Op(), &n.Y) {
   808  		n.SetType(nil)
   809  		return n
   810  	}
   811  	n.SetType(types.NewSlice(t.Elem()))
   812  	return n
   813  }
   814  
   815  // tcUnsafeString typechecks an OUNSAFESTRING node.
   816  func tcUnsafeString(n *ir.BinaryExpr) *ir.BinaryExpr {
   817  	n.X = Expr(n.X)
   818  	n.Y = Expr(n.Y)
   819  	if n.X.Type() == nil || n.Y.Type() == nil {
   820  		n.SetType(nil)
   821  		return n
   822  	}
   823  	t := n.X.Type()
   824  	if !t.IsPtr() || !types.Identical(t.Elem(), types.Types[types.TUINT8]) {
   825  		base.Errorf("first argument to unsafe.String must be *byte; have %L", t)
   826  	}
   827  
   828  	if !checkunsafesliceorstring(n.Op(), &n.Y) {
   829  		n.SetType(nil)
   830  		return n
   831  	}
   832  	n.SetType(types.Types[types.TSTRING])
   833  	return n
   834  }