diff options
Diffstat (limited to 'src/internal/pkgbits')
| -rw-r--r-- | src/internal/pkgbits/decoder.go | 37 | ||||
| -rw-r--r-- | src/internal/pkgbits/doc.go | 30 | ||||
| -rw-r--r-- | src/internal/pkgbits/encoder.go | 16 | ||||
| -rw-r--r-- | src/internal/pkgbits/reloc.go | 2 |
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. |
