// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package gc import ( "cmd/compile/internal/types" ) type exporter struct { marked map[*types.Type]bool // types already seen by markType } // markType recursively visits types reachable from t to identify // functions whose inline bodies may be needed. func (p *exporter) markType(t *types.Type) { if p.marked[t] { return } p.marked[t] = true // If this is a named type, mark all of its associated // methods. Skip interface types because t.Methods contains // only their unexpanded method set (i.e., exclusive of // interface embeddings), and the switch statement below // handles their full method set. if t.Sym != nil && t.Etype != TINTER { for _, m := range t.Methods().Slice() { if types.IsExported(m.Sym.Name) { p.markType(m.Type) } } } // Recursively mark any types that can be produced given a // value of type t: dereferencing a pointer; indexing or // iterating over an array, slice, or map; receiving from a // channel; accessing a struct field or interface method; or // calling a function. // // Notably, we don't mark function parameter types, because // the user already needs some way to construct values of // those types. switch t.Etype { case TPTR, TARRAY, TSLICE: p.markType(t.Elem()) case TCHAN: if t.ChanDir().CanRecv() { p.markType(t.Elem()) } case TMAP: p.markType(t.Key()) p.markType(t.Elem()) case TSTRUCT: for _, f := range t.FieldSlice() { if types.IsExported(f.Sym.Name) || f.Embedded != 0 { p.markType(f.Type) } } case TFUNC: // If t is the type of a function or method, then // t.Nname() is its ONAME. Mark its inline body and // any recursively called functions for export. inlFlood(asNode(t.Nname())) for _, f := range t.Results().FieldSlice() { p.markType(f.Type) } case TINTER: for _, f := range t.FieldSlice() { if types.IsExported(f.Sym.Name) { p.markType(f.Type) } } } } // deltaNewFile is a magic line delta offset indicating a new file. // We use -64 because it is rare; see issue 20080 and CL 41619. // -64 is the smallest int that fits in a single byte as a varint. const deltaNewFile = -64 // ---------------------------------------------------------------------------- // Export format // Tags. Must be < 0. const ( // Objects packageTag = -(iota + 1) constTag typeTag varTag funcTag endTag // Types namedTag arrayTag sliceTag dddTag structTag pointerTag signatureTag interfaceTag mapTag chanTag // Values falseTag trueTag int64Tag floatTag fractionTag // not used by gc complexTag stringTag nilTag unknownTag // not used by gc (only appears in packages with errors) // Type aliases aliasTag ) // untype returns the "pseudo" untyped type for a Ctype (import/export use only). // (we can't use a pre-initialized array because we must be sure all types are // set up) func untype(ctype Ctype) *types.Type { switch ctype { case CTINT: return types.Idealint case CTRUNE: return types.Idealrune case CTFLT: return types.Idealfloat case CTCPLX: return types.Idealcomplex case CTSTR: return types.Idealstring case CTBOOL: return types.Idealbool case CTNIL: return types.Types[TNIL] } Fatalf("exporter: unknown Ctype") return nil } var predecl []*types.Type // initialized lazily func predeclared() []*types.Type { if predecl == nil { // initialize lazily to be sure that all // elements have been initialized before predecl = []*types.Type{ // basic types types.Types[TBOOL], types.Types[TINT], types.Types[TINT8], types.Types[TINT16], types.Types[TINT32], types.Types[TINT64], types.Types[TUINT], types.Types[TUINT8], types.Types[TUINT16], types.Types[TUINT32], types.Types[TUINT64], types.Types[TUINTPTR], types.Types[TFLOAT32], types.Types[TFLOAT64], types.Types[TCOMPLEX64], types.Types[TCOMPLEX128], types.Types[TSTRING], // basic type aliases types.Bytetype, types.Runetype, // error types.Errortype, // untyped types untype(CTBOOL), untype(CTINT), untype(CTRUNE), untype(CTFLT), untype(CTCPLX), untype(CTSTR), untype(CTNIL), // package unsafe types.Types[TUNSAFEPTR], // invalid type (package contains errors) types.Types[Txxx], // any type, for builtin export data types.Types[TANY], } } return predecl }