// Copyright 2009 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" "cmd/internal/bio" "cmd/internal/src" "fmt" ) var ( Debug_export int // if set, print debugging information about export data ) func exportf(bout *bio.Writer, format string, args ...interface{}) { fmt.Fprintf(bout, format, args...) if Debug_export != 0 { fmt.Printf(format, args...) } } var asmlist []*Node // exportsym marks n for export (or reexport). func exportsym(n *Node) { if n.Sym.OnExportList() { return } n.Sym.SetOnExportList(true) if Debug['E'] != 0 { fmt.Printf("export symbol %v\n", n.Sym) } exportlist = append(exportlist, n) } func initname(s string) bool { return s == "init" } func autoexport(n *Node, ctxt Class) { if n.Sym.Pkg != localpkg { return } if (ctxt != PEXTERN && ctxt != PFUNC) || dclcontext != PEXTERN { return } if n.Type != nil && n.Type.IsKind(TFUNC) && n.IsMethod() { return } if types.IsExported(n.Sym.Name) || initname(n.Sym.Name) { exportsym(n) } if asmhdr != "" && !n.Sym.Asm() { n.Sym.SetAsm(true) asmlist = append(asmlist, n) } } func dumpexport(bout *bio.Writer) { // The linker also looks for the $$ marker - use char after $$ to distinguish format. exportf(bout, "\n$$B\n") // indicate binary export format off := bout.Offset() iexport(bout.Writer) size := bout.Offset() - off exportf(bout, "\n$$\n") if Debug_export != 0 { fmt.Printf("BenchmarkExportSize:%s 1 %d bytes\n", myimportpath, size) } } func importsym(ipkg *types.Pkg, s *types.Sym, op Op) *Node { n := asNode(s.PkgDef()) if n == nil { // iimport should have created a stub ONONAME // declaration for all imported symbols. The exception // is declarations for Runtimepkg, which are populated // by loadsys instead. if s.Pkg != Runtimepkg { Fatalf("missing ONONAME for %v\n", s) } n = dclname(s) s.SetPkgDef(asTypesNode(n)) s.Importdef = ipkg } if n.Op != ONONAME && n.Op != op { redeclare(lineno, s, fmt.Sprintf("during import %q", ipkg.Path)) } return n } // pkgtype returns the named type declared by symbol s. // If no such type has been declared yet, a forward declaration is returned. // ipkg is the package being imported func importtype(ipkg *types.Pkg, pos src.XPos, s *types.Sym) *types.Type { n := importsym(ipkg, s, OTYPE) if n.Op != OTYPE { t := types.New(TFORW) t.Sym = s t.Nod = asTypesNode(n) n.Op = OTYPE n.Pos = pos n.Type = t n.SetClass(PEXTERN) } t := n.Type if t == nil { Fatalf("importtype %v", s) } return t } // importobj declares symbol s as an imported object representable by op. // ipkg is the package being imported func importobj(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op Op, ctxt Class, t *types.Type) *Node { n := importsym(ipkg, s, op) if n.Op != ONONAME { if n.Op == op && (n.Class() != ctxt || !types.Identical(n.Type, t)) { redeclare(lineno, s, fmt.Sprintf("during import %q", ipkg.Path)) } return nil } n.Op = op n.Pos = pos n.SetClass(ctxt) if ctxt == PFUNC { n.Sym.SetFunc(true) } n.Type = t return n } // importconst declares symbol s as an imported constant with type t and value val. // ipkg is the package being imported func importconst(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type, val Val) { n := importobj(ipkg, pos, s, OLITERAL, PEXTERN, t) if n == nil { // TODO: Check that value matches. return } n.SetVal(val) if Debug['E'] != 0 { fmt.Printf("import const %v %L = %v\n", s, t, val) } } // importfunc declares symbol s as an imported function with type t. // ipkg is the package being imported func importfunc(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) { n := importobj(ipkg, pos, s, ONAME, PFUNC, t) if n == nil { return } n.Func = new(Func) t.SetNname(asTypesNode(n)) if Debug['E'] != 0 { fmt.Printf("import func %v%S\n", s, t) } } // importvar declares symbol s as an imported variable with type t. // ipkg is the package being imported func importvar(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) { n := importobj(ipkg, pos, s, ONAME, PEXTERN, t) if n == nil { return } if Debug['E'] != 0 { fmt.Printf("import var %v %L\n", s, t) } } // importalias declares symbol s as an imported type alias with type t. // ipkg is the package being imported func importalias(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) { n := importobj(ipkg, pos, s, OTYPE, PEXTERN, t) if n == nil { return } if Debug['E'] != 0 { fmt.Printf("import type %v = %L\n", s, t) } } func dumpasmhdr() { b, err := bio.Create(asmhdr) if err != nil { Fatalf("%v", err) } fmt.Fprintf(b, "// generated by compile -asmhdr from package %s\n\n", localpkg.Name) for _, n := range asmlist { if n.Sym.IsBlank() { continue } switch n.Op { case OLITERAL: t := n.Val().Ctype() if t == CTFLT || t == CTCPLX { break } fmt.Fprintf(b, "#define const_%s %#v\n", n.Sym.Name, n.Val()) case OTYPE: t := n.Type if !t.IsStruct() || t.StructType().Map != nil || t.IsFuncArgStruct() { break } fmt.Fprintf(b, "#define %s__size %d\n", n.Sym.Name, int(t.Width)) for _, f := range t.Fields().Slice() { if !f.Sym.IsBlank() { fmt.Fprintf(b, "#define %s_%s %d\n", n.Sym.Name, f.Sym.Name, int(f.Offset)) } } } } b.Close() }