github.com/hikaru7719/go@v0.0.0-20181025140707-c8b2ac68906a/src/cmd/compile/internal/gc/export.go (about)

     1  // Copyright 2009 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  	"cmd/internal/bio"
    10  	"cmd/internal/src"
    11  	"fmt"
    12  )
    13  
    14  var (
    15  	Debug_export int // if set, print debugging information about export data
    16  )
    17  
    18  func exportf(bout *bio.Writer, format string, args ...interface{}) {
    19  	fmt.Fprintf(bout, format, args...)
    20  	if Debug_export != 0 {
    21  		fmt.Printf(format, args...)
    22  	}
    23  }
    24  
    25  var asmlist []*Node
    26  
    27  // exportsym marks n for export (or reexport).
    28  func exportsym(n *Node) {
    29  	if n.Sym.OnExportList() {
    30  		return
    31  	}
    32  	n.Sym.SetOnExportList(true)
    33  
    34  	if Debug['E'] != 0 {
    35  		fmt.Printf("export symbol %v\n", n.Sym)
    36  	}
    37  
    38  	exportlist = append(exportlist, n)
    39  }
    40  
    41  func initname(s string) bool {
    42  	return s == "init"
    43  }
    44  
    45  func autoexport(n *Node, ctxt Class) {
    46  	if n.Sym.Pkg != localpkg {
    47  		return
    48  	}
    49  	if (ctxt != PEXTERN && ctxt != PFUNC) || dclcontext != PEXTERN {
    50  		return
    51  	}
    52  	if n.Type != nil && n.Type.IsKind(TFUNC) && n.IsMethod() {
    53  		return
    54  	}
    55  
    56  	if types.IsExported(n.Sym.Name) || initname(n.Sym.Name) {
    57  		exportsym(n)
    58  	}
    59  	if asmhdr != "" && !n.Sym.Asm() {
    60  		n.Sym.SetAsm(true)
    61  		asmlist = append(asmlist, n)
    62  	}
    63  }
    64  
    65  // methodbyname sorts types by symbol name.
    66  type methodbyname []*types.Field
    67  
    68  func (x methodbyname) Len() int           { return len(x) }
    69  func (x methodbyname) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
    70  func (x methodbyname) Less(i, j int) bool { return x[i].Sym.Name < x[j].Sym.Name }
    71  
    72  func dumpexport(bout *bio.Writer) {
    73  	// The linker also looks for the $$ marker - use char after $$ to distinguish format.
    74  	exportf(bout, "\n$$B\n") // indicate binary export format
    75  	off := bout.Offset()
    76  	iexport(bout.Writer)
    77  	size := bout.Offset() - off
    78  	exportf(bout, "\n$$\n")
    79  
    80  	if Debug_export != 0 {
    81  		fmt.Printf("export data size = %d bytes\n", size)
    82  	}
    83  }
    84  
    85  func importsym(ipkg *types.Pkg, s *types.Sym, op Op) *Node {
    86  	n := asNode(s.PkgDef())
    87  	if n == nil {
    88  		// iimport should have created a stub ONONAME
    89  		// declaration for all imported symbols. The exception
    90  		// is declarations for Runtimepkg, which are populated
    91  		// by loadsys instead.
    92  		if s.Pkg != Runtimepkg {
    93  			Fatalf("missing ONONAME for %v\n", s)
    94  		}
    95  
    96  		n = dclname(s)
    97  		s.SetPkgDef(asTypesNode(n))
    98  		s.Importdef = ipkg
    99  	}
   100  	if n.Op != ONONAME && n.Op != op {
   101  		redeclare(lineno, s, fmt.Sprintf("during import %q", ipkg.Path))
   102  	}
   103  	return n
   104  }
   105  
   106  // pkgtype returns the named type declared by symbol s.
   107  // If no such type has been declared yet, a forward declaration is returned.
   108  // ipkg is the package being imported
   109  func importtype(ipkg *types.Pkg, pos src.XPos, s *types.Sym) *types.Type {
   110  	n := importsym(ipkg, s, OTYPE)
   111  	if n.Op != OTYPE {
   112  		t := types.New(TFORW)
   113  		t.Sym = s
   114  		t.Nod = asTypesNode(n)
   115  
   116  		n.Op = OTYPE
   117  		n.Pos = pos
   118  		n.Type = t
   119  		n.SetClass(PEXTERN)
   120  	}
   121  
   122  	t := n.Type
   123  	if t == nil {
   124  		Fatalf("importtype %v", s)
   125  	}
   126  	return t
   127  }
   128  
   129  // importobj declares symbol s as an imported object representable by op.
   130  // ipkg is the package being imported
   131  func importobj(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op Op, ctxt Class, t *types.Type) *Node {
   132  	n := importsym(ipkg, s, op)
   133  	if n.Op != ONONAME {
   134  		if n.Op == op && (n.Class() != ctxt || !types.Identical(n.Type, t)) {
   135  			redeclare(lineno, s, fmt.Sprintf("during import %q", ipkg.Path))
   136  		}
   137  		return nil
   138  	}
   139  
   140  	n.Op = op
   141  	n.Pos = pos
   142  	n.SetClass(ctxt)
   143  	n.Type = t
   144  	return n
   145  }
   146  
   147  // importconst declares symbol s as an imported constant with type t and value val.
   148  // ipkg is the package being imported
   149  func importconst(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type, val Val) {
   150  	n := importobj(ipkg, pos, s, OLITERAL, PEXTERN, t)
   151  	if n == nil { // TODO: Check that value matches.
   152  		return
   153  	}
   154  
   155  	n.SetVal(val)
   156  
   157  	if Debug['E'] != 0 {
   158  		fmt.Printf("import const %v %L = %v\n", s, t, val)
   159  	}
   160  }
   161  
   162  // importfunc declares symbol s as an imported function with type t.
   163  // ipkg is the package being imported
   164  func importfunc(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) {
   165  	n := importobj(ipkg, pos, s, ONAME, PFUNC, t)
   166  	if n == nil {
   167  		return
   168  	}
   169  
   170  	n.Func = new(Func)
   171  	t.SetNname(asTypesNode(n))
   172  
   173  	if Debug['E'] != 0 {
   174  		fmt.Printf("import func %v%S\n", s, t)
   175  	}
   176  }
   177  
   178  // importvar declares symbol s as an imported variable with type t.
   179  // ipkg is the package being imported
   180  func importvar(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) {
   181  	n := importobj(ipkg, pos, s, ONAME, PEXTERN, t)
   182  	if n == nil {
   183  		return
   184  	}
   185  
   186  	if Debug['E'] != 0 {
   187  		fmt.Printf("import var %v %L\n", s, t)
   188  	}
   189  }
   190  
   191  // importalias declares symbol s as an imported type alias with type t.
   192  // ipkg is the package being imported
   193  func importalias(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) {
   194  	n := importobj(ipkg, pos, s, OTYPE, PEXTERN, t)
   195  	if n == nil {
   196  		return
   197  	}
   198  
   199  	if Debug['E'] != 0 {
   200  		fmt.Printf("import type %v = %L\n", s, t)
   201  	}
   202  }
   203  
   204  func dumpasmhdr() {
   205  	b, err := bio.Create(asmhdr)
   206  	if err != nil {
   207  		Fatalf("%v", err)
   208  	}
   209  	fmt.Fprintf(b, "// generated by compile -asmhdr from package %s\n\n", localpkg.Name)
   210  	for _, n := range asmlist {
   211  		if n.Sym.IsBlank() {
   212  			continue
   213  		}
   214  		switch n.Op {
   215  		case OLITERAL:
   216  			fmt.Fprintf(b, "#define const_%s %#v\n", n.Sym.Name, n.Val())
   217  
   218  		case OTYPE:
   219  			t := n.Type
   220  			if !t.IsStruct() || t.StructType().Map != nil || t.IsFuncArgStruct() {
   221  				break
   222  			}
   223  			fmt.Fprintf(b, "#define %s__size %d\n", n.Sym.Name, int(t.Width))
   224  			for _, f := range t.Fields().Slice() {
   225  				if !f.Sym.IsBlank() {
   226  					fmt.Fprintf(b, "#define %s_%s %d\n", n.Sym.Name, f.Sym.Name, int(f.Offset))
   227  				}
   228  			}
   229  		}
   230  	}
   231  
   232  	b.Close()
   233  }