Documentation
¶
Overview ¶
Package pkgbits implements low-level coding abstractions for Unified IR's (UIR) binary export data format.
At a low-level, the exported objects of a package are encoded as a byte array. This array contains byte representations of primitive, potentially variable-length values, such as integers, booleans, strings, and constants.
Additionally, the array may contain values which denote indices in the byte array itself. These are termed "relocations" and allow for references.
The details of mapping high-level Go constructs to primitives are left to other packages.
Index ¶
- type AbsElemIdx
- type Code
- type CodeObj
- type CodeType
- type CodeVal
- type Decoder
- func (r *Decoder) Bool() bool
- func (r *Decoder) Code(mark SyncMarker) int
- func (r *Decoder) Int64() int64
- func (r *Decoder) Len() int
- func (r *Decoder) Reloc(k SectionKind) RelElemIdx
- func (r *Decoder) String() string
- func (r *Decoder) Sync(mWant SyncMarker)
- func (r *Decoder) Uint() uint
- func (r *Decoder) Uint64() uint64
- func (r *Decoder) Value() constant.Value
- func (w *Decoder) Version() Version
- type Encoder
- func (w *Encoder) Bool(b bool) bool
- func (w *Encoder) Code(c Code)
- func (w *Encoder) Flush() RelElemIdx
- func (w *Encoder) Int(x int)
- func (w *Encoder) Int64(x int64)
- func (w *Encoder) Len(x int)
- func (w *Encoder) Reloc(k SectionKind, idx RelElemIdx)
- func (w *Encoder) String(s string)
- func (w *Encoder) StringRef(idx RelElemIdx)
- func (w *Encoder) Strings(ss []string)
- func (w *Encoder) Sync(m SyncMarker)
- func (w *Encoder) Uint(x uint)
- func (w *Encoder) Uint64(x uint64)
- func (w *Encoder) Value(val constant.Value)
- func (w *Encoder) Version() Version
- type Field
- type Index
- type PkgDecoder
- func (pr *PkgDecoder) AbsIdx(k SectionKind, idx RelElemIdx) int
- func (pr *PkgDecoder) DataIdx(k SectionKind, idx RelElemIdx) string
- func (pr *PkgDecoder) Fingerprint() [8]byte
- func (pr *PkgDecoder) NewDecoder(k SectionKind, idx RelElemIdx, marker SyncMarker) Decoder
- func (pr *PkgDecoder) NewDecoderRaw(k SectionKind, idx RelElemIdx) Decoder
- func (pr *PkgDecoder) NumElems(k SectionKind) int
- func (pr *PkgDecoder) PeekObj(idx RelElemIdx) (string, string, CodeObj)
- func (pr *PkgDecoder) PeekPkgPath(idx RelElemIdx) string
- func (pr *PkgDecoder) PkgPath() string
- func (pr *PkgDecoder) RetireDecoder(d *Decoder)
- func (pr *PkgDecoder) StringIdx(idx RelElemIdx) string
- func (pr *PkgDecoder) TempDecoder(k SectionKind, idx RelElemIdx, marker SyncMarker) Decoder
- func (pr *PkgDecoder) TempDecoderRaw(k SectionKind, idx RelElemIdx) Decoder
- type PkgEncoder
- func (pw *PkgEncoder) DumpTo(out0 io.Writer) (fingerprint [8]byte, err error)
- func (pw *PkgEncoder) NewEncoder(k SectionKind, marker SyncMarker) *Encoder
- func (pw *PkgEncoder) NewEncoderRaw(k SectionKind) *Encoder
- func (pw *PkgEncoder) NumElems(k SectionKind) int
- func (pw *PkgEncoder) StringIdx(s string) RelElemIdx
- func (pw *PkgEncoder) SyncMarkers() bool
- func (pw *PkgEncoder) Version() Version
- type RefTableEntry
- type RelElemIdx
- type SectionKind
- type SyncMarker
- type Version
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AbsElemIdx ¶
type AbsElemIdx = uint32
An AbsElemIdx, or absolute element index, is an index into the elements that is not relative to some other index.
type Code ¶
type Code interface {
// Marker returns the SyncMarker for the Code's dynamic type.
Marker() SyncMarker
// Value returns the Code's ordinal value.
Value() int
}
A Code is a value written with its own sync marker, so that a reader that is checking markers can tell which enumeration it is decoding.
nanogo's reader dropped this interface, because only the encoder calls it. The writer half brings it back.
type CodeObj ¶
type CodeObj int
A CodeObj distinguishes among go/types.Object encodings.
func (CodeObj) Marker ¶
func (c CodeObj) Marker() SyncMarker
type CodeType ¶
type CodeType int
A CodeType distinguishes among go/types.Type encodings.
func (CodeType) Marker ¶
func (c CodeType) Marker() SyncMarker
type CodeVal ¶
type CodeVal int
A CodeVal distinguishes among go/constant.Value encodings.
func (CodeVal) Marker ¶
func (c CodeVal) Marker() SyncMarker
type Decoder ¶
type Decoder struct {
Relocs []RefTableEntry
Data strings.Reader
Idx RelElemIdx
// contains filtered or unexported fields
}
A Decoder provides methods for decoding an individual element's bitstream data.
func (*Decoder) Code ¶
func (r *Decoder) Code(mark SyncMarker) int
Code decodes a Code value from the element bitstream and returns its ordinal value. It's the caller's responsibility to convert the result to an appropriate Code type.
TODO(mdempsky): Ideally this method would have signature "Code[T Code] T" instead, but we don't allow generic methods and the compiler can't depend on generics yet anyway.
func (*Decoder) Reloc ¶
func (r *Decoder) Reloc(k SectionKind) RelElemIdx
Reloc decodes a relocation of expected section k from the element bitstream and returns an index to the referenced element.
func (*Decoder) Sync ¶
func (r *Decoder) Sync(mWant SyncMarker)
Sync decodes a sync marker from the element bitstream and asserts that it matches the expected marker.
If EnableSync is false, then Sync is a no-op.
type Encoder ¶
type Encoder struct {
// Relocs is the element's reference table, in the order the
// references were first made. RelocMap finds an existing entry and is
// never ranged over.
Relocs []RefTableEntry
RelocMap map[RefTableEntry]uint32
Data bytes.Buffer
Idx RelElemIdx
// contains filtered or unexported fields
}
An Encoder writes one element's bitstream.
func (*Encoder) Bool ¶
Bool writes b and returns it, so that a caller can branch on the value it just wrote.
func (*Encoder) Flush ¶
func (w *Encoder) Flush() RelElemIdx
Flush finalises the element and returns its index.
The reference table is written in front of the data, because a reader resolves a reference by table index and must be able to read the table without reading the element.
func (*Encoder) Reloc ¶
func (w *Encoder) Reloc(k SectionKind, idx RelElemIdx)
Reloc writes a reference to the element at (k, idx).
Only the table index reaches the bitstream, so a reader knows the section from context and not from the stream.
func (*Encoder) String ¶
String writes a string, by adding it to the strings section and writing a reference to it.
func (*Encoder) StringRef ¶
func (w *Encoder) StringRef(idx RelElemIdx)
StringRef writes a reference to an already added string.
func (*Encoder) Sync ¶
func (w *Encoder) Sync(m SyncMarker)
Sync writes a sync marker, which this encoder never does.
The calls are kept so that the writer reads as the mirror of the reader and a later port can turn markers back on in one place.
type Field ¶
type Field int
Field denotes a unit of data in the serialized unified IR bitstream. It is conceptually a like field in a structure.
We only really need Fields when the data may or may not be present in a stream based on the Version of the bitstream.
Unlike much of pkgbits, Fields are not serialized and can change values as needed.
const ( // Flags in a uint32 in the header of a bitstream // that is used to indicate whether optional features are enabled. Flags Field = iota // Deprecated: HasInit was a bool indicating whether a package // has any init functions. HasInit // Deprecated: DerivedFuncInstance was a bool indicating // whether an object was a function instance. DerivedFuncInstance // ObjAlias has a list of TypeParamNames. AliasTypeParamNames // Deprecated: DerivedInfoNeeded was a bool indicating // whether a type was a derived type. DerivedInfoNeeded // Composite literals use a more compact format for element lists. CompactCompLiterals // Generic methods may appear as standalone function objects. GenericMethods )
type Index ¶
type Index int32
An Index represents a bitstream element index *within* (i.e., relative to) a particular section.
type PkgDecoder ¶
type PkgDecoder struct {
// contains filtered or unexported fields
}
A PkgDecoder provides methods for decoding a package's Unified IR export data.
func NewPkgDecoder ¶
func NewPkgDecoder(pkgPath, input string) PkgDecoder
NewPkgDecoder returns a PkgDecoder initialized to read the Unified IR export data from input. pkgPath is the package path for the compilation unit that produced the export data.
func (*PkgDecoder) AbsIdx ¶
func (pr *PkgDecoder) AbsIdx(k SectionKind, idx RelElemIdx) int
AbsIdx returns the absolute index for the given (section, index) pair.
func (*PkgDecoder) DataIdx ¶
func (pr *PkgDecoder) DataIdx(k SectionKind, idx RelElemIdx) string
DataIdx returns the raw element bitstream for the given (section, index) pair.
func (*PkgDecoder) Fingerprint ¶
func (pr *PkgDecoder) Fingerprint() [8]byte
Fingerprint returns the package fingerprint.
It is the last 8 bytes of the payload. An object that imports the package records it in its Autolib entry, and the linker refuses a build whose two copies disagree, so a compiler that reads export data must be able to report it.
func (*PkgDecoder) NewDecoder ¶
func (pr *PkgDecoder) NewDecoder(k SectionKind, idx RelElemIdx, marker SyncMarker) Decoder
NewDecoder returns a Decoder for the given (section, index) pair, and decodes the given SyncMarker from the element bitstream.
func (*PkgDecoder) NewDecoderRaw ¶
func (pr *PkgDecoder) NewDecoderRaw(k SectionKind, idx RelElemIdx) Decoder
NewDecoderRaw returns a Decoder for the given (section, index) pair.
Most callers should use NewDecoder instead.
func (*PkgDecoder) NumElems ¶
func (pr *PkgDecoder) NumElems(k SectionKind) int
NumElems returns the number of elements in section k.
func (*PkgDecoder) PeekObj ¶
func (pr *PkgDecoder) PeekObj(idx RelElemIdx) (string, string, CodeObj)
PeekObj returns the package path, object name and CodeObj of the object at the given index, without decoding the object itself.
func (*PkgDecoder) PeekPkgPath ¶
func (pr *PkgDecoder) PeekPkgPath(idx RelElemIdx) string
PeekPkgPath returns the package path for the specified package index.
nanogo restored this and PkgDecoder.PeekObj with the writer half: both answer what an element is without decoding it, which is what a writer that copies or checks elements needs.
func (*PkgDecoder) PkgPath ¶
func (pr *PkgDecoder) PkgPath() string
PkgPath returns the package path for the package
TODO(mdempsky): Remove; unneeded since CL 391014.
func (*PkgDecoder) RetireDecoder ¶
func (pr *PkgDecoder) RetireDecoder(d *Decoder)
func (*PkgDecoder) StringIdx ¶
func (pr *PkgDecoder) StringIdx(idx RelElemIdx) string
StringIdx returns the string value for the given string index.
func (*PkgDecoder) TempDecoder ¶
func (pr *PkgDecoder) TempDecoder(k SectionKind, idx RelElemIdx, marker SyncMarker) Decoder
TempDecoder returns a Decoder for the given (section, index) pair, and decodes the given SyncMarker from the element bitstream. If possible the Decoder should be RetireDecoder'd when it is no longer needed, this will avoid heap allocations.
func (*PkgDecoder) TempDecoderRaw ¶
func (pr *PkgDecoder) TempDecoderRaw(k SectionKind, idx RelElemIdx) Decoder
type PkgEncoder ¶
type PkgEncoder struct {
// contains filtered or unexported fields
}
A PkgEncoder builds a package's Unified IR export data.
It is the mirror of PkgDecoder: the same sections, the same element indices, the same reference tables. See doc.go for the container's shape.
func NewPkgEncoder ¶
func NewPkgEncoder(v Version) PkgEncoder
NewPkgEncoder returns a PkgEncoder that writes at version v.
nanogo diverges from upstream by taking no frame count. Upstream can write a sync marker before every field, which is a debugging aid for the writer and the reader together. nanogo writes none, for the reason [PkgDecoder.Sync] already records from the other side: the ported reader desyncs on marked data at the first object that stands in for another package's declaration, so data nanogo marked would be data nanogo cannot read.
func (*PkgEncoder) DumpTo ¶
func (pw *PkgEncoder) DumpTo(out0 io.Writer) (fingerprint [8]byte, err error)
DumpTo writes the encoded package to out and returns its fingerprint.
The fingerprint is the first eight bytes of the SHA-256 of everything before it, and it is also the last eight bytes of the payload. An importing object records it in its Autolib entry and the linker refuses a build whose two copies disagree, so the caller has to carry it into the object it writes.
nanogo diverges from upstream by returning the write error rather than asserting it away. The caller is writing a file the build asked for.
func (*PkgEncoder) NewEncoder ¶
func (pw *PkgEncoder) NewEncoder(k SectionKind, marker SyncMarker) *Encoder
NewEncoder reserves a new element in section k and writes marker as the start of its bitstream.
func (*PkgEncoder) NewEncoderRaw ¶
func (pw *PkgEncoder) NewEncoderRaw(k SectionKind) *Encoder
NewEncoderRaw reserves a new element in section k.
Most callers want PkgEncoder.NewEncoder. The index is assigned now and the bitstream is stored by Encoder.Flush, so an element may reference an element that is not written yet, which is how a cyclic type graph is encoded.
func (*PkgEncoder) NumElems ¶
func (pw *PkgEncoder) NumElems(k SectionKind) int
NumElems returns the number of elements written to section k.
func (*PkgEncoder) StringIdx ¶
func (pw *PkgEncoder) StringIdx(s string) RelElemIdx
StringIdx adds s to the strings section if it is not already there, and returns its index.
func (*PkgEncoder) SyncMarkers ¶
func (pw *PkgEncoder) SyncMarkers() bool
SyncMarkers reports whether the encoder writes sync markers. It never does.
func (*PkgEncoder) Version ¶
func (pw *PkgEncoder) Version() Version
Version reports the version the elements are written at.
type RefTableEntry ¶
type RefTableEntry struct {
Kind SectionKind
Idx RelElemIdx
}
A RefTableEntry is an entry in an element's reference table. All elements are preceded by a reference table which provides locations for referenced elements.
type RelElemIdx ¶
type RelElemIdx = Index
TODO(markfreeman): Make this its own type. A RelElemIdx, or relative element index, is an index into the elements relative to some other index, such as the start of a section.
const ( PublicRootIdx RelElemIdx = 0 PrivateRootIdx RelElemIdx = 1 )
Reserved indices within the SectionMeta section.
type SectionKind ¶
type SectionKind int32 // TODO(markfreeman): Replace with uint8.
A SectionKind indicates a section, as well as the ordering of sections within unified export data. Any object given a dedicated section can be referred to via a section / index pair (and thus dereferenced) in other sections.
const ( SectionString SectionKind = iota SectionMeta SectionPosBase SectionPkg SectionName SectionType SectionObj SectionObjExt SectionObjDict SectionBody )
type SyncMarker ¶
type SyncMarker int
SyncMarker is an enum type that represents markers that may be written to export data to ensure the reader and writer stay synchronized.
const ( // Low-level coding markers. SyncEOF SyncMarker SyncBool SyncInt64 SyncUint64 SyncString SyncValue SyncVal SyncRelocs SyncReloc SyncUseReloc // Higher-level object and type markers. SyncPublic SyncPos SyncPosBase SyncObject SyncObject1 SyncPkg SyncPkgDef SyncMethod SyncType SyncTypeIdx SyncTypeParamNames SyncSignature SyncParams SyncParam SyncCodeObj SyncSym SyncLocalIdent SyncSelector // Private markers (only known to cmd/compile). SyncPrivate SyncFuncExt SyncVarExt SyncTypeExt SyncPragma SyncExprList SyncExprs SyncExpr SyncExprType SyncAssign SyncOp SyncFuncLit SyncCompLit SyncDecl SyncFuncBody SyncOpenScope SyncCloseScope SyncCloseAnotherScope SyncDeclNames SyncDeclName SyncStmts SyncBlockStmt SyncIfStmt SyncForStmt SyncSwitchStmt SyncRangeStmt SyncCaseClause SyncCommClause SyncSelectStmt SyncDecls SyncLabeledStmt SyncUseObjLocal SyncAddLocal SyncLinkname SyncStmt1 SyncStmtsEnd SyncLabel SyncOptLabel SyncMultiExpr SyncRType SyncConvRTTI )
func (SyncMarker) String ¶
func (i SyncMarker) String() string
type Version ¶
type Version uint32
Version indicates a version of a unified IR bitstream. Each Version indicates the addition, removal, or change of new data in the bitstream.
These are serialized to disk and the interpretation remains fixed.
const ( // V0: initial prototype. // // All data that is not assigned a Field is in version V0 // and has not been deprecated. V0 Version = iota // V1: adds the Flags uint32 word V1 // V2: removes unused legacy fields and supports type parameters for aliases. // - remove the legacy "has init" bool from the public root // - remove obj's "derived func instance" bool // - add a TypeParamNames field to ObjAlias // - remove derived info "needed" bool V2 // V3: introduces a more compact format for composite literal element lists // - negative lengths indicate that (some) elements may have keys // - positive lengths indicate that no element has a key // - a negative struct field index indicates an embedded field V3 // V4: encodes generic methods as standalone function objects V4 )