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

     1  // Copyright 2021 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package generator
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"math"
    11  )
    12  
    13  // numparm describes a numeric parameter type; it implements the
    14  // "parm" interface.
    15  type numparm struct {
    16  	tag         string
    17  	widthInBits uint32
    18  	ctl         bool
    19  	isBlank
    20  	addrTakenHow
    21  	isGenValFunc
    22  	skipCompare
    23  }
    24  
    25  var f32parm *numparm = &numparm{
    26  	tag:         "float",
    27  	widthInBits: uint32(32),
    28  	ctl:         false,
    29  }
    30  var f64parm *numparm = &numparm{
    31  	tag:         "float",
    32  	widthInBits: uint32(64),
    33  	ctl:         false,
    34  }
    35  
    36  func (p numparm) TypeName() string {
    37  	if p.tag == "byte" {
    38  		return "byte"
    39  	}
    40  	return fmt.Sprintf("%s%d", p.tag, p.widthInBits)
    41  }
    42  
    43  func (p numparm) QualName() string {
    44  	return p.TypeName()
    45  }
    46  
    47  func (p numparm) String() string {
    48  	if p.tag == "byte" {
    49  		return "byte"
    50  	}
    51  	ctl := ""
    52  	if p.ctl {
    53  		ctl = " [ctl=yes]"
    54  	}
    55  	return fmt.Sprintf("%s%s", p.TypeName(), ctl)
    56  }
    57  
    58  func (p numparm) NumElements() int {
    59  	return 1
    60  }
    61  
    62  func (p numparm) IsControl() bool {
    63  	return p.ctl
    64  }
    65  
    66  func (p numparm) GenElemRef(elidx int, path string) (string, parm) {
    67  	return path, &p
    68  }
    69  
    70  func (p numparm) Declare(b *bytes.Buffer, prefix string, suffix string, caller bool) {
    71  	t := fmt.Sprintf("%s%d%s", p.tag, p.widthInBits, suffix)
    72  	if p.tag == "byte" {
    73  		t = fmt.Sprintf("%s%s", p.tag, suffix)
    74  	}
    75  	b.WriteString(prefix + " " + t)
    76  }
    77  
    78  func (p numparm) genRandNum(s *genstate, value int) (string, int) {
    79  	which := uint8(s.wr.Intn(int64(100)))
    80  	if p.tag == "int" {
    81  		var v int64
    82  		if which < 3 {
    83  			// max
    84  			v = (1 << (p.widthInBits - 1)) - 1
    85  
    86  		} else if which < 5 {
    87  			// min
    88  			v = (-1 << (p.widthInBits - 1))
    89  		} else {
    90  			nrange := int64(1 << (p.widthInBits - 2))
    91  			v = s.wr.Intn(nrange)
    92  			if value%2 != 0 {
    93  				v = -v
    94  			}
    95  		}
    96  		return fmt.Sprintf("%s%d(%d)", p.tag, p.widthInBits, v), value + 1
    97  	}
    98  	if p.tag == "uint" || p.tag == "byte" {
    99  		nrange := int64(1 << (p.widthInBits - 2))
   100  		v := s.wr.Intn(nrange)
   101  		if p.tag == "byte" {
   102  			return fmt.Sprintf("%s(%d)", p.tag, v), value + 1
   103  		}
   104  		return fmt.Sprintf("%s%d(0x%x)", p.tag, p.widthInBits, v), value + 1
   105  	}
   106  	if p.tag == "float" {
   107  		if p.widthInBits == 32 {
   108  			rf := s.wr.Float32() * (math.MaxFloat32 / 4)
   109  			if value%2 != 0 {
   110  				rf = -rf
   111  			}
   112  			return fmt.Sprintf("%s%d(%v)", p.tag, p.widthInBits, rf), value + 1
   113  		}
   114  		if p.widthInBits == 64 {
   115  			return fmt.Sprintf("%s%d(%v)", p.tag, p.widthInBits,
   116  				s.wr.NormFloat64()), value + 1
   117  		}
   118  		panic("unknown float type")
   119  	}
   120  	if p.tag == "complex" {
   121  		if p.widthInBits == 64 {
   122  			f1, v2 := f32parm.genRandNum(s, value)
   123  			f2, v3 := f32parm.genRandNum(s, v2)
   124  			return fmt.Sprintf("complex(%s,%s)", f1, f2), v3
   125  		}
   126  		if p.widthInBits == 128 {
   127  			f1, v2 := f64parm.genRandNum(s, value)
   128  			f2, v3 := f64parm.genRandNum(s, v2)
   129  			return fmt.Sprintf("complex(%v,%v)", f1, f2), v3
   130  		}
   131  		panic("unknown complex type")
   132  	}
   133  	panic("unknown numeric type")
   134  }
   135  
   136  func (p numparm) GenValue(s *genstate, f *funcdef, value int, caller bool) (string, int) {
   137  	r, nv := p.genRandNum(s, value)
   138  	verb(5, "numparm.GenValue(%d) = %s", value, r)
   139  	return r, nv
   140  }
   141  
   142  func (p numparm) HasPointer() bool {
   143  	return false
   144  }