| // 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) |
| } |
| } |
| } |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // 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 |
| ) |
| |
| 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 |
| types.UntypedBool, |
| types.UntypedInt, |
| types.UntypedRune, |
| types.UntypedFloat, |
| types.UntypedComplex, |
| types.UntypedString, |
| types.Types[TNIL], |
| |
| // package unsafe |
| types.Types[TUNSAFEPTR], |
| |
| // invalid type (package contains errors) |
| types.Types[Txxx], |
| |
| // any type, for builtin export data |
| types.Types[TANY], |
| } |
| } |
| return predecl |
| } |