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 5package typecheck 6 7import ( 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. 19func 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. 37func 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, ...). 58func 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 76func 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. 88func 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. 124func 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.) 136func 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. 148func 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. 292func 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. 353func 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. 375func 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. 399func 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. 441func 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. 483func 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. 517func 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. 626func 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. 670func 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. 689func 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. 700func 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. 715func 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. 728func 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. 754func 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. 776func 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. 792func 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. 819func 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. 841type ClosureStructIter struct { 842 closureVars []*ir.Name 843 offset int64 844 next int 845} 846 847// NewClosureStructIter creates a new ClosureStructIter for closureVars. 848func 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. 858func (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