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