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

View as plain text