1// skip
2
3// NOTE: the actual tests to run are rotate[0123].go
4
5// Copyright 2012 The Go Authors.  All rights reserved.
6// Use of this source code is governed by a BSD-style
7// license that can be found in the LICENSE file.
8
9// Generate test of shift and rotate by constants.
10// The output is compiled and run.
11//
12// The integer type depends on the value of mode (rotate direction,
13// signedness).
14
15package main
16
17import (
18	"bufio"
19	"flag"
20	"fmt"
21	"os"
22	"strings"
23)
24
25func main() {
26	flag.Parse()
27
28	b := bufio.NewWriter(os.Stdout)
29	defer b.Flush()
30
31	fmt.Fprintf(b, "%s\n", prolog)
32
33	for logBits := uint(3); logBits <= 6; logBits++ {
34		typ := fmt.Sprintf("int%d", 1<<logBits)
35		fmt.Fprint(b, strings.Replace(checkFunc, "XXX", typ, -1))
36		fmt.Fprint(b, strings.Replace(checkFunc, "XXX", "u"+typ, -1))
37		gentest(b, 1<<logBits, mode&1 != 0, mode&2 != 0)
38	}
39}
40
41const prolog = `
42
43package main
44
45import (
46	"fmt"
47	"os"
48)
49
50var (
51	i8 int8 = 0x12
52	i16 int16 = 0x1234
53	i32 int32 = 0x12345678
54	i64 int64 = 0x123456789abcdef0
55	ui8 uint8 = 0x12
56	ui16 uint16 = 0x1234
57	ui32 uint32 = 0x12345678
58	ui64 uint64 = 0x123456789abcdef0
59
60	ni8 = ^i8
61	ni16 = ^i16
62	ni32 = ^i32
63	ni64 = ^i64
64	nui8 = ^ui8
65	nui16 = ^ui16
66	nui32 = ^ui32
67	nui64 = ^ui64
68)
69
70var nfail = 0
71
72func main() {
73	if nfail > 0 {
74		fmt.Printf("BUG\n")
75	}
76}
77
78`
79
80const checkFunc = `
81func check_XXX(desc string, have, want XXX) {
82	if have != want {
83		nfail++
84		fmt.Printf("%s = %T(%#x), want %T(%#x)\n", desc, have, have, want, want)
85		if nfail >= 100 {
86			fmt.Printf("BUG: stopping after 100 failures\n")
87			os.Exit(0)
88		}
89	}
90}
91`
92
93var (
94	uop = [2]func(x, y uint64) uint64{
95		func(x, y uint64) uint64 {
96			return x | y
97		},
98		func(x, y uint64) uint64 {
99			return x ^ y
100		},
101	}
102	iop = [2]func(x, y int64) int64{
103		func(x, y int64) int64 {
104			return x | y
105		},
106		func(x, y int64) int64 {
107			return x ^ y
108		},
109	}
110	cop = [2]byte{'|', '^'}
111)
112
113func gentest(b *bufio.Writer, bits uint, unsigned, inverted bool) {
114	fmt.Fprintf(b, "func init() {\n")
115	defer fmt.Fprintf(b, "}\n")
116	n := 0
117
118	// Generate tests for left/right and right/left.
119	for l := uint(0); l <= bits; l++ {
120		for r := uint(0); r <= bits; r++ {
121			for o, op := range cop {
122				typ := fmt.Sprintf("int%d", bits)
123				v := fmt.Sprintf("i%d", bits)
124				if unsigned {
125					typ = "u" + typ
126					v = "u" + v
127				}
128				v0 := int64(0x123456789abcdef0)
129				if inverted {
130					v = "n" + v
131					v0 = ^v0
132				}
133				expr1 := fmt.Sprintf("%s<<%d %c %s>>%d", v, l, op, v, r)
134				expr2 := fmt.Sprintf("%s>>%d %c %s<<%d", v, r, op, v, l)
135
136				var result string
137				if unsigned {
138					v := uint64(v0) >> (64 - bits)
139					v = uop[o](v<<l, v>>r)
140					v <<= 64 - bits
141					v >>= 64 - bits
142					result = fmt.Sprintf("%#x", v)
143				} else {
144					v := int64(v0) >> (64 - bits)
145					v = iop[o](v<<l, v>>r)
146					v <<= 64 - bits
147					v >>= 64 - bits
148					result = fmt.Sprintf("%#x", v)
149				}
150
151				fmt.Fprintf(b, "\tcheck_%s(%q, %s, %s(%s))\n", typ, expr1, expr1, typ, result)
152				fmt.Fprintf(b, "\tcheck_%s(%q, %s, %s(%s))\n", typ, expr2, expr2, typ, result)
153
154				// Chop test into multiple functions so that there's not one
155				// enormous function to compile/link.
156				// All the functions are named init so we don't have to do
157				// anything special to call them.  ☺
158				if n++; n >= 50 {
159					fmt.Fprintf(b, "}\n")
160					fmt.Fprintf(b, "func init() {\n")
161					n = 0
162				}
163			}
164		}
165	}
166}
167