...

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

     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	func dumpexport(bout *bio.Writer) {
    66		// The linker also looks for the $$ marker - use char after $$ to distinguish format.
    67		exportf(bout, "\n$$B\n") // indicate binary export format
    68		off := bout.Offset()
    69		iexport(bout.Writer)
    70		size := bout.Offset() - off
    71		exportf(bout, "\n$$\n")
    72	
    73		if Debug_export != 0 {
    74			fmt.Printf("export data size = %d bytes\n", size)
    75		}
    76	}
    77	
    78	func importsym(ipkg *types.Pkg, s *types.Sym, op Op) *Node {
    79		n := asNode(s.PkgDef())
    80		if n == nil {
    81			// iimport should have created a stub ONONAME
    82			// declaration for all imported symbols. The exception
    83			// is declarations for Runtimepkg, which are populated
    84			// by loadsys instead.
    85			if s.Pkg != Runtimepkg {
    86				Fatalf("missing ONONAME for %v\n", s)
    87			}
    88	
    89			n = dclname(s)
    90			s.SetPkgDef(asTypesNode(n))
    91			s.Importdef = ipkg
    92		}
    93		if n.Op != ONONAME && n.Op != op {
    94			redeclare(lineno, s, fmt.Sprintf("during import %q", ipkg.Path))
    95		}
    96		return n
    97	}
    98	
    99	// pkgtype returns the named type declared by symbol s.
   100	// If no such type has been declared yet, a forward declaration is returned.
   101	// ipkg is the package being imported
   102	func importtype(ipkg *types.Pkg, pos src.XPos, s *types.Sym) *types.Type {
   103		n := importsym(ipkg, s, OTYPE)
   104		if n.Op != OTYPE {
   105			t := types.New(TFORW)
   106			t.Sym = s
   107			t.Nod = asTypesNode(n)
   108	
   109			n.Op = OTYPE
   110			n.Pos = pos
   111			n.Type = t
   112			n.SetClass(PEXTERN)
   113		}
   114	
   115		t := n.Type
   116		if t == nil {
   117			Fatalf("importtype %v", s)
   118		}
   119		return t
   120	}
   121	
   122	// importobj declares symbol s as an imported object representable by op.
   123	// ipkg is the package being imported
   124	func importobj(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op Op, ctxt Class, t *types.Type) *Node {
   125		n := importsym(ipkg, s, op)
   126		if n.Op != ONONAME {
   127			if n.Op == op && (n.Class() != ctxt || !types.Identical(n.Type, t)) {
   128				redeclare(lineno, s, fmt.Sprintf("during import %q", ipkg.Path))
   129			}
   130			return nil
   131		}
   132	
   133		n.Op = op
   134		n.Pos = pos
   135		n.SetClass(ctxt)
   136		if ctxt == PFUNC {
   137			n.Sym.SetFunc(true)
   138		}
   139		n.Type = t
   140		return n
   141	}
   142	
   143	// importconst declares symbol s as an imported constant with type t and value val.
   144	// ipkg is the package being imported
   145	func importconst(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type, val Val) {
   146		n := importobj(ipkg, pos, s, OLITERAL, PEXTERN, t)
   147		if n == nil { // TODO: Check that value matches.
   148			return
   149		}
   150	
   151		n.SetVal(val)
   152	
   153		if Debug['E'] != 0 {
   154			fmt.Printf("import const %v %L = %v\n", s, t, val)
   155		}
   156	}
   157	
   158	// importfunc declares symbol s as an imported function with type t.
   159	// ipkg is the package being imported
   160	func importfunc(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) {
   161		n := importobj(ipkg, pos, s, ONAME, PFUNC, t)
   162		if n == nil {
   163			return
   164		}
   165	
   166		n.Func = new(Func)
   167		t.SetNname(asTypesNode(n))
   168	
   169		if Debug['E'] != 0 {
   170			fmt.Printf("import func %v%S\n", s, t)
   171		}
   172	}
   173	
   174	// importvar declares symbol s as an imported variable with type t.
   175	// ipkg is the package being imported
   176	func importvar(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) {
   177		n := importobj(ipkg, pos, s, ONAME, PEXTERN, t)
   178		if n == nil {
   179			return
   180		}
   181	
   182		if Debug['E'] != 0 {
   183			fmt.Printf("import var %v %L\n", s, t)
   184		}
   185	}
   186	
   187	// importalias declares symbol s as an imported type alias with type t.
   188	// ipkg is the package being imported
   189	func importalias(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) {
   190		n := importobj(ipkg, pos, s, OTYPE, PEXTERN, t)
   191		if n == nil {
   192			return
   193		}
   194	
   195		if Debug['E'] != 0 {
   196			fmt.Printf("import type %v = %L\n", s, t)
   197		}
   198	}
   199	
   200	func dumpasmhdr() {
   201		b, err := bio.Create(asmhdr)
   202		if err != nil {
   203			Fatalf("%v", err)
   204		}
   205		fmt.Fprintf(b, "// generated by compile -asmhdr from package %s\n\n", localpkg.Name)
   206		for _, n := range asmlist {
   207			if n.Sym.IsBlank() {
   208				continue
   209			}
   210			switch n.Op {
   211			case OLITERAL:
   212				t := n.Val().Ctype()
   213				if t == CTFLT || t == CTCPLX {
   214					break
   215				}
   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	}
   234	

View as plain text