Home | History | Annotate | Download | only in fixedbugs
      1 // runoutput
      2 
      3 // Copyright 2015 The Go Authors. All rights reserved.
      4 // Use of this source code is governed by a BSD-style
      5 // license that can be found in the LICENSE file.
      6 
      7 package main
      8 
      9 import (
     10 	"fmt"
     11 	"math/big"
     12 	"unsafe"
     13 )
     14 
     15 var one = big.NewInt(1)
     16 
     17 type _type struct {
     18 	name   string
     19 	bits   uint
     20 	signed bool
     21 }
     22 
     23 // testvalues returns a list of all test values for this type.
     24 func (t *_type) testvalues() []*big.Int {
     25 	var a []*big.Int
     26 
     27 	a = append(a, big.NewInt(0))
     28 	a = append(a, big.NewInt(1))
     29 	a = append(a, big.NewInt(2))
     30 	if t.signed {
     31 		a = append(a, big.NewInt(-1))
     32 		a = append(a, big.NewInt(-2))
     33 		r := big.NewInt(1)
     34 		a = append(a, r.Lsh(r, t.bits-1).Sub(r, big.NewInt(1)))
     35 		r = big.NewInt(1)
     36 		a = append(a, r.Lsh(r, t.bits-1).Sub(r, big.NewInt(2)))
     37 		r = big.NewInt(1)
     38 		a = append(a, r.Lsh(r, t.bits-1).Neg(r))
     39 		r = big.NewInt(1)
     40 		a = append(a, r.Lsh(r, t.bits-1).Neg(r).Add(r, big.NewInt(1)))
     41 	} else {
     42 		r := big.NewInt(1)
     43 		a = append(a, r.Lsh(r, t.bits).Sub(r, big.NewInt(1)))
     44 		r = big.NewInt(1)
     45 		a = append(a, r.Lsh(r, t.bits).Sub(r, big.NewInt(2)))
     46 	}
     47 	return a
     48 }
     49 
     50 // trunc truncates a value to the range of the given type.
     51 func (t *_type) trunc(x *big.Int) *big.Int {
     52 	r := new(big.Int)
     53 	m := new(big.Int)
     54 	m.Lsh(one, t.bits)
     55 	m.Sub(m, one)
     56 	r.And(x, m)
     57 	if t.signed && r.Bit(int(t.bits)-1) == 1 {
     58 		m.Neg(one)
     59 		m.Lsh(m, t.bits)
     60 		r.Or(r, m)
     61 	}
     62 	return r
     63 }
     64 
     65 var types = []_type{
     66 	_type{"byte", 8, false},
     67 	_type{"int8", 8, true},
     68 	_type{"uint8", 8, false},
     69 	_type{"rune", 32, true},
     70 	_type{"int16", 16, true},
     71 	_type{"uint16", 16, false},
     72 	_type{"int32", 32, true},
     73 	_type{"uint32", 32, false},
     74 	_type{"int64", 64, true},
     75 	_type{"uint64", 64, false},
     76 	_type{"int", 8 * uint(unsafe.Sizeof(int(0))), true},
     77 	_type{"uint", 8 * uint(unsafe.Sizeof(uint(0))), false},
     78 	_type{"uintptr", 8 * uint(unsafe.Sizeof((*byte)(nil))), false},
     79 }
     80 
     81 type binop struct {
     82 	name string
     83 	eval func(x, y *big.Int) *big.Int
     84 }
     85 
     86 var binops = []binop{
     87 	binop{"+", func(x, y *big.Int) *big.Int { return new(big.Int).Add(x, y) }},
     88 	binop{"-", func(x, y *big.Int) *big.Int { return new(big.Int).Sub(x, y) }},
     89 	binop{"*", func(x, y *big.Int) *big.Int { return new(big.Int).Mul(x, y) }},
     90 	binop{"/", func(x, y *big.Int) *big.Int { return new(big.Int).Quo(x, y) }},
     91 	binop{"%", func(x, y *big.Int) *big.Int { return new(big.Int).Rem(x, y) }},
     92 	binop{"&", func(x, y *big.Int) *big.Int { return new(big.Int).And(x, y) }},
     93 	binop{"|", func(x, y *big.Int) *big.Int { return new(big.Int).Or(x, y) }},
     94 	binop{"^", func(x, y *big.Int) *big.Int { return new(big.Int).Xor(x, y) }},
     95 	binop{"&^", func(x, y *big.Int) *big.Int { return new(big.Int).AndNot(x, y) }},
     96 }
     97 
     98 type unop struct {
     99 	name string
    100 	eval func(x *big.Int) *big.Int
    101 }
    102 
    103 var unops = []unop{
    104 	unop{"+", func(x *big.Int) *big.Int { return new(big.Int).Set(x) }},
    105 	unop{"-", func(x *big.Int) *big.Int { return new(big.Int).Neg(x) }},
    106 	unop{"^", func(x *big.Int) *big.Int { return new(big.Int).Not(x) }},
    107 }
    108 
    109 type shiftop struct {
    110 	name string
    111 	eval func(x *big.Int, i uint) *big.Int
    112 }
    113 
    114 var shiftops = []shiftop{
    115 	shiftop{"<<", func(x *big.Int, i uint) *big.Int { return new(big.Int).Lsh(x, i) }},
    116 	shiftop{">>", func(x *big.Int, i uint) *big.Int { return new(big.Int).Rsh(x, i) }},
    117 }
    118 
    119 // valname returns the name of n as can be used as part of a variable name.
    120 func valname(n *big.Int) string {
    121 	s := fmt.Sprintf("%d", n)
    122 	if s[0] == '-' {
    123 		s = "neg" + s[1:]
    124 	}
    125 	return s
    126 }
    127 
    128 func main() {
    129 	fmt.Println("package main")
    130 
    131 	// We make variables to hold all the different values we'd like to use.
    132 	// We use global variables to prevent any constant folding.
    133 	for _, t := range types {
    134 		for _, n := range t.testvalues() {
    135 			fmt.Printf("var %s_%s %s = %d\n", t.name, valname(n), t.name, n)
    136 		}
    137 	}
    138 
    139 	fmt.Println("func main() {")
    140 
    141 	for _, t := range types {
    142 		// test binary ops
    143 		for _, op := range binops {
    144 			for _, x := range t.testvalues() {
    145 				for _, y := range t.testvalues() {
    146 					if (op.name == "/" || op.name == "%") && y.Sign() == 0 {
    147 						continue
    148 					}
    149 					r := t.trunc(op.eval(x, y))
    150 					eqn := fmt.Sprintf("%s_%s %s %s_%s != %d", t.name, valname(x), op.name, t.name, valname(y), r)
    151 					fmt.Printf("\tif %s { println(\"bad: %s\") }\n", eqn, eqn)
    152 				}
    153 			}
    154 		}
    155 		// test unary ops
    156 		for _, op := range unops {
    157 			for _, x := range t.testvalues() {
    158 				r := t.trunc(op.eval(x))
    159 				eqn := fmt.Sprintf("%s %s_%s != %d", op.name, t.name, valname(x), r)
    160 				fmt.Printf("\tif %s { println(\"bad: %s\") }\n", eqn, eqn)
    161 			}
    162 		}
    163 		// test shifts
    164 		for _, op := range shiftops {
    165 			for _, x := range t.testvalues() {
    166 
    167 				for _, i := range []uint{0, 1, t.bits - 2, t.bits - 1, t.bits, t.bits + 1} {
    168 					r := t.trunc(op.eval(x, i))
    169 					eqn := fmt.Sprintf("%s_%s %s %d != %d", t.name, valname(x), op.name, i, r)
    170 					fmt.Printf("\tif %s { println(\"bad: %s\") }\n", eqn, eqn)
    171 				}
    172 			}
    173 		}
    174 	}
    175 
    176 	fmt.Println("}")
    177 }
    178