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