package gcimporter
import (
)
func ( *token.FileSet, *types.Package) ([]byte, error) {
const , = false, true
var bytes.Buffer
:= iexportCommon(&, , , , iexportVersion, []*types.Package{})
return .Bytes(),
}
func ( *token.FileSet, map[string]*types.Package, []byte, string, InsertType) (*types.Package, error) {
const = false
, := iimportCommon(, , , , , )
if != nil {
return nil,
}
return [0], nil
}
type InsertType = func(pkg *types.Package, name string)
const bundleVersion = 0
func ( io.Writer, *token.FileSet, *types.Package) error {
const , = false, false
return iexportCommon(, , , , iexportVersion, []*types.Package{})
}
func ( io.Writer, *token.FileSet, []*types.Package) error {
const , = true, false
return iexportCommon(, , , , iexportVersion, )
}
func ( io.Writer, *token.FileSet, , bool, int, []*types.Package) ( error) {
if !debug {
defer func() {
if := recover(); != nil {
if , := .(internalError); {
=
return
}
panic()
}
}()
}
:= iexporter{
fset: ,
version: ,
shallow: ,
allPkgs: map[*types.Package]bool{},
stringIndex: map[string]uint64{},
declIndex: map[types.Object]uint64{},
tparamNames: map[types.Object]string{},
typIndex: map[types.Type]uint64{},
}
if ! {
.localpkg = [0]
}
for , := range predeclared() {
.typIndex[] = uint64()
}
if len(.typIndex) > predeclReserved {
panic(internalErrorf("too many predeclared types: %d > %d", len(.typIndex), predeclReserved))
}
for , := range {
:= .Scope()
for , := range .Names() {
if token.IsExported() {
.pushDecl(.Lookup())
}
}
if {
.allPkgs[] = true
for , := range .Imports() {
.allPkgs[] = true
}
}
}
for !.declTodo.empty() {
.doDecl(.declTodo.popHead())
}
var intWriter
var []uint64
if .shallow {
= make([]uint64, len(.fileInfos))
for , := range .fileInfos {
[] = uint64(.Len())
.encodeFile(&, .file, .needed)
}
}
:= uint64(.data0.Len())
:= .newWriter()
.writeIndex(.declIndex)
if {
.uint64(uint64(len()))
for , := range {
.pkg()
:= .Imports()
.uint64(uint64(len()))
for , := range {
.pkg()
}
}
}
.flush()
var intWriter
if {
.uint64(bundleVersion)
}
.uint64(uint64(.version))
.uint64(uint64(.strings.Len()))
if .shallow {
.uint64(uint64(.Len()))
.uint64(uint64(len()))
for , := range {
.uint64()
}
}
.uint64()
io.Copy(, &)
io.Copy(, &.strings)
if .shallow {
io.Copy(, &)
}
io.Copy(, &.data0)
return nil
}
func ( *iexporter) ( *intWriter, *token.File, []uint64) {
_ = [0]
.uint64(.stringOff(.Name()))
:= uint64(.Size())
.uint64()
sort.Slice(, func(, int) bool { return [] < [] })
:= tokeninternal.GetLines()
.uint64(uint64(len()))
var [][2]int
:
for , := range {
:=
if < len()-1 {
= uint64([+1])
}
if [0] < {
= append(, [2]int{, })
for [0] < {
= [1:]
if len() == 0 {
break
}
}
}
}
.uint64(uint64(len()))
var [2]int
for , := range {
.uint64(uint64([0] - [0]))
.uint64(uint64([1] - [1]))
=
}
}
func ( *exportWriter) ( map[types.Object]uint64) {
type struct {
types.Object
string
}
:= map[*types.Package][]{}
if .p.localpkg != nil {
[.p.localpkg] = nil
}
for := range .p.allPkgs {
[] = nil
}
for := range {
:= .p.exportName()
[.Pkg()] = append([.Pkg()], {, })
}
var []*types.Package
for , := range {
= append(, )
sort.Slice(, func(, int) bool {
return []. < [].
})
}
sort.Slice(, func(, int) bool {
return .exportPath([]) < .exportPath([])
})
.uint64(uint64(len()))
for , := range {
.string(.exportPath())
.string(.Name())
.uint64(uint64(0))
:= []
.uint64(uint64(len()))
for , := range {
.string(.)
.uint64([.])
}
}
}
func ( *iexporter) ( types.Object) ( string) {
if := .tparamNames[]; != "" {
return
}
return .Name()
}
type iexporter struct {
fset *token.FileSet
out *bytes.Buffer
version int
shallow bool
localpkg *types.Package
allPkgs map[*types.Package]bool
declTodo objQueue
strings intWriter
stringIndex map[string]uint64
fileInfo map[*token.File]uint64
fileInfos []*filePositions
data0 intWriter
declIndex map[types.Object]uint64
tparamNames map[types.Object]string
typIndex map[types.Type]uint64
indent int
}
type filePositions struct {
file *token.File
needed []uint64
}
func ( *iexporter) ( string, ...interface{}) {
if !trace {
return
}
fmt.Printf(strings.Repeat("..", .indent)++"\n", ...)
}
func ( *iexporter) ( string) uint64 {
, := .stringIndex[]
if ! {
= uint64(.strings.Len())
.stringIndex[] =
.strings.uint64(uint64(len()))
.strings.WriteString()
}
return
}
func ( *iexporter) ( *token.File, token.Pos) (uint64, uint64) {
, := .fileInfo[]
if ! {
= uint64(len(.fileInfo))
.fileInfos = append(.fileInfos, &filePositions{file: })
if .fileInfo == nil {
.fileInfo = make(map[*token.File]uint64)
}
.fileInfo[] =
}
:= .fileInfos[]
:= uint64(.Offset())
.needed = append(.needed, )
return ,
}
func ( *iexporter) ( types.Object) {
if .Pkg() == types.Unsafe {
panic("cannot export package unsafe")
}
if .shallow && .Pkg() != .localpkg {
return
}
if , := .declIndex[]; {
return
}
.declIndex[] = ^uint64(0)
.declTodo.pushTail()
}
type exportWriter struct {
p *iexporter
data intWriter
currPkg *types.Package
prevFile string
prevLine int64
prevColumn int64
}
func ( *exportWriter) ( *types.Package) string {
if == .p.localpkg {
return ""
}
return .Path()
}
func ( *iexporter) ( types.Object) {
if trace {
.trace("exporting decl %v (%T)", , )
.indent++
defer func() {
.indent--
.trace("=> %s", )
}()
}
:= .newWriter()
.setPkg(.Pkg(), false)
switch obj := .(type) {
case *types.Var:
.tag('V')
.pos(.Pos())
.typ(.Type(), .Pkg())
case *types.Func:
, := .Type().(*types.Signature)
if .Recv() != nil {
if .Recv().Type() != types.Typ[types.Invalid] {
panic(internalErrorf("unexpected method: %v", ))
}
}
if typeparams.ForSignature().Len() == 0 {
.tag('F')
} else {
.tag('G')
}
.pos(.Pos())
if := typeparams.ForSignature(); .Len() > 0 {
.tparamList(.Name(), , .Pkg())
}
.signature()
case *types.Const:
.tag('C')
.pos(.Pos())
.value(.Type(), .Val())
case *types.TypeName:
:= .Type()
if , := .(*typeparams.TypeParam); {
.tag('P')
.pos(.Pos())
:= .Constraint()
if .version >= iexportVersionGo1_18 {
:= false
if , := .(*types.Interface); != nil {
= typeparams.IsImplicit()
}
.bool()
}
.typ(, .Pkg())
break
}
if .IsAlias() {
.tag('A')
.pos(.Pos())
.typ(, .Pkg())
break
}
, := .(*types.Named)
if ! {
panic(internalErrorf("%s is not a defined type", ))
}
if typeparams.ForNamed().Len() == 0 {
.tag('T')
} else {
.tag('U')
}
.pos(.Pos())
if typeparams.ForNamed().Len() > 0 {
.tparamList(.Name(), typeparams.ForNamed(), .Pkg())
}
:= .Type().Underlying()
.typ(, .Pkg())
if types.IsInterface() {
break
}
:= .NumMethods()
.uint64(uint64())
for := 0; < ; ++ {
:= .Method()
.pos(.Pos())
.string(.Name())
, := .Type().(*types.Signature)
if := typeparams.RecvTypeParams(); .Len() > 0 {
:= .Name() + "." + .Name()
for := 0; < .Len(); ++ {
:= .At()
:= tparamExportName(, )
.p.tparamNames[.Obj()] =
}
}
.param(.Recv())
.signature()
}
default:
panic(internalErrorf("unexpected object: %v", ))
}
.declIndex[] = .flush()
}
func ( *exportWriter) ( byte) {
.data.WriteByte()
}
func ( *exportWriter) ( token.Pos) {
if .p.shallow {
.posV2()
} else if .p.version >= iexportVersionPosCol {
.posV1()
} else {
.posV0()
}
}
func ( *exportWriter) ( token.Pos) {
if == token.NoPos {
.uint64(0)
return
}
:= .p.fset.File()
, := .p.fileIndexAndOffset(, )
.uint64(1 + )
.uint64()
}
func ( *exportWriter) ( token.Pos) {
if .p.fset == nil {
.int64(0)
return
}
:= .p.fset.Position()
:= .Filename
:= int64(.Line)
:= int64(.Column)
:= ( - .prevColumn) << 1
:= ( - .prevLine) << 1
if != .prevFile {
|= 1
}
if != 0 {
|= 1
}
.int64()
if &1 != 0 {
.int64()
if &1 != 0 {
.string()
}
}
.prevFile =
.prevLine =
.prevColumn =
}
func ( *exportWriter) ( token.Pos) {
if .p.fset == nil {
.int64(0)
return
}
:= .p.fset.Position()
:= .Filename
:= int64(.Line)
if == .prevFile {
:= - .prevLine
.int64()
if == deltaNewFile {
.int64(-1)
}
} else {
.int64(deltaNewFile)
.int64()
.string()
.prevFile =
}
.prevLine =
}
func ( *exportWriter) ( *types.Package) {
.p.allPkgs[] = true
.string(.exportPath())
}
func ( *exportWriter) ( *types.TypeName) {
:= .p.exportName()
.p.pushDecl()
.string()
.pkg(.Pkg())
}
func ( *exportWriter) ( types.Type, *types.Package) {
.data.uint64(.p.typOff(, ))
}
func ( *iexporter) () *exportWriter {
return &exportWriter{p: }
}
func ( *exportWriter) () uint64 {
:= uint64(.p.data0.Len())
io.Copy(&.p.data0, &.data)
return
}
func ( *iexporter) ( types.Type, *types.Package) uint64 {
, := .typIndex[]
if ! {
:= .newWriter()
.doTyp(, )
= predeclReserved + .flush()
.typIndex[] =
}
return
}
func ( *exportWriter) ( itag) {
.data.uint64(uint64())
}
func ( *exportWriter) ( types.Type, *types.Package) {
if trace {
.p.trace("exporting type %s (%T)", , )
.p.indent++
defer func() {
.p.indent--
.p.trace("=> %s", )
}()
}
switch t := .(type) {
case *types.Named:
if := typeparams.NamedTypeArgs(); .Len() > 0 {
.startType(instanceType)
.pos(.Obj().Pos())
.typeList(, )
.typ(typeparams.NamedTypeOrigin(), )
return
}
.startType(definedType)
.qualifiedType(.Obj())
case *typeparams.TypeParam:
.startType(typeParamType)
.qualifiedType(.Obj())
case *types.Pointer:
.startType(pointerType)
.typ(.Elem(), )
case *types.Slice:
.startType(sliceType)
.typ(.Elem(), )
case *types.Array:
.startType(arrayType)
.uint64(uint64(.Len()))
.typ(.Elem(), )
case *types.Chan:
.startType(chanType)
var uint64
switch .Dir() {
case types.RecvOnly:
= 1
case types.SendOnly:
= 2
case types.SendRecv:
= 3
}
.uint64()
.typ(.Elem(), )
case *types.Map:
.startType(mapType)
.typ(.Key(), )
.typ(.Elem(), )
case *types.Signature:
.startType(signatureType)
.setPkg(, true)
.signature()
case *types.Struct:
.startType(structType)
:= .NumFields()
if > 0 {
.setPkg(.Field(0).Pkg(), true)
} else {
.setPkg(, true)
}
.uint64(uint64())
for := 0; < ; ++ {
:= .Field()
.pos(.Pos())
.string(.Name())
.typ(.Type(), )
.bool(.Anonymous())
.string(.Tag())
}
case *types.Interface:
.startType(interfaceType)
.setPkg(, true)
:= .NumEmbeddeds()
.uint64(uint64())
for := 0; < ; ++ {
:= .EmbeddedType()
:=
if , := .(*types.Named); != nil {
.pos(.Obj().Pos())
} else {
.pos(token.NoPos)
}
.typ(, )
}
= .NumExplicitMethods()
.uint64(uint64())
for := 0; < ; ++ {
:= .ExplicitMethod()
.pos(.Pos())
.string(.Name())
, := .Type().(*types.Signature)
.signature()
}
case *typeparams.Union:
.startType(unionType)
:= .Len()
.uint64(uint64())
for := 0; < ; ++ {
:= .Term()
.bool(.Tilde())
.typ(.Type(), )
}
default:
panic(internalErrorf("unexpected type: %v, %v", , reflect.TypeOf()))
}
}
func ( *exportWriter) ( *types.Package, bool) {
if {
.pkg()
}
.currPkg =
}
func ( *exportWriter) ( *types.Signature) {
.paramList(.Params())
.paramList(.Results())
if .Params().Len() > 0 {
.bool(.Variadic())
}
}
func ( *exportWriter) ( *typeparams.TypeList, *types.Package) {
.uint64(uint64(.Len()))
for := 0; < .Len(); ++ {
.typ(.At(), )
}
}
func ( *exportWriter) ( string, *typeparams.TypeParamList, *types.Package) {
:= uint64(.Len())
.uint64()
for := 0; < .Len(); ++ {
:= .At()
:= tparamExportName(, )
.p.tparamNames[.Obj()] =
.typ(.At(), )
}
}
const blankMarker = "$"
func ( string, *typeparams.TypeParam) string {
assert( != "")
:= .Obj().Name()
if == "_" {
= blankMarker + strconv.Itoa(.Index())
}
return + "." +
}
func ( string) string {
:= strings.LastIndex(, ".")
if < 0 {
errorf("malformed type parameter export name %s: missing prefix", )
}
:= [+1:]
if strings.HasPrefix(, blankMarker) {
return "_"
}
return
}
func ( *exportWriter) ( *types.Tuple) {
:= .Len()
.uint64(uint64())
for := 0; < ; ++ {
.param(.At())
}
}
func ( *exportWriter) ( types.Object) {
.pos(.Pos())
.localIdent()
.typ(.Type(), .Pkg())
}
func ( *exportWriter) ( types.Type, constant.Value) {
.typ(, nil)
if .p.version >= iexportVersionGo1_18 {
.int64(int64(.Kind()))
}
switch := .Underlying().(*types.Basic); .Info() & types.IsConstType {
case types.IsBoolean:
.bool(constant.BoolVal())
case types.IsInteger:
var big.Int
if , := constant.Int64Val(); {
.SetInt64()
} else if , := constant.Uint64Val(); {
.SetUint64()
} else {
.SetString(.ExactString(), 10)
}
.mpint(&, )
case types.IsFloat:
:= constantToFloat()
.mpfloat(, )
case types.IsComplex:
.mpfloat(constantToFloat(constant.Real()), )
.mpfloat(constantToFloat(constant.Imag()), )
case types.IsString:
.string(constant.StringVal())
default:
if .Kind() == types.Invalid {
break
}
panic(internalErrorf("unexpected type %v (%v)", , .Underlying()))
}
}
func ( constant.Value) *big.Float {
= constant.ToFloat()
const = 512
var big.Float
.SetPrec()
if , := constant.Float64Val(); {
.SetFloat64()
} else if , := constant.Num(), constant.Denom(); .Kind() == constant.Int {
:= valueToRat()
:= valueToRat()
.SetRat(.Quo(, ))
} else {
, := .SetString(.ExactString())
assert()
}
return &
}
func ( *exportWriter) ( *big.Int, types.Type) {
, := .Underlying().(*types.Basic)
if ! {
panic(internalErrorf("unexpected type %v (%T)", .Underlying(), .Underlying()))
}
, := intSize()
:= .Sign() < 0
if ! && {
panic(internalErrorf("negative unsigned integer; type %v, value %v", , ))
}
:= .Bytes()
if len() > 0 && [0] == 0 {
panic(internalErrorf("leading zeros"))
}
if uint(len()) > {
panic(internalErrorf("bad mpint length: %d > %d (type %v, value %v)", len(), , , ))
}
:= 256 -
if {
= 256 - 2*
}
if == 1 {
= 256
}
if len() <= 1 {
var uint
if len() == 1 {
= uint([0])
}
if {
<<= 1
if {
--
}
}
if < {
.data.WriteByte(byte())
return
}
}
:= 256 - uint(len())
if {
= 256 - 2*uint(len())
if {
|= 1
}
}
if < || >= 256 {
panic(internalErrorf("encoding mistake: %d, %v, %v => %d", len(), , , ))
}
.data.WriteByte(byte())
.data.Write()
}
func ( *exportWriter) ( *big.Float, types.Type) {
if .IsInf() {
panic("infinite constant")
}
var big.Float
:= int64(.MantExp(&))
:= .MinPrec()
.SetMantExp(&, int())
-= int64()
, := .Int(nil)
if != big.Exact {
panic(internalErrorf("mantissa scaling failed for %f (%s)", , ))
}
.mpint(, )
if .Sign() != 0 {
.int64()
}
}
func ( *exportWriter) ( bool) bool {
var uint64
if {
= 1
}
.uint64()
return
}
func ( *exportWriter) ( int64) { .data.int64() }
func ( *exportWriter) ( uint64) { .data.uint64() }
func ( *exportWriter) ( string) { .uint64(.p.stringOff()) }
func ( *exportWriter) ( types.Object) {
if == nil {
.string("")
return
}
:= .Name()
if == "_" {
.string("_")
return
}
.string()
}
type intWriter struct {
bytes.Buffer
}
func ( *intWriter) ( int64) {
var [binary.MaxVarintLen64]byte
:= binary.PutVarint([:], )
.Write([:])
}
func ( *intWriter) ( uint64) {
var [binary.MaxVarintLen64]byte
:= binary.PutUvarint([:], )
.Write([:])
}
func ( bool) {
if ! {
panic("internal error: assertion failed")
}
}
type objQueue struct {
ring []types.Object
head, tail int
}
func ( *objQueue) () bool {
return .head == .tail
}
func ( *objQueue) ( types.Object) {
if len(.ring) == 0 {
.ring = make([]types.Object, 16)
} else if .head+len(.ring) == .tail {
:= make([]types.Object, len(.ring)*2)
:= .ring[.head%len(.ring):]
if .tail-.head <= len() {
= [:.tail-.head]
copy(, )
} else {
:= copy(, )
copy([:], .ring[:.tail%len(.ring)])
}
.ring, .head, .tail = , 0, .tail-.head
}
.ring[.tail%len(.ring)] =
.tail++
}
func ( *objQueue) () types.Object {
if .empty() {
panic("dequeue empty")
}
:= .ring[.head%len(.ring)]
.head++
return
}