From 69b412b7d6e9cbd9908b7a9641d1c6af3ff6bc63 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 16 May 2022 12:02:54 -0700 Subject: [PATCH] internal/pkgbits: better documentation Change-Id: I3f96a6e8a43faa5c8111b9d979aa37822c1dce06 Reviewed-on: https://go-review.googlesource.com/c/go/+/407434 Reviewed-by: Robert Griesemer Reviewed-by: Cuong Manh Le Run-TryBot: Matthew Dempsky TryBot-Result: Gopher Robot Reviewed-by: David Chase --- src/cmd/compile/internal/importer/support.go | 2 ++ src/cmd/compile/internal/noder/writer.go | 9 +++++ src/go/internal/gcimporter/support.go | 2 ++ src/internal/pkgbits/decoder.go | 37 ++++++++++++++++++-- src/internal/pkgbits/doc.go | 30 ++++++++++++++++ src/internal/pkgbits/encoder.go | 16 +++++++-- src/internal/pkgbits/reloc.go | 2 +- 7 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 src/internal/pkgbits/doc.go diff --git a/src/cmd/compile/internal/importer/support.go b/src/cmd/compile/internal/importer/support.go index e382b2f28b..8f53192e81 100644 --- a/src/cmd/compile/internal/importer/support.go +++ b/src/cmd/compile/internal/importer/support.go @@ -138,11 +138,13 @@ type anyType struct{} func (t anyType) Underlying() types2.Type { return t } func (t anyType) String() string { return "any" } +// See cmd/compile/internal/noder.derivedInfo. type derivedInfo struct { idx int needed bool } +// See cmd/compile/internal/noder.typeInfo. type typeInfo struct { idx int derived bool diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 772a9e27c8..298ed493f7 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -109,11 +109,20 @@ type writerDict struct { itabs []itabInfo } +// A derivedInfo represents a reference to an encoded generic Go type. type derivedInfo struct { idx int needed bool } +// A typeInfo represents a reference to an encoded Go type. +// +// If derived is true, then the typeInfo represents a generic Go type +// that contains type parameters. In this case, idx is an index into +// the readerDict.derived{,Types} arrays. +// +// Otherwise, the typeInfo represents a non-generic Go type, and idx +// is an index into the reader.typs array instead. type typeInfo struct { idx int derived bool diff --git a/src/go/internal/gcimporter/support.go b/src/go/internal/gcimporter/support.go index 8b61a417ad..4be10b1699 100644 --- a/src/go/internal/gcimporter/support.go +++ b/src/go/internal/gcimporter/support.go @@ -155,11 +155,13 @@ type anyType struct{} func (t anyType) Underlying() types.Type { return t } func (t anyType) String() string { return "any" } +// See cmd/compile/internal/noder.derivedInfo. type derivedInfo struct { idx int needed bool } +// See cmd/compile/internal/noder.typeInfo. type typeInfo struct { idx int derived bool diff --git a/src/internal/pkgbits/decoder.go b/src/internal/pkgbits/decoder.go index 5b4e8f69af..85bf218d91 100644 --- a/src/internal/pkgbits/decoder.go +++ b/src/internal/pkgbits/decoder.go @@ -17,12 +17,36 @@ import ( "strings" ) +// A PkgDecoder provides methods for decoding a package's Unified IR +// export data. type PkgDecoder struct { + // pkgPath is the package path for the package to be decoded. + // + // TODO(mdempsky): Remove; unneeded since CL 391014. pkgPath string + // elemData is the full data payload of the encoded package. + // Elements are densely and contiguously packed together. + // + // The last 8 bytes of elemData are the package fingerprint. + elemData string + + // elemEnds stores the byte-offset end positions of element + // bitstreams within elemData. + // + // For example, element I's bitstream data starts at elemEnds[I-1] + // (or 0, if I==0) and ends at elemEnds[I]. + // + // Note: elemEnds is indexed by absolute indices, not + // section-relative indices. + elemEnds []uint32 + + // elemEndsEnds stores the index-offset end positions of relocation + // sections within elemEnds. + // + // For example, section K's end positions start at elemEndsEnds[K-1] + // (or 0, if K==0) and end at elemEndsEnds[K]. elemEndsEnds [numRelocs]uint32 - elemEnds []uint32 - elemData string // last 8 bytes are fingerprint } func (pr *PkgDecoder) PkgPath() string { return pr.pkgPath } @@ -55,6 +79,7 @@ func NewPkgDecoder(pkgPath, input string) PkgDecoder { return pr } +// NumElems returns the number of elements in section k. func (pr *PkgDecoder) NumElems(k RelocKind) int { count := int(pr.elemEndsEnds[k]) if k > 0 { @@ -63,16 +88,20 @@ func (pr *PkgDecoder) NumElems(k RelocKind) int { return count } +// TotalElems returns the total number of elements across all sections. func (pr *PkgDecoder) TotalElems() int { return len(pr.elemEnds) } +// Fingerprint returns the package fingerprint. func (pr *PkgDecoder) Fingerprint() [8]byte { var fp [8]byte copy(fp[:], pr.elemData[len(pr.elemData)-8:]) return fp } +// AbsIdx returns the absolute index for the given (section, index) +// pair. func (pr *PkgDecoder) AbsIdx(k RelocKind, idx int) int { absIdx := idx if k > 0 { @@ -84,6 +113,8 @@ func (pr *PkgDecoder) AbsIdx(k RelocKind, idx int) int { return absIdx } +// DataIdx returns the raw element bitstream for the given (section, +// index) pair. func (pr *PkgDecoder) DataIdx(k RelocKind, idx int) string { absIdx := pr.AbsIdx(k, idx) @@ -126,6 +157,8 @@ func (pr *PkgDecoder) NewDecoderRaw(k RelocKind, idx int) Decoder { return r } +// A Decoder provides methods for decoding an individual element's +// bitstream data. type Decoder struct { common *PkgDecoder diff --git a/src/internal/pkgbits/doc.go b/src/internal/pkgbits/doc.go new file mode 100644 index 0000000000..4862e39049 --- /dev/null +++ b/src/internal/pkgbits/doc.go @@ -0,0 +1,30 @@ +// Copyright 2022 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. + +// Package pkgbits implements low-level coding abstractions for +// Unified IR's export data format. +// +// At a low-level, a package is a collection of bitstream elements. +// Each element has a "kind" and a dense, non-negative index. +// Elements can be randomly accessed given their kind and index. +// +// Individual elements are sequences of variable-length values (e.g., +// integers, booleans, strings, go/constant values, cross-references +// to other elements). Package pkgbits provides APIs for encoding and +// decoding these low-level values, but the details of mapping +// higher-level Go constructs into elements is left to higher-level +// abstractions. +// +// Elements may cross-reference each other with "relocations." For +// example, an element representing a pointer type has a relocation +// referring to the element type. +// +// Go constructs may be composed as a constellation of multiple +// elements. For example, a declared function may have one element to +// describe the object (e.g., its name, type, position), and a +// separate element to describe its function body. This allows readers +// some flexibility in efficiently seeking or re-reading data (e.g., +// inlining requires re-reading the function body for each inlined +// call, without needing to re-read the object-level details). +package pkgbits diff --git a/src/internal/pkgbits/encoder.go b/src/internal/pkgbits/encoder.go index 4780f01c39..f274e2a676 100644 --- a/src/internal/pkgbits/encoder.go +++ b/src/internal/pkgbits/encoder.go @@ -16,9 +16,14 @@ import ( "runtime" ) +// A PkgEncoder provides methods for encoding a package's Unified IR +// export data. type PkgEncoder struct { + // elems holds the bitstream for previously encoded elements. elems [numRelocs][]string + // stringsIdx maps previously encoded strings to their index within + // the RelocString section, to allow deduplication. stringsIdx map[string]int syncFrames int @@ -31,6 +36,8 @@ func NewPkgEncoder(syncFrames int) PkgEncoder { } } +// DumpTo writes the package's encoded data to out0 and returns the +// package fingerprint. func (pw *PkgEncoder) DumpTo(out0 io.Writer) (fingerprint [8]byte) { h := md5.New() out := io.MultiWriter(out0, h) @@ -41,12 +48,14 @@ func (pw *PkgEncoder) DumpTo(out0 io.Writer) (fingerprint [8]byte) { writeUint32(0) // version + // Write elemEndsEnds. var sum uint32 for _, elems := range &pw.elems { sum += uint32(len(elems)) writeUint32(sum) } + // Write elemEnds. sum = 0 for _, elems := range &pw.elems { for _, elem := range elems { @@ -55,6 +64,7 @@ func (pw *PkgEncoder) DumpTo(out0 io.Writer) (fingerprint [8]byte) { } } + // Write elemData. for _, elems := range &pw.elems { for _, elem := range elems { _, err := io.WriteString(out, elem) @@ -62,6 +72,7 @@ func (pw *PkgEncoder) DumpTo(out0 io.Writer) (fingerprint [8]byte) { } } + // Write fingerprint. copy(fingerprint[:], h.Sum(nil)) _, err := out0.Write(fingerprint[:]) assert(err == nil) @@ -98,8 +109,8 @@ func (pw *PkgEncoder) NewEncoderRaw(k RelocKind) Encoder { } } -// Encoders - +// An Encoder provides methods for encoding an individual element's +// bitstream data. type Encoder struct { p *PkgEncoder @@ -112,6 +123,7 @@ type Encoder struct { Idx int } +// Flush finalizes the element's bitstream and returns its Index. func (w *Encoder) Flush() int { var sb bytes.Buffer // TODO(mdempsky): strings.Builder after #44505 is resolved diff --git a/src/internal/pkgbits/reloc.go b/src/internal/pkgbits/reloc.go index 43040ca2ff..efe662ddf2 100644 --- a/src/internal/pkgbits/reloc.go +++ b/src/internal/pkgbits/reloc.go @@ -9,7 +9,7 @@ package pkgbits // A RelocKind indicates a particular section within a unified IR export. type RelocKind int -// A relocEnt (relocation entry) is an entry in an atom's local +// A relocEnt (relocation entry) is an entry in an element's local // reference table. // // TODO(mdempsky): Rename this too. -- 2.50.0