// 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 } } } } }