Source file src/cmd/compile/internal/rangefunc/rewrite.go

     1  // Copyright 2023 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  /*
     6  Package rangefunc rewrites range-over-func to code that doesn't use range-over-funcs.
     7  Rewriting the construct in the front end, before noder, means the functions generated during
     8  the rewrite are available in a noder-generated representation for inlining by the back end.
     9  
    10  # Theory of Operation
    11  
    12  The basic idea is to rewrite
    13  
    14  	for x := range f {
    15  		...
    16  	}
    17  
    18  into
    19  
    20  	f(func(x T) bool {
    21  		...
    22  	})
    23  
    24  But it's not usually that easy.
    25  
    26  # Range variables
    27  
    28  For a range not using :=, the assigned variables cannot be function parameters
    29  in the generated body function. Instead, we allocate fake parameters and
    30  start the body with an assignment. For example:
    31  
    32  	for expr1, expr2 = range f {
    33  		...
    34  	}
    35  
    36  becomes
    37  
    38  	f(func(#p1 T1, #p2 T2) bool {
    39  		expr1, expr2 = #p1, #p2
    40  		...
    41  	})
    42  
    43  (All the generated variables have a # at the start to signal that they
    44  are internal variables when looking at the generated code in a
    45  debugger. Because variables have all been resolved to the specific
    46  objects they represent, there is no danger of using plain "p1" and
    47  colliding with a Go variable named "p1"; the # is just nice to have,
    48  not for correctness.)
    49  
    50  It can also happen that there are fewer range variables than function
    51  arguments, in which case we end up with something like
    52  
    53  	f(func(x T1, _ T2) bool {
    54  		...
    55  	})
    56  
    57  or
    58  
    59  	f(func(#p1 T1, #p2 T2, _ T3) bool {
    60  		expr1, expr2 = #p1, #p2
    61  		...
    62  	})
    63  
    64  # Return
    65  
    66  If the body contains a "break", that break turns into "return false",
    67  to tell f to stop. And if the body contains a "continue", that turns
    68  into "return true", to tell f to proceed with the next value.
    69  Those are the easy cases.
    70  
    71  If the body contains a return or a break/continue/goto L, then we need
    72  to rewrite that into code that breaks out of the loop and then
    73  triggers that control flow. In general we rewrite
    74  
    75  	for x := range f {
    76  		...
    77  	}
    78  
    79  into
    80  
    81  	{
    82  		var #next int
    83  		f(func(x T1) bool {
    84  			...
    85  			return true
    86  		})
    87  		... check #next ...
    88  	}
    89  
    90  The variable #next is an integer code that says what to do when f
    91  returns. Each difficult statement sets #next and then returns false to
    92  stop f.
    93  
    94  A plain "return" rewrites to {#next = -1; return false}.
    95  The return false breaks the loop. Then when f returns, the "check
    96  #next" section includes
    97  
    98  	if #next == -1 { return }
    99  
   100  which causes the return we want.
   101  
   102  Return with arguments is more involved, and has to deal with
   103  corner cases involving panic, defer, and recover.  The results
   104  of the enclosing function or closure are rewritten to give them
   105  names if they don't have them already, and the names are assigned
   106  at the return site.
   107  
   108  	  func foo() (#rv1 A, #rv2 B) {
   109  
   110  		{
   111  			var (
   112  				#next int
   113  			)
   114  			f(func(x T1) bool {
   115  				...
   116  				{
   117  					// return a, b
   118  					#rv1, #rv2 = a, b
   119  					#next = -1
   120  					return false
   121  				}
   122  				...
   123  				return true
   124  			})
   125  			if #next == -1 { return }
   126  		}
   127  
   128  # Checking
   129  
   130  To permit checking that an iterator is well-behaved -- that is, that
   131  it does not call the loop body again after it has returned false or
   132  after the entire loop has exited (it might retain a copy of the body
   133  function, or pass it to another goroutine) -- each generated loop has
   134  its own #stateK variable that is used to check for permitted call
   135  patterns to the yield function for a loop body.
   136  
   137  The state values are:
   138  
   139  abi.RF_DONE = 0      // body of loop has exited in a non-panic way
   140  abi.RF_READY = 1     // body of loop has not exited yet, is not running
   141  abi.RF_PANIC = 2     // body of loop is either currently running, or has panicked
   142  abi.RF_EXHAUSTED = 3 // iterator function call, e.g. f(func(x t){...}), returned so the sequence is "exhausted".
   143  
   144  abi.RF_MISSING_PANIC = 4 // used to report errors.
   145  
   146  The value of #stateK transitions
   147  (1) before calling the iterator function,
   148  
   149  	var #stateN = abi.RF_READY
   150  
   151  (2) after the iterator function call returns,
   152  
   153  	if #stateN == abi.RF_PANIC {
   154  		panic(runtime.panicrangestate(abi.RF_MISSING_PANIC))
   155  	}
   156  	#stateN = abi.RF_EXHAUSTED
   157  
   158  (3) at the beginning of the iteration of the loop body,
   159  
   160  	if #stateN != abi.RF_READY { runtime.panicrangestate(#stateN) }
   161  	#stateN = abi.RF_PANIC
   162  
   163  (4) when loop iteration continues,
   164  
   165  	#stateN = abi.RF_READY
   166  	[return true]
   167  
   168  (5) when control flow exits the loop body.
   169  
   170  	#stateN = abi.RF_DONE
   171  	[return false]
   172  
   173  For example:
   174  
   175  	for x := range f {
   176  		...
   177  		if ... { break }
   178  		...
   179  	}
   180  
   181  becomes
   182  
   183  		{
   184  			var #state1 = abi.RF_READY
   185  			f(func(x T1) bool {
   186  				if #state1 != abi.RF_READY { runtime.panicrangestate(#state1) }
   187  				#state1 = abi.RF_PANIC
   188  				...
   189  				if ... { #state1 = abi.RF_DONE ; return false }
   190  				...
   191  				#state1 = abi.RF_READY
   192  				return true
   193  			})
   194  	        if #state1 == abi.RF_PANIC {
   195  	        	// the code for the loop body did not return normally
   196  	        	panic(runtime.panicrangestate(abi.RF_MISSING_PANIC))
   197  	        }
   198  			#state1 = abi.RF_EXHAUSTED
   199  		}
   200  
   201  # Nested Loops
   202  
   203  So far we've only considered a single loop. If a function contains a
   204  sequence of loops, each can be translated individually. But loops can
   205  be nested. It would work to translate the innermost loop and then
   206  translate the loop around it, and so on, except that there'd be a lot
   207  of rewriting of rewritten code and the overall traversals could end up
   208  taking time quadratic in the depth of the nesting. To avoid all that,
   209  we use a single rewriting pass that handles a top-most range-over-func
   210  loop and all the range-over-func loops it contains at the same time.
   211  
   212  If we need to return from inside a doubly-nested loop, the rewrites
   213  above stay the same, but the check after the inner loop only says
   214  
   215  	if #next < 0 { return false }
   216  
   217  to stop the outer loop so it can do the actual return. That is,
   218  
   219  	for range f {
   220  		for range g {
   221  			...
   222  			return a, b
   223  			...
   224  		}
   225  	}
   226  
   227  becomes
   228  
   229  	{
   230  		var (
   231  			#next int
   232  		)
   233  		var #state1 = abi.RF_READY
   234  		f(func() bool {
   235  			if #state1 != abi.RF_READY { runtime.panicrangestate(#state1) }
   236  			#state1 = abi.RF_PANIC
   237  			var #state2 = abi.RF_READY
   238  			g(func() bool {
   239  				if #state2 != abi.RF_READY { runtime.panicrangestate(#state2) }
   240  				...
   241  				{
   242  					// return a, b
   243  					#rv1, #rv2 = a, b
   244  					#next = -1
   245  					#state2 = abi.RF_DONE
   246  					return false
   247  				}
   248  				...
   249  				#state2 = abi.RF_READY
   250  				return true
   251  			})
   252  	        if #state2 == abi.RF_PANIC {
   253  	        	panic(runtime.panicrangestate(abi.RF_MISSING_PANIC))
   254  	        }
   255  			#state2 = abi.RF_EXHAUSTED
   256  			if #next < 0 {
   257  				#state1 = abi.RF_DONE
   258  				return false
   259  			}
   260  			#state1 = abi.RF_READY
   261  			return true
   262  		})
   263  	    if #state1 == abi.RF_PANIC {
   264  	       	panic(runtime.panicrangestate(abi.RF_MISSING_PANIC))
   265  	    }
   266  		#state1 = abi.RF_EXHAUSTED
   267  		if #next == -1 {
   268  			return
   269  		}
   270  	}
   271  
   272  # Labeled break/continue of range-over-func loops
   273  
   274  For a labeled break or continue of an outer range-over-func, we
   275  use positive #next values.
   276  
   277  Any such labeled break or continue
   278  really means "do N breaks" or "do N breaks and 1 continue".
   279  
   280  The positive #next value tells which level of loop N to target
   281  with a break or continue, where perLoopStep*N means break out of
   282  level N and perLoopStep*N-1 means continue into level N.  The
   283  outermost loop has level 1, therefore #next == perLoopStep means
   284  to break from the outermost loop, and #next == perLoopStep-1 means
   285  to continue the outermost loop.
   286  
   287  Loops that might need to propagate a labeled break or continue
   288  add one or both of these to the #next checks:
   289  
   290  	    // N == depth of this loop, one less than the one just exited.
   291  		if #next != 0 {
   292  		  if #next >= perLoopStep*N-1 { // break or continue this loop
   293  		  	if #next >= perLoopStep*N+1 { // error checking
   294  		  	   // TODO reason about what exactly can appear
   295  		  	   // here given full  or partial checking.
   296  	           runtime.panicrangestate(abi.RF_DONE)
   297  		  	}
   298  		  	rv := #next & 1 == 1 // code generates into #next&1
   299  			#next = 0
   300  			return rv
   301  		  }
   302  		  return false // or handle returns and gotos
   303  		}
   304  
   305  For example (with perLoopStep == 2)
   306  
   307  	F: for range f { // 1, 2
   308  		for range g { // 3, 4
   309  			for range h {
   310  				...
   311  				break F
   312  				...
   313  				...
   314  				continue F
   315  				...
   316  			}
   317  		}
   318  		...
   319  	}
   320  
   321  becomes
   322  
   323  	{
   324  		var #next int
   325  		var #state1 = abi.RF_READY
   326  		f(func() { // 1,2
   327  			if #state1 != abi.RF_READY { runtime.panicrangestate(#state1) }
   328  			#state1 = abi.RF_PANIC
   329  			var #state2 = abi.RF_READY
   330  			g(func() { // 3,4
   331  				if #state2 != abi.RF_READY { runtime.panicrangestate(#state2) }
   332  				#state2 = abi.RF_PANIC
   333  				var #state3 = abi.RF_READY
   334  				h(func() { // 5,6
   335  					if #state3 != abi.RF_READY { runtime.panicrangestate(#state3) }
   336  					#state3 = abi.RF_PANIC
   337  					...
   338  					{
   339  						// break F
   340  						#next = 2
   341  						#state3 = abi.RF_DONE
   342  						return false
   343  					}
   344  					...
   345  					{
   346  						// continue F
   347  						#next = 1
   348  						#state3 = abi.RF_DONE
   349  						return false
   350  					}
   351  					...
   352  					#state3 = abi.RF_READY
   353  					return true
   354  				})
   355  				if #state3 == abi.RF_PANIC {
   356  					panic(runtime.panicrangestate(abi.RF_MISSING_PANIC))
   357  				}
   358  				#state3 = abi.RF_EXHAUSTED
   359  				if #next != 0 {
   360  					// no breaks or continues targeting this loop
   361  					#state2 = abi.RF_DONE
   362  					return false
   363  				}
   364  				return true
   365  			})
   366  	    	if #state2 == abi.RF_PANIC {
   367  	       		panic(runtime.panicrangestate(abi.RF_MISSING_PANIC))
   368  	   		}
   369  			#state2 = abi.RF_EXHAUSTED
   370  			if #next != 0 { // just exited g, test for break/continue applied to f/F
   371  				if #next >= 1 {
   372  					if #next >= 3 { runtime.panicrangestate(abi.RF_DONE) } // error
   373  					rv := #next&1 == 1
   374  					#next = 0
   375  					return rv
   376  				}
   377  				#state1 = abi.RF_DONE
   378  				return false
   379  			}
   380  			...
   381  			return true
   382  		})
   383  	    if #state1 == abi.RF_PANIC {
   384  	       	panic(runtime.panicrangestate(abi.RF_MISSING_PANIC))
   385  	    }
   386  		#state1 = abi.RF_EXHAUSTED
   387  	}
   388  
   389  Note that the post-h checks only consider a break,
   390  since no generated code tries to continue g.
   391  
   392  # Gotos and other labeled break/continue
   393  
   394  The final control flow translations are goto and break/continue of a
   395  non-range-over-func statement. In both cases, we may need to break
   396  out of one or more range-over-func loops before we can do the actual
   397  control flow statement. Each such break/continue/goto L statement is
   398  assigned a unique negative #next value (since -1 is return). Then
   399  the post-checks for a given loop test for the specific codes that
   400  refer to labels directly targetable from that block. Otherwise, the
   401  generic
   402  
   403  	if #next < 0 { return false }
   404  
   405  check handles stopping the next loop to get one step closer to the label.
   406  
   407  For example
   408  
   409  	Top: print("start\n")
   410  	for range f {
   411  		for range g {
   412  			...
   413  			for range h {
   414  				...
   415  				goto Top
   416  				...
   417  			}
   418  		}
   419  	}
   420  
   421  becomes
   422  
   423  	Top: print("start\n")
   424  	{
   425  		var #next int
   426  		var #state1 = abi.RF_READY
   427  		f(func() {
   428  			if #state1 != abi.RF_READY{ runtime.panicrangestate(#state1) }
   429  			#state1 = abi.RF_PANIC
   430  			var #state2 = abi.RF_READY
   431  			g(func() {
   432  				if #state2 != abi.RF_READY { runtime.panicrangestate(#state2) }
   433  				#state2 = abi.RF_PANIC
   434  				...
   435  				var #state3 bool = abi.RF_READY
   436  				h(func() {
   437  					if #state3 != abi.RF_READY { runtime.panicrangestate(#state3) }
   438  					#state3 = abi.RF_PANIC
   439  					...
   440  					{
   441  						// goto Top
   442  						#next = -3
   443  						#state3 = abi.RF_DONE
   444  						return false
   445  					}
   446  					...
   447  					#state3 = abi.RF_READY
   448  					return true
   449  				})
   450  				if #state3 == abi.RF_PANIC {runtime.panicrangestate(abi.RF_MISSING_PANIC)}
   451  				#state3 = abi.RF_EXHAUSTED
   452  				if #next < 0 {
   453  					#state2 = abi.RF_DONE
   454  					return false
   455  				}
   456  				#state2 = abi.RF_READY
   457  				return true
   458  			})
   459  			if #state2 == abi.RF_PANIC {runtime.panicrangestate(abi.RF_MISSING_PANIC)}
   460  			#state2 = abi.RF_EXHAUSTED
   461  			if #next < 0 {
   462  				#state1 = abi.RF_DONE
   463  				return false
   464  			}
   465  			#state1 = abi.RF_READY
   466  			return true
   467  		})
   468  		if #state1 == abi.RF_PANIC {runtime.panicrangestate(abi.RF_MISSING_PANIC)}
   469  		#state1 = abi.RF_EXHAUSTED
   470  		if #next == -3 {
   471  			#next = 0
   472  			goto Top
   473  		}
   474  	}
   475  
   476  Labeled break/continue to non-range-over-funcs are handled the same
   477  way as goto.
   478  
   479  # Defers
   480  
   481  The last wrinkle is handling defer statements. If we have
   482  
   483  	for range f {
   484  		defer print("A")
   485  	}
   486  
   487  we cannot rewrite that into
   488  
   489  	f(func() {
   490  		defer print("A")
   491  	})
   492  
   493  because the deferred code will run at the end of the iteration, not
   494  the end of the containing function. To fix that, the runtime provides
   495  a special hook that lets us obtain a defer "token" representing the
   496  outer function and then use it in a later defer to attach the deferred
   497  code to that outer function.
   498  
   499  Normally,
   500  
   501  	defer print("A")
   502  
   503  compiles to
   504  
   505  	runtime.deferproc(func() { print("A") })
   506  
   507  This changes in a range-over-func. For example:
   508  
   509  	for range f {
   510  		defer print("A")
   511  	}
   512  
   513  compiles to
   514  
   515  	var #defers = runtime.deferrangefunc()
   516  	f(func() {
   517  		runtime.deferprocat(func() { print("A") }, #defers)
   518  	})
   519  
   520  For this rewriting phase, we insert the explicit initialization of
   521  #defers and then attach the #defers variable to the CallStmt
   522  representing the defer. That variable will be propagated to the
   523  backend and will cause the backend to compile the defer using
   524  deferprocat instead of an ordinary deferproc.
   525  
   526  TODO: Could call runtime.deferrangefuncend after f.
   527  */
   528  package rangefunc
   529  
   530  import (
   531  	"cmd/compile/internal/base"
   532  	"cmd/compile/internal/syntax"
   533  	"cmd/compile/internal/types2"
   534  	"fmt"
   535  	"go/constant"
   536  	"internal/abi"
   537  	"os"
   538  )
   539  
   540  // nopos is the zero syntax.Pos.
   541  var nopos syntax.Pos
   542  
   543  // A rewriter implements rewriting the range-over-funcs in a given function.
   544  type rewriter struct {
   545  	pkg   *types2.Package
   546  	info  *types2.Info
   547  	sig   *types2.Signature
   548  	outer *syntax.FuncType
   549  	body  *syntax.BlockStmt
   550  
   551  	// References to important types and values.
   552  	any   types2.Object
   553  	bool  types2.Object
   554  	int   types2.Object
   555  	true  types2.Object
   556  	false types2.Object
   557  
   558  	// Branch numbering, computed as needed.
   559  	branchNext map[branch]int             // branch -> #next value
   560  	labelLoop  map[string]*syntax.ForStmt // label -> innermost rangefunc loop it is declared inside (nil for no loop)
   561  
   562  	// Stack of nodes being visited.
   563  	stack    []syntax.Node // all nodes
   564  	forStack []*forLoop    // range-over-func loops
   565  
   566  	rewritten map[*syntax.ForStmt]syntax.Stmt
   567  
   568  	// Declared variables in generated code for outermost loop.
   569  	declStmt         *syntax.DeclStmt
   570  	nextVar          types2.Object
   571  	defers           types2.Object
   572  	stateVarCount    int // stateVars are referenced from their respective loops
   573  	bodyClosureCount int // to help the debugger, the closures generated for loop bodies get names
   574  
   575  	rangefuncBodyClosures map[*syntax.FuncLit]bool
   576  }
   577  
   578  // A branch is a single labeled branch.
   579  type branch struct {
   580  	tok   syntax.Token
   581  	label string
   582  }
   583  
   584  // A forLoop describes a single range-over-func loop being processed.
   585  type forLoop struct {
   586  	nfor         *syntax.ForStmt // actual syntax
   587  	stateVar     *types2.Var     // #state variable for this loop
   588  	stateVarDecl *syntax.VarDecl
   589  	depth        int // outermost loop has depth 1, otherwise depth = depth(parent)+1
   590  
   591  	checkRet      bool     // add check for "return" after loop
   592  	checkBreak    bool     // add check for "break" after loop
   593  	checkContinue bool     // add check for "continue" after loop
   594  	checkBranch   []branch // add check for labeled branch after loop
   595  }
   596  
   597  type State int
   598  
   599  // Rewrite rewrites all the range-over-funcs in the files.
   600  // It returns the set of function literals generated from rangefunc loop bodies.
   601  // This allows for rangefunc loop bodies to be distingushed by debuggers.
   602  func Rewrite(pkg *types2.Package, info *types2.Info, files []*syntax.File) map[*syntax.FuncLit]bool {
   603  	ri := make(map[*syntax.FuncLit]bool)
   604  	for _, file := range files {
   605  		syntax.Inspect(file, func(n syntax.Node) bool {
   606  			switch n := n.(type) {
   607  			case *syntax.FuncDecl:
   608  				sig, _ := info.Defs[n.Name].Type().(*types2.Signature)
   609  				rewriteFunc(pkg, info, n.Type, n.Body, sig, ri)
   610  				return false
   611  			case *syntax.FuncLit:
   612  				sig, _ := info.Types[n].Type.(*types2.Signature)
   613  				if sig == nil {
   614  					tv := n.GetTypeInfo()
   615  					sig = tv.Type.(*types2.Signature)
   616  				}
   617  				rewriteFunc(pkg, info, n.Type, n.Body, sig, ri)
   618  				return false
   619  			}
   620  			return true
   621  		})
   622  	}
   623  	return ri
   624  }
   625  
   626  // rewriteFunc rewrites all the range-over-funcs in a single function (a top-level func or a func literal).
   627  // The typ and body are the function's type and body.
   628  func rewriteFunc(pkg *types2.Package, info *types2.Info, typ *syntax.FuncType, body *syntax.BlockStmt, sig *types2.Signature, ri map[*syntax.FuncLit]bool) {
   629  	if body == nil {
   630  		return
   631  	}
   632  	r := &rewriter{
   633  		pkg:                   pkg,
   634  		info:                  info,
   635  		outer:                 typ,
   636  		body:                  body,
   637  		sig:                   sig,
   638  		rangefuncBodyClosures: ri,
   639  	}
   640  	syntax.Inspect(body, r.inspect)
   641  	if (base.Flag.W != 0) && r.forStack != nil {
   642  		syntax.Fdump(os.Stderr, body)
   643  	}
   644  }
   645  
   646  // checkFuncMisuse reports whether to check for misuse of iterator callbacks functions.
   647  func (r *rewriter) checkFuncMisuse() bool {
   648  	return base.Debug.RangeFuncCheck != 0
   649  }
   650  
   651  // inspect is a callback for syntax.Inspect that drives the actual rewriting.
   652  // If it sees a func literal, it kicks off a separate rewrite for that literal.
   653  // Otherwise, it maintains a stack of range-over-func loops and
   654  // converts each in turn.
   655  func (r *rewriter) inspect(n syntax.Node) bool {
   656  	switch n := n.(type) {
   657  	case *syntax.FuncLit:
   658  		sig, _ := r.info.Types[n].Type.(*types2.Signature)
   659  		if sig == nil {
   660  			tv := n.GetTypeInfo()
   661  			sig = tv.Type.(*types2.Signature)
   662  		}
   663  		rewriteFunc(r.pkg, r.info, n.Type, n.Body, sig, r.rangefuncBodyClosures)
   664  		return false
   665  
   666  	default:
   667  		// Push n onto stack.
   668  		r.stack = append(r.stack, n)
   669  		if nfor, ok := forRangeFunc(n); ok {
   670  			loop := &forLoop{nfor: nfor, depth: 1 + len(r.forStack)}
   671  			r.forStack = append(r.forStack, loop)
   672  			r.startLoop(loop)
   673  		}
   674  
   675  	case nil:
   676  		// n == nil signals that we are done visiting
   677  		// the top-of-stack node's children. Find it.
   678  		n = r.stack[len(r.stack)-1]
   679  
   680  		// If we are inside a range-over-func,
   681  		// take this moment to replace any break/continue/goto/return
   682  		// statements directly contained in this node.
   683  		// Also replace any converted for statements
   684  		// with the rewritten block.
   685  		switch n := n.(type) {
   686  		case *syntax.BlockStmt:
   687  			for i, s := range n.List {
   688  				n.List[i] = r.editStmt(s)
   689  			}
   690  		case *syntax.CaseClause:
   691  			for i, s := range n.Body {
   692  				n.Body[i] = r.editStmt(s)
   693  			}
   694  		case *syntax.CommClause:
   695  			for i, s := range n.Body {
   696  				n.Body[i] = r.editStmt(s)
   697  			}
   698  		case *syntax.LabeledStmt:
   699  			n.Stmt = r.editStmt(n.Stmt)
   700  		}
   701  
   702  		// Pop n.
   703  		if len(r.forStack) > 0 && r.stack[len(r.stack)-1] == r.forStack[len(r.forStack)-1].nfor {
   704  			r.endLoop(r.forStack[len(r.forStack)-1])
   705  			r.forStack = r.forStack[:len(r.forStack)-1]
   706  		}
   707  		r.stack = r.stack[:len(r.stack)-1]
   708  	}
   709  	return true
   710  }
   711  
   712  // startLoop sets up for converting a range-over-func loop.
   713  func (r *rewriter) startLoop(loop *forLoop) {
   714  	// For first loop in function, allocate syntax for any, bool, int, true, and false.
   715  	if r.any == nil {
   716  		r.any = types2.Universe.Lookup("any")
   717  		r.bool = types2.Universe.Lookup("bool")
   718  		r.int = types2.Universe.Lookup("int")
   719  		r.true = types2.Universe.Lookup("true")
   720  		r.false = types2.Universe.Lookup("false")
   721  		r.rewritten = make(map[*syntax.ForStmt]syntax.Stmt)
   722  	}
   723  	if r.checkFuncMisuse() {
   724  		// declare the state flag for this loop's body
   725  		loop.stateVar, loop.stateVarDecl = r.stateVar(loop.nfor.Pos())
   726  	}
   727  }
   728  
   729  // editStmt returns the replacement for the statement x,
   730  // or x itself if it should be left alone.
   731  // This includes the for loops we are converting,
   732  // as left in x.rewritten by r.endLoop.
   733  func (r *rewriter) editStmt(x syntax.Stmt) syntax.Stmt {
   734  	if x, ok := x.(*syntax.ForStmt); ok {
   735  		if s := r.rewritten[x]; s != nil {
   736  			return s
   737  		}
   738  	}
   739  
   740  	if len(r.forStack) > 0 {
   741  		switch x := x.(type) {
   742  		case *syntax.BranchStmt:
   743  			return r.editBranch(x)
   744  		case *syntax.CallStmt:
   745  			if x.Tok == syntax.Defer {
   746  				return r.editDefer(x)
   747  			}
   748  		case *syntax.ReturnStmt:
   749  			return r.editReturn(x)
   750  		}
   751  	}
   752  
   753  	return x
   754  }
   755  
   756  // editDefer returns the replacement for the defer statement x.
   757  // See the "Defers" section in the package doc comment above for more context.
   758  func (r *rewriter) editDefer(x *syntax.CallStmt) syntax.Stmt {
   759  	if r.defers == nil {
   760  		// Declare and initialize the #defers token.
   761  		init := &syntax.CallExpr{
   762  			Fun: runtimeSym(r.info, "deferrangefunc"),
   763  		}
   764  		tv := syntax.TypeAndValue{Type: r.any.Type()}
   765  		tv.SetIsValue()
   766  		init.SetTypeInfo(tv)
   767  		r.defers = r.declOuterVar("#defers", r.any.Type(), init)
   768  	}
   769  
   770  	// Attach the token as an "extra" argument to the defer.
   771  	x.DeferAt = r.useObj(r.defers)
   772  	setPos(x.DeferAt, x.Pos())
   773  	return x
   774  }
   775  
   776  func (r *rewriter) stateVar(pos syntax.Pos) (*types2.Var, *syntax.VarDecl) {
   777  	r.stateVarCount++
   778  
   779  	name := fmt.Sprintf("#state%d", r.stateVarCount)
   780  	typ := r.int.Type()
   781  	obj := types2.NewVar(pos, r.pkg, name, typ)
   782  	n := syntax.NewName(pos, name)
   783  	setValueType(n, typ)
   784  	r.info.Defs[n] = obj
   785  
   786  	return obj, &syntax.VarDecl{NameList: []*syntax.Name{n}, Values: r.stateConst(abi.RF_READY)}
   787  }
   788  
   789  // editReturn returns the replacement for the return statement x.
   790  // See the "Return" section in the package doc comment above for more context.
   791  func (r *rewriter) editReturn(x *syntax.ReturnStmt) syntax.Stmt {
   792  	bl := &syntax.BlockStmt{}
   793  
   794  	if x.Results != nil {
   795  		// rewrite "return val" into "assign to named result; return"
   796  		if len(r.outer.ResultList) > 0 {
   797  			// Make sure that result parameters all have names
   798  			for i, a := range r.outer.ResultList {
   799  				if a.Name == nil || a.Name.Value == "_" {
   800  					r.generateParamName(r.outer.ResultList, i) // updates a.Name
   801  				}
   802  			}
   803  		}
   804  		// Assign to named results
   805  		results := []types2.Object{}
   806  		for _, a := range r.outer.ResultList {
   807  			results = append(results, r.info.Defs[a.Name])
   808  		}
   809  		bl.List = append(bl.List, &syntax.AssignStmt{Lhs: r.useList(results), Rhs: x.Results})
   810  		x.Results = nil
   811  	}
   812  
   813  	next := -1 // return
   814  
   815  	// Tell the loops along the way to check for a return.
   816  	for _, loop := range r.forStack {
   817  		loop.checkRet = true
   818  	}
   819  
   820  	// Set #next, and return false.
   821  
   822  	bl.List = append(bl.List, &syntax.AssignStmt{Lhs: r.next(), Rhs: r.intConst(next)})
   823  	if r.checkFuncMisuse() {
   824  		// mark this loop as exited, the others (which will be exited if iterators do not interfere) have not, yet.
   825  		bl.List = append(bl.List, r.setState(abi.RF_DONE, x.Pos()))
   826  	}
   827  	bl.List = append(bl.List, &syntax.ReturnStmt{Results: r.useObj(r.false)})
   828  	setPos(bl, x.Pos())
   829  	return bl
   830  }
   831  
   832  // perLoopStep is part of the encoding of loop-spanning control flow
   833  // for function range iterators.  Each multiple of two encodes a "return false"
   834  // passing control to an enclosing iterator; a terminal value of 1 encodes
   835  // "return true" (i.e., local continue) from the body function, and a terminal
   836  // value of 0 encodes executing the remainder of the body function.
   837  const perLoopStep = 2
   838  
   839  // editBranch returns the replacement for the branch statement x,
   840  // or x itself if it should be left alone.
   841  // See the package doc comment above for more context.
   842  func (r *rewriter) editBranch(x *syntax.BranchStmt) syntax.Stmt {
   843  	if x.Tok == syntax.Fallthrough {
   844  		// Fallthrough is unaffected by the rewrite.
   845  		return x
   846  	}
   847  
   848  	// Find target of break/continue/goto in r.forStack.
   849  	// (The target may not be in r.forStack at all.)
   850  	targ := x.Target
   851  	i := len(r.forStack) - 1
   852  	if x.Label == nil && r.forStack[i].nfor != targ {
   853  		// Unlabeled break or continue that's not nfor must be inside nfor. Leave alone.
   854  		return x
   855  	}
   856  	for i >= 0 && r.forStack[i].nfor != targ {
   857  		i--
   858  	}
   859  	// exitFrom is the index of the loop interior to the target of the control flow,
   860  	// if such a loop exists (it does not if i == len(r.forStack) - 1)
   861  	exitFrom := i + 1
   862  
   863  	// Compute the value to assign to #next and the specific return to use.
   864  	var next int
   865  	var ret *syntax.ReturnStmt
   866  	if x.Tok == syntax.Goto || i < 0 {
   867  		// goto Label
   868  		// or break/continue of labeled non-range-over-func loop (x.Label != nil).
   869  		// We may be able to leave it alone, or we may have to break
   870  		// out of one or more nested loops and then use #next to signal
   871  		// to complete the break/continue/goto.
   872  		// Figure out which range-over-func loop contains the label.
   873  		r.computeBranchNext()
   874  		nfor := r.forStack[len(r.forStack)-1].nfor
   875  		label := x.Label.Value
   876  		targ := r.labelLoop[label]
   877  		if nfor == targ {
   878  			// Label is in the innermost range-over-func loop; use it directly.
   879  			return x
   880  		}
   881  
   882  		// Set #next to the code meaning break/continue/goto label.
   883  		next = r.branchNext[branch{x.Tok, label}]
   884  
   885  		// Break out of nested loops up to targ.
   886  		i := len(r.forStack) - 1
   887  		for i >= 0 && r.forStack[i].nfor != targ {
   888  			i--
   889  		}
   890  		exitFrom = i + 1
   891  
   892  		// Mark loop we exit to get to targ to check for that branch.
   893  		// When i==-1 / exitFrom == 0 that's the outermost func body.
   894  		top := r.forStack[exitFrom]
   895  		top.checkBranch = append(top.checkBranch, branch{x.Tok, label})
   896  
   897  		// Mark loops along the way to check for a plain return, so they break.
   898  		for j := exitFrom + 1; j < len(r.forStack); j++ {
   899  			r.forStack[j].checkRet = true
   900  		}
   901  
   902  		// In the innermost loop, use a plain "return false".
   903  		ret = &syntax.ReturnStmt{Results: r.useObj(r.false)}
   904  	} else {
   905  		// break/continue of labeled range-over-func loop.
   906  		if exitFrom == len(r.forStack) {
   907  			// Simple break or continue.
   908  			// Continue returns true, break returns false, optionally both adjust state,
   909  			// neither modifies #next.
   910  			var state abi.RF_State
   911  			if x.Tok == syntax.Continue {
   912  				ret = &syntax.ReturnStmt{Results: r.useObj(r.true)}
   913  				state = abi.RF_READY
   914  			} else {
   915  				ret = &syntax.ReturnStmt{Results: r.useObj(r.false)}
   916  				state = abi.RF_DONE
   917  			}
   918  			var stmts []syntax.Stmt
   919  			if r.checkFuncMisuse() {
   920  				stmts = []syntax.Stmt{r.setState(state, x.Pos()), ret}
   921  			} else {
   922  				stmts = []syntax.Stmt{ret}
   923  			}
   924  			bl := &syntax.BlockStmt{
   925  				List: stmts,
   926  			}
   927  			setPos(bl, x.Pos())
   928  			return bl
   929  		}
   930  
   931  		ret = &syntax.ReturnStmt{Results: r.useObj(r.false)}
   932  
   933  		// The loop inside the one we are break/continue-ing
   934  		// needs to make that happen when we break out of it.
   935  		if x.Tok == syntax.Continue {
   936  			r.forStack[exitFrom].checkContinue = true
   937  		} else {
   938  			exitFrom = i // exitFrom--
   939  			r.forStack[exitFrom].checkBreak = true
   940  		}
   941  
   942  		// The loops along the way just need to break.
   943  		for j := exitFrom + 1; j < len(r.forStack); j++ {
   944  			r.forStack[j].checkBreak = true
   945  		}
   946  
   947  		// Set next to break the appropriate number of times;
   948  		// the final time may be a continue, not a break.
   949  		next = perLoopStep * (i + 1)
   950  		if x.Tok == syntax.Continue {
   951  			next--
   952  		}
   953  	}
   954  
   955  	// Assign #next = next and do the return.
   956  	as := &syntax.AssignStmt{Lhs: r.next(), Rhs: r.intConst(next)}
   957  	bl := &syntax.BlockStmt{
   958  		List: []syntax.Stmt{as},
   959  	}
   960  
   961  	if r.checkFuncMisuse() {
   962  		// Set #stateK for this loop.
   963  		// The exterior loops have not exited yet, and the iterator might interfere.
   964  		bl.List = append(bl.List, r.setState(abi.RF_DONE, x.Pos()))
   965  	}
   966  
   967  	bl.List = append(bl.List, ret)
   968  	setPos(bl, x.Pos())
   969  	return bl
   970  }
   971  
   972  // computeBranchNext computes the branchNext numbering
   973  // and determines which labels end up inside which range-over-func loop bodies.
   974  func (r *rewriter) computeBranchNext() {
   975  	if r.labelLoop != nil {
   976  		return
   977  	}
   978  
   979  	r.labelLoop = make(map[string]*syntax.ForStmt)
   980  	r.branchNext = make(map[branch]int)
   981  
   982  	var labels []string
   983  	var stack []syntax.Node
   984  	var forStack []*syntax.ForStmt
   985  	forStack = append(forStack, nil)
   986  	syntax.Inspect(r.body, func(n syntax.Node) bool {
   987  		if n != nil {
   988  			stack = append(stack, n)
   989  			if nfor, ok := forRangeFunc(n); ok {
   990  				forStack = append(forStack, nfor)
   991  			}
   992  			if n, ok := n.(*syntax.LabeledStmt); ok {
   993  				l := n.Label.Value
   994  				labels = append(labels, l)
   995  				f := forStack[len(forStack)-1]
   996  				r.labelLoop[l] = f
   997  			}
   998  		} else {
   999  			n := stack[len(stack)-1]
  1000  			stack = stack[:len(stack)-1]
  1001  			if n == forStack[len(forStack)-1] {
  1002  				forStack = forStack[:len(forStack)-1]
  1003  			}
  1004  		}
  1005  		return true
  1006  	})
  1007  
  1008  	// Assign numbers to all the labels we observed.
  1009  	used := -1 // returns use -1
  1010  	for _, l := range labels {
  1011  		used -= 3
  1012  		r.branchNext[branch{syntax.Break, l}] = used
  1013  		r.branchNext[branch{syntax.Continue, l}] = used + 1
  1014  		r.branchNext[branch{syntax.Goto, l}] = used + 2
  1015  	}
  1016  }
  1017  
  1018  // endLoop finishes the conversion of a range-over-func loop.
  1019  // We have inspected and rewritten the body of the loop and can now
  1020  // construct the body function and rewrite the for loop into a call
  1021  // bracketed by any declarations and checks it requires.
  1022  func (r *rewriter) endLoop(loop *forLoop) {
  1023  	// Pick apart for range X { ... }
  1024  	nfor := loop.nfor
  1025  	start, end := nfor.Pos(), nfor.Body.Rbrace // start, end position of for loop
  1026  	rclause := nfor.Init.(*syntax.RangeClause)
  1027  	rfunc := types2.CoreType(rclause.X.GetTypeInfo().Type).(*types2.Signature) // type of X - func(func(...)bool)
  1028  	if rfunc.Params().Len() != 1 {
  1029  		base.Fatalf("invalid typecheck of range func")
  1030  	}
  1031  	ftyp := types2.CoreType(rfunc.Params().At(0).Type()).(*types2.Signature) // func(...) bool
  1032  	if ftyp.Results().Len() != 1 {
  1033  		base.Fatalf("invalid typecheck of range func")
  1034  	}
  1035  
  1036  	// Give the closure generated for the body a name, to help the debugger connect it to its frame, if active.
  1037  	r.bodyClosureCount++
  1038  	clo := r.bodyFunc(nfor.Body.List, syntax.UnpackListExpr(rclause.Lhs), rclause.Def, ftyp, start, end)
  1039  	cloDecl, cloVar := r.declSingleVar(fmt.Sprintf("#yield%d", r.bodyClosureCount), clo.GetTypeInfo().Type, clo)
  1040  	setPos(cloDecl, start)
  1041  
  1042  	// Build X(bodyFunc)
  1043  	call := &syntax.ExprStmt{
  1044  		X: &syntax.CallExpr{
  1045  			Fun: rclause.X,
  1046  			ArgList: []syntax.Expr{
  1047  				r.useObj(cloVar),
  1048  			},
  1049  		},
  1050  	}
  1051  	setPos(call, start)
  1052  
  1053  	// Build checks based on #next after X(bodyFunc)
  1054  	checks := r.checks(loop, end)
  1055  
  1056  	// Rewrite for vars := range X { ... } to
  1057  	//
  1058  	//	{
  1059  	//		r.declStmt
  1060  	//		call
  1061  	//		checks
  1062  	//	}
  1063  	//
  1064  	// The r.declStmt can be added to by this loop or any inner loop
  1065  	// during the creation of r.bodyFunc; it is only emitted in the outermost
  1066  	// converted range loop.
  1067  	block := &syntax.BlockStmt{Rbrace: end}
  1068  	setPos(block, start)
  1069  	if len(r.forStack) == 1 && r.declStmt != nil {
  1070  		setPos(r.declStmt, start)
  1071  		block.List = append(block.List, r.declStmt)
  1072  	}
  1073  
  1074  	// declare the state variable here so it has proper scope and initialization
  1075  	if r.checkFuncMisuse() {
  1076  		stateVarDecl := &syntax.DeclStmt{DeclList: []syntax.Decl{loop.stateVarDecl}}
  1077  		setPos(stateVarDecl, start)
  1078  		block.List = append(block.List, stateVarDecl)
  1079  	}
  1080  
  1081  	// iteratorFunc(bodyFunc)
  1082  	block.List = append(block.List, cloDecl, call)
  1083  
  1084  	if r.checkFuncMisuse() {
  1085  		// iteratorFunc has exited, check for swallowed panic, and set body state to abi.RF_EXHAUSTED
  1086  		nif := &syntax.IfStmt{
  1087  			Cond: r.cond(syntax.Eql, r.useObj(loop.stateVar), r.stateConst(abi.RF_PANIC)),
  1088  			Then: &syntax.BlockStmt{
  1089  				List: []syntax.Stmt{r.callPanic(start, r.stateConst(abi.RF_MISSING_PANIC))},
  1090  			},
  1091  		}
  1092  		setPos(nif, end)
  1093  		block.List = append(block.List, nif)
  1094  		block.List = append(block.List, r.setState(abi.RF_EXHAUSTED, end))
  1095  	}
  1096  	block.List = append(block.List, checks...)
  1097  
  1098  	if len(r.forStack) == 1 { // ending an outermost loop
  1099  		r.declStmt = nil
  1100  		r.nextVar = nil
  1101  		r.defers = nil
  1102  	}
  1103  
  1104  	r.rewritten[nfor] = block
  1105  }
  1106  
  1107  func (r *rewriter) cond(op syntax.Operator, x, y syntax.Expr) *syntax.Operation {
  1108  	cond := &syntax.Operation{Op: op, X: x, Y: y}
  1109  	tv := syntax.TypeAndValue{Type: r.bool.Type()}
  1110  	tv.SetIsValue()
  1111  	cond.SetTypeInfo(tv)
  1112  	return cond
  1113  }
  1114  
  1115  func (r *rewriter) setState(val abi.RF_State, pos syntax.Pos) *syntax.AssignStmt {
  1116  	ss := r.setStateAt(len(r.forStack)-1, val)
  1117  	setPos(ss, pos)
  1118  	return ss
  1119  }
  1120  
  1121  func (r *rewriter) setStateAt(index int, stateVal abi.RF_State) *syntax.AssignStmt {
  1122  	loop := r.forStack[index]
  1123  	return &syntax.AssignStmt{
  1124  		Lhs: r.useObj(loop.stateVar),
  1125  		Rhs: r.stateConst(stateVal),
  1126  	}
  1127  }
  1128  
  1129  // bodyFunc converts the loop body (control flow has already been updated)
  1130  // to a func literal that can be passed to the range function.
  1131  //
  1132  // vars is the range variables from the range statement.
  1133  // def indicates whether this is a := range statement.
  1134  // ftyp is the type of the function we are creating
  1135  // start and end are the syntax positions to use for new nodes
  1136  // that should be at the start or end of the loop.
  1137  func (r *rewriter) bodyFunc(body []syntax.Stmt, lhs []syntax.Expr, def bool, ftyp *types2.Signature, start, end syntax.Pos) *syntax.FuncLit {
  1138  	// Starting X(bodyFunc); build up bodyFunc first.
  1139  	var params, results []*types2.Var
  1140  	results = append(results, types2.NewVar(start, nil, "#r", r.bool.Type()))
  1141  	bodyFunc := &syntax.FuncLit{
  1142  		// Note: Type is ignored but needs to be non-nil to avoid panic in syntax.Inspect.
  1143  		Type: &syntax.FuncType{},
  1144  		Body: &syntax.BlockStmt{
  1145  			List:   []syntax.Stmt{},
  1146  			Rbrace: end,
  1147  		},
  1148  	}
  1149  	r.rangefuncBodyClosures[bodyFunc] = true
  1150  	setPos(bodyFunc, start)
  1151  
  1152  	for i := 0; i < ftyp.Params().Len(); i++ {
  1153  		typ := ftyp.Params().At(i).Type()
  1154  		var paramVar *types2.Var
  1155  		if i < len(lhs) && def {
  1156  			// Reuse range variable as parameter.
  1157  			x := lhs[i]
  1158  			paramVar = r.info.Defs[x.(*syntax.Name)].(*types2.Var)
  1159  		} else {
  1160  			// Declare new parameter and assign it to range expression.
  1161  			paramVar = types2.NewVar(start, r.pkg, fmt.Sprintf("#p%d", 1+i), typ)
  1162  			if i < len(lhs) {
  1163  				x := lhs[i]
  1164  				as := &syntax.AssignStmt{Lhs: x, Rhs: r.useObj(paramVar)}
  1165  				as.SetPos(x.Pos())
  1166  				setPos(as.Rhs, x.Pos())
  1167  				bodyFunc.Body.List = append(bodyFunc.Body.List, as)
  1168  			}
  1169  		}
  1170  		params = append(params, paramVar)
  1171  	}
  1172  
  1173  	tv := syntax.TypeAndValue{
  1174  		Type: types2.NewSignatureType(nil, nil, nil,
  1175  			types2.NewTuple(params...),
  1176  			types2.NewTuple(results...),
  1177  			false),
  1178  	}
  1179  	tv.SetIsValue()
  1180  	bodyFunc.SetTypeInfo(tv)
  1181  
  1182  	loop := r.forStack[len(r.forStack)-1]
  1183  
  1184  	if r.checkFuncMisuse() {
  1185  		bodyFunc.Body.List = append(bodyFunc.Body.List, r.assertReady(start, loop))
  1186  		bodyFunc.Body.List = append(bodyFunc.Body.List, r.setState(abi.RF_PANIC, start))
  1187  	}
  1188  
  1189  	// Original loop body (already rewritten by editStmt during inspect).
  1190  	bodyFunc.Body.List = append(bodyFunc.Body.List, body...)
  1191  
  1192  	// end of loop body, set state to abi.RF_READY and return true to continue iteration
  1193  	if r.checkFuncMisuse() {
  1194  		bodyFunc.Body.List = append(bodyFunc.Body.List, r.setState(abi.RF_READY, end))
  1195  	}
  1196  	ret := &syntax.ReturnStmt{Results: r.useObj(r.true)}
  1197  	ret.SetPos(end)
  1198  	bodyFunc.Body.List = append(bodyFunc.Body.List, ret)
  1199  
  1200  	return bodyFunc
  1201  }
  1202  
  1203  // checks returns the post-call checks that need to be done for the given loop.
  1204  func (r *rewriter) checks(loop *forLoop, pos syntax.Pos) []syntax.Stmt {
  1205  	var list []syntax.Stmt
  1206  	if len(loop.checkBranch) > 0 {
  1207  		did := make(map[branch]bool)
  1208  		for _, br := range loop.checkBranch {
  1209  			if did[br] {
  1210  				continue
  1211  			}
  1212  			did[br] = true
  1213  			doBranch := &syntax.BranchStmt{Tok: br.tok, Label: &syntax.Name{Value: br.label}}
  1214  			list = append(list, r.ifNext(syntax.Eql, r.branchNext[br], true, doBranch))
  1215  		}
  1216  	}
  1217  
  1218  	curLoop := loop.depth - 1
  1219  	curLoopIndex := curLoop - 1
  1220  
  1221  	if len(r.forStack) == 1 {
  1222  		if loop.checkRet {
  1223  			list = append(list, r.ifNext(syntax.Eql, -1, false, retStmt(nil)))
  1224  		}
  1225  	} else {
  1226  
  1227  		// Idealized check, implemented more simply for now.
  1228  
  1229  		//	// N == depth of this loop, one less than the one just exited.
  1230  		//	if #next != 0 {
  1231  		//		if #next >= perLoopStep*N-1 { // this loop
  1232  		//			if #next >= perLoopStep*N+1 { // error checking
  1233  		//      		runtime.panicrangestate(abi.RF_DONE)
  1234  		//   		}
  1235  		//			rv := #next & 1 == 1 // code generates into #next&1
  1236  		//			#next = 0
  1237  		//			return rv
  1238  		//		}
  1239  		// 		return false // or handle returns and gotos
  1240  		//	}
  1241  
  1242  		if loop.checkRet {
  1243  			// Note: next < 0 also handles gotos handled by outer loops.
  1244  			// We set checkRet in that case to trigger this check.
  1245  			if r.checkFuncMisuse() {
  1246  				list = append(list, r.ifNext(syntax.Lss, 0, false, r.setStateAt(curLoopIndex, abi.RF_DONE), retStmt(r.useObj(r.false))))
  1247  			} else {
  1248  				list = append(list, r.ifNext(syntax.Lss, 0, false, retStmt(r.useObj(r.false))))
  1249  			}
  1250  		}
  1251  
  1252  		depthStep := perLoopStep * (curLoop)
  1253  
  1254  		if r.checkFuncMisuse() {
  1255  			list = append(list, r.ifNext(syntax.Gtr, depthStep, false, r.callPanic(pos, r.stateConst(abi.RF_DONE))))
  1256  		} else {
  1257  			list = append(list, r.ifNext(syntax.Gtr, depthStep, true))
  1258  		}
  1259  
  1260  		if r.checkFuncMisuse() {
  1261  			if loop.checkContinue {
  1262  				list = append(list, r.ifNext(syntax.Eql, depthStep-1, true, r.setStateAt(curLoopIndex, abi.RF_READY), retStmt(r.useObj(r.true))))
  1263  			}
  1264  
  1265  			if loop.checkBreak {
  1266  				list = append(list, r.ifNext(syntax.Eql, depthStep, true, r.setStateAt(curLoopIndex, abi.RF_DONE), retStmt(r.useObj(r.false))))
  1267  			}
  1268  
  1269  			if loop.checkContinue || loop.checkBreak {
  1270  				list = append(list, r.ifNext(syntax.Gtr, 0, false, r.setStateAt(curLoopIndex, abi.RF_DONE), retStmt(r.useObj(r.false))))
  1271  			}
  1272  
  1273  		} else {
  1274  			if loop.checkContinue {
  1275  				list = append(list, r.ifNext(syntax.Eql, depthStep-1, true, retStmt(r.useObj(r.true))))
  1276  			}
  1277  			if loop.checkBreak {
  1278  				list = append(list, r.ifNext(syntax.Eql, depthStep, true, retStmt(r.useObj(r.false))))
  1279  			}
  1280  			if loop.checkContinue || loop.checkBreak {
  1281  				list = append(list, r.ifNext(syntax.Gtr, 0, false, retStmt(r.useObj(r.false))))
  1282  			}
  1283  		}
  1284  	}
  1285  
  1286  	for _, j := range list {
  1287  		setPos(j, pos)
  1288  	}
  1289  	return list
  1290  }
  1291  
  1292  // retStmt returns a return statement returning the given return values.
  1293  func retStmt(results syntax.Expr) *syntax.ReturnStmt {
  1294  	return &syntax.ReturnStmt{Results: results}
  1295  }
  1296  
  1297  // ifNext returns the statement:
  1298  //
  1299  //	if #next op c { [#next = 0;] thens... }
  1300  func (r *rewriter) ifNext(op syntax.Operator, c int, zeroNext bool, thens ...syntax.Stmt) syntax.Stmt {
  1301  	var thenList []syntax.Stmt
  1302  	if zeroNext {
  1303  		clr := &syntax.AssignStmt{
  1304  			Lhs: r.next(),
  1305  			Rhs: r.intConst(0),
  1306  		}
  1307  		thenList = append(thenList, clr)
  1308  	}
  1309  	for _, then := range thens {
  1310  		thenList = append(thenList, then)
  1311  	}
  1312  	nif := &syntax.IfStmt{
  1313  		Cond: r.cond(op, r.next(), r.intConst(c)),
  1314  		Then: &syntax.BlockStmt{
  1315  			List: thenList,
  1316  		},
  1317  	}
  1318  	return nif
  1319  }
  1320  
  1321  // setValueType marks x as a value with type typ.
  1322  func setValueType(x syntax.Expr, typ syntax.Type) {
  1323  	tv := syntax.TypeAndValue{Type: typ}
  1324  	tv.SetIsValue()
  1325  	x.SetTypeInfo(tv)
  1326  }
  1327  
  1328  // assertReady returns the statement:
  1329  //
  1330  //	if #stateK != abi.RF_READY { runtime.panicrangestate(#stateK) }
  1331  //
  1332  // where #stateK is the state variable for loop.
  1333  func (r *rewriter) assertReady(start syntax.Pos, loop *forLoop) syntax.Stmt {
  1334  	nif := &syntax.IfStmt{
  1335  		Cond: r.cond(syntax.Neq, r.useObj(loop.stateVar), r.stateConst(abi.RF_READY)),
  1336  		Then: &syntax.BlockStmt{
  1337  			List: []syntax.Stmt{r.callPanic(start, r.useObj(loop.stateVar))},
  1338  		},
  1339  	}
  1340  	setPos(nif, start)
  1341  	return nif
  1342  }
  1343  
  1344  func (r *rewriter) callPanic(start syntax.Pos, arg syntax.Expr) syntax.Stmt {
  1345  	callPanicExpr := &syntax.CallExpr{
  1346  		Fun:     runtimeSym(r.info, "panicrangestate"),
  1347  		ArgList: []syntax.Expr{arg},
  1348  	}
  1349  	setValueType(callPanicExpr, nil) // no result type
  1350  	return &syntax.ExprStmt{X: callPanicExpr}
  1351  }
  1352  
  1353  // next returns a reference to the #next variable.
  1354  func (r *rewriter) next() *syntax.Name {
  1355  	if r.nextVar == nil {
  1356  		r.nextVar = r.declOuterVar("#next", r.int.Type(), nil)
  1357  	}
  1358  	return r.useObj(r.nextVar)
  1359  }
  1360  
  1361  // forRangeFunc checks whether n is a range-over-func.
  1362  // If so, it returns n.(*syntax.ForStmt), true.
  1363  // Otherwise it returns nil, false.
  1364  func forRangeFunc(n syntax.Node) (*syntax.ForStmt, bool) {
  1365  	nfor, ok := n.(*syntax.ForStmt)
  1366  	if !ok {
  1367  		return nil, false
  1368  	}
  1369  	nrange, ok := nfor.Init.(*syntax.RangeClause)
  1370  	if !ok {
  1371  		return nil, false
  1372  	}
  1373  	_, ok = types2.CoreType(nrange.X.GetTypeInfo().Type).(*types2.Signature)
  1374  	if !ok {
  1375  		return nil, false
  1376  	}
  1377  	return nfor, true
  1378  }
  1379  
  1380  // intConst returns syntax for an integer literal with the given value.
  1381  func (r *rewriter) intConst(c int) *syntax.BasicLit {
  1382  	lit := &syntax.BasicLit{
  1383  		Value: fmt.Sprint(c),
  1384  		Kind:  syntax.IntLit,
  1385  	}
  1386  	tv := syntax.TypeAndValue{Type: r.int.Type(), Value: constant.MakeInt64(int64(c))}
  1387  	tv.SetIsValue()
  1388  	lit.SetTypeInfo(tv)
  1389  	return lit
  1390  }
  1391  
  1392  func (r *rewriter) stateConst(s abi.RF_State) *syntax.BasicLit {
  1393  	return r.intConst(int(s))
  1394  }
  1395  
  1396  // useObj returns syntax for a reference to decl, which should be its declaration.
  1397  func (r *rewriter) useObj(obj types2.Object) *syntax.Name {
  1398  	n := syntax.NewName(nopos, obj.Name())
  1399  	tv := syntax.TypeAndValue{Type: obj.Type()}
  1400  	tv.SetIsValue()
  1401  	n.SetTypeInfo(tv)
  1402  	r.info.Uses[n] = obj
  1403  	return n
  1404  }
  1405  
  1406  // useList is useVar for a list of decls.
  1407  func (r *rewriter) useList(vars []types2.Object) syntax.Expr {
  1408  	var new []syntax.Expr
  1409  	for _, obj := range vars {
  1410  		new = append(new, r.useObj(obj))
  1411  	}
  1412  	if len(new) == 1 {
  1413  		return new[0]
  1414  	}
  1415  	return &syntax.ListExpr{ElemList: new}
  1416  }
  1417  
  1418  func (r *rewriter) makeVarName(pos syntax.Pos, name string, typ types2.Type) (*types2.Var, *syntax.Name) {
  1419  	obj := types2.NewVar(pos, r.pkg, name, typ)
  1420  	n := syntax.NewName(pos, name)
  1421  	tv := syntax.TypeAndValue{Type: typ}
  1422  	tv.SetIsValue()
  1423  	n.SetTypeInfo(tv)
  1424  	r.info.Defs[n] = obj
  1425  	return obj, n
  1426  }
  1427  
  1428  func (r *rewriter) generateParamName(results []*syntax.Field, i int) {
  1429  	obj, n := r.sig.RenameResult(results, i)
  1430  	r.info.Defs[n] = obj
  1431  }
  1432  
  1433  // declOuterVar declares a variable with a given name, type, and initializer value,
  1434  // in the same scope as the outermost loop in a loop nest.
  1435  func (r *rewriter) declOuterVar(name string, typ types2.Type, init syntax.Expr) *types2.Var {
  1436  	if r.declStmt == nil {
  1437  		r.declStmt = &syntax.DeclStmt{}
  1438  	}
  1439  	stmt := r.declStmt
  1440  	obj, n := r.makeVarName(stmt.Pos(), name, typ)
  1441  	stmt.DeclList = append(stmt.DeclList, &syntax.VarDecl{
  1442  		NameList: []*syntax.Name{n},
  1443  		// Note: Type is ignored
  1444  		Values: init,
  1445  	})
  1446  	return obj
  1447  }
  1448  
  1449  // declSingleVar declares a variable with a given name, type, and initializer value,
  1450  // and returns both the declaration and variable, so that the declaration can be placed
  1451  // in a specific scope.
  1452  func (r *rewriter) declSingleVar(name string, typ types2.Type, init syntax.Expr) (*syntax.DeclStmt, *types2.Var) {
  1453  	stmt := &syntax.DeclStmt{}
  1454  	obj, n := r.makeVarName(stmt.Pos(), name, typ)
  1455  	stmt.DeclList = append(stmt.DeclList, &syntax.VarDecl{
  1456  		NameList: []*syntax.Name{n},
  1457  		// Note: Type is ignored
  1458  		Values: init,
  1459  	})
  1460  	return stmt, obj
  1461  }
  1462  
  1463  // runtimePkg is a fake runtime package that contains what we need to refer to in package runtime.
  1464  var runtimePkg = func() *types2.Package {
  1465  	var nopos syntax.Pos
  1466  	pkg := types2.NewPackage("runtime", "runtime")
  1467  	anyType := types2.Universe.Lookup("any").Type()
  1468  	intType := types2.Universe.Lookup("int").Type()
  1469  
  1470  	// func deferrangefunc() unsafe.Pointer
  1471  	obj := types2.NewFunc(nopos, pkg, "deferrangefunc", types2.NewSignatureType(nil, nil, nil, nil, types2.NewTuple(types2.NewParam(nopos, pkg, "extra", anyType)), false))
  1472  	pkg.Scope().Insert(obj)
  1473  
  1474  	// func panicrangestate()
  1475  	obj = types2.NewFunc(nopos, pkg, "panicrangestate", types2.NewSignatureType(nil, nil, nil, types2.NewTuple(types2.NewParam(nopos, pkg, "state", intType)), nil, false))
  1476  	pkg.Scope().Insert(obj)
  1477  
  1478  	return pkg
  1479  }()
  1480  
  1481  // runtimeSym returns a reference to a symbol in the fake runtime package.
  1482  func runtimeSym(info *types2.Info, name string) *syntax.Name {
  1483  	obj := runtimePkg.Scope().Lookup(name)
  1484  	n := syntax.NewName(nopos, "runtime."+name)
  1485  	tv := syntax.TypeAndValue{Type: obj.Type()}
  1486  	tv.SetIsValue()
  1487  	tv.SetIsRuntimeHelper()
  1488  	n.SetTypeInfo(tv)
  1489  	info.Uses[n] = obj
  1490  	return n
  1491  }
  1492  
  1493  // setPos walks the top structure of x that has no position assigned
  1494  // and assigns it all to have position pos.
  1495  // When setPos encounters a syntax node with a position assigned,
  1496  // setPos does not look inside that node.
  1497  // setPos only needs to handle syntax we create in this package;
  1498  // all other syntax should have positions assigned already.
  1499  func setPos(x syntax.Node, pos syntax.Pos) {
  1500  	if x == nil {
  1501  		return
  1502  	}
  1503  	syntax.Inspect(x, func(n syntax.Node) bool {
  1504  		if n == nil || n.Pos() != nopos {
  1505  			return false
  1506  		}
  1507  		n.SetPos(pos)
  1508  		switch n := n.(type) {
  1509  		case *syntax.BlockStmt:
  1510  			if n.Rbrace == nopos {
  1511  				n.Rbrace = pos
  1512  			}
  1513  		}
  1514  		return true
  1515  	})
  1516  }
  1517  

View as plain text