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

View as plain text