...

Source file src/pkg/cmd/compile/internal/gc/bexport.go

     1	// Copyright 2015 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 gc
     6	
     7	import (
     8		"cmd/compile/internal/types"
     9	)
    10	
    11	type exporter struct {
    12		marked map[*types.Type]bool // types already seen by markType
    13	}
    14	
    15	// markType recursively visits types reachable from t to identify
    16	// functions whose inline bodies may be needed.
    17	func (p *exporter) markType(t *types.Type) {
    18		if p.marked[t] {
    19			return
    20		}
    21		p.marked[t] = true
    22	
    23		// If this is a named type, mark all of its associated
    24		// methods. Skip interface types because t.Methods contains
    25		// only their unexpanded method set (i.e., exclusive of
    26		// interface embeddings), and the switch statement below
    27		// handles their full method set.
    28		if t.Sym != nil && t.Etype != TINTER {
    29			for _, m := range t.Methods().Slice() {
    30				if types.IsExported(m.Sym.Name) {
    31					p.markType(m.Type)
    32				}
    33			}
    34		}
    35	
    36		// Recursively mark any types that can be produced given a
    37		// value of type t: dereferencing a pointer; indexing or
    38		// iterating over an array, slice, or map; receiving from a
    39		// channel; accessing a struct field or interface method; or
    40		// calling a function.
    41		//
    42		// Notably, we don't mark function parameter types, because
    43		// the user already needs some way to construct values of
    44		// those types.
    45		switch t.Etype {
    46		case TPTR, TARRAY, TSLICE, TCHAN:
    47			// TODO(mdempsky): Skip marking element type for
    48			// send-only channels?
    49			p.markType(t.Elem())
    50	
    51		case TMAP:
    52			p.markType(t.Key())
    53			p.markType(t.Elem())
    54	
    55		case TSTRUCT:
    56			for _, f := range t.FieldSlice() {
    57				if types.IsExported(f.Sym.Name) || f.Embedded != 0 {
    58					p.markType(f.Type)
    59				}
    60			}
    61	
    62		case TFUNC:
    63			// If t is the type of a function or method, then
    64			// t.Nname() is its ONAME. Mark its inline body and
    65			// any recursively called functions for export.
    66			inlFlood(asNode(t.Nname()))
    67	
    68			for _, f := range t.Results().FieldSlice() {
    69				p.markType(f.Type)
    70			}
    71	
    72		case TINTER:
    73			for _, f := range t.FieldSlice() {
    74				if types.IsExported(f.Sym.Name) {
    75					p.markType(f.Type)
    76				}
    77			}
    78		}
    79	}
    80	
    81	// deltaNewFile is a magic line delta offset indicating a new file.
    82	// We use -64 because it is rare; see issue 20080 and CL 41619.
    83	// -64 is the smallest int that fits in a single byte as a varint.
    84	const deltaNewFile = -64
    85	
    86	// ----------------------------------------------------------------------------
    87	// Export format
    88	
    89	// Tags. Must be < 0.
    90	const (
    91		// Objects
    92		packageTag = -(iota + 1)
    93		constTag
    94		typeTag
    95		varTag
    96		funcTag
    97		endTag
    98	
    99		// Types
   100		namedTag
   101		arrayTag
   102		sliceTag
   103		dddTag
   104		structTag
   105		pointerTag
   106		signatureTag
   107		interfaceTag
   108		mapTag
   109		chanTag
   110	
   111		// Values
   112		falseTag
   113		trueTag
   114		int64Tag
   115		floatTag
   116		fractionTag // not used by gc
   117		complexTag
   118		stringTag
   119		nilTag
   120		unknownTag // not used by gc (only appears in packages with errors)
   121	
   122		// Type aliases
   123		aliasTag
   124	)
   125	
   126	// untype returns the "pseudo" untyped type for a Ctype (import/export use only).
   127	// (we can't use an pre-initialized array because we must be sure all types are
   128	// set up)
   129	func untype(ctype Ctype) *types.Type {
   130		switch ctype {
   131		case CTINT:
   132			return types.Idealint
   133		case CTRUNE:
   134			return types.Idealrune
   135		case CTFLT:
   136			return types.Idealfloat
   137		case CTCPLX:
   138			return types.Idealcomplex
   139		case CTSTR:
   140			return types.Idealstring
   141		case CTBOOL:
   142			return types.Idealbool
   143		case CTNIL:
   144			return types.Types[TNIL]
   145		}
   146		Fatalf("exporter: unknown Ctype")
   147		return nil
   148	}
   149	
   150	var predecl []*types.Type // initialized lazily
   151	
   152	func predeclared() []*types.Type {
   153		if predecl == nil {
   154			// initialize lazily to be sure that all
   155			// elements have been initialized before
   156			predecl = []*types.Type{
   157				// basic types
   158				types.Types[TBOOL],
   159				types.Types[TINT],
   160				types.Types[TINT8],
   161				types.Types[TINT16],
   162				types.Types[TINT32],
   163				types.Types[TINT64],
   164				types.Types[TUINT],
   165				types.Types[TUINT8],
   166				types.Types[TUINT16],
   167				types.Types[TUINT32],
   168				types.Types[TUINT64],
   169				types.Types[TUINTPTR],
   170				types.Types[TFLOAT32],
   171				types.Types[TFLOAT64],
   172				types.Types[TCOMPLEX64],
   173				types.Types[TCOMPLEX128],
   174				types.Types[TSTRING],
   175	
   176				// basic type aliases
   177				types.Bytetype,
   178				types.Runetype,
   179	
   180				// error
   181				types.Errortype,
   182	
   183				// untyped types
   184				untype(CTBOOL),
   185				untype(CTINT),
   186				untype(CTRUNE),
   187				untype(CTFLT),
   188				untype(CTCPLX),
   189				untype(CTSTR),
   190				untype(CTNIL),
   191	
   192				// package unsafe
   193				types.Types[TUNSAFEPTR],
   194	
   195				// invalid type (package contains errors)
   196				types.Types[Txxx],
   197	
   198				// any type, for builtin export data
   199				types.Types[TANY],
   200			}
   201		}
   202		return predecl
   203	}
   204	

View as plain text