github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/compile/typecheck/func.go (about) 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 "github.com/go-asm/go/cmd/compile/base" 9 "github.com/go-asm/go/cmd/compile/ir" 10 "github.com/go-asm/go/cmd/compile/types" 11 "github.com/go-asm/go/cmd/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 for i, v := range clo.Func.ClosureVars { 107 typ := v.Type() 108 if !v.Byval() { 109 typ = types.NewPtr(typ) 110 } 111 fields[1+i] = types.NewField(base.AutogeneratedPos, types.LocalPkg.LookupNum("X", i), typ) 112 } 113 typ := types.NewStruct(fields) 114 typ.SetNoalg(true) 115 return typ 116 } 117 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()), 125 }) 126 t.SetNoalg(true) 127 return t 128 } 129 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) 136 } 137 138 if name := n.Nname; name.Typecheck() == 0 { 139 base.AssertfAt(name.Type() != nil, n.Pos(), "missing type: %v", name) 140 name.SetTypecheck(1) 141 } 142 } 143 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.Fun = typecheck(n.Fun, ctxExpr|ctxType|ctxCallee) 148 149 l := n.Fun 150 151 if l.Op() == ir.ONAME && l.(*ir.Name).BuiltinOp != 0 { 152 l := l.(*ir.Name) 153 if n.IsDDD && l.BuiltinOp != ir.OAPPEND { 154 base.Errorf("invalid use of ... with builtin %v", l) 155 } 156 157 // builtin: OLEN, OCAP, etc. 158 switch l.BuiltinOp { 159 default: 160 base.Fatalf("unknown builtin %v", l) 161 162 case ir.OAPPEND, ir.ODELETE, ir.OMAKE, ir.OMAX, ir.OMIN, ir.OPRINT, ir.OPRINTLN, ir.ORECOVER: 163 n.SetOp(l.BuiltinOp) 164 n.Fun = nil 165 n.SetTypecheck(0) // re-typechecking new op is OK, not a loop 166 return typecheck(n, top) 167 168 case ir.OCAP, ir.OCLEAR, ir.OCLOSE, ir.OIMAG, ir.OLEN, ir.OPANIC, ir.OREAL, ir.OUNSAFESTRINGDATA, ir.OUNSAFESLICEDATA: 169 typecheckargs(n) 170 fallthrough 171 case ir.ONEW: 172 arg, ok := needOneArg(n, "%v", n.Op()) 173 if !ok { 174 n.SetType(nil) 175 return n 176 } 177 u := ir.NewUnaryExpr(n.Pos(), l.BuiltinOp, arg) 178 return typecheck(ir.InitExpr(n.Init(), u), top) // typecheckargs can add to old.Init 179 180 case ir.OCOMPLEX, ir.OCOPY, ir.OUNSAFEADD, ir.OUNSAFESLICE, ir.OUNSAFESTRING: 181 typecheckargs(n) 182 arg1, arg2, ok := needTwoArgs(n) 183 if !ok { 184 n.SetType(nil) 185 return n 186 } 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 189 } 190 panic("unreachable") 191 } 192 193 n.Fun = DefaultLit(n.Fun, nil) 194 l = n.Fun 195 if l.Op() == ir.OTYPE { 196 if n.IsDDD { 197 base.Fatalf("invalid use of ... in type conversion to %v", l.Type()) 198 } 199 200 // pick off before type-checking arguments 201 arg, ok := needOneArg(n, "conversion to %v", l.Type()) 202 if !ok { 203 n.SetType(nil) 204 return n 205 } 206 207 n := ir.NewConvExpr(n.Pos(), ir.OCONV, nil, arg) 208 n.SetType(l.Type()) 209 return tcConv(n) 210 } 211 212 RewriteNonNameCall(n) 213 typecheckargs(n) 214 t := l.Type() 215 if t == nil { 216 n.SetType(nil) 217 return n 218 } 219 types.CheckSize(t) 220 221 switch l.Op() { 222 case ir.ODOTINTER: 223 n.SetOp(ir.OCALLINTER) 224 225 case ir.ODOTMETH: 226 l := l.(*ir.SelectorExpr) 227 n.SetOp(ir.OCALLMETH) 228 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. 233 tp := t.Recv().Type 234 235 if l.X == nil || !types.Identical(l.X.Type(), tp) { 236 base.Fatalf("method receiver") 237 } 238 239 default: 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())) 247 } else { 248 base.Errorf("cannot call non-function %L", l) 249 } 250 n.SetType(nil) 251 return n 252 } 253 } 254 255 typecheckaste(ir.OCALL, n.Fun, n.IsDDD, t.Params(), n.Args, func() string { return fmt.Sprintf("argument to %v", n.Fun) }) 256 FixVariadicCall(n) 257 FixMethodCall(n) 258 if t.NumResults() == 0 { 259 return n 260 } 261 if t.NumResults() == 1 { 262 n.SetType(l.Type().Result(0).Type) 263 264 if n.Op() == ir.OCALLFUNC && n.Fun.Op() == ir.ONAME { 265 if sym := n.Fun.(*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. 272 n.SetOp(ir.OGETG) 273 } 274 } 275 return n 276 } 277 278 // multiple return 279 if top&(ctxMultiOK|ctxStmt) == 0 { 280 base.Errorf("multiple-value %v() in single-value context", l) 281 return n 282 } 283 284 n.SetType(l.Type().ResultsTuple()) 285 return n 286 } 287 288 // tcAppend typechecks an OAPPEND node. 289 func tcAppend(n *ir.CallExpr) ir.Node { 290 typecheckargs(n) 291 args := n.Args 292 if len(args) == 0 { 293 base.Errorf("missing arguments to append") 294 n.SetType(nil) 295 return n 296 } 297 298 t := args[0].Type() 299 if t == nil { 300 n.SetType(nil) 301 return n 302 } 303 304 n.SetType(t) 305 if !t.IsSlice() { 306 if ir.IsNil(args[0]) { 307 base.Errorf("first argument to append must be typed slice; have untyped nil") 308 n.SetType(nil) 309 return n 310 } 311 312 base.Errorf("first argument to append must be slice; have %L", t) 313 n.SetType(nil) 314 return n 315 } 316 317 if n.IsDDD { 318 if len(args) == 1 { 319 base.Errorf("cannot use ... on first argument to append") 320 n.SetType(nil) 321 return n 322 } 323 324 if len(args) != 2 { 325 base.Errorf("too many arguments to append") 326 n.SetType(nil) 327 return n 328 } 329 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.) 334 // See issue 53888. 335 return n 336 } 337 338 as := args[1:] 339 for i, n := range as { 340 if n.Type() == nil { 341 continue 342 } 343 as[i] = AssignConv(n, t.Elem(), "append") 344 types.CheckSize(as[i].Type()) // ensure width is calculated for backend 345 } 346 return n 347 } 348 349 // tcClear typechecks an OCLEAR node. 350 func tcClear(n *ir.UnaryExpr) ir.Node { 351 n.X = Expr(n.X) 352 n.X = DefaultLit(n.X, nil) 353 l := n.X 354 t := l.Type() 355 if t == nil { 356 n.SetType(nil) 357 return n 358 } 359 360 switch { 361 case t.IsMap(), t.IsSlice(): 362 default: 363 base.Errorf("invalid operation: %v (argument must be a map or slice)", n) 364 n.SetType(nil) 365 return n 366 } 367 368 return n 369 } 370 371 // tcClose typechecks an OCLOSE node. 372 func tcClose(n *ir.UnaryExpr) ir.Node { 373 n.X = Expr(n.X) 374 n.X = DefaultLit(n.X, nil) 375 l := n.X 376 t := l.Type() 377 if t == nil { 378 n.SetType(nil) 379 return n 380 } 381 if !t.IsChan() { 382 base.Errorf("invalid operation: %v (non-chan type %v)", n, t) 383 n.SetType(nil) 384 return n 385 } 386 387 if !t.ChanDir().CanSend() { 388 base.Errorf("invalid operation: %v (cannot close receive-only channel)", n) 389 n.SetType(nil) 390 return n 391 } 392 return n 393 } 394 395 // tcComplex typechecks an OCOMPLEX node. 396 func tcComplex(n *ir.BinaryExpr) ir.Node { 397 l := Expr(n.X) 398 r := Expr(n.Y) 399 if l.Type() == nil || r.Type() == nil { 400 n.SetType(nil) 401 return n 402 } 403 l, r = defaultlit2(l, r, false) 404 if l.Type() == nil || r.Type() == nil { 405 n.SetType(nil) 406 return n 407 } 408 n.X = l 409 n.Y = r 410 411 if !types.Identical(l.Type(), r.Type()) { 412 base.Errorf("invalid operation: %v (mismatched types %v and %v)", n, l.Type(), r.Type()) 413 n.SetType(nil) 414 return n 415 } 416 417 var t *types.Type 418 switch l.Type().Kind() { 419 default: 420 base.Errorf("invalid operation: %v (arguments have type %v, expected floating-point)", n, l.Type()) 421 n.SetType(nil) 422 return n 423 424 case types.TIDEAL: 425 t = types.UntypedComplex 426 427 case types.TFLOAT32: 428 t = types.Types[types.TCOMPLEX64] 429 430 case types.TFLOAT64: 431 t = types.Types[types.TCOMPLEX128] 432 } 433 n.SetType(t) 434 return n 435 } 436 437 // tcCopy typechecks an OCOPY node. 438 func tcCopy(n *ir.BinaryExpr) ir.Node { 439 n.SetType(types.Types[types.TINT]) 440 n.X = Expr(n.X) 441 n.X = DefaultLit(n.X, nil) 442 n.Y = Expr(n.Y) 443 n.Y = DefaultLit(n.Y, nil) 444 if n.X.Type() == nil || n.Y.Type() == nil { 445 n.SetType(nil) 446 return n 447 } 448 449 // copy([]byte, string) 450 if n.X.Type().IsSlice() && n.Y.Type().IsString() { 451 if types.Identical(n.X.Type().Elem(), types.ByteType) { 452 return n 453 } 454 base.Errorf("arguments to copy have different element types: %L and string", n.X.Type()) 455 n.SetType(nil) 456 return n 457 } 458 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()) 464 } else { 465 base.Errorf("second argument to copy should be slice or string; have %L", n.Y.Type()) 466 } 467 n.SetType(nil) 468 return n 469 } 470 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()) 473 n.SetType(nil) 474 return n 475 } 476 return n 477 } 478 479 // tcDelete typechecks an ODELETE node. 480 func tcDelete(n *ir.CallExpr) ir.Node { 481 typecheckargs(n) 482 args := n.Args 483 if len(args) == 0 { 484 base.Errorf("missing arguments to delete") 485 n.SetType(nil) 486 return n 487 } 488 489 if len(args) == 1 { 490 base.Errorf("missing second (key) argument to delete") 491 n.SetType(nil) 492 return n 493 } 494 495 if len(args) != 2 { 496 base.Errorf("too many arguments to delete") 497 n.SetType(nil) 498 return n 499 } 500 501 l := args[0] 502 r := args[1] 503 if l.Type() != nil && !l.Type().IsMap() { 504 base.Errorf("first argument to delete must be map; have %L", l.Type()) 505 n.SetType(nil) 506 return n 507 } 508 509 args[1] = AssignConv(r, l.Type().Key(), "delete") 510 return n 511 } 512 513 // tcMake typechecks an OMAKE node. 514 func tcMake(n *ir.CallExpr) ir.Node { 515 args := n.Args 516 if len(args) == 0 { 517 base.Errorf("missing argument to make") 518 n.SetType(nil) 519 return n 520 } 521 522 n.Args = nil 523 l := args[0] 524 l = typecheck(l, ctxType) 525 t := l.Type() 526 if t == nil { 527 n.SetType(nil) 528 return n 529 } 530 531 i := 1 532 var nn ir.Node 533 switch t.Kind() { 534 default: 535 base.Errorf("cannot make type %v", t) 536 n.SetType(nil) 537 return n 538 539 case types.TSLICE: 540 if i >= len(args) { 541 base.Errorf("missing len argument to make(%v)", t) 542 n.SetType(nil) 543 return n 544 } 545 546 l = args[i] 547 i++ 548 l = Expr(l) 549 var r ir.Node 550 if i < len(args) { 551 r = args[i] 552 i++ 553 r = Expr(r) 554 } 555 556 if l.Type() == nil || (r != nil && r.Type() == nil) { 557 n.SetType(nil) 558 return n 559 } 560 if !checkmake(t, "len", &l) || r != nil && !checkmake(t, "cap", &r) { 561 n.SetType(nil) 562 return n 563 } 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) 566 n.SetType(nil) 567 return n 568 } 569 nn = ir.NewMakeExpr(n.Pos(), ir.OMAKESLICE, l, r) 570 571 case types.TMAP: 572 if i < len(args) { 573 l = args[i] 574 i++ 575 l = Expr(l) 576 l = DefaultLit(l, types.Types[types.TINT]) 577 if l.Type() == nil { 578 n.SetType(nil) 579 return n 580 } 581 if !checkmake(t, "size", &l) { 582 n.SetType(nil) 583 return n 584 } 585 } else { 586 l = ir.NewInt(base.Pos, 0) 587 } 588 nn = ir.NewMakeExpr(n.Pos(), ir.OMAKEMAP, l, nil) 589 nn.SetEsc(n.Esc()) 590 591 case types.TCHAN: 592 l = nil 593 if i < len(args) { 594 l = args[i] 595 i++ 596 l = Expr(l) 597 l = DefaultLit(l, types.Types[types.TINT]) 598 if l.Type() == nil { 599 n.SetType(nil) 600 return n 601 } 602 if !checkmake(t, "buffer", &l) { 603 n.SetType(nil) 604 return n 605 } 606 } else { 607 l = ir.NewInt(base.Pos, 0) 608 } 609 nn = ir.NewMakeExpr(n.Pos(), ir.OMAKECHAN, l, nil) 610 } 611 612 if i < len(args) { 613 base.Errorf("too many arguments to make(%v)", t) 614 n.SetType(nil) 615 return n 616 } 617 618 nn.SetType(t) 619 return nn 620 } 621 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. 628 t := n.Type() 629 630 if t == nil { 631 base.Fatalf("no type specified for OMAKESLICECOPY") 632 } 633 634 if !t.IsSlice() { 635 base.Fatalf("invalid type %v for OMAKESLICECOPY", n.Type()) 636 } 637 638 if n.Len == nil { 639 base.Fatalf("missing len argument for OMAKESLICECOPY") 640 } 641 642 if n.Cap == nil { 643 base.Fatalf("missing slice argument to copy for OMAKESLICECOPY") 644 } 645 646 n.Len = Expr(n.Len) 647 n.Cap = Expr(n.Cap) 648 649 n.Len = DefaultLit(n.Len, types.Types[types.TINT]) 650 651 if !n.Len.Type().IsInteger() && n.Type().Kind() != types.TIDEAL { 652 base.Errorf("non-integer len argument in OMAKESLICECOPY") 653 } 654 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") 658 } 659 if constant.Sign(n.Len.Val()) < 0 { 660 base.Fatalf("len for OMAKESLICECOPY must be non-negative") 661 } 662 } 663 return n 664 } 665 666 // tcNew typechecks an ONEW node. 667 func tcNew(n *ir.UnaryExpr) ir.Node { 668 if n.X == nil { 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") 672 } 673 l := n.X 674 l = typecheck(l, ctxType) 675 t := l.Type() 676 if t == nil { 677 n.SetType(nil) 678 return n 679 } 680 n.X = l 681 n.SetType(types.NewPtr(t)) 682 return n 683 } 684 685 // tcPanic typechecks an OPANIC node. 686 func tcPanic(n *ir.UnaryExpr) ir.Node { 687 n.X = Expr(n.X) 688 n.X = AssignConv(n.X, types.Types[types.TINTER], "argument to panic") 689 if n.X.Type() == nil { 690 n.SetType(nil) 691 return n 692 } 693 return n 694 } 695 696 // tcPrint typechecks an OPRINT or OPRINTN node. 697 func tcPrint(n *ir.CallExpr) ir.Node { 698 typecheckargs(n) 699 ls := n.Args 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]) 704 } else { 705 ls[i1] = DefaultLit(ls[i1], nil) 706 } 707 } 708 return n 709 } 710 711 // tcMinMax typechecks an OMIN or OMAX node. 712 func tcMinMax(n *ir.CallExpr) ir.Node { 713 typecheckargs(n) 714 arg0 := n.Args[0] 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) 718 } 719 } 720 n.SetType(arg0.Type()) 721 return n 722 } 723 724 // tcRealImag typechecks an OREAL or OIMAG node. 725 func tcRealImag(n *ir.UnaryExpr) ir.Node { 726 n.X = Expr(n.X) 727 l := n.X 728 t := l.Type() 729 if t == nil { 730 n.SetType(nil) 731 return n 732 } 733 734 // Determine result type. 735 switch t.Kind() { 736 case types.TIDEAL: 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]) 742 default: 743 base.Errorf("invalid argument %L for %v", l, n.Op()) 744 n.SetType(nil) 745 return n 746 } 747 return n 748 } 749 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") 754 n.SetType(nil) 755 return n 756 } 757 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)) 762 } 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) 765 766 n.SetOp(ir.ORECOVERFP) 767 n.SetType(types.Types[types.TINTER]) 768 n.Args = []ir.Node{Expr(fp)} 769 return n 770 } 771 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 { 777 n.SetType(nil) 778 return n 779 } 780 if !n.Y.Type().IsInteger() { 781 n.SetType(nil) 782 return n 783 } 784 n.SetType(n.X.Type()) 785 return n 786 } 787 788 // tcUnsafeSlice typechecks an OUNSAFESLICE node. 789 func tcUnsafeSlice(n *ir.BinaryExpr) *ir.BinaryExpr { 790 n.X = Expr(n.X) 791 n.Y = Expr(n.Y) 792 if n.X.Type() == nil || n.Y.Type() == nil { 793 n.SetType(nil) 794 return n 795 } 796 t := n.X.Type() 797 if !t.IsPtr() { 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") 805 } 806 807 if !checkunsafesliceorstring(n.Op(), &n.Y) { 808 n.SetType(nil) 809 return n 810 } 811 n.SetType(types.NewSlice(t.Elem())) 812 return n 813 } 814 815 // tcUnsafeString typechecks an OUNSAFESTRING node. 816 func tcUnsafeString(n *ir.BinaryExpr) *ir.BinaryExpr { 817 n.X = Expr(n.X) 818 n.Y = Expr(n.Y) 819 if n.X.Type() == nil || n.Y.Type() == nil { 820 n.SetType(nil) 821 return n 822 } 823 t := n.X.Type() 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) 826 } 827 828 if !checkunsafesliceorstring(n.Op(), &n.Y) { 829 n.SetType(nil) 830 return n 831 } 832 n.SetType(types.Types[types.TSTRING]) 833 return n 834 }