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 }