blob: 8eb67e92f0dcbf07b9aadcbd5d01c5cba3eb92ec [file] [log] [blame]
// Copyright 2025 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.
/*
The Unified IR (UIR) format is implicitly defined by the package noder.
At the highest level, a package encoded in UIR follows the grammar
below.
File = Header Payload fingerprint .
Header = version [ flags ] sectionEnds elementEnds .
version = uint32 . // used for backward compatibility
flags = uint32 . // feature flags used across versions
sectionEnds = [10]uint32 . // defines section boundaries
elementEnds = []uint32 . // defines element boundaries
fingerprint = [8]byte . // sha256 fingerprint
The payload is a series of sections. Each section has a kind which
determines its index in the series.
SectionKind = Uint64 .
Payload = SectionString
SectionMeta
SectionPosBase
SectionPkg
SectionName
SectionType
SectionObj
SectionObjExt // TODO(markfreeman) Define.
SectionObjDict // TODO(markfreeman) Define.
SectionBody // TODO(markfreeman) Define.
.
# Sections
A section is a series of elements of a type determined by the section's
kind. Go constructs are mapped onto one or more elements with possibly
different types; in that case, the elements are in different sections.
Elements are accessed using an element index relative to the start of
the section.
RelElemIdx = Uint64 .
## String Section
String values are stored as elements in the string section. Elements
outside the string section access string values by reference.
SectionString = { String } .
Note that despite being an element, a string does not begin with a
reference table.
## Meta Section
The meta section provides fundamental information for a package. It
contains exactly two elements — a public root and a private root.
SectionMeta = PublicRoot
PrivateRoot // TODO(markfreeman): Define.
.
The public root element identifies the package and provides references
for all exported objects it contains.
PublicRoot = RefTable
[ Sync ]
PkgRef
[ HasInit ]
ObjectRefCount // TODO(markfreeman): Define.
{ ObjectRef } // TODO(markfreeman): Define.
.
HasInit = Bool . // Whether the package uses any
// initialization functions.
## PosBase Section
This section provides position information. It is a series of PosBase
elements.
SectionPosBase = { PosBase } .
A base is either a file base or line base (produced by a line
directive). Every base has a position, line, and column; these are
constant for file bases and hence not encoded.
PosBase = RefTable
[ Sync ]
StringRef // the (absolute) file name for the base
Bool // true if a file base, else a line base
// The below is omitted for file bases.
[ Pos
Uint64 // line
Uint64 ] // column
.
A source position Pos represents a file-absolute (line, column) pair
and a PosBase indicating the position Pos is relative to. Positions
without a PosBase have no line or column.
Pos = [ Sync ]
Bool // true if the position has a base
// The below is omitted if the position has no base.
[ Ref[PosBase]
Uint64 // line
Uint64 ] // column
.
## Package Section
The package section holds package information. It is a series of Pkg
elements.
SectionPkg = { Pkg } .
A Pkg element contains a (path, name) pair and a series of imported
packages. The below package paths have special meaning.
+--------------+-----------------------------------+
| package path | indicates |
+--------------+-----------------------------------+
| "" | the current package |
| "builtin" | the fake builtin package |
| "unsafe" | the compiler-known unsafe package |
+--------------+-----------------------------------+
Pkg = RefTable
[ Sync ]
StringRef // path
// The below is omitted for the special package paths
// "builtin" and "unsafe".
[ StringRef // name
Imports ]
.
Imports = Uint64 // the number of declared imports
{ PkgRef } // references to declared imports
.
Note, a PkgRef is *not* equivalent to Ref[Pkg] due to an extra marker.
PkgRef = [ Sync ]
Ref[Pkg]
.
## Type Section
The type section is a series of type definition elements.
SectionType = { TypeDef } .
A type definition can be in one of several formats, which are identified
by their TypeSpec code.
TypeDef = RefTable
[ Sync ]
[ Sync ]
Uint64 // denotes which TypeSpec to use
TypeSpec
.
TypeSpec = TypeSpecBasic // TODO(markfreeman): Define.
| TypeSpecNamed // TODO(markfreeman): Define.
| TypeSpecPointer // TODO(markfreeman): Define.
| TypeSpecSlice // TODO(markfreeman): Define.
| TypeSpecArray // TODO(markfreeman): Define.
| TypeSpecChan // TODO(markfreeman): Define.
| TypeSpecMap // TODO(markfreeman): Define.
| TypeSpecSignature // TODO(markfreeman): Define.
| TypeSpecStruct // TODO(markfreeman): Define.
| TypeSpecInterface // TODO(markfreeman): Define.
| TypeSpecUnion // TODO(markfreeman): Define.
| TypeSpecTypeParam // TODO(markfreeman): Define.
.
// TODO(markfreeman): Document the reader dictionary once we understand it more.
To use a type elsewhere, a TypeUse is encoded.
TypeUse = [ Sync ]
Bool // whether it is a derived type
[ Uint64 ] // if derived, an index into the reader dictionary
[ Ref[TypeDef] ] // else, a reference to the type
.
## Object Sections
Information about an object (e.g. variable, function, type name, etc.)
is split into multiple elements in different sections. Those elements
have the same section-relative element index.
### Name Section
The name section holds a series of names.
SectionName = { Name } .
Names are elements holding qualified identifiers and type information
for objects.
Name = RefTable
[ Sync ]
[ Sync ]
PkgRef // the object's package
StringRef // the object's package-local name
[ Sync ]
Uint64 // the object's type (e.g. Var, Func, etc.)
.
### Definition Section
The definition section holds definitions for objects defined by the target
package; it does not contain definitions for imported objects.
SectionObj = { ObjectDef } .
Object definitions can be in one of several formats. To determine the correct
format, the name section must be referenced; it contains a code indicating
the object's type.
ObjectDef = RefTable
[ Sync ]
ObjectSpec
.
ObjectSpec = ObjectSpecConst // TODO(markfreeman) Define.
| ObjectSpecFunc // TODO(markfreeman) Define.
| ObjectSpecAlias // TODO(markfreeman) Define.
| ObjectSpecNamedType // TODO(markfreeman) Define.
| ObjectSpecVar // TODO(markfreeman) Define.
.
To use an object definition elsewhere, an ObjectUse is encoded.
ObjectUse = [ Sync ]
[ Bool ]
Ref[ObjectDef]
Uint64 // the number of type arguments
{ TypeUse } // references to the type arguments
.
# References
A reference table precedes every element. Each entry in the table
contains a (section, index) pair denoting the location of the
referenced element.
RefTable = [ Sync ]
Uint64 // the number of table entries
{ RefTableEntry }
.
RefTableEntry = [ Sync ]
SectionKind
RelElemIdx
.
Elements encode references to other elements as an index in the
reference table — not the location of the referenced element directly.
RefTableIdx = Uint64 .
To do this, the Ref[T] primitive is used as below; note that this is
the same shape as provided by package pkgbits, just with new
interpretation applied.
Ref[T] = [ Sync ]
RefTableIdx // the Uint64
.
# Primitives
Primitive encoding is handled separately by the pkgbits package. Check
there for definitions of the below productions.
* Bool
* Int64
* Uint64
* String
* Ref[T]
* Sync
*/
package noder