GoPLS Viewer

Home|gopls/cmd/signature-fuzzer/internal/fuzz-generator/generator.go
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
39package generator
40
41import (
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.
59type 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
120const CallerName = "Caller"
121const 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.
127type 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).
229func SetTunables(t TunableParams) {
230    checkTunables(t)
231    tunables = t
232}
233
234var 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
246const (
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
259var tunables = TunableParams{
260    nParmRange:            15,
261    nReturnRange:          7,
262    nStructFields:         7,
263    nArrayElements:        5,
264    sliceFraction:         50,
265    intBitRanges:          [4]uint8{30202030},
266    floatBitRanges:        [2]uint8{5050},
267    unsignedRanges:        [2]uint8{5050},
268    blankPerc:             15,
269    structDepth:           3,
270    typeFractions:         defaultTypeFractions,
271    recurPerc:             20,
272    methodPerc:            10,
273    pointerMethodCallPerc50,
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{50251510},
284}
285
286func DefaultTunables() TunableParams {
287    return tunables
288}
289
290func 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
358func (t *TunableParamsDisableReflectionCalls() {
359    t.doReflectCall = false
360}
361
362func (t *TunableParamsDisableRecursiveCalls() {
363    t.recurPerc = 0
364}
365
366func (t *TunableParamsDisableMethodCalls() {
367    t.methodPerc = 0
368}
369
370func (t *TunableParamsDisableTakeAddr() {
371    t.takeAddress = false
372}
373
374func (t *TunableParamsDisableDefer() {
375    t.doDefer = false
376}
377
378func (t *TunableParamsLimitInputs(n interror {
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
389func (t *TunableParamsLimitOutputs(n interror {
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.
405func ParseMaskString(arg stringtag string) (map[int]interror) {
406    if arg == "" {
407        return nilnil
408    }
409    verb(1"%s mask is %s"tagarg)
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 nilfmt.Errorf("malformed range %s in %s mask arg"stag)
417            }
418            ierr := strconv.Atoi(rng[0])
419            if err != nil {
420                return nilfmt.Errorf("malformed range value %s in %s mask arg"rng[0], tag)
421            }
422            jerr2 := strconv.Atoi(rng[1])
423            if err2 != nil {
424                return nilfmt.Errorf("malformed range value %s in %s mask arg"rng[1], tag)
425            }
426            for k := ik < jk++ {
427                m[k] = 1
428            }
429        } else {
430            ierr := strconv.Atoi(s)
431            if err != nil {
432                return nilfmt.Errorf("malformed value %s in %s mask arg"stag)
433            }
434            m[i] = 1
435        }
436    }
437    return mnil
438}
439
440func writeCom(b *bytes.Bufferi int) {
441    if i != 0 {
442        b.WriteString(", ")
443    }
444}
445
446var Verbctl int = 0
447
448func verb(vlevel ints stringa ...interface{}) {
449    if Verbctl >= vlevel {
450        fmt.Printf(sa...)
451        fmt.Printf("\n")
452    }
453}
454
455type 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
475type 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
500func (s *genstateintFlavor() string {
501    which := uint8(s.wr.Intn(100))
502    if which < s.tunables.unsignedRanges[0] {
503        return "uint"
504    }
505    return "int"
506}
507
508func (s *genstateintBits() 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
522func (s *genstatefloatBits() 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
530func (s *genstategenAddrTaken() 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
544func (s *genstatepushTunables() {
545    s.tstack = append(s.tstacks.tunables)
546}
547
548func (s *genstatepopTunables() {
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.
562func (s *genstateredistributeFraction(toIncorporate uint8avoid []int) {
563    inavoid := func(j intbool {
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.
600func (s *genstateprecludeSelectedTypes(t intt2 ...int) {
601    avoid := []int{t}
602    avoid = append(avoidt2...)
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(favoid)
609}
610
611func (s *genstateGenMapKeyType(f *funcdefdepth intpidx intparm {
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(MapTfIdxPointerTfIdx)
618    return s.GenParm(fdepth+1falsepidx)
619}
620
621func (s *genstateGenParm(f *funcdefdepth intmkctl boolpidx intparm {
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(StructTfIdxArrayTfIdxMapTfIdxPointerTfIdx)
629    }
630
631    // Convert tf into a cumulative sum
632    tf := s.tunables.typeFractions
633    sum := uint8(0)
634    for i := 0i < 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.idxns)
660            sp.qname = fmt.Sprintf("%s.StructF%dS%d",
661                s.checkerPkg(pidx), f.idxns)
662            f.structdefs = append(f.structdefssp)
663            tnf := int64(s.tunables.nStructFields) / int64(depth+1)
664            nf := int(s.wr.Intn(tnf))
665            for fi := 0fi < nffi++ {
666                fp := s.GenParm(fdepth+1falsepidx)
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.fieldsfp)
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.idxnsnel)
687            ap.qname = fmt.Sprintf("%s.ArrayF%dS%dE%d"s.checkerPkg(pidx),
688                f.idxnsnel)
689            f.arraydefs = append(f.arraydefsap)
690            ap.nelements = nel
691            ap.slice = issl
692            ap.eltype = s.GenParm(fdepth+1falsepidx)
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.mapdefsmp)
714            f.mapkeytmps = append(f.mapkeytmps"")
715            f.mapkeytypes = append(f.mapkeytypesmp.keytype)
716            mp.aname = fmt.Sprintf("MapF%dM%d"f.idxns)
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.idxns)
722            mkt := fmt.Sprintf("Mk%dt%d"f.idxns)
723            mp.keytmp = mkt
724            mk := s.GenMapKeyType(fdepth+1pidx)
725            mp.keytype = mk
726            mp.valtype = s.GenParm(fdepth+1falsepidx)
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(fdepth+1falsepidx))
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
802func (s *genstateGenReturn(f *funcdefdepth intpidx intparm {
803    return s.GenParm(fdepthfalsepidx)
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.
809func (s *genstateGenFunc(fidx intpidx 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(f0falsepidx)
823        target.SetBlank(false)
824        f.receiver = s.makeTypedefParm(ftargetpidx)
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 := 0pi < numParamspi++ {
836        newparm := s.GenParm(f0needControlpidx)
837        if !pTaken {
838            newparm.SetAddrTaken(notAddrTaken)
839        }
840        if newparm.IsControl() {
841            needControl = false
842        }
843        f.params = append(f.paramsnewparm)
844        f.dodefp = append(f.dodefpuint8(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 := 0ri < numReturnsri++ {
852        r := s.GenReturn(f0pidx)
853        if !rTaken {
854            r.SetAddrTaken(notAddrTaken)
855        }
856        f.returns = append(f.returnsr)
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
867func genDeref(p parm) (parmstring) {
868    curp := p
869    star := ""
870    for {
871        if ppok := curp.(*pointerparm); ok {
872            star += "*"
873            curp = pp.totype
874        } else {
875            return curpstar
876        }
877    }
878}
879
880func (s *genstateeqFuncRef(f *funcdeft parmcaller boolstring {
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).
893func (s *genstateemitCompareFunc(f *funcdefb *bytes.Bufferp 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"rcvrtntntn))
906    b.WriteString("  return ")
907    numel := p.NumElements()
908    ncmp := 0
909    for i := 0i < numeli++ {
910        lelreflelparm := p.GenElemRef(i"left")
911        relref_ := p.GenElemRef(i"right")
912        if lelref == "" || lelref == "_" {
913            continue
914        }
915        basepstar := 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(fbasepfalse)
926            b.WriteString(fmt.Sprintf(" %s(%s%s, %s%s)"efnstarlelrefstarrelref))
927        } else {
928            b.WriteString(fmt.Sprintf("%s%s == %s%s"starlelrefstarrelref))
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.
940func (s *genstateemitStructAndArrayDefs(f *funcdefb *bytes.Buffer) {
941    for _str := range f.structdefs {
942        b.WriteString(fmt.Sprintf("type %s struct {\n"str.sname))
943        for fisp := range str.fields {
944            sp.Declare(b"  "+str.FieldName(fi), "\n"false)
945        }
946        b.WriteString("}\n\n")
947        s.emitCompareFunc(fb, &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            elemsa.eltype.TypeName()))
956        s.emitCompareFunc(fb, &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(fb, &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(fb, &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.
980func (s *genstateGenValue(f *funcdefp parmvalue intcaller bool) (stringint) {
981    var valstr string
982    valstrvalue = p.GenValue(sfvaluecaller)
983    if !s.tunables.doFuncCallValues || !p.IsGenVal() || caller {
984        return valstrvalue
985    }
986
987    mkInvoc := func(fname stringstring {
988        meth := ""
989        if f.mapkeyts != "" {
990            meth = "mkt."
991        }
992        return fmt.Sprintf("%s%s()"methfname)
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    fnameok := 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.newGenvalFuncsfuncdesc{ppnamefnametagtagpayloadvalstr})
1015    s.genvalFuncs[tag] = fname
1016    return mkInvoc(fname), value
1017}
1018
1019func (s *genstateemitMapKeyTmps(f *funcdefb *bytes.Bufferpidx intvalue intcaller boolint {
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 it := range f.mapkeytypes {
1030        var keystr string
1031        keystrvalue = s.GenValue(ftvaluecaller)
1032        tname := f.mapkeytmps[i]
1033        b.WriteString(fmt.Sprintf("  %s := %s\n"tnamekeystr))
1034        b.WriteString(fmt.Sprintf("  mkt.%s = %s\n"tnametname))
1035    }
1036    return value
1037}
1038
1039func (s *genstateemitCheckReturnsInCaller(f *funcdefb *bytes.Bufferpidx intreflectCall bool) {
1040    cm := f.complexityMeasure()
1041    rvalp := func(ri intstring {
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 rirp := range f.returns {
1052        if reflectCall {
1053            b.WriteString(fmt.Sprintf("  rr%di := rvslice[%d].Interface()\n"riri))
1054            b.WriteString(fmt.Sprintf("  rr%dv:= rr%di.("riri))
1055            rp.Declare(b""""true)
1056            b.WriteString(")\n")
1057        }
1058        pfc := ""
1059        curpstar := 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(fcurptrue)
1070            b.WriteString(fmt.Sprintf("  if %s%s(%s%s, %sc%d) {\n"pfcefnstarrvalp(ri), starri))
1071        } else {
1072            b.WriteString(fmt.Sprintf("  if %s%s%s != %sc%d {\n"pfcstarrvalp(ri), starri))
1073        }
1074        b.WriteString(fmt.Sprintf("    NoteFailure(%d, %d, %d, \"%s\", %s, %d, true, uint64(0))\n"cmpidxf.idxs.checkerPkg(pidx), failTagri))
1075        b.WriteString("  }\n")
1076    }
1077}
1078
1079func (s *genstateemitCaller(f *funcdefb *bytes.Bufferpidx int) {
1080
1081    b.WriteString(fmt.Sprintf("func %s%d(mode string) {\n"CallerNamef.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(fbpidxvaluetrue)
1095
1096    // generate return constants
1097    s.wr.Checkpoint("before return constants")
1098    for rir := range f.returns {
1099        rc := fmt.Sprintf("c%d"ri)
1100        value = s.emitVarAssign(fbrrcvaluetrue)
1101    }
1102
1103    // generate param constants
1104    s.wr.Checkpoint("before param constants")
1105    for pip := range f.params {
1106        verb(4"emitCaller gen p%d value=%d"pivalue)
1107        if p.IsControl() {
1108            _ = uint8(s.wr.Intn(100)) < 50
1109            p.Declare(bfmt.Sprintf("  var p%d "pi), " = 10\n"true)
1110        } else {
1111            pc := fmt.Sprintf("p%d"pi)
1112            value = s.emitVarAssign(fbppcvaluetrue)
1113        }
1114        f.values = append(f.valuesvalue)
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        valstrvalue := s.GenValue(ff.receivervaluetrue)
1122        b.WriteString(fmt.Sprintf("  rcvr = %s\n"valstr))
1123        f.values = append(f.valuesvalue)
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(bri)
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("preff.idx))
1148    for pi := range f.params {
1149        writeCom(bpi)
1150        b.WriteString(fmt.Sprintf("p%d"pi))
1151    }
1152    b.WriteString(")\n")
1153
1154    // check values returned (normal call case)
1155    s.emitCheckReturnsInCaller(fbpidxfalse /* 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(bpi)
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(fbpidxtrue /* 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
1190func checkableElements(p parmint {
1191    if p.IsBlank() {
1192        return 0
1193    }
1194    spisstruct := 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    apisarray := 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).
1220type funcdesc struct {
1221    p       parm
1222    pp      parm
1223    name    string
1224    tag     string
1225    payload string
1226}
1227
1228func (s *genstateemitDerefFuncs(b *bytes.Bufferemit 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.derefFuncsfd.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
1248func (s *genstateemitAssignFuncs(b *bytes.Bufferemit 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.assignFuncsfd.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
1268func (s *genstateemitNewFuncs(b *bytes.Bufferemit 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.allocFuncsfd.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
1292func (s *genstateemitGlobalVars(b *bytes.Bufferemit 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.globVarsfd.tag)
1298            continue
1299        }
1300        b.WriteString("var ")
1301        fd.pp.Declare(bfd.name""false)
1302        b.WriteString("\n")
1303    }
1304    s.newGlobVars = nil
1305    b.WriteString("\n")
1306}
1307
1308func (s *genstateemitGenValFuncs(f *funcdefb *bytes.Bufferemit 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.genvalFuncsfd.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() "rcvrfd.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                mpismap := cp.(*mapparm)
1328                if ismap {
1329                    b.WriteString(fmt.Sprintf("  %s := mkt.%s\n",
1330                        mp.keytmpmp.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
1341func (s *genstateemitAddrTakenHelpers(f *funcdefb *bytes.Bufferemit bool) {
1342    b.WriteString("// begin addr taken helpers\n")
1343    s.emitDerefFuncs(bemit)
1344    s.emitAssignFuncs(bemit)
1345    s.emitNewFuncs(bemit)
1346    s.emitGlobalVars(bemit)
1347    s.emitGenValFuncs(fbemit)
1348    b.WriteString("// end addr taken helpers\n")
1349}
1350
1351func (s *genstategenGlobVar(p parmstring {
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    gvok := s.globVars[tag]
1359    if ok {
1360        return gv
1361    }
1362    gv = fmt.Sprintf("gvar_%d"len(s.globVars))
1363    s.newGlobVars = append(s.newGlobVarsfuncdesc{ppppppnamegvtagtag})
1364    s.globVars[tag] = gv
1365    return gv
1366}
1367
1368func (s *genstategenParamDerefFunc(p parmstring {
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    fok := s.derefFuncs[tag]
1376    if ok {
1377        return f
1378    }
1379    f = fmt.Sprintf("deref_%d"len(s.derefFuncs))
1380    s.newDerefFuncs = append(s.newDerefFuncsfuncdesc{ppppppnameftagtag})
1381    s.derefFuncs[tag] = f
1382    return f
1383}
1384
1385func (s *genstategenAssignFunc(p parmstring {
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    fok := s.assignFuncs[tag]
1393    if ok {
1394        return f
1395    }
1396    f = fmt.Sprintf("retassign_%d"len(s.assignFuncs))
1397    s.newAssignFuncs = append(s.newAssignFuncsfuncdesc{ppppppnameftagtag})
1398    s.assignFuncs[tag] = f
1399    return f
1400}
1401
1402func (s *genstategenAllocFunc(p parmstring {
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    fok := s.allocFuncs[tag]
1410    if ok {
1411        return f
1412    }
1413    f = fmt.Sprintf("New_%d"len(s.allocFuncs))
1414    s.newAllocFuncs = append(s.newAllocFuncsfuncdesc{ppppppnameftagtag})
1415    s.allocFuncs[tag] = f
1416    return f
1417}
1418
1419func (s *genstategenParamRef(p parmidx intstring {
1420    switch p.AddrTaken() {
1421    case notAddrTaken:
1422        return fmt.Sprintf("p%d"idx)
1423    case addrTakenSimpleaddrTakenHeap:
1424        return fmt.Sprintf("(*ap%d)"idx)
1425    case addrTakenPassed:
1426        f := s.genParamDerefFunc(p)
1427        return fmt.Sprintf("%s(ap%d)"fidx)
1428    default:
1429        panic("bad")
1430    }
1431}
1432
1433func (s *genstategenReturnAssign(b *bytes.Bufferr parmidx intval string) {
1434    switch r.AddrTaken() {
1435    case notAddrTaken:
1436        b.WriteString(fmt.Sprintf("  r%d = %s\n"idxval))
1437    case addrTakenSimpleaddrTakenHeap:
1438        b.WriteString(fmt.Sprintf("  (*ar%d) = %v\n"idxval))
1439    case addrTakenPassed:
1440        f := s.genAssignFunc(r)
1441        b.WriteString(fmt.Sprintf("  %s(ar%d, %v)\n"fidxval))
1442    default:
1443        panic("bad")
1444    }
1445}
1446
1447func (s *genstateemitParamElemCheck(f *funcdefb *bytes.Bufferp parmpvar stringcvar stringparamidx intelemidx 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                pvarcvar))
1457        default:
1458            panic("should never happen")
1459        }
1460    } else {
1461        basepstar := 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(fbasepfalse)
1468            b.WriteString(fmt.Sprintf("  if !%s(%s%s, %s%s) {\n",
1469                efnstarpvarstarcvar))
1470        } else {
1471            b.WriteString(fmt.Sprintf("  if %s%s != %s%s {\n",
1472                starpvarstarcvar))
1473        }
1474    }
1475    cm := f.complexityMeasure()
1476    b.WriteString(fmt.Sprintf("    NoteFailureElem(%d, %d, %d, \"%s\", \"parm\", %d, %d, false, pad[0])\n"cms.pkidxf.idxs.checkerPkg(s.pkidx), paramidxelemidx))
1477    b.WriteString("    return\n")
1478    b.WriteString("  }\n")
1479}
1480
1481func (s *genstateemitParamChecks(f *funcdefb *bytes.Bufferpidx intvalue int) (intbool) {
1482    var valstr string
1483    haveControl := false
1484    dangling := []int{}
1485    for pip := range f.params {
1486        verb(4"emitting parmcheck p%d numel=%d pt=%s value=%d",
1487            pip.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(ppi)))
1493            s.emitReturn(fbfalse)
1494            b.WriteString("  }\n")
1495            haveControl = true
1496
1497        } else if p.IsBlank() {
1498            valstrvalue = s.GenValue(fpvaluefalse)
1499            if f.recur {
1500                b.WriteString(fmt.Sprintf("  brc%d := %s\n"pivalstr))
1501            } else {
1502                b.WriteString(fmt.Sprintf("  _ = %s\n"valstr))
1503            }
1504        } else {
1505            numel := p.NumElements()
1506            cel := checkableElements(p)
1507            for i := 0i < numeli++ {
1508                verb(4"emitting check-code for p%d el %d value=%d"piivalue)
1509                elrefelparm := p.GenElemRef(is.genParamRef(ppi))
1510                valstrvalue = s.GenValue(felparmvaluefalse)
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"pii)
1521                    b.WriteString(fmt.Sprintf("  %s := %s\n"cvarvalstr))
1522                    s.emitParamElemCheck(fbelparmelrefcvarpii)
1523                }
1524            }
1525            if p.AddrTaken() != notAddrTaken {
1526                dangling = append(danglingpi)
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"pif.idxs.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 := 0i < numeli++ {
1542            verb(4"emitting check-code for rcvr el %d value=%d"ivalue)
1543            elrefelparm := f.receiver.GenElemRef(i"rcvr")
1544            valstrvalue = s.GenValue(felparmvaluefalse)
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"cvarvalstr))
1557                s.emitParamElemCheck(fbelparmelrefcvar, -1i)
1558            }
1559        }
1560    }
1561
1562    return valuehaveControl
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.
1575func (s *genstateemitDeferChecks(f *funcdefb *bytes.Bufferpidx intvalue intint {
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(passedp)
1586    }
1587
1588    b.WriteString("  defer func(")
1589    pc := 0
1590    for pip := range f.params {
1591        if p.IsControl() || p.IsBlank() {
1592            continue
1593        }
1594        if passed[pi] {
1595            writeCom(bpc)
1596            n := fmt.Sprintf("p%d"pi)
1597            p.Declare(bn""false)
1598            pc++
1599        }
1600    }
1601    b.WriteString(") {\n")
1602
1603    for pip := 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 := 0i < numeli++ {
1615            elrefelparm := p.GenElemRef(is.genParamRef(ppi))
1616            if elref == "" || elref == "_" || cel == 0 {
1617                verb(4"empty skip p%d el %d"pii)
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"pii)
1626                s.emitParamElemCheck(fbelparmelrefcvarpii)
1627            }
1628        }
1629    }
1630    b.WriteString("  } (")
1631    pc = 0
1632    for pip := range f.params {
1633        if p.IsControl() || p.IsBlank() {
1634            continue
1635        }
1636        if passed[pi] {
1637            writeCom(bpc)
1638            b.WriteString(fmt.Sprintf("p%d"pi))
1639            pc++
1640        }
1641    }
1642    b.WriteString(")\n\n")
1643
1644    return value
1645}
1646
1647func (s *genstateemitVarAssign(f *funcdefb *bytes.Bufferr parmrname stringvalue intcaller boolint {
1648    var valstr string
1649    isassign := uint8(s.wr.Intn(100)) < 50
1650    if rmpismap := r.(*mapparm); ismap && isassign {
1651        // emit: var m ... ; m[k] = v
1652        r.Declare(b"  "+rname+" := make("")\n"caller)
1653        valstrvalue = s.GenValue(frmp.valtypevaluecaller)
1654        b.WriteString(fmt.Sprintf("  %s[mkt.%s] = %s\n",
1655            rnamermp.keytmpvalstr))
1656    } else {
1657        // emit r = c
1658        valstrvalue = s.GenValue(frvaluecaller)
1659        b.WriteString(fmt.Sprintf("  %s := %s\n"rnamevalstr))
1660    }
1661    return value
1662}
1663
1664func (s *genstateemitChecker(f *funcdefb *bytes.Bufferpidx intemit bool) {
1665    verb(4"emitting struct and array defs")
1666    s.emitStructAndArrayDefs(fb)
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(bn""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"pidxf.idx)
1688
1689    // params
1690    for pip := range f.params {
1691        writeCom(bpi)
1692        n := fmt.Sprintf("p%d"pi)
1693        if p.IsBlank() {
1694            n = "_"
1695        }
1696        p.Declare(bn""false)
1697    }
1698    b.WriteString(") ")
1699
1700    // returns
1701    if len(f.returns) > 0 {
1702        b.WriteString("(")
1703    }
1704    for rir := range f.returns {
1705        writeCom(bri)
1706        r.Declare(bfmt.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(fbpidxvaluefalse)
1723
1724    // generate return constants
1725    s.wr.Checkpoint("before return constants")
1726    for rir := range f.returns {
1727        rc := fmt.Sprintf("rc%d"ri)
1728        value = s.emitVarAssign(fbrrcvaluefalse)
1729    }
1730
1731    // Prepare to reference params/returns by address.
1732    lists := [][]parm{f.paramsf.returns}
1733    names := []string{"p""r"}
1734    var aCounts [2]int
1735    for ilst := range lists {
1736        for pip := 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"npinpi))
1743            if p.AddrTaken() == addrTakenHeap {
1744                gv := s.genGlobVar(p)
1745                b.WriteString(fmt.Sprintf("  %s = a%s%d\n"gvnpi))
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(), pidxf.idxs.checkerPkg(pidx), 0))
1754        }
1755    }
1756
1757    // parameter checking code
1758    var haveControl bool
1759    s.wr.Checkpoint("before param checks")
1760    valuehaveControl = s.emitParamChecks(fbpidxvalue)
1761
1762    // defer testing
1763    if s.tunables.doDefer && f.dodefc < s.tunables.deferFraction {
1764        s.wr.Checkpoint("before defer checks")
1765        _ = s.emitDeferChecks(fbpidxvalue)
1766    }
1767
1768    // returns
1769    s.emitReturn(fbhaveControl)
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(fbemit)
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.
1787func (f *funcdefcomplexityMeasure() 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.
1802func (s *genstateemitRecursiveCall(f *funcdefstring {
1803    b := bytes.NewBuffer(nil)
1804    rcvr := ""
1805    if f.isMethod {
1806        rcvr = "rcvr."
1807    }
1808    b.WriteString(fmt.Sprintf(" %sTest%d("rcvrf.idx))
1809    for pip := range f.params {
1810        writeCom(bpi)
1811        if p.IsControl() {
1812            b.WriteString(fmt.Sprintf(" %s-1"s.genParamRef(ppi)))
1813        } else {
1814            if !p.IsBlank() {
1815                b.WriteString(fmt.Sprintf(" %s"s.genParamRef(ppi)))
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.
1826func (s *genstateemitReturn(f *funcdefb *bytes.BufferdoRecursiveCall 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 rir := range f.returns {
1843        if r.AddrTaken() != notAddrTaken {
1844            indirectReturn = true
1845        }
1846        t := ""
1847        if doRecursiveCall {
1848            t = "t"
1849        }
1850        retvals = append(retvalsfmt.Sprintf("rc%s%d"tri))
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(bri)
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 rir := range f.returns {
1881            s.genReturnAssign(brriretvals[ri])
1882        }
1883        b.WriteString("  return\n")
1884    } else {
1885        b.WriteString("  return ")
1886        for ri := range f.returns {
1887            writeCom(bri)
1888            b.WriteString(retvals[ri])
1889        }
1890        b.WriteString("\n")
1891    }
1892}
1893
1894func (s *genstateGenPair(calloutfile *os.Filecheckoutfile *os.Filefidx intpidx intb *bytes.Bufferseed int64emit boolint64 {
1895
1896    verb(1"gen fidx %d pidx %d"fidxpidx)
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(seeds.RandCtl)
1903    s.wr.tag = "genfunc"
1904    fp := s.GenFunc(fidxpidx)
1905
1906    // Emit caller side
1907    wrcaller := NewWrapRand(seeds.RandCtl)
1908    s.wr = wrcaller
1909    s.wr.tag = "caller"
1910    s.emitCaller(fpbpidx)
1911    if emit {
1912        b.WriteTo(calloutfile)
1913    }
1914    b.Reset()
1915
1916    // Emit checker side
1917    wrchecker := NewWrapRand(seeds.RandCtl)
1918    s.wr = wrchecker
1919    s.wr.tag = "checker"
1920    s.emitChecker(fpbpidxemit)
1921    if emit {
1922        b.WriteTo(checkoutfile)
1923    }
1924    b.Reset()
1925    wrchecker.Check(wrcaller)
1926
1927    return seed + 1
1928}
1929
1930func (s *genstateopenOutputFile(filename stringpk stringimports []stringipref string) *os.File {
1931    iprefix := func(f stringstring {
1932        if ipref == "" {
1933            return f
1934        }
1935        return ipref + "/" + f
1936    }
1937    verb(1"opening %s"filename)
1938    outferr := os.OpenFile(filenameos.O_WRONLY|os.O_CREATE|os.O_TRUNC0666)
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
1970type miscVals struct {
1971    NumTpk   int
1972    MaxFail  int
1973    NumTests int
1974}
1975
1976const utilsTemplate = `
1977
1978import (
1979  "fmt"
1980  "os"
1981)
1982
1983type UtilsType int
1984var ParamFailCount [{{.NumTpk}}]int
1985var ReturnFailCount [{{.NumTpk}}]int
1986var FailCount [{{.NumTpk}}]int
1987var Mode [{{.NumTpk}}]string
1988
1989//go:noinline
1990func 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
2007func 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
2024func BeginFcn(p int) {
2025    ParamFailCount[p] = 0
2026    ReturnFailCount[p] = 0
2027}
2028
2029func EndFcn(p int) {
2030    FailCount[p] += ParamFailCount[p]
2031    FailCount[p] += ReturnFailCount[p]
2032}
2033`
2034
2035func (s *genstateemitUtils(outf *os.Filemaxfail intnumtpk int) {
2036    vals := miscVals{
2037        NumTpk:  numtpk,
2038        MaxFailmaxfail,
2039    }
2040    t := template.Must(template.New("utils").Parse(utilsTemplate))
2041    err := t.Execute(outfvals)
2042    if err != nil {
2043        log.Fatal(err)
2044    }
2045}
2046
2047const mainPreamble = `
2048
2049import (
2050    "fmt"
2051    "os"
2052)
2053
2054func main() {
2055  fmt.Fprintf(os.Stderr, "starting main\n")
2056`
2057
2058func (s *genstateemitMain(outf *os.Filenumit intfcnmask map[int]intpkmask map[int]int) {
2059    fmt.Fprintf(outf"%s"mainPreamble)
2060    fmt.Fprintf(outf"  pch := make(chan bool, %d)\n"s.NumTestPackages)
2061    for k := 0k < s.NumTestPackagesk++ {
2062        cp := fmt.Sprintf("%s%s%d"s.TagCallerNamek)
2063        fmt.Fprintf(outf"  go func(ch chan bool) {\n")
2064        for i := 0i < numiti++ {
2065            if shouldEmitFP(ikfcnmaskpkmask) {
2066                fmt.Fprintf(outf"    %s.%s%d(\"normal\")\n"cpCallerNamei)
2067                if s.tunables.doReflectCall {
2068                    fmt.Fprintf(outf"    %s.%s%d(\"reflect\")\n"cpCallerNamei)
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
2090func makeDir(d string) {
2091    fierr := os.Stat(d)
2092    if err == nil && fi.IsDir() {
2093        return
2094    }
2095    verb(1"creating %s"d)
2096    if err := os.Mkdir(d0777); err != nil {
2097        log.Fatal(err)
2098    }
2099}
2100
2101func (s *genstatecallerPkg(which intstring {
2102    return s.Tag + CallerName + strconv.Itoa(which)
2103}
2104
2105func (s *genstatecallerFile(which intstring {
2106    cp := s.callerPkg(which)
2107    return filepath.Join(s.OutDircpcp+".go")
2108}
2109
2110func (s *genstatecheckerPkg(which intstring {
2111    return s.Tag + CheckerName + strconv.Itoa(which)
2112}
2113
2114func (s *genstatecheckerFile(which intstring {
2115    cp := s.checkerPkg(which)
2116    return filepath.Join(s.OutDircpcp+".go")
2117}
2118
2119func (s *genstateutilsPkg() string {
2120    return s.Tag + "Utils"
2121}
2122
2123func (s *genstatebeginPackage(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
2132func runImports(files []string) {
2133    verb(1"... running goimports")
2134    args := make([]string0len(files)+1)
2135    args = append(args"-w")
2136    args = append(argsfiles...)
2137    cmd := exec.Command("goimports"args...)
2138    coutputcerr := 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.
2151func shouldEmitFP(fn intpk intfcnmask map[int]intpkmask map[int]intbool {
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"fnpkdoemit)
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'.
2173func Generate(c GenConfigint {
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        GenConfigc,
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 := 0i < s.NumTestPackagesi++ {
2193        if shouldEmitFP(-1inils.PkgMask) {
2194            makeDir(s.OutDir + "/" + s.callerPkg(i))
2195            makeDir(s.OutDir + "/" + s.checkerPkg(i))
2196            makeDir(s.OutDir + "/" + s.utilsPkg())
2197            mainimports = append(mainimportss.callerPkg(i))
2198        }
2199    }
2200    mainimports = append(mainimportss.utilsPkg())
2201
2202    // Emit utils package.
2203    verb(1"emit utils")
2204    utilsfile := s.OutDir + "/" + s.utilsPkg() + "/" + s.utilsPkg() + ".go"
2205    utilsoutfile := s.openOutputFile(utilsfiles.utilsPkg(), []string{}, "")
2206    s.emitUtils(utilsoutfiles.MaxFails.NumTestPackages)
2207    utilsoutfile.Close()
2208
2209    mainfile := s.OutDir + "/" + mainpkg + ".go"
2210    mainoutfile := s.openOutputFile(mainfile"main"mainimportsipref)
2211
2212    allfiles := []string{mainfileutilsfile}
2213    for k := 0k < s.NumTestPackagesk++ {
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 calleroutfilecheckeroutfile *os.File
2224        if shouldEmitFP(-1knils.PkgMask) {
2225            calleroutfile = s.openOutputFile(s.callerFile(k), s.callerPkg(k),
2226                callerImportsipref)
2227            checkeroutfile = s.openOutputFile(s.checkerFile(k), s.checkerPkg(k),
2228                checkerImportsipref)
2229            allfiles = append(allfiless.callerFile(k), s.checkerFile(k))
2230        }
2231
2232        s.beginPackage(k)
2233
2234        var b bytes.Buffer
2235        for i := 0i < s.NumTestFunctionsi++ {
2236            doemit := shouldEmitFP(iks.FcnMasks.PkgMask)
2237            s.Seed = s.GenPair(calleroutfilecheckeroutfileik,
2238                &bs.Seeddoemit)
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(mainoutfiles.NumTestFunctionss.FcnMasks.PkgMask)
2250
2251    // emit go.mod
2252    verb(1"opening go.mod")
2253    fn := s.OutDir + "/go.mod"
2254    outferr := os.OpenFile(fnos.O_WRONLY|os.O_CREATE|os.O_TRUNC0666)
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}
2270
MembersX
TunableParams.takeAddress
genstate.emitVarAssign.s
DefaultTunables
genstate.emitCompareFunc.BlockStmt.relref
genstate.emitCompareFunc.BlockStmt._
funcdesc
genstate.emitAssignFuncs.s
genstate.emitParamElemCheck.b
TunableParams.nArrayElements
TunableParams.pointerMethodCallPerc
genstate.GenPair.calloutfile
genstate.checkerPkg.s
Generate.ipref
genstate.GenParm.addrTaken
genstate.GenPair.fp
genstate.emitRecursiveCall
genstate.emitGenValFuncs.RangeStmt_36422.fd
genstate.emitChecker.emit
genstate.emitDeferChecks.pidx
genstate.emitChecker.BlockStmt.n
genstate.precludeSelectedTypes
genstate.emitCaller.pref
genstate.emitParamChecks.RangeStmt_41225.pi
genstate.emitChecker.RangeStmt_46828.p
genstate.GenReturn.pidx
genstate.emitAddrTakenHelpers.emit
genstate.emitAssignFuncs.RangeStmt_34798.fd
genstate.genReturnAssign.BlockStmt.f
genstate.emitChecker.RangeStmt_47668.r
genstate.GenPair.wrcaller
genstate.callerPkg.s
Generate.BlockStmt.b
TunableParams.structDepth
genstate.intBits.RangeStmt_14539.v
genstate.emitCaller.BlockStmt.RangeStmt_32763.pi
genstate.genAssignFunc.p
genstate.emitChecker.RangeStmt_47930.BlockStmt.RangeStmt_47960.pi
funcdef.complexityMeasure.v
GenConfig.FcnMask
genstate.emitStructAndArrayDefs
genDeref
genstate.eqFuncRef
genstate.emitMapKeyTmps.RangeStmt_28251.BlockStmt.keystr
genstate.emitDeferChecks.RangeStmt_44398.pi
genstate.emitChecker.b
genstate.emitRecursiveCall.RangeStmt_50135.pi
genstate.genAddrTaken
genstate.redistributeFraction.avoid
miscVals.MaxFail
genstate.emitGenValFuncs.RangeStmt_36422.BlockStmt.BlockStmt.RangeStmt_36897.cp
genstate.emitDeferChecks.passed
genstate.GenValue
genstate.emitCaller.BlockStmt.value
genstate.genGlobVar.p
genstate.genAllocFunc.ppp
genstate.emitChecker.RangeStmt_47056.ri
TunableParams.LimitInputs.n
genstate.redistributeFraction.s
funcdef.values
genstate.newGenvalFuncs
genstate.emitCheckReturnsInCaller.cm
funcdesc.name
GenConfig.NumTestFunctions
verb.vlevel
genstate.emitDeferChecks.f
genstate.precludeSelectedTypes.RangeStmt_16973.idx
genstate.genAllocFunc
genstate.emitMapKeyTmps.f
CallerName
TunableParams.nReturnRange
genstate.emitParamElemCheck.cvar
genstate.checkerFile.s
genstate.newGlobVars
genstate.GenParm.retval
genDeref.star
genstate.emitCompareFunc.BlockStmt.star
genstate.emitCheckReturnsInCaller.RangeStmt_28861.ri
genstate.emitMain.outf
TunableParams.nStructFields
TunableParams.funcCallValFraction
ParseMaskString.RangeStmt_12407.BlockStmt.BlockStmt.i
genstate.emitGenValFuncs.emit
genstate.emitParamElemCheck.elemidx
genstate.emitChecker.RangeStmt_47930.i
miscVals
funcdef.params
genstate.emitCompareFunc.p
genstate.eqFuncRef.t
genstate.emitCheckReturnsInCaller.RangeStmt_28861.BlockStmt.star
genstate.emitCaller.RangeStmt_31829.pi
genstate.emitParamChecks
genstate.emitChecker.RangeStmt_47668.BlockStmt.rc
genstate.emitChecker.RangeStmt_47930.lst
GenConfig.EmitBad
genstate.GenFunc.pi
genstate.GenReturn
genstate.GenFunc.spw
genDeref.p
genstate.eqFuncRef.s
miscVals.NumTests
GenConfig.OutDir
TunableParams.DisableTakeAddr
genstate.emitReturn.f
TunableParams.doSkipCompare
genstate.emitCheckReturnsInCaller.b
funcdesc.pp
genstate.emitVarAssign
miscVals.NumTpk
GenConfig.Pragma
genstate.emitStructAndArrayDefs.RangeStmt_26056.BlockStmt.elems
genstate.emitMain.BlockStmt.cp
genstate.genReturnAssign.s
genstate.openOutputFile.RangeStmt_53326.imp
genstate.emitChecker.RangeStmt_46828.BlockStmt.n
genstate.beginPackage.pkidx
shouldEmitFP.pkmask
checkTunables.s
genstate.emitCaller.RangeStmt_30582.BlockStmt.BlockStmt.pc
genstate.GenFunc.numParams
genstate.emitCompareFunc.b
genstate.emitStructAndArrayDefs.f
genstate.emitDeferChecks.RangeStmt_45357.p
TunableParams.DisableDefer
genstate.derefFuncs
funcdef.idx
funcdef.rstack
genstate.ipref
genstate.emitCompareFunc.i
genstate.genParamDerefFunc
genstate.callerFile.cp
TunableParams.skipCompareFraction
checkTunables
genstate.emitMapKeyTmps.pidx
genstate.emitDeferChecks.b
genstate.pushTunables.s
genstate.GenParm.BlockStmt.BlockStmt.ns
genstate.emitStructAndArrayDefs.RangeStmt_25805.BlockStmt.RangeStmt_25904.sp
genstate.GenValue.bs
template
genstate.eqFuncRef.caller
genstate.emitReturn.RangeStmt_50942.r
genstate.callerFile.which
Generate.BlockStmt.calleroutfile
genstate.newAssignFuncs
genstate.GenFunc.f
genstate.emitDerefFuncs.b
Generate.outf
genstate.GenParm.BlockStmt.BlockStmt.nf
genstate.emitMapKeyTmps.RangeStmt_28251.i
genstate.GenPair.pidx
genstate.GenPair.seed
genstate.emitUtils.err
genstate.emitMain.numit
TunableParams.DisableRecursiveCalls.t
funcdef.returns
genstate.GenParm.BlockStmt.BlockStmt.fp
genstate.emitCheckReturnsInCaller.RangeStmt_28861.rp
genstate.emitCaller.RangeStmt_30391.BlockStmt.rc
genstate.emitGenValFuncs.RangeStmt_36422.BlockStmt.rcvr
genstate.genAllocFunc.b
genstate.emitParamChecks.BlockStmt.BlockStmt.BlockStmt._
ParseMaskString.ss
funcdef.dodefp
Generate.BlockStmt.checkeroutfile
genstate.GenValue.BlockStmt.meth
genstate.genReturnAssign
Generate.mainimports
verb.a
genstate.GenFunc.pidx
genstate.emitCompareFunc.f
genstate.emitCaller.RangeStmt_31568.ri
genstate.emitParamChecks.pidx
genstate.emitChecker.RangeStmt_47056.r
GenConfig.PkgPath
genstate.intFlavor.s
genstate.emitReturn.BlockStmt.BlockStmt.RangeStmt_51427.ri
genstate.emitUtils.maxfail
TunableParams.blankPerc
genstate.emitGenValFuncs.b
genstate.emitParamChecks.haveControl
TunableParams.DisableReflectionCalls.t
genstate.emitCaller.b
genstate.emitParamChecks.RangeStmt_41225.BlockStmt.BlockStmt.BlockStmt.BlockStmt._
genstate.emitVarAssign.r
genstate.emitVarAssign.valstr
genstate.emitReturn.s
TunableParams.DisableRecursiveCalls
genstate.genParamRef.s
genstate.emitCompareFunc.tn
TunableParams.recurPerc
genstate.popTunables.s
genstate.GenReturn.f
genstate.emitCompareFunc.BlockStmt.lelparm
genstate.emitCompareFunc.BlockStmt.BlockStmt.efn
genstate.GenValue.b
checkableElements
genstate.emitChecker.value
TunableParams.methodPerc
ParseMaskString.arg
genstate.emitMain.s
shouldEmitFP.emitfn
ParseMaskString.RangeStmt_12407.BlockStmt.BlockStmt.rng
genstate.checkerFile.which
genstate.emitParamElemCheck.pvar
genstate.emitDeferChecks
funcdef.typedefs
genstate.floatBits.which
genstate.GenParm.BlockStmt.BlockStmt.mp
genstate.GenReturn.depth
genstate.emitCheckReturnsInCaller.reflectCall
genstate.emitReturn.retvals
TunableParams.DisableTakeAddr.t
genstate.errs
genstate.GenMapKeyType.pidx
genstate.emitParamChecks.f
verb
funcdef.arraydefs
genstate.GenPair.wrchecker
genstate.emitUtils.outf
genstate.emitMain
genstate.genReturnAssign.b
genstate.emitVarAssign.rname
genstate.emitParamChecks.BlockStmt.i
genstate.utilsPkg.s
genstate.emitCompareFunc
genstate.emitParamChecks.dangling
genstate.precludeSelectedTypes.t
genstate.GenPair
genstate.callerFile
GenConfig.BadFuncIdx
genstate.allocFuncs
genstate.openOutputFile.pk
genstate.genAllocFunc.pp
genstate.emitParamChecks.BlockStmt.BlockStmt.BlockStmt.basep
genstate.emitCaller.RangeStmt_30391.ri
genstate.genReturnAssign.idx
genstate.emitParamChecks.BlockStmt.BlockStmt.elref
Generate.BlockStmt.callerImports
TunableParams.DisableMethodCalls.t
funcdef.mapkeyts
genstate.GenParm.BlockStmt.BlockStmt.BlockStmt.fp
genstate.emitUtils.numtpk
runImports.files
genstate.genAddrTaken.t
genstate.GenParm.pidx
genstate.beginPackage
genstate.intBits.which
genstate.GenParm.i
genstate.genParamDerefFunc.b
genstate.genParamDerefFunc.tag
genstate.emitParamElemCheck.BlockStmt.star
genstate.emitReturn.BlockStmt.RangeStmt_51982.ri
checkTunables.RangeStmt_9513.v
genstate.emitMapKeyTmps.s
genstate.GenParm.which
genstate.emitStructAndArrayDefs.s
genstate.emitStructAndArrayDefs.RangeStmt_26056.a
genstate.genGlobVar
genstate.emitParamChecks.RangeStmt_41225.BlockStmt.BlockStmt.BlockStmt.elparm
genstate.emitRecursiveCall.b
TunableParams.deferFraction
genstate.genAddrTaken.RangeStmt_14969.v
genstate.GenPair.s
genstate.emitChecker.names
genstate.emitUtils.t
genstate.emitParamElemCheck
genstate.emitDeferChecks.RangeStmt_44619.BlockStmt.i
genstate.GenValue.tag
genstate.emitParamElemCheck.s
genstate.GenFunc.s
genstate.eqFuncRef.f
genstate.openOutputFile.imports
TunableParams.takenFraction
genstate.newDerefFuncs
genstate.intBits.s
genstate.GenParm.sum
genstate.GenParm.BlockStmt.BlockStmt.fi
genstate.emitAssignFuncs
genstate.genGlobVar.ppp
genstate.genParamRef.p
TunableParams.LimitOutputs
verb.s
genstate.GenPair.emit
genstate.callerPkg.which
shouldEmitFP.fcnmask
genstate.emitVarAssign.b
genstate.GenPair.b
genstate.emitCheckReturnsInCaller.s
genstate.emitReturn.BlockStmt.rcall
genstate.GenPair.fidx
runImports.cmd
ParseMaskString.RangeStmt_12407.BlockStmt.BlockStmt.k
genstate
genstate.openOutputFile.err
genstate.GenValue.s
genstate.emitParamChecks.BlockStmt.BlockStmt.BlockStmt.cvar
genstate.emitAddrTakenHelpers.s
genstate.emitParamElemCheck.BlockStmt.basep
genstate.emitReturn
runImports.cerr
genstate.assignFuncs
genstate.intFlavor.which
genstate.GenParm.BlockStmt.BlockStmt.ap
genstate.emitNewFuncs.s
genstate.emitMapKeyTmps.b
TunableParams.LimitOutputs.t
genstate.GenMapKeyType.s
genstate.emitReturn.BlockStmt.RangeStmt_51832.ri
genstate.openOutputFile.haveunsafe
funcdef.receiver
genstate.precludeSelectedTypes.s
genstate.GenMapKeyType.f
genstate.GenParm.depth
genstate.GenFunc.numReturns
genstate.emitCompareFunc.numel
genstate.emitCompareFunc.BlockStmt.basep
genstate.emitStructAndArrayDefs.BlockStmt.RangeStmt_26698.i
funcdef
genstate.intBits.bits
Generate.k
genstate.emitCheckReturnsInCaller
genstate.emitReturn.b
genstate.emitGenValFuncs
genstate.emitChecker.RangeStmt_46828.pi
GenConfig.RunGoImports
funcdef.dodefc
checkableElements.p
GenConfig
genDeref.curp
genstate.genAllocFunc.tag
genstate.emitVarAssign.f
GenConfig.ForceStackGrowth
genstate.emitGenValFuncs.s
genstate.emitDeferChecks.RangeStmt_44619.BlockStmt.BlockStmt.elparm
funcdesc.payload
genstate.emitRecursiveCall.rcvr
makeDir
log
genstate.emitStructAndArrayDefs.RangeStmt_26462.td
SetTunables
genstate.genAddrTaken.res
genstate.precludeSelectedTypes.avoid
genstate.emitCheckReturnsInCaller.pidx
strings
TunableParams.unsignedRanges
genstate.genAllocFunc.p
genstate.emitDeferChecks.RangeStmt_44619.BlockStmt.BlockStmt.BlockStmt.basep
sha1
genstate.GenParm.s
genstate.genAddrTaken.which
genstate.genAssignFunc.ppp
genstate.tstack
genstate.intBits.t
TunableParams.DisableMethodCalls
writeCom.b
genstate.GenMapKeyType.depth
genstate.emitMapKeyTmps.cp
genstate.emitNewFuncs
genstate.emitAddrTakenHelpers.b
GenConfig.Seed
checkTunables.RangeStmt_10470.v
genstate.emitRecursiveCall.f
genstate.emitCaller
genstate.floatBits
genstate.emitStructAndArrayDefs.b
TunableParams.intBitRanges
funcdef.complexityMeasure.RangeStmt_49794.r
genstate.genAssignFunc.tag
genstate.emitGlobalVars.s
genstate.genParamDerefFunc.ppp
genstate.emitParamChecks.RangeStmt_41225.BlockStmt.BlockStmt.BlockStmt.elref
Generate.utilsoutfile
TunableParams.nParmRange
genstate.genParamDerefFunc.p
genstate.emitMapKeyTmps.value
genstate.emitAddrTakenHelpers
genstate.emitChecker.lists
genstate.emitMain.k
genstate.emitCompareFunc.ncmp
genstate.emitStructAndArrayDefs.RangeStmt_25805.BlockStmt.RangeStmt_25904.fi
genstate.emitAddrTakenHelpers.f
genstate.emitUtils.vals
genstate.callerPkg
genstate.checkerFile
GenConfig.BadPackageIdx
checkTunables.RangeStmt_10325.v
genstate.precludeSelectedTypes.t2
genstate.GenParm.tf
genstate.emitGlobalVars.b
genstate.emitParamElemCheck.BlockStmt.BlockStmt.efn
genstate.emitReturn.doRecursiveCall
genstate.openOutputFile
TunableParams
checkTunables.t
genstate.checkerPkg.which
genstate.emitGlobalVars
genstate.genReturnAssign.val
genstate.GenParm
genstate.GenFunc.fidx
genstate.emitStructAndArrayDefs.RangeStmt_25805.str
genstate.emitGenValFuncs.RangeStmt_36422.BlockStmt.BlockStmt.contained
genstate.emitChecker.f
genstate.emitChecker.RangeStmt_47930.BlockStmt.RangeStmt_47960.BlockStmt.BlockStmt.gv
GenConfig.NumTestPackages
genstate.redistributeFraction.toIncorporate
genstate.emitVarAssign.value
genstate.emitNewFuncs.b
genstate.emitParamChecks.value
genstate.emitVarAssign.caller
genstate.emitUtils
strconv
TunableParams.DisableDefer.t
genstate.emitChecker.aCounts
genstate.callerFile.s
genstate.emitParamChecks.BlockStmt.numel
funcdef.complexityMeasure.RangeStmt_49738.p
genstate.emitCheckReturnsInCaller.f
genstate.emitParamChecks.RangeStmt_41225.BlockStmt.BlockStmt.BlockStmt.BlockStmt.basep
genstate.emitCheckReturnsInCaller.RangeStmt_28861.BlockStmt.pfc
genstate.emitCaller.BlockStmt.valstr
genstate.emitGlobalVars.RangeStmt_36017.fd
genstate.emitChecker.s
errors
GenConfig.PkgMask
genstate.emitUtils.s
genstate.checkerPkg
genstate.emitCompareFunc.s
genstate.emitDeferChecks.s
genstate.emitDeferChecks.RangeStmt_44619.p
funcdef.complexityMeasure
Generate.err
TunableParams.doFuncCallValues
SetTunables.t
genstate.GenParm.BlockStmt.BlockStmt.ip
genstate.GenFunc.ri
genstate.GenValue.p
genstate.emitMapKeyTmps
genstate.emitDerefFuncs.s
genstate.emitParamChecks.b
genstate.pushTunables
genstate.redistributeFraction.BlockStmt.RangeStmt_15822.k
makeDir.d
genstate.emitChecker.pidx
genstate.emitMain.pkmask
funcdesc.p
genstate.openOutputFile.outf
TunableParams.typeFractions
genstate.emitCaller.RangeStmt_30582.pi
genstate.emitCaller.s
genstate.genParamDerefFunc.pp
genstate.emitDeferChecks.RangeStmt_44619.pi
genstate.emitDeferChecks.RangeStmt_45357.pi
genstate.GenParm.mkctl
genstate.GenParm.BlockStmt.BlockStmt.mkt
genstate.emitAssignFuncs.b
mainPreamble
Generate.i
TunableParams.LimitInputs
genstate.GenParm.f
genstate.emitDeferChecks.RangeStmt_44398.BlockStmt.BlockStmt.n
genstate.emitChecker.haveControl
genstate.emitMain.fcnmask
ParseMaskString
ParseMaskString.RangeStmt_12407.BlockStmt.BlockStmt.j
Generate.BlockStmt.i
GenConfig.RandCtl
genstate.emitCompareFunc.rcvr
genstate.emitParamChecks.RangeStmt_41225.BlockStmt.BlockStmt.cel
genstate.emitReturn.RangeStmt_50942.BlockStmt.t
Generate.BlockStmt.BlockStmt.doemit
GenConfig.Tag
genstate.genParamDerefFunc.s
checkableElements.BlockStmt.RangeStmt_33280.fi
genstate.emitAssignFuncs.emit
genstate.genGlobVar.b
genstate.genGlobVar.tag
genstate.emitParamChecks.RangeStmt_41225.BlockStmt.BlockStmt.BlockStmt.BlockStmt.cvar
makeDir.fi
GenConfig.MaxFail
funcdef.mapdefs
runImports
Generate.mainoutfile
genstate.emitCompareFunc.BlockStmt.lelref
genstate.genAllocFunc.s
genstate.genParamRef.idx
genstate.emitRecursiveCall.RangeStmt_50135.p
genstate.emitMain.BlockStmt.i
genstate.tunables
genstate.GenFunc.needControl
genstate.emitDeferChecks.RangeStmt_44619.BlockStmt.BlockStmt.BlockStmt.cvar
genstate.emitReturn.BlockStmt.RangeStmt_51832.r
genstate.emitNewFuncs.emit
genstate.emitDeferChecks.RangeStmt_44398.p
genstate.GenFunc.BlockStmt.newparm
genstate.genGlobVar.pp
genstate.genAssignFunc
genstate.emitParamChecks.RangeStmt_41225.BlockStmt.BlockStmt.i
genstate.utilsPkg
Generate
checkTunables.RangeStmt_9660.v
funcdef.structdefs
genstate.emitDerefFuncs
genstate.GenReturn.s
genstate.GenFunc.BlockStmt.target
Verbctl
utilsTemplate
genstate.redistributeFraction
Generate.allfiles
genstate.emitMapKeyTmps.RangeStmt_28251.t
genstate.emitCaller.f
genstate.checkerFile.cp
ParseMaskString.RangeStmt_12407.BlockStmt.BlockStmt.err2
genstate.eqFuncRef.cp
genstate.genParamRef
genstate.openOutputFile.ipref
ParseMaskString.RangeStmt_12407.BlockStmt.BlockStmt.err
genstate.GenMapKeyType
genstate.globVars
genstate.GenValue.valstr
TunableParams.doDefer
TunableParams.LimitInputs.t
genstate.genAssignFunc.b
genstate.emitParamElemCheck.p
genstate.emitParamChecks.BlockStmt.BlockStmt.elparm
genstate.openOutputFile.filename
writeCom.i
genstate.genAssignFunc.s
genstate.emitDerefFuncs.emit
genstate.emitParamChecks.RangeStmt_41225.p
genstate.emitRecursiveCall.s
shouldEmitFP
shouldEmitFP.fn
genstate.GenValue.hashstr
checkableElements.BlockStmt.s
genstate.emitDeferChecks.pc
genstate.emitReturn.RangeStmt_50942.ri
shouldEmitFP.emitpk
StructTfIdx
genstate.wr
genstate.GenParm.BlockStmt.BlockStmt.nel
shouldEmitFP.pk
genstate.emitCaller.RangeStmt_30391.r
genstate.emitReturn.indirectReturn
genstate.GenValue.value
genstate.emitCaller.RangeStmt_30582.p
genstate.emitParamElemCheck.paramidx
TunableParams.addrFractions
genstate.redistributeFraction.BlockStmt.BlockStmt.RangeStmt_15939.i
genstate.newAllocFuncs
genstate.GenFunc
funcdesc.tag
checkTunables.RangeStmt_10174.v
funcdef.isMethod
genstate.emitCaller.pidx
genstate.emitDeferChecks.RangeStmt_44619.BlockStmt.cel
TunableParams.LimitOutputs.n
genstate.GenParm.BlockStmt.BlockStmt.mk
genstate.emitParamChecks.s
genstate.floatBits.s
genstate.emitCaller.value
genstate.emitCheckReturnsInCaller.failTag
genstate.emitNewFuncs.RangeStmt_35350.fd
genstate.emitGenValFuncs.f
genstate.emitParamChecks.RangeStmt_42892.pi
genstate.emitDeferChecks.RangeStmt_44619.BlockStmt.BlockStmt.BlockStmt._
runImports.coutput
genstate.genAddrTaken.s
genstate.GenParm.BlockStmt.BlockStmt.sp
genstate.genAssignFunc.pp
genstate.genParamRef.BlockStmt.f
genstate.emitDeferChecks.RangeStmt_44619.BlockStmt.which
funcdef.complexityMeasure.f
runImports.args
ParseMaskString.RangeStmt_12407.s
genstate.precludeSelectedTypes.f
genstate.GenValue.h
genstate.emitParamChecks.valstr
genstate.intBits
genstate.GenParm.BlockStmt.BlockStmt.pp
genstate.emitDeferChecks.RangeStmt_44619.BlockStmt.numel
Generate.s
TunableParams.DisableReflectionCalls
writeCom
genstate.GenValue.f
genstate.emitDerefFuncs.RangeStmt_34244.fd
TunableParams.floatBitRanges
genstate.emitStructAndArrayDefs.RangeStmt_26288.a
genstate.GenValue.caller
genstate.genReturnAssign.r
genstate.emitParamElemCheck.cm
genstate.emitParamChecks.RangeStmt_41225.BlockStmt.BlockStmt.numel
genstate.openOutputFile.s
genstate.intFlavor
genstate.GenParm.BlockStmt.BlockStmt.bp
genstate.emitChecker.RangeStmt_47668.ri
Generate.c
genstate.pkidx
genstate.emitParamElemCheck.f
funcdef.mapkeytmps
genstate.genGlobVar.s
genstate.GenPair.checkoutfile
Generate.BlockStmt.checkerImports
TunableParams.doReflectCall
funcdef.mapkeytypes
ParseMaskString.m
genstate.emitMapKeyTmps.caller
genstate.emitGlobalVars.emit
genstate.emitDeferChecks.RangeStmt_44619.BlockStmt.BlockStmt.elref
genstate.emitChecker
makeDir.err
TunableParams.sliceFraction
ParseMaskString.tag
genstate.popTunables
genstate.GenFunc.BlockStmt.r
CheckerName
funcdef.recur
genstate.emitDeferChecks.RangeStmt_44273.i
genstate.beginPackage.s
genstate.emitCheckReturnsInCaller.RangeStmt_28861.BlockStmt.curp
genstate.emitDeferChecks.value
genstate.genvalFuncs
genstate.emitChecker.RangeStmt_47930.BlockStmt.RangeStmt_47960.p
Members
X