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
)
func ( *token.FileSet, map[string]*types.Package, []byte, string) (int, *types.Package, error) {
, := iimportCommon(, , , false, , nil)
if != nil {
return 0, nil,
}
return 0, [0], nil
}
func ( *token.FileSet, map[string]*types.Package, []byte) ([]*types.Package, error) {
return iimportCommon(, , , true, "", nil)
}
func ( *token.FileSet, map[string]*types.Package, []byte, bool, string, InsertType) ( []*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("cannot import %q (%v), possibly version skew - reinstall package", , )
}
}
}()
}
:= &intReader{bytes.NewReader(), }
if {
:= .uint64()
switch {
case :
default:
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 != nil {
= int64(.uint64())
= make([]uint64, .uint64())
for := range {
[] = .uint64()
}
}
:= int64(.uint64())
, := .Seek(0, io.SeekCurrent)
:= [ : +]
:= [+ : ++]
:= [++ : +++]
.Seek(++, io.SeekCurrent)
:= iimporter{
version: int(),
ipath: ,
insert: ,
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([]*types.Package, .uint64())
for := range {
:= .uint64()
:= .stringAt()
:= .stringAt(.uint64())
_ = .uint64()
if == "" {
=
}
:= []
if == nil {
= types.NewPackage(, )
[] =
} else if .Name() != {
errorf("conflicting names %s and %s for package %q", .Name(), , )
}
if == 0 && ! {
.localpkg =
}
.pkgCache[] =
:= make(map[string]uint64)
:= .uint64()
assert( == 0 || .localpkg == || .insert == nil)
for ; > 0; -- {
:= .stringAt(.uint64())
[] = .uint64()
}
.pkgIndex[] =
[] =
}
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 {
typeparams.SetTypeParamConstraint(.t, .constraint)
}
for , := range .interfaceList {
.Complete()
}
return , nil
}
type setConstraintArgs struct {
t *typeparams.TypeParam
constraint types.Type
}
type iimporter struct {
version int
ipath string
localpkg *types.Package
insert func(pkg *types.Package, name string)
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
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 ! {
if .insert != nil {
assert( != .localpkg)
.insert(, )
return
}
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
}
, := .(*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 'A':
:= .typ()
.declare(types.NewTypeName(, .currPkg, , ))
case 'C':
, := .value()
.declare(types.NewConst(, .currPkg, , , ))
case 'F', 'G':
var []*typeparams.TypeParam
if == 'G' {
= .tparamList()
}
:= .signature(nil, nil, )
.declare(types.NewFunc(, .currPkg, , ))
case 'T', 'U':
:= types.NewTypeName(, .currPkg, , nil)
:= types.NewNamed(, nil, nil)
.declare()
if == 'U' {
:= .tparamList()
typeparams.SetForNamed(, )
}
:= .p.typAt(.uint64(), ).Underlying()
.SetUnderlying()
if !isInterface() {
for := .uint64(); > 0; -- {
:= .pos()
:= .ident()
:= .param()
:= baseType(.Type())
assert( != nil)
:= typeparams.NamedTypeArgs()
var []*typeparams.TypeParam
if .Len() > 0 {
= make([]*typeparams.TypeParam, .Len())
for := range {
[] = .At().(*typeparams.TypeParam)
}
}
:= .signature(, , nil)
.AddMethod(types.NewFunc(, .currPkg, , ))
}
}
case 'P':
if .p.version < iexportVersionGenerics {
errorf("unexpected type param type")
}
:= tparamName()
:= types.NewTypeName(, .currPkg, , nil)
:= typeparams.NewTypeParam(, nil)
:= ident{.currPkg, }
.p.tparamIndex[] =
var bool
if .p.version >= iexportVersionGo1_18 {
= .bool()
}
:= .typ()
if {
, := .(*types.Interface)
if == nil {
errorf("non-interface constraint marked implicit")
}
typeparams.MarkImplicit()
}
.p.later = append(.p.later, setConstraintArgs{t: , constraint: })
case 'V':
:= .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.insert != nil {
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 {
, := .(*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 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 {
:= .pos()
:= .ident()
:= .typ()
:= .bool()
:= .string()
[] = types.NewField(, .currPkg, , , )
[] =
}
return types.NewStruct(, )
case interfaceType:
.currPkg = .pkg()
:= make([]types.Type, .uint64())
for := range {
_ = .pos()
[] = .typ()
}
:= make([]*types.Func, .uint64())
for := range {
:= .pos()
:= .ident()
var *types.Var
if != nil {
= types.NewVar(token.NoPos, .currPkg, "", )
}
:= .signature(, nil, 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()
, := typeparams.Instantiate(nil, , , false)
return
case unionType:
if .p.version < iexportVersionGenerics {
errorf("unexpected instantiation type")
}
:= make([]*typeparams.Term, .uint64())
for := range {
[] = typeparams.NewTerm(.bool(), .typ())
}
return typeparams.NewUnion()
}
}
func ( *importReader) () itag {
return itag(.uint64())
}
func ( *importReader) ( *types.Var, []*typeparams.TypeParam, []*typeparams.TypeParam) *types.Signature {
:= .paramList()
:= .paramList()
:= .Len() > 0 && .bool()
return typeparams.NewSignatureType(, , , , , )
}
func ( *importReader) () []*typeparams.TypeParam {
:= .uint64()
if == 0 {
return nil
}
:= make([]*typeparams.TypeParam, )
for := range {
[] = .typ().(*typeparams.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
}
func ( types.Type) *types.Named {
if , := .(*types.Pointer); != nil {
= .Elem()
}
, := .(*types.Named)
return
}