package gcimporter
import (
)
type intReader struct {
*bytes.Reader
path string
}
func ( *intReader) () int64 {
, := binary.ReadVarint(.Reader)
if != nil {
errorf("import %q: read varint error: %v", .path, )
}
return
}
func ( *intReader) () uint64 {
, := binary.ReadUvarint(.Reader)
if != nil {
errorf("import %q: read varint error: %v", .path, )
}
return
}
const (
iexportVersionGo1_11 = 0
iexportVersionPosCol = 1
iexportVersionGo1_18 = 2
iexportVersionGenerics = 2
iexportVersionCurrent = 2
)
type ident struct {
pkg *types.Package
name string
}
const predeclReserved = 32
type itag uint64
const (
definedType itag = iota
pointerType
sliceType
arrayType
chanType
mapType
signatureType
structType
interfaceType
typeParamType
instanceType
unionType
aliasType
)
const (
varTag = 'V'
funcTag = 'F'
genericFuncTag = 'G'
constTag = 'C'
aliasTag = 'A'
genericAliasTag = 'B'
typeParamTag = 'P'
typeTag = 'T'
genericTypeTag = 'U'
)
func ( *token.FileSet, map[string]*types.Package, []byte, string) (int, *types.Package, error) {
, := iimportCommon(, GetPackagesFromMap(), , false, , false, nil)
if != nil {
return 0, nil,
}
return 0, [0], nil
}
func ( *token.FileSet, map[string]*types.Package, []byte) ([]*types.Package, error) {
return iimportCommon(, GetPackagesFromMap(), , true, "", false, nil)
}
type GetPackagesFunc = func(items []GetPackagesItem) error
type GetPackagesItem struct {
Name, Path string
Pkg *types.Package
pathOffset uint64
nameIndex map[string]uint64
}
func ( map[string]*types.Package) GetPackagesFunc {
return func( []GetPackagesItem) error {
for , := range {
, := [.Path]
if ! {
= types.NewPackage(.Path, .Name)
[.Path] =
}
[].Pkg =
}
return nil
}
}
func ( *token.FileSet, GetPackagesFunc, []byte, bool, string, bool, ReportFunc) ( []*types.Package, error) {
const = iexportVersionCurrent
:= int64(-1)
if !debug {
defer func() {
if := recover(); != nil {
if {
= fmt.Errorf("%v", )
} else if > {
= fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", , )
} else {
= fmt.Errorf("internal error while importing %q (%v); please report an issue", , )
}
}
}()
}
:= &intReader{bytes.NewReader(), }
if {
if := .uint64(); != bundleVersion {
errorf("unknown bundle format version %d", )
}
}
= int64(.uint64())
switch {
case iexportVersionGo1_18, iexportVersionPosCol, iexportVersionGo1_11:
default:
if > iexportVersionGo1_18 {
errorf("unstable iexport format version %d, just rebuild compiler and std library", )
} else {
errorf("unknown iexport format version %d", )
}
}
:= int64(.uint64())
var int64
var []uint64
if {
= int64(.uint64())
= make([]uint64, .uint64())
for := range {
[] = .uint64()
}
}
:= int64(.uint64())
, := .Seek(0, io.SeekCurrent)
:= [ : +]
:= [+ : ++]
:= [++ : +++]
.Seek(++, io.SeekCurrent)
:= iimporter{
version: int(),
ipath: ,
aliases: aliases.Enabled(),
shallow: ,
reportf: ,
stringData: ,
stringCache: make(map[uint64]string),
fileOffset: ,
fileData: ,
fileCache: make([]*token.File, len()),
pkgCache: make(map[uint64]*types.Package),
declData: ,
pkgIndex: make(map[*types.Package]map[string]uint64),
typCache: make(map[uint64]types.Type),
tparamIndex: make(map[ident]types.Type),
fake: fakeFileSet{
fset: ,
files: make(map[string]*fileInfo),
},
}
defer .fake.setLines()
for , := range predeclared() {
.typCache[uint64()] =
}
:= make([]GetPackagesItem, .uint64())
:= make(map[string]bool)
for := range {
:= .uint64()
:= .stringAt()
:= .stringAt(.uint64())
_ = .uint64()
if == "" {
=
}
[].Name =
[].Path =
[].pathOffset =
:= make(map[string]uint64)
:= .uint64()
assert(!( && > 0 && != 0))
for ; > 0; -- {
:= .stringAt(.uint64())
[] = .uint64()
}
[].nameIndex =
[] = true
}
if len() != len() {
("found duplicate PkgPaths while reading export data manifest: %v", )
}
if := (); != nil {
return nil,
}
:= make([]*types.Package, len())
for , := range {
:= .Pkg
if == nil {
errorf("internal error: getPackages returned nil package for %q", .Path)
} else if .Path() != .Path {
errorf("internal error: getPackages returned wrong path %q, want %q", .Path(), .Path)
} else if .Name() != .Name {
errorf("internal error: getPackages returned wrong name %s for package %q, want %s", .Name(), .Path, .Name)
}
.pkgCache[.pathOffset] =
.pkgIndex[] = .nameIndex
[] =
}
if {
= make([]*types.Package, .uint64())
for := range {
:= .pkgAt(.uint64())
:= make([]*types.Package, .uint64())
for := range {
[] = .pkgAt(.uint64())
}
.SetImports()
[] =
}
} else {
if len() == 0 {
errorf("no packages found for %s", )
panic("unreachable")
}
= [:1]
:= append(([]*types.Package)(nil), [1:]...)
sort.Sort(byPath())
[0].SetImports()
}
for , := range {
if .Complete() {
continue
}
:= make([]string, 0, len(.pkgIndex[]))
for := range .pkgIndex[] {
= append(, )
}
sort.Strings()
for , := range {
.doDecl(, )
}
.MarkComplete()
}
for , := range .later {
.t.SetConstraint(.constraint)
}
for , := range .interfaceList {
.Complete()
}
for , := range .instanceList {
if , := .Underlying().(*types.Interface); != nil {
.Complete()
}
}
return , nil
}
type setConstraintArgs struct {
t *types.TypeParam
constraint types.Type
}
type iimporter struct {
version int
ipath string
aliases bool
shallow bool
reportf ReportFunc
stringData []byte
stringCache map[uint64]string
fileOffset []uint64
fileData []byte
fileCache []*token.File
pkgCache map[uint64]*types.Package
declData []byte
pkgIndex map[*types.Package]map[string]uint64
typCache map[uint64]types.Type
tparamIndex map[ident]types.Type
fake fakeFileSet
interfaceList []*types.Interface
instanceList []types.Type
later []setConstraintArgs
indent int
}
func ( *iimporter) ( string, ...interface{}) {
if !trace {
return
}
fmt.Printf(strings.Repeat("..", .indent)++"\n", ...)
}
func ( *iimporter) ( *types.Package, string) {
if debug {
.trace("import decl %s", )
.indent++
defer func() {
.indent--
.trace("=> %s", )
}()
}
if := .Scope().Lookup(); != nil {
return
}
, := .pkgIndex[][]
if ! {
errorf("%v.%v not in index", , )
}
:= &importReader{p: , currPkg: }
.declReader.Reset(.declData[:])
.obj()
}
func ( *iimporter) ( uint64) string {
if , := .stringCache[]; {
return
}
, := binary.Uvarint(.stringData[:])
if <= 0 {
errorf("varint failed")
}
:= + uint64()
:= string(.stringData[ : +])
.stringCache[] =
return
}
func ( *iimporter) ( uint64) *token.File {
:= .fileCache[]
if == nil {
:= .fileOffset[]
= .decodeFile(intReader{bytes.NewReader(.fileData[:]), .ipath})
.fileCache[] =
}
return
}
func ( *iimporter) ( intReader) *token.File {
:= .stringAt(.uint64())
:= int(.uint64())
:= .fake.fset.AddFile(, -1, )
:= make([]int, int(.uint64()))
var , int
for , := 0, int(.uint64()); < ; ++ {
+= int(.uint64())
+= int(.uint64())
[] =
for := - 1; > 0 && [] == 0; -- {
[] = [+1] - 1
}
}
for := len() - 1; > 0 && [] == 0; -- {
--
[] =
}
if !.SetLines() {
errorf("SetLines failed: %d", )
}
return
}
func ( *iimporter) ( uint64) *types.Package {
if , := .pkgCache[]; {
return
}
:= .stringAt()
errorf("missing package %q in %q", , .ipath)
return nil
}
func ( *iimporter) ( uint64, *types.Named) types.Type {
if , := .typCache[]; && canReuse(, ) {
return
}
if < predeclReserved {
errorf("predeclared type missing from cache: %v", )
}
:= &importReader{p: }
.declReader.Reset(.declData[-predeclReserved:])
:= .doType()
if canReuse(, ) {
.typCache[] =
}
return
}
func ( *types.Named, types.Type) bool {
if == nil {
return true
}
, := aliases.Unalias().(*types.Interface)
if == nil {
return true
}
return .NumEmbeddeds() == 0 && .NumExplicitMethods() == 0
}
type importReader struct {
p *iimporter
declReader bytes.Reader
currPkg *types.Package
prevFile string
prevLine int64
prevColumn int64
}
func ( *importReader) ( string) {
:= .byte()
:= .pos()
switch {
case aliasTag:
:= .typ()
.declare(aliases.NewAlias(.p.aliases, , .currPkg, , ))
case constTag:
, := .value()
.declare(types.NewConst(, .currPkg, , , ))
case funcTag, genericFuncTag:
var []*types.TypeParam
if == genericFuncTag {
= .tparamList()
}
:= .signature(nil, nil, )
.declare(types.NewFunc(, .currPkg, , ))
case typeTag, genericTypeTag:
:= types.NewTypeName(, .currPkg, , nil)
:= types.NewNamed(, nil, nil)
.declare()
if == genericTypeTag {
:= .tparamList()
.SetTypeParams()
}
:= .p.typAt(.uint64(), ).Underlying()
.SetUnderlying()
if !isInterface() {
for := .uint64(); > 0; -- {
:= .pos()
:= .ident()
:= .param()
, := typesinternal.ReceiverNamed()
:= .TypeArgs()
var []*types.TypeParam
if .Len() > 0 {
= make([]*types.TypeParam, .Len())
for := range {
[] = aliases.Unalias(.At()).(*types.TypeParam)
}
}
:= .signature(, , nil)
.AddMethod(types.NewFunc(, .currPkg, , ))
}
}
case typeParamTag:
if .p.version < iexportVersionGenerics {
errorf("unexpected type param type")
}
:= tparamName()
:= types.NewTypeName(, .currPkg, , nil)
:= types.NewTypeParam(, nil)
:= ident{.currPkg, }
.p.tparamIndex[] =
var bool
if .p.version >= iexportVersionGo1_18 {
= .bool()
}
:= .typ()
if {
, := aliases.Unalias().(*types.Interface)
if == nil {
errorf("non-interface constraint marked implicit")
}
.MarkImplicit()
}
.p.later = append(.p.later, setConstraintArgs{t: , constraint: })
case varTag:
:= .typ()
.declare(types.NewVar(, .currPkg, , ))
default:
errorf("unexpected tag: %v", )
}
}
func ( *importReader) ( types.Object) {
.Pkg().Scope().Insert()
}
func ( *importReader) () ( types.Type, constant.Value) {
= .typ()
if .p.version >= iexportVersionGo1_18 {
_ = constant.Kind(.int64())
}
switch := .Underlying().(*types.Basic); .Info() & types.IsConstType {
case types.IsBoolean:
= constant.MakeBool(.bool())
case types.IsString:
= constant.MakeString(.string())
case types.IsInteger:
var big.Int
.mpint(&, )
= constant.Make(&)
case types.IsFloat:
= .mpfloat()
case types.IsComplex:
:= .mpfloat()
:= .mpfloat()
= constant.BinaryOp(, token.ADD, constant.MakeImag())
default:
if .Kind() == types.Invalid {
= constant.MakeUnknown()
return
}
errorf("unexpected type %v", )
panic("unreachable")
}
return
}
func ( *types.Basic) ( bool, uint) {
if (.Info() & types.IsUntyped) != 0 {
return true, 64
}
switch .Kind() {
case types.Float32, types.Complex64:
return true, 3
case types.Float64, types.Complex128:
return true, 7
}
= (.Info() & types.IsUnsigned) == 0
switch .Kind() {
case types.Int8, types.Uint8:
= 1
case types.Int16, types.Uint16:
= 2
case types.Int32, types.Uint32:
= 4
default:
= 8
}
return
}
func ( *importReader) ( *big.Int, *types.Basic) {
, := intSize()
:= 256 -
if {
= 256 - 2*
}
if == 1 {
= 256
}
, := .declReader.ReadByte()
if uint() < {
:= int64()
if {
>>= 1
if &1 != 0 {
= ^
}
}
.SetInt64()
return
}
:= -
if {
= -( &^ 1) >> 1
}
if < 1 || uint() > {
errorf("weird decoding: %v, %v => %v", , , )
}
:= make([]byte, )
io.ReadFull(&.declReader, )
.SetBytes()
if && &1 != 0 {
.Neg()
}
}
func ( *importReader) ( *types.Basic) constant.Value {
var big.Int
.mpint(&, )
var big.Float
.SetInt(&)
if .Sign() != 0 {
.SetMantExp(&, int(.int64()))
}
return constant.Make(&)
}
func ( *importReader) () string {
return .string()
}
func ( *importReader) () (*types.Package, string) {
:= .string()
:= .pkg()
return ,
}
func ( *importReader) () token.Pos {
if .p.shallow {
return .posv2()
}
if .p.version >= iexportVersionPosCol {
.posv1()
} else {
.posv0()
}
if .prevFile == "" && .prevLine == 0 && .prevColumn == 0 {
return token.NoPos
}
return .p.fake.pos(.prevFile, int(.prevLine), int(.prevColumn))
}
func ( *importReader) () {
:= .int64()
if != deltaNewFile {
.prevLine +=
} else if := .int64(); == -1 {
.prevLine += deltaNewFile
} else {
.prevFile = .string()
.prevLine =
}
}
func ( *importReader) () {
:= .int64()
.prevColumn += >> 1
if &1 != 0 {
= .int64()
.prevLine += >> 1
if &1 != 0 {
.prevFile = .string()
}
}
}
func ( *importReader) () token.Pos {
:= .uint64()
if == 0 {
return token.NoPos
}
:= .p.fileAt( - 1)
return .Pos(int(.uint64()))
}
func ( *importReader) () types.Type {
return .p.typAt(.uint64(), nil)
}
func ( types.Type) bool {
, := aliases.Unalias().(*types.Interface)
return
}
func ( *importReader) () *types.Package { return .p.pkgAt(.uint64()) }
func ( *importReader) () string { return .p.stringAt(.uint64()) }
func ( *importReader) ( *types.Named) ( types.Type) {
:= .kind()
if debug {
.p.trace("importing type %d (base: %s)", , )
.p.indent++
defer func() {
.p.indent--
.p.trace("=> %s", )
}()
}
switch {
default:
errorf("unexpected kind tag in %q: %v", .p.ipath, )
return nil
case aliasType, definedType:
, := .qualifiedIdent()
.p.doDecl(, )
return .Scope().Lookup().(*types.TypeName).Type()
case pointerType:
return types.NewPointer(.typ())
case sliceType:
return types.NewSlice(.typ())
case arrayType:
:= .uint64()
return types.NewArray(.typ(), int64())
case chanType:
:= chanDir(int(.uint64()))
return types.NewChan(, .typ())
case mapType:
return types.NewMap(.typ(), .typ())
case signatureType:
.currPkg = .pkg()
return .signature(nil, nil, nil)
case structType:
.currPkg = .pkg()
:= make([]*types.Var, .uint64())
:= make([]string, len())
for := range {
var *types.Var
if .p.shallow {
, _ = .objectPathObject().(*types.Var)
}
:= .pos()
:= .ident()
:= .typ()
:= .bool()
:= .string()
if == nil {
= types.NewField(, .currPkg, , , )
}
[] =
[] =
}
return types.NewStruct(, )
case interfaceType:
.currPkg = .pkg()
:= make([]types.Type, .uint64())
for := range {
_ = .pos()
[] = .typ()
}
:= make([]*types.Func, .uint64())
for := range {
var *types.Func
if .p.shallow {
, _ = .objectPathObject().(*types.Func)
}
:= .pos()
:= .ident()
var *types.Var
if != nil {
= types.NewVar(token.NoPos, .currPkg, "", )
}
:= .signature(, nil, nil)
if == nil {
= types.NewFunc(, .currPkg, , )
}
[] =
}
:= newInterface(, )
.p.interfaceList = append(.p.interfaceList, )
return
case typeParamType:
if .p.version < iexportVersionGenerics {
errorf("unexpected type param type")
}
, := .qualifiedIdent()
:= ident{, }
if , := .p.tparamIndex[]; {
return
}
.p.doDecl(, )
return .p.tparamIndex[]
case instanceType:
if .p.version < iexportVersionGenerics {
errorf("unexpected instantiation type")
}
_ = .pos()
:= .uint64()
:= make([]types.Type, )
for := range {
[] = .typ()
}
:= .typ()
, := types.Instantiate(nil, , , false)
.p.instanceList = append(.p.instanceList, )
return
case unionType:
if .p.version < iexportVersionGenerics {
errorf("unexpected instantiation type")
}
:= make([]*types.Term, .uint64())
for := range {
[] = types.NewTerm(.bool(), .typ())
}
return types.NewUnion()
}
}
func ( *importReader) () itag {
return itag(.uint64())
}
func ( *importReader) () types.Object {
:= objectpath.Path(.string())
if == "" {
return nil
}
:= .pkg()
, := objectpath.Object(, )
if != nil {
if .p.reportf != nil {
.p.reportf("failed to find object for objectPath %q: %v", , )
}
}
return
}
func ( *importReader) ( *types.Var, []*types.TypeParam, []*types.TypeParam) *types.Signature {
:= .paramList()
:= .paramList()
:= .Len() > 0 && .bool()
return types.NewSignatureType(, , , , , )
}
func ( *importReader) () []*types.TypeParam {
:= .uint64()
if == 0 {
return nil
}
:= make([]*types.TypeParam, )
for := range {
[] = aliases.Unalias(.typ()).(*types.TypeParam)
}
return
}
func ( *importReader) () *types.Tuple {
:= make([]*types.Var, .uint64())
for := range {
[] = .param()
}
return types.NewTuple(...)
}
func ( *importReader) () *types.Var {
:= .pos()
:= .ident()
:= .typ()
return types.NewParam(, .currPkg, , )
}
func ( *importReader) () bool {
return .uint64() != 0
}
func ( *importReader) () int64 {
, := binary.ReadVarint(&.declReader)
if != nil {
errorf("readVarint: %v", )
}
return
}
func ( *importReader) () uint64 {
, := binary.ReadUvarint(&.declReader)
if != nil {
errorf("readUvarint: %v", )
}
return
}
func ( *importReader) () byte {
, := .declReader.ReadByte()
if != nil {
errorf("declReader.ReadByte: %v", )
}
return
}