[dev.regabi] strconv: add to bootstrap packages

go/constant relies on strconv for parsing Go literals, while older
versions of strconv either lack recent Go language features (e.g., Go
1.13's new numeric literals) or have errors (e.g., mishandling of
carriage returns in raw string literals prior to Go 1.8).

This requires two changes:

1. Splitting out the internal/bytealg dependency into a separate file,
which can be easily substituted with a simple loop for bootstrap
builds.

2. Updating eisel_lemire.go to not utilize Go 1.13 functionality
(underscores in numeric literals and signed shift counts).

Change-Id: Ib48a858a03b155eebdcd08d577aec2254337e70e
Reviewed-on: https://go-review.googlesource.com/c/go/+/272749
Reviewed-by: Robert Griesemer <gri@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
Trust: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Matthew Dempsky 2020-11-23 21:48:38 -08:00
parent c767d73227
commit 015423a15b
6 changed files with 42 additions and 15 deletions

View file

@ -18,7 +18,7 @@ func TestDeps(t *testing.T) {
} }
for _, dep := range strings.Fields(strings.Trim(string(out), "[]")) { for _, dep := range strings.Fields(strings.Trim(string(out), "[]")) {
switch dep { switch dep {
case "go/build", "go/token": case "go/build", "go/scanner":
t.Errorf("undesired dependency on %q", dep) t.Errorf("undesired dependency on %q", dep)
} }
} }

View file

@ -96,6 +96,7 @@ var bootstrapDirs = []string{
"debug/elf", "debug/elf",
"debug/macho", "debug/macho",
"debug/pe", "debug/pe",
"go/constant",
"internal/goversion", "internal/goversion",
"internal/race", "internal/race",
"internal/unsafeheader", "internal/unsafeheader",
@ -103,6 +104,7 @@ var bootstrapDirs = []string{
"math/big", "math/big",
"math/bits", "math/bits",
"sort", "sort",
"strconv",
} }
// File prefixes that are ignored by go/build anyway, and cause // File prefixes that are ignored by go/build anyway, and cause

14
src/strconv/bytealg.go Normal file
View file

@ -0,0 +1,14 @@
// Copyright 2009 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.
// +build !compiler_bootstrap
package strconv
import "internal/bytealg"
// contains reports whether the string contains the byte c.
func contains(s string, c byte) bool {
return bytealg.IndexByteString(s, c) != -1
}

View file

@ -0,0 +1,17 @@
// Copyright 2020 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.
// +build compiler_bootstrap
package strconv
// contains reports whether the string contains the byte c.
func contains(s string, c byte) bool {
for i := 0; i < len(s); i++ {
if s[i] == c {
return true
}
}
return false
}

View file

@ -29,7 +29,7 @@ func eiselLemire64(man uint64, exp10 int, neg bool) (f float64, ok bool) {
// Exp10 Range. // Exp10 Range.
if man == 0 { if man == 0 {
if neg { if neg {
f = math.Float64frombits(0x80000000_00000000) // Negative zero. f = math.Float64frombits(0x8000000000000000) // Negative zero.
} }
return f, true return f, true
} }
@ -39,7 +39,7 @@ func eiselLemire64(man uint64, exp10 int, neg bool) (f float64, ok bool) {
// Normalization. // Normalization.
clz := bits.LeadingZeros64(man) clz := bits.LeadingZeros64(man)
man <<= clz man <<= uint(clz)
const float64ExponentBias = 1023 const float64ExponentBias = 1023
retExp2 := uint64(217706*exp10>>16+64+float64ExponentBias) - uint64(clz) retExp2 := uint64(217706*exp10>>16+64+float64ExponentBias) - uint64(clz)
@ -84,9 +84,9 @@ func eiselLemire64(man uint64, exp10 int, neg bool) (f float64, ok bool) {
if retExp2-1 >= 0x7FF-1 { if retExp2-1 >= 0x7FF-1 {
return 0, false return 0, false
} }
retBits := retExp2<<52 | retMantissa&0x000FFFFF_FFFFFFFF retBits := retExp2<<52 | retMantissa&0x000FFFFFFFFFFFFF
if neg { if neg {
retBits |= 0x80000000_00000000 retBits |= 0x8000000000000000
} }
return math.Float64frombits(retBits), true return math.Float64frombits(retBits), true
} }
@ -114,7 +114,7 @@ func eiselLemire32(man uint64, exp10 int, neg bool) (f float32, ok bool) {
// Normalization. // Normalization.
clz := bits.LeadingZeros64(man) clz := bits.LeadingZeros64(man)
man <<= clz man <<= uint(clz)
const float32ExponentBias = 127 const float32ExponentBias = 127
retExp2 := uint64(217706*exp10>>16+64+float32ExponentBias) - uint64(clz) retExp2 := uint64(217706*exp10>>16+64+float32ExponentBias) - uint64(clz)
@ -122,13 +122,13 @@ func eiselLemire32(man uint64, exp10 int, neg bool) (f float32, ok bool) {
xHi, xLo := bits.Mul64(man, detailedPowersOfTen[exp10-detailedPowersOfTenMinExp10][1]) xHi, xLo := bits.Mul64(man, detailedPowersOfTen[exp10-detailedPowersOfTenMinExp10][1])
// Wider Approximation. // Wider Approximation.
if xHi&0x3F_FFFFFFFF == 0x3F_FFFFFFFF && xLo+man < man { if xHi&0x3FFFFFFFFF == 0x3FFFFFFFFF && xLo+man < man {
yHi, yLo := bits.Mul64(man, detailedPowersOfTen[exp10-detailedPowersOfTenMinExp10][0]) yHi, yLo := bits.Mul64(man, detailedPowersOfTen[exp10-detailedPowersOfTenMinExp10][0])
mergedHi, mergedLo := xHi, xLo+yHi mergedHi, mergedLo := xHi, xLo+yHi
if mergedLo < xLo { if mergedLo < xLo {
mergedHi++ mergedHi++
} }
if mergedHi&0x3F_FFFFFFFF == 0x3F_FFFFFFFF && mergedLo+1 == 0 && yLo+man < man { if mergedHi&0x3FFFFFFFFF == 0x3FFFFFFFFF && mergedLo+1 == 0 && yLo+man < man {
return 0, false return 0, false
} }
xHi, xLo = mergedHi, mergedLo xHi, xLo = mergedHi, mergedLo
@ -140,7 +140,7 @@ func eiselLemire32(man uint64, exp10 int, neg bool) (f float32, ok bool) {
retExp2 -= 1 ^ msb retExp2 -= 1 ^ msb
// Half-way Ambiguity. // Half-way Ambiguity.
if xLo == 0 && xHi&0x3F_FFFFFFFF == 0 && retMantissa&3 == 1 { if xLo == 0 && xHi&0x3FFFFFFFFF == 0 && retMantissa&3 == 1 {
return 0, false return 0, false
} }

View file

@ -7,7 +7,6 @@
package strconv package strconv
import ( import (
"internal/bytealg"
"unicode/utf8" "unicode/utf8"
) )
@ -436,11 +435,6 @@ func Unquote(s string) (string, error) {
return string(buf), nil return string(buf), nil
} }
// contains reports whether the string contains the byte c.
func contains(s string, c byte) bool {
return bytealg.IndexByteString(s, c) != -1
}
// bsearch16 returns the smallest i such that a[i] >= x. // bsearch16 returns the smallest i such that a[i] >= x.
// If there is no such i, bsearch16 returns len(a). // If there is no such i, bsearch16 returns len(a).
func bsearch16(a []uint16, x uint16) int { func bsearch16(a []uint16, x uint16) int {