Source file src/cmd/compile/internal/typecheck/func.go

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

View as plain text