| // skip | |
| // NOTE: the actual tests to run are rotate[0123].go | |
| // Copyright 2012 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| // Generate test of shift and rotate by constants. | |
| // The output is compiled and run. | |
| // | |
| // The integer type depends on the value of mode (rotate direction, | |
| // signedness). | |
| package main | |
| import ( | |
| "bufio" | |
| "flag" | |
| "fmt" | |
| "os" | |
| "strings" | |
| ) | |
| func main() { | |
| flag.Parse() | |
| b := bufio.NewWriter(os.Stdout) | |
| defer b.Flush() | |
| fmt.Fprintf(b, "%s\n", prolog) | |
| for logBits := uint(3); logBits <= 6; logBits++ { | |
| typ := fmt.Sprintf("int%d", 1<<logBits) | |
| fmt.Fprint(b, strings.Replace(checkFunc, "XXX", typ, -1)) | |
| fmt.Fprint(b, strings.Replace(checkFunc, "XXX", "u"+typ, -1)) | |
| gentest(b, 1<<logBits, mode&1 != 0, mode&2 != 0) | |
| } | |
| } | |
| const prolog = ` | |
| package main | |
| import ( | |
| "fmt" | |
| "os" | |
| ) | |
| var ( | |
| i8 int8 = 0x12 | |
| i16 int16 = 0x1234 | |
| i32 int32 = 0x12345678 | |
| i64 int64 = 0x123456789abcdef0 | |
| ui8 uint8 = 0x12 | |
| ui16 uint16 = 0x1234 | |
| ui32 uint32 = 0x12345678 | |
| ui64 uint64 = 0x123456789abcdef0 | |
| ni8 = ^i8 | |
| ni16 = ^i16 | |
| ni32 = ^i32 | |
| ni64 = ^i64 | |
| nui8 = ^ui8 | |
| nui16 = ^ui16 | |
| nui32 = ^ui32 | |
| nui64 = ^ui64 | |
| ) | |
| var nfail = 0 | |
| func main() { | |
| if nfail > 0 { | |
| fmt.Printf("BUG\n") | |
| } | |
| } | |
| ` | |
| const checkFunc = ` | |
| func check_XXX(desc string, have, want XXX) { | |
| if have != want { | |
| nfail++ | |
| fmt.Printf("%s = %T(%#x), want %T(%#x)\n", desc, have, have, want, want) | |
| if nfail >= 100 { | |
| fmt.Printf("BUG: stopping after 100 failures\n") | |
| os.Exit(0) | |
| } | |
| } | |
| } | |
| ` | |
| var ( | |
| uop = [2]func(x, y uint64) uint64{ | |
| func(x, y uint64) uint64 { | |
| return x | y | |
| }, | |
| func(x, y uint64) uint64 { | |
| return x ^ y | |
| }, | |
| } | |
| iop = [2]func(x, y int64) int64{ | |
| func(x, y int64) int64 { | |
| return x | y | |
| }, | |
| func(x, y int64) int64 { | |
| return x ^ y | |
| }, | |
| } | |
| cop = [2]byte{'|', '^'} | |
| ) | |
| func gentest(b *bufio.Writer, bits uint, unsigned, inverted bool) { | |
| fmt.Fprintf(b, "func init() {\n") | |
| defer fmt.Fprintf(b, "}\n") | |
| n := 0 | |
| // Generate tests for left/right and right/left. | |
| for l := uint(0); l <= bits; l++ { | |
| for r := uint(0); r <= bits; r++ { | |
| for o, op := range cop { | |
| typ := fmt.Sprintf("int%d", bits) | |
| v := fmt.Sprintf("i%d", bits) | |
| if unsigned { | |
| typ = "u" + typ | |
| v = "u" + v | |
| } | |
| v0 := int64(0x123456789abcdef0) | |
| if inverted { | |
| v = "n" + v | |
| v0 = ^v0 | |
| } | |
| expr1 := fmt.Sprintf("%s<<%d %c %s>>%d", v, l, op, v, r) | |
| expr2 := fmt.Sprintf("%s>>%d %c %s<<%d", v, r, op, v, l) | |
| var result string | |
| if unsigned { | |
| v := uint64(v0) >> (64 - bits) | |
| v = uop[o](v<<l, v>>r) | |
| v <<= 64 - bits | |
| v >>= 64 - bits | |
| result = fmt.Sprintf("%#x", v) | |
| } else { | |
| v := int64(v0) >> (64 - bits) | |
| v = iop[o](v<<l, v>>r) | |
| v <<= 64 - bits | |
| v >>= 64 - bits | |
| result = fmt.Sprintf("%#x", v) | |
| } | |
| fmt.Fprintf(b, "\tcheck_%s(%q, %s, %s(%s))\n", typ, expr1, expr1, typ, result) | |
| fmt.Fprintf(b, "\tcheck_%s(%q, %s, %s(%s))\n", typ, expr2, expr2, typ, result) | |
| // Chop test into multiple functions so that there's not one | |
| // enormous function to compile/link. | |
| // All the functions are named init so we don't have to do | |
| // anything special to call them. ☺ | |
| if n++; n >= 50 { | |
| fmt.Fprintf(b, "}\n") | |
| fmt.Fprintf(b, "func init() {\n") | |
| n = 0 | |
| } | |
| } | |
| } | |
| } | |
| } |