github.com/bir3/gocompiler@v0.9.2202/src/go/internal/gcimporter/ureader.go (about)

     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 gcimporter
     6  
     7  import (
     8  	"github.com/bir3/gocompiler/src/go/token"
     9  	"github.com/bir3/gocompiler/src/go/types"
    10  	"github.com/bir3/gocompiler/src/internal/pkgbits"
    11  	"sort"
    12  )
    13  
    14  // A pkgReader holds the shared state for reading a unified IR package
    15  // description.
    16  type pkgReader struct {
    17  	pkgbits.PkgDecoder
    18  
    19  	fake	fakeFileSet
    20  
    21  	ctxt	*types.Context
    22  	imports	map[string]*types.Package	// previously imported packages, indexed by path
    23  
    24  	// lazily initialized arrays corresponding to the unified IR
    25  	// PosBase, Pkg, and Type sections, respectively.
    26  	posBases	[]string	// position bases (i.e., file names)
    27  	pkgs		[]*types.Package
    28  	typs		[]types.Type
    29  
    30  	// laterFns holds functions that need to be invoked at the end of
    31  	// import reading.
    32  	laterFns	[]func()
    33  
    34  	// ifaces holds a list of constructed Interfaces, which need to have
    35  	// Complete called after importing is done.
    36  	ifaces	[]*types.Interface
    37  }
    38  
    39  // later adds a function to be invoked at the end of import reading.
    40  func (pr *pkgReader) later(fn func()) {
    41  	pr.laterFns = append(pr.laterFns, fn)
    42  }
    43  
    44  // readUnifiedPackage reads a package description from the given
    45  // unified IR export data decoder.
    46  func readUnifiedPackage(fset *token.FileSet, ctxt *types.Context, imports map[string]*types.Package, input pkgbits.PkgDecoder) *types.Package {
    47  	pr := pkgReader{
    48  		PkgDecoder:	input,
    49  
    50  		fake: fakeFileSet{
    51  			fset:	fset,
    52  			files:	make(map[string]*fileInfo),
    53  		},
    54  
    55  		ctxt:		ctxt,
    56  		imports:	imports,
    57  
    58  		posBases:	make([]string, input.NumElems(pkgbits.RelocPosBase)),
    59  		pkgs:		make([]*types.Package, input.NumElems(pkgbits.RelocPkg)),
    60  		typs:		make([]types.Type, input.NumElems(pkgbits.RelocType)),
    61  	}
    62  	defer pr.fake.setLines()
    63  
    64  	r := pr.newReader(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic)
    65  	pkg := r.pkg()
    66  	r.Bool()	// TODO(mdempsky): Remove; was "has init"
    67  
    68  	for i, n := 0, r.Len(); i < n; i++ {
    69  		// As if r.obj(), but avoiding the Scope.Lookup call,
    70  		// to avoid eager loading of imports.
    71  		r.Sync(pkgbits.SyncObject)
    72  		assert(!r.Bool())
    73  		r.p.objIdx(r.Reloc(pkgbits.RelocObj))
    74  		assert(r.Len() == 0)
    75  	}
    76  
    77  	r.Sync(pkgbits.SyncEOF)
    78  
    79  	for _, fn := range pr.laterFns {
    80  		fn()
    81  	}
    82  
    83  	for _, iface := range pr.ifaces {
    84  		iface.Complete()
    85  	}
    86  
    87  	// Imports() of pkg are all of the transitive packages that were loaded.
    88  	var imps []*types.Package
    89  	for _, imp := range pr.pkgs {
    90  		if imp != nil && imp != pkg {
    91  			imps = append(imps, imp)
    92  		}
    93  	}
    94  	sort.Sort(byPath(imps))
    95  	pkg.SetImports(imps)
    96  
    97  	pkg.MarkComplete()
    98  	return pkg
    99  }
   100  
   101  // A reader holds the state for reading a single unified IR element
   102  // within a package.
   103  type reader struct {
   104  	pkgbits.Decoder
   105  
   106  	p	*pkgReader
   107  
   108  	dict	*readerDict
   109  }
   110  
   111  // A readerDict holds the state for type parameters that parameterize
   112  // the current unified IR element.
   113  type readerDict struct {
   114  	// bounds is a slice of typeInfos corresponding to the underlying
   115  	// bounds of the element's type parameters.
   116  	bounds	[]typeInfo
   117  
   118  	// tparams is a slice of the constructed TypeParams for the element.
   119  	tparams	[]*types.TypeParam
   120  
   121  	// derived is a slice of types derived from tparams, which may be
   122  	// instantiated while reading the current element.
   123  	derived		[]derivedInfo
   124  	derivedTypes	[]types.Type	// lazily instantiated from derived
   125  }
   126  
   127  func (pr *pkgReader) newReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader {
   128  	return &reader{
   129  		Decoder:	pr.NewDecoder(k, idx, marker),
   130  		p:		pr,
   131  	}
   132  }
   133  
   134  func (pr *pkgReader) tempReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader {
   135  	return &reader{
   136  		Decoder:	pr.TempDecoder(k, idx, marker),
   137  		p:		pr,
   138  	}
   139  }
   140  
   141  func (pr *pkgReader) retireReader(r *reader) {
   142  	pr.RetireDecoder(&r.Decoder)
   143  }
   144  
   145  // @@@ Positions
   146  
   147  func (r *reader) pos() token.Pos {
   148  	r.Sync(pkgbits.SyncPos)
   149  	if !r.Bool() {
   150  		return token.NoPos
   151  	}
   152  
   153  	// TODO(mdempsky): Delta encoding.
   154  	posBase := r.posBase()
   155  	line := r.Uint()
   156  	col := r.Uint()
   157  	return r.p.fake.pos(posBase, int(line), int(col))
   158  }
   159  
   160  func (r *reader) posBase() string {
   161  	return r.p.posBaseIdx(r.Reloc(pkgbits.RelocPosBase))
   162  }
   163  
   164  func (pr *pkgReader) posBaseIdx(idx pkgbits.Index) string {
   165  	if b := pr.posBases[idx]; b != "" {
   166  		return b
   167  	}
   168  
   169  	var filename string
   170  	{
   171  		r := pr.tempReader(pkgbits.RelocPosBase, idx, pkgbits.SyncPosBase)
   172  
   173  		// Within types2, position bases have a lot more details (e.g.,
   174  		// keeping track of where //line directives appeared exactly).
   175  		//
   176  		// For go/types, we just track the file name.
   177  
   178  		filename = r.String()
   179  
   180  		if r.Bool() {	// file base
   181  			// Was: "b = token.NewTrimmedFileBase(filename, true)"
   182  		} else {	// line base
   183  			pos := r.pos()
   184  			line := r.Uint()
   185  			col := r.Uint()
   186  
   187  			// Was: "b = token.NewLineBase(pos, filename, true, line, col)"
   188  			_, _, _ = pos, line, col
   189  		}
   190  		pr.retireReader(r)
   191  	}
   192  	b := filename
   193  	pr.posBases[idx] = b
   194  	return b
   195  }
   196  
   197  // @@@ Packages
   198  
   199  func (r *reader) pkg() *types.Package {
   200  	r.Sync(pkgbits.SyncPkg)
   201  	return r.p.pkgIdx(r.Reloc(pkgbits.RelocPkg))
   202  }
   203  
   204  func (pr *pkgReader) pkgIdx(idx pkgbits.Index) *types.Package {
   205  	// TODO(mdempsky): Consider using some non-nil pointer to indicate
   206  	// the universe scope, so we don't need to keep re-reading it.
   207  	if pkg := pr.pkgs[idx]; pkg != nil {
   208  		return pkg
   209  	}
   210  
   211  	pkg := pr.newReader(pkgbits.RelocPkg, idx, pkgbits.SyncPkgDef).doPkg()
   212  	pr.pkgs[idx] = pkg
   213  	return pkg
   214  }
   215  
   216  func (r *reader) doPkg() *types.Package {
   217  	path := r.String()
   218  	switch path {
   219  	case "":
   220  		path = r.p.PkgPath()
   221  	case "builtin":
   222  		return nil	// universe
   223  	case "unsafe":
   224  		return types.Unsafe
   225  	}
   226  
   227  	if pkg := r.p.imports[path]; pkg != nil {
   228  		return pkg
   229  	}
   230  
   231  	name := r.String()
   232  
   233  	pkg := types.NewPackage(path, name)
   234  	r.p.imports[path] = pkg
   235  
   236  	return pkg
   237  }
   238  
   239  // @@@ Types
   240  
   241  func (r *reader) typ() types.Type {
   242  	return r.p.typIdx(r.typInfo(), r.dict)
   243  }
   244  
   245  func (r *reader) typInfo() typeInfo {
   246  	r.Sync(pkgbits.SyncType)
   247  	if r.Bool() {
   248  		return typeInfo{idx: pkgbits.Index(r.Len()), derived: true}
   249  	}
   250  	return typeInfo{idx: r.Reloc(pkgbits.RelocType), derived: false}
   251  }
   252  
   253  func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict) types.Type {
   254  	idx := info.idx
   255  	var where *types.Type
   256  	if info.derived {
   257  		where = &dict.derivedTypes[idx]
   258  		idx = dict.derived[idx].idx
   259  	} else {
   260  		where = &pr.typs[idx]
   261  	}
   262  
   263  	if typ := *where; typ != nil {
   264  		return typ
   265  	}
   266  
   267  	var typ types.Type
   268  	{
   269  		r := pr.tempReader(pkgbits.RelocType, idx, pkgbits.SyncTypeIdx)
   270  		r.dict = dict
   271  
   272  		typ = r.doTyp()
   273  		assert(typ != nil)
   274  		pr.retireReader(r)
   275  	}
   276  	// See comment in pkgReader.typIdx explaining how this happens.
   277  	if prev := *where; prev != nil {
   278  		return prev
   279  	}
   280  
   281  	*where = typ
   282  	return typ
   283  }
   284  
   285  func (r *reader) doTyp() (res types.Type) {
   286  	switch tag := pkgbits.CodeType(r.Code(pkgbits.SyncType)); tag {
   287  	default:
   288  		errorf("unhandled type tag: %v", tag)
   289  		panic("unreachable")
   290  
   291  	case pkgbits.TypeBasic:
   292  		return types.Typ[r.Len()]
   293  
   294  	case pkgbits.TypeNamed:
   295  		obj, targs := r.obj()
   296  		name := obj.(*types.TypeName)
   297  		if len(targs) != 0 {
   298  			t, _ := types.Instantiate(r.p.ctxt, name.Type(), targs, false)
   299  			return t
   300  		}
   301  		return name.Type()
   302  
   303  	case pkgbits.TypeTypeParam:
   304  		return r.dict.tparams[r.Len()]
   305  
   306  	case pkgbits.TypeArray:
   307  		len := int64(r.Uint64())
   308  		return types.NewArray(r.typ(), len)
   309  	case pkgbits.TypeChan:
   310  		dir := types.ChanDir(r.Len())
   311  		return types.NewChan(dir, r.typ())
   312  	case pkgbits.TypeMap:
   313  		return types.NewMap(r.typ(), r.typ())
   314  	case pkgbits.TypePointer:
   315  		return types.NewPointer(r.typ())
   316  	case pkgbits.TypeSignature:
   317  		return r.signature(nil, nil, nil)
   318  	case pkgbits.TypeSlice:
   319  		return types.NewSlice(r.typ())
   320  	case pkgbits.TypeStruct:
   321  		return r.structType()
   322  	case pkgbits.TypeInterface:
   323  		return r.interfaceType()
   324  	case pkgbits.TypeUnion:
   325  		return r.unionType()
   326  	}
   327  }
   328  
   329  func (r *reader) structType() *types.Struct {
   330  	fields := make([]*types.Var, r.Len())
   331  	var tags []string
   332  	for i := range fields {
   333  		pos := r.pos()
   334  		pkg, name := r.selector()
   335  		ftyp := r.typ()
   336  		tag := r.String()
   337  		embedded := r.Bool()
   338  
   339  		fields[i] = types.NewField(pos, pkg, name, ftyp, embedded)
   340  		if tag != "" {
   341  			for len(tags) < i {
   342  				tags = append(tags, "")
   343  			}
   344  			tags = append(tags, tag)
   345  		}
   346  	}
   347  	return types.NewStruct(fields, tags)
   348  }
   349  
   350  func (r *reader) unionType() *types.Union {
   351  	terms := make([]*types.Term, r.Len())
   352  	for i := range terms {
   353  		terms[i] = types.NewTerm(r.Bool(), r.typ())
   354  	}
   355  	return types.NewUnion(terms)
   356  }
   357  
   358  func (r *reader) interfaceType() *types.Interface {
   359  	methods := make([]*types.Func, r.Len())
   360  	embeddeds := make([]types.Type, r.Len())
   361  	implicit := len(methods) == 0 && len(embeddeds) == 1 && r.Bool()
   362  
   363  	for i := range methods {
   364  		pos := r.pos()
   365  		pkg, name := r.selector()
   366  		mtyp := r.signature(nil, nil, nil)
   367  		methods[i] = types.NewFunc(pos, pkg, name, mtyp)
   368  	}
   369  
   370  	for i := range embeddeds {
   371  		embeddeds[i] = r.typ()
   372  	}
   373  
   374  	iface := types.NewInterfaceType(methods, embeddeds)
   375  	if implicit {
   376  		iface.MarkImplicit()
   377  	}
   378  
   379  	// We need to call iface.Complete(), but if there are any embedded
   380  	// defined types, then we may not have set their underlying
   381  	// interface type yet. So we need to defer calling Complete until
   382  	// after we've called SetUnderlying everywhere.
   383  	//
   384  	// TODO(mdempsky): After CL 424876 lands, it should be safe to call
   385  	// iface.Complete() immediately.
   386  	r.p.ifaces = append(r.p.ifaces, iface)
   387  
   388  	return iface
   389  }
   390  
   391  func (r *reader) signature(recv *types.Var, rtparams, tparams []*types.TypeParam) *types.Signature {
   392  	r.Sync(pkgbits.SyncSignature)
   393  
   394  	params := r.params()
   395  	results := r.params()
   396  	variadic := r.Bool()
   397  
   398  	return types.NewSignatureType(recv, rtparams, tparams, params, results, variadic)
   399  }
   400  
   401  func (r *reader) params() *types.Tuple {
   402  	r.Sync(pkgbits.SyncParams)
   403  
   404  	params := make([]*types.Var, r.Len())
   405  	for i := range params {
   406  		params[i] = r.param()
   407  	}
   408  
   409  	return types.NewTuple(params...)
   410  }
   411  
   412  func (r *reader) param() *types.Var {
   413  	r.Sync(pkgbits.SyncParam)
   414  
   415  	pos := r.pos()
   416  	pkg, name := r.localIdent()
   417  	typ := r.typ()
   418  
   419  	return types.NewParam(pos, pkg, name, typ)
   420  }
   421  
   422  // @@@ Objects
   423  
   424  func (r *reader) obj() (types.Object, []types.Type) {
   425  	r.Sync(pkgbits.SyncObject)
   426  
   427  	assert(!r.Bool())
   428  
   429  	pkg, name := r.p.objIdx(r.Reloc(pkgbits.RelocObj))
   430  	obj := pkgScope(pkg).Lookup(name)
   431  
   432  	targs := make([]types.Type, r.Len())
   433  	for i := range targs {
   434  		targs[i] = r.typ()
   435  	}
   436  
   437  	return obj, targs
   438  }
   439  
   440  func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
   441  
   442  	var objPkg *types.Package
   443  	var objName string
   444  	var tag pkgbits.CodeObj
   445  	{
   446  		rname := pr.tempReader(pkgbits.RelocName, idx, pkgbits.SyncObject1)
   447  
   448  		objPkg, objName = rname.qualifiedIdent()
   449  		assert(objName != "")
   450  
   451  		tag = pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj))
   452  		pr.retireReader(rname)
   453  	}
   454  
   455  	if tag == pkgbits.ObjStub {
   456  		assert(objPkg == nil || objPkg == types.Unsafe)
   457  		return objPkg, objName
   458  	}
   459  
   460  	// Ignore local types promoted to global scope (#55110).
   461  	if _, suffix := splitVargenSuffix(objName); suffix != "" {
   462  		return objPkg, objName
   463  	}
   464  
   465  	if objPkg.Scope().Lookup(objName) == nil {
   466  		dict := pr.objDictIdx(idx)
   467  
   468  		r := pr.newReader(pkgbits.RelocObj, idx, pkgbits.SyncObject1)
   469  		r.dict = dict
   470  
   471  		declare := func(obj types.Object) {
   472  			objPkg.Scope().Insert(obj)
   473  		}
   474  
   475  		switch tag {
   476  		default:
   477  			panic("weird")
   478  
   479  		case pkgbits.ObjAlias:
   480  			pos := r.pos()
   481  			typ := r.typ()
   482  			declare(types.NewTypeName(pos, objPkg, objName, typ))
   483  
   484  		case pkgbits.ObjConst:
   485  			pos := r.pos()
   486  			typ := r.typ()
   487  			val := r.Value()
   488  			declare(types.NewConst(pos, objPkg, objName, typ, val))
   489  
   490  		case pkgbits.ObjFunc:
   491  			pos := r.pos()
   492  			tparams := r.typeParamNames()
   493  			sig := r.signature(nil, nil, tparams)
   494  			declare(types.NewFunc(pos, objPkg, objName, sig))
   495  
   496  		case pkgbits.ObjType:
   497  			pos := r.pos()
   498  
   499  			obj := types.NewTypeName(pos, objPkg, objName, nil)
   500  			named := types.NewNamed(obj, nil, nil)
   501  			declare(obj)
   502  
   503  			named.SetTypeParams(r.typeParamNames())
   504  
   505  			underlying := r.typ().Underlying()
   506  
   507  			// If the underlying type is an interface, we need to
   508  			// duplicate its methods so we can replace the receiver
   509  			// parameter's type (#49906).
   510  			if iface, ok := underlying.(*types.Interface); ok && iface.NumExplicitMethods() != 0 {
   511  				methods := make([]*types.Func, iface.NumExplicitMethods())
   512  				for i := range methods {
   513  					fn := iface.ExplicitMethod(i)
   514  					sig := fn.Type().(*types.Signature)
   515  
   516  					recv := types.NewVar(fn.Pos(), fn.Pkg(), "", named)
   517  					methods[i] = types.NewFunc(fn.Pos(), fn.Pkg(), fn.Name(), types.NewSignature(recv, sig.Params(), sig.Results(), sig.Variadic()))
   518  				}
   519  
   520  				embeds := make([]types.Type, iface.NumEmbeddeds())
   521  				for i := range embeds {
   522  					embeds[i] = iface.EmbeddedType(i)
   523  				}
   524  
   525  				newIface := types.NewInterfaceType(methods, embeds)
   526  				r.p.ifaces = append(r.p.ifaces, newIface)
   527  				underlying = newIface
   528  			}
   529  
   530  			named.SetUnderlying(underlying)
   531  
   532  			for i, n := 0, r.Len(); i < n; i++ {
   533  				named.AddMethod(r.method())
   534  			}
   535  
   536  		case pkgbits.ObjVar:
   537  			pos := r.pos()
   538  			typ := r.typ()
   539  			declare(types.NewVar(pos, objPkg, objName, typ))
   540  		}
   541  	}
   542  
   543  	return objPkg, objName
   544  }
   545  
   546  func (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict {
   547  
   548  	var dict readerDict
   549  
   550  	{
   551  		r := pr.tempReader(pkgbits.RelocObjDict, idx, pkgbits.SyncObject1)
   552  		if implicits := r.Len(); implicits != 0 {
   553  			errorf("unexpected object with %v implicit type parameter(s)", implicits)
   554  		}
   555  
   556  		dict.bounds = make([]typeInfo, r.Len())
   557  		for i := range dict.bounds {
   558  			dict.bounds[i] = r.typInfo()
   559  		}
   560  
   561  		dict.derived = make([]derivedInfo, r.Len())
   562  		dict.derivedTypes = make([]types.Type, len(dict.derived))
   563  		for i := range dict.derived {
   564  			dict.derived[i] = derivedInfo{r.Reloc(pkgbits.RelocType), r.Bool()}
   565  		}
   566  
   567  		pr.retireReader(r)
   568  	}
   569  	// function references follow, but reader doesn't need those
   570  
   571  	return &dict
   572  }
   573  
   574  func (r *reader) typeParamNames() []*types.TypeParam {
   575  	r.Sync(pkgbits.SyncTypeParamNames)
   576  
   577  	// Note: This code assumes it only processes objects without
   578  	// implement type parameters. This is currently fine, because
   579  	// reader is only used to read in exported declarations, which are
   580  	// always package scoped.
   581  
   582  	if len(r.dict.bounds) == 0 {
   583  		return nil
   584  	}
   585  
   586  	// Careful: Type parameter lists may have cycles. To allow for this,
   587  	// we construct the type parameter list in two passes: first we
   588  	// create all the TypeNames and TypeParams, then we construct and
   589  	// set the bound type.
   590  
   591  	r.dict.tparams = make([]*types.TypeParam, len(r.dict.bounds))
   592  	for i := range r.dict.bounds {
   593  		pos := r.pos()
   594  		pkg, name := r.localIdent()
   595  
   596  		tname := types.NewTypeName(pos, pkg, name, nil)
   597  		r.dict.tparams[i] = types.NewTypeParam(tname, nil)
   598  	}
   599  
   600  	typs := make([]types.Type, len(r.dict.bounds))
   601  	for i, bound := range r.dict.bounds {
   602  		typs[i] = r.p.typIdx(bound, r.dict)
   603  	}
   604  
   605  	// TODO(mdempsky): This is subtle, elaborate further.
   606  	//
   607  	// We have to save tparams outside of the closure, because
   608  	// typeParamNames() can be called multiple times with the same
   609  	// dictionary instance.
   610  	//
   611  	// Also, this needs to happen later to make sure SetUnderlying has
   612  	// been called.
   613  	//
   614  	// TODO(mdempsky): Is it safe to have a single "later" slice or do
   615  	// we need to have multiple passes? See comments on CL 386002 and
   616  	// go.dev/issue/52104.
   617  	tparams := r.dict.tparams
   618  	r.p.later(func() {
   619  		for i, typ := range typs {
   620  			tparams[i].SetConstraint(typ)
   621  		}
   622  	})
   623  
   624  	return r.dict.tparams
   625  }
   626  
   627  func (r *reader) method() *types.Func {
   628  	r.Sync(pkgbits.SyncMethod)
   629  	pos := r.pos()
   630  	pkg, name := r.selector()
   631  
   632  	rparams := r.typeParamNames()
   633  	sig := r.signature(r.param(), rparams, nil)
   634  
   635  	_ = r.pos()	// TODO(mdempsky): Remove; this is a hacker for linker.go.
   636  	return types.NewFunc(pos, pkg, name, sig)
   637  }
   638  
   639  func (r *reader) qualifiedIdent() (*types.Package, string)	{ return r.ident(pkgbits.SyncSym) }
   640  func (r *reader) localIdent() (*types.Package, string)		{ return r.ident(pkgbits.SyncLocalIdent) }
   641  func (r *reader) selector() (*types.Package, string)		{ return r.ident(pkgbits.SyncSelector) }
   642  
   643  func (r *reader) ident(marker pkgbits.SyncMarker) (*types.Package, string) {
   644  	r.Sync(marker)
   645  	return r.pkg(), r.String()
   646  }
   647  
   648  // pkgScope returns pkg.Scope().
   649  // If pkg is nil, it returns types.Universe instead.
   650  //
   651  // TODO(mdempsky): Remove after x/tools can depend on Go 1.19.
   652  func pkgScope(pkg *types.Package) *types.Scope {
   653  	if pkg != nil {
   654  		return pkg.Scope()
   655  	}
   656  	return types.Universe
   657  }