github.com/cockroachdb/tools@v0.0.0-20230222021103-a6d27438930d/cmd/signature-fuzzer/internal/fuzz-generator/generator.go (about)

     1  // Copyright 2021 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  // This package generates source code for a stand-alone Go program
     6  // useful for function signature fuzzing. The generated program is a
     7  // series of function pairs, a "Caller" function and a "Checker"
     8  // function. The signature of the Checker function is generated
     9  // randomly (random number of parameters and returns, each with
    10  // randomly chosen types). The "Caller" func contains invocations of
    11  // the "Checker" function, each passing randomly chosen values to the
    12  // params of the "Checker", then the caller verifies that expected
    13  // values are returned correctly.  The "Checker" function in turn has
    14  // code to verify that the expected values arrive correctly, and so
    15  // on.
    16  //
    17  // The main exported items of interest for this package are:
    18  //
    19  // - the Generate function, which takes a GenConfig object and emits
    20  //   code according to the config's specification
    21  //
    22  // - the GenConfig struct, which is basically a large collection of
    23  //   knobs/switches to control the mechanics of how/where code is
    24  //   generated
    25  //
    26  // - the TunableParams struct, which controls the nature of the
    27  //   generated code (for example, the maximum number of function
    28  //   parameters, etc), and the SetTunables func which tells the
    29  //   package what tunable parameters to use.
    30  
    31  // Notes for posterity:
    32  // - many parts of this package would have been better off being written
    33  //   using text/template instead of generating code directly; perhaps
    34  //   at some point it could be converted over (big job).
    35  // - for the various 'fractions' fields in the TunableParams struct,
    36  //   it would be good to have a named type of some sort, with methods
    37  //   for managing things like checking to make sure values sum to 100.
    38  
    39  package generator
    40  
    41  import (
    42  	"bytes"
    43  	"crypto/sha1"
    44  	"errors"
    45  	"fmt"
    46  	"html/template"
    47  	"log"
    48  	"os"
    49  	"os/exec"
    50  	"path/filepath"
    51  	"strconv"
    52  	"strings"
    53  )
    54  
    55  // GenConfig contains configuration parameters relating to the
    56  // mechanics of the code generation, e.g. how many packages/functions
    57  // to emit, path to a directory into which we place the generated
    58  // code, prefixes/packagenames for the generate code, and so on.
    59  type GenConfig struct {
    60  	// Tag is a string prefix prepended to functions within
    61  	// the generated code.
    62  	Tag string
    63  
    64  	// Output directory in to which we'll emit generated code.
    65  	// This will be created if it does not exist.
    66  	OutDir string
    67  
    68  	// Packagepath prefix given to the generated code.
    69  	PkgPath string
    70  
    71  	// Number of test packages created within the generated corpus.
    72  	// Each test package is essentially an independent collection
    73  	// generated code; the point of having multiple packages is to
    74  	// be able to get faster builds (more parallelism), and to avoid
    75  	// the compile time issues that crop up with 'giant' packages.
    76  	NumTestPackages int
    77  
    78  	// Number of test function pairs within each generated test package.
    79  	// Each pair consists of a "caller" function and  "callee" function.
    80  	NumTestFunctions int
    81  
    82  	// Seed for random number generator.
    83  	Seed int64
    84  
    85  	// Pragma is a "// go:..." compiler directive to apply to the
    86  	// callee function as part of a generated function pair.
    87  	Pragma string
    88  
    89  	// Function and package mask used for minimization purposes.
    90  	// If a given mask is non-nil, then the generator will only
    91  	// emit code for a given func or package if its index is
    92  	// present in the mask map.
    93  	FcnMask map[int]int
    94  	PkgMask map[int]int
    95  
    96  	// Maximum number of failures to encounter before bailing out.
    97  	MaxFail int
    98  
    99  	// forcestackgrowth if set tells the generator to insert
   100  	// calls to runtime.gcTestMoveStackOnNextCall at various points
   101  	// in the generated code.
   102  	ForceStackGrowth bool
   103  
   104  	// Random number generator control flag (debugging)
   105  	RandCtl int
   106  
   107  	// Tells the generator to run "goimports" on the emitted code.
   108  	RunGoImports bool
   109  
   110  	// Debugging/testing hook. If set to 1, emit code that will cause the
   111  	// build to fail; if set to 2, emit code that will cause a test to fail.
   112  	EmitBad int
   113  
   114  	// If EmitBad above is set, then these can be used to select the ID of
   115  	// a specific bad func/package.
   116  	BadPackageIdx int
   117  	BadFuncIdx    int
   118  }
   119  
   120  const CallerName = "Caller"
   121  const CheckerName = "Checker"
   122  
   123  // TunableParams contains configuration parameters that control the
   124  // flavor of code generated for a given test function. This includes
   125  // things like the number of params/returns, the percentages of types
   126  // (int, struct, etc) of the params/returns, and so on.
   127  type TunableParams struct {
   128  	// between 0 and N params
   129  	nParmRange uint8
   130  
   131  	// between 0 and N returns
   132  	nReturnRange uint8
   133  
   134  	// structs have between 0 and N members
   135  	nStructFields uint8
   136  
   137  	// arrays/slices have between 0 and N elements
   138  	nArrayElements uint8
   139  
   140  	// fraction of slices vs arrays. This is a value between 0 and 100 (0 meaning
   141  	// no slices [only arrays] and 100 meaning all slices, no arrays).
   142  	sliceFraction uint8
   143  
   144  	// Controls how often "int" vars wind up as 8/16/32/64, should
   145  	// add up to 100. Ex: 100 0 0 0 means all ints are 8 bit, 25
   146  	// 25 25 25 means equal likelihood of all types.
   147  	intBitRanges [4]uint8
   148  
   149  	// Similar to the above but for 32/64 float types
   150  	floatBitRanges [2]uint8
   151  
   152  	// Similar to the above but for unsigned, signed ints.
   153  	unsignedRanges [2]uint8
   154  
   155  	// Percentage of params, struct fields that should be "_". Ranges
   156  	// from 0 to 100.
   157  	blankPerc uint8
   158  
   159  	// How deeply structs are allowed to be nested (ranges from 0 to N).
   160  	structDepth uint8
   161  
   162  	// Fraction of param and return types assigned to each of:
   163  	// struct/array/map/pointer/int/float/complex/byte/string at the
   164  	// top level. If nesting precludes using a struct, other types
   165  	// are chosen from instead according to same proportions. The sum
   166  	// of typeFractions values should add up to 100.
   167  	typeFractions [9]uint8
   168  
   169  	// Percentage of the time we'll emit recursive calls, from 0 to 100.
   170  	recurPerc uint8
   171  
   172  	// Percentage of time that we turn the test function into a method,
   173  	// and if it is a method, fraction of time that we use a pointer
   174  	// method call vs value method call. Each range from 0 to 100.
   175  	methodPerc            uint8
   176  	pointerMethodCallPerc uint8
   177  
   178  	// If true, test reflect.Call path as well.
   179  	doReflectCall bool
   180  
   181  	// If true, then randomly take addresses of params/returns.
   182  	takeAddress bool
   183  
   184  	// Fraction of the time that any params/returns are address taken.
   185  	// Ranges from 0 to 100.
   186  	takenFraction uint8
   187  
   188  	// For a given address-taken param or return, controls the
   189  	// manner in which the indirect read or write takes
   190  	// place. This is a set of percentages for
   191  	// not/simple/passed/heap, where "not" means not address
   192  	// taken, "simple" means a simple read or write, "passed"
   193  	// means that the address is passed to a well-behaved
   194  	// function, and "heap" means that the address is assigned to
   195  	// a global. Values in addrFractions should add up to 100.
   196  	addrFractions [4]uint8
   197  
   198  	// If true, then perform testing of go/defer statements.
   199  	doDefer bool
   200  
   201  	// fraction of test functions for which we emit a defer. Ranges from 0 to 100.
   202  	deferFraction uint8
   203  
   204  	// If true, randomly pick between emitting a value by literal
   205  	// (e.g. "int(1)" vs emitting a call to a function that
   206  	// will produce the same value (e.g. "myHelperEmitsInt1()").
   207  	doFuncCallValues bool
   208  
   209  	// Fraction of the time that we emit a function call to create
   210  	// a param value vs emitting a literal. Ranges from 0 to 100.
   211  	funcCallValFraction uint8
   212  
   213  	// If true, randomly decide to not check selected components of
   214  	// a composite value (e.g. for a struct, check field F1 but not F2).
   215  	// The intent is to generate partially live values.
   216  	doSkipCompare bool
   217  
   218  	// Fraction of the time that we decided to skip sub-components of
   219  	// composite values. Ranges from 0 to 100.
   220  	skipCompareFraction uint8
   221  }
   222  
   223  // SetTunables accepts a TunableParams object, checks to make sure
   224  // that the settings in it are sane/logical, and applies the
   225  // parameters for any subsequent calls to the Generate function. This
   226  // function will issue a fatal error if any of the tunable params are
   227  // incorrect/insane (for example, a 'percentage' value outside the
   228  // range of 0-100).
   229  func SetTunables(t TunableParams) {
   230  	checkTunables(t)
   231  	tunables = t
   232  }
   233  
   234  var defaultTypeFractions = [9]uint8{
   235  	10, // struct
   236  	10, // array
   237  	10, // map
   238  	15, // pointer
   239  	20, // numeric
   240  	15, // float
   241  	5,  // complex
   242  	5,  // byte
   243  	10, // string
   244  }
   245  
   246  const (
   247  	// Param not address taken.
   248  	StructTfIdx = iota
   249  	ArrayTfIdx
   250  	MapTfIdx
   251  	PointerTfIdx
   252  	NumericTfIdx
   253  	FloatTfIdx
   254  	ComplexTfIdx
   255  	ByteTfIdx
   256  	StringTfIdx
   257  )
   258  
   259  var tunables = TunableParams{
   260  	nParmRange:            15,
   261  	nReturnRange:          7,
   262  	nStructFields:         7,
   263  	nArrayElements:        5,
   264  	sliceFraction:         50,
   265  	intBitRanges:          [4]uint8{30, 20, 20, 30},
   266  	floatBitRanges:        [2]uint8{50, 50},
   267  	unsignedRanges:        [2]uint8{50, 50},
   268  	blankPerc:             15,
   269  	structDepth:           3,
   270  	typeFractions:         defaultTypeFractions,
   271  	recurPerc:             20,
   272  	methodPerc:            10,
   273  	pointerMethodCallPerc: 50,
   274  	doReflectCall:         true,
   275  	doDefer:               true,
   276  	takeAddress:           true,
   277  	doFuncCallValues:      true,
   278  	takenFraction:         20,
   279  	deferFraction:         30,
   280  	funcCallValFraction:   5,
   281  	doSkipCompare:         true,
   282  	skipCompareFraction:   10,
   283  	addrFractions:         [4]uint8{50, 25, 15, 10},
   284  }
   285  
   286  func DefaultTunables() TunableParams {
   287  	return tunables
   288  }
   289  
   290  func checkTunables(t TunableParams) {
   291  	var s int = 0
   292  
   293  	for _, v := range t.intBitRanges {
   294  		s += int(v)
   295  	}
   296  	if s != 100 {
   297  		log.Fatal(errors.New("intBitRanges tunable does not sum to 100"))
   298  	}
   299  
   300  	s = 0
   301  	for _, v := range t.unsignedRanges {
   302  		s += int(v)
   303  	}
   304  	if s != 100 {
   305  		log.Fatal(errors.New("unsignedRanges tunable does not sum to 100"))
   306  	}
   307  
   308  	if t.blankPerc > 100 {
   309  		log.Fatal(errors.New("blankPerc bad value, over 100"))
   310  	}
   311  	if t.recurPerc > 100 {
   312  		log.Fatal(errors.New("recurPerc bad value, over 100"))
   313  	}
   314  	if t.methodPerc > 100 {
   315  		log.Fatal(errors.New("methodPerc bad value, over 100"))
   316  	}
   317  	if t.pointerMethodCallPerc > 100 {
   318  		log.Fatal(errors.New("pointerMethodCallPerc bad value, over 100"))
   319  	}
   320  
   321  	s = 0
   322  	for _, v := range t.floatBitRanges {
   323  		s += int(v)
   324  	}
   325  	if s != 100 {
   326  		log.Fatal(errors.New("floatBitRanges tunable does not sum to 100"))
   327  	}
   328  
   329  	s = 0
   330  	for _, v := range t.typeFractions {
   331  		s += int(v)
   332  	}
   333  	if s != 100 {
   334  		panic(errors.New("typeFractions tunable does not sum to 100"))
   335  	}
   336  
   337  	s = 0
   338  	for _, v := range t.addrFractions {
   339  		s += int(v)
   340  	}
   341  	if s != 100 {
   342  		log.Fatal(errors.New("addrFractions tunable does not sum to 100"))
   343  	}
   344  	if t.takenFraction > 100 {
   345  		log.Fatal(errors.New("takenFraction not between 0 and 100"))
   346  	}
   347  	if t.deferFraction > 100 {
   348  		log.Fatal(errors.New("deferFraction not between 0 and 100"))
   349  	}
   350  	if t.sliceFraction > 100 {
   351  		log.Fatal(errors.New("sliceFraction not between 0 and 100"))
   352  	}
   353  	if t.skipCompareFraction > 100 {
   354  		log.Fatal(errors.New("skipCompareFraction not between 0 and 100"))
   355  	}
   356  }
   357  
   358  func (t *TunableParams) DisableReflectionCalls() {
   359  	t.doReflectCall = false
   360  }
   361  
   362  func (t *TunableParams) DisableRecursiveCalls() {
   363  	t.recurPerc = 0
   364  }
   365  
   366  func (t *TunableParams) DisableMethodCalls() {
   367  	t.methodPerc = 0
   368  }
   369  
   370  func (t *TunableParams) DisableTakeAddr() {
   371  	t.takeAddress = false
   372  }
   373  
   374  func (t *TunableParams) DisableDefer() {
   375  	t.doDefer = false
   376  }
   377  
   378  func (t *TunableParams) LimitInputs(n int) error {
   379  	if n > 100 {
   380  		return fmt.Errorf("value %d passed to LimitInputs is too large *(max 100)", n)
   381  	}
   382  	if n < 0 {
   383  		return fmt.Errorf("value %d passed to LimitInputs is invalid", n)
   384  	}
   385  	t.nParmRange = uint8(n)
   386  	return nil
   387  }
   388  
   389  func (t *TunableParams) LimitOutputs(n int) error {
   390  	if n > 100 {
   391  		return fmt.Errorf("value %d passed to LimitOutputs is too large *(max 100)", n)
   392  	}
   393  	if n < 0 {
   394  		return fmt.Errorf("value %d passed to LimitOutputs is invalid", n)
   395  	}
   396  	t.nReturnRange = uint8(n)
   397  	return nil
   398  }
   399  
   400  // ParseMaskString parses a string of the form K,J,...,M-N,Q-R,...,Z
   401  // e.g. comma-separated integers or ranges of integers, returning the
   402  // result in a form suitable for FcnMask or PkgMask fields in a
   403  // Config. Here "tag" holds the mask flavor (fcn or pkg) and "arg" is
   404  // the string argument to be parsed.
   405  func ParseMaskString(arg string, tag string) (map[int]int, error) {
   406  	if arg == "" {
   407  		return nil, nil
   408  	}
   409  	verb(1, "%s mask is %s", tag, arg)
   410  	m := make(map[int]int)
   411  	ss := strings.Split(arg, ":")
   412  	for _, s := range ss {
   413  		if strings.Contains(s, "-") {
   414  			rng := strings.Split(s, "-")
   415  			if len(rng) != 2 {
   416  				return nil, fmt.Errorf("malformed range %s in %s mask arg", s, tag)
   417  			}
   418  			i, err := strconv.Atoi(rng[0])
   419  			if err != nil {
   420  				return nil, fmt.Errorf("malformed range value %s in %s mask arg", rng[0], tag)
   421  			}
   422  			j, err2 := strconv.Atoi(rng[1])
   423  			if err2 != nil {
   424  				return nil, fmt.Errorf("malformed range value %s in %s mask arg", rng[1], tag)
   425  			}
   426  			for k := i; k < j; k++ {
   427  				m[k] = 1
   428  			}
   429  		} else {
   430  			i, err := strconv.Atoi(s)
   431  			if err != nil {
   432  				return nil, fmt.Errorf("malformed value %s in %s mask arg", s, tag)
   433  			}
   434  			m[i] = 1
   435  		}
   436  	}
   437  	return m, nil
   438  }
   439  
   440  func writeCom(b *bytes.Buffer, i int) {
   441  	if i != 0 {
   442  		b.WriteString(", ")
   443  	}
   444  }
   445  
   446  var Verbctl int = 0
   447  
   448  func verb(vlevel int, s string, a ...interface{}) {
   449  	if Verbctl >= vlevel {
   450  		fmt.Printf(s, a...)
   451  		fmt.Printf("\n")
   452  	}
   453  }
   454  
   455  type funcdef struct {
   456  	idx         int
   457  	structdefs  []structparm
   458  	arraydefs   []arrayparm
   459  	typedefs    []typedefparm
   460  	mapdefs     []mapparm
   461  	mapkeytypes []parm
   462  	mapkeytmps  []string
   463  	mapkeyts    string
   464  	receiver    parm
   465  	params      []parm
   466  	returns     []parm
   467  	values      []int
   468  	dodefc      uint8
   469  	dodefp      []uint8
   470  	rstack      int
   471  	recur       bool
   472  	isMethod    bool
   473  }
   474  
   475  type genstate struct {
   476  	GenConfig
   477  	ipref string
   478  	//tag            string
   479  	//numtpk         int
   480  	pkidx int
   481  	errs  int
   482  	//pragma         string
   483  	//sforce         bool
   484  	//randctl        int
   485  	tunables       TunableParams
   486  	tstack         []TunableParams
   487  	derefFuncs     map[string]string
   488  	newDerefFuncs  []funcdesc
   489  	assignFuncs    map[string]string
   490  	newAssignFuncs []funcdesc
   491  	allocFuncs     map[string]string
   492  	newAllocFuncs  []funcdesc
   493  	genvalFuncs    map[string]string
   494  	newGenvalFuncs []funcdesc
   495  	globVars       map[string]string
   496  	newGlobVars    []funcdesc
   497  	wr             *wraprand
   498  }
   499  
   500  func (s *genstate) intFlavor() string {
   501  	which := uint8(s.wr.Intn(100))
   502  	if which < s.tunables.unsignedRanges[0] {
   503  		return "uint"
   504  	}
   505  	return "int"
   506  }
   507  
   508  func (s *genstate) intBits() uint32 {
   509  	which := uint8(s.wr.Intn(100))
   510  	var t uint8 = 0
   511  	var bits uint32 = 8
   512  	for _, v := range s.tunables.intBitRanges {
   513  		t += v
   514  		if which < t {
   515  			return bits
   516  		}
   517  		bits *= 2
   518  	}
   519  	return uint32(s.tunables.intBitRanges[3])
   520  }
   521  
   522  func (s *genstate) floatBits() uint32 {
   523  	which := uint8(s.wr.Intn(100))
   524  	if which < s.tunables.floatBitRanges[0] {
   525  		return uint32(32)
   526  	}
   527  	return uint32(64)
   528  }
   529  
   530  func (s *genstate) genAddrTaken() addrTakenHow {
   531  	which := uint8(s.wr.Intn(100))
   532  	res := notAddrTaken
   533  	var t uint8 = 0
   534  	for _, v := range s.tunables.addrFractions {
   535  		t += v
   536  		if which < t {
   537  			return res
   538  		}
   539  		res++
   540  	}
   541  	return notAddrTaken
   542  }
   543  
   544  func (s *genstate) pushTunables() {
   545  	s.tstack = append(s.tstack, s.tunables)
   546  }
   547  
   548  func (s *genstate) popTunables() {
   549  	if len(s.tstack) == 0 {
   550  		panic("untables stack underflow")
   551  	}
   552  	s.tunables = s.tstack[0]
   553  	s.tstack = s.tstack[1:]
   554  }
   555  
   556  // redistributeFraction accepts a value 'toIncorporate' and updates
   557  // 'typeFraction' to add in the values from 'toIncorporate' equally to
   558  // all slots not in 'avoid'. This is done by successively walking
   559  // through 'typeFraction' adding 1 to each non-avoid slot, then
   560  // repeating until we've added a total of 'toIncorporate' elements.
   561  // See precludeSelectedTypes below for more info.
   562  func (s *genstate) redistributeFraction(toIncorporate uint8, avoid []int) {
   563  	inavoid := func(j int) bool {
   564  		for _, k := range avoid {
   565  			if j == k {
   566  				return true
   567  			}
   568  		}
   569  		return false
   570  	}
   571  
   572  	doredis := func() {
   573  		for {
   574  			for i := range s.tunables.typeFractions {
   575  				if inavoid(i) {
   576  					continue
   577  				}
   578  				s.tunables.typeFractions[i]++
   579  				toIncorporate--
   580  				if toIncorporate == 0 {
   581  					return
   582  				}
   583  			}
   584  		}
   585  	}
   586  	doredis()
   587  	checkTunables(s.tunables)
   588  }
   589  
   590  // precludeSelectedTypes accepts a set of values (t, t2, ...)
   591  // corresponding to slots in 'typeFractions', sums up the values from
   592  // the slots, zeroes out the slots, and finally takes the values and
   593  // redistributes them equally to the other slots.  For example,
   594  // suppose 'typeFractions' starts as [10, 10, 10, 15, 20, 15, 5, 5, 10],
   595  // then we decide we want to eliminate or 'knock out' map types and
   596  // pointer types (slots 2 and 3 in the array above) going forward.  To
   597  // restore the invariant that values in 'typeFractions' sum to 100, we
   598  // take the values from slots 2 and 3 (a total of 25) and evenly
   599  // distribute those values to the other slots in the array.
   600  func (s *genstate) precludeSelectedTypes(t int, t2 ...int) {
   601  	avoid := []int{t}
   602  	avoid = append(avoid, t2...)
   603  	f := uint8(0)
   604  	for _, idx := range avoid {
   605  		f += s.tunables.typeFractions[idx]
   606  		s.tunables.typeFractions[idx] = 0
   607  	}
   608  	s.redistributeFraction(f, avoid)
   609  }
   610  
   611  func (s *genstate) GenMapKeyType(f *funcdef, depth int, pidx int) parm {
   612  	s.pushTunables()
   613  	defer s.popTunables()
   614  	// maps we can't allow at all; pointers might be possible but
   615  	//  would be too much work to arrange. Avoid slices as well.
   616  	s.tunables.sliceFraction = 0
   617  	s.precludeSelectedTypes(MapTfIdx, PointerTfIdx)
   618  	return s.GenParm(f, depth+1, false, pidx)
   619  }
   620  
   621  func (s *genstate) GenParm(f *funcdef, depth int, mkctl bool, pidx int) parm {
   622  
   623  	// Enforcement for struct/array/map/pointer array nesting depth.
   624  	toodeep := depth >= int(s.tunables.structDepth)
   625  	if toodeep {
   626  		s.pushTunables()
   627  		defer s.popTunables()
   628  		s.precludeSelectedTypes(StructTfIdx, ArrayTfIdx, MapTfIdx, PointerTfIdx)
   629  	}
   630  
   631  	// Convert tf into a cumulative sum
   632  	tf := s.tunables.typeFractions
   633  	sum := uint8(0)
   634  	for i := 0; i < len(tf); i++ {
   635  		sum += tf[i]
   636  		tf[i] = sum
   637  	}
   638  
   639  	isblank := uint8(s.wr.Intn(100)) < s.tunables.blankPerc
   640  	addrTaken := notAddrTaken
   641  	if depth == 0 && tunables.takeAddress && !isblank {
   642  		addrTaken = s.genAddrTaken()
   643  	}
   644  	isGenValFunc := tunables.doFuncCallValues &&
   645  		uint8(s.wr.Intn(100)) < s.tunables.funcCallValFraction
   646  
   647  	// Make adjusted selection (pick a bucket within tf)
   648  	which := uint8(s.wr.Intn(100))
   649  	verb(3, "which=%d", which)
   650  	var retval parm
   651  	switch {
   652  	case which < tf[StructTfIdx]:
   653  		{
   654  			if toodeep {
   655  				panic("should not be here")
   656  			}
   657  			var sp structparm
   658  			ns := len(f.structdefs)
   659  			sp.sname = fmt.Sprintf("StructF%dS%d", f.idx, ns)
   660  			sp.qname = fmt.Sprintf("%s.StructF%dS%d",
   661  				s.checkerPkg(pidx), f.idx, ns)
   662  			f.structdefs = append(f.structdefs, sp)
   663  			tnf := int64(s.tunables.nStructFields) / int64(depth+1)
   664  			nf := int(s.wr.Intn(tnf))
   665  			for fi := 0; fi < nf; fi++ {
   666  				fp := s.GenParm(f, depth+1, false, pidx)
   667  				skComp := tunables.doSkipCompare &&
   668  					uint8(s.wr.Intn(100)) < s.tunables.skipCompareFraction
   669  				if skComp && checkableElements(fp) != 0 {
   670  					fp.SetSkipCompare(SkipAll)
   671  				}
   672  				sp.fields = append(sp.fields, fp)
   673  			}
   674  			f.structdefs[ns] = sp
   675  			retval = &sp
   676  		}
   677  	case which < tf[ArrayTfIdx]:
   678  		{
   679  			if toodeep {
   680  				panic("should not be here")
   681  			}
   682  			var ap arrayparm
   683  			ns := len(f.arraydefs)
   684  			nel := uint8(s.wr.Intn(int64(s.tunables.nArrayElements)))
   685  			issl := uint8(s.wr.Intn(100)) < s.tunables.sliceFraction
   686  			ap.aname = fmt.Sprintf("ArrayF%dS%dE%d", f.idx, ns, nel)
   687  			ap.qname = fmt.Sprintf("%s.ArrayF%dS%dE%d", s.checkerPkg(pidx),
   688  				f.idx, ns, nel)
   689  			f.arraydefs = append(f.arraydefs, ap)
   690  			ap.nelements = nel
   691  			ap.slice = issl
   692  			ap.eltype = s.GenParm(f, depth+1, false, pidx)
   693  			ap.eltype.SetBlank(false)
   694  			skComp := tunables.doSkipCompare &&
   695  				uint8(s.wr.Intn(100)) < s.tunables.skipCompareFraction
   696  			if skComp && checkableElements(ap.eltype) != 0 {
   697  				if issl {
   698  					ap.SetSkipCompare(SkipPayload)
   699  				}
   700  			}
   701  			f.arraydefs[ns] = ap
   702  			retval = &ap
   703  		}
   704  	case which < tf[MapTfIdx]:
   705  		{
   706  			if toodeep {
   707  				panic("should not be here")
   708  			}
   709  			var mp mapparm
   710  			ns := len(f.mapdefs)
   711  
   712  			// append early, since calls below might also append
   713  			f.mapdefs = append(f.mapdefs, mp)
   714  			f.mapkeytmps = append(f.mapkeytmps, "")
   715  			f.mapkeytypes = append(f.mapkeytypes, mp.keytype)
   716  			mp.aname = fmt.Sprintf("MapF%dM%d", f.idx, ns)
   717  			if f.mapkeyts == "" {
   718  				f.mapkeyts = fmt.Sprintf("MapKeysF%d", f.idx)
   719  			}
   720  			mp.qname = fmt.Sprintf("%s.MapF%dM%d", s.checkerPkg(pidx),
   721  				f.idx, ns)
   722  			mkt := fmt.Sprintf("Mk%dt%d", f.idx, ns)
   723  			mp.keytmp = mkt
   724  			mk := s.GenMapKeyType(f, depth+1, pidx)
   725  			mp.keytype = mk
   726  			mp.valtype = s.GenParm(f, depth+1, false, pidx)
   727  			mp.valtype.SetBlank(false)
   728  			mp.keytype.SetBlank(false)
   729  			// now update the previously appended placeholders
   730  			f.mapdefs[ns] = mp
   731  			f.mapkeytypes[ns] = mk
   732  			f.mapkeytmps[ns] = mkt
   733  			retval = &mp
   734  		}
   735  	case which < tf[PointerTfIdx]:
   736  		{
   737  			if toodeep {
   738  				panic("should not be here")
   739  			}
   740  			pp := mkPointerParm(s.GenParm(f, depth+1, false, pidx))
   741  			retval = &pp
   742  		}
   743  	case which < tf[NumericTfIdx]:
   744  		{
   745  			var ip numparm
   746  			ip.tag = s.intFlavor()
   747  			ip.widthInBits = s.intBits()
   748  			if mkctl {
   749  				ip.ctl = true
   750  			}
   751  			retval = &ip
   752  		}
   753  	case which < tf[FloatTfIdx]:
   754  		{
   755  			var fp numparm
   756  			fp.tag = "float"
   757  			fp.widthInBits = s.floatBits()
   758  			retval = &fp
   759  		}
   760  	case which < tf[ComplexTfIdx]:
   761  		{
   762  			var fp numparm
   763  			fp.tag = "complex"
   764  			fp.widthInBits = s.floatBits() * 2
   765  			retval = &fp
   766  		}
   767  	case which < tf[ByteTfIdx]:
   768  		{
   769  			var bp numparm
   770  			bp.tag = "byte"
   771  			bp.widthInBits = 8
   772  			retval = &bp
   773  		}
   774  	case which < tf[StringTfIdx]:
   775  		{
   776  			var sp stringparm
   777  			sp.tag = "string"
   778  			skComp := tunables.doSkipCompare &&
   779  				uint8(s.wr.Intn(100)) < s.tunables.skipCompareFraction
   780  			if skComp {
   781  				sp.SetSkipCompare(SkipPayload)
   782  			}
   783  			retval = &sp
   784  		}
   785  	default:
   786  		{
   787  			// fallback
   788  			var ip numparm
   789  			ip.tag = "uint"
   790  			ip.widthInBits = 8
   791  			retval = &ip
   792  		}
   793  	}
   794  	if !mkctl {
   795  		retval.SetBlank(isblank)
   796  	}
   797  	retval.SetAddrTaken(addrTaken)
   798  	retval.SetIsGenVal(isGenValFunc)
   799  	return retval
   800  }
   801  
   802  func (s *genstate) GenReturn(f *funcdef, depth int, pidx int) parm {
   803  	return s.GenParm(f, depth, false, pidx)
   804  }
   805  
   806  // GenFunc cooks up the random signature (and other attributes) of a
   807  // given checker function, returning a funcdef object that describes
   808  // the new fcn.
   809  func (s *genstate) GenFunc(fidx int, pidx int) *funcdef {
   810  	f := new(funcdef)
   811  	f.idx = fidx
   812  	numParams := int(s.wr.Intn(int64(1 + int(s.tunables.nParmRange))))
   813  	numReturns := int(s.wr.Intn(int64(1 + int(s.tunables.nReturnRange))))
   814  	f.recur = uint8(s.wr.Intn(100)) < s.tunables.recurPerc
   815  	f.isMethod = uint8(s.wr.Intn(100)) < s.tunables.methodPerc
   816  	genReceiverType := func() {
   817  		// Receiver type can't be pointer type. Temporarily update
   818  		// tunables to eliminate that possibility.
   819  		s.pushTunables()
   820  		defer s.popTunables()
   821  		s.precludeSelectedTypes(PointerTfIdx)
   822  		target := s.GenParm(f, 0, false, pidx)
   823  		target.SetBlank(false)
   824  		f.receiver = s.makeTypedefParm(f, target, pidx)
   825  		if f.receiver.IsBlank() {
   826  			f.recur = false
   827  		}
   828  	}
   829  	if f.isMethod {
   830  		genReceiverType()
   831  	}
   832  	needControl := f.recur
   833  	f.dodefc = uint8(s.wr.Intn(100))
   834  	pTaken := uint8(s.wr.Intn(100)) < s.tunables.takenFraction
   835  	for pi := 0; pi < numParams; pi++ {
   836  		newparm := s.GenParm(f, 0, needControl, pidx)
   837  		if !pTaken {
   838  			newparm.SetAddrTaken(notAddrTaken)
   839  		}
   840  		if newparm.IsControl() {
   841  			needControl = false
   842  		}
   843  		f.params = append(f.params, newparm)
   844  		f.dodefp = append(f.dodefp, uint8(s.wr.Intn(100)))
   845  	}
   846  	if f.recur && needControl {
   847  		f.recur = false
   848  	}
   849  
   850  	rTaken := uint8(s.wr.Intn(100)) < s.tunables.takenFraction
   851  	for ri := 0; ri < numReturns; ri++ {
   852  		r := s.GenReturn(f, 0, pidx)
   853  		if !rTaken {
   854  			r.SetAddrTaken(notAddrTaken)
   855  		}
   856  		f.returns = append(f.returns, r)
   857  	}
   858  	spw := uint(s.wr.Intn(11))
   859  	rstack := 1 << spw
   860  	if rstack < 4 {
   861  		rstack = 4
   862  	}
   863  	f.rstack = rstack
   864  	return f
   865  }
   866  
   867  func genDeref(p parm) (parm, string) {
   868  	curp := p
   869  	star := ""
   870  	for {
   871  		if pp, ok := curp.(*pointerparm); ok {
   872  			star += "*"
   873  			curp = pp.totype
   874  		} else {
   875  			return curp, star
   876  		}
   877  	}
   878  }
   879  
   880  func (s *genstate) eqFuncRef(f *funcdef, t parm, caller bool) string {
   881  	cp := ""
   882  	if f.mapkeyts != "" {
   883  		cp = "mkt."
   884  	} else if caller {
   885  		cp = s.checkerPkg(s.pkidx) + "."
   886  	}
   887  	return cp + "Equal" + t.TypeName()
   888  }
   889  
   890  // emitCompareFunc creates an 'equals' function for a specific
   891  // generated type (this is basically a way to compare objects that
   892  // contain pointer fields / pointery things).
   893  func (s *genstate) emitCompareFunc(f *funcdef, b *bytes.Buffer, p parm) {
   894  	if !p.HasPointer() {
   895  		return
   896  	}
   897  
   898  	tn := p.TypeName()
   899  	b.WriteString(fmt.Sprintf("// equal func for %s\n", tn))
   900  	b.WriteString("//go:noinline\n")
   901  	rcvr := ""
   902  	if f.mapkeyts != "" {
   903  		rcvr = fmt.Sprintf("(mkt *%s) ", f.mapkeyts)
   904  	}
   905  	b.WriteString(fmt.Sprintf("func %sEqual%s(left %s, right %s) bool {\n", rcvr, tn, tn, tn))
   906  	b.WriteString("  return ")
   907  	numel := p.NumElements()
   908  	ncmp := 0
   909  	for i := 0; i < numel; i++ {
   910  		lelref, lelparm := p.GenElemRef(i, "left")
   911  		relref, _ := p.GenElemRef(i, "right")
   912  		if lelref == "" || lelref == "_" {
   913  			continue
   914  		}
   915  		basep, star := genDeref(lelparm)
   916  		// Handle *p where p is an empty struct.
   917  		if basep.NumElements() == 0 {
   918  			continue
   919  		}
   920  		if ncmp != 0 {
   921  			b.WriteString("  && ")
   922  		}
   923  		ncmp++
   924  		if basep.HasPointer() {
   925  			efn := s.eqFuncRef(f, basep, false)
   926  			b.WriteString(fmt.Sprintf(" %s(%s%s, %s%s)", efn, star, lelref, star, relref))
   927  		} else {
   928  			b.WriteString(fmt.Sprintf("%s%s == %s%s", star, lelref, star, relref))
   929  		}
   930  	}
   931  	if ncmp == 0 {
   932  		b.WriteString("true")
   933  	}
   934  	b.WriteString("\n}\n\n")
   935  }
   936  
   937  // emitStructAndArrayDefs writes out definitions of the random types
   938  // we happened to cook up while generating code for a specific
   939  // function pair.
   940  func (s *genstate) emitStructAndArrayDefs(f *funcdef, b *bytes.Buffer) {
   941  	for _, str := range f.structdefs {
   942  		b.WriteString(fmt.Sprintf("type %s struct {\n", str.sname))
   943  		for fi, sp := range str.fields {
   944  			sp.Declare(b, "  "+str.FieldName(fi), "\n", false)
   945  		}
   946  		b.WriteString("}\n\n")
   947  		s.emitCompareFunc(f, b, &str)
   948  	}
   949  	for _, a := range f.arraydefs {
   950  		elems := fmt.Sprintf("%d", a.nelements)
   951  		if a.slice {
   952  			elems = ""
   953  		}
   954  		b.WriteString(fmt.Sprintf("type %s [%s]%s\n\n", a.aname,
   955  			elems, a.eltype.TypeName()))
   956  		s.emitCompareFunc(f, b, &a)
   957  	}
   958  	for _, a := range f.mapdefs {
   959  		b.WriteString(fmt.Sprintf("type %s map[%s]%s\n\n", a.aname,
   960  			a.keytype.TypeName(), a.valtype.TypeName()))
   961  		s.emitCompareFunc(f, b, &a)
   962  	}
   963  	for _, td := range f.typedefs {
   964  		b.WriteString(fmt.Sprintf("type %s %s\n\n", td.aname,
   965  			td.target.TypeName()))
   966  		s.emitCompareFunc(f, b, &td)
   967  	}
   968  	if f.mapkeyts != "" {
   969  		b.WriteString(fmt.Sprintf("type %s struct {\n", f.mapkeyts))
   970  		for i := range f.mapkeytypes {
   971  			f.mapkeytypes[i].Declare(b, "  "+f.mapkeytmps[i], "\n", false)
   972  		}
   973  		b.WriteString("}\n\n")
   974  	}
   975  }
   976  
   977  // GenValue method of genstate wraps the parm method of the same
   978  // name, but optionally returns a call to a function to produce
   979  // the value as opposed to a literal value.
   980  func (s *genstate) GenValue(f *funcdef, p parm, value int, caller bool) (string, int) {
   981  	var valstr string
   982  	valstr, value = p.GenValue(s, f, value, caller)
   983  	if !s.tunables.doFuncCallValues || !p.IsGenVal() || caller {
   984  		return valstr, value
   985  	}
   986  
   987  	mkInvoc := func(fname string) string {
   988  		meth := ""
   989  		if f.mapkeyts != "" {
   990  			meth = "mkt."
   991  		}
   992  		return fmt.Sprintf("%s%s()", meth, fname)
   993  	}
   994  
   995  	b := bytes.NewBuffer(nil)
   996  	p.Declare(b, "x", "", false)
   997  	h := sha1.New()
   998  	h.Write([]byte(valstr))
   999  	h.Write(b.Bytes())
  1000  	if f.mapkeyts != "" {
  1001  		h.Write([]byte(f.mapkeyts))
  1002  	}
  1003  	h.Write(b.Bytes())
  1004  	bs := h.Sum(nil)
  1005  	hashstr := fmt.Sprintf("%x", bs)
  1006  	b.WriteString(hashstr)
  1007  	tag := b.String()
  1008  	fname, ok := s.genvalFuncs[tag]
  1009  	if ok {
  1010  		return mkInvoc(fname), value
  1011  	}
  1012  
  1013  	fname = fmt.Sprintf("genval_%d", len(s.genvalFuncs))
  1014  	s.newGenvalFuncs = append(s.newGenvalFuncs, funcdesc{p: p, name: fname, tag: tag, payload: valstr})
  1015  	s.genvalFuncs[tag] = fname
  1016  	return mkInvoc(fname), value
  1017  }
  1018  
  1019  func (s *genstate) emitMapKeyTmps(f *funcdef, b *bytes.Buffer, pidx int, value int, caller bool) int {
  1020  	if f.mapkeyts == "" {
  1021  		return value
  1022  	}
  1023  	// map key tmps
  1024  	cp := ""
  1025  	if caller {
  1026  		cp = s.checkerPkg(pidx) + "."
  1027  	}
  1028  	b.WriteString("  var mkt " + cp + f.mapkeyts + "\n")
  1029  	for i, t := range f.mapkeytypes {
  1030  		var keystr string
  1031  		keystr, value = s.GenValue(f, t, value, caller)
  1032  		tname := f.mapkeytmps[i]
  1033  		b.WriteString(fmt.Sprintf("  %s := %s\n", tname, keystr))
  1034  		b.WriteString(fmt.Sprintf("  mkt.%s = %s\n", tname, tname))
  1035  	}
  1036  	return value
  1037  }
  1038  
  1039  func (s *genstate) emitCheckReturnsInCaller(f *funcdef, b *bytes.Buffer, pidx int, reflectCall bool) {
  1040  	cm := f.complexityMeasure()
  1041  	rvalp := func(ri int) string {
  1042  		if reflectCall {
  1043  			return fmt.Sprintf("rr%dv", ri)
  1044  		}
  1045  		return fmt.Sprintf("r%d", ri)
  1046  	}
  1047  	failTag := "\"return\""
  1048  	if reflectCall {
  1049  		failTag = "\"reflect return\""
  1050  	}
  1051  	for ri, rp := range f.returns {
  1052  		if reflectCall {
  1053  			b.WriteString(fmt.Sprintf("  rr%di := rvslice[%d].Interface()\n", ri, ri))
  1054  			b.WriteString(fmt.Sprintf("  rr%dv:= rr%di.(", ri, ri))
  1055  			rp.Declare(b, "", "", true)
  1056  			b.WriteString(")\n")
  1057  		}
  1058  		pfc := ""
  1059  		curp, star := genDeref(rp)
  1060  		// Handle *p where p is an empty struct.
  1061  		if curp.NumElements() == 0 {
  1062  			b.WriteString(fmt.Sprintf("  _, _ = %s, c%d // zero size\n", rvalp(ri), ri))
  1063  			continue
  1064  		}
  1065  		if star != "" {
  1066  			pfc = fmt.Sprintf("ParamFailCount[%d] == 0 && ", pidx)
  1067  		}
  1068  		if curp.HasPointer() {
  1069  			efn := "!" + s.eqFuncRef(f, curp, true)
  1070  			b.WriteString(fmt.Sprintf("  if %s%s(%s%s, %sc%d) {\n", pfc, efn, star, rvalp(ri), star, ri))
  1071  		} else {
  1072  			b.WriteString(fmt.Sprintf("  if %s%s%s != %sc%d {\n", pfc, star, rvalp(ri), star, ri))
  1073  		}
  1074  		b.WriteString(fmt.Sprintf("    NoteFailure(%d, %d, %d, \"%s\", %s, %d, true, uint64(0))\n", cm, pidx, f.idx, s.checkerPkg(pidx), failTag, ri))
  1075  		b.WriteString("  }\n")
  1076  	}
  1077  }
  1078  
  1079  func (s *genstate) emitCaller(f *funcdef, b *bytes.Buffer, pidx int) {
  1080  
  1081  	b.WriteString(fmt.Sprintf("func %s%d(mode string) {\n", CallerName, f.idx))
  1082  
  1083  	b.WriteString(fmt.Sprintf("  BeginFcn(%d)\n", pidx))
  1084  
  1085  	if s.EmitBad == 1 {
  1086  		if s.BadPackageIdx == pidx && s.BadFuncIdx == f.idx {
  1087  			b.WriteString("  bad code here, should cause build failure <<==\n")
  1088  		}
  1089  	}
  1090  
  1091  	var value int = 1
  1092  
  1093  	s.wr.Checkpoint("before mapkeytmps")
  1094  	value = s.emitMapKeyTmps(f, b, pidx, value, true)
  1095  
  1096  	// generate return constants
  1097  	s.wr.Checkpoint("before return constants")
  1098  	for ri, r := range f.returns {
  1099  		rc := fmt.Sprintf("c%d", ri)
  1100  		value = s.emitVarAssign(f, b, r, rc, value, true)
  1101  	}
  1102  
  1103  	// generate param constants
  1104  	s.wr.Checkpoint("before param constants")
  1105  	for pi, p := range f.params {
  1106  		verb(4, "emitCaller gen p%d value=%d", pi, value)
  1107  		if p.IsControl() {
  1108  			_ = uint8(s.wr.Intn(100)) < 50
  1109  			p.Declare(b, fmt.Sprintf("  var p%d ", pi), " = 10\n", true)
  1110  		} else {
  1111  			pc := fmt.Sprintf("p%d", pi)
  1112  			value = s.emitVarAssign(f, b, p, pc, value, true)
  1113  		}
  1114  		f.values = append(f.values, value)
  1115  	}
  1116  
  1117  	// generate receiver constant if applicable
  1118  	if f.isMethod {
  1119  		s.wr.Checkpoint("before receiver constant")
  1120  		f.receiver.Declare(b, "  var rcvr", "\n", true)
  1121  		valstr, value := s.GenValue(f, f.receiver, value, true)
  1122  		b.WriteString(fmt.Sprintf("  rcvr = %s\n", valstr))
  1123  		f.values = append(f.values, value)
  1124  	}
  1125  
  1126  	b.WriteString(fmt.Sprintf("  Mode[%d] = \"\"\n", pidx))
  1127  
  1128  	// calling code
  1129  	b.WriteString(fmt.Sprintf("  // %d returns %d params\n",
  1130  		len(f.returns), len(f.params)))
  1131  	if s.ForceStackGrowth {
  1132  		b.WriteString("  hackStack() // force stack growth on next call\n")
  1133  	}
  1134  	b.WriteString("  if mode == \"normal\" {\n")
  1135  	b.WriteString("  ")
  1136  	for ri := range f.returns {
  1137  		writeCom(b, ri)
  1138  		b.WriteString(fmt.Sprintf("r%d", ri))
  1139  	}
  1140  	if len(f.returns) > 0 {
  1141  		b.WriteString(" := ")
  1142  	}
  1143  	pref := s.checkerPkg(pidx)
  1144  	if f.isMethod {
  1145  		pref = "rcvr"
  1146  	}
  1147  	b.WriteString(fmt.Sprintf("%s.Test%d(", pref, f.idx))
  1148  	for pi := range f.params {
  1149  		writeCom(b, pi)
  1150  		b.WriteString(fmt.Sprintf("p%d", pi))
  1151  	}
  1152  	b.WriteString(")\n")
  1153  
  1154  	// check values returned (normal call case)
  1155  	s.emitCheckReturnsInCaller(f, b, pidx, false /* not a reflect call */)
  1156  	b.WriteString("  }") // end of 'if normal call' block
  1157  	if s.tunables.doReflectCall {
  1158  		b.WriteString("else {\n") // beginning of reflect call block
  1159  		// now make the same call via reflection
  1160  		b.WriteString("  // same call via reflection\n")
  1161  		b.WriteString(fmt.Sprintf("  Mode[%d] = \"reflect\"\n", pidx))
  1162  		if f.isMethod {
  1163  			b.WriteString("  rcv := reflect.ValueOf(rcvr)\n")
  1164  			b.WriteString(fmt.Sprintf("  rc := rcv.MethodByName(\"Test%d\")\n", f.idx))
  1165  		} else {
  1166  			b.WriteString(fmt.Sprintf("  rc := reflect.ValueOf(%s.Test%d)\n",
  1167  				s.checkerPkg(pidx), f.idx))
  1168  		}
  1169  		b.WriteString("  ")
  1170  		if len(f.returns) > 0 {
  1171  			b.WriteString("rvslice := ")
  1172  		}
  1173  		b.WriteString("  rc.Call([]reflect.Value{")
  1174  		for pi := range f.params {
  1175  			writeCom(b, pi)
  1176  			b.WriteString(fmt.Sprintf("reflect.ValueOf(p%d)", pi))
  1177  		}
  1178  		b.WriteString("})\n")
  1179  
  1180  		// check values returned (reflect call case)
  1181  		s.emitCheckReturnsInCaller(f, b, pidx, true /* is a reflect call */)
  1182  		b.WriteString("}\n") // end of reflect call block
  1183  	}
  1184  
  1185  	b.WriteString(fmt.Sprintf("\n  EndFcn(%d)\n", pidx))
  1186  
  1187  	b.WriteString("}\n\n")
  1188  }
  1189  
  1190  func checkableElements(p parm) int {
  1191  	if p.IsBlank() {
  1192  		return 0
  1193  	}
  1194  	sp, isstruct := p.(*structparm)
  1195  	if isstruct {
  1196  		s := 0
  1197  		for fi := range sp.fields {
  1198  			s += checkableElements(sp.fields[fi])
  1199  		}
  1200  		return s
  1201  	}
  1202  	ap, isarray := p.(*arrayparm)
  1203  	if isarray {
  1204  		if ap.nelements == 0 {
  1205  			return 0
  1206  		}
  1207  		return int(ap.nelements) * checkableElements(ap.eltype)
  1208  	}
  1209  	return 1
  1210  }
  1211  
  1212  // funcdesc describes an auto-generated helper function or global
  1213  // variable, such as an allocation function (returns new(T)) or a
  1214  // pointer assignment function (assigns value of T to type *T). Here
  1215  // 'p' is a param type T, 'pp' is a pointer type *T, 'name' is the
  1216  // name within the generated code of the function or variable and
  1217  // 'tag' is a descriptive tag used to look up the entity in a map (so
  1218  // that we don't have to emit multiple copies of a function that
  1219  // assigns int to *int, for example).
  1220  type funcdesc struct {
  1221  	p       parm
  1222  	pp      parm
  1223  	name    string
  1224  	tag     string
  1225  	payload string
  1226  }
  1227  
  1228  func (s *genstate) emitDerefFuncs(b *bytes.Buffer, emit bool) {
  1229  	b.WriteString("// dereference helpers\n")
  1230  	for _, fd := range s.newDerefFuncs {
  1231  		if !emit {
  1232  			b.WriteString(fmt.Sprintf("\n// skip derefunc %s\n", fd.name))
  1233  			delete(s.derefFuncs, fd.tag)
  1234  			continue
  1235  		}
  1236  		b.WriteString("\n//go:noinline\n")
  1237  		b.WriteString(fmt.Sprintf("func %s(", fd.name))
  1238  		fd.pp.Declare(b, "x", "", false)
  1239  		b.WriteString(") ")
  1240  		fd.p.Declare(b, "", "", false)
  1241  		b.WriteString(" {\n")
  1242  		b.WriteString("  return *x\n")
  1243  		b.WriteString("}\n")
  1244  	}
  1245  	s.newDerefFuncs = nil
  1246  }
  1247  
  1248  func (s *genstate) emitAssignFuncs(b *bytes.Buffer, emit bool) {
  1249  	b.WriteString("// assign helpers\n")
  1250  	for _, fd := range s.newAssignFuncs {
  1251  		if !emit {
  1252  			b.WriteString(fmt.Sprintf("\n// skip assignfunc %s\n", fd.name))
  1253  			delete(s.assignFuncs, fd.tag)
  1254  			continue
  1255  		}
  1256  		b.WriteString("\n//go:noinline\n")
  1257  		b.WriteString(fmt.Sprintf("func %s(", fd.name))
  1258  		fd.pp.Declare(b, "x", "", false)
  1259  		b.WriteString(", ")
  1260  		fd.p.Declare(b, "v", "", false)
  1261  		b.WriteString(") {\n")
  1262  		b.WriteString("  *x = v\n")
  1263  		b.WriteString("}\n")
  1264  	}
  1265  	s.newAssignFuncs = nil
  1266  }
  1267  
  1268  func (s *genstate) emitNewFuncs(b *bytes.Buffer, emit bool) {
  1269  	b.WriteString("// 'new' funcs\n")
  1270  	for _, fd := range s.newAllocFuncs {
  1271  		if !emit {
  1272  			b.WriteString(fmt.Sprintf("\n// skip newfunc %s\n", fd.name))
  1273  			delete(s.allocFuncs, fd.tag)
  1274  			continue
  1275  		}
  1276  		b.WriteString("\n//go:noinline\n")
  1277  		b.WriteString(fmt.Sprintf("func %s(", fd.name))
  1278  		fd.p.Declare(b, "i", "", false)
  1279  		b.WriteString(") ")
  1280  		fd.pp.Declare(b, "", "", false)
  1281  		b.WriteString(" {\n")
  1282  		b.WriteString("  x := new(")
  1283  		fd.p.Declare(b, "", "", false)
  1284  		b.WriteString(")\n")
  1285  		b.WriteString("  *x = i\n")
  1286  		b.WriteString("  return x\n")
  1287  		b.WriteString("}\n\n")
  1288  	}
  1289  	s.newAllocFuncs = nil
  1290  }
  1291  
  1292  func (s *genstate) emitGlobalVars(b *bytes.Buffer, emit bool) {
  1293  	b.WriteString("// global vars\n")
  1294  	for _, fd := range s.newGlobVars {
  1295  		if !emit {
  1296  			b.WriteString(fmt.Sprintf("\n// skip gvar %s\n", fd.name))
  1297  			delete(s.globVars, fd.tag)
  1298  			continue
  1299  		}
  1300  		b.WriteString("var ")
  1301  		fd.pp.Declare(b, fd.name, "", false)
  1302  		b.WriteString("\n")
  1303  	}
  1304  	s.newGlobVars = nil
  1305  	b.WriteString("\n")
  1306  }
  1307  
  1308  func (s *genstate) emitGenValFuncs(f *funcdef, b *bytes.Buffer, emit bool) {
  1309  	b.WriteString("// genval helpers\n")
  1310  	for _, fd := range s.newGenvalFuncs {
  1311  		if !emit {
  1312  			b.WriteString(fmt.Sprintf("\n// skip genvalfunc %s\n", fd.name))
  1313  			delete(s.genvalFuncs, fd.tag)
  1314  			continue
  1315  		}
  1316  		b.WriteString("\n//go:noinline\n")
  1317  		rcvr := ""
  1318  		if f.mapkeyts != "" {
  1319  			rcvr = fmt.Sprintf("(mkt *%s) ", f.mapkeyts)
  1320  		}
  1321  		b.WriteString(fmt.Sprintf("func %s%s() ", rcvr, fd.name))
  1322  		fd.p.Declare(b, "", "", false)
  1323  		b.WriteString(" {\n")
  1324  		if f.mapkeyts != "" {
  1325  			contained := containedParms(fd.p)
  1326  			for _, cp := range contained {
  1327  				mp, ismap := cp.(*mapparm)
  1328  				if ismap {
  1329  					b.WriteString(fmt.Sprintf("  %s := mkt.%s\n",
  1330  						mp.keytmp, mp.keytmp))
  1331  					b.WriteString(fmt.Sprintf("  _ = %s\n", mp.keytmp))
  1332  				}
  1333  			}
  1334  		}
  1335  		b.WriteString(fmt.Sprintf("  return %s\n", fd.payload))
  1336  		b.WriteString("}\n")
  1337  	}
  1338  	s.newGenvalFuncs = nil
  1339  }
  1340  
  1341  func (s *genstate) emitAddrTakenHelpers(f *funcdef, b *bytes.Buffer, emit bool) {
  1342  	b.WriteString("// begin addr taken helpers\n")
  1343  	s.emitDerefFuncs(b, emit)
  1344  	s.emitAssignFuncs(b, emit)
  1345  	s.emitNewFuncs(b, emit)
  1346  	s.emitGlobalVars(b, emit)
  1347  	s.emitGenValFuncs(f, b, emit)
  1348  	b.WriteString("// end addr taken helpers\n")
  1349  }
  1350  
  1351  func (s *genstate) genGlobVar(p parm) string {
  1352  	var pp parm
  1353  	ppp := mkPointerParm(p)
  1354  	pp = &ppp
  1355  	b := bytes.NewBuffer(nil)
  1356  	pp.Declare(b, "gv", "", false)
  1357  	tag := b.String()
  1358  	gv, ok := s.globVars[tag]
  1359  	if ok {
  1360  		return gv
  1361  	}
  1362  	gv = fmt.Sprintf("gvar_%d", len(s.globVars))
  1363  	s.newGlobVars = append(s.newGlobVars, funcdesc{pp: pp, p: p, name: gv, tag: tag})
  1364  	s.globVars[tag] = gv
  1365  	return gv
  1366  }
  1367  
  1368  func (s *genstate) genParamDerefFunc(p parm) string {
  1369  	var pp parm
  1370  	ppp := mkPointerParm(p)
  1371  	pp = &ppp
  1372  	b := bytes.NewBuffer(nil)
  1373  	pp.Declare(b, "x", "", false)
  1374  	tag := b.String()
  1375  	f, ok := s.derefFuncs[tag]
  1376  	if ok {
  1377  		return f
  1378  	}
  1379  	f = fmt.Sprintf("deref_%d", len(s.derefFuncs))
  1380  	s.newDerefFuncs = append(s.newDerefFuncs, funcdesc{pp: pp, p: p, name: f, tag: tag})
  1381  	s.derefFuncs[tag] = f
  1382  	return f
  1383  }
  1384  
  1385  func (s *genstate) genAssignFunc(p parm) string {
  1386  	var pp parm
  1387  	ppp := mkPointerParm(p)
  1388  	pp = &ppp
  1389  	b := bytes.NewBuffer(nil)
  1390  	pp.Declare(b, "x", "", false)
  1391  	tag := b.String()
  1392  	f, ok := s.assignFuncs[tag]
  1393  	if ok {
  1394  		return f
  1395  	}
  1396  	f = fmt.Sprintf("retassign_%d", len(s.assignFuncs))
  1397  	s.newAssignFuncs = append(s.newAssignFuncs, funcdesc{pp: pp, p: p, name: f, tag: tag})
  1398  	s.assignFuncs[tag] = f
  1399  	return f
  1400  }
  1401  
  1402  func (s *genstate) genAllocFunc(p parm) string {
  1403  	var pp parm
  1404  	ppp := mkPointerParm(p)
  1405  	pp = &ppp
  1406  	b := bytes.NewBuffer(nil)
  1407  	pp.Declare(b, "x", "", false)
  1408  	tag := b.String()
  1409  	f, ok := s.allocFuncs[tag]
  1410  	if ok {
  1411  		return f
  1412  	}
  1413  	f = fmt.Sprintf("New_%d", len(s.allocFuncs))
  1414  	s.newAllocFuncs = append(s.newAllocFuncs, funcdesc{pp: pp, p: p, name: f, tag: tag})
  1415  	s.allocFuncs[tag] = f
  1416  	return f
  1417  }
  1418  
  1419  func (s *genstate) genParamRef(p parm, idx int) string {
  1420  	switch p.AddrTaken() {
  1421  	case notAddrTaken:
  1422  		return fmt.Sprintf("p%d", idx)
  1423  	case addrTakenSimple, addrTakenHeap:
  1424  		return fmt.Sprintf("(*ap%d)", idx)
  1425  	case addrTakenPassed:
  1426  		f := s.genParamDerefFunc(p)
  1427  		return fmt.Sprintf("%s(ap%d)", f, idx)
  1428  	default:
  1429  		panic("bad")
  1430  	}
  1431  }
  1432  
  1433  func (s *genstate) genReturnAssign(b *bytes.Buffer, r parm, idx int, val string) {
  1434  	switch r.AddrTaken() {
  1435  	case notAddrTaken:
  1436  		b.WriteString(fmt.Sprintf("  r%d = %s\n", idx, val))
  1437  	case addrTakenSimple, addrTakenHeap:
  1438  		b.WriteString(fmt.Sprintf("  (*ar%d) = %v\n", idx, val))
  1439  	case addrTakenPassed:
  1440  		f := s.genAssignFunc(r)
  1441  		b.WriteString(fmt.Sprintf("  %s(ar%d, %v)\n", f, idx, val))
  1442  	default:
  1443  		panic("bad")
  1444  	}
  1445  }
  1446  
  1447  func (s *genstate) emitParamElemCheck(f *funcdef, b *bytes.Buffer, p parm, pvar string, cvar string, paramidx int, elemidx int) {
  1448  	if p.SkipCompare() == SkipAll {
  1449  		b.WriteString(fmt.Sprintf("  // selective skip of %s\n", pvar))
  1450  		b.WriteString(fmt.Sprintf("  _ = %s\n", cvar))
  1451  		return
  1452  	} else if p.SkipCompare() == SkipPayload {
  1453  		switch p.(type) {
  1454  		case *stringparm, *arrayparm:
  1455  			b.WriteString(fmt.Sprintf("  if len(%s) != len(%s) { // skip payload\n",
  1456  				pvar, cvar))
  1457  		default:
  1458  			panic("should never happen")
  1459  		}
  1460  	} else {
  1461  		basep, star := genDeref(p)
  1462  		// Handle *p where p is an empty struct.
  1463  		if basep.NumElements() == 0 {
  1464  			return
  1465  		}
  1466  		if basep.HasPointer() {
  1467  			efn := s.eqFuncRef(f, basep, false)
  1468  			b.WriteString(fmt.Sprintf("  if !%s(%s%s, %s%s) {\n",
  1469  				efn, star, pvar, star, cvar))
  1470  		} else {
  1471  			b.WriteString(fmt.Sprintf("  if %s%s != %s%s {\n",
  1472  				star, pvar, star, cvar))
  1473  		}
  1474  	}
  1475  	cm := f.complexityMeasure()
  1476  	b.WriteString(fmt.Sprintf("    NoteFailureElem(%d, %d, %d, \"%s\", \"parm\", %d, %d, false, pad[0])\n", cm, s.pkidx, f.idx, s.checkerPkg(s.pkidx), paramidx, elemidx))
  1477  	b.WriteString("    return\n")
  1478  	b.WriteString("  }\n")
  1479  }
  1480  
  1481  func (s *genstate) emitParamChecks(f *funcdef, b *bytes.Buffer, pidx int, value int) (int, bool) {
  1482  	var valstr string
  1483  	haveControl := false
  1484  	dangling := []int{}
  1485  	for pi, p := range f.params {
  1486  		verb(4, "emitting parmcheck p%d numel=%d pt=%s value=%d",
  1487  			pi, p.NumElements(), p.TypeName(), value)
  1488  		// To balance code in caller
  1489  		_ = uint8(s.wr.Intn(100)) < 50
  1490  		if p.IsControl() {
  1491  			b.WriteString(fmt.Sprintf("  if %s == 0 {\n",
  1492  				s.genParamRef(p, pi)))
  1493  			s.emitReturn(f, b, false)
  1494  			b.WriteString("  }\n")
  1495  			haveControl = true
  1496  
  1497  		} else if p.IsBlank() {
  1498  			valstr, value = s.GenValue(f, p, value, false)
  1499  			if f.recur {
  1500  				b.WriteString(fmt.Sprintf("  brc%d := %s\n", pi, valstr))
  1501  			} else {
  1502  				b.WriteString(fmt.Sprintf("  _ = %s\n", valstr))
  1503  			}
  1504  		} else {
  1505  			numel := p.NumElements()
  1506  			cel := checkableElements(p)
  1507  			for i := 0; i < numel; i++ {
  1508  				verb(4, "emitting check-code for p%d el %d value=%d", pi, i, value)
  1509  				elref, elparm := p.GenElemRef(i, s.genParamRef(p, pi))
  1510  				valstr, value = s.GenValue(f, elparm, value, false)
  1511  				if elref == "" || elref == "_" || cel == 0 {
  1512  					b.WriteString(fmt.Sprintf("  // blank skip: %s\n", valstr))
  1513  					continue
  1514  				} else {
  1515  					basep, _ := genDeref(elparm)
  1516  					// Handle *p where p is an empty struct.
  1517  					if basep.NumElements() == 0 {
  1518  						continue
  1519  					}
  1520  					cvar := fmt.Sprintf("p%df%dc", pi, i)
  1521  					b.WriteString(fmt.Sprintf("  %s := %s\n", cvar, valstr))
  1522  					s.emitParamElemCheck(f, b, elparm, elref, cvar, pi, i)
  1523  				}
  1524  			}
  1525  			if p.AddrTaken() != notAddrTaken {
  1526  				dangling = append(dangling, pi)
  1527  			}
  1528  		}
  1529  		if value != f.values[pi] {
  1530  			fmt.Fprintf(os.Stderr, "internal error: checker/caller value mismatch after emitting param %d func Test%d pkg %s: caller %d checker %d\n", pi, f.idx, s.checkerPkg(pidx), f.values[pi], value)
  1531  			s.errs++
  1532  		}
  1533  	}
  1534  	for _, pi := range dangling {
  1535  		b.WriteString(fmt.Sprintf("  _ = ap%d // ref\n", pi))
  1536  	}
  1537  
  1538  	// receiver value check
  1539  	if f.isMethod {
  1540  		numel := f.receiver.NumElements()
  1541  		for i := 0; i < numel; i++ {
  1542  			verb(4, "emitting check-code for rcvr el %d value=%d", i, value)
  1543  			elref, elparm := f.receiver.GenElemRef(i, "rcvr")
  1544  			valstr, value = s.GenValue(f, elparm, value, false)
  1545  			if elref == "" || strings.HasPrefix(elref, "_") || f.receiver.IsBlank() {
  1546  				verb(4, "empty skip rcvr el %d", i)
  1547  				continue
  1548  			} else {
  1549  
  1550  				basep, _ := genDeref(elparm)
  1551  				// Handle *p where p is an empty struct.
  1552  				if basep.NumElements() == 0 {
  1553  					continue
  1554  				}
  1555  				cvar := fmt.Sprintf("rcvrf%dc", i)
  1556  				b.WriteString(fmt.Sprintf("  %s := %s\n", cvar, valstr))
  1557  				s.emitParamElemCheck(f, b, elparm, elref, cvar, -1, i)
  1558  			}
  1559  		}
  1560  	}
  1561  
  1562  	return value, haveControl
  1563  }
  1564  
  1565  // emitDeferChecks creates code like
  1566  //
  1567  //	defer func(...args...) {
  1568  //	  check arg
  1569  //	  check param
  1570  //	}(...)
  1571  //
  1572  // where we randomly choose to either pass a param through to the
  1573  // function literal, or have the param captured by the closure, then
  1574  // check its value in the defer.
  1575  func (s *genstate) emitDeferChecks(f *funcdef, b *bytes.Buffer, pidx int, value int) int {
  1576  
  1577  	if len(f.params) == 0 {
  1578  		return value
  1579  	}
  1580  
  1581  	// make a pass through the params and randomly decide which will be passed into the func.
  1582  	passed := []bool{}
  1583  	for i := range f.params {
  1584  		p := f.dodefp[i] < 50
  1585  		passed = append(passed, p)
  1586  	}
  1587  
  1588  	b.WriteString("  defer func(")
  1589  	pc := 0
  1590  	for pi, p := range f.params {
  1591  		if p.IsControl() || p.IsBlank() {
  1592  			continue
  1593  		}
  1594  		if passed[pi] {
  1595  			writeCom(b, pc)
  1596  			n := fmt.Sprintf("p%d", pi)
  1597  			p.Declare(b, n, "", false)
  1598  			pc++
  1599  		}
  1600  	}
  1601  	b.WriteString(") {\n")
  1602  
  1603  	for pi, p := range f.params {
  1604  		if p.IsControl() || p.IsBlank() {
  1605  			continue
  1606  		}
  1607  		which := "passed"
  1608  		if !passed[pi] {
  1609  			which = "captured"
  1610  		}
  1611  		b.WriteString("  // check parm " + which + "\n")
  1612  		numel := p.NumElements()
  1613  		cel := checkableElements(p)
  1614  		for i := 0; i < numel; i++ {
  1615  			elref, elparm := p.GenElemRef(i, s.genParamRef(p, pi))
  1616  			if elref == "" || elref == "_" || cel == 0 {
  1617  				verb(4, "empty skip p%d el %d", pi, i)
  1618  				continue
  1619  			} else {
  1620  				basep, _ := genDeref(elparm)
  1621  				// Handle *p where p is an empty struct.
  1622  				if basep.NumElements() == 0 {
  1623  					continue
  1624  				}
  1625  				cvar := fmt.Sprintf("p%df%dc", pi, i)
  1626  				s.emitParamElemCheck(f, b, elparm, elref, cvar, pi, i)
  1627  			}
  1628  		}
  1629  	}
  1630  	b.WriteString("  } (")
  1631  	pc = 0
  1632  	for pi, p := range f.params {
  1633  		if p.IsControl() || p.IsBlank() {
  1634  			continue
  1635  		}
  1636  		if passed[pi] {
  1637  			writeCom(b, pc)
  1638  			b.WriteString(fmt.Sprintf("p%d", pi))
  1639  			pc++
  1640  		}
  1641  	}
  1642  	b.WriteString(")\n\n")
  1643  
  1644  	return value
  1645  }
  1646  
  1647  func (s *genstate) emitVarAssign(f *funcdef, b *bytes.Buffer, r parm, rname string, value int, caller bool) int {
  1648  	var valstr string
  1649  	isassign := uint8(s.wr.Intn(100)) < 50
  1650  	if rmp, ismap := r.(*mapparm); ismap && isassign {
  1651  		// emit: var m ... ; m[k] = v
  1652  		r.Declare(b, "  "+rname+" := make(", ")\n", caller)
  1653  		valstr, value = s.GenValue(f, rmp.valtype, value, caller)
  1654  		b.WriteString(fmt.Sprintf("  %s[mkt.%s] = %s\n",
  1655  			rname, rmp.keytmp, valstr))
  1656  	} else {
  1657  		// emit r = c
  1658  		valstr, value = s.GenValue(f, r, value, caller)
  1659  		b.WriteString(fmt.Sprintf("  %s := %s\n", rname, valstr))
  1660  	}
  1661  	return value
  1662  }
  1663  
  1664  func (s *genstate) emitChecker(f *funcdef, b *bytes.Buffer, pidx int, emit bool) {
  1665  	verb(4, "emitting struct and array defs")
  1666  	s.emitStructAndArrayDefs(f, b)
  1667  	b.WriteString(fmt.Sprintf("// %d returns %d params\n", len(f.returns), len(f.params)))
  1668  	if s.Pragma != "" {
  1669  		b.WriteString("//go:" + s.Pragma + "\n")
  1670  	}
  1671  	b.WriteString("//go:noinline\n")
  1672  
  1673  	b.WriteString("func")
  1674  
  1675  	if f.isMethod {
  1676  		b.WriteString(" (")
  1677  		n := "rcvr"
  1678  		if f.receiver.IsBlank() {
  1679  			n = "_"
  1680  		}
  1681  		f.receiver.Declare(b, n, "", false)
  1682  		b.WriteString(")")
  1683  	}
  1684  
  1685  	b.WriteString(fmt.Sprintf(" Test%d(", f.idx))
  1686  
  1687  	verb(4, "emitting checker p%d/Test%d", pidx, f.idx)
  1688  
  1689  	// params
  1690  	for pi, p := range f.params {
  1691  		writeCom(b, pi)
  1692  		n := fmt.Sprintf("p%d", pi)
  1693  		if p.IsBlank() {
  1694  			n = "_"
  1695  		}
  1696  		p.Declare(b, n, "", false)
  1697  	}
  1698  	b.WriteString(") ")
  1699  
  1700  	// returns
  1701  	if len(f.returns) > 0 {
  1702  		b.WriteString("(")
  1703  	}
  1704  	for ri, r := range f.returns {
  1705  		writeCom(b, ri)
  1706  		r.Declare(b, fmt.Sprintf("r%d", ri), "", false)
  1707  	}
  1708  	if len(f.returns) > 0 {
  1709  		b.WriteString(")")
  1710  	}
  1711  	b.WriteString(" {\n")
  1712  
  1713  	// local storage
  1714  	b.WriteString("  // consume some stack space, so as to trigger morestack\n")
  1715  	b.WriteString(fmt.Sprintf("  var pad [%d]uint64\n", f.rstack))
  1716  	b.WriteString(fmt.Sprintf("  pad[FailCount[%d] & 0x1]++\n", pidx))
  1717  
  1718  	value := 1
  1719  
  1720  	// generate map key tmps
  1721  	s.wr.Checkpoint("before map key temps")
  1722  	value = s.emitMapKeyTmps(f, b, pidx, value, false)
  1723  
  1724  	// generate return constants
  1725  	s.wr.Checkpoint("before return constants")
  1726  	for ri, r := range f.returns {
  1727  		rc := fmt.Sprintf("rc%d", ri)
  1728  		value = s.emitVarAssign(f, b, r, rc, value, false)
  1729  	}
  1730  
  1731  	// Prepare to reference params/returns by address.
  1732  	lists := [][]parm{f.params, f.returns}
  1733  	names := []string{"p", "r"}
  1734  	var aCounts [2]int
  1735  	for i, lst := range lists {
  1736  		for pi, p := range lst {
  1737  			if p.AddrTaken() == notAddrTaken {
  1738  				continue
  1739  			}
  1740  			aCounts[i]++
  1741  			n := names[i]
  1742  			b.WriteString(fmt.Sprintf("  a%s%d := &%s%d\n", n, pi, n, pi))
  1743  			if p.AddrTaken() == addrTakenHeap {
  1744  				gv := s.genGlobVar(p)
  1745  				b.WriteString(fmt.Sprintf("  %s = a%s%d\n", gv, n, pi))
  1746  			}
  1747  		}
  1748  	}
  1749  
  1750  	if s.EmitBad == 2 {
  1751  		if s.BadPackageIdx == pidx && s.BadFuncIdx == f.idx {
  1752  			b.WriteString("  // force runtime failure here (debugging)\n")
  1753  			b.WriteString(fmt.Sprintf("    NoteFailure(%d, %d, %d, \"%s\", \"artificial\", %d, true, uint64(0))\n", f.complexityMeasure(), pidx, f.idx, s.checkerPkg(pidx), 0))
  1754  		}
  1755  	}
  1756  
  1757  	// parameter checking code
  1758  	var haveControl bool
  1759  	s.wr.Checkpoint("before param checks")
  1760  	value, haveControl = s.emitParamChecks(f, b, pidx, value)
  1761  
  1762  	// defer testing
  1763  	if s.tunables.doDefer && f.dodefc < s.tunables.deferFraction {
  1764  		s.wr.Checkpoint("before defer checks")
  1765  		_ = s.emitDeferChecks(f, b, pidx, value)
  1766  	}
  1767  
  1768  	// returns
  1769  	s.emitReturn(f, b, haveControl)
  1770  
  1771  	b.WriteString(fmt.Sprintf("  // %d addr-taken params, %d addr-taken returns\n",
  1772  		aCounts[0], aCounts[1]))
  1773  
  1774  	b.WriteString("}\n\n")
  1775  
  1776  	// emit any new helper funcs referenced by this test function
  1777  	s.emitAddrTakenHelpers(f, b, emit)
  1778  }
  1779  
  1780  // complexityMeasure returns an integer that estimates how complex a
  1781  // given test function is relative to some other function. The more
  1782  // parameters + returns and the more complicated the types of the
  1783  // params/returns, the higher the number returned here. In theory this
  1784  // could be worked into the minimization process (e.g. pick the least
  1785  // complex func that reproduces the failure), but for now that isn't
  1786  // wired up yet.
  1787  func (f *funcdef) complexityMeasure() int {
  1788  	v := int(0)
  1789  	if f.isMethod {
  1790  		v += f.receiver.NumElements()
  1791  	}
  1792  	for _, p := range f.params {
  1793  		v += p.NumElements()
  1794  	}
  1795  	for _, r := range f.returns {
  1796  		v += r.NumElements()
  1797  	}
  1798  	return v
  1799  }
  1800  
  1801  // emitRecursiveCall generates a recursive call to the test function in question.
  1802  func (s *genstate) emitRecursiveCall(f *funcdef) string {
  1803  	b := bytes.NewBuffer(nil)
  1804  	rcvr := ""
  1805  	if f.isMethod {
  1806  		rcvr = "rcvr."
  1807  	}
  1808  	b.WriteString(fmt.Sprintf(" %sTest%d(", rcvr, f.idx))
  1809  	for pi, p := range f.params {
  1810  		writeCom(b, pi)
  1811  		if p.IsControl() {
  1812  			b.WriteString(fmt.Sprintf(" %s-1", s.genParamRef(p, pi)))
  1813  		} else {
  1814  			if !p.IsBlank() {
  1815  				b.WriteString(fmt.Sprintf(" %s", s.genParamRef(p, pi)))
  1816  			} else {
  1817  				b.WriteString(fmt.Sprintf(" brc%d", pi))
  1818  			}
  1819  		}
  1820  	}
  1821  	b.WriteString(")")
  1822  	return b.String()
  1823  }
  1824  
  1825  // emitReturn generates a return sequence.
  1826  func (s *genstate) emitReturn(f *funcdef, b *bytes.Buffer, doRecursiveCall bool) {
  1827  	// If any of the return values are address-taken, then instead of
  1828  	//
  1829  	//   return x, y, z
  1830  	//
  1831  	// we emit
  1832  	//
  1833  	//   r1 = ...
  1834  	//   r2 = ...
  1835  	//   ...
  1836  	//   return
  1837  	//
  1838  	// Make an initial pass through the returns to see if we need to do this.
  1839  	// Figure out the final return values in the process.
  1840  	indirectReturn := false
  1841  	retvals := []string{}
  1842  	for ri, r := range f.returns {
  1843  		if r.AddrTaken() != notAddrTaken {
  1844  			indirectReturn = true
  1845  		}
  1846  		t := ""
  1847  		if doRecursiveCall {
  1848  			t = "t"
  1849  		}
  1850  		retvals = append(retvals, fmt.Sprintf("rc%s%d", t, ri))
  1851  	}
  1852  
  1853  	// generate the recursive call itself if applicable
  1854  	if doRecursiveCall {
  1855  		b.WriteString("  // recursive call\n  ")
  1856  		if s.ForceStackGrowth {
  1857  			b.WriteString("  hackStack() // force stack growth on next call\n")
  1858  		}
  1859  		rcall := s.emitRecursiveCall(f)
  1860  		if indirectReturn {
  1861  			for ri := range f.returns {
  1862  				writeCom(b, ri)
  1863  				b.WriteString(fmt.Sprintf("  rct%d", ri))
  1864  			}
  1865  			b.WriteString(" := ")
  1866  			b.WriteString(rcall)
  1867  			b.WriteString("\n")
  1868  		} else {
  1869  			if len(f.returns) == 0 {
  1870  				b.WriteString(fmt.Sprintf("%s\n  return\n", rcall))
  1871  			} else {
  1872  				b.WriteString(fmt.Sprintf("  return %s\n", rcall))
  1873  			}
  1874  			return
  1875  		}
  1876  	}
  1877  
  1878  	// now the actual return
  1879  	if indirectReturn {
  1880  		for ri, r := range f.returns {
  1881  			s.genReturnAssign(b, r, ri, retvals[ri])
  1882  		}
  1883  		b.WriteString("  return\n")
  1884  	} else {
  1885  		b.WriteString("  return ")
  1886  		for ri := range f.returns {
  1887  			writeCom(b, ri)
  1888  			b.WriteString(retvals[ri])
  1889  		}
  1890  		b.WriteString("\n")
  1891  	}
  1892  }
  1893  
  1894  func (s *genstate) GenPair(calloutfile *os.File, checkoutfile *os.File, fidx int, pidx int, b *bytes.Buffer, seed int64, emit bool) int64 {
  1895  
  1896  	verb(1, "gen fidx %d pidx %d", fidx, pidx)
  1897  
  1898  	checkTunables(tunables)
  1899  	s.tunables = tunables
  1900  
  1901  	// Generate a function with a random number of params and returns
  1902  	s.wr = NewWrapRand(seed, s.RandCtl)
  1903  	s.wr.tag = "genfunc"
  1904  	fp := s.GenFunc(fidx, pidx)
  1905  
  1906  	// Emit caller side
  1907  	wrcaller := NewWrapRand(seed, s.RandCtl)
  1908  	s.wr = wrcaller
  1909  	s.wr.tag = "caller"
  1910  	s.emitCaller(fp, b, pidx)
  1911  	if emit {
  1912  		b.WriteTo(calloutfile)
  1913  	}
  1914  	b.Reset()
  1915  
  1916  	// Emit checker side
  1917  	wrchecker := NewWrapRand(seed, s.RandCtl)
  1918  	s.wr = wrchecker
  1919  	s.wr.tag = "checker"
  1920  	s.emitChecker(fp, b, pidx, emit)
  1921  	if emit {
  1922  		b.WriteTo(checkoutfile)
  1923  	}
  1924  	b.Reset()
  1925  	wrchecker.Check(wrcaller)
  1926  
  1927  	return seed + 1
  1928  }
  1929  
  1930  func (s *genstate) openOutputFile(filename string, pk string, imports []string, ipref string) *os.File {
  1931  	iprefix := func(f string) string {
  1932  		if ipref == "" {
  1933  			return f
  1934  		}
  1935  		return ipref + "/" + f
  1936  	}
  1937  	verb(1, "opening %s", filename)
  1938  	outf, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
  1939  	if err != nil {
  1940  		log.Fatal(err)
  1941  	}
  1942  	haveunsafe := false
  1943  	outf.WriteString(fmt.Sprintf("package %s\n\n", pk))
  1944  	for _, imp := range imports {
  1945  		if imp == "reflect" {
  1946  			outf.WriteString("import \"reflect\"\n")
  1947  			continue
  1948  		}
  1949  		if imp == "unsafe" {
  1950  			outf.WriteString("import _ \"unsafe\"\n")
  1951  			haveunsafe = true
  1952  			continue
  1953  		}
  1954  		if imp == s.utilsPkg() {
  1955  
  1956  			outf.WriteString(fmt.Sprintf("import . \"%s\"\n", iprefix(imp)))
  1957  			continue
  1958  		}
  1959  		outf.WriteString(fmt.Sprintf("import \"%s\"\n", iprefix(imp)))
  1960  	}
  1961  	outf.WriteString("\n")
  1962  	if s.ForceStackGrowth && haveunsafe {
  1963  		outf.WriteString("// Hack: reach into runtime to grab this testing hook.\n")
  1964  		outf.WriteString("//go:linkname hackStack runtime.gcTestMoveStackOnNextCall\n")
  1965  		outf.WriteString("func hackStack()\n\n")
  1966  	}
  1967  	return outf
  1968  }
  1969  
  1970  type miscVals struct {
  1971  	NumTpk   int
  1972  	MaxFail  int
  1973  	NumTests int
  1974  }
  1975  
  1976  const utilsTemplate = `
  1977  
  1978  import (
  1979    "fmt"
  1980    "os"
  1981  )
  1982  
  1983  type UtilsType int
  1984  var ParamFailCount [{{.NumTpk}}]int
  1985  var ReturnFailCount [{{.NumTpk}}]int
  1986  var FailCount [{{.NumTpk}}]int
  1987  var Mode [{{.NumTpk}}]string
  1988  
  1989  //go:noinline
  1990  func NoteFailure(cm int, pidx int, fidx int, pkg string, pref string, parmNo int, isret bool, _ uint64) {
  1991  	if isret {
  1992  		if ParamFailCount[pidx] != 0 {
  1993  			return
  1994  		}
  1995  		ReturnFailCount[pidx]++
  1996  	} else {
  1997  		ParamFailCount[pidx]++
  1998  	}
  1999  	fmt.Fprintf(os.Stderr, "Error: fail %s |%d|%d|%d| =%s.Test%d= %s %d\n", Mode, cm, pidx, fidx, pkg, fidx, pref, parmNo)
  2000  
  2001  	if ParamFailCount[pidx]+FailCount[pidx]+ReturnFailCount[pidx] > {{.MaxFail}} {
  2002  		os.Exit(1)
  2003  	}
  2004  }
  2005  
  2006  //go:noinline
  2007  func NoteFailureElem(cm int, pidx int, fidx int, pkg string, pref string, parmNo int, elem int, isret bool, _ uint64) {
  2008  
  2009  	if isret {
  2010  		if ParamFailCount[pidx] != 0 {
  2011  			return
  2012  		}
  2013  		ReturnFailCount[pidx]++
  2014  	} else {
  2015  		ParamFailCount[pidx]++
  2016  	}
  2017  	fmt.Fprintf(os.Stderr, "Error: fail %s |%d|%d|%d| =%s.Test%d= %s %d elem %d\n", Mode, cm, pidx, fidx, pkg, fidx, pref, parmNo, elem)
  2018  
  2019  	if ParamFailCount[pidx]+FailCount[pidx]+ReturnFailCount[pidx] > {{.MaxFail}} {
  2020  		os.Exit(1)
  2021  	}
  2022  }
  2023  
  2024  func BeginFcn(p int) {
  2025  	ParamFailCount[p] = 0
  2026  	ReturnFailCount[p] = 0
  2027  }
  2028  
  2029  func EndFcn(p int) {
  2030  	FailCount[p] += ParamFailCount[p]
  2031  	FailCount[p] += ReturnFailCount[p]
  2032  }
  2033  `
  2034  
  2035  func (s *genstate) emitUtils(outf *os.File, maxfail int, numtpk int) {
  2036  	vals := miscVals{
  2037  		NumTpk:  numtpk,
  2038  		MaxFail: maxfail,
  2039  	}
  2040  	t := template.Must(template.New("utils").Parse(utilsTemplate))
  2041  	err := t.Execute(outf, vals)
  2042  	if err != nil {
  2043  		log.Fatal(err)
  2044  	}
  2045  }
  2046  
  2047  const mainPreamble = `
  2048  
  2049  import (
  2050  	"fmt"
  2051  	"os"
  2052  )
  2053  
  2054  func main() {
  2055    fmt.Fprintf(os.Stderr, "starting main\n")
  2056  `
  2057  
  2058  func (s *genstate) emitMain(outf *os.File, numit int, fcnmask map[int]int, pkmask map[int]int) {
  2059  	fmt.Fprintf(outf, "%s", mainPreamble)
  2060  	fmt.Fprintf(outf, "  pch := make(chan bool, %d)\n", s.NumTestPackages)
  2061  	for k := 0; k < s.NumTestPackages; k++ {
  2062  		cp := fmt.Sprintf("%s%s%d", s.Tag, CallerName, k)
  2063  		fmt.Fprintf(outf, "  go func(ch chan bool) {\n")
  2064  		for i := 0; i < numit; i++ {
  2065  			if shouldEmitFP(i, k, fcnmask, pkmask) {
  2066  				fmt.Fprintf(outf, "    %s.%s%d(\"normal\")\n", cp, CallerName, i)
  2067  				if s.tunables.doReflectCall {
  2068  					fmt.Fprintf(outf, "    %s.%s%d(\"reflect\")\n", cp, CallerName, i)
  2069  				}
  2070  			}
  2071  		}
  2072  		fmt.Fprintf(outf, "    pch <- true\n")
  2073  		fmt.Fprintf(outf, "  }(pch)\n")
  2074  	}
  2075  	fmt.Fprintf(outf, "  for pidx := 0; pidx < %d; pidx++ {\n", s.NumTestPackages)
  2076  	fmt.Fprintf(outf, "    _ = <- pch\n")
  2077  	fmt.Fprintf(outf, "  }\n")
  2078  	fmt.Fprintf(outf, "  tf := 0\n")
  2079  	fmt.Fprintf(outf, "  for pidx := 0; pidx < %d; pidx++ {\n", s.NumTestPackages)
  2080  	fmt.Fprintf(outf, "    tf += FailCount[pidx]\n")
  2081  	fmt.Fprintf(outf, "  }\n")
  2082  	fmt.Fprintf(outf, "  if tf != 0 {\n")
  2083  	fmt.Fprintf(outf, "    fmt.Fprintf(os.Stderr, \"FAILURES: %%d\\n\", tf)\n")
  2084  	fmt.Fprintf(outf, "    os.Exit(2)\n")
  2085  	fmt.Fprintf(outf, "  }\n")
  2086  	fmt.Fprintf(outf, "  fmt.Fprintf(os.Stderr, \"finished %d tests\\n\")\n", numit*s.NumTestPackages)
  2087  	fmt.Fprintf(outf, "}\n")
  2088  }
  2089  
  2090  func makeDir(d string) {
  2091  	fi, err := os.Stat(d)
  2092  	if err == nil && fi.IsDir() {
  2093  		return
  2094  	}
  2095  	verb(1, "creating %s", d)
  2096  	if err := os.Mkdir(d, 0777); err != nil {
  2097  		log.Fatal(err)
  2098  	}
  2099  }
  2100  
  2101  func (s *genstate) callerPkg(which int) string {
  2102  	return s.Tag + CallerName + strconv.Itoa(which)
  2103  }
  2104  
  2105  func (s *genstate) callerFile(which int) string {
  2106  	cp := s.callerPkg(which)
  2107  	return filepath.Join(s.OutDir, cp, cp+".go")
  2108  }
  2109  
  2110  func (s *genstate) checkerPkg(which int) string {
  2111  	return s.Tag + CheckerName + strconv.Itoa(which)
  2112  }
  2113  
  2114  func (s *genstate) checkerFile(which int) string {
  2115  	cp := s.checkerPkg(which)
  2116  	return filepath.Join(s.OutDir, cp, cp+".go")
  2117  }
  2118  
  2119  func (s *genstate) utilsPkg() string {
  2120  	return s.Tag + "Utils"
  2121  }
  2122  
  2123  func (s *genstate) beginPackage(pkidx int) {
  2124  	s.pkidx = pkidx
  2125  	s.derefFuncs = make(map[string]string)
  2126  	s.assignFuncs = make(map[string]string)
  2127  	s.allocFuncs = make(map[string]string)
  2128  	s.globVars = make(map[string]string)
  2129  	s.genvalFuncs = make(map[string]string)
  2130  }
  2131  
  2132  func runImports(files []string) {
  2133  	verb(1, "... running goimports")
  2134  	args := make([]string, 0, len(files)+1)
  2135  	args = append(args, "-w")
  2136  	args = append(args, files...)
  2137  	cmd := exec.Command("goimports", args...)
  2138  	coutput, cerr := cmd.CombinedOutput()
  2139  	if cerr != nil {
  2140  		log.Fatalf("goimports command failed: %s", string(coutput))
  2141  	}
  2142  	verb(1, "... goimports run complete")
  2143  }
  2144  
  2145  // shouldEmitFP returns true if we should actually emit code for the function
  2146  // with the specified package + fcn indices. For "regular" runs, fcnmask and pkmask
  2147  // will be empty, meaning we want to emit every function in every package. The
  2148  // fuzz-runner program also tries to do testcase "minimization", which means that it
  2149  // will try to whittle down the set of packages and functions (by running the generator
  2150  // using the fcnmask and pkmask options) to emit only specific packages or functions.
  2151  func shouldEmitFP(fn int, pk int, fcnmask map[int]int, pkmask map[int]int) bool {
  2152  	emitpk := true
  2153  	emitfn := true
  2154  	if len(pkmask) != 0 {
  2155  		emitpk = false
  2156  		if _, ok := pkmask[pk]; ok {
  2157  			emitpk = true
  2158  		}
  2159  	}
  2160  	if len(fcnmask) != 0 {
  2161  		emitfn = false
  2162  		if _, ok := fcnmask[fn]; ok {
  2163  			emitfn = true
  2164  		}
  2165  	}
  2166  	doemit := emitpk && emitfn
  2167  	verb(2, "shouldEmitFP(F=%d,P=%d) returns %v", fn, pk, doemit)
  2168  	return doemit
  2169  }
  2170  
  2171  // Generate is the top level code generation hook for this package.
  2172  // Emits code according to the schema in config object 'c'.
  2173  func Generate(c GenConfig) int {
  2174  	mainpkg := c.Tag + "Main"
  2175  
  2176  	var ipref string
  2177  	if len(c.PkgPath) > 0 {
  2178  		ipref = c.PkgPath
  2179  	}
  2180  
  2181  	s := genstate{
  2182  		GenConfig: c,
  2183  		ipref:     ipref,
  2184  	}
  2185  
  2186  	if s.OutDir != "." {
  2187  		verb(1, "creating %s", s.OutDir)
  2188  		makeDir(s.OutDir)
  2189  	}
  2190  
  2191  	mainimports := []string{}
  2192  	for i := 0; i < s.NumTestPackages; i++ {
  2193  		if shouldEmitFP(-1, i, nil, s.PkgMask) {
  2194  			makeDir(s.OutDir + "/" + s.callerPkg(i))
  2195  			makeDir(s.OutDir + "/" + s.checkerPkg(i))
  2196  			makeDir(s.OutDir + "/" + s.utilsPkg())
  2197  			mainimports = append(mainimports, s.callerPkg(i))
  2198  		}
  2199  	}
  2200  	mainimports = append(mainimports, s.utilsPkg())
  2201  
  2202  	// Emit utils package.
  2203  	verb(1, "emit utils")
  2204  	utilsfile := s.OutDir + "/" + s.utilsPkg() + "/" + s.utilsPkg() + ".go"
  2205  	utilsoutfile := s.openOutputFile(utilsfile, s.utilsPkg(), []string{}, "")
  2206  	s.emitUtils(utilsoutfile, s.MaxFail, s.NumTestPackages)
  2207  	utilsoutfile.Close()
  2208  
  2209  	mainfile := s.OutDir + "/" + mainpkg + ".go"
  2210  	mainoutfile := s.openOutputFile(mainfile, "main", mainimports, ipref)
  2211  
  2212  	allfiles := []string{mainfile, utilsfile}
  2213  	for k := 0; k < s.NumTestPackages; k++ {
  2214  		callerImports := []string{s.checkerPkg(k), s.utilsPkg()}
  2215  		checkerImports := []string{s.utilsPkg()}
  2216  		if tunables.doReflectCall {
  2217  			callerImports = append(callerImports, "reflect")
  2218  		}
  2219  		if s.ForceStackGrowth {
  2220  			callerImports = append(callerImports, "unsafe")
  2221  			checkerImports = append(checkerImports, "unsafe")
  2222  		}
  2223  		var calleroutfile, checkeroutfile *os.File
  2224  		if shouldEmitFP(-1, k, nil, s.PkgMask) {
  2225  			calleroutfile = s.openOutputFile(s.callerFile(k), s.callerPkg(k),
  2226  				callerImports, ipref)
  2227  			checkeroutfile = s.openOutputFile(s.checkerFile(k), s.checkerPkg(k),
  2228  				checkerImports, ipref)
  2229  			allfiles = append(allfiles, s.callerFile(k), s.checkerFile(k))
  2230  		}
  2231  
  2232  		s.beginPackage(k)
  2233  
  2234  		var b bytes.Buffer
  2235  		for i := 0; i < s.NumTestFunctions; i++ {
  2236  			doemit := shouldEmitFP(i, k, s.FcnMask, s.PkgMask)
  2237  			s.Seed = s.GenPair(calleroutfile, checkeroutfile, i, k,
  2238  				&b, s.Seed, doemit)
  2239  		}
  2240  
  2241  		// When minimization is in effect, we sometimes wind
  2242  		// up eliminating all refs to the utils package. Add a
  2243  		// dummy to help with this.
  2244  		fmt.Fprintf(calleroutfile, "\n// dummy\nvar Dummy UtilsType\n")
  2245  		fmt.Fprintf(checkeroutfile, "\n// dummy\nvar Dummy UtilsType\n")
  2246  		calleroutfile.Close()
  2247  		checkeroutfile.Close()
  2248  	}
  2249  	s.emitMain(mainoutfile, s.NumTestFunctions, s.FcnMask, s.PkgMask)
  2250  
  2251  	// emit go.mod
  2252  	verb(1, "opening go.mod")
  2253  	fn := s.OutDir + "/go.mod"
  2254  	outf, err := os.OpenFile(fn, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
  2255  	if err != nil {
  2256  		log.Fatal(err)
  2257  	}
  2258  	outf.WriteString(fmt.Sprintf("module %s\n\ngo 1.17\n", s.PkgPath))
  2259  	outf.Close()
  2260  
  2261  	verb(1, "closing files")
  2262  	mainoutfile.Close()
  2263  
  2264  	if s.errs == 0 && s.RunGoImports {
  2265  		runImports(allfiles)
  2266  	}
  2267  
  2268  	return s.errs
  2269  }