Source file src/cmd/compile/internal/importer/ureader.go

     1  // Copyright 2021 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // package importer implements package reading for gc-generated object files.
     6  package importer
     7  
     8  import (
     9  	"cmd/compile/internal/base"
    10  	"cmd/compile/internal/syntax"
    11  	"cmd/compile/internal/types2"
    12  	"cmd/internal/src"
    13  	"internal/pkgbits"
    14  )
    15  
    16  type pkgReader struct {
    17  	pkgbits.PkgDecoder
    18  
    19  	ctxt        *types2.Context
    20  	imports     map[string]*types2.Package
    21  	enableAlias bool // whether to use aliases
    22  
    23  	posBases []*syntax.PosBase
    24  	pkgs     []*types2.Package
    25  	typs     []types2.Type
    26  }
    27  
    28  func ReadPackage(ctxt *types2.Context, imports map[string]*types2.Package, input pkgbits.PkgDecoder) *types2.Package {
    29  	pr := pkgReader{
    30  		PkgDecoder: input,
    31  
    32  		ctxt:        ctxt,
    33  		imports:     imports,
    34  		enableAlias: true,
    35  
    36  		posBases: make([]*syntax.PosBase, input.NumElems(pkgbits.SectionPosBase)),
    37  		pkgs:     make([]*types2.Package, input.NumElems(pkgbits.SectionPkg)),
    38  		typs:     make([]types2.Type, input.NumElems(pkgbits.SectionType)),
    39  	}
    40  
    41  	r := pr.newReader(pkgbits.SectionMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic)
    42  	pkg := r.pkg()
    43  
    44  	if r.Version().Has(pkgbits.HasInit) {
    45  		r.Bool()
    46  	}
    47  
    48  	for i, n := 0, r.Len(); i < n; i++ {
    49  		// As if r.obj(), but avoiding the Scope.Lookup call,
    50  		// to avoid eager loading of imports.
    51  		r.Sync(pkgbits.SyncObject)
    52  		if r.Version().Has(pkgbits.DerivedFuncInstance) {
    53  			assert(!r.Bool())
    54  		}
    55  		r.p.objIdx(r.Reloc(pkgbits.SectionObj))
    56  		assert(r.Len() == 0)
    57  	}
    58  
    59  	r.Sync(pkgbits.SyncEOF)
    60  
    61  	pkg.MarkComplete()
    62  	return pkg
    63  }
    64  
    65  type reader struct {
    66  	pkgbits.Decoder
    67  
    68  	p *pkgReader
    69  
    70  	dict    *readerDict
    71  	delayed []func()
    72  }
    73  
    74  type readerDict struct {
    75  	rtbounds []typeInfo
    76  	rtparams []*types2.TypeParam
    77  
    78  	tbounds []typeInfo
    79  	tparams []*types2.TypeParam
    80  
    81  	derived      []derivedInfo
    82  	derivedTypes []types2.Type
    83  }
    84  
    85  type readerTypeBound struct {
    86  	derived  bool
    87  	boundIdx int
    88  }
    89  
    90  func (pr *pkgReader) newReader(k pkgbits.SectionKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader {
    91  	return &reader{
    92  		Decoder: pr.NewDecoder(k, idx, marker),
    93  		p:       pr,
    94  	}
    95  }
    96  
    97  func (pr *pkgReader) tempReader(k pkgbits.SectionKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader {
    98  	return &reader{
    99  		Decoder: pr.TempDecoder(k, idx, marker),
   100  		p:       pr,
   101  	}
   102  }
   103  
   104  func (pr *pkgReader) retireReader(r *reader) {
   105  	pr.RetireDecoder(&r.Decoder)
   106  }
   107  
   108  // @@@ Positions
   109  
   110  func (r *reader) pos() syntax.Pos {
   111  	r.Sync(pkgbits.SyncPos)
   112  	if !r.Bool() {
   113  		return syntax.Pos{}
   114  	}
   115  
   116  	// TODO(mdempsky): Delta encoding.
   117  	posBase := r.posBase()
   118  	line := r.Uint()
   119  	col := r.Uint()
   120  	return syntax.MakePos(posBase, line, col)
   121  }
   122  
   123  func (r *reader) posBase() *syntax.PosBase {
   124  	return r.p.posBaseIdx(r.Reloc(pkgbits.SectionPosBase))
   125  }
   126  
   127  func (pr *pkgReader) posBaseIdx(idx pkgbits.Index) *syntax.PosBase {
   128  	if b := pr.posBases[idx]; b != nil {
   129  		return b
   130  	}
   131  	var b *syntax.PosBase
   132  	{
   133  		r := pr.tempReader(pkgbits.SectionPosBase, idx, pkgbits.SyncPosBase)
   134  
   135  		filename := r.String()
   136  
   137  		if r.Bool() {
   138  			b = syntax.NewTrimmedFileBase(filename, true)
   139  		} else {
   140  			pos := r.pos()
   141  			line := r.Uint()
   142  			col := r.Uint()
   143  			b = syntax.NewLineBase(pos, filename, true, line, col)
   144  		}
   145  		pr.retireReader(r)
   146  	}
   147  
   148  	pr.posBases[idx] = b
   149  	return b
   150  }
   151  
   152  // @@@ Packages
   153  
   154  func (r *reader) pkg() *types2.Package {
   155  	r.Sync(pkgbits.SyncPkg)
   156  	return r.p.pkgIdx(r.Reloc(pkgbits.SectionPkg))
   157  }
   158  
   159  func (pr *pkgReader) pkgIdx(idx pkgbits.Index) *types2.Package {
   160  	// TODO(mdempsky): Consider using some non-nil pointer to indicate
   161  	// the universe scope, so we don't need to keep re-reading it.
   162  	if pkg := pr.pkgs[idx]; pkg != nil {
   163  		return pkg
   164  	}
   165  
   166  	pkg := pr.newReader(pkgbits.SectionPkg, idx, pkgbits.SyncPkgDef).doPkg()
   167  	pr.pkgs[idx] = pkg
   168  	return pkg
   169  }
   170  
   171  func (r *reader) doPkg() *types2.Package {
   172  	path := r.String()
   173  	switch path {
   174  	case "":
   175  		path = r.p.PkgPath()
   176  	case "builtin":
   177  		return nil // universe
   178  	case "unsafe":
   179  		return types2.Unsafe
   180  	}
   181  
   182  	if pkg := r.p.imports[path]; pkg != nil {
   183  		return pkg
   184  	}
   185  
   186  	name := r.String()
   187  	pkg := types2.NewPackage(path, name)
   188  	r.p.imports[path] = pkg
   189  
   190  	// TODO(mdempsky): The list of imported packages is important for
   191  	// go/types, but we could probably skip populating it for types2.
   192  	imports := make([]*types2.Package, r.Len())
   193  	for i := range imports {
   194  		imports[i] = r.pkg()
   195  	}
   196  	pkg.SetImports(imports)
   197  
   198  	return pkg
   199  }
   200  
   201  // @@@ Types
   202  
   203  func (r *reader) typ() types2.Type {
   204  	return r.p.typIdx(r.typInfo(), r.dict)
   205  }
   206  
   207  func (r *reader) typInfo() typeInfo {
   208  	r.Sync(pkgbits.SyncType)
   209  	if r.Bool() {
   210  		return typeInfo{idx: pkgbits.Index(r.Len()), derived: true}
   211  	}
   212  	return typeInfo{idx: r.Reloc(pkgbits.SectionType), derived: false}
   213  }
   214  
   215  func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict) types2.Type {
   216  	idx := info.idx
   217  	var where *types2.Type
   218  	if info.derived {
   219  		where = &dict.derivedTypes[idx]
   220  		idx = dict.derived[idx].idx
   221  	} else {
   222  		where = &pr.typs[idx]
   223  	}
   224  
   225  	if typ := *where; typ != nil {
   226  		return typ
   227  	}
   228  
   229  	var typ types2.Type
   230  	{
   231  		r := pr.tempReader(pkgbits.SectionType, idx, pkgbits.SyncTypeIdx)
   232  		r.dict = dict
   233  
   234  		typ = r.doTyp()
   235  		assert(typ != nil)
   236  		pr.retireReader(r)
   237  	}
   238  
   239  	// See comment in pkgReader.typIdx explaining how this happens.
   240  	if prev := *where; prev != nil {
   241  		return prev
   242  	}
   243  
   244  	*where = typ
   245  	return typ
   246  }
   247  
   248  func (r *reader) doTyp() (res types2.Type) {
   249  	switch tag := pkgbits.CodeType(r.Code(pkgbits.SyncType)); tag {
   250  	default:
   251  		base.FatalfAt(src.NoXPos, "unhandled type tag: %v", tag)
   252  		panic("unreachable")
   253  
   254  	case pkgbits.TypeBasic:
   255  		return types2.Typ[r.Len()]
   256  
   257  	case pkgbits.TypeNamed:
   258  		obj, targs := r.obj()
   259  		name := obj.(*types2.TypeName)
   260  		if len(targs) != 0 {
   261  			t, _ := types2.Instantiate(r.p.ctxt, name.Type(), targs, false)
   262  			return t
   263  		}
   264  		return name.Type()
   265  
   266  	case pkgbits.TypeTypeParam:
   267  		n := r.Len()
   268  		if n < len(r.dict.rtbounds) {
   269  			return r.dict.rtparams[n]
   270  		}
   271  		return r.dict.tparams[n-len(r.dict.rtbounds)]
   272  
   273  	case pkgbits.TypeArray:
   274  		len := int64(r.Uint64())
   275  		return types2.NewArray(r.typ(), len)
   276  	case pkgbits.TypeChan:
   277  		dir := types2.ChanDir(r.Len())
   278  		return types2.NewChan(dir, r.typ())
   279  	case pkgbits.TypeMap:
   280  		return types2.NewMap(r.typ(), r.typ())
   281  	case pkgbits.TypePointer:
   282  		return types2.NewPointer(r.typ())
   283  	case pkgbits.TypeSignature:
   284  		return r.signature(nil, nil, nil)
   285  	case pkgbits.TypeSlice:
   286  		return types2.NewSlice(r.typ())
   287  	case pkgbits.TypeStruct:
   288  		return r.structType()
   289  	case pkgbits.TypeInterface:
   290  		return r.interfaceType()
   291  	case pkgbits.TypeUnion:
   292  		return r.unionType()
   293  	}
   294  }
   295  
   296  func (r *reader) structType() *types2.Struct {
   297  	fields := make([]*types2.Var, r.Len())
   298  	var tags []string
   299  	for i := range fields {
   300  		pos := r.pos()
   301  		pkg, name := r.selector()
   302  		ftyp := r.typ()
   303  		tag := r.String()
   304  		embedded := r.Bool()
   305  
   306  		fields[i] = types2.NewField(pos, pkg, name, ftyp, embedded)
   307  		if tag != "" {
   308  			for len(tags) < i {
   309  				tags = append(tags, "")
   310  			}
   311  			tags = append(tags, tag)
   312  		}
   313  	}
   314  	return types2.NewStruct(fields, tags)
   315  }
   316  
   317  func (r *reader) unionType() *types2.Union {
   318  	terms := make([]*types2.Term, r.Len())
   319  	for i := range terms {
   320  		terms[i] = types2.NewTerm(r.Bool(), r.typ())
   321  	}
   322  	return types2.NewUnion(terms)
   323  }
   324  
   325  func (r *reader) interfaceType() *types2.Interface {
   326  	methods := make([]*types2.Func, r.Len())
   327  	embeddeds := make([]types2.Type, r.Len())
   328  	implicit := len(methods) == 0 && len(embeddeds) == 1 && r.Bool()
   329  
   330  	for i := range methods {
   331  		pos := r.pos()
   332  		pkg, name := r.selector()
   333  		mtyp := r.signature(nil, nil, nil)
   334  		methods[i] = types2.NewFunc(pos, pkg, name, mtyp)
   335  	}
   336  
   337  	for i := range embeddeds {
   338  		embeddeds[i] = r.typ()
   339  	}
   340  
   341  	iface := types2.NewInterfaceType(methods, embeddeds)
   342  	if implicit {
   343  		iface.MarkImplicit()
   344  	}
   345  	return iface
   346  }
   347  
   348  func (r *reader) signature(recv *types2.Var, rtparams, tparams []*types2.TypeParam) *types2.Signature {
   349  	r.Sync(pkgbits.SyncSignature)
   350  
   351  	params := r.params()
   352  	results := r.params()
   353  	variadic := r.Bool()
   354  
   355  	return types2.NewSignatureType(recv, rtparams, tparams, params, results, variadic)
   356  }
   357  
   358  func (r *reader) params() *types2.Tuple {
   359  	r.Sync(pkgbits.SyncParams)
   360  	params := make([]*types2.Var, r.Len())
   361  	for i := range params {
   362  		params[i] = r.param()
   363  	}
   364  	return types2.NewTuple(params...)
   365  }
   366  
   367  func (r *reader) param() *types2.Var {
   368  	r.Sync(pkgbits.SyncParam)
   369  
   370  	pos := r.pos()
   371  	pkg, name := r.localIdent()
   372  	typ := r.typ()
   373  
   374  	return types2.NewParam(pos, pkg, name, typ)
   375  }
   376  
   377  // @@@ Objects
   378  
   379  func (r *reader) obj() (types2.Object, []types2.Type) {
   380  	r.Sync(pkgbits.SyncObject)
   381  
   382  	if r.Version().Has(pkgbits.DerivedFuncInstance) {
   383  		assert(!r.Bool())
   384  	}
   385  
   386  	pkg, name := r.p.objIdx(r.Reloc(pkgbits.SectionObj))
   387  	obj := pkg.Scope().Lookup(name)
   388  
   389  	targs := make([]types2.Type, r.Len())
   390  	for i := range targs {
   391  		targs[i] = r.typ()
   392  	}
   393  
   394  	return obj, targs
   395  }
   396  
   397  func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types2.Package, string) {
   398  	var objPkg *types2.Package
   399  	var objName string
   400  	var tag pkgbits.CodeObj
   401  	{
   402  		rname := pr.tempReader(pkgbits.SectionName, idx, pkgbits.SyncObject1)
   403  
   404  		objPkg, objName = rname.qualifiedIdent()
   405  		assert(objName != "")
   406  
   407  		tag = pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj))
   408  		pr.retireReader(rname)
   409  	}
   410  
   411  	if tag == pkgbits.ObjStub {
   412  		base.Assertf(objPkg == nil || objPkg == types2.Unsafe, "unexpected stub package: %v", objPkg)
   413  		return objPkg, objName
   414  	}
   415  
   416  	objPkg.Scope().InsertLazy(objName, func() types2.Object {
   417  		dict := pr.objDictIdx(idx)
   418  
   419  		r := pr.newReader(pkgbits.SectionObj, idx, pkgbits.SyncObject1)
   420  		r.dict = dict
   421  
   422  		switch tag {
   423  		default:
   424  			panic("weird")
   425  
   426  		case pkgbits.ObjAlias:
   427  			pos := r.pos()
   428  			var tparams []*types2.TypeParam
   429  			if r.Version().Has(pkgbits.AliasTypeParamNames) {
   430  				tparams = r.typeParamNames(false, false)
   431  			}
   432  			typ := r.typ()
   433  			return newAliasTypeName(pr.enableAlias, pos, objPkg, objName, typ, tparams)
   434  
   435  		case pkgbits.ObjConst:
   436  			pos := r.pos()
   437  			typ := r.typ()
   438  			val := r.Value()
   439  			return types2.NewConst(pos, objPkg, objName, typ, val)
   440  
   441  		case pkgbits.ObjFunc:
   442  			pos := r.pos()
   443  			if r.Version().Has(pkgbits.GenericMethods) {
   444  				assert(!r.Bool()) // generic methods are read in their defining type
   445  			}
   446  			tparams := r.typeParamNames(false, false)
   447  			sig := r.signature(nil, nil, tparams)
   448  			return types2.NewFunc(pos, objPkg, objName, sig)
   449  
   450  		case pkgbits.ObjType:
   451  			pos := r.pos()
   452  
   453  			return types2.NewTypeNameLazy(pos, objPkg, objName, func(_ *types2.Named) ([]*types2.TypeParam, types2.Type, []*types2.Func, []func()) {
   454  				tparams := r.typeParamNames(true, false)
   455  
   456  				// TODO(mdempsky): Rewrite receiver types to underlying is an
   457  				// Interface? The go/types importer does this (I think because
   458  				// unit tests expected that), but cmd/compile doesn't care
   459  				// about it, so maybe we can avoid worrying about that here.
   460  				underlying := r.typ().Underlying()
   461  
   462  				methods := make([]*types2.Func, r.Len())
   463  				for i := range methods {
   464  					methods[i] = r.method(true)
   465  				}
   466  
   467  				if r.Version().Has(pkgbits.GenericMethods) {
   468  					for range r.Len() {
   469  						// Careful: objIdx is used to read in package-scoped declarations, which
   470  						// methods are not. Instead, decode it here. This makes it easier to
   471  						// associate it with the type and avoids the main objIdx loop.
   472  						idx := r.Reloc(pkgbits.SectionObj)
   473  
   474  						t := pr.tempReader(pkgbits.SectionObj, idx, pkgbits.SyncObject1)
   475  						t.dict = pr.objDictIdx(idx)
   476  
   477  						pos := t.pos()
   478  						assert(t.Bool()) // generic method
   479  						pkg, name := t.selector()
   480  						rtparams := t.typeParamNames(true, true)
   481  						recv := t.param()
   482  						tparams := t.typeParamNames(true, false)
   483  						sig := t.signature(recv, rtparams, tparams)
   484  
   485  						r.delayed = append(r.delayed, t.delayed...) // propagate before retiring
   486  
   487  						pr.retireReader(t)
   488  						methods = append(methods, types2.NewFunc(pos, pkg, name, sig))
   489  					}
   490  				}
   491  
   492  				return tparams, underlying, methods, r.delayed
   493  			})
   494  
   495  		case pkgbits.ObjVar:
   496  			pos := r.pos()
   497  			typ := r.typ()
   498  			return types2.NewVar(pos, objPkg, objName, typ)
   499  		}
   500  	})
   501  
   502  	return objPkg, objName
   503  }
   504  
   505  func (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict {
   506  	var dict readerDict
   507  	{
   508  		r := pr.tempReader(pkgbits.SectionObjDict, idx, pkgbits.SyncObject1)
   509  
   510  		if implicits := r.Len(); implicits != 0 {
   511  			base.Fatalf("unexpected object with %v implicit type parameter(s)", implicits)
   512  		}
   513  
   514  		nreceivers := 0
   515  		if r.Version().Has(pkgbits.GenericMethods) {
   516  			nreceivers = r.Len()
   517  		}
   518  		nexplicits := r.Len()
   519  
   520  		dict.rtbounds = make([]typeInfo, nreceivers)
   521  		for i := range dict.rtbounds {
   522  			dict.rtbounds[i] = r.typInfo()
   523  		}
   524  
   525  		dict.tbounds = make([]typeInfo, nexplicits)
   526  		for i := range dict.tbounds {
   527  			dict.tbounds[i] = r.typInfo()
   528  		}
   529  
   530  		dict.derived = make([]derivedInfo, r.Len())
   531  		dict.derivedTypes = make([]types2.Type, len(dict.derived))
   532  		for i := range dict.derived {
   533  			dict.derived[i] = derivedInfo{idx: r.Reloc(pkgbits.SectionType)}
   534  			if r.Version().Has(pkgbits.DerivedInfoNeeded) {
   535  				assert(!r.Bool())
   536  			}
   537  		}
   538  
   539  		pr.retireReader(r)
   540  	}
   541  	// function references follow, but reader doesn't need those
   542  
   543  	return &dict
   544  }
   545  
   546  func (r *reader) typeParamNames(isLazy bool, isGenMeth bool) []*types2.TypeParam {
   547  	r.Sync(pkgbits.SyncTypeParamNames)
   548  
   549  	// Note: This code assumes there are no implicit type parameters.
   550  	// This is fine since it only reads exported declarations, which
   551  	// never have implicits.
   552  
   553  	var in []typeInfo
   554  	var out *[]*types2.TypeParam
   555  	if isGenMeth {
   556  		in = r.dict.rtbounds
   557  		out = &r.dict.rtparams
   558  	} else {
   559  		in = r.dict.tbounds
   560  		out = &r.dict.tparams
   561  	}
   562  
   563  	if len(in) == 0 {
   564  		return nil
   565  	}
   566  
   567  	// Careful: Type parameter lists may have cycles. To allow for this,
   568  	// we construct the type parameter list in two passes: first we
   569  	// create all the TypeNames and TypeParams, then we construct and
   570  	// set the bound type.
   571  
   572  	// We have to save tparams outside of the closure, because typeParamNames
   573  	// can be called multiple times with the same dictionary instance.
   574  	tparams := make([]*types2.TypeParam, len(in))
   575  	*out = tparams
   576  
   577  	for i := range in {
   578  		pos := r.pos()
   579  		pkg, name := r.localIdent()
   580  
   581  		tname := types2.NewTypeName(pos, pkg, name, nil)
   582  		tparams[i] = types2.NewTypeParam(tname, nil)
   583  	}
   584  
   585  	// Type parameters that are read by lazy loaders cannot have their
   586  	// constraints set eagerly; do them after loading (go.dev/issue/63285).
   587  	if isLazy {
   588  		// The reader dictionary will continue mutating before we have time
   589  		// to call delayed functions; make a local copy of the constraints.
   590  		types := make([]types2.Type, len(in))
   591  		for i, info := range in {
   592  			types[i] = r.p.typIdx(info, r.dict)
   593  		}
   594  
   595  		r.delayed = append(r.delayed, func() {
   596  			for i, typ := range types {
   597  				tparams[i].SetConstraint(typ)
   598  			}
   599  		})
   600  	} else {
   601  		for i, info := range in {
   602  			tparams[i].SetConstraint(r.p.typIdx(info, r.dict))
   603  		}
   604  	}
   605  
   606  	return tparams
   607  }
   608  
   609  func (r *reader) method(isLazy bool) *types2.Func {
   610  	r.Sync(pkgbits.SyncMethod)
   611  	pos := r.pos()
   612  	pkg, name := r.selector()
   613  
   614  	rtparams := r.typeParamNames(isLazy, false)
   615  	sig := r.signature(r.param(), rtparams, nil)
   616  
   617  	_ = r.pos() // TODO(mdempsky): Remove; this is a hacker for linker.go.
   618  	return types2.NewFunc(pos, pkg, name, sig)
   619  }
   620  
   621  func (r *reader) qualifiedIdent() (*types2.Package, string) { return r.ident(pkgbits.SyncSym) }
   622  func (r *reader) localIdent() (*types2.Package, string)     { return r.ident(pkgbits.SyncLocalIdent) }
   623  func (r *reader) selector() (*types2.Package, string)       { return r.ident(pkgbits.SyncSelector) }
   624  
   625  func (r *reader) ident(marker pkgbits.SyncMarker) (*types2.Package, string) {
   626  	r.Sync(marker)
   627  	return r.pkg(), r.String()
   628  }
   629  
   630  // newAliasTypeName returns a new TypeName, with a materialized *types2.Alias if supported.
   631  func newAliasTypeName(aliases bool, pos syntax.Pos, pkg *types2.Package, name string, rhs types2.Type, tparams []*types2.TypeParam) *types2.TypeName {
   632  	// Copied from x/tools/internal/aliases.NewAlias via
   633  	// GOROOT/src/go/internal/gcimporter/ureader.go.
   634  	if aliases {
   635  		tname := types2.NewTypeName(pos, pkg, name, nil)
   636  		a := types2.NewAlias(tname, rhs) // form TypeName -> Alias cycle
   637  		a.SetTypeParams(tparams)
   638  		return tname
   639  	}
   640  	assert(len(tparams) == 0)
   641  	return types2.NewTypeName(pos, pkg, name, rhs)
   642  }
   643  

View as plain text