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