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"
17 // package all the arguments that match a ... T parameter into a []T.
18 func MakeDotArgs(typ *types.Type, args []ir.Node) ir.Node {
24 lit := ir.NewCompLitExpr(base.Pos, ir.OCOMPLIT, ir.TypeNode(typ), nil)
25 lit.List.Append(args...)
32 base.Fatalf("mkdotargslice: typecheck failed")
37 // FixVariadicCall rewrites calls to variadic functions to use an
38 // explicit ... argument if one is not already present.
39 func FixVariadicCall(call *ir.CallExpr) {
40 fntype := call.X.Type()
41 if !fntype.IsVariadic() || call.IsDDD {
45 vi := fntype.NumParams() - 1
46 vt := fntype.Params().Field(vi).Type
50 slice := MakeDotArgs(vt, extra)
51 for i := range extra {
52 extra[i] = nil // allow GC
55 call.Args = append(args[:vi], slice)
59 // ClosureType returns the struct type used to hold all the information
60 // needed in the closure for clo (clo must be a OCLOSURE node).
61 // The address of a variable of the returned type can be cast to a func.
62 func ClosureType(clo *ir.ClosureExpr) *types.Type {
63 // Create closure in the form of a composite literal.
64 // supposing the closure captures an int i and a string s
65 // and has one float64 argument and no results,
66 // the generated code looks like:
68 // clos = &struct{.F uintptr; i *int; s *string}{func.1, &i, &s}
70 // The use of the struct provides type information to the garbage
71 // collector so that it can walk the closure. We could use (in this case)
72 // [3]unsafe.Pointer instead, but that would leave the gc in the dark.
73 // The information appears in the binary in the form of type descriptors;
74 // the struct is unnamed so that closures in multiple packages with the
75 // same struct type can share the descriptor.
76 fields := []*types.Field{
77 types.NewField(base.Pos, Lookup(".F"), types.Types[types.TUINTPTR]),
79 for _, v := range clo.Func.ClosureVars {
82 typ = types.NewPtr(typ)
84 fields = append(fields, types.NewField(base.Pos, v.Sym(), typ))
86 typ := types.NewStruct(types.NoPkg, fields)
91 // PartialCallType returns the struct type used to hold all the information
92 // needed in the closure for n (n must be a OCALLPART node).
93 // The address of a variable of the returned type can be cast to a func.
94 func PartialCallType(n *ir.SelectorExpr) *types.Type {
95 t := types.NewStruct(types.NoPkg, []*types.Field{
96 types.NewField(base.Pos, Lookup("F"), types.Types[types.TUINTPTR]),
97 types.NewField(base.Pos, Lookup("R"), n.X.Type()),
103 // Lazy typechecking of imported bodies. For local functions, CanInline will set ->typecheck
104 // because they're a copy of an already checked body.
105 func ImportedBody(fn *ir.Func) {
106 lno := ir.SetPos(fn.Nname)
108 // When we load an inlined body, we need to allow OADDR
109 // operations on untyped expressions. We will fix the
110 // addrtaken flags on all the arguments of the OADDR with the
111 // computeAddrtaken call below (after we typecheck the body).
112 // TODO: export/import types and addrtaken marks along with inlined bodies,
113 // so this will be unnecessary.
114 IncrementalAddrtaken = false
117 ComputeAddrtaken(fn.Inl.Body) // compute addrtaken marks once types are available
118 DirtyAddrtaken = false
120 IncrementalAddrtaken = true
125 // Stmts(fn.Inl.Body) below is only for imported functions;
126 // their bodies may refer to unsafe as long as the package
127 // was marked safe during import (which was checked then).
128 // the ->inl of a local function has been typechecked before CanInline copied it.
129 pkg := fnpkg(fn.Nname)
131 if pkg == types.LocalPkg || pkg == nil {
132 return // ImportedBody on local function
135 if base.Flag.LowerM > 2 || base.Debug.Export != 0 {
136 fmt.Printf("typecheck import [%v] %L { %v }\n", fn.Sym(), fn, ir.Nodes(fn.Inl.Body))
144 // During ImportBody (which imports fn.Func.Inl.Body),
145 // declarations are added to fn.Func.Dcl by funcBody(). Move them
146 // to fn.Func.Inl.Dcl for consistency with how local functions
147 // behave. (Append because ImportedBody may be called multiple
148 // times on same fn.)
149 fn.Inl.Dcl = append(fn.Inl.Dcl, fn.Dcl...)
155 // Get the function's package. For ordinary functions it's on the ->sym, but for imported methods
156 // the ->sym can be re-used in the local package, so peel it off the receiver's type.
157 func fnpkg(fn *ir.Name) *types.Pkg {
160 rcvr := fn.Type().Recv().Type
165 if rcvr.Sym() == nil {
166 base.Fatalf("receiver with no sym: [%v] %L (%v)", fn.Sym(), fn, rcvr)
168 return rcvr.Sym().Pkg
175 // closurename generates a new unique name for a closure within
177 func ClosureName(outerfunc *ir.Func) *types.Sym {
182 if outerfunc != nil {
183 if outerfunc.OClosure != nil {
187 outer = ir.FuncName(outerfunc)
189 // There may be multiple functions named "_". In those
190 // cases, we can't use their individual Closgens as it
191 // would lead to name clashes.
192 if !ir.IsBlank(outerfunc.Nname) {
193 gen = &outerfunc.Closgen
198 return Lookup(fmt.Sprintf("%s.%s%d", outer, prefix, *gen))
201 // globClosgen is like Func.Closgen, but for the global scope.
202 var globClosgen int32
204 // MethodValueWrapper returns the DCLFUNC node representing the
205 // wrapper function (*-fm) needed for the given method value. If the
206 // wrapper function hasn't already been created yet, it's created and
207 // added to Target.Decls.
209 // TODO(mdempsky): Move into walk. This isn't part of type checking.
210 func MethodValueWrapper(dot *ir.SelectorExpr) *ir.Func {
211 if dot.Op() != ir.OCALLPART {
212 base.Fatalf("MethodValueWrapper: unexpected %v (%v)", dot, dot.Op())
217 rcvrtype := dot.X.Type()
218 sym := ir.MethodSymSuffix(rcvrtype, meth, "-fm")
221 return sym.Def.(*ir.Func)
225 savecurfn := ir.CurFunc
226 saveLineNo := base.Pos
229 // Set line number equal to the line number where the method is declared.
230 if pos := dot.Selection.Pos; pos.IsKnown() {
233 // Note: !dot.Selection.Pos.IsKnown() happens for method expressions where
234 // the method is implicitly declared. The Error method of the
235 // built-in error type is one such method. We leave the line
236 // number at the use of the method expression in this
237 // case. See issue 29389.
239 tfn := ir.NewFuncType(base.Pos, nil,
240 NewFuncParams(t0.Params(), true),
241 NewFuncParams(t0.Results(), false))
243 fn := DeclFunc(sym, tfn)
248 // Declare and initialize variable holding receiver.
249 ptr := ir.NewNameAt(base.Pos, Lookup(".this"))
250 ptr.Class = ir.PAUTOHEAP
251 ptr.SetType(rcvrtype)
253 ptr.SetIsClosureVar(true)
255 fn.ClosureVars = append(fn.ClosureVars, ptr)
257 call := ir.NewCallExpr(base.Pos, ir.OCALL, ir.NewSelectorExpr(base.Pos, ir.OXDOT, ptr, meth), nil)
258 call.Args = ir.ParamNames(tfn.Type())
259 call.IsDDD = tfn.Type().IsVariadic()
261 var body ir.Node = call
262 if t0.NumResults() != 0 {
263 ret := ir.NewReturnStmt(base.Pos, nil)
264 ret.Results = []ir.Node{call}
268 fn.Body = []ir.Node{body}
272 // Need to typecheck the body of the just-generated wrapper.
273 // typecheckslice() requires that Curfn is set when processing an ORETURN.
277 Target.Decls = append(Target.Decls, fn)
278 ir.CurFunc = savecurfn
279 base.Pos = saveLineNo
284 // tcClosure typechecks an OCLOSURE node. It also creates the named
285 // function associated with the closure.
286 // TODO: This creation of the named function should probably really be done in a
287 // separate pass from type-checking.
288 func tcClosure(clo *ir.ClosureExpr, top int) {
290 // Set current associated iota value, so iota can be used inside
291 // function in ConstSpec, see issue #22344
292 if x := getIotaValue(); x >= 0 {
296 fn.SetClosureCalled(top&ctxCallee != 0)
298 // Do not typecheck fn twice, otherwise, we will end up pushing
299 // fn to Target.Decls multiple times, causing InitLSym called twice.
301 if fn.Typecheck() == 1 {
302 clo.SetType(fn.Type())
306 // Don't give a name and add to xtop if we are typechecking an inlined
307 // body in ImportedBody(), since we only want to create the named function
308 // when the closure is actually inlined (and then we force a typecheck
309 // explicitly in (*inlsubst).node()).
310 inTypeCheckInl := ir.CurFunc != nil && ir.CurFunc.Body == nil
312 fn.Nname.SetSym(ClosureName(ir.CurFunc))
313 ir.MarkFunc(fn.Nname)
316 clo.SetType(fn.Type())
318 // Type check the body now, but only if we're inside a function.
319 // At top level (in a variable initialization: curfn==nil) we're not
320 // ready to type check code yet; we'll check it later, because the
321 // underlying closure function we create is added to Target.Decls.
322 if ir.CurFunc != nil && clo.Type() != nil {
330 for _, v := range fn.ClosureVars {
332 // If v.Type is nil, it means v looked like it was going to be
333 // used in the closure, but isn't. This happens in struct
334 // literals like s{f: x} where we can't distinguish whether f is
335 // a field identifier or expression until resolving s.
339 // type check closed variables outside the closure, so that the
340 // outer frame also captures them.
343 fn.ClosureVars[out] = v
346 fn.ClosureVars = fn.ClosureVars[:out]
349 s := fmt.Sprintf("New closure func: %s", ir.FuncName(fn))
353 // Add function to xtop once only when we give it a name
354 Target.Decls = append(Target.Decls, fn)
358 // type check function definition
359 // To be called by typecheck, not directly.
360 // (Call typecheck.Func instead.)
361 func tcFunc(n *ir.Func) {
362 if base.EnableTrace && base.Flag.LowerT {
363 defer tracePrint("tcFunc", n)(nil)
366 n.Nname = AssignExpr(n.Nname).(*ir.Name)
372 if rcvr != nil && n.Shortname != nil {
373 m := addmethod(n, n.Shortname, t, true, n.Pragma&ir.Nointerface != 0)
378 n.Nname.SetSym(ir.MethodSym(rcvr.Type, n.Shortname))
379 Declare(n.Nname, ir.PFUNC)
383 // tcCall typechecks an OCALL node.
384 func tcCall(n *ir.CallExpr, top int) ir.Node {
385 n.Use = ir.CallUseExpr
387 n.Use = ir.CallUseStmt
389 Stmts(n.Init()) // imported rewritten f(g()) calls (#30907)
390 n.X = typecheck(n.X, ctxExpr|ctxType|ctxCallee)
397 if l.Op() == ir.ONAME && l.(*ir.Name).BuiltinOp != 0 {
399 if n.IsDDD && l.BuiltinOp != ir.OAPPEND {
400 base.Errorf("invalid use of ... with builtin %v", l)
403 // builtin: OLEN, OCAP, etc.
406 base.Fatalf("unknown builtin %v", l)
408 case ir.OAPPEND, ir.ODELETE, ir.OMAKE, ir.OPRINT, ir.OPRINTN, ir.ORECOVER:
411 n.SetTypecheck(0) // re-typechecking new op is OK, not a loop
412 return typecheck(n, top)
414 case ir.OCAP, ir.OCLOSE, ir.OIMAG, ir.OLEN, ir.OPANIC, ir.OREAL:
417 case ir.ONEW, ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF:
418 arg, ok := needOneArg(n, "%v", n.Op())
423 u := ir.NewUnaryExpr(n.Pos(), l.BuiltinOp, arg)
424 return typecheck(ir.InitExpr(n.Init(), u), top) // typecheckargs can add to old.Init
426 case ir.OCOMPLEX, ir.OCOPY:
428 arg1, arg2, ok := needTwoArgs(n)
433 b := ir.NewBinaryExpr(n.Pos(), l.BuiltinOp, arg1, arg2)
434 return typecheck(ir.InitExpr(n.Init(), b), top) // typecheckargs can add to old.Init
439 n.X = DefaultLit(n.X, nil)
441 if l.Op() == ir.OTYPE {
443 if !l.Type().Broke() {
444 base.Errorf("invalid use of ... in type conversion to %v", l.Type())
449 // pick off before type-checking arguments
450 arg, ok := needOneArg(n, "conversion to %v", l.Type())
456 n := ir.NewConvExpr(n.Pos(), ir.OCONV, nil, arg)
458 return typecheck1(n, top)
471 n.SetOp(ir.OCALLINTER)
474 l := l.(*ir.SelectorExpr)
475 n.SetOp(ir.OCALLMETH)
477 // typecheckaste was used here but there wasn't enough
478 // information further down the call chain to know if we
479 // were testing a method receiver for unexported fields.
480 // It isn't necessary, so just do a sanity check.
483 if l.X == nil || !types.Identical(l.X.Type(), tp) {
484 base.Fatalf("method receiver")
488 n.SetOp(ir.OCALLFUNC)
489 if t.Kind() != types.TFUNC {
490 if o := ir.Orig(l); o.Name() != nil && types.BuiltinPkg.Lookup(o.Sym().Name).Def != nil {
491 // be more specific when the non-function
492 // name matches a predeclared function
493 base.Errorf("cannot call non-function %L, declared at %s",
494 l, base.FmtPos(o.Name().Pos()))
496 base.Errorf("cannot call non-function %L", l)
503 typecheckaste(ir.OCALL, n.X, n.IsDDD, t.Params(), n.Args, func() string { return fmt.Sprintf("argument to %v", n.X) })
504 if t.NumResults() == 0 {
507 if t.NumResults() == 1 {
508 n.SetType(l.Type().Results().Field(0).Type)
510 if n.Op() == ir.OCALLFUNC && n.X.Op() == ir.ONAME {
511 if sym := n.X.(*ir.Name).Sym(); types.IsRuntimePkg(sym.Pkg) && sym.Name == "getg" {
512 // Emit code for runtime.getg() directly instead of calling function.
513 // Most such rewrites (for example the similar one for math.Sqrt) should be done in walk,
514 // so that the ordering pass can make sure to preserve the semantics of the original code
515 // (in particular, the exact time of the function call) by introducing temporaries.
516 // In this case, we know getg() always returns the same result within a given function
517 // and we want to avoid the temporaries, so we do the rewrite earlier than is typical.
525 if top&(ctxMultiOK|ctxStmt) == 0 {
526 base.Errorf("multiple-value %v() in single-value context", l)
530 n.SetType(l.Type().Results())
534 // tcAppend typechecks an OAPPEND node.
535 func tcAppend(n *ir.CallExpr) ir.Node {
539 base.Errorf("missing arguments to append")
552 if ir.IsNil(args[0]) {
553 base.Errorf("first argument to append must be typed slice; have untyped nil")
558 base.Errorf("first argument to append must be slice; have %L", t)
565 base.Errorf("cannot use ... on first argument to append")
571 base.Errorf("too many arguments to append")
576 if t.Elem().IsKind(types.TUINT8) && args[1].Type().IsString() {
577 args[1] = DefaultLit(args[1], types.Types[types.TSTRING])
581 args[1] = AssignConv(args[1], t.Underlying(), "append")
586 for i, n := range as {
590 as[i] = AssignConv(n, t.Elem(), "append")
591 types.CheckSize(as[i].Type()) // ensure width is calculated for backend
596 // tcClose typechecks an OCLOSE node.
597 func tcClose(n *ir.UnaryExpr) ir.Node {
599 n.X = DefaultLit(n.X, nil)
607 base.Errorf("invalid operation: %v (non-chan type %v)", n, t)
612 if !t.ChanDir().CanSend() {
613 base.Errorf("invalid operation: %v (cannot close receive-only channel)", n)
620 // tcComplex typechecks an OCOMPLEX node.
621 func tcComplex(n *ir.BinaryExpr) ir.Node {
624 if l.Type() == nil || r.Type() == nil {
628 l, r = defaultlit2(l, r, false)
629 if l.Type() == nil || r.Type() == nil {
636 if !types.Identical(l.Type(), r.Type()) {
637 base.Errorf("invalid operation: %v (mismatched types %v and %v)", n, l.Type(), r.Type())
643 switch l.Type().Kind() {
645 base.Errorf("invalid operation: %v (arguments have type %v, expected floating-point)", n, l.Type())
650 t = types.UntypedComplex
653 t = types.Types[types.TCOMPLEX64]
656 t = types.Types[types.TCOMPLEX128]
662 // tcCopy typechecks an OCOPY node.
663 func tcCopy(n *ir.BinaryExpr) ir.Node {
664 n.SetType(types.Types[types.TINT])
666 n.X = DefaultLit(n.X, nil)
668 n.Y = DefaultLit(n.Y, nil)
669 if n.X.Type() == nil || n.Y.Type() == nil {
674 // copy([]byte, string)
675 if n.X.Type().IsSlice() && n.Y.Type().IsString() {
676 if types.Identical(n.X.Type().Elem(), types.ByteType) {
679 base.Errorf("arguments to copy have different element types: %L and string", n.X.Type())
684 if !n.X.Type().IsSlice() || !n.Y.Type().IsSlice() {
685 if !n.X.Type().IsSlice() && !n.Y.Type().IsSlice() {
686 base.Errorf("arguments to copy must be slices; have %L, %L", n.X.Type(), n.Y.Type())
687 } else if !n.X.Type().IsSlice() {
688 base.Errorf("first argument to copy should be slice; have %L", n.X.Type())
690 base.Errorf("second argument to copy should be slice or string; have %L", n.Y.Type())
696 if !types.Identical(n.X.Type().Elem(), n.Y.Type().Elem()) {
697 base.Errorf("arguments to copy have different element types: %L and %L", n.X.Type(), n.Y.Type())
704 // tcDelete typechecks an ODELETE node.
705 func tcDelete(n *ir.CallExpr) ir.Node {
709 base.Errorf("missing arguments to delete")
715 base.Errorf("missing second (key) argument to delete")
721 base.Errorf("too many arguments to delete")
728 if l.Type() != nil && !l.Type().IsMap() {
729 base.Errorf("first argument to delete must be map; have %L", l.Type())
734 args[1] = AssignConv(r, l.Type().Key(), "delete")
738 // tcMake typechecks an OMAKE node.
739 func tcMake(n *ir.CallExpr) ir.Node {
742 base.Errorf("missing argument to make")
749 l = typecheck(l, ctxType)
760 base.Errorf("cannot make type %v", t)
766 base.Errorf("missing len argument to make(%v)", t)
781 if l.Type() == nil || (r != nil && r.Type() == nil) {
785 if !checkmake(t, "len", &l) || r != nil && !checkmake(t, "cap", &r) {
789 if ir.IsConst(l, constant.Int) && r != nil && ir.IsConst(r, constant.Int) && constant.Compare(l.Val(), token.GTR, r.Val()) {
790 base.Errorf("len larger than cap in make(%v)", t)
794 nn = ir.NewMakeExpr(n.Pos(), ir.OMAKESLICE, l, r)
801 l = DefaultLit(l, types.Types[types.TINT])
806 if !checkmake(t, "size", &l) {
813 nn = ir.NewMakeExpr(n.Pos(), ir.OMAKEMAP, l, nil)
822 l = DefaultLit(l, types.Types[types.TINT])
827 if !checkmake(t, "buffer", &l) {
834 nn = ir.NewMakeExpr(n.Pos(), ir.OMAKECHAN, l, nil)
838 base.Errorf("too many arguments to make(%v)", t)
847 // tcMakeSliceCopy typechecks an OMAKESLICECOPY node.
848 func tcMakeSliceCopy(n *ir.MakeExpr) ir.Node {
849 // Errors here are Fatalf instead of Errorf because only the compiler
850 // can construct an OMAKESLICECOPY node.
851 // Components used in OMAKESCLICECOPY that are supplied by parsed source code
852 // have already been typechecked in OMAKE and OCOPY earlier.
856 base.Fatalf("no type specified for OMAKESLICECOPY")
860 base.Fatalf("invalid type %v for OMAKESLICECOPY", n.Type())
864 base.Fatalf("missing len argument for OMAKESLICECOPY")
868 base.Fatalf("missing slice argument to copy for OMAKESLICECOPY")
874 n.Len = DefaultLit(n.Len, types.Types[types.TINT])
876 if !n.Len.Type().IsInteger() && n.Type().Kind() != types.TIDEAL {
877 base.Errorf("non-integer len argument in OMAKESLICECOPY")
880 if ir.IsConst(n.Len, constant.Int) {
881 if ir.ConstOverflow(n.Len.Val(), types.Types[types.TINT]) {
882 base.Fatalf("len for OMAKESLICECOPY too large")
884 if constant.Sign(n.Len.Val()) < 0 {
885 base.Fatalf("len for OMAKESLICECOPY must be non-negative")
891 // tcNew typechecks an ONEW node.
892 func tcNew(n *ir.UnaryExpr) ir.Node {
894 // Fatalf because the OCALL above checked for us,
895 // so this must be an internally-generated mistake.
896 base.Fatalf("missing argument to new")
899 l = typecheck(l, ctxType)
906 n.SetType(types.NewPtr(t))
910 // tcPanic typechecks an OPANIC node.
911 func tcPanic(n *ir.UnaryExpr) ir.Node {
913 n.X = AssignConv(n.X, types.Types[types.TINTER], "argument to panic")
914 if n.X.Type() == nil {
921 // tcPrint typechecks an OPRINT or OPRINTN node.
922 func tcPrint(n *ir.CallExpr) ir.Node {
925 for i1, n1 := range ls {
926 // Special case for print: int constant is int64, not int.
927 if ir.IsConst(n1, constant.Int) {
928 ls[i1] = DefaultLit(ls[i1], types.Types[types.TINT64])
930 ls[i1] = DefaultLit(ls[i1], nil)
936 // tcRealImag typechecks an OREAL or OIMAG node.
937 func tcRealImag(n *ir.UnaryExpr) ir.Node {
946 // Determine result type.
949 n.SetType(types.UntypedFloat)
950 case types.TCOMPLEX64:
951 n.SetType(types.Types[types.TFLOAT32])
952 case types.TCOMPLEX128:
953 n.SetType(types.Types[types.TFLOAT64])
955 base.Errorf("invalid argument %L for %v", l, n.Op())
962 // tcRecover typechecks an ORECOVER node.
963 func tcRecover(n *ir.CallExpr) ir.Node {
964 if len(n.Args) != 0 {
965 base.Errorf("too many arguments to recover")
970 n.SetType(types.Types[types.TINTER])