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