github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/compile/internal/gc/mpint.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package gc 6 7 import ( 8 "fmt" 9 "math/big" 10 ) 11 12 // implements integer arithmetic 13 14 // Mpint represents an integer constant. 15 type Mpint struct { 16 Val big.Int 17 Ovf bool // set if Val overflowed compiler limit (sticky) 18 Rune bool // set if syntax indicates default type rune 19 } 20 21 func (a *Mpint) SetOverflow() { 22 a.Val.SetUint64(1) // avoid spurious div-zero errors 23 a.Ovf = true 24 } 25 26 func (a *Mpint) checkOverflow(extra int) bool { 27 // We don't need to be precise here, any reasonable upper limit would do. 28 // For now, use existing limit so we pass all the tests unchanged. 29 if a.Val.BitLen()+extra > Mpprec { 30 a.SetOverflow() 31 } 32 return a.Ovf 33 } 34 35 func (a *Mpint) Set(b *Mpint) { 36 a.Val.Set(&b.Val) 37 } 38 39 func (a *Mpint) SetFloat(b *Mpflt) bool { 40 // avoid converting huge floating-point numbers to integers 41 // (2*Mpprec is large enough to permit all tests to pass) 42 if b.Val.MantExp(nil) > 2*Mpprec { 43 a.SetOverflow() 44 return false 45 } 46 47 if _, acc := b.Val.Int(&a.Val); acc == big.Exact { 48 return true 49 } 50 51 const delta = 16 // a reasonably small number of bits > 0 52 var t big.Float 53 t.SetPrec(Mpprec - delta) 54 55 // try rounding down a little 56 t.SetMode(big.ToZero) 57 t.Set(&b.Val) 58 if _, acc := t.Int(&a.Val); acc == big.Exact { 59 return true 60 } 61 62 // try rounding up a little 63 t.SetMode(big.AwayFromZero) 64 t.Set(&b.Val) 65 if _, acc := t.Int(&a.Val); acc == big.Exact { 66 return true 67 } 68 69 a.Ovf = false 70 return false 71 } 72 73 func (a *Mpint) Add(b *Mpint) { 74 if a.Ovf || b.Ovf { 75 if nsavederrors+nerrors == 0 { 76 Fatalf("ovf in Mpint Add") 77 } 78 a.SetOverflow() 79 return 80 } 81 82 a.Val.Add(&a.Val, &b.Val) 83 84 if a.checkOverflow(0) { 85 yyerror("constant addition overflow") 86 } 87 } 88 89 func (a *Mpint) Sub(b *Mpint) { 90 if a.Ovf || b.Ovf { 91 if nsavederrors+nerrors == 0 { 92 Fatalf("ovf in Mpint Sub") 93 } 94 a.SetOverflow() 95 return 96 } 97 98 a.Val.Sub(&a.Val, &b.Val) 99 100 if a.checkOverflow(0) { 101 yyerror("constant subtraction overflow") 102 } 103 } 104 105 func (a *Mpint) Mul(b *Mpint) { 106 if a.Ovf || b.Ovf { 107 if nsavederrors+nerrors == 0 { 108 Fatalf("ovf in Mpint Mul") 109 } 110 a.SetOverflow() 111 return 112 } 113 114 a.Val.Mul(&a.Val, &b.Val) 115 116 if a.checkOverflow(0) { 117 yyerror("constant multiplication overflow") 118 } 119 } 120 121 func (a *Mpint) Quo(b *Mpint) { 122 if a.Ovf || b.Ovf { 123 if nsavederrors+nerrors == 0 { 124 Fatalf("ovf in Mpint Quo") 125 } 126 a.SetOverflow() 127 return 128 } 129 130 a.Val.Quo(&a.Val, &b.Val) 131 132 if a.checkOverflow(0) { 133 // can only happen for div-0 which should be checked elsewhere 134 yyerror("constant division overflow") 135 } 136 } 137 138 func (a *Mpint) Rem(b *Mpint) { 139 if a.Ovf || b.Ovf { 140 if nsavederrors+nerrors == 0 { 141 Fatalf("ovf in Mpint Rem") 142 } 143 a.SetOverflow() 144 return 145 } 146 147 a.Val.Rem(&a.Val, &b.Val) 148 149 if a.checkOverflow(0) { 150 // should never happen 151 yyerror("constant modulo overflow") 152 } 153 } 154 155 func (a *Mpint) Or(b *Mpint) { 156 if a.Ovf || b.Ovf { 157 if nsavederrors+nerrors == 0 { 158 Fatalf("ovf in Mpint Or") 159 } 160 a.SetOverflow() 161 return 162 } 163 164 a.Val.Or(&a.Val, &b.Val) 165 } 166 167 func (a *Mpint) And(b *Mpint) { 168 if a.Ovf || b.Ovf { 169 if nsavederrors+nerrors == 0 { 170 Fatalf("ovf in Mpint And") 171 } 172 a.SetOverflow() 173 return 174 } 175 176 a.Val.And(&a.Val, &b.Val) 177 } 178 179 func (a *Mpint) AndNot(b *Mpint) { 180 if a.Ovf || b.Ovf { 181 if nsavederrors+nerrors == 0 { 182 Fatalf("ovf in Mpint AndNot") 183 } 184 a.SetOverflow() 185 return 186 } 187 188 a.Val.AndNot(&a.Val, &b.Val) 189 } 190 191 func (a *Mpint) Xor(b *Mpint) { 192 if a.Ovf || b.Ovf { 193 if nsavederrors+nerrors == 0 { 194 Fatalf("ovf in Mpint Xor") 195 } 196 a.SetOverflow() 197 return 198 } 199 200 a.Val.Xor(&a.Val, &b.Val) 201 } 202 203 func (a *Mpint) Lsh(b *Mpint) { 204 if a.Ovf || b.Ovf { 205 if nsavederrors+nerrors == 0 { 206 Fatalf("ovf in Mpint Lsh") 207 } 208 a.SetOverflow() 209 return 210 } 211 212 s := b.Int64() 213 if s < 0 || s >= Mpprec { 214 msg := "shift count too large" 215 if s < 0 { 216 msg = "invalid negative shift count" 217 } 218 yyerror("%s: %d", msg, s) 219 a.SetInt64(0) 220 return 221 } 222 223 if a.checkOverflow(int(s)) { 224 yyerror("constant shift overflow") 225 return 226 } 227 a.Val.Lsh(&a.Val, uint(s)) 228 } 229 230 func (a *Mpint) Rsh(b *Mpint) { 231 if a.Ovf || b.Ovf { 232 if nsavederrors+nerrors == 0 { 233 Fatalf("ovf in Mpint Rsh") 234 } 235 a.SetOverflow() 236 return 237 } 238 239 s := b.Int64() 240 if s < 0 { 241 yyerror("invalid negative shift count: %d", s) 242 if a.Val.Sign() < 0 { 243 a.SetInt64(-1) 244 } else { 245 a.SetInt64(0) 246 } 247 return 248 } 249 250 a.Val.Rsh(&a.Val, uint(s)) 251 } 252 253 func (a *Mpint) Cmp(b *Mpint) int { 254 return a.Val.Cmp(&b.Val) 255 } 256 257 func (a *Mpint) CmpInt64(c int64) int { 258 if c == 0 { 259 return a.Val.Sign() // common case shortcut 260 } 261 return a.Val.Cmp(big.NewInt(c)) 262 } 263 264 func (a *Mpint) Neg() { 265 a.Val.Neg(&a.Val) 266 } 267 268 func (a *Mpint) Int64() int64 { 269 if a.Ovf { 270 if nsavederrors+nerrors == 0 { 271 Fatalf("constant overflow") 272 } 273 return 0 274 } 275 276 return a.Val.Int64() 277 } 278 279 func (a *Mpint) SetInt64(c int64) { 280 a.Val.SetInt64(c) 281 } 282 283 func (a *Mpint) SetString(as string) { 284 _, ok := a.Val.SetString(as, 0) 285 if !ok { 286 // The lexer checks for correct syntax of the literal 287 // and reports detailed errors. Thus SetString should 288 // never fail (in theory it might run out of memory, 289 // but that wouldn't be reported as an error here). 290 Fatalf("malformed integer constant: %s", as) 291 return 292 } 293 if a.checkOverflow(0) { 294 yyerror("constant too large: %s", as) 295 } 296 } 297 298 func (a *Mpint) GoString() string { 299 return a.Val.String() 300 } 301 302 func (a *Mpint) String() string { 303 return fmt.Sprintf("%#x", &a.Val) 304 }