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 {
22 n = ir.NewNilExpr(pos)
25 args = append([]ir.Node(nil), args...)
26 lit := ir.NewCompLitExpr(pos, ir.OCOMPLIT, ir.TypeNode(typ), args)
33 base.FatalfAt(pos, "mkdotargslice: typecheck failed")
38 // FixVariadicCall rewrites calls to variadic functions to use an
39 // explicit ... argument if one is not already present.
40 func FixVariadicCall(call *ir.CallExpr) {
41 fntype := call.X.Type()
42 if !fntype.IsVariadic() || call.IsDDD {
46 vi := fntype.NumParams() - 1
47 vt := fntype.Params().Field(vi).Type
51 slice := MakeDotArgs(call.Pos(), vt, extra)
52 for i := range extra {
53 extra[i] = nil // allow GC
56 call.Args = append(args[:vi], slice)
60 // FixMethodCall rewrites a method call t.M(...) into a function call T.M(t, ...).
61 func FixMethodCall(call *ir.CallExpr) {
62 if call.X.Op() != ir.ODOTMETH {
66 dot := call.X.(*ir.SelectorExpr)
68 fn := Expr(ir.NewSelectorExpr(dot.Pos(), ir.OXDOT, ir.TypeNode(dot.X.Type()), dot.Selection.Sym))
70 args := make([]ir.Node, 1+len(call.Args))
72 copy(args[1:], call.Args)
74 call.SetOp(ir.OCALLFUNC)
79 // ClosureType returns the struct type used to hold all the information
80 // needed in the closure for clo (clo must be a OCLOSURE node).
81 // The address of a variable of the returned type can be cast to a func.
82 func ClosureType(clo *ir.ClosureExpr) *types.Type {
83 // Create closure in the form of a composite literal.
84 // supposing the closure captures an int i and a string s
85 // and has one float64 argument and no results,
86 // the generated code looks like:
88 // clos = &struct{.F uintptr; i *int; s *string}{func.1, &i, &s}
90 // The use of the struct provides type information to the garbage
91 // collector so that it can walk the closure. We could use (in this case)
92 // [3]unsafe.Pointer instead, but that would leave the gc in the dark.
93 // The information appears in the binary in the form of type descriptors;
94 // the struct is unnamed so that closures in multiple packages with the
95 // same struct type can share the descriptor.
97 // Make sure the .F field is in the same package as the rest of the
98 // fields. This deals with closures in instantiated functions, which are
99 // compiled as if from the source package of the generic function.
101 if len(clo.Func.ClosureVars) == 0 {
104 for _, v := range clo.Func.ClosureVars {
107 } else if pkg != v.Sym().Pkg {
108 base.Fatalf("Closure variables from multiple packages")
113 fields := []*types.Field{
114 types.NewField(base.Pos, pkg.Lookup(".F"), types.Types[types.TUINTPTR]),
116 for _, v := range clo.Func.ClosureVars {
119 typ = types.NewPtr(typ)
121 fields = append(fields, types.NewField(base.Pos, v.Sym(), typ))
123 typ := types.NewStruct(types.NoPkg, fields)
128 // PartialCallType returns the struct type used to hold all the information
129 // needed in the closure for n (n must be a OMETHVALUE node).
130 // The address of a variable of the returned type can be cast to a func.
131 func PartialCallType(n *ir.SelectorExpr) *types.Type {
132 t := types.NewStruct(types.NoPkg, []*types.Field{
133 types.NewField(base.Pos, Lookup("F"), types.Types[types.TUINTPTR]),
134 types.NewField(base.Pos, Lookup("R"), n.X.Type()),
140 // True if we are typechecking an inline body in ImportedBody below. We use this
141 // flag to not create a new closure function in tcClosure when we are just
142 // typechecking an inline body, as opposed to the body of a real function.
143 var inTypeCheckInl bool
145 // ImportedBody returns immediately if the inlining information for fn is
146 // populated. Otherwise, fn must be an imported function. If so, ImportedBody
147 // loads in the dcls and body for fn, and typechecks as needed.
148 func ImportedBody(fn *ir.Func) {
149 if fn.Inl.Body != nil {
152 lno := ir.SetPos(fn.Nname)
154 // When we load an inlined body, we need to allow OADDR
155 // operations on untyped expressions. We will fix the
156 // addrtaken flags on all the arguments of the OADDR with the
157 // computeAddrtaken call below (after we typecheck the body).
158 // TODO: export/import types and addrtaken marks along with inlined bodies,
159 // so this will be unnecessary.
160 IncrementalAddrtaken = false
163 ComputeAddrtaken(fn.Inl.Body) // compute addrtaken marks once types are available
164 DirtyAddrtaken = false
166 IncrementalAddrtaken = true
171 // Stmts(fn.Inl.Body) below is only for imported functions;
172 // their bodies may refer to unsafe as long as the package
173 // was marked safe during import (which was checked then).
174 // the ->inl of a local function has been typechecked before CanInline copied it.
175 pkg := fnpkg(fn.Nname)
177 if pkg == types.LocalPkg || pkg == nil {
178 return // ImportedBody on local function
181 if base.Flag.LowerM > 2 || base.Debug.Export != 0 {
182 fmt.Printf("typecheck import [%v] %L { %v }\n", fn.Sym(), fn, ir.Nodes(fn.Inl.Body))
185 if !go117ExportTypes {
186 // If we didn't export & import types, typecheck the code here.
190 base.Fatalf("inTypeCheckInl should not be set recursively")
192 inTypeCheckInl = true
194 inTypeCheckInl = false
201 // Get the function's package. For ordinary functions it's on the ->sym, but for imported methods
202 // the ->sym can be re-used in the local package, so peel it off the receiver's type.
203 func fnpkg(fn *ir.Name) *types.Pkg {
206 rcvr := fn.Type().Recv().Type
211 if rcvr.Sym() == nil {
212 base.Fatalf("receiver with no sym: [%v] %L (%v)", fn.Sym(), fn, rcvr)
214 return rcvr.Sym().Pkg
221 // tcClosure typechecks an OCLOSURE node. It also creates the named
222 // function associated with the closure.
223 // TODO: This creation of the named function should probably really be done in a
224 // separate pass from type-checking.
225 func tcClosure(clo *ir.ClosureExpr, top int) ir.Node {
228 // We used to allow IR builders to typecheck the underlying Func
229 // themselves, but that led to too much variety and inconsistency
230 // around who's responsible for naming the function, typechecking
231 // it, or adding it to Target.Decls.
233 // It's now all or nothing. Callers are still allowed to do these
234 // themselves, but then they assume responsibility for all of them.
235 if fn.Typecheck() == 1 {
236 base.FatalfAt(fn.Pos(), "underlying closure func already typechecked: %v", fn)
239 // Set current associated iota value, so iota can be used inside
240 // function in ConstSpec, see issue #22344
241 if x := getIotaValue(); x >= 0 {
245 fn.SetClosureCalled(top&ctxCallee != 0)
247 ir.NameClosure(clo, ir.CurFunc)
250 // Type check the body now, but only if we're inside a function.
251 // At top level (in a variable initialization: curfn==nil) we're not
252 // ready to type check code yet; we'll check it later, because the
253 // underlying closure function we create is added to Target.Decls.
254 if ir.CurFunc != nil {
262 for _, v := range fn.ClosureVars {
264 // If v.Type is nil, it means v looked like it was going to be
265 // used in the closure, but isn't. This happens in struct
266 // literals like s{f: x} where we can't distinguish whether f is
267 // a field identifier or expression until resolving s.
271 // type check closed variables outside the closure, so that the
272 // outer frame also captures them.
275 fn.ClosureVars[out] = v
278 fn.ClosureVars = fn.ClosureVars[:out]
280 clo.SetType(fn.Type())
284 // We're typechecking an imported function, so it's not actually
285 // part of Target. Skip adding it to Target.Decls so we don't
290 return ir.UseClosure(clo, target)
293 // type check function definition
294 // To be called by typecheck, not directly.
295 // (Call typecheck.Func instead.)
296 func tcFunc(n *ir.Func) {
297 if base.EnableTrace && base.Flag.LowerT {
298 defer tracePrint("tcFunc", n)(nil)
301 n.Nname = AssignExpr(n.Nname).(*ir.Name)
307 if rcvr != nil && n.Shortname != nil {
308 m := addmethod(n, n.Shortname, t, true, n.Pragma&ir.Nointerface != 0)
313 n.Nname.SetSym(ir.MethodSym(rcvr.Type, n.Shortname))
314 Declare(n.Nname, ir.PFUNC)
318 // tcCall typechecks an OCALL node.
319 func tcCall(n *ir.CallExpr, top int) ir.Node {
320 n.Use = ir.CallUseExpr
322 n.Use = ir.CallUseStmt
324 Stmts(n.Init()) // imported rewritten f(g()) calls (#30907)
325 n.X = typecheck(n.X, ctxExpr|ctxType|ctxCallee)
332 if l.Op() == ir.ONAME && l.(*ir.Name).BuiltinOp != 0 {
334 if n.IsDDD && l.BuiltinOp != ir.OAPPEND {
335 base.Errorf("invalid use of ... with builtin %v", l)
338 // builtin: OLEN, OCAP, etc.
341 base.Fatalf("unknown builtin %v", l)
343 case ir.OAPPEND, ir.ODELETE, ir.OMAKE, ir.OPRINT, ir.OPRINTN, ir.ORECOVER:
346 n.SetTypecheck(0) // re-typechecking new op is OK, not a loop
347 return typecheck(n, top)
349 case ir.OCAP, ir.OCLOSE, ir.OIMAG, ir.OLEN, ir.OPANIC, ir.OREAL:
352 case ir.ONEW, ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF:
353 arg, ok := needOneArg(n, "%v", n.Op())
358 u := ir.NewUnaryExpr(n.Pos(), l.BuiltinOp, arg)
359 return typecheck(ir.InitExpr(n.Init(), u), top) // typecheckargs can add to old.Init
361 case ir.OCOMPLEX, ir.OCOPY, ir.OUNSAFEADD, ir.OUNSAFESLICE:
363 arg1, arg2, ok := needTwoArgs(n)
368 b := ir.NewBinaryExpr(n.Pos(), l.BuiltinOp, arg1, arg2)
369 return typecheck(ir.InitExpr(n.Init(), b), top) // typecheckargs can add to old.Init
374 n.X = DefaultLit(n.X, nil)
376 if l.Op() == ir.OTYPE {
378 if !l.Type().Broke() {
379 base.Errorf("invalid use of ... in type conversion to %v", l.Type())
384 // pick off before type-checking arguments
385 arg, ok := needOneArg(n, "conversion to %v", l.Type())
391 n := ir.NewConvExpr(n.Pos(), ir.OCONV, nil, arg)
406 n.SetOp(ir.OCALLINTER)
409 l := l.(*ir.SelectorExpr)
410 n.SetOp(ir.OCALLMETH)
412 // typecheckaste was used here but there wasn't enough
413 // information further down the call chain to know if we
414 // were testing a method receiver for unexported fields.
415 // It isn't necessary, so just do a sanity check.
418 if l.X == nil || !types.Identical(l.X.Type(), tp) {
419 base.Fatalf("method receiver")
423 n.SetOp(ir.OCALLFUNC)
424 if t.Kind() != types.TFUNC {
425 if o := ir.Orig(l); o.Name() != nil && types.BuiltinPkg.Lookup(o.Sym().Name).Def != nil {
426 // be more specific when the non-function
427 // name matches a predeclared function
428 base.Errorf("cannot call non-function %L, declared at %s",
429 l, base.FmtPos(o.Name().Pos()))
431 base.Errorf("cannot call non-function %L", l)
438 typecheckaste(ir.OCALL, n.X, n.IsDDD, t.Params(), n.Args, func() string { return fmt.Sprintf("argument to %v", n.X) })
440 if t.NumResults() == 0 {
443 if t.NumResults() == 1 {
444 n.SetType(l.Type().Results().Field(0).Type)
446 if n.Op() == ir.OCALLFUNC && n.X.Op() == ir.ONAME {
447 if sym := n.X.(*ir.Name).Sym(); types.IsRuntimePkg(sym.Pkg) && sym.Name == "getg" {
448 // Emit code for runtime.getg() directly instead of calling function.
449 // Most such rewrites (for example the similar one for math.Sqrt) should be done in walk,
450 // so that the ordering pass can make sure to preserve the semantics of the original code
451 // (in particular, the exact time of the function call) by introducing temporaries.
452 // In this case, we know getg() always returns the same result within a given function
453 // and we want to avoid the temporaries, so we do the rewrite earlier than is typical.
461 if top&(ctxMultiOK|ctxStmt) == 0 {
462 base.Errorf("multiple-value %v() in single-value context", l)
466 n.SetType(l.Type().Results())
470 // tcAppend typechecks an OAPPEND node.
471 func tcAppend(n *ir.CallExpr) ir.Node {
475 base.Errorf("missing arguments to append")
488 if ir.IsNil(args[0]) {
489 base.Errorf("first argument to append must be typed slice; have untyped nil")
494 base.Errorf("first argument to append must be slice; have %L", t)
501 base.Errorf("cannot use ... on first argument to append")
507 base.Errorf("too many arguments to append")
512 if t.Elem().IsKind(types.TUINT8) && args[1].Type().IsString() {
513 args[1] = DefaultLit(args[1], types.Types[types.TSTRING])
517 args[1] = AssignConv(args[1], t.Underlying(), "append")
522 for i, n := range as {
526 as[i] = AssignConv(n, t.Elem(), "append")
527 types.CheckSize(as[i].Type()) // ensure width is calculated for backend
532 // tcClose typechecks an OCLOSE node.
533 func tcClose(n *ir.UnaryExpr) ir.Node {
535 n.X = DefaultLit(n.X, nil)
543 base.Errorf("invalid operation: %v (non-chan type %v)", n, t)
548 if !t.ChanDir().CanSend() {
549 base.Errorf("invalid operation: %v (cannot close receive-only channel)", n)
556 // tcComplex typechecks an OCOMPLEX node.
557 func tcComplex(n *ir.BinaryExpr) ir.Node {
560 if l.Type() == nil || r.Type() == nil {
564 l, r = defaultlit2(l, r, false)
565 if l.Type() == nil || r.Type() == nil {
572 if !types.Identical(l.Type(), r.Type()) {
573 base.Errorf("invalid operation: %v (mismatched types %v and %v)", n, l.Type(), r.Type())
579 switch l.Type().Kind() {
581 base.Errorf("invalid operation: %v (arguments have type %v, expected floating-point)", n, l.Type())
586 t = types.UntypedComplex
589 t = types.Types[types.TCOMPLEX64]
592 t = types.Types[types.TCOMPLEX128]
598 // tcCopy typechecks an OCOPY node.
599 func tcCopy(n *ir.BinaryExpr) ir.Node {
600 n.SetType(types.Types[types.TINT])
602 n.X = DefaultLit(n.X, nil)
604 n.Y = DefaultLit(n.Y, nil)
605 if n.X.Type() == nil || n.Y.Type() == nil {
610 // copy([]byte, string)
611 if n.X.Type().IsSlice() && n.Y.Type().IsString() {
612 if types.Identical(n.X.Type().Elem(), types.ByteType) {
615 base.Errorf("arguments to copy have different element types: %L and string", n.X.Type())
620 if !n.X.Type().IsSlice() || !n.Y.Type().IsSlice() {
621 if !n.X.Type().IsSlice() && !n.Y.Type().IsSlice() {
622 base.Errorf("arguments to copy must be slices; have %L, %L", n.X.Type(), n.Y.Type())
623 } else if !n.X.Type().IsSlice() {
624 base.Errorf("first argument to copy should be slice; have %L", n.X.Type())
626 base.Errorf("second argument to copy should be slice or string; have %L", n.Y.Type())
632 if !types.Identical(n.X.Type().Elem(), n.Y.Type().Elem()) {
633 base.Errorf("arguments to copy have different element types: %L and %L", n.X.Type(), n.Y.Type())
640 // tcDelete typechecks an ODELETE node.
641 func tcDelete(n *ir.CallExpr) ir.Node {
645 base.Errorf("missing arguments to delete")
651 base.Errorf("missing second (key) argument to delete")
657 base.Errorf("too many arguments to delete")
664 if l.Type() != nil && !l.Type().IsMap() {
665 base.Errorf("first argument to delete must be map; have %L", l.Type())
670 args[1] = AssignConv(r, l.Type().Key(), "delete")
674 // tcMake typechecks an OMAKE node.
675 func tcMake(n *ir.CallExpr) ir.Node {
678 base.Errorf("missing argument to make")
685 l = typecheck(l, ctxType)
696 base.Errorf("cannot make type %v", t)
702 base.Errorf("missing len argument to make(%v)", t)
717 if l.Type() == nil || (r != nil && r.Type() == nil) {
721 if !checkmake(t, "len", &l) || r != nil && !checkmake(t, "cap", &r) {
725 if ir.IsConst(l, constant.Int) && r != nil && ir.IsConst(r, constant.Int) && constant.Compare(l.Val(), token.GTR, r.Val()) {
726 base.Errorf("len larger than cap in make(%v)", t)
730 nn = ir.NewMakeExpr(n.Pos(), ir.OMAKESLICE, l, r)
737 l = DefaultLit(l, types.Types[types.TINT])
742 if !checkmake(t, "size", &l) {
749 nn = ir.NewMakeExpr(n.Pos(), ir.OMAKEMAP, l, nil)
758 l = DefaultLit(l, types.Types[types.TINT])
763 if !checkmake(t, "buffer", &l) {
770 nn = ir.NewMakeExpr(n.Pos(), ir.OMAKECHAN, l, nil)
774 base.Errorf("too many arguments to make(%v)", t)
783 // tcMakeSliceCopy typechecks an OMAKESLICECOPY node.
784 func tcMakeSliceCopy(n *ir.MakeExpr) ir.Node {
785 // Errors here are Fatalf instead of Errorf because only the compiler
786 // can construct an OMAKESLICECOPY node.
787 // Components used in OMAKESCLICECOPY that are supplied by parsed source code
788 // have already been typechecked in OMAKE and OCOPY earlier.
792 base.Fatalf("no type specified for OMAKESLICECOPY")
796 base.Fatalf("invalid type %v for OMAKESLICECOPY", n.Type())
800 base.Fatalf("missing len argument for OMAKESLICECOPY")
804 base.Fatalf("missing slice argument to copy for OMAKESLICECOPY")
810 n.Len = DefaultLit(n.Len, types.Types[types.TINT])
812 if !n.Len.Type().IsInteger() && n.Type().Kind() != types.TIDEAL {
813 base.Errorf("non-integer len argument in OMAKESLICECOPY")
816 if ir.IsConst(n.Len, constant.Int) {
817 if ir.ConstOverflow(n.Len.Val(), types.Types[types.TINT]) {
818 base.Fatalf("len for OMAKESLICECOPY too large")
820 if constant.Sign(n.Len.Val()) < 0 {
821 base.Fatalf("len for OMAKESLICECOPY must be non-negative")
827 // tcNew typechecks an ONEW node.
828 func tcNew(n *ir.UnaryExpr) ir.Node {
830 // Fatalf because the OCALL above checked for us,
831 // so this must be an internally-generated mistake.
832 base.Fatalf("missing argument to new")
835 l = typecheck(l, ctxType)
842 n.SetType(types.NewPtr(t))
846 // tcPanic typechecks an OPANIC node.
847 func tcPanic(n *ir.UnaryExpr) ir.Node {
849 n.X = AssignConv(n.X, types.Types[types.TINTER], "argument to panic")
850 if n.X.Type() == nil {
857 // tcPrint typechecks an OPRINT or OPRINTN node.
858 func tcPrint(n *ir.CallExpr) ir.Node {
861 for i1, n1 := range ls {
862 // Special case for print: int constant is int64, not int.
863 if ir.IsConst(n1, constant.Int) {
864 ls[i1] = DefaultLit(ls[i1], types.Types[types.TINT64])
866 ls[i1] = DefaultLit(ls[i1], nil)
872 // tcRealImag typechecks an OREAL or OIMAG node.
873 func tcRealImag(n *ir.UnaryExpr) ir.Node {
882 // Determine result type.
885 n.SetType(types.UntypedFloat)
886 case types.TCOMPLEX64:
887 n.SetType(types.Types[types.TFLOAT32])
888 case types.TCOMPLEX128:
889 n.SetType(types.Types[types.TFLOAT64])
891 base.Errorf("invalid argument %L for %v", l, n.Op())
898 // tcRecover typechecks an ORECOVER node.
899 func tcRecover(n *ir.CallExpr) ir.Node {
900 if len(n.Args) != 0 {
901 base.Errorf("too many arguments to recover")
906 n.SetType(types.Types[types.TINTER])
910 // tcRecoverFP typechecks an ORECOVERFP node.
911 func tcRecoverFP(n *ir.CallExpr) ir.Node {
912 if len(n.Args) != 1 {
913 base.FatalfAt(n.Pos(), "wrong number of arguments: %v", n)
916 n.Args[0] = Expr(n.Args[0])
917 if !n.Args[0].Type().IsPtrShaped() {
918 base.FatalfAt(n.Pos(), "%L is not pointer shaped", n.Args[0])
921 n.SetType(types.Types[types.TINTER])
925 // tcUnsafeAdd typechecks an OUNSAFEADD node.
926 func tcUnsafeAdd(n *ir.BinaryExpr) *ir.BinaryExpr {
927 if !types.AllowsGoVersion(curpkg(), 1, 17) {
928 base.ErrorfVers("go1.17", "unsafe.Add")
933 n.X = AssignConv(Expr(n.X), types.Types[types.TUNSAFEPTR], "argument to unsafe.Add")
934 n.Y = DefaultLit(Expr(n.Y), types.Types[types.TINT])
935 if n.X.Type() == nil || n.Y.Type() == nil {
939 if !n.Y.Type().IsInteger() {
943 n.SetType(n.X.Type())
947 // tcUnsafeSlice typechecks an OUNSAFESLICE node.
948 func tcUnsafeSlice(n *ir.BinaryExpr) *ir.BinaryExpr {
949 if !types.AllowsGoVersion(curpkg(), 1, 17) {
950 base.ErrorfVers("go1.17", "unsafe.Slice")
957 if n.X.Type() == nil || n.Y.Type() == nil {
963 base.Errorf("first argument to unsafe.Slice must be pointer; have %L", t)
964 } else if t.Elem().NotInHeap() {
965 // TODO(mdempsky): This can be relaxed, but should only affect the
966 // Go runtime itself. End users should only see //go:notinheap
967 // types due to incomplete C structs in cgo, and those types don't
968 // have a meaningful size anyway.
969 base.Errorf("unsafe.Slice of incomplete (or unallocatable) type not allowed")
972 if !checkunsafeslice(&n.Y) {
976 n.SetType(types.NewSlice(t.Elem()))