1
2
3
4
5
457 package rangefunc
458
459 import (
460 "cmd/compile/internal/base"
461 "cmd/compile/internal/syntax"
462 "cmd/compile/internal/types2"
463 "fmt"
464 "go/constant"
465 "os"
466 )
467
468
469 var nopos syntax.Pos
470
471
472 type rewriter struct {
473 pkg *types2.Package
474 info *types2.Info
475 outer *syntax.FuncType
476 body *syntax.BlockStmt
477
478
479 any types2.Object
480 bool types2.Object
481 int types2.Object
482 true types2.Object
483 false types2.Object
484
485
486 branchNext map[branch]int
487 labelLoop map[string]*syntax.ForStmt
488
489
490 stack []syntax.Node
491 forStack []*forLoop
492
493 rewritten map[*syntax.ForStmt]syntax.Stmt
494
495
496 declStmt *syntax.DeclStmt
497 nextVar types2.Object
498 retVars []types2.Object
499 defers types2.Object
500 exitVarCount int
501 }
502
503
504 type branch struct {
505 tok syntax.Token
506 label string
507 }
508
509
510 type forLoop struct {
511 nfor *syntax.ForStmt
512 exitFlag *types2.Var
513 exitFlagDecl *syntax.VarDecl
514
515 checkRet bool
516 checkRetArgs bool
517 checkBreak bool
518 checkContinue bool
519 checkBranch []branch
520 }
521
522
523 func Rewrite(pkg *types2.Package, info *types2.Info, files []*syntax.File) {
524 for _, file := range files {
525 syntax.Inspect(file, func(n syntax.Node) bool {
526 switch n := n.(type) {
527 case *syntax.FuncDecl:
528 rewriteFunc(pkg, info, n.Type, n.Body)
529 return false
530 case *syntax.FuncLit:
531 rewriteFunc(pkg, info, n.Type, n.Body)
532 return false
533 }
534 return true
535 })
536 }
537 }
538
539
540
541 func rewriteFunc(pkg *types2.Package, info *types2.Info, typ *syntax.FuncType, body *syntax.BlockStmt) {
542 if body == nil {
543 return
544 }
545 r := &rewriter{
546 pkg: pkg,
547 info: info,
548 outer: typ,
549 body: body,
550 }
551 syntax.Inspect(body, r.inspect)
552 if (base.Flag.W != 0) && r.forStack != nil {
553 syntax.Fdump(os.Stderr, body)
554 }
555 }
556
557
558 func (r *rewriter) checkFuncMisuse() bool {
559 return base.Debug.RangeFuncCheck != 0
560 }
561
562
563
564
565
566 func (r *rewriter) inspect(n syntax.Node) bool {
567 switch n := n.(type) {
568 case *syntax.FuncLit:
569 rewriteFunc(r.pkg, r.info, n.Type, n.Body)
570 return false
571
572 default:
573
574 r.stack = append(r.stack, n)
575 if nfor, ok := forRangeFunc(n); ok {
576 loop := &forLoop{nfor: nfor}
577 r.forStack = append(r.forStack, loop)
578 r.startLoop(loop)
579 }
580
581 case nil:
582
583
584 n = r.stack[len(r.stack)-1]
585
586
587
588
589
590
591 switch n := n.(type) {
592 case *syntax.BlockStmt:
593 for i, s := range n.List {
594 n.List[i] = r.editStmt(s)
595 }
596 case *syntax.CaseClause:
597 for i, s := range n.Body {
598 n.Body[i] = r.editStmt(s)
599 }
600 case *syntax.CommClause:
601 for i, s := range n.Body {
602 n.Body[i] = r.editStmt(s)
603 }
604 case *syntax.LabeledStmt:
605 n.Stmt = r.editStmt(n.Stmt)
606 }
607
608
609 if len(r.forStack) > 0 && r.stack[len(r.stack)-1] == r.forStack[len(r.forStack)-1].nfor {
610 r.endLoop(r.forStack[len(r.forStack)-1])
611 r.forStack = r.forStack[:len(r.forStack)-1]
612 }
613 r.stack = r.stack[:len(r.stack)-1]
614 }
615 return true
616 }
617
618
619 func (r *rewriter) startLoop(loop *forLoop) {
620
621 if r.any == nil {
622 r.any = types2.Universe.Lookup("any")
623 r.bool = types2.Universe.Lookup("bool")
624 r.int = types2.Universe.Lookup("int")
625 r.true = types2.Universe.Lookup("true")
626 r.false = types2.Universe.Lookup("false")
627 r.rewritten = make(map[*syntax.ForStmt]syntax.Stmt)
628 }
629 if r.checkFuncMisuse() {
630
631 loop.exitFlag, loop.exitFlagDecl = r.exitVar(loop.nfor.Pos())
632 }
633 }
634
635
636
637
638
639 func (r *rewriter) editStmt(x syntax.Stmt) syntax.Stmt {
640 if x, ok := x.(*syntax.ForStmt); ok {
641 if s := r.rewritten[x]; s != nil {
642 return s
643 }
644 }
645
646 if len(r.forStack) > 0 {
647 switch x := x.(type) {
648 case *syntax.BranchStmt:
649 return r.editBranch(x)
650 case *syntax.CallStmt:
651 if x.Tok == syntax.Defer {
652 return r.editDefer(x)
653 }
654 case *syntax.ReturnStmt:
655 return r.editReturn(x)
656 }
657 }
658
659 return x
660 }
661
662
663
664 func (r *rewriter) editDefer(x *syntax.CallStmt) syntax.Stmt {
665 if r.defers == nil {
666
667 init := &syntax.CallExpr{
668 Fun: runtimeSym(r.info, "deferrangefunc"),
669 }
670 tv := syntax.TypeAndValue{Type: r.any.Type()}
671 tv.SetIsValue()
672 init.SetTypeInfo(tv)
673 r.defers = r.declVar("#defers", r.any.Type(), init)
674 }
675
676
677 x.DeferAt = r.useVar(r.defers)
678 setPos(x.DeferAt, x.Pos())
679 return x
680 }
681
682 func (r *rewriter) exitVar(pos syntax.Pos) (*types2.Var, *syntax.VarDecl) {
683 r.exitVarCount++
684
685 name := fmt.Sprintf("#exit%d", r.exitVarCount)
686 typ := r.bool.Type()
687 obj := types2.NewVar(pos, r.pkg, name, typ)
688 n := syntax.NewName(pos, name)
689 setValueType(n, typ)
690 r.info.Defs[n] = obj
691
692 return obj, &syntax.VarDecl{NameList: []*syntax.Name{n}}
693 }
694
695
696
697 func (r *rewriter) editReturn(x *syntax.ReturnStmt) syntax.Stmt {
698
699 var next int
700 if x.Results == nil {
701 next = -1
702 r.forStack[0].checkRet = true
703 } else {
704 next = -2
705 r.forStack[0].checkRetArgs = true
706 }
707
708
709 for _, loop := range r.forStack[1:] {
710 loop.checkRet = true
711 }
712
713
714 bl := &syntax.BlockStmt{}
715 if x.Results != nil {
716 if r.retVars == nil {
717 for i, a := range r.outer.ResultList {
718 obj := r.declVar(fmt.Sprintf("#r%d", i+1), a.Type.GetTypeInfo().Type, nil)
719 r.retVars = append(r.retVars, obj)
720 }
721 }
722 bl.List = append(bl.List, &syntax.AssignStmt{Lhs: r.useList(r.retVars), Rhs: x.Results})
723 }
724 bl.List = append(bl.List, &syntax.AssignStmt{Lhs: r.next(), Rhs: r.intConst(next)})
725 if r.checkFuncMisuse() {
726
727 for i := 0; i < len(r.forStack); i++ {
728 bl.List = append(bl.List, r.setExitedAt(i))
729 }
730 }
731 bl.List = append(bl.List, &syntax.ReturnStmt{Results: r.useVar(r.false)})
732 setPos(bl, x.Pos())
733 return bl
734 }
735
736
737
738
739
740
741 const perLoopStep = 2
742
743
744
745
746 func (r *rewriter) editBranch(x *syntax.BranchStmt) syntax.Stmt {
747 if x.Tok == syntax.Fallthrough {
748
749 return x
750 }
751
752
753
754 targ := x.Target
755 i := len(r.forStack) - 1
756 if x.Label == nil && r.forStack[i].nfor != targ {
757
758 return x
759 }
760 for i >= 0 && r.forStack[i].nfor != targ {
761 i--
762 }
763
764
765 exitFrom := i + 1
766
767
768 var next int
769 var ret *syntax.ReturnStmt
770 if x.Tok == syntax.Goto || i < 0 {
771
772
773
774
775
776
777 r.computeBranchNext()
778 nfor := r.forStack[len(r.forStack)-1].nfor
779 label := x.Label.Value
780 targ := r.labelLoop[label]
781 if nfor == targ {
782
783 return x
784 }
785
786
787 next = r.branchNext[branch{x.Tok, label}]
788
789
790 i := len(r.forStack) - 1
791 for i >= 0 && r.forStack[i].nfor != targ {
792 i--
793 }
794 exitFrom = i + 1
795
796
797
798 top := r.forStack[i+1]
799 top.checkBranch = append(top.checkBranch, branch{x.Tok, label})
800
801
802 for j := i + 2; j < len(r.forStack); j++ {
803 r.forStack[j].checkRet = true
804 }
805
806
807 ret = &syntax.ReturnStmt{Results: r.useVar(r.false)}
808 } else {
809
810 depth := len(r.forStack) - 1 - i
811
812
813
814
815 if depth == 0 && x.Tok == syntax.Continue {
816 ret = &syntax.ReturnStmt{Results: r.useVar(r.true)}
817 setPos(ret, x.Pos())
818 return ret
819 }
820 ret = &syntax.ReturnStmt{Results: r.useVar(r.false)}
821
822
823
824 if depth == 0 {
825 var stmts []syntax.Stmt
826 if r.checkFuncMisuse() {
827 stmts = []syntax.Stmt{r.setExited(), ret}
828 } else {
829 stmts = []syntax.Stmt{ret}
830 }
831 bl := &syntax.BlockStmt{
832 List: stmts,
833 }
834 setPos(bl, x.Pos())
835 return bl
836 }
837
838
839
840 if x.Tok == syntax.Continue {
841 r.forStack[exitFrom].checkContinue = true
842 } else {
843 exitFrom = i
844 r.forStack[exitFrom].checkBreak = true
845 }
846
847
848 for j := exitFrom + 1; j < len(r.forStack); j++ {
849 r.forStack[j].checkBreak = true
850 }
851
852
853
854 next = perLoopStep * depth
855 if x.Tok == syntax.Continue {
856 next--
857 }
858 }
859
860
861 as := &syntax.AssignStmt{Lhs: r.next(), Rhs: r.intConst(next)}
862 bl := &syntax.BlockStmt{
863 List: []syntax.Stmt{as},
864 }
865
866 if r.checkFuncMisuse() {
867
868 for i := exitFrom; i < len(r.forStack); i++ {
869 bl.List = append(bl.List, r.setExitedAt(i))
870 }
871 }
872
873 bl.List = append(bl.List, ret)
874 setPos(bl, x.Pos())
875 return bl
876 }
877
878
879
880 func (r *rewriter) computeBranchNext() {
881 if r.labelLoop != nil {
882 return
883 }
884
885 r.labelLoop = make(map[string]*syntax.ForStmt)
886 r.branchNext = make(map[branch]int)
887
888 var labels []string
889 var stack []syntax.Node
890 var forStack []*syntax.ForStmt
891 forStack = append(forStack, nil)
892 syntax.Inspect(r.body, func(n syntax.Node) bool {
893 if n != nil {
894 stack = append(stack, n)
895 if nfor, ok := forRangeFunc(n); ok {
896 forStack = append(forStack, nfor)
897 }
898 if n, ok := n.(*syntax.LabeledStmt); ok {
899 l := n.Label.Value
900 labels = append(labels, l)
901 f := forStack[len(forStack)-1]
902 r.labelLoop[l] = f
903 }
904 } else {
905 n := stack[len(stack)-1]
906 stack = stack[:len(stack)-1]
907 if n == forStack[len(forStack)-1] {
908 forStack = forStack[:len(forStack)-1]
909 }
910 }
911 return true
912 })
913
914
915 used := -2
916 for _, l := range labels {
917 used -= 3
918 r.branchNext[branch{syntax.Break, l}] = used
919 r.branchNext[branch{syntax.Continue, l}] = used + 1
920 r.branchNext[branch{syntax.Goto, l}] = used + 2
921 }
922 }
923
924
925
926
927
928 func (r *rewriter) endLoop(loop *forLoop) {
929
930 nfor := loop.nfor
931 start, end := nfor.Pos(), nfor.Body.Rbrace
932 rclause := nfor.Init.(*syntax.RangeClause)
933 rfunc := types2.CoreType(rclause.X.GetTypeInfo().Type).(*types2.Signature)
934 if rfunc.Params().Len() != 1 {
935 base.Fatalf("invalid typecheck of range func")
936 }
937 ftyp := types2.CoreType(rfunc.Params().At(0).Type()).(*types2.Signature)
938 if ftyp.Results().Len() != 1 {
939 base.Fatalf("invalid typecheck of range func")
940 }
941
942
943 call := &syntax.ExprStmt{
944 X: &syntax.CallExpr{
945 Fun: rclause.X,
946 ArgList: []syntax.Expr{
947 r.bodyFunc(nfor.Body.List, syntax.UnpackListExpr(rclause.Lhs), rclause.Def, ftyp, start, end),
948 },
949 },
950 }
951 setPos(call, start)
952
953
954 checks := r.checks(loop, end)
955
956
957
958
959
960
961
962
963
964
965
966
967 block := &syntax.BlockStmt{Rbrace: end}
968 setPos(block, start)
969 if len(r.forStack) == 1 && r.declStmt != nil {
970 setPos(r.declStmt, start)
971 block.List = append(block.List, r.declStmt)
972 }
973
974
975 if r.checkFuncMisuse() {
976 exitFlagDecl := &syntax.DeclStmt{DeclList: []syntax.Decl{loop.exitFlagDecl}}
977 block.List = append(block.List, exitFlagDecl)
978 }
979
980
981 block.List = append(block.List, call)
982
983 if r.checkFuncMisuse() {
984
985 block.List = append(block.List, r.setExited())
986 }
987 block.List = append(block.List, checks...)
988
989 if len(r.forStack) == 1 {
990 r.declStmt = nil
991 r.nextVar = nil
992 r.retVars = nil
993 r.defers = nil
994 }
995
996 r.rewritten[nfor] = block
997 }
998
999 func (r *rewriter) setExited() *syntax.AssignStmt {
1000 return r.setExitedAt(len(r.forStack) - 1)
1001 }
1002
1003 func (r *rewriter) setExitedAt(index int) *syntax.AssignStmt {
1004 loop := r.forStack[index]
1005 return &syntax.AssignStmt{
1006 Lhs: r.useVar(loop.exitFlag),
1007 Rhs: r.useVar(r.true),
1008 }
1009 }
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019 func (r *rewriter) bodyFunc(body []syntax.Stmt, lhs []syntax.Expr, def bool, ftyp *types2.Signature, start, end syntax.Pos) *syntax.FuncLit {
1020
1021 var params, results []*types2.Var
1022 results = append(results, types2.NewVar(start, nil, "", r.bool.Type()))
1023 bodyFunc := &syntax.FuncLit{
1024
1025 Type: &syntax.FuncType{},
1026 Body: &syntax.BlockStmt{
1027 List: []syntax.Stmt{},
1028 Rbrace: end,
1029 },
1030 }
1031 setPos(bodyFunc, start)
1032
1033 for i := 0; i < ftyp.Params().Len(); i++ {
1034 typ := ftyp.Params().At(i).Type()
1035 var paramVar *types2.Var
1036 if i < len(lhs) && def {
1037
1038 x := lhs[i]
1039 paramVar = r.info.Defs[x.(*syntax.Name)].(*types2.Var)
1040 } else {
1041
1042 paramVar = types2.NewVar(start, r.pkg, fmt.Sprintf("#p%d", 1+i), typ)
1043 if i < len(lhs) {
1044 x := lhs[i]
1045 as := &syntax.AssignStmt{Lhs: x, Rhs: r.useVar(paramVar)}
1046 as.SetPos(x.Pos())
1047 setPos(as.Rhs, x.Pos())
1048 bodyFunc.Body.List = append(bodyFunc.Body.List, as)
1049 }
1050 }
1051 params = append(params, paramVar)
1052 }
1053
1054 tv := syntax.TypeAndValue{
1055 Type: types2.NewSignatureType(nil, nil, nil,
1056 types2.NewTuple(params...),
1057 types2.NewTuple(results...),
1058 false),
1059 }
1060 tv.SetIsValue()
1061 bodyFunc.SetTypeInfo(tv)
1062
1063 loop := r.forStack[len(r.forStack)-1]
1064
1065 if r.checkFuncMisuse() {
1066 bodyFunc.Body.List = append(bodyFunc.Body.List, r.assertNotExited(start, loop))
1067 }
1068
1069
1070 bodyFunc.Body.List = append(bodyFunc.Body.List, body...)
1071
1072
1073 ret := &syntax.ReturnStmt{Results: r.useVar(r.true)}
1074 ret.SetPos(end)
1075 bodyFunc.Body.List = append(bodyFunc.Body.List, ret)
1076
1077 return bodyFunc
1078 }
1079
1080
1081 func (r *rewriter) checks(loop *forLoop, pos syntax.Pos) []syntax.Stmt {
1082 var list []syntax.Stmt
1083 if len(loop.checkBranch) > 0 {
1084 did := make(map[branch]bool)
1085 for _, br := range loop.checkBranch {
1086 if did[br] {
1087 continue
1088 }
1089 did[br] = true
1090 doBranch := &syntax.BranchStmt{Tok: br.tok, Label: &syntax.Name{Value: br.label}}
1091 list = append(list, r.ifNext(syntax.Eql, r.branchNext[br], doBranch))
1092 }
1093 }
1094 if len(r.forStack) == 1 {
1095 if loop.checkRetArgs {
1096 list = append(list, r.ifNext(syntax.Eql, -2, retStmt(r.useList(r.retVars))))
1097 }
1098 if loop.checkRet {
1099 list = append(list, r.ifNext(syntax.Eql, -1, retStmt(nil)))
1100 }
1101 } else {
1102 if loop.checkRetArgs || loop.checkRet {
1103
1104
1105 list = append(list, r.ifNext(syntax.Lss, 0, retStmt(r.useVar(r.false))))
1106 }
1107 if loop.checkBreak {
1108 list = append(list, r.ifNext(syntax.Geq, perLoopStep, retStmt(r.useVar(r.false))))
1109 }
1110 if loop.checkContinue {
1111 list = append(list, r.ifNext(syntax.Eql, perLoopStep-1, retStmt(r.useVar(r.true))))
1112 }
1113 }
1114
1115 for _, j := range list {
1116 setPos(j, pos)
1117 }
1118 return list
1119 }
1120
1121
1122 func retStmt(results syntax.Expr) *syntax.ReturnStmt {
1123 return &syntax.ReturnStmt{Results: results}
1124 }
1125
1126
1127
1128
1129
1130
1131
1132
1133 func (r *rewriter) ifNext(op syntax.Operator, c int, then syntax.Stmt) syntax.Stmt {
1134 nif := &syntax.IfStmt{
1135 Cond: &syntax.Operation{Op: op, X: r.next(), Y: r.intConst(c)},
1136 Then: &syntax.BlockStmt{
1137 List: []syntax.Stmt{then},
1138 },
1139 }
1140 tv := syntax.TypeAndValue{Type: r.bool.Type()}
1141 tv.SetIsValue()
1142 nif.Cond.SetTypeInfo(tv)
1143
1144 if op == syntax.Geq {
1145 sub := &syntax.AssignStmt{
1146 Op: syntax.Sub,
1147 Lhs: r.next(),
1148 Rhs: r.intConst(c),
1149 }
1150 nif.Then.List = []syntax.Stmt{sub, then}
1151 }
1152 if op == syntax.Eql && c != -1 && c != -2 {
1153 clr := &syntax.AssignStmt{
1154 Lhs: r.next(),
1155 Rhs: r.intConst(0),
1156 }
1157 nif.Then.List = []syntax.Stmt{clr, then}
1158 }
1159
1160 return nif
1161 }
1162
1163
1164 func setValueType(x syntax.Expr, typ syntax.Type) {
1165 tv := syntax.TypeAndValue{Type: typ}
1166 tv.SetIsValue()
1167 x.SetTypeInfo(tv)
1168 }
1169
1170
1171
1172
1173
1174
1175 func (r *rewriter) assertNotExited(start syntax.Pos, loop *forLoop) syntax.Stmt {
1176 callPanicExpr := &syntax.CallExpr{
1177 Fun: runtimeSym(r.info, "panicrangeexit"),
1178 }
1179 setValueType(callPanicExpr, nil)
1180
1181 callPanic := &syntax.ExprStmt{X: callPanicExpr}
1182
1183 nif := &syntax.IfStmt{
1184 Cond: r.useVar(loop.exitFlag),
1185 Then: &syntax.BlockStmt{
1186 List: []syntax.Stmt{callPanic},
1187 },
1188 }
1189 setPos(nif, start)
1190 return nif
1191 }
1192
1193
1194 func (r *rewriter) next() *syntax.Name {
1195 if r.nextVar == nil {
1196 r.nextVar = r.declVar("#next", r.int.Type(), nil)
1197 }
1198 return r.useVar(r.nextVar)
1199 }
1200
1201
1202
1203
1204 func forRangeFunc(n syntax.Node) (*syntax.ForStmt, bool) {
1205 nfor, ok := n.(*syntax.ForStmt)
1206 if !ok {
1207 return nil, false
1208 }
1209 nrange, ok := nfor.Init.(*syntax.RangeClause)
1210 if !ok {
1211 return nil, false
1212 }
1213 _, ok = types2.CoreType(nrange.X.GetTypeInfo().Type).(*types2.Signature)
1214 if !ok {
1215 return nil, false
1216 }
1217 return nfor, true
1218 }
1219
1220
1221 func (r *rewriter) intConst(c int) *syntax.BasicLit {
1222 lit := &syntax.BasicLit{
1223 Value: fmt.Sprint(c),
1224 Kind: syntax.IntLit,
1225 }
1226 tv := syntax.TypeAndValue{Type: r.int.Type(), Value: constant.MakeInt64(int64(c))}
1227 tv.SetIsValue()
1228 lit.SetTypeInfo(tv)
1229 return lit
1230 }
1231
1232
1233 func (r *rewriter) useVar(obj types2.Object) *syntax.Name {
1234 n := syntax.NewName(nopos, obj.Name())
1235 tv := syntax.TypeAndValue{Type: obj.Type()}
1236 tv.SetIsValue()
1237 n.SetTypeInfo(tv)
1238 r.info.Uses[n] = obj
1239 return n
1240 }
1241
1242
1243 func (r *rewriter) useList(vars []types2.Object) syntax.Expr {
1244 var new []syntax.Expr
1245 for _, obj := range vars {
1246 new = append(new, r.useVar(obj))
1247 }
1248 if len(new) == 1 {
1249 return new[0]
1250 }
1251 return &syntax.ListExpr{ElemList: new}
1252 }
1253
1254
1255 func (r *rewriter) declVar(name string, typ types2.Type, init syntax.Expr) *types2.Var {
1256 if r.declStmt == nil {
1257 r.declStmt = &syntax.DeclStmt{}
1258 }
1259 stmt := r.declStmt
1260 obj := types2.NewVar(stmt.Pos(), r.pkg, name, typ)
1261 n := syntax.NewName(stmt.Pos(), name)
1262 tv := syntax.TypeAndValue{Type: typ}
1263 tv.SetIsValue()
1264 n.SetTypeInfo(tv)
1265 r.info.Defs[n] = obj
1266 stmt.DeclList = append(stmt.DeclList, &syntax.VarDecl{
1267 NameList: []*syntax.Name{n},
1268
1269 Values: init,
1270 })
1271 return obj
1272 }
1273
1274
1275
1276 func declType(pos syntax.Pos, name string, typ types2.Type) *syntax.Name {
1277 n := syntax.NewName(pos, name)
1278 n.SetTypeInfo(syntax.TypeAndValue{Type: typ})
1279 return n
1280 }
1281
1282
1283 var runtimePkg = func() *types2.Package {
1284 var nopos syntax.Pos
1285 pkg := types2.NewPackage("runtime", "runtime")
1286 anyType := types2.Universe.Lookup("any").Type()
1287
1288
1289 obj := types2.NewFunc(nopos, pkg, "deferrangefunc", types2.NewSignatureType(nil, nil, nil, nil, types2.NewTuple(types2.NewParam(nopos, pkg, "extra", anyType)), false))
1290 pkg.Scope().Insert(obj)
1291
1292
1293 obj = types2.NewFunc(nopos, pkg, "panicrangeexit", types2.NewSignatureType(nil, nil, nil, nil, nil, false))
1294 pkg.Scope().Insert(obj)
1295
1296 return pkg
1297 }()
1298
1299
1300 func runtimeSym(info *types2.Info, name string) *syntax.Name {
1301 obj := runtimePkg.Scope().Lookup(name)
1302 n := syntax.NewName(nopos, "runtime."+name)
1303 tv := syntax.TypeAndValue{Type: obj.Type()}
1304 tv.SetIsValue()
1305 tv.SetIsRuntimeHelper()
1306 n.SetTypeInfo(tv)
1307 info.Uses[n] = obj
1308 return n
1309 }
1310
1311
1312
1313
1314
1315
1316
1317 func setPos(x syntax.Node, pos syntax.Pos) {
1318 if x == nil {
1319 return
1320 }
1321 syntax.Inspect(x, func(n syntax.Node) bool {
1322 if n == nil || n.Pos() != nopos {
1323 return false
1324 }
1325 n.SetPos(pos)
1326 switch n := n.(type) {
1327 case *syntax.BlockStmt:
1328 if n.Rbrace == nopos {
1329 n.Rbrace = pos
1330 }
1331 }
1332 return true
1333 })
1334 }
1335
View as plain text