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.
8 "cmd/compile/internal/base"
9 "cmd/compile/internal/ir"
10 "cmd/compile/internal/types"
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 {
21 return ir.NewNilExpr(pos, typ)
24 args = append([]ir.Node(nil), args...)
25 lit := ir.NewCompLitExpr(pos, ir.OCOMPLIT, typ, args)
30 base.FatalfAt(pos, "mkdotargslice: typecheck failed")
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.X.Type()
39 if !fntype.IsVariadic() || call.IsDDD {
43 vi := fntype.NumParams() - 1
44 vt := fntype.Param(vi).Type
48 slice := MakeDotArgs(call.Pos(), vt, extra)
49 for i := range extra {
50 extra[i] = nil // allow GC
53 call.Args = append(args[:vi], slice)
57 // FixMethodCall rewrites a method call t.M(...) into a function call T.M(t, ...).
58 func FixMethodCall(call *ir.CallExpr) {
59 if call.X.Op() != ir.ODOTMETH {
63 dot := call.X.(*ir.SelectorExpr)
65 fn := NewMethodExpr(dot.Pos(), dot.X.Type(), dot.Selection.Sym)
67 args := make([]ir.Node, 1+len(call.Args))
69 copy(args[1:], call.Args)
71 call.SetOp(ir.OCALLFUNC)
76 func AssertFixedCall(call *ir.CallExpr) {
77 if call.X.Type().IsVariadic() && !call.IsDDD {
78 base.FatalfAt(call.Pos(), "missed FixVariadicCall")
80 if call.Op() == ir.OCALLMETH {
81 base.FatalfAt(call.Pos(), "missed FixMethodCall")
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:
94 // clos = &struct{F uintptr; X0 *int; X1 *string}{func.1, &i, &s}
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.
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 {
109 typ = types.NewPtr(typ)
111 fields[1+i] = types.NewField(base.AutogeneratedPos, types.LocalPkg.LookupNum("X", i), typ)
113 typ := types.NewStruct(fields)
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()),
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)
138 if name := n.Nname; name.Typecheck() == 0 {
139 base.AssertfAt(name.Type() != nil, n.Pos(), "missing type: %v", name)
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.X = typecheck(n.X, ctxExpr|ctxType|ctxCallee)
151 if l.Op() == ir.ONAME && l.(*ir.Name).BuiltinOp != 0 {
153 if n.IsDDD && l.BuiltinOp != ir.OAPPEND {
154 base.Errorf("invalid use of ... with builtin %v", l)
157 // builtin: OLEN, OCAP, etc.
160 base.Fatalf("unknown builtin %v", l)
162 case ir.OAPPEND, ir.ODELETE, ir.OMAKE, ir.OMAX, ir.OMIN, ir.OPRINT, ir.OPRINTN, ir.ORECOVER:
165 n.SetTypecheck(0) // re-typechecking new op is OK, not a loop
166 return typecheck(n, top)
168 case ir.OCAP, ir.OCLEAR, ir.OCLOSE, ir.OIMAG, ir.OLEN, ir.OPANIC, ir.OREAL, ir.OUNSAFESTRINGDATA, ir.OUNSAFESLICEDATA:
171 case ir.ONEW, ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF:
172 arg, ok := needOneArg(n, "%v", n.Op())
177 u := ir.NewUnaryExpr(n.Pos(), l.BuiltinOp, arg)
178 return typecheck(ir.InitExpr(n.Init(), u), top) // typecheckargs can add to old.Init
180 case ir.OCOMPLEX, ir.OCOPY, ir.OUNSAFEADD, ir.OUNSAFESLICE, ir.OUNSAFESTRING:
182 arg1, arg2, ok := needTwoArgs(n)
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
193 n.X = DefaultLit(n.X, nil)
195 if l.Op() == ir.OTYPE {
197 base.Fatalf("invalid use of ... in type conversion to %v", l.Type())
200 // pick off before type-checking arguments
201 arg, ok := needOneArg(n, "conversion to %v", l.Type())
207 n := ir.NewConvExpr(n.Pos(), ir.OCONV, nil, arg)
212 RewriteNonNameCall(n)
223 n.SetOp(ir.OCALLINTER)
226 l := l.(*ir.SelectorExpr)
227 n.SetOp(ir.OCALLMETH)
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.
235 if l.X == nil || !types.Identical(l.X.Type(), tp) {
236 base.Fatalf("method receiver")
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()))
248 base.Errorf("cannot call non-function %L", l)
255 typecheckaste(ir.OCALL, n.X, n.IsDDD, t.Params(), n.Args, func() string { return fmt.Sprintf("argument to %v", n.X) })
258 if t.NumResults() == 0 {
261 if t.NumResults() == 1 {
262 n.SetType(l.Type().Result(0).Type)
264 if n.Op() == ir.OCALLFUNC && n.X.Op() == ir.ONAME {
265 if sym := n.X.(*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.
279 if top&(ctxMultiOK|ctxStmt) == 0 {
280 base.Errorf("multiple-value %v() in single-value context", l)
284 n.SetType(l.Type().ResultsTuple())
288 // tcAppend typechecks an OAPPEND node.
289 func tcAppend(n *ir.CallExpr) ir.Node {
293 base.Errorf("missing arguments to append")
306 if ir.IsNil(args[0]) {
307 base.Errorf("first argument to append must be typed slice; have untyped nil")
312 base.Errorf("first argument to append must be slice; have %L", t)
319 base.Errorf("cannot use ... on first argument to append")
325 base.Errorf("too many arguments to append")
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.)
339 for i, n := range as {
343 as[i] = AssignConv(n, t.Elem(), "append")
344 types.CheckSize(as[i].Type()) // ensure width is calculated for backend
349 // tcClear typechecks an OCLEAR node.
350 func tcClear(n *ir.UnaryExpr) ir.Node {
352 n.X = DefaultLit(n.X, nil)
361 case t.IsMap(), t.IsSlice():
363 base.Errorf("invalid operation: %v (argument must be a map or slice)", n)
371 // tcClose typechecks an OCLOSE node.
372 func tcClose(n *ir.UnaryExpr) ir.Node {
374 n.X = DefaultLit(n.X, nil)
382 base.Errorf("invalid operation: %v (non-chan type %v)", n, t)
387 if !t.ChanDir().CanSend() {
388 base.Errorf("invalid operation: %v (cannot close receive-only channel)", n)
395 // tcComplex typechecks an OCOMPLEX node.
396 func tcComplex(n *ir.BinaryExpr) ir.Node {
399 if l.Type() == nil || r.Type() == nil {
403 l, r = defaultlit2(l, r, false)
404 if l.Type() == nil || r.Type() == nil {
411 if !types.Identical(l.Type(), r.Type()) {
412 base.Errorf("invalid operation: %v (mismatched types %v and %v)", n, l.Type(), r.Type())
418 switch l.Type().Kind() {
420 base.Errorf("invalid operation: %v (arguments have type %v, expected floating-point)", n, l.Type())
425 t = types.UntypedComplex
428 t = types.Types[types.TCOMPLEX64]
431 t = types.Types[types.TCOMPLEX128]
437 // tcCopy typechecks an OCOPY node.
438 func tcCopy(n *ir.BinaryExpr) ir.Node {
439 n.SetType(types.Types[types.TINT])
441 n.X = DefaultLit(n.X, nil)
443 n.Y = DefaultLit(n.Y, nil)
444 if n.X.Type() == nil || n.Y.Type() == nil {
449 // copy([]byte, string)
450 if n.X.Type().IsSlice() && n.Y.Type().IsString() {
451 if types.Identical(n.X.Type().Elem(), types.ByteType) {
454 base.Errorf("arguments to copy have different element types: %L and string", n.X.Type())
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())
465 base.Errorf("second argument to copy should be slice or string; have %L", n.Y.Type())
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())
479 // tcDelete typechecks an ODELETE node.
480 func tcDelete(n *ir.CallExpr) ir.Node {
484 base.Errorf("missing arguments to delete")
490 base.Errorf("missing second (key) argument to delete")
496 base.Errorf("too many arguments to delete")
503 if l.Type() != nil && !l.Type().IsMap() {
504 base.Errorf("first argument to delete must be map; have %L", l.Type())
509 args[1] = AssignConv(r, l.Type().Key(), "delete")
513 // tcMake typechecks an OMAKE node.
514 func tcMake(n *ir.CallExpr) ir.Node {
517 base.Errorf("missing argument to make")
524 l = typecheck(l, ctxType)
535 base.Errorf("cannot make type %v", t)
541 base.Errorf("missing len argument to make(%v)", t)
556 if l.Type() == nil || (r != nil && r.Type() == nil) {
560 if !checkmake(t, "len", &l) || r != nil && !checkmake(t, "cap", &r) {
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)
569 nn = ir.NewMakeExpr(n.Pos(), ir.OMAKESLICE, l, r)
576 l = DefaultLit(l, types.Types[types.TINT])
581 if !checkmake(t, "size", &l) {
586 l = ir.NewInt(base.Pos, 0)
588 nn = ir.NewMakeExpr(n.Pos(), ir.OMAKEMAP, l, nil)
597 l = DefaultLit(l, types.Types[types.TINT])
602 if !checkmake(t, "buffer", &l) {
607 l = ir.NewInt(base.Pos, 0)
609 nn = ir.NewMakeExpr(n.Pos(), ir.OMAKECHAN, l, nil)
613 base.Errorf("too many arguments to make(%v)", t)
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.
631 base.Fatalf("no type specified for OMAKESLICECOPY")
635 base.Fatalf("invalid type %v for OMAKESLICECOPY", n.Type())
639 base.Fatalf("missing len argument for OMAKESLICECOPY")
643 base.Fatalf("missing slice argument to copy for OMAKESLICECOPY")
649 n.Len = DefaultLit(n.Len, types.Types[types.TINT])
651 if !n.Len.Type().IsInteger() && n.Type().Kind() != types.TIDEAL {
652 base.Errorf("non-integer len argument in OMAKESLICECOPY")
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")
659 if constant.Sign(n.Len.Val()) < 0 {
660 base.Fatalf("len for OMAKESLICECOPY must be non-negative")
666 // tcNew typechecks an ONEW node.
667 func tcNew(n *ir.UnaryExpr) ir.Node {
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")
674 l = typecheck(l, ctxType)
681 n.SetType(types.NewPtr(t))
685 // tcPanic typechecks an OPANIC node.
686 func tcPanic(n *ir.UnaryExpr) ir.Node {
688 n.X = AssignConv(n.X, types.Types[types.TINTER], "argument to panic")
689 if n.X.Type() == nil {
696 // tcPrint typechecks an OPRINT or OPRINTN node.
697 func tcPrint(n *ir.CallExpr) ir.Node {
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])
705 ls[i1] = DefaultLit(ls[i1], nil)
711 // tcMinMax typechecks an OMIN or OMAX node.
712 func tcMinMax(n *ir.CallExpr) ir.Node {
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)
720 n.SetType(arg0.Type())
724 // tcRealImag typechecks an OREAL or OIMAG node.
725 func tcRealImag(n *ir.UnaryExpr) ir.Node {
734 // Determine result type.
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])
743 base.Errorf("invalid argument %L for %v", l, n.Op())
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")
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))
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)
766 n.SetOp(ir.ORECOVERFP)
767 n.SetType(types.Types[types.TINTER])
768 n.Args = []ir.Node{Expr(fp)}
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 {
780 if !n.Y.Type().IsInteger() {
784 n.SetType(n.X.Type())
788 // tcUnsafeSlice typechecks an OUNSAFESLICE node.
789 func tcUnsafeSlice(n *ir.BinaryExpr) *ir.BinaryExpr {
792 if n.X.Type() == nil || n.Y.Type() == nil {
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")
807 if !checkunsafesliceorstring(n.Op(), &n.Y) {
811 n.SetType(types.NewSlice(t.Elem()))
815 // tcUnsafeString typechecks an OUNSAFESTRING node.
816 func tcUnsafeString(n *ir.BinaryExpr) *ir.BinaryExpr {
819 if n.X.Type() == nil || n.Y.Type() == nil {
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)
828 if !checkunsafesliceorstring(n.Op(), &n.Y) {
832 n.SetType(types.Types[types.TSTRING])