aboutsummaryrefslogtreecommitdiff
path: root/src/internal/pkgbits
diff options
context:
space:
mode:
Diffstat (limited to 'src/internal/pkgbits')
-rw-r--r--src/internal/pkgbits/decoder.go37
-rw-r--r--src/internal/pkgbits/doc.go30
-rw-r--r--src/internal/pkgbits/encoder.go16
-rw-r--r--src/internal/pkgbits/reloc.go2
4 files changed, 80 insertions, 5 deletions
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.