github.com/sanprasirt/go@v0.0.0-20170607001320-a027466e4b6d/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, pos src.Pos) ScopeID { 82 old := p.scope 83 p.scope = 0 84 funchdr(n) 85 return old 86 } 87 88 func (p *noder) funcbody(n *Node, pos src.Pos, old ScopeID) { 89 funcbody(n) 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, fun.Pos()) 386 387 endPos := fun.Pos() 388 if fun.Body != nil { 389 if f.Noescape() { 390 yyerrorl(f.Pos, "can only use //go:noescape with external func implementations") 391 } 392 393 body := p.stmts(fun.Body.List) 394 if body == nil { 395 body = []*Node{p.nod(fun, OEMPTY, nil, nil)} 396 } 397 f.Nbody.Set(body) 398 399 endPos = fun.Body.Rbrace 400 lineno = Ctxt.PosTable.XPos(fun.Body.Rbrace) 401 f.Func.Endlineno = lineno 402 } else { 403 if pure_go || strings.HasPrefix(f.funcname(), "init.") { 404 yyerrorl(f.Pos, "missing function body for %q", f.funcname()) 405 } 406 } 407 408 p.funcbody(f, endPos, oldScope) 409 return f 410 } 411 412 func (p *noder) signature(recv *syntax.Field, typ *syntax.FuncType) *Node { 413 n := p.nod(typ, OTFUNC, nil, nil) 414 if recv != nil { 415 n.Left = p.param(recv, false, false) 416 } 417 n.List.Set(p.params(typ.ParamList, true)) 418 n.Rlist.Set(p.params(typ.ResultList, false)) 419 return n 420 } 421 422 func (p *noder) params(params []*syntax.Field, dddOk bool) []*Node { 423 var nodes []*Node 424 for i, param := range params { 425 p.lineno(param) 426 nodes = append(nodes, p.param(param, dddOk, i+1 == len(params))) 427 } 428 return nodes 429 } 430 431 func (p *noder) param(param *syntax.Field, dddOk, final bool) *Node { 432 var name *Node 433 if param.Name != nil { 434 name = p.newname(param.Name) 435 } 436 437 typ := p.typeExpr(param.Type) 438 n := p.nod(param, ODCLFIELD, name, typ) 439 440 // rewrite ...T parameter 441 if typ.Op == ODDD { 442 if !dddOk { 443 yyerror("cannot use ... in receiver or result parameter list") 444 } else if !final { 445 yyerror("can only use ... with final parameter in list") 446 } 447 typ.Op = OTARRAY 448 typ.Right = typ.Left 449 typ.Left = nil 450 n.SetIsddd(true) 451 if n.Left != nil { 452 n.Left.SetIsddd(true) 453 } 454 } 455 456 return n 457 } 458 459 func (p *noder) exprList(expr syntax.Expr) []*Node { 460 if list, ok := expr.(*syntax.ListExpr); ok { 461 return p.exprs(list.ElemList) 462 } 463 return []*Node{p.expr(expr)} 464 } 465 466 func (p *noder) exprs(exprs []syntax.Expr) []*Node { 467 var nodes []*Node 468 for _, expr := range exprs { 469 nodes = append(nodes, p.expr(expr)) 470 } 471 return nodes 472 } 473 474 func (p *noder) expr(expr syntax.Expr) *Node { 475 p.lineno(expr) 476 switch expr := expr.(type) { 477 case nil, *syntax.BadExpr: 478 return nil 479 case *syntax.Name: 480 return p.mkname(expr) 481 case *syntax.BasicLit: 482 return p.setlineno(expr, nodlit(p.basicLit(expr))) 483 484 case *syntax.CompositeLit: 485 n := p.nod(expr, OCOMPLIT, nil, nil) 486 if expr.Type != nil { 487 n.Right = p.expr(expr.Type) 488 } 489 l := p.exprs(expr.ElemList) 490 for i, e := range l { 491 l[i] = p.wrapname(expr.ElemList[i], e) 492 } 493 n.List.Set(l) 494 lineno = Ctxt.PosTable.XPos(expr.Rbrace) 495 return n 496 case *syntax.KeyValueExpr: 497 return p.nod(expr, OKEY, p.expr(expr.Key), p.wrapname(expr.Value, p.expr(expr.Value))) 498 case *syntax.FuncLit: 499 return p.funcLit(expr) 500 case *syntax.ParenExpr: 501 return p.nod(expr, OPAREN, p.expr(expr.X), nil) 502 case *syntax.SelectorExpr: 503 // parser.new_dotname 504 obj := p.expr(expr.X) 505 if obj.Op == OPACK { 506 obj.Name.SetUsed(true) 507 return oldname(restrictlookup(expr.Sel.Value, obj.Name.Pkg)) 508 } 509 return p.setlineno(expr, nodSym(OXDOT, obj, p.name(expr.Sel))) 510 case *syntax.IndexExpr: 511 return p.nod(expr, OINDEX, p.expr(expr.X), p.expr(expr.Index)) 512 case *syntax.SliceExpr: 513 op := OSLICE 514 if expr.Full { 515 op = OSLICE3 516 } 517 n := p.nod(expr, op, p.expr(expr.X), nil) 518 var index [3]*Node 519 for i, x := range expr.Index { 520 if x != nil { 521 index[i] = p.expr(x) 522 } 523 } 524 n.SetSliceBounds(index[0], index[1], index[2]) 525 return n 526 case *syntax.AssertExpr: 527 if expr.Type == nil { 528 panic("unexpected AssertExpr") 529 } 530 // TODO(mdempsky): parser.pexpr uses p.expr(), but 531 // seems like the type field should be parsed with 532 // ntype? Shrug, doesn't matter here. 533 return p.nod(expr, ODOTTYPE, p.expr(expr.X), p.expr(expr.Type)) 534 case *syntax.Operation: 535 x := p.expr(expr.X) 536 if expr.Y == nil { 537 if expr.Op == syntax.And { 538 x = unparen(x) // TODO(mdempsky): Needed? 539 if x.Op == OCOMPLIT { 540 // Special case for &T{...}: turn into (*T){...}. 541 // TODO(mdempsky): Switch back to p.nod after we 542 // get rid of gcCompat. 543 x.Right = nod(OIND, x.Right, nil) 544 x.Right.SetImplicit(true) 545 return x 546 } 547 } 548 return p.nod(expr, p.unOp(expr.Op), x, nil) 549 } 550 return p.nod(expr, p.binOp(expr.Op), x, p.expr(expr.Y)) 551 case *syntax.CallExpr: 552 n := p.nod(expr, OCALL, p.expr(expr.Fun), nil) 553 n.List.Set(p.exprs(expr.ArgList)) 554 n.SetIsddd(expr.HasDots) 555 return n 556 557 case *syntax.ArrayType: 558 var len *Node 559 if expr.Len != nil { 560 len = p.expr(expr.Len) 561 } else { 562 len = p.nod(expr, ODDD, nil, nil) 563 } 564 return p.nod(expr, OTARRAY, len, p.typeExpr(expr.Elem)) 565 case *syntax.SliceType: 566 return p.nod(expr, OTARRAY, nil, p.typeExpr(expr.Elem)) 567 case *syntax.DotsType: 568 return p.nod(expr, ODDD, p.typeExpr(expr.Elem), nil) 569 case *syntax.StructType: 570 return p.structType(expr) 571 case *syntax.InterfaceType: 572 return p.interfaceType(expr) 573 case *syntax.FuncType: 574 return p.signature(nil, expr) 575 case *syntax.MapType: 576 return p.nod(expr, OTMAP, p.typeExpr(expr.Key), p.typeExpr(expr.Value)) 577 case *syntax.ChanType: 578 n := p.nod(expr, OTCHAN, p.typeExpr(expr.Elem), nil) 579 n.Etype = types.EType(p.chanDir(expr.Dir)) 580 return n 581 582 case *syntax.TypeSwitchGuard: 583 n := p.nod(expr, OTYPESW, nil, p.expr(expr.X)) 584 if expr.Lhs != nil { 585 n.Left = p.declName(expr.Lhs) 586 if isblank(n.Left) { 587 yyerror("invalid variable name %v in type switch", n.Left) 588 } 589 } 590 return n 591 } 592 panic("unhandled Expr") 593 } 594 595 func (p *noder) typeExpr(typ syntax.Expr) *Node { 596 // TODO(mdempsky): Be stricter? typecheck should handle errors anyway. 597 return p.expr(typ) 598 } 599 600 func (p *noder) typeExprOrNil(typ syntax.Expr) *Node { 601 if typ != nil { 602 return p.expr(typ) 603 } 604 return nil 605 } 606 607 func (p *noder) chanDir(dir syntax.ChanDir) types.ChanDir { 608 switch dir { 609 case 0: 610 return types.Cboth 611 case syntax.SendOnly: 612 return types.Csend 613 case syntax.RecvOnly: 614 return types.Crecv 615 } 616 panic("unhandled ChanDir") 617 } 618 619 func (p *noder) structType(expr *syntax.StructType) *Node { 620 var l []*Node 621 for i, field := range expr.FieldList { 622 p.lineno(field) 623 var n *Node 624 if field.Name == nil { 625 n = p.embedded(field.Type) 626 } else { 627 n = p.nod(field, ODCLFIELD, p.newname(field.Name), p.typeExpr(field.Type)) 628 } 629 if i < len(expr.TagList) && expr.TagList[i] != nil { 630 n.SetVal(p.basicLit(expr.TagList[i])) 631 } 632 l = append(l, n) 633 } 634 635 p.lineno(expr) 636 n := p.nod(expr, OTSTRUCT, nil, nil) 637 n.List.Set(l) 638 return n 639 } 640 641 func (p *noder) interfaceType(expr *syntax.InterfaceType) *Node { 642 var l []*Node 643 for _, method := range expr.MethodList { 644 p.lineno(method) 645 var n *Node 646 if method.Name == nil { 647 n = p.nod(method, ODCLFIELD, nil, oldname(p.packname(method.Type))) 648 } else { 649 mname := p.newname(method.Name) 650 sig := p.typeExpr(method.Type) 651 sig.Left = fakeRecv() 652 n = p.nod(method, ODCLFIELD, mname, sig) 653 ifacedcl(n) 654 } 655 l = append(l, n) 656 } 657 658 n := p.nod(expr, OTINTER, nil, nil) 659 n.List.Set(l) 660 return n 661 } 662 663 func (p *noder) packname(expr syntax.Expr) *types.Sym { 664 switch expr := expr.(type) { 665 case *syntax.Name: 666 name := p.name(expr) 667 if n := oldname(name); n.Name != nil && n.Name.Pack != nil { 668 n.Name.Pack.Name.SetUsed(true) 669 } 670 return name 671 case *syntax.SelectorExpr: 672 name := p.name(expr.X.(*syntax.Name)) 673 var pkg *types.Pkg 674 if asNode(name.Def) == nil || asNode(name.Def).Op != OPACK { 675 yyerror("%v is not a package", name) 676 pkg = localpkg 677 } else { 678 asNode(name.Def).Name.SetUsed(true) 679 pkg = asNode(name.Def).Name.Pkg 680 } 681 return restrictlookup(expr.Sel.Value, pkg) 682 } 683 panic(fmt.Sprintf("unexpected packname: %#v", expr)) 684 } 685 686 func (p *noder) embedded(typ syntax.Expr) *Node { 687 op, isStar := typ.(*syntax.Operation) 688 if isStar { 689 if op.Op != syntax.Mul || op.Y != nil { 690 panic("unexpected Operation") 691 } 692 typ = op.X 693 } 694 n := embedded(p.packname(typ), localpkg) 695 if isStar { 696 n.Right = p.nod(op, OIND, n.Right, nil) 697 } 698 return n 699 } 700 701 func (p *noder) stmts(stmts []syntax.Stmt) []*Node { 702 var nodes []*Node 703 for _, stmt := range stmts { 704 s := p.stmt(stmt) 705 if s == nil { 706 } else if s.Op == OBLOCK && s.Ninit.Len() == 0 { 707 nodes = append(nodes, s.List.Slice()...) 708 } else { 709 nodes = append(nodes, s) 710 } 711 } 712 return nodes 713 } 714 715 func (p *noder) stmt(stmt syntax.Stmt) *Node { 716 p.lineno(stmt) 717 switch stmt := stmt.(type) { 718 case *syntax.EmptyStmt: 719 return nil 720 case *syntax.LabeledStmt: 721 return p.labeledStmt(stmt) 722 case *syntax.BlockStmt: 723 l := p.blockStmt(stmt) 724 if len(l) == 0 { 725 // TODO(mdempsky): Line number? 726 return nod(OEMPTY, nil, nil) 727 } 728 return liststmt(l) 729 case *syntax.ExprStmt: 730 return p.wrapname(stmt, p.expr(stmt.X)) 731 case *syntax.SendStmt: 732 return p.nod(stmt, OSEND, p.expr(stmt.Chan), p.expr(stmt.Value)) 733 case *syntax.DeclStmt: 734 return liststmt(p.decls(stmt.DeclList)) 735 case *syntax.AssignStmt: 736 if stmt.Op != 0 && stmt.Op != syntax.Def { 737 n := p.nod(stmt, OASOP, p.expr(stmt.Lhs), p.expr(stmt.Rhs)) 738 n.SetImplicit(stmt.Rhs == syntax.ImplicitOne) 739 n.Etype = types.EType(p.binOp(stmt.Op)) 740 return n 741 } 742 743 lhs := p.exprList(stmt.Lhs) 744 rhs := p.exprList(stmt.Rhs) 745 746 n := p.nod(stmt, OAS, nil, nil) // assume common case 747 748 if stmt.Op == syntax.Def { 749 n.SetColas(true) 750 colasdefn(lhs, n) // modifies lhs, call before using lhs[0] in common case 751 } 752 753 if len(lhs) == 1 && len(rhs) == 1 { 754 // common case 755 n.Left = lhs[0] 756 n.Right = rhs[0] 757 } else { 758 n.Op = OAS2 759 n.List.Set(lhs) 760 n.Rlist.Set(rhs) 761 } 762 return n 763 764 case *syntax.BranchStmt: 765 var op Op 766 switch stmt.Tok { 767 case syntax.Break: 768 op = OBREAK 769 case syntax.Continue: 770 op = OCONTINUE 771 case syntax.Fallthrough: 772 op = OXFALL 773 case syntax.Goto: 774 op = OGOTO 775 default: 776 panic("unhandled BranchStmt") 777 } 778 n := p.nod(stmt, op, nil, nil) 779 if stmt.Label != nil { 780 n.Left = p.newname(stmt.Label) 781 } 782 if op == OXFALL { 783 n.Xoffset = int64(types.Block) 784 } 785 return n 786 case *syntax.CallStmt: 787 var op Op 788 switch stmt.Tok { 789 case syntax.Defer: 790 op = ODEFER 791 case syntax.Go: 792 op = OPROC 793 default: 794 panic("unhandled CallStmt") 795 } 796 return p.nod(stmt, op, p.expr(stmt.Call), nil) 797 case *syntax.ReturnStmt: 798 var results []*Node 799 if stmt.Results != nil { 800 results = p.exprList(stmt.Results) 801 } 802 n := p.nod(stmt, ORETURN, nil, nil) 803 n.List.Set(results) 804 if n.List.Len() == 0 && Curfn != nil { 805 for _, ln := range Curfn.Func.Dcl { 806 if ln.Class() == PPARAM { 807 continue 808 } 809 if ln.Class() != PPARAMOUT { 810 break 811 } 812 if asNode(ln.Sym.Def) != ln { 813 yyerror("%s is shadowed during return", ln.Sym.Name) 814 } 815 } 816 } 817 return n 818 case *syntax.IfStmt: 819 return p.ifStmt(stmt) 820 case *syntax.ForStmt: 821 return p.forStmt(stmt) 822 case *syntax.SwitchStmt: 823 return p.switchStmt(stmt) 824 case *syntax.SelectStmt: 825 return p.selectStmt(stmt) 826 } 827 panic("unhandled Stmt") 828 } 829 830 func (p *noder) blockStmt(stmt *syntax.BlockStmt) []*Node { 831 p.openScope(stmt.Pos()) 832 nodes := p.stmts(stmt.List) 833 p.closeScope(stmt.Rbrace) 834 return nodes 835 } 836 837 func (p *noder) ifStmt(stmt *syntax.IfStmt) *Node { 838 p.openScope(stmt.Pos()) 839 n := p.nod(stmt, OIF, nil, nil) 840 if stmt.Init != nil { 841 n.Ninit.Set1(p.stmt(stmt.Init)) 842 } 843 if stmt.Cond != nil { 844 n.Left = p.expr(stmt.Cond) 845 } 846 n.Nbody.Set(p.blockStmt(stmt.Then)) 847 if stmt.Else != nil { 848 e := p.stmt(stmt.Else) 849 if e.Op == OBLOCK && e.Ninit.Len() == 0 { 850 n.Rlist.Set(e.List.Slice()) 851 } else { 852 n.Rlist.Set1(e) 853 } 854 } 855 p.closeAnotherScope() 856 return n 857 } 858 859 func (p *noder) forStmt(stmt *syntax.ForStmt) *Node { 860 p.openScope(stmt.Pos()) 861 var n *Node 862 if r, ok := stmt.Init.(*syntax.RangeClause); ok { 863 if stmt.Cond != nil || stmt.Post != nil { 864 panic("unexpected RangeClause") 865 } 866 867 n = p.nod(r, ORANGE, nil, p.expr(r.X)) 868 if r.Lhs != nil { 869 lhs := p.exprList(r.Lhs) 870 n.List.Set(lhs) 871 if r.Def { 872 n.SetColas(true) 873 colasdefn(lhs, n) 874 } 875 } 876 } else { 877 n = p.nod(stmt, OFOR, nil, nil) 878 if stmt.Init != nil { 879 n.Ninit.Set1(p.stmt(stmt.Init)) 880 } 881 if stmt.Cond != nil { 882 n.Left = p.expr(stmt.Cond) 883 } 884 if stmt.Post != nil { 885 n.Right = p.stmt(stmt.Post) 886 } 887 } 888 n.Nbody.Set(p.blockStmt(stmt.Body)) 889 p.closeAnotherScope() 890 return n 891 } 892 893 func (p *noder) switchStmt(stmt *syntax.SwitchStmt) *Node { 894 p.openScope(stmt.Pos()) 895 n := p.nod(stmt, OSWITCH, nil, nil) 896 if stmt.Init != nil { 897 n.Ninit.Set1(p.stmt(stmt.Init)) 898 } 899 if stmt.Tag != nil { 900 n.Left = p.expr(stmt.Tag) 901 } 902 903 tswitch := n.Left 904 if tswitch != nil && (tswitch.Op != OTYPESW || tswitch.Left == nil) { 905 tswitch = nil 906 } 907 n.List.Set(p.caseClauses(stmt.Body, tswitch, stmt.Rbrace)) 908 909 p.closeScope(stmt.Rbrace) 910 return n 911 } 912 913 func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *Node, rbrace src.Pos) []*Node { 914 var nodes []*Node 915 for i, clause := range clauses { 916 p.lineno(clause) 917 if i > 0 { 918 p.closeScope(clause.Pos()) 919 } 920 p.openScope(clause.Pos()) 921 922 n := p.nod(clause, OXCASE, nil, nil) 923 if clause.Cases != nil { 924 n.List.Set(p.exprList(clause.Cases)) 925 } 926 if tswitch != nil { 927 nn := newname(tswitch.Left.Sym) 928 declare(nn, dclcontext) 929 n.Rlist.Set1(nn) 930 // keep track of the instances for reporting unused 931 nn.Name.Defn = tswitch 932 } 933 n.Xoffset = int64(types.Block) 934 n.Nbody.Set(p.stmts(clause.Body)) 935 nodes = append(nodes, n) 936 } 937 if len(clauses) > 0 { 938 p.closeScope(rbrace) 939 } 940 return nodes 941 } 942 943 func (p *noder) selectStmt(stmt *syntax.SelectStmt) *Node { 944 n := p.nod(stmt, OSELECT, nil, nil) 945 n.List.Set(p.commClauses(stmt.Body, stmt.Rbrace)) 946 return n 947 } 948 949 func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace src.Pos) []*Node { 950 var nodes []*Node 951 for i, clause := range clauses { 952 p.lineno(clause) 953 if i > 0 { 954 p.closeScope(clause.Pos()) 955 } 956 p.openScope(clause.Pos()) 957 958 n := p.nod(clause, OXCASE, nil, nil) 959 if clause.Comm != nil { 960 n.List.Set1(p.stmt(clause.Comm)) 961 } 962 n.Xoffset = int64(types.Block) 963 n.Nbody.Set(p.stmts(clause.Body)) 964 nodes = append(nodes, n) 965 } 966 if len(clauses) > 0 { 967 p.closeScope(rbrace) 968 } 969 return nodes 970 } 971 972 func (p *noder) labeledStmt(label *syntax.LabeledStmt) *Node { 973 lhs := p.nod(label, OLABEL, p.newname(label.Label), nil) 974 975 var ls *Node 976 if label.Stmt != nil { // TODO(mdempsky): Should always be present. 977 ls = p.stmt(label.Stmt) 978 } 979 980 lhs.Name.Defn = ls 981 l := []*Node{lhs} 982 if ls != nil { 983 if ls.Op == OBLOCK && ls.Ninit.Len() == 0 { 984 l = append(l, ls.List.Slice()...) 985 } else { 986 l = append(l, ls) 987 } 988 } 989 return liststmt(l) 990 } 991 992 var unOps = [...]Op{ 993 syntax.Recv: ORECV, 994 syntax.Mul: OIND, 995 syntax.And: OADDR, 996 997 syntax.Not: ONOT, 998 syntax.Xor: OCOM, 999 syntax.Add: OPLUS, 1000 syntax.Sub: OMINUS, 1001 } 1002 1003 func (p *noder) unOp(op syntax.Operator) Op { 1004 if uint64(op) >= uint64(len(unOps)) || unOps[op] == 0 { 1005 panic("invalid Operator") 1006 } 1007 return unOps[op] 1008 } 1009 1010 var binOps = [...]Op{ 1011 syntax.OrOr: OOROR, 1012 syntax.AndAnd: OANDAND, 1013 1014 syntax.Eql: OEQ, 1015 syntax.Neq: ONE, 1016 syntax.Lss: OLT, 1017 syntax.Leq: OLE, 1018 syntax.Gtr: OGT, 1019 syntax.Geq: OGE, 1020 1021 syntax.Add: OADD, 1022 syntax.Sub: OSUB, 1023 syntax.Or: OOR, 1024 syntax.Xor: OXOR, 1025 1026 syntax.Mul: OMUL, 1027 syntax.Div: ODIV, 1028 syntax.Rem: OMOD, 1029 syntax.And: OAND, 1030 syntax.AndNot: OANDNOT, 1031 syntax.Shl: OLSH, 1032 syntax.Shr: ORSH, 1033 } 1034 1035 func (p *noder) binOp(op syntax.Operator) Op { 1036 if uint64(op) >= uint64(len(binOps)) || binOps[op] == 0 { 1037 panic("invalid Operator") 1038 } 1039 return binOps[op] 1040 } 1041 1042 func (p *noder) basicLit(lit *syntax.BasicLit) Val { 1043 // TODO: Don't try to convert if we had syntax errors (conversions may fail). 1044 // Use dummy values so we can continue to compile. Eventually, use a 1045 // form of "unknown" literals that are ignored during type-checking so 1046 // we can continue type-checking w/o spurious follow-up errors. 1047 switch s := lit.Value; lit.Kind { 1048 case syntax.IntLit: 1049 x := new(Mpint) 1050 x.SetString(s) 1051 return Val{U: x} 1052 1053 case syntax.FloatLit: 1054 x := newMpflt() 1055 x.SetString(s) 1056 return Val{U: x} 1057 1058 case syntax.ImagLit: 1059 x := new(Mpcplx) 1060 x.Imag.SetString(strings.TrimSuffix(s, "i")) 1061 return Val{U: x} 1062 1063 case syntax.RuneLit: 1064 var r rune 1065 if u, err := strconv.Unquote(s); err == nil && len(u) > 0 { 1066 // Package syntax already reported any errors. 1067 // Check for them again though because 0 is a 1068 // better fallback value for invalid rune 1069 // literals than 0xFFFD. 1070 if len(u) == 1 { 1071 r = rune(u[0]) 1072 } else { 1073 r, _ = utf8.DecodeRuneInString(u) 1074 } 1075 } 1076 x := new(Mpint) 1077 x.SetInt64(int64(r)) 1078 x.Rune = true 1079 return Val{U: x} 1080 1081 case syntax.StringLit: 1082 if len(s) > 0 && s[0] == '`' { 1083 // strip carriage returns from raw string 1084 s = strings.Replace(s, "\r", "", -1) 1085 } 1086 // Ignore errors because package syntax already reported them. 1087 u, _ := strconv.Unquote(s) 1088 return Val{U: u} 1089 1090 default: 1091 panic("unhandled BasicLit kind") 1092 } 1093 } 1094 1095 func (p *noder) name(name *syntax.Name) *types.Sym { 1096 return lookup(name.Value) 1097 } 1098 1099 func (p *noder) mkname(name *syntax.Name) *Node { 1100 // TODO(mdempsky): Set line number? 1101 return mkname(p.name(name)) 1102 } 1103 1104 func (p *noder) newname(name *syntax.Name) *Node { 1105 // TODO(mdempsky): Set line number? 1106 return newname(p.name(name)) 1107 } 1108 1109 func (p *noder) wrapname(n syntax.Node, x *Node) *Node { 1110 // These nodes do not carry line numbers. 1111 // Introduce a wrapper node to give them the correct line. 1112 switch x.Op { 1113 case OTYPE, OLITERAL: 1114 if x.Sym == nil { 1115 break 1116 } 1117 fallthrough 1118 case ONAME, ONONAME, OPACK: 1119 x = p.nod(n, OPAREN, x, nil) 1120 x.SetImplicit(true) 1121 } 1122 return x 1123 } 1124 1125 func (p *noder) nod(orig syntax.Node, op Op, left, right *Node) *Node { 1126 return p.setlineno(orig, nod(op, left, right)) 1127 } 1128 1129 func (p *noder) setlineno(src_ syntax.Node, dst *Node) *Node { 1130 pos := src_.Pos() 1131 if !pos.IsKnown() { 1132 // TODO(mdempsky): Shouldn't happen. Fix package syntax. 1133 return dst 1134 } 1135 dst.Pos = Ctxt.PosTable.XPos(pos) 1136 return dst 1137 } 1138 1139 func (p *noder) lineno(n syntax.Node) { 1140 if n == nil { 1141 return 1142 } 1143 pos := n.Pos() 1144 if !pos.IsKnown() { 1145 // TODO(mdempsky): Shouldn't happen. Fix package syntax. 1146 return 1147 } 1148 lineno = Ctxt.PosTable.XPos(pos) 1149 } 1150 1151 // error is called concurrently if files are parsed concurrently. 1152 func (p *noder) error(err error) { 1153 p.err <- err.(syntax.Error) 1154 } 1155 1156 // pragmas that are allowed in the std lib, but don't have 1157 // a syntax.Pragma value (see lex.go) associated with them. 1158 var allowedStdPragmas = map[string]bool{ 1159 "go:cgo_export_static": true, 1160 "go:cgo_export_dynamic": true, 1161 "go:cgo_import_static": true, 1162 "go:cgo_import_dynamic": true, 1163 "go:cgo_ldflag": true, 1164 "go:cgo_dynamic_linker": true, 1165 "go:generate": true, 1166 } 1167 1168 // pragma is called concurrently if files are parsed concurrently. 1169 func (p *noder) pragma(pos src.Pos, text string) syntax.Pragma { 1170 switch { 1171 case strings.HasPrefix(text, "line "): 1172 // line directives are handled by syntax package 1173 panic("unreachable") 1174 1175 case strings.HasPrefix(text, "go:linkname "): 1176 f := strings.Fields(text) 1177 if len(f) != 3 { 1178 p.error(syntax.Error{Pos: pos, Msg: "usage: //go:linkname localname linkname"}) 1179 break 1180 } 1181 p.linknames = append(p.linknames, linkname{pos, f[1], f[2]}) 1182 1183 case strings.HasPrefix(text, "go:cgo_"): 1184 p.pragcgobuf += p.pragcgo(pos, text) 1185 fallthrough // because of //go:cgo_unsafe_args 1186 default: 1187 verb := text 1188 if i := strings.Index(text, " "); i >= 0 { 1189 verb = verb[:i] 1190 } 1191 prag := pragmaValue(verb) 1192 const runtimePragmas = Systemstack | Nowritebarrier | Nowritebarrierrec | Yeswritebarrierrec 1193 if !compiling_runtime && prag&runtimePragmas != 0 { 1194 p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in runtime", verb)}) 1195 } 1196 if prag == 0 && !allowedStdPragmas[verb] && compiling_std { 1197 p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s is not allowed in the standard library", verb)}) 1198 } 1199 return prag 1200 } 1201 1202 return 0 1203 } 1204 1205 func mkname(sym *types.Sym) *Node { 1206 n := oldname(sym) 1207 if n.Name != nil && n.Name.Pack != nil { 1208 n.Name.Pack.Name.SetUsed(true) 1209 } 1210 return n 1211 } 1212 1213 func unparen(x *Node) *Node { 1214 for x.Op == OPAREN { 1215 x = x.Left 1216 } 1217 return x 1218 }