github.com/euank/go@v0.0.0-20160829210321-495514729181/src/cmd/compile/internal/gc/noder.go (about) 1 // Copyright 2016 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 gc 6 7 import ( 8 "fmt" 9 "sort" 10 "strconv" 11 "strings" 12 "unicode/utf8" 13 14 "cmd/compile/internal/syntax" 15 "cmd/internal/obj" 16 ) 17 18 func parseFile(filename string) { 19 errh := func(_, line int, msg string) { 20 yyerrorl(lexlineno+int32(line)-1, "%s", msg) 21 } 22 23 file, err := syntax.ReadFile(filename, errh, 0) 24 if err != nil { 25 Fatalf("syntax.ReadFile %s: %v", filename, err) 26 } 27 28 p := noder{pragmas: file.Pragmas} 29 30 p.lineno(file.PkgName) 31 mkpackage(file.PkgName.Value) 32 33 xtop = append(xtop, p.decls(file.DeclList, true)...) 34 p.globalPragmas() 35 lexlineno += p.maxline 36 37 if nsyntaxerrors == 0 { 38 testdclstack() 39 } 40 } 41 42 // noder transforms package syntax's AST into a Nod tree. 43 type noder struct { 44 indent []byte 45 pragmas []syntax.Pragma 46 pline int32 47 maxline int32 48 } 49 50 func (p *noder) decls(decls []syntax.Decl, top bool) (l []*Node) { 51 var lastConstGroup *syntax.Group 52 var lastConstRHS []*Node 53 var iotaVal int32 54 55 for _, decl := range decls { 56 p.lineno(decl) 57 switch decl := decl.(type) { 58 case *syntax.ImportDecl: 59 p.importDecl(decl) 60 61 case *syntax.VarDecl: 62 l = append(l, p.varDecl(decl)...) 63 case *syntax.ConstDecl: 64 // Tricky to handle golang.org/issue/15550 correctly. 65 66 prevIota := iota_ 67 68 if decl.Group == nil || decl.Group != lastConstGroup { 69 iotaVal = 0 70 lastConstRHS = nil 71 } 72 73 iota_ = iotaVal 74 lastconst = lastConstRHS 75 76 l = append(l, p.constDecl(decl)...) 77 78 lastConstRHS = lastconst 79 lastconst = nil 80 81 iota_ = prevIota 82 iotaVal++ 83 84 lastConstGroup = decl.Group 85 86 case *syntax.TypeDecl: 87 l = append(l, p.typeDecl(decl)) 88 89 case *syntax.FuncDecl: 90 l = append(l, p.funcDecl(decl)) 91 92 default: 93 panic("unhandled Decl") 94 } 95 96 if top { 97 p.pline = p.maxline 98 } 99 } 100 101 return 102 } 103 104 func (p *noder) importDecl(imp *syntax.ImportDecl) { 105 val := p.basicLit(imp.Path) 106 importfile(&val, p.indent) 107 ipkg := importpkg 108 importpkg = nil 109 110 if ipkg == nil { 111 if nerrors == 0 { 112 Fatalf("phase error in import") 113 } 114 return 115 } 116 117 ipkg.Direct = true 118 119 var my *Sym 120 if imp.LocalPkgName != nil { 121 my = p.name(imp.LocalPkgName) 122 } else { 123 my = Lookup(ipkg.Name) 124 } 125 126 pack := p.nod(imp, OPACK, nil, nil) 127 pack.Sym = my 128 pack.Name.Pkg = ipkg 129 130 if my.Name == "." { 131 importdot(ipkg, pack) 132 return 133 } 134 if my.Name == "init" { 135 yyerrorl(pack.Lineno, "cannot import package as init - init must be a func") 136 return 137 } 138 if my.Name == "_" { 139 return 140 } 141 if my.Def != nil { 142 lineno = pack.Lineno 143 redeclare(my, "as imported package name") 144 } 145 my.Def = pack 146 my.Lastlineno = pack.Lineno 147 my.Block = 1 // at top level 148 } 149 150 func (p *noder) varDecl(decl *syntax.VarDecl) []*Node { 151 names := p.declNames(decl.NameList) 152 153 var typ *Node 154 if decl.Type != nil { 155 typ = p.typeExpr(decl.Type) 156 } 157 158 var exprs []*Node 159 if decl.Values != nil { 160 exprs = p.exprList(decl.Values) 161 } 162 163 return variter(names, typ, exprs) 164 } 165 166 func (p *noder) constDecl(decl *syntax.ConstDecl) []*Node { 167 names := p.declNames(decl.NameList) 168 169 var typ *Node 170 if decl.Type != nil { 171 typ = p.typeExpr(decl.Type) 172 } 173 174 var exprs []*Node 175 if decl.Values != nil { 176 exprs = p.exprList(decl.Values) 177 } 178 179 return constiter(names, typ, exprs) 180 } 181 182 func (p *noder) typeDecl(decl *syntax.TypeDecl) *Node { 183 name := typedcl0(p.name(decl.Name)) 184 185 var typ *Node 186 if decl.Type != nil { 187 typ = p.typeExpr(decl.Type) 188 } 189 190 return typedcl1(name, typ, true) 191 } 192 193 func (p *noder) declNames(names []*syntax.Name) []*Node { 194 var nodes []*Node 195 for _, name := range names { 196 nodes = append(nodes, p.declName(name)) 197 } 198 return nodes 199 } 200 201 func (p *noder) declName(name *syntax.Name) *Node { 202 // TODO(mdempsky): Set lineno? 203 return dclname(p.name(name)) 204 } 205 206 func (p *noder) funcDecl(fun *syntax.FuncDecl) *Node { 207 f := p.funcHeader(fun) 208 if f == nil { 209 return nil 210 } 211 212 var body []*Node 213 if fun.Body != nil { 214 body = p.stmts(fun.Body) 215 if body == nil { 216 body = []*Node{p.nod(fun, OEMPTY, nil, nil)} 217 } 218 } 219 220 pragma := p.pragma() 221 222 f.Nbody.Set(body) 223 f.Noescape = pragma&Noescape != 0 224 if f.Noescape && len(body) != 0 { 225 Yyerror("can only use //go:noescape with external func implementations") 226 } 227 f.Func.Pragma = pragma 228 lineno = lexlineno + int32(fun.EndLine) - 1 229 f.Func.Endlineno = lineno 230 231 funcbody(f) 232 233 return f 234 } 235 236 func (p *noder) funcHeader(fun *syntax.FuncDecl) *Node { 237 name := p.name(fun.Name) 238 t := p.signature(fun.Recv, fun.Type) 239 f := p.nod(fun, ODCLFUNC, nil, nil) 240 241 if fun.Recv == nil { 242 // FunctionName Signature 243 if name.Name == "init" { 244 name = renameinit() 245 if t.List.Len() > 0 || t.Rlist.Len() > 0 { 246 Yyerror("func init must have no arguments and no return values") 247 } 248 } 249 250 if localpkg.Name == "main" && name.Name == "main" { 251 if t.List.Len() > 0 || t.Rlist.Len() > 0 { 252 Yyerror("func main must have no arguments and no return values") 253 } 254 } 255 256 f.Func.Nname = newfuncname(name) 257 } else { 258 // Receiver MethodName Signature 259 260 f.Func.Shortname = newfuncname(name) 261 f.Func.Nname = methodname(f.Func.Shortname, t.Left.Right) 262 } 263 264 f.Func.Nname.Name.Defn = f 265 f.Func.Nname.Name.Param.Ntype = t // TODO: check if nname already has an ntype 266 267 declare(f.Func.Nname, PFUNC) 268 funchdr(f) 269 return f 270 } 271 272 func (p *noder) signature(recv *syntax.Field, typ *syntax.FuncType) *Node { 273 n := p.nod(typ, OTFUNC, nil, nil) 274 if recv != nil { 275 n.Left = p.param(recv, false, false) 276 } 277 n.List.Set(p.params(typ.ParamList, true)) 278 n.Rlist.Set(p.params(typ.ResultList, false)) 279 return n 280 } 281 282 func (p *noder) params(params []*syntax.Field, dddOk bool) []*Node { 283 var nodes []*Node 284 for i, param := range params { 285 p.lineno(param) 286 nodes = append(nodes, p.param(param, dddOk, i+1 == len(params))) 287 } 288 return nodes 289 } 290 291 func (p *noder) param(param *syntax.Field, dddOk, final bool) *Node { 292 var name *Node 293 if param.Name != nil { 294 name = p.newname(param.Name) 295 } 296 297 typ := p.typeExpr(param.Type) 298 n := p.nod(param, ODCLFIELD, name, typ) 299 300 // rewrite ...T parameter 301 if typ.Op == ODDD { 302 if !dddOk { 303 Yyerror("cannot use ... in receiver or result parameter list") 304 } else if !final { 305 Yyerror("can only use ... with final parameter in list") 306 } 307 typ.Op = OTARRAY 308 typ.Right = typ.Left 309 typ.Left = nil 310 n.Isddd = true 311 if n.Left != nil { 312 n.Left.Isddd = true 313 } 314 } 315 316 return n 317 } 318 319 func (p *noder) exprList(expr syntax.Expr) []*Node { 320 if list, ok := expr.(*syntax.ListExpr); ok { 321 return p.exprs(list.ElemList) 322 } 323 return []*Node{p.expr(expr)} 324 } 325 326 func (p *noder) exprs(exprs []syntax.Expr) []*Node { 327 var nodes []*Node 328 for _, expr := range exprs { 329 nodes = append(nodes, p.expr(expr)) 330 } 331 return nodes 332 } 333 334 func (p *noder) expr(expr syntax.Expr) *Node { 335 p.lineno(expr) 336 switch expr := expr.(type) { 337 case nil: 338 return nil 339 case *syntax.Name: 340 return p.mkname(expr) 341 case *syntax.BasicLit: 342 return p.setlineno(expr, nodlit(p.basicLit(expr))) 343 344 case *syntax.CompositeLit: 345 n := p.nod(expr, OCOMPLIT, nil, nil) 346 if expr.Type != nil { 347 n.Right = p.expr(expr.Type) 348 } 349 // TODO(mdempsky): Should apply wrapname to n.List nodes. 350 n.List.Set(p.exprs(expr.ElemList)) 351 return n 352 case *syntax.KeyValueExpr: 353 return p.nod(expr, OKEY, p.expr(expr.Key), p.wrapname(expr.Value, p.expr(expr.Value))) 354 case *syntax.FuncLit: 355 closurehdr(p.typeExpr(expr.Type)) 356 body := p.stmts(expr.Body) 357 lineno = lexlineno + int32(expr.EndLine) - 1 358 return p.setlineno(expr, closurebody(body)) 359 case *syntax.ParenExpr: 360 return p.nod(expr, OPAREN, p.expr(expr.X), nil) 361 case *syntax.SelectorExpr: 362 // parser.new_dotname 363 obj := p.expr(expr.X) 364 sel := p.name(expr.Sel) 365 if obj.Op == OPACK { 366 s := restrictlookup(sel.Name, obj.Name.Pkg) 367 obj.Used = true 368 return oldname(s) 369 } 370 return p.setlineno(expr, NodSym(OXDOT, obj, sel)) 371 case *syntax.IndexExpr: 372 return p.nod(expr, OINDEX, p.expr(expr.X), p.expr(expr.Index)) 373 case *syntax.SliceExpr: 374 op := OSLICE 375 if expr.Full { 376 op = OSLICE3 377 } 378 n := p.nod(expr, op, p.expr(expr.X), nil) 379 var index [3]*Node 380 for i, x := range expr.Index { 381 if x != nil { 382 index[i] = p.expr(x) 383 } 384 } 385 n.SetSliceBounds(index[0], index[1], index[2]) 386 return n 387 case *syntax.AssertExpr: 388 if expr.Type == nil { 389 panic("unexpected AssertExpr") 390 } 391 // TODO(mdempsky): parser.pexpr uses p.expr(), but 392 // seems like the type field should be parsed with 393 // ntype? Shrug, doesn't matter here. 394 return p.nod(expr, ODOTTYPE, p.expr(expr.X), p.expr(expr.Type)) 395 case *syntax.Operation: 396 x := p.expr(expr.X) 397 if expr.Y == nil { 398 if expr.Op == syntax.And { 399 x = unparen(x) // TODO(mdempsky): Needed? 400 if x.Op == OCOMPLIT { 401 // Special case for &T{...}: turn into (*T){...}. 402 x.Right = p.nod(expr, OIND, x.Right, nil) 403 x.Right.Implicit = true 404 return x 405 } 406 } 407 return p.nod(expr, p.unOp(expr.Op), x, nil) 408 } 409 return p.nod(expr, p.binOp(expr.Op), x, p.expr(expr.Y)) 410 case *syntax.CallExpr: 411 n := p.nod(expr, OCALL, p.expr(expr.Fun), nil) 412 n.List.Set(p.exprs(expr.ArgList)) 413 n.Isddd = expr.HasDots 414 return n 415 416 case *syntax.ArrayType: 417 var len *Node 418 if expr.Len != nil { 419 len = p.expr(expr.Len) 420 } else { 421 len = p.nod(expr, ODDD, nil, nil) 422 } 423 return p.nod(expr, OTARRAY, len, p.typeExpr(expr.Elem)) 424 case *syntax.SliceType: 425 return p.nod(expr, OTARRAY, nil, p.typeExpr(expr.Elem)) 426 case *syntax.DotsType: 427 return p.nod(expr, ODDD, p.typeExpr(expr.Elem), nil) 428 case *syntax.StructType: 429 return p.structType(expr) 430 case *syntax.InterfaceType: 431 return p.interfaceType(expr) 432 case *syntax.FuncType: 433 return p.signature(nil, expr) 434 case *syntax.MapType: 435 return p.nod(expr, OTMAP, p.typeExpr(expr.Key), p.typeExpr(expr.Value)) 436 case *syntax.ChanType: 437 n := p.nod(expr, OTCHAN, p.typeExpr(expr.Elem), nil) 438 n.Etype = EType(p.chanDir(expr.Dir)) 439 return n 440 441 case *syntax.TypeSwitchGuard: 442 n := p.nod(expr, OTYPESW, nil, p.expr(expr.X)) 443 if expr.Lhs != nil { 444 n.Left = p.declName(expr.Lhs) 445 if isblank(n.Left) { 446 Yyerror("invalid variable name %s in type switch", n.Left) 447 } 448 } 449 return n 450 } 451 panic("unhandled Expr") 452 } 453 454 func (p *noder) typeExpr(typ syntax.Expr) *Node { 455 // TODO(mdempsky): Be stricter? typecheck should handle errors anyway. 456 return p.expr(typ) 457 } 458 459 func (p *noder) chanDir(dir syntax.ChanDir) ChanDir { 460 switch dir { 461 case 0: 462 return Cboth 463 case syntax.SendOnly: 464 return Csend 465 case syntax.RecvOnly: 466 return Crecv 467 } 468 panic("unhandled ChanDir") 469 } 470 471 func (p *noder) structType(expr *syntax.StructType) *Node { 472 var l []*Node 473 for i, field := range expr.FieldList { 474 p.lineno(field) 475 var n *Node 476 if field.Name == nil { 477 n = p.embedded(field.Type) 478 } else { 479 n = p.nod(field, ODCLFIELD, p.newname(field.Name), p.typeExpr(field.Type)) 480 } 481 if i < len(expr.TagList) && expr.TagList[i] != nil { 482 n.SetVal(p.basicLit(expr.TagList[i])) 483 } 484 l = append(l, n) 485 } 486 487 n := p.nod(expr, OTSTRUCT, nil, nil) 488 n.List.Set(l) 489 return n 490 } 491 492 func (p *noder) interfaceType(expr *syntax.InterfaceType) *Node { 493 var l []*Node 494 for _, method := range expr.MethodList { 495 p.lineno(method) 496 var n *Node 497 if method.Name == nil { 498 n = p.nod(method, ODCLFIELD, nil, oldname(p.packname(method.Type))) 499 } else { 500 mname := p.newname(method.Name) 501 sig := p.typeExpr(method.Type) 502 sig.Left = fakethis() 503 n = p.nod(method, ODCLFIELD, mname, sig) 504 ifacedcl(n) 505 } 506 l = append(l, n) 507 } 508 509 n := p.nod(expr, OTINTER, nil, nil) 510 n.List.Set(l) 511 return n 512 } 513 514 func (p *noder) packname(expr syntax.Expr) *Sym { 515 switch expr := expr.(type) { 516 case *syntax.Name: 517 name := p.name(expr) 518 if n := oldname(name); n.Name != nil && n.Name.Pack != nil { 519 n.Name.Pack.Used = true 520 } 521 return name 522 case *syntax.SelectorExpr: 523 name := p.name(expr.X.(*syntax.Name)) 524 s := p.name(expr.Sel) 525 var pkg *Pkg 526 if name.Def == nil || name.Def.Op != OPACK { 527 Yyerror("%v is not a package", name) 528 pkg = localpkg 529 } else { 530 name.Def.Used = true 531 pkg = name.Def.Name.Pkg 532 } 533 return restrictlookup(s.Name, pkg) 534 } 535 panic(fmt.Sprintf("unexpected packname: %#v", expr)) 536 } 537 538 func (p *noder) embedded(typ syntax.Expr) *Node { 539 op, isStar := typ.(*syntax.Operation) 540 if isStar { 541 if op.Op != syntax.Mul || op.Y != nil { 542 panic("unexpected Operation") 543 } 544 typ = op.X 545 } 546 n := embedded(p.packname(typ), localpkg) 547 if isStar { 548 n.Right = p.nod(op, OIND, n.Right, nil) 549 } 550 return n 551 } 552 553 func (p *noder) stmts(stmts []syntax.Stmt) []*Node { 554 var nodes []*Node 555 for _, stmt := range stmts { 556 s := p.stmt(stmt) 557 if s == nil { 558 } else if s.Op == OBLOCK && s.Ninit.Len() == 0 { 559 nodes = append(nodes, s.List.Slice()...) 560 } else { 561 nodes = append(nodes, s) 562 } 563 } 564 return nodes 565 } 566 567 func (p *noder) stmt(stmt syntax.Stmt) *Node { 568 p.lineno(stmt) 569 switch stmt := stmt.(type) { 570 case *syntax.EmptyStmt: 571 return nil 572 case *syntax.LabeledStmt: 573 return p.labeledStmt(stmt) 574 case *syntax.BlockStmt: 575 return p.body(stmt.Body) 576 case *syntax.ExprStmt: 577 return p.wrapname(stmt, p.expr(stmt.X)) 578 case *syntax.SendStmt: 579 return p.nod(stmt, OSEND, p.expr(stmt.Chan), p.expr(stmt.Value)) 580 case *syntax.DeclStmt: 581 return liststmt(p.decls(stmt.DeclList, false)) 582 case *syntax.AssignStmt: 583 if stmt.Op != 0 && stmt.Op != syntax.Def { 584 n := p.nod(stmt, OASOP, p.expr(stmt.Lhs), p.expr(stmt.Rhs)) 585 n.Implicit = stmt.Rhs == syntax.ImplicitOne 586 n.Etype = EType(p.binOp(stmt.Op)) 587 return n 588 } 589 590 lhs := p.exprList(stmt.Lhs) 591 rhs := p.exprList(stmt.Rhs) 592 593 n := p.nod(stmt, OAS, nil, nil) // assume common case 594 595 if stmt.Op == syntax.Def { 596 n.Colas = true 597 colasdefn(lhs, n) // modifies lhs, call before using lhs[0] in common case 598 } 599 600 if len(lhs) == 1 && len(rhs) == 1 { 601 // common case 602 n.Left = lhs[0] 603 n.Right = rhs[0] 604 } else { 605 n.Op = OAS2 606 n.List.Set(lhs) 607 n.Rlist.Set(rhs) 608 } 609 return n 610 611 case *syntax.BranchStmt: 612 var op Op 613 switch stmt.Tok { 614 case syntax.Break: 615 op = OBREAK 616 case syntax.Continue: 617 op = OCONTINUE 618 case syntax.Fallthrough: 619 op = OXFALL 620 case syntax.Goto: 621 op = OGOTO 622 default: 623 panic("unhandled BranchStmt") 624 } 625 n := p.nod(stmt, op, nil, nil) 626 if stmt.Label != nil { 627 n.Left = p.newname(stmt.Label) 628 } 629 if op == OGOTO { 630 n.Sym = dclstack // context, for goto restriction 631 } 632 if op == OXFALL { 633 n.Xoffset = int64(block) 634 } 635 return n 636 case *syntax.CallStmt: 637 var op Op 638 switch stmt.Tok { 639 case syntax.Defer: 640 op = ODEFER 641 case syntax.Go: 642 op = OPROC 643 default: 644 panic("unhandled CallStmt") 645 } 646 return p.nod(stmt, op, p.expr(stmt.Call), nil) 647 case *syntax.ReturnStmt: 648 var results []*Node 649 if stmt.Results != nil { 650 results = p.exprList(stmt.Results) 651 } 652 n := p.nod(stmt, ORETURN, nil, nil) 653 n.List.Set(results) 654 if n.List.Len() == 0 && Curfn != nil { 655 for _, ln := range Curfn.Func.Dcl { 656 if ln.Class == PPARAM { 657 continue 658 } 659 if ln.Class != PPARAMOUT { 660 break 661 } 662 if ln.Sym.Def != ln { 663 Yyerror("%s is shadowed during return", ln.Sym.Name) 664 } 665 } 666 } 667 return n 668 case *syntax.IfStmt: 669 return p.ifStmt(stmt) 670 case *syntax.ForStmt: 671 return p.forStmt(stmt) 672 case *syntax.SwitchStmt: 673 return p.switchStmt(stmt) 674 case *syntax.SelectStmt: 675 return p.selectStmt(stmt) 676 } 677 panic("unhandled Stmt") 678 } 679 680 func (p *noder) body(body []syntax.Stmt) *Node { 681 l := p.bodyList(body) 682 if len(l) == 0 { 683 // TODO(mdempsky): Line number? 684 return Nod(OEMPTY, nil, nil) 685 } 686 return liststmt(l) 687 } 688 689 func (p *noder) bodyList(body []syntax.Stmt) []*Node { 690 markdcl() 691 nodes := p.stmts(body) 692 popdcl() 693 return nodes 694 } 695 696 func (p *noder) ifStmt(stmt *syntax.IfStmt) *Node { 697 markdcl() 698 n := p.nod(stmt, OIF, nil, nil) 699 if stmt.Init != nil { 700 n.Ninit.Set1(p.stmt(stmt.Init)) 701 } 702 if stmt.Cond != nil { 703 n.Left = p.expr(stmt.Cond) 704 } 705 n.Nbody.Set(p.bodyList(stmt.Then)) 706 if stmt.Else != nil { 707 e := p.stmt(stmt.Else) 708 if e.Op == OBLOCK && e.Ninit.Len() == 0 { 709 n.Rlist.Set(e.List.Slice()) 710 } else { 711 n.Rlist.Set1(e) 712 } 713 } 714 popdcl() 715 return n 716 } 717 718 func (p *noder) forStmt(stmt *syntax.ForStmt) *Node { 719 markdcl() 720 var n *Node 721 if r, ok := stmt.Init.(*syntax.RangeClause); ok { 722 if stmt.Cond != nil || stmt.Post != nil { 723 panic("unexpected RangeClause") 724 } 725 726 n = p.nod(r, ORANGE, nil, p.expr(r.X)) 727 if r.Lhs != nil { 728 lhs := p.exprList(r.Lhs) 729 n.List.Set(lhs) 730 if r.Def { 731 n.Colas = true 732 colasdefn(lhs, n) 733 } 734 } 735 } else { 736 n = p.nod(stmt, OFOR, nil, nil) 737 if stmt.Init != nil { 738 n.Ninit.Set1(p.stmt(stmt.Init)) 739 } 740 if stmt.Cond != nil { 741 n.Left = p.expr(stmt.Cond) 742 } 743 if stmt.Post != nil { 744 n.Right = p.stmt(stmt.Post) 745 } 746 } 747 n.Nbody.Set(p.bodyList(stmt.Body)) 748 popdcl() 749 return n 750 } 751 752 func (p *noder) switchStmt(stmt *syntax.SwitchStmt) *Node { 753 markdcl() 754 n := p.nod(stmt, OSWITCH, nil, nil) 755 if stmt.Init != nil { 756 n.Ninit.Set1(p.stmt(stmt.Init)) 757 } 758 if stmt.Tag != nil { 759 n.Left = p.expr(stmt.Tag) 760 } 761 762 tswitch := n.Left 763 if tswitch != nil && (tswitch.Op != OTYPESW || tswitch.Left == nil) { 764 tswitch = nil 765 } 766 767 n.List.Set(p.caseClauses(stmt.Body, tswitch)) 768 769 popdcl() 770 return n 771 } 772 773 func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *Node) []*Node { 774 var nodes []*Node 775 for _, clause := range clauses { 776 p.lineno(clause) 777 markdcl() 778 n := p.nod(clause, OXCASE, nil, nil) 779 if clause.Cases != nil { 780 n.List.Set(p.exprList(clause.Cases)) 781 } 782 if tswitch != nil { 783 nn := newname(tswitch.Left.Sym) 784 declare(nn, dclcontext) 785 n.Rlist.Set1(nn) 786 // keep track of the instances for reporting unused 787 nn.Name.Defn = tswitch 788 } 789 n.Xoffset = int64(block) 790 n.Nbody.Set(p.stmts(clause.Body)) 791 popdcl() 792 nodes = append(nodes, n) 793 } 794 return nodes 795 } 796 797 func (p *noder) selectStmt(stmt *syntax.SelectStmt) *Node { 798 n := p.nod(stmt, OSELECT, nil, nil) 799 n.List.Set(p.commClauses(stmt.Body)) 800 return n 801 } 802 803 func (p *noder) commClauses(clauses []*syntax.CommClause) []*Node { 804 var nodes []*Node 805 for _, clause := range clauses { 806 p.lineno(clause) 807 markdcl() 808 n := p.nod(clause, OXCASE, nil, nil) 809 if clause.Comm != nil { 810 n.List.Set1(p.stmt(clause.Comm)) 811 } 812 n.Xoffset = int64(block) 813 n.Nbody.Set(p.stmts(clause.Body)) 814 popdcl() 815 nodes = append(nodes, n) 816 } 817 return nodes 818 } 819 820 func (p *noder) labeledStmt(label *syntax.LabeledStmt) *Node { 821 lhs := p.nod(label, OLABEL, p.newname(label.Label), nil) 822 lhs.Sym = dclstack 823 824 var ls *Node 825 if label.Stmt != nil { // TODO(mdempsky): Should always be present. 826 ls = p.stmt(label.Stmt) 827 } 828 829 lhs.Name.Defn = ls 830 l := []*Node{lhs} 831 if ls != nil { 832 if ls.Op == OBLOCK && ls.Ninit.Len() == 0 { 833 l = append(l, ls.List.Slice()...) 834 } else { 835 l = append(l, ls) 836 } 837 } 838 return liststmt(l) 839 } 840 841 var unOps = [...]Op{ 842 syntax.Recv: ORECV, 843 syntax.Mul: OIND, 844 syntax.And: OADDR, 845 846 syntax.Not: ONOT, 847 syntax.Xor: OCOM, 848 syntax.Add: OPLUS, 849 syntax.Sub: OMINUS, 850 } 851 852 func (p *noder) unOp(op syntax.Operator) Op { 853 if uint64(op) >= uint64(len(unOps)) || unOps[op] == 0 { 854 panic("invalid Operator") 855 } 856 return unOps[op] 857 } 858 859 var binOps = [...]Op{ 860 syntax.OrOr: OOROR, 861 syntax.AndAnd: OANDAND, 862 863 syntax.Eql: OEQ, 864 syntax.Neq: ONE, 865 syntax.Lss: OLT, 866 syntax.Leq: OLE, 867 syntax.Gtr: OGT, 868 syntax.Geq: OGE, 869 870 syntax.Add: OADD, 871 syntax.Sub: OSUB, 872 syntax.Or: OOR, 873 syntax.Xor: OXOR, 874 875 syntax.Mul: OMUL, 876 syntax.Div: ODIV, 877 syntax.Rem: OMOD, 878 syntax.And: OAND, 879 syntax.AndNot: OANDNOT, 880 syntax.Shl: OLSH, 881 syntax.Shr: ORSH, 882 } 883 884 func (p *noder) binOp(op syntax.Operator) Op { 885 if uint64(op) >= uint64(len(binOps)) || binOps[op] == 0 { 886 panic("invalid Operator") 887 } 888 return binOps[op] 889 } 890 891 func (p *noder) basicLit(lit *syntax.BasicLit) Val { 892 // TODO: Don't try to convert if we had syntax errors (conversions may fail). 893 // Use dummy values so we can continue to compile. Eventually, use a 894 // form of "unknown" literals that are ignored during type-checking so 895 // we can continue type-checking w/o spurious follow-up errors. 896 switch s := lit.Value; lit.Kind { 897 case syntax.IntLit: 898 x := new(Mpint) 899 x.SetString(s) 900 return Val{U: x} 901 902 case syntax.FloatLit: 903 x := newMpflt() 904 x.SetString(s) 905 return Val{U: x} 906 907 case syntax.ImagLit: 908 x := new(Mpcplx) 909 x.Imag.SetString(strings.TrimSuffix(s, "i")) 910 return Val{U: x} 911 912 case syntax.RuneLit: 913 var r rune 914 if u, err := strconv.Unquote(s); err == nil && len(u) > 0 { 915 // Package syntax already reported any errors. 916 // Check for them again though because 0 is a 917 // better fallback value for invalid rune 918 // literals than 0xFFFD. 919 if len(u) == 1 { 920 r = rune(u[0]) 921 } else { 922 r, _ = utf8.DecodeRuneInString(u) 923 } 924 } 925 x := new(Mpint) 926 x.SetInt64(int64(r)) 927 x.Rune = true 928 return Val{U: x} 929 930 case syntax.StringLit: 931 if len(s) > 0 && s[0] == '`' { 932 // strip carriage returns from raw string 933 s = strings.Replace(s, "\r", "", -1) 934 } 935 // Ignore errors because package syntax already reported them. 936 u, _ := strconv.Unquote(s) 937 return Val{U: u} 938 939 default: 940 panic("unhandled BasicLit kind") 941 } 942 } 943 944 func (p *noder) name(name *syntax.Name) *Sym { 945 return Lookup(name.Value) 946 } 947 948 func (p *noder) mkname(name *syntax.Name) *Node { 949 // TODO(mdempsky): Set line number? 950 return mkname(p.name(name)) 951 } 952 953 func (p *noder) newname(name *syntax.Name) *Node { 954 // TODO(mdempsky): Set line number? 955 return newname(p.name(name)) 956 } 957 958 func (p *noder) wrapname(n syntax.Node, x *Node) *Node { 959 // These nodes do not carry line numbers. 960 // Introduce a wrapper node to give them the correct line. 961 switch x.Op { 962 case ONAME, ONONAME, OTYPE, OPACK, OLITERAL: 963 x = p.nod(n, OPAREN, x, nil) 964 x.Implicit = true 965 } 966 return x 967 } 968 969 func (p *noder) nod(orig syntax.Node, op Op, left, right *Node) *Node { 970 return p.setlineno(orig, Nod(op, left, right)) 971 } 972 973 func (p *noder) setlineno(src syntax.Node, dst *Node) *Node { 974 l := int32(src.Line()) 975 if l == 0 { 976 // TODO(mdempsky): Shouldn't happen. Fix package syntax. 977 return dst 978 } 979 if l > p.maxline { 980 p.maxline = l 981 } 982 dst.Lineno = lexlineno + l - 1 983 return dst 984 } 985 986 func (p *noder) lineno(n syntax.Node) { 987 if n == nil { 988 return 989 } 990 l := int32(n.Line()) 991 if l == 0 { 992 // TODO(mdempsky): Shouldn't happen. Fix package syntax. 993 return 994 } 995 if l > p.maxline { 996 p.maxline = l 997 } 998 lineno = lexlineno + l - 1 999 } 1000 1001 func (p *noder) pragma() Pragma { 1002 lo := sort.Search(len(p.pragmas), func(i int) bool { return int32(p.pragmas[i].Line) >= p.pline }) 1003 hi := sort.Search(len(p.pragmas), func(i int) bool { return int32(p.pragmas[i].Line) > p.maxline }) 1004 1005 var res Pragma 1006 for _, prag := range p.pragmas[lo:hi] { 1007 text := prag.Text 1008 if !strings.HasPrefix(text, "go:") { 1009 continue 1010 } 1011 1012 verb := text 1013 if i := strings.Index(text, " "); i >= 0 { 1014 verb = verb[:i] 1015 } 1016 1017 switch verb { 1018 case "go:nointerface": 1019 if obj.Fieldtrack_enabled != 0 { 1020 res |= Nointerface 1021 } 1022 case "go:noescape": 1023 res |= Noescape 1024 case "go:norace": 1025 res |= Norace 1026 case "go:nosplit": 1027 res |= Nosplit 1028 case "go:noinline": 1029 res |= Noinline 1030 case "go:systemstack": 1031 if !compiling_runtime { 1032 Yyerror("//go:systemstack only allowed in runtime") 1033 } 1034 res |= Systemstack 1035 case "go:nowritebarrier": 1036 if !compiling_runtime { 1037 Yyerror("//go:nowritebarrier only allowed in runtime") 1038 } 1039 res |= Nowritebarrier 1040 case "go:nowritebarrierrec": 1041 if !compiling_runtime { 1042 Yyerror("//go:nowritebarrierrec only allowed in runtime") 1043 } 1044 res |= Nowritebarrierrec | Nowritebarrier // implies Nowritebarrier 1045 case "go:cgo_unsafe_args": 1046 res |= CgoUnsafeArgs 1047 case "go:uintptrescapes": 1048 // For the next function declared in the file 1049 // any uintptr arguments may be pointer values 1050 // converted to uintptr. This directive 1051 // ensures that the referenced allocated 1052 // object, if any, is retained and not moved 1053 // until the call completes, even though from 1054 // the types alone it would appear that the 1055 // object is no longer needed during the 1056 // call. The conversion to uintptr must appear 1057 // in the argument list. 1058 // Used in syscall/dll_windows.go. 1059 res |= UintptrEscapes 1060 } 1061 } 1062 return res 1063 } 1064 1065 func (p *noder) globalPragmas() { 1066 origlexlineno := lexlineno 1067 defer func() { 1068 lexlineno = origlexlineno 1069 }() 1070 1071 for _, prag := range p.pragmas { 1072 text := prag.Text 1073 1074 if strings.HasPrefix(text, "go:cgo_") { 1075 pragcgobuf += pragcgo(text) 1076 } 1077 1078 if strings.HasPrefix(text, "go:linkname ") { 1079 if !imported_unsafe { 1080 Yyerror("//go:linkname only allowed in Go files that import \"unsafe\"") 1081 } 1082 f := strings.Fields(text) 1083 if len(f) != 3 { 1084 Yyerror("usage: //go:linkname localname linkname") 1085 break 1086 } 1087 Lookup(f[1]).Linkname = f[2] 1088 } 1089 1090 // TODO(mdempsky): Move into package syntax. 1091 if strings.HasPrefix(text, "line ") { 1092 i := strings.IndexByte(text, ':') 1093 if i < 0 { 1094 continue 1095 } 1096 n, err := strconv.Atoi(text[i+1:]) 1097 if err != nil { 1098 // todo: make this an error instead? it is almost certainly a bug. 1099 continue 1100 } 1101 if n > 1e8 { 1102 Yyerror("line number out of range") 1103 errorexit() 1104 } 1105 if n <= 0 { 1106 continue 1107 } 1108 lexlineno = origlexlineno + int32(prag.Line) 1109 linehistupdate(text[5:i], n) 1110 } 1111 } 1112 }