| // 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 |