github.com/eun/go@v0.0.0-20170811110501-92cfd07a6cfd/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 n := embedded(p.packname(typ), localpkg) 693 if isStar { 694 n.Right = p.nod(op, OIND, n.Right, nil) 695 } 696 return n 697 } 698 699 func (p *noder) stmts(stmts []syntax.Stmt) []*Node { 700 var nodes []*Node 701 for _, stmt := range stmts { 702 s := p.stmt(stmt) 703 if s == nil { 704 } else if s.Op == OBLOCK && s.Ninit.Len() == 0 { 705 nodes = append(nodes, s.List.Slice()...) 706 } else { 707 nodes = append(nodes, s) 708 } 709 } 710 return nodes 711 } 712 713 func (p *noder) stmt(stmt syntax.Stmt) *Node { 714 p.lineno(stmt) 715 switch stmt := stmt.(type) { 716 case *syntax.EmptyStmt: 717 return nil 718 case *syntax.LabeledStmt: 719 return p.labeledStmt(stmt) 720 case *syntax.BlockStmt: 721 l := p.blockStmt(stmt) 722 if len(l) == 0 { 723 // TODO(mdempsky): Line number? 724 return nod(OEMPTY, nil, nil) 725 } 726 return liststmt(l) 727 case *syntax.ExprStmt: 728 return p.wrapname(stmt, p.expr(stmt.X)) 729 case *syntax.SendStmt: 730 return p.nod(stmt, OSEND, p.expr(stmt.Chan), p.expr(stmt.Value)) 731 case *syntax.DeclStmt: 732 return liststmt(p.decls(stmt.DeclList)) 733 case *syntax.AssignStmt: 734 if stmt.Op != 0 && stmt.Op != syntax.Def { 735 n := p.nod(stmt, OASOP, p.expr(stmt.Lhs), p.expr(stmt.Rhs)) 736 n.SetImplicit(stmt.Rhs == syntax.ImplicitOne) 737 n.Etype = types.EType(p.binOp(stmt.Op)) 738 return n 739 } 740 741 lhs := p.exprList(stmt.Lhs) 742 rhs := p.exprList(stmt.Rhs) 743 744 n := p.nod(stmt, OAS, nil, nil) // assume common case 745 746 if stmt.Op == syntax.Def { 747 n.SetColas(true) 748 colasdefn(lhs, n) // modifies lhs, call before using lhs[0] in common case 749 } 750 751 if len(lhs) == 1 && len(rhs) == 1 { 752 // common case 753 n.Left = lhs[0] 754 n.Right = rhs[0] 755 } else { 756 n.Op = OAS2 757 n.List.Set(lhs) 758 n.Rlist.Set(rhs) 759 } 760 return n 761 762 case *syntax.BranchStmt: 763 var op Op 764 switch stmt.Tok { 765 case syntax.Break: 766 op = OBREAK 767 case syntax.Continue: 768 op = OCONTINUE 769 case syntax.Fallthrough: 770 op = OXFALL 771 case syntax.Goto: 772 op = OGOTO 773 default: 774 panic("unhandled BranchStmt") 775 } 776 n := p.nod(stmt, op, nil, nil) 777 if stmt.Label != nil { 778 n.Left = p.newname(stmt.Label) 779 } 780 if op == OXFALL { 781 n.Xoffset = int64(types.Block) 782 } 783 return n 784 case *syntax.CallStmt: 785 var op Op 786 switch stmt.Tok { 787 case syntax.Defer: 788 op = ODEFER 789 case syntax.Go: 790 op = OPROC 791 default: 792 panic("unhandled CallStmt") 793 } 794 return p.nod(stmt, op, p.expr(stmt.Call), nil) 795 case *syntax.ReturnStmt: 796 var results []*Node 797 if stmt.Results != nil { 798 results = p.exprList(stmt.Results) 799 } 800 n := p.nod(stmt, ORETURN, nil, nil) 801 n.List.Set(results) 802 if n.List.Len() == 0 && Curfn != nil { 803 for _, ln := range Curfn.Func.Dcl { 804 if ln.Class() == PPARAM { 805 continue 806 } 807 if ln.Class() != PPARAMOUT { 808 break 809 } 810 if asNode(ln.Sym.Def) != ln { 811 yyerror("%s is shadowed during return", ln.Sym.Name) 812 } 813 } 814 } 815 return n 816 case *syntax.IfStmt: 817 return p.ifStmt(stmt) 818 case *syntax.ForStmt: 819 return p.forStmt(stmt) 820 case *syntax.SwitchStmt: 821 return p.switchStmt(stmt) 822 case *syntax.SelectStmt: 823 return p.selectStmt(stmt) 824 } 825 panic("unhandled Stmt") 826 } 827 828 func (p *noder) blockStmt(stmt *syntax.BlockStmt) []*Node { 829 p.openScope(stmt.Pos()) 830 nodes := p.stmts(stmt.List) 831 p.closeScope(stmt.Rbrace) 832 return nodes 833 } 834 835 func (p *noder) ifStmt(stmt *syntax.IfStmt) *Node { 836 p.openScope(stmt.Pos()) 837 n := p.nod(stmt, OIF, nil, nil) 838 if stmt.Init != nil { 839 n.Ninit.Set1(p.stmt(stmt.Init)) 840 } 841 if stmt.Cond != nil { 842 n.Left = p.expr(stmt.Cond) 843 } 844 n.Nbody.Set(p.blockStmt(stmt.Then)) 845 if stmt.Else != nil { 846 e := p.stmt(stmt.Else) 847 if e.Op == OBLOCK && e.Ninit.Len() == 0 { 848 n.Rlist.Set(e.List.Slice()) 849 } else { 850 n.Rlist.Set1(e) 851 } 852 } 853 p.closeAnotherScope() 854 return n 855 } 856 857 func (p *noder) forStmt(stmt *syntax.ForStmt) *Node { 858 p.openScope(stmt.Pos()) 859 var n *Node 860 if r, ok := stmt.Init.(*syntax.RangeClause); ok { 861 if stmt.Cond != nil || stmt.Post != nil { 862 panic("unexpected RangeClause") 863 } 864 865 n = p.nod(r, ORANGE, nil, p.expr(r.X)) 866 if r.Lhs != nil { 867 lhs := p.exprList(r.Lhs) 868 n.List.Set(lhs) 869 if r.Def { 870 n.SetColas(true) 871 colasdefn(lhs, n) 872 } 873 } 874 } else { 875 n = p.nod(stmt, OFOR, nil, nil) 876 if stmt.Init != nil { 877 n.Ninit.Set1(p.stmt(stmt.Init)) 878 } 879 if stmt.Cond != nil { 880 n.Left = p.expr(stmt.Cond) 881 } 882 if stmt.Post != nil { 883 n.Right = p.stmt(stmt.Post) 884 } 885 } 886 n.Nbody.Set(p.blockStmt(stmt.Body)) 887 p.closeAnotherScope() 888 return n 889 } 890 891 func (p *noder) switchStmt(stmt *syntax.SwitchStmt) *Node { 892 p.openScope(stmt.Pos()) 893 n := p.nod(stmt, OSWITCH, nil, nil) 894 if stmt.Init != nil { 895 n.Ninit.Set1(p.stmt(stmt.Init)) 896 } 897 if stmt.Tag != nil { 898 n.Left = p.expr(stmt.Tag) 899 } 900 901 tswitch := n.Left 902 if tswitch != nil && (tswitch.Op != OTYPESW || tswitch.Left == nil) { 903 tswitch = nil 904 } 905 n.List.Set(p.caseClauses(stmt.Body, tswitch, stmt.Rbrace)) 906 907 p.closeScope(stmt.Rbrace) 908 return n 909 } 910 911 func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *Node, rbrace src.Pos) []*Node { 912 var nodes []*Node 913 for i, clause := range clauses { 914 p.lineno(clause) 915 if i > 0 { 916 p.closeScope(clause.Pos()) 917 } 918 p.openScope(clause.Pos()) 919 920 n := p.nod(clause, OXCASE, nil, nil) 921 if clause.Cases != nil { 922 n.List.Set(p.exprList(clause.Cases)) 923 } 924 if tswitch != nil { 925 nn := newname(tswitch.Left.Sym) 926 declare(nn, dclcontext) 927 n.Rlist.Set1(nn) 928 // keep track of the instances for reporting unused 929 nn.Name.Defn = tswitch 930 } 931 n.Xoffset = int64(types.Block) 932 n.Nbody.Set(p.stmts(clause.Body)) 933 nodes = append(nodes, n) 934 } 935 if len(clauses) > 0 { 936 p.closeScope(rbrace) 937 } 938 return nodes 939 } 940 941 func (p *noder) selectStmt(stmt *syntax.SelectStmt) *Node { 942 n := p.nod(stmt, OSELECT, nil, nil) 943 n.List.Set(p.commClauses(stmt.Body, stmt.Rbrace)) 944 return n 945 } 946 947 func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace src.Pos) []*Node { 948 var nodes []*Node 949 for i, clause := range clauses { 950 p.lineno(clause) 951 if i > 0 { 952 p.closeScope(clause.Pos()) 953 } 954 p.openScope(clause.Pos()) 955 956 n := p.nod(clause, OXCASE, nil, nil) 957 if clause.Comm != nil { 958 n.List.Set1(p.stmt(clause.Comm)) 959 } 960 n.Xoffset = int64(types.Block) 961 n.Nbody.Set(p.stmts(clause.Body)) 962 nodes = append(nodes, n) 963 } 964 if len(clauses) > 0 { 965 p.closeScope(rbrace) 966 } 967 return nodes 968 } 969 970 func (p *noder) labeledStmt(label *syntax.LabeledStmt) *Node { 971 lhs := p.nod(label, OLABEL, p.newname(label.Label), nil) 972 973 var ls *Node 974 if label.Stmt != nil { // TODO(mdempsky): Should always be present. 975 ls = p.stmt(label.Stmt) 976 } 977 978 lhs.Name.Defn = ls 979 l := []*Node{lhs} 980 if ls != nil { 981 if ls.Op == OBLOCK && ls.Ninit.Len() == 0 { 982 l = append(l, ls.List.Slice()...) 983 } else { 984 l = append(l, ls) 985 } 986 } 987 return liststmt(l) 988 } 989 990 var unOps = [...]Op{ 991 syntax.Recv: ORECV, 992 syntax.Mul: OIND, 993 syntax.And: OADDR, 994 995 syntax.Not: ONOT, 996 syntax.Xor: OCOM, 997 syntax.Add: OPLUS, 998 syntax.Sub: OMINUS, 999 } 1000 1001 func (p *noder) unOp(op syntax.Operator) Op { 1002 if uint64(op) >= uint64(len(unOps)) || unOps[op] == 0 { 1003 panic("invalid Operator") 1004 } 1005 return unOps[op] 1006 } 1007 1008 var binOps = [...]Op{ 1009 syntax.OrOr: OOROR, 1010 syntax.AndAnd: OANDAND, 1011 1012 syntax.Eql: OEQ, 1013 syntax.Neq: ONE, 1014 syntax.Lss: OLT, 1015 syntax.Leq: OLE, 1016 syntax.Gtr: OGT, 1017 syntax.Geq: OGE, 1018 1019 syntax.Add: OADD, 1020 syntax.Sub: OSUB, 1021 syntax.Or: OOR, 1022 syntax.Xor: OXOR, 1023 1024 syntax.Mul: OMUL, 1025 syntax.Div: ODIV, 1026 syntax.Rem: OMOD, 1027 syntax.And: OAND, 1028 syntax.AndNot: OANDNOT, 1029 syntax.Shl: OLSH, 1030 syntax.Shr: ORSH, 1031 } 1032 1033 func (p *noder) binOp(op syntax.Operator) Op { 1034 if uint64(op) >= uint64(len(binOps)) || binOps[op] == 0 { 1035 panic("invalid Operator") 1036 } 1037 return binOps[op] 1038 } 1039 1040 func (p *noder) basicLit(lit *syntax.BasicLit) Val { 1041 // TODO: Don't try to convert if we had syntax errors (conversions may fail). 1042 // Use dummy values so we can continue to compile. Eventually, use a 1043 // form of "unknown" literals that are ignored during type-checking so 1044 // we can continue type-checking w/o spurious follow-up errors. 1045 switch s := lit.Value; lit.Kind { 1046 case syntax.IntLit: 1047 x := new(Mpint) 1048 x.SetString(s) 1049 return Val{U: x} 1050 1051 case syntax.FloatLit: 1052 x := newMpflt() 1053 x.SetString(s) 1054 return Val{U: x} 1055 1056 case syntax.ImagLit: 1057 x := new(Mpcplx) 1058 x.Imag.SetString(strings.TrimSuffix(s, "i")) 1059 return Val{U: x} 1060 1061 case syntax.RuneLit: 1062 var r rune 1063 if u, err := strconv.Unquote(s); err == nil && len(u) > 0 { 1064 // Package syntax already reported any errors. 1065 // Check for them again though because 0 is a 1066 // better fallback value for invalid rune 1067 // literals than 0xFFFD. 1068 if len(u) == 1 { 1069 r = rune(u[0]) 1070 } else { 1071 r, _ = utf8.DecodeRuneInString(u) 1072 } 1073 } 1074 x := new(Mpint) 1075 x.SetInt64(int64(r)) 1076 x.Rune = true 1077 return Val{U: x} 1078 1079 case syntax.StringLit: 1080 if len(s) > 0 && s[0] == '`' { 1081 // strip carriage returns from raw string 1082 s = strings.Replace(s, "\r", "", -1) 1083 } 1084 // Ignore errors because package syntax already reported them. 1085 u, _ := strconv.Unquote(s) 1086 return Val{U: u} 1087 1088 default: 1089 panic("unhandled BasicLit kind") 1090 } 1091 } 1092 1093 func (p *noder) name(name *syntax.Name) *types.Sym { 1094 return lookup(name.Value) 1095 } 1096 1097 func (p *noder) mkname(name *syntax.Name) *Node { 1098 // TODO(mdempsky): Set line number? 1099 return mkname(p.name(name)) 1100 } 1101 1102 func (p *noder) newname(name *syntax.Name) *Node { 1103 // TODO(mdempsky): Set line number? 1104 return newname(p.name(name)) 1105 } 1106 1107 func (p *noder) wrapname(n syntax.Node, x *Node) *Node { 1108 // These nodes do not carry line numbers. 1109 // Introduce a wrapper node to give them the correct line. 1110 switch x.Op { 1111 case OTYPE, OLITERAL: 1112 if x.Sym == nil { 1113 break 1114 } 1115 fallthrough 1116 case ONAME, ONONAME, OPACK: 1117 x = p.nod(n, OPAREN, x, nil) 1118 x.SetImplicit(true) 1119 } 1120 return x 1121 } 1122 1123 func (p *noder) nod(orig syntax.Node, op Op, left, right *Node) *Node { 1124 return p.setlineno(orig, nod(op, left, right)) 1125 } 1126 1127 func (p *noder) setlineno(src_ syntax.Node, dst *Node) *Node { 1128 pos := src_.Pos() 1129 if !pos.IsKnown() { 1130 // TODO(mdempsky): Shouldn't happen. Fix package syntax. 1131 return dst 1132 } 1133 dst.Pos = Ctxt.PosTable.XPos(pos) 1134 return dst 1135 } 1136 1137 func (p *noder) lineno(n syntax.Node) { 1138 if n == nil { 1139 return 1140 } 1141 pos := n.Pos() 1142 if !pos.IsKnown() { 1143 // TODO(mdempsky): Shouldn't happen. Fix package syntax. 1144 return 1145 } 1146 lineno = Ctxt.PosTable.XPos(pos) 1147 } 1148 1149 // error is called concurrently if files are parsed concurrently. 1150 func (p *noder) error(err error) { 1151 p.err <- err.(syntax.Error) 1152 } 1153 1154 // pragmas that are allowed in the std lib, but don't have 1155 // a syntax.Pragma value (see lex.go) associated with them. 1156 var allowedStdPragmas = map[string]bool{ 1157 "go:cgo_export_static": true, 1158 "go:cgo_export_dynamic": true, 1159 "go:cgo_import_static": true, 1160 "go:cgo_import_dynamic": true, 1161 "go:cgo_ldflag": true, 1162 "go:cgo_dynamic_linker": true, 1163 "go:generate": true, 1164 } 1165 1166 // pragma is called concurrently if files are parsed concurrently. 1167 func (p *noder) pragma(pos src.Pos, text string) syntax.Pragma { 1168 switch { 1169 case strings.HasPrefix(text, "line "): 1170 // line directives are handled by syntax package 1171 panic("unreachable") 1172 1173 case strings.HasPrefix(text, "go:linkname "): 1174 f := strings.Fields(text) 1175 if len(f) != 3 { 1176 p.error(syntax.Error{Pos: pos, Msg: "usage: //go:linkname localname linkname"}) 1177 break 1178 } 1179 p.linknames = append(p.linknames, linkname{pos, f[1], f[2]}) 1180 1181 case strings.HasPrefix(text, "go:cgo_"): 1182 p.pragcgobuf += p.pragcgo(pos, text) 1183 fallthrough // because of //go:cgo_unsafe_args 1184 default: 1185 verb := text 1186 if i := strings.Index(text, " "); i >= 0 { 1187 verb = verb[:i] 1188 } 1189 prag := pragmaValue(verb) 1190 const runtimePragmas = Systemstack | Nowritebarrier | Nowritebarrierrec | Yeswritebarrierrec 1191 if !compiling_runtime && prag&runtimePragmas != 0 { 1192 p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in runtime", verb)}) 1193 } 1194 if prag == 0 && !allowedStdPragmas[verb] && compiling_std { 1195 p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s is not allowed in the standard library", verb)}) 1196 } 1197 return prag 1198 } 1199 1200 return 0 1201 } 1202 1203 func mkname(sym *types.Sym) *Node { 1204 n := oldname(sym) 1205 if n.Name != nil && n.Name.Pack != nil { 1206 n.Name.Pack.Name.SetUsed(true) 1207 } 1208 return n 1209 } 1210 1211 func unparen(x *Node) *Node { 1212 for x.Op == OPAREN { 1213 x = x.Left 1214 } 1215 return x 1216 }