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

View as plain text