mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
cmd/compile/internal/noder: write V2 bitstream aliastypeparams=1
Enables V2 unified IR bitstreams when GOEXPERIMENT aliastypeparams are enabled. Allows pkgbits.NewPkgEncoder to set the output version. Reenables support for writing V0 streams. Updates #68778 Updates #68526 Change-Id: I590c494d81ab7db148232ceaba52229068d1e986 Reviewed-on: https://go-review.googlesource.com/c/go/+/608595 Reviewed-by: David Chase <drchase@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
This commit is contained in:
parent
6d52d7d22b
commit
9e8ea567c8
@ -6,6 +6,7 @@ package noder
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"internal/buildcfg"
|
||||||
"internal/pkgbits"
|
"internal/pkgbits"
|
||||||
"internal/types/errors"
|
"internal/types/errors"
|
||||||
"io"
|
"io"
|
||||||
@ -462,8 +463,13 @@ func readPackage(pr *pkgReader, importpkg *types.Pkg, localStub bool) {
|
|||||||
// writeUnifiedExport writes to `out` the finalized, self-contained
|
// writeUnifiedExport writes to `out` the finalized, self-contained
|
||||||
// Unified IR export data file for the current compilation unit.
|
// Unified IR export data file for the current compilation unit.
|
||||||
func writeUnifiedExport(out io.Writer) {
|
func writeUnifiedExport(out io.Writer) {
|
||||||
|
// Use V2 as the encoded version aliastypeparams GOEXPERIMENT is enabled.
|
||||||
|
version := pkgbits.V1
|
||||||
|
if buildcfg.Experiment.AliasTypeParams {
|
||||||
|
version = pkgbits.V2
|
||||||
|
}
|
||||||
l := linker{
|
l := linker{
|
||||||
pw: pkgbits.NewPkgEncoder(base.Debug.SyncFrames),
|
pw: pkgbits.NewPkgEncoder(version, base.Debug.SyncFrames),
|
||||||
|
|
||||||
pkgs: make(map[string]index),
|
pkgs: make(map[string]index),
|
||||||
decls: make(map[*types.Sym]index),
|
decls: make(map[*types.Sym]index),
|
||||||
|
@ -96,8 +96,13 @@ type pkgWriter struct {
|
|||||||
// newPkgWriter returns an initialized pkgWriter for the specified
|
// newPkgWriter returns an initialized pkgWriter for the specified
|
||||||
// package.
|
// package.
|
||||||
func newPkgWriter(m posMap, pkg *types2.Package, info *types2.Info, otherInfo map[*syntax.FuncLit]bool) *pkgWriter {
|
func newPkgWriter(m posMap, pkg *types2.Package, info *types2.Info, otherInfo map[*syntax.FuncLit]bool) *pkgWriter {
|
||||||
|
// Use V2 as the encoded version aliastypeparams GOEXPERIMENT is enabled.
|
||||||
|
version := pkgbits.V1
|
||||||
|
if buildcfg.Experiment.AliasTypeParams {
|
||||||
|
version = pkgbits.V2
|
||||||
|
}
|
||||||
return &pkgWriter{
|
return &pkgWriter{
|
||||||
PkgEncoder: pkgbits.NewPkgEncoder(base.Debug.SyncFrames),
|
PkgEncoder: pkgbits.NewPkgEncoder(version, base.Debug.SyncFrames),
|
||||||
|
|
||||||
m: m,
|
m: m,
|
||||||
curpkg: pkg,
|
curpkg: pkg,
|
||||||
@ -864,8 +869,7 @@ func (w *writer) doObj(wext *writer, obj types2.Object) pkgbits.CodeObj {
|
|||||||
if w.Version().Has(pkgbits.AliasTypeParamNames) {
|
if w.Version().Has(pkgbits.AliasTypeParamNames) {
|
||||||
w.typeParamNames(tparams)
|
w.typeParamNames(tparams)
|
||||||
}
|
}
|
||||||
// TODO(taking): enable this assertion once this is not intended to be a nop.
|
assert(w.Version().Has(pkgbits.AliasTypeParamNames) || tparams.Len() == 0)
|
||||||
// assert(w.Version().Has(pkgbits.AliasTypeParamNames) || tparams.Len() == 0)
|
|
||||||
w.typ(rhs)
|
w.typ(rhs)
|
||||||
return pkgbits.ObjAlias
|
return pkgbits.ObjAlias
|
||||||
}
|
}
|
||||||
|
@ -82,8 +82,8 @@ func NewPkgDecoder(pkgPath, input string) PkgDecoder {
|
|||||||
assert(binary.Read(r, binary.LittleEndian, &ver) == nil)
|
assert(binary.Read(r, binary.LittleEndian, &ver) == nil)
|
||||||
pr.version = Version(ver)
|
pr.version = Version(ver)
|
||||||
|
|
||||||
if pr.version >= V2 { // TODO(taking): Switch to numVersions.
|
if pr.version >= numVersions {
|
||||||
panic(fmt.Errorf("cannot decode %q, export data version %d is too new", pkgPath, pr.version))
|
panic(fmt.Errorf("cannot decode %q, export data version %d is greater than maximum supported version %d", pkgPath, pr.version, numVersions-1))
|
||||||
}
|
}
|
||||||
|
|
||||||
if pr.version.Has(Flags) {
|
if pr.version.Has(Flags) {
|
||||||
@ -101,7 +101,9 @@ func NewPkgDecoder(pkgPath, input string) PkgDecoder {
|
|||||||
assert(err == nil)
|
assert(err == nil)
|
||||||
|
|
||||||
pr.elemData = input[pos:]
|
pr.elemData = input[pos:]
|
||||||
assert(len(pr.elemData)-8 == int(pr.elemEnds[len(pr.elemEnds)-1]))
|
|
||||||
|
const fingerprintSize = 8
|
||||||
|
assert(len(pr.elemData)-fingerprintSize == int(pr.elemEnds[len(pr.elemEnds)-1]))
|
||||||
|
|
||||||
return pr
|
return pr
|
||||||
}
|
}
|
||||||
|
@ -15,9 +15,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// currentVersion is the current version number written.
|
|
||||||
const currentVersion = V1
|
|
||||||
|
|
||||||
// A PkgEncoder provides methods for encoding a package's Unified IR
|
// A PkgEncoder provides methods for encoding a package's Unified IR
|
||||||
// export data.
|
// export data.
|
||||||
type PkgEncoder struct {
|
type PkgEncoder struct {
|
||||||
@ -47,10 +44,9 @@ func (pw *PkgEncoder) SyncMarkers() bool { return pw.syncFrames >= 0 }
|
|||||||
// export data files, but can help diagnosing desync errors in
|
// export data files, but can help diagnosing desync errors in
|
||||||
// higher-level Unified IR reader/writer code. If syncFrames is
|
// higher-level Unified IR reader/writer code. If syncFrames is
|
||||||
// negative, then sync markers are omitted entirely.
|
// negative, then sync markers are omitted entirely.
|
||||||
func NewPkgEncoder(syncFrames int) PkgEncoder {
|
func NewPkgEncoder(version Version, syncFrames int) PkgEncoder {
|
||||||
return PkgEncoder{
|
return PkgEncoder{
|
||||||
// TODO(taking): Change NewPkgEncoder to take a version as an argument, and remove currentVersion.
|
version: version,
|
||||||
version: currentVersion,
|
|
||||||
stringsIdx: make(map[string]Index),
|
stringsIdx: make(map[string]Index),
|
||||||
syncFrames: syncFrames,
|
syncFrames: syncFrames,
|
||||||
}
|
}
|
||||||
@ -68,11 +64,13 @@ func (pw *PkgEncoder) DumpTo(out0 io.Writer) (fingerprint [8]byte) {
|
|||||||
|
|
||||||
writeUint32(uint32(pw.version))
|
writeUint32(uint32(pw.version))
|
||||||
|
|
||||||
var flags uint32
|
if pw.version.Has(Flags) {
|
||||||
if pw.SyncMarkers() {
|
var flags uint32
|
||||||
flags |= flagSyncMarkers
|
if pw.SyncMarkers() {
|
||||||
|
flags |= flagSyncMarkers
|
||||||
|
}
|
||||||
|
writeUint32(flags)
|
||||||
}
|
}
|
||||||
writeUint32(flags)
|
|
||||||
|
|
||||||
// Write elemEndsEnds.
|
// Write elemEndsEnds.
|
||||||
var sum uint32
|
var sum uint32
|
||||||
|
@ -11,19 +11,25 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestRoundTrip(t *testing.T) {
|
func TestRoundTrip(t *testing.T) {
|
||||||
pw := pkgbits.NewPkgEncoder(-1)
|
for _, version := range []pkgbits.Version{
|
||||||
w := pw.NewEncoder(pkgbits.RelocMeta, pkgbits.SyncPublic)
|
pkgbits.V0,
|
||||||
w.Flush()
|
pkgbits.V1,
|
||||||
|
pkgbits.V2,
|
||||||
|
} {
|
||||||
|
pw := pkgbits.NewPkgEncoder(version, -1)
|
||||||
|
w := pw.NewEncoder(pkgbits.RelocMeta, pkgbits.SyncPublic)
|
||||||
|
w.Flush()
|
||||||
|
|
||||||
var b strings.Builder
|
var b strings.Builder
|
||||||
_ = pw.DumpTo(&b)
|
_ = pw.DumpTo(&b)
|
||||||
input := b.String()
|
input := b.String()
|
||||||
|
|
||||||
pr := pkgbits.NewPkgDecoder("package_id", input)
|
pr := pkgbits.NewPkgDecoder("package_id", input)
|
||||||
r := pr.NewDecoder(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic)
|
r := pr.NewDecoder(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic)
|
||||||
|
|
||||||
if r.Version() != w.Version() {
|
if r.Version() != w.Version() {
|
||||||
t.Errorf("Expected reader version %q to be the writer version %q", r.Version(), w.Version())
|
t.Errorf("Expected reader version %q to be the writer version %q", r.Version(), w.Version())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,8 +6,7 @@
|
|||||||
|
|
||||||
package a
|
package a
|
||||||
|
|
||||||
// TODO(#68778): enable once type parameterized aliases are allowed in exportdata.
|
type A[T any] = struct{ F T }
|
||||||
// type A[T any] = struct{ F T }
|
|
||||||
|
|
||||||
type B = struct{ F int }
|
type B = struct{ F int }
|
||||||
|
|
||||||
|
@ -7,12 +7,14 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"issue68526.dir/a"
|
"issue68526.dir/a"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
unexported()
|
unexported()
|
||||||
// exported()
|
exported()
|
||||||
}
|
}
|
||||||
|
|
||||||
func unexported() {
|
func unexported() {
|
||||||
@ -23,23 +25,21 @@ func unexported() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(#68778): enable once type parameterized aliases are allowed in exportdata.
|
func exported() {
|
||||||
|
var (
|
||||||
|
astr a.A[string]
|
||||||
|
aint a.A[int]
|
||||||
|
)
|
||||||
|
|
||||||
// func exported() {
|
if any(astr) != any(struct{ F string }{}) || any(aint) != any(struct{ F int }{}) {
|
||||||
// var (
|
panic("zero value of alias and concrete type not identical")
|
||||||
// astr a.A[string]
|
}
|
||||||
// aint a.A[int]
|
|
||||||
// )
|
|
||||||
|
|
||||||
// if any(astr) != any(struct{ F string }{}) || any(aint) != any(struct{ F int }{}) {
|
if any(astr) == any(aint) {
|
||||||
// panic("zero value of alias and concrete type not identical")
|
panic("zero value of struct{ F string } and struct{ F int } are not distinct")
|
||||||
// }
|
}
|
||||||
|
|
||||||
// if any(astr) == any(aint) {
|
if got := fmt.Sprintf("%T", astr); got != "struct { F string }" {
|
||||||
// panic("zero value of struct{ F string } and struct{ F int } are not distinct")
|
panic(got)
|
||||||
// }
|
}
|
||||||
|
}
|
||||||
// if got := fmt.Sprintf("%T", astr); got != "struct { F string }" {
|
|
||||||
// panic(got)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user