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