Skip to content

Commit

Permalink
cmd/compile/internal/noder: write V2 bitstream aliastypeparams=1
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
timothy-king committed Aug 28, 2024
1 parent 6d52d7d commit 9e8ea56
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 47 deletions.
8 changes: 7 additions & 1 deletion src/cmd/compile/internal/noder/unified.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package noder

import (
"fmt"
"internal/buildcfg"
"internal/pkgbits"
"internal/types/errors"
"io"
Expand Down Expand Up @@ -462,8 +463,13 @@ func readPackage(pr *pkgReader, importpkg *types.Pkg, localStub bool) {
// writeUnifiedExport writes to `out` the finalized, self-contained
// Unified IR export data file for the current compilation unit.
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{
pw: pkgbits.NewPkgEncoder(base.Debug.SyncFrames),
pw: pkgbits.NewPkgEncoder(version, base.Debug.SyncFrames),

pkgs: make(map[string]index),
decls: make(map[*types.Sym]index),
Expand Down
10 changes: 7 additions & 3 deletions src/cmd/compile/internal/noder/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,13 @@ type pkgWriter struct {
// newPkgWriter returns an initialized pkgWriter for the specified
// package.
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{
PkgEncoder: pkgbits.NewPkgEncoder(base.Debug.SyncFrames),
PkgEncoder: pkgbits.NewPkgEncoder(version, base.Debug.SyncFrames),

m: m,
curpkg: pkg,
Expand Down Expand Up @@ -864,8 +869,7 @@ func (w *writer) doObj(wext *writer, obj types2.Object) pkgbits.CodeObj {
if w.Version().Has(pkgbits.AliasTypeParamNames) {
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)
return pkgbits.ObjAlias
}
Expand Down
8 changes: 5 additions & 3 deletions src/internal/pkgbits/decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ func NewPkgDecoder(pkgPath, input string) PkgDecoder {
assert(binary.Read(r, binary.LittleEndian, &ver) == nil)
pr.version = Version(ver)

if pr.version >= V2 { // TODO(taking): Switch to numVersions.
panic(fmt.Errorf("cannot decode %q, export data version %d is too new", pkgPath, pr.version))
if pr.version >= numVersions {
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) {
Expand All @@ -101,7 +101,9 @@ func NewPkgDecoder(pkgPath, input string) PkgDecoder {
assert(err == nil)

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
}
Expand Down
18 changes: 8 additions & 10 deletions src/internal/pkgbits/encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@ import (
"strings"
)

// currentVersion is the current version number written.
const currentVersion = V1

// A PkgEncoder provides methods for encoding a package's Unified IR
// export data.
type PkgEncoder struct {
Expand Down Expand Up @@ -47,10 +44,9 @@ func (pw *PkgEncoder) SyncMarkers() bool { return pw.syncFrames >= 0 }
// export data files, but can help diagnosing desync errors in
// higher-level Unified IR reader/writer code. If syncFrames is
// negative, then sync markers are omitted entirely.
func NewPkgEncoder(syncFrames int) PkgEncoder {
func NewPkgEncoder(version Version, syncFrames int) PkgEncoder {
return PkgEncoder{
// TODO(taking): Change NewPkgEncoder to take a version as an argument, and remove currentVersion.
version: currentVersion,
version: version,
stringsIdx: make(map[string]Index),
syncFrames: syncFrames,
}
Expand All @@ -68,11 +64,13 @@ func (pw *PkgEncoder) DumpTo(out0 io.Writer) (fingerprint [8]byte) {

writeUint32(uint32(pw.version))

var flags uint32
if pw.SyncMarkers() {
flags |= flagSyncMarkers
if pw.version.Has(Flags) {
var flags uint32
if pw.SyncMarkers() {
flags |= flagSyncMarkers
}
writeUint32(flags)
}
writeUint32(flags)

// Write elemEndsEnds.
var sum uint32
Expand Down
26 changes: 16 additions & 10 deletions src/internal/pkgbits/pkgbits_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,25 @@ import (
)

func TestRoundTrip(t *testing.T) {
pw := pkgbits.NewPkgEncoder(-1)
w := pw.NewEncoder(pkgbits.RelocMeta, pkgbits.SyncPublic)
w.Flush()
for _, version := range []pkgbits.Version{
pkgbits.V0,
pkgbits.V1,
pkgbits.V2,
} {
pw := pkgbits.NewPkgEncoder(version, -1)
w := pw.NewEncoder(pkgbits.RelocMeta, pkgbits.SyncPublic)
w.Flush()

var b strings.Builder
_ = pw.DumpTo(&b)
input := b.String()
var b strings.Builder
_ = pw.DumpTo(&b)
input := b.String()

pr := pkgbits.NewPkgDecoder("package_id", input)
r := pr.NewDecoder(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic)
pr := pkgbits.NewPkgDecoder("package_id", input)
r := pr.NewDecoder(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic)

if r.Version() != w.Version() {
t.Errorf("Expected reader version %q to be the writer version %q", 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())
}
}
}

Expand Down
3 changes: 1 addition & 2 deletions test/fixedbugs/issue68526.dir/a/a.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@

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 }

Expand Down
36 changes: 18 additions & 18 deletions test/fixedbugs/issue68526.dir/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
package main

import (
"fmt"

"issue68526.dir/a"
)

func main() {
unexported()
// exported()
exported()
}

func unexported() {
Expand All @@ -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() {
var (
astr a.A[string]
aint a.A[int]
)

// if any(astr) != any(struct{ F string }{}) || any(aint) != any(struct{ F int }{}) {
// panic("zero value of alias and concrete type not identical")
// }
if any(astr) != any(struct{ F string }{}) || any(aint) != any(struct{ F int }{}) {
panic("zero value of alias and concrete type not identical")
}

// if any(astr) == any(aint) {
// panic("zero value of struct{ F string } and struct{ F int } are not distinct")
// }
if any(astr) == any(aint) {
panic("zero value of struct{ F string } and struct{ F int } are not distinct")
}

// if got := fmt.Sprintf("%T", astr); got != "struct { F string }" {
// panic(got)
// }
// }
if got := fmt.Sprintf("%T", astr); got != "struct { F string }" {
panic(got)
}
}

0 comments on commit 9e8ea56

Please sign in to comment.