blob: 623d61ad74456929e543881ce6b9713f7e210c60 [file] [log] [blame]
Russ Cox8c195bd2015-02-13 14:40:36 -05001// 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
5package gc
6
7import (
8 "cmd/internal/obj"
9 "fmt"
10 "sort"
11 "unicode"
12 "unicode/utf8"
13)
14
15var asmlist *NodeList
16
17// Mark n's symbol as exported
18func exportsym(n *Node) {
19 if n == nil || n.Sym == nil {
20 return
21 }
22 if n.Sym.Flags&(SymExport|SymPackage) != 0 {
23 if n.Sym.Flags&SymPackage != 0 {
Russ Cox17228f42015-04-17 12:03:22 -040024 Yyerror("export/package mismatch: %v", n.Sym)
Russ Cox8c195bd2015-02-13 14:40:36 -050025 }
26 return
27 }
28
29 n.Sym.Flags |= SymExport
30
31 if Debug['E'] != 0 {
Russ Cox17228f42015-04-17 12:03:22 -040032 fmt.Printf("export symbol %v\n", n.Sym)
Russ Cox8c195bd2015-02-13 14:40:36 -050033 }
34 exportlist = list(exportlist, n)
35}
36
37func exportname(s string) bool {
38 if s[0] < utf8.RuneSelf {
39 return 'A' <= s[0] && s[0] <= 'Z'
40 }
41 r, _ := utf8.DecodeRuneInString(s)
42 return unicode.IsUpper(r)
43}
44
Russ Coxdc7b54b2015-02-17 22:13:49 -050045func initname(s string) bool {
46 return s == "init"
Russ Cox8c195bd2015-02-13 14:40:36 -050047}
48
49// exportedsym reports whether a symbol will be visible
50// to files that import our package.
Russ Coxdc7b54b2015-02-17 22:13:49 -050051func exportedsym(sym *Sym) bool {
Russ Cox8c195bd2015-02-13 14:40:36 -050052 // Builtins are visible everywhere.
53 if sym.Pkg == builtinpkg || sym.Origpkg == builtinpkg {
Russ Coxdc7b54b2015-02-17 22:13:49 -050054 return true
Russ Cox8c195bd2015-02-13 14:40:36 -050055 }
56
Russ Coxdc7b54b2015-02-17 22:13:49 -050057 return sym.Pkg == localpkg && exportname(sym.Name)
Russ Cox8c195bd2015-02-13 14:40:36 -050058}
59
Josh Bleecher Snyder102b8062015-03-27 12:00:07 -070060func autoexport(n *Node, ctxt uint8) {
Russ Cox8c195bd2015-02-13 14:40:36 -050061 if n == nil || n.Sym == nil {
62 return
63 }
64 if (ctxt != PEXTERN && ctxt != PFUNC) || dclcontext != PEXTERN {
65 return
66 }
Josh Bleecher Snyderbd8bb672015-05-19 15:25:35 -070067 if n.Param != nil && n.Param.Ntype != nil && n.Param.Ntype.Op == OTFUNC && n.Param.Ntype.Left != nil { // method
Russ Cox8c195bd2015-02-13 14:40:36 -050068 return
69 }
70
71 // -A is for cmd/gc/mkbuiltin script, so export everything
Russ Coxdc7b54b2015-02-17 22:13:49 -050072 if Debug['A'] != 0 || exportname(n.Sym.Name) || initname(n.Sym.Name) {
Russ Cox8c195bd2015-02-13 14:40:36 -050073 exportsym(n)
74 }
Russ Coxdc7b54b2015-02-17 22:13:49 -050075 if asmhdr != "" && n.Sym.Pkg == localpkg && n.Sym.Flags&SymAsm == 0 {
Russ Cox8c195bd2015-02-13 14:40:36 -050076 n.Sym.Flags |= SymAsm
77 asmlist = list(asmlist, n)
78 }
79}
80
81func dumppkg(p *Pkg) {
Russ Cox8c195bd2015-02-13 14:40:36 -050082 if p == nil || p == localpkg || p.Exported != 0 || p == builtinpkg {
83 return
84 }
85 p.Exported = 1
Russ Cox382b44e2015-02-23 16:07:24 -050086 suffix := ""
Russ Coxdc7b54b2015-02-17 22:13:49 -050087 if p.Direct == 0 {
Russ Cox8c195bd2015-02-13 14:40:36 -050088 suffix = " // indirect"
89 }
Russ Coxbed1f902015-03-02 16:03:26 -050090 fmt.Fprintf(bout, "\timport %s %q%s\n", p.Name, p.Path, suffix)
Russ Cox8c195bd2015-02-13 14:40:36 -050091}
92
93// Look for anything we need for the inline body
94func reexportdeplist(ll *NodeList) {
95 for ; ll != nil; ll = ll.Next {
96 reexportdep(ll.N)
97 }
98}
99
100func reexportdep(n *Node) {
Russ Coxdc7b54b2015-02-17 22:13:49 -0500101 if n == nil {
Russ Cox8c195bd2015-02-13 14:40:36 -0500102 return
103 }
104
105 //print("reexportdep %+hN\n", n);
106 switch n.Op {
107 case ONAME:
108 switch n.Class &^ PHEAP {
109 // methods will be printed along with their type
110 // nodes for T.Method expressions
111 case PFUNC:
112 if n.Left != nil && n.Left.Op == OTYPE {
113 break
114 }
115
116 // nodes for method calls.
Russ Coxdc7b54b2015-02-17 22:13:49 -0500117 if n.Type == nil || n.Type.Thistuple > 0 {
Russ Cox8c195bd2015-02-13 14:40:36 -0500118 break
119 }
120 fallthrough
121
Russ Cox8c195bd2015-02-13 14:40:36 -0500122 case PEXTERN:
Russ Coxdc7b54b2015-02-17 22:13:49 -0500123 if n.Sym != nil && !exportedsym(n.Sym) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500124 if Debug['E'] != 0 {
Russ Cox17228f42015-04-17 12:03:22 -0400125 fmt.Printf("reexport name %v\n", n.Sym)
Russ Cox8c195bd2015-02-13 14:40:36 -0500126 }
127 exportlist = list(exportlist, n)
128 }
129 }
130
131 // Local variables in the bodies need their type.
132 case ODCL:
Russ Cox382b44e2015-02-23 16:07:24 -0500133 t := n.Left.Type
Russ Cox8c195bd2015-02-13 14:40:36 -0500134
135 if t != Types[t.Etype] && t != idealbool && t != idealstring {
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +0000136 if Isptr[t.Etype] {
Russ Cox8c195bd2015-02-13 14:40:36 -0500137 t = t.Type
138 }
Russ Coxdc7b54b2015-02-17 22:13:49 -0500139 if t != nil && t.Sym != nil && t.Sym.Def != nil && !exportedsym(t.Sym) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500140 if Debug['E'] != 0 {
Russ Cox17228f42015-04-17 12:03:22 -0400141 fmt.Printf("reexport type %v from declaration\n", t.Sym)
Russ Cox8c195bd2015-02-13 14:40:36 -0500142 }
143 exportlist = list(exportlist, t.Sym.Def)
144 }
145 }
146
147 case OLITERAL:
Russ Cox382b44e2015-02-23 16:07:24 -0500148 t := n.Type
Russ Cox8c195bd2015-02-13 14:40:36 -0500149 if t != Types[n.Type.Etype] && t != idealbool && t != idealstring {
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +0000150 if Isptr[t.Etype] {
Russ Cox8c195bd2015-02-13 14:40:36 -0500151 t = t.Type
152 }
Russ Coxdc7b54b2015-02-17 22:13:49 -0500153 if t != nil && t.Sym != nil && t.Sym.Def != nil && !exportedsym(t.Sym) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500154 if Debug['E'] != 0 {
Russ Cox17228f42015-04-17 12:03:22 -0400155 fmt.Printf("reexport literal type %v\n", t.Sym)
Russ Cox8c195bd2015-02-13 14:40:36 -0500156 }
157 exportlist = list(exportlist, t.Sym.Def)
158 }
159 }
160 fallthrough
161
Russ Cox8c195bd2015-02-13 14:40:36 -0500162 case OTYPE:
Russ Coxdc7b54b2015-02-17 22:13:49 -0500163 if n.Sym != nil && !exportedsym(n.Sym) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500164 if Debug['E'] != 0 {
Russ Cox17228f42015-04-17 12:03:22 -0400165 fmt.Printf("reexport literal/type %v\n", n.Sym)
Russ Cox8c195bd2015-02-13 14:40:36 -0500166 }
167 exportlist = list(exportlist, n)
168 }
169
170 // for operations that need a type when rendered, put the type on the export list.
171 case OCONV,
172 OCONVIFACE,
173 OCONVNOP,
174 ORUNESTR,
175 OARRAYBYTESTR,
176 OARRAYRUNESTR,
177 OSTRARRAYBYTE,
178 OSTRARRAYRUNE,
179 ODOTTYPE,
180 ODOTTYPE2,
181 OSTRUCTLIT,
182 OARRAYLIT,
183 OPTRLIT,
184 OMAKEMAP,
185 OMAKESLICE,
186 OMAKECHAN:
Russ Cox382b44e2015-02-23 16:07:24 -0500187 t := n.Type
Russ Cox8c195bd2015-02-13 14:40:36 -0500188
Russ Coxdc7b54b2015-02-17 22:13:49 -0500189 if t.Sym == nil && t.Type != nil {
Russ Cox8c195bd2015-02-13 14:40:36 -0500190 t = t.Type
191 }
Russ Coxdc7b54b2015-02-17 22:13:49 -0500192 if t != nil && t.Sym != nil && t.Sym.Def != nil && !exportedsym(t.Sym) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500193 if Debug['E'] != 0 {
Russ Cox17228f42015-04-17 12:03:22 -0400194 fmt.Printf("reexport type for expression %v\n", t.Sym)
Russ Cox8c195bd2015-02-13 14:40:36 -0500195 }
196 exportlist = list(exportlist, t.Sym.Def)
197 }
198 }
199
200 reexportdep(n.Left)
201 reexportdep(n.Right)
202 reexportdeplist(n.List)
203 reexportdeplist(n.Rlist)
204 reexportdeplist(n.Ninit)
Russ Cox8c195bd2015-02-13 14:40:36 -0500205 reexportdeplist(n.Nbody)
Russ Cox8c195bd2015-02-13 14:40:36 -0500206}
207
208func dumpexportconst(s *Sym) {
Russ Cox382b44e2015-02-23 16:07:24 -0500209 n := s.Def
Russ Cox8c195bd2015-02-13 14:40:36 -0500210 typecheck(&n, Erv)
211 if n == nil || n.Op != OLITERAL {
Russ Cox17228f42015-04-17 12:03:22 -0400212 Fatal("dumpexportconst: oconst nil: %v", s)
Russ Cox8c195bd2015-02-13 14:40:36 -0500213 }
214
Russ Cox382b44e2015-02-23 16:07:24 -0500215 t := n.Type // may or may not be specified
Russ Cox8c195bd2015-02-13 14:40:36 -0500216 dumpexporttype(t)
217
Russ Coxdc7b54b2015-02-17 22:13:49 -0500218 if t != nil && !isideal(t) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500219 fmt.Fprintf(bout, "\tconst %v %v = %v\n", Sconv(s, obj.FmtSharp), Tconv(t, obj.FmtSharp), Vconv(&n.Val, obj.FmtSharp))
220 } else {
221 fmt.Fprintf(bout, "\tconst %v = %v\n", Sconv(s, obj.FmtSharp), Vconv(&n.Val, obj.FmtSharp))
222 }
223}
224
225func dumpexportvar(s *Sym) {
Russ Cox382b44e2015-02-23 16:07:24 -0500226 n := s.Def
Russ Cox8c195bd2015-02-13 14:40:36 -0500227 typecheck(&n, Erv|Ecall)
228 if n == nil || n.Type == nil {
Russ Cox17228f42015-04-17 12:03:22 -0400229 Yyerror("variable exported but not defined: %v", s)
Russ Cox8c195bd2015-02-13 14:40:36 -0500230 return
231 }
232
Russ Cox382b44e2015-02-23 16:07:24 -0500233 t := n.Type
Russ Cox8c195bd2015-02-13 14:40:36 -0500234 dumpexporttype(t)
235
236 if t.Etype == TFUNC && n.Class == PFUNC {
Josh Bleecher Snyder3ed9e4c2015-03-25 19:33:01 -0700237 if n.Func != nil && n.Func.Inl != nil {
Russ Cox8c195bd2015-02-13 14:40:36 -0500238 // when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet.
239 // currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package
240 if Debug['l'] < 2 {
241 typecheckinl(n)
242 }
243
244 // NOTE: The space after %#S here is necessary for ld's export data parser.
Josh Bleecher Snyder3ed9e4c2015-03-25 19:33:01 -0700245 fmt.Fprintf(bout, "\tfunc %v %v { %v }\n", Sconv(s, obj.FmtSharp), Tconv(t, obj.FmtShort|obj.FmtSharp), Hconv(n.Func.Inl, obj.FmtSharp))
Russ Cox8c195bd2015-02-13 14:40:36 -0500246
Josh Bleecher Snyder3ed9e4c2015-03-25 19:33:01 -0700247 reexportdeplist(n.Func.Inl)
Russ Cox8c195bd2015-02-13 14:40:36 -0500248 } else {
249 fmt.Fprintf(bout, "\tfunc %v %v\n", Sconv(s, obj.FmtSharp), Tconv(t, obj.FmtShort|obj.FmtSharp))
250 }
251 } else {
252 fmt.Fprintf(bout, "\tvar %v %v\n", Sconv(s, obj.FmtSharp), Tconv(t, obj.FmtSharp))
253 }
254}
255
256type methodbyname []*Type
257
258func (x methodbyname) Len() int {
259 return len(x)
260}
261
262func (x methodbyname) Swap(i, j int) {
263 x[i], x[j] = x[j], x[i]
264}
265
266func (x methodbyname) Less(i, j int) bool {
Russ Cox382b44e2015-02-23 16:07:24 -0500267 a := x[i]
268 b := x[j]
Russ Cox8c195bd2015-02-13 14:40:36 -0500269 return stringsCompare(a.Sym.Name, b.Sym.Name) < 0
270}
271
272func dumpexporttype(t *Type) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500273 if t == nil {
274 return
275 }
276 if t.Printed != 0 || t == Types[t.Etype] || t == bytetype || t == runetype || t == errortype {
277 return
278 }
279 t.Printed = 1
280
281 if t.Sym != nil && t.Etype != TFIELD {
282 dumppkg(t.Sym.Pkg)
283 }
284
285 dumpexporttype(t.Type)
286 dumpexporttype(t.Down)
287
288 if t.Sym == nil || t.Etype == TFIELD {
289 return
290 }
291
Russ Cox382b44e2015-02-23 16:07:24 -0500292 n := 0
293 for f := t.Method; f != nil; f = f.Down {
Russ Cox8c195bd2015-02-13 14:40:36 -0500294 dumpexporttype(f)
295 n++
296 }
297
Russ Cox382b44e2015-02-23 16:07:24 -0500298 m := make([]*Type, n)
299 i := 0
300 for f := t.Method; f != nil; f = f.Down {
Russ Cox8c195bd2015-02-13 14:40:36 -0500301 m[i] = f
302 i++
303 }
304 sort.Sort(methodbyname(m[:n]))
305
306 fmt.Fprintf(bout, "\ttype %v %v\n", Sconv(t.Sym, obj.FmtSharp), Tconv(t, obj.FmtSharp|obj.FmtLong))
Russ Cox382b44e2015-02-23 16:07:24 -0500307 var f *Type
308 for i := 0; i < n; i++ {
Russ Cox8c195bd2015-02-13 14:40:36 -0500309 f = m[i]
Russ Coxdc7b54b2015-02-17 22:13:49 -0500310 if f.Nointerface {
Russ Cox8c195bd2015-02-13 14:40:36 -0500311 fmt.Fprintf(bout, "\t//go:nointerface\n")
312 }
Josh Bleecher Snyder3ed9e4c2015-03-25 19:33:01 -0700313 if f.Type.Nname != nil && f.Type.Nname.Func.Inl != nil { // nname was set by caninl
Russ Cox8c195bd2015-02-13 14:40:36 -0500314
315 // when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet.
316 // currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package
317 if Debug['l'] < 2 {
318 typecheckinl(f.Type.Nname)
319 }
Josh Bleecher Snyder3ed9e4c2015-03-25 19:33:01 -0700320 fmt.Fprintf(bout, "\tfunc (%v) %v %v { %v }\n", Tconv(getthisx(f.Type).Type, obj.FmtSharp), Sconv(f.Sym, obj.FmtShort|obj.FmtByte|obj.FmtSharp), Tconv(f.Type, obj.FmtShort|obj.FmtSharp), Hconv(f.Type.Nname.Func.Inl, obj.FmtSharp))
321 reexportdeplist(f.Type.Nname.Func.Inl)
Russ Cox8c195bd2015-02-13 14:40:36 -0500322 } else {
323 fmt.Fprintf(bout, "\tfunc (%v) %v %v\n", Tconv(getthisx(f.Type).Type, obj.FmtSharp), Sconv(f.Sym, obj.FmtShort|obj.FmtByte|obj.FmtSharp), Tconv(f.Type, obj.FmtShort|obj.FmtSharp))
324 }
325 }
326}
327
328func dumpsym(s *Sym) {
329 if s.Flags&SymExported != 0 {
330 return
331 }
332 s.Flags |= SymExported
333
334 if s.Def == nil {
Russ Cox17228f42015-04-17 12:03:22 -0400335 Yyerror("unknown export symbol: %v", s)
Russ Cox8c195bd2015-02-13 14:40:36 -0500336 return
337 }
338
339 // print("dumpsym %O %+S\n", s->def->op, s);
340 dumppkg(s.Pkg)
341
342 switch s.Def.Op {
343 default:
Russ Cox17228f42015-04-17 12:03:22 -0400344 Yyerror("unexpected export symbol: %v %v", Oconv(int(s.Def.Op), 0), s)
Russ Cox8c195bd2015-02-13 14:40:36 -0500345
346 case OLITERAL:
347 dumpexportconst(s)
348
349 case OTYPE:
350 if s.Def.Type.Etype == TFORW {
Russ Cox17228f42015-04-17 12:03:22 -0400351 Yyerror("export of incomplete type %v", s)
Russ Cox8c195bd2015-02-13 14:40:36 -0500352 } else {
353 dumpexporttype(s.Def.Type)
354 }
355
356 case ONAME:
357 dumpexportvar(s)
358 }
359}
360
361func dumpexport() {
Russ Cox382b44e2015-02-23 16:07:24 -0500362 lno := lineno
Russ Cox8c195bd2015-02-13 14:40:36 -0500363
364 fmt.Fprintf(bout, "\n$$\npackage %s", localpkg.Name)
365 if safemode != 0 {
366 fmt.Fprintf(bout, " safe")
367 }
368 fmt.Fprintf(bout, "\n")
369
Russ Coxd0b59de2015-03-02 16:21:15 -0500370 for _, p := range pkgs {
371 if p.Direct != 0 {
372 dumppkg(p)
Russ Cox8c195bd2015-02-13 14:40:36 -0500373 }
374 }
375
Russ Cox382b44e2015-02-23 16:07:24 -0500376 for l := exportlist; l != nil; l = l.Next {
Russ Cox8c195bd2015-02-13 14:40:36 -0500377 lineno = l.N.Lineno
378 dumpsym(l.N.Sym)
379 }
380
381 fmt.Fprintf(bout, "\n$$\n")
382 lineno = lno
383}
384
385/*
386 * import
387 */
388
389/*
390 * return the sym for ss, which should match lexical
391 */
392func importsym(s *Sym, op int) *Sym {
Russ Cox8c195bd2015-02-13 14:40:36 -0500393 if s.Def != nil && int(s.Def.Op) != op {
Russ Coxbed1f902015-03-02 16:03:26 -0500394 pkgstr := fmt.Sprintf("during import %q", importpkg.Path)
Russ Cox8c195bd2015-02-13 14:40:36 -0500395 redeclare(s, pkgstr)
396 }
397
398 // mark the symbol so it is not reexported
399 if s.Def == nil {
Russ Coxdc7b54b2015-02-17 22:13:49 -0500400 if exportname(s.Name) || initname(s.Name) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500401 s.Flags |= SymExport
402 } else {
403 s.Flags |= SymPackage // package scope
404 }
405 }
406
407 return s
408}
409
410/*
411 * return the type pkg.name, forward declaring if needed
412 */
413func pkgtype(s *Sym) *Type {
Russ Cox8c195bd2015-02-13 14:40:36 -0500414 importsym(s, OTYPE)
415 if s.Def == nil || s.Def.Op != OTYPE {
Russ Cox382b44e2015-02-23 16:07:24 -0500416 t := typ(TFORW)
Russ Cox8c195bd2015-02-13 14:40:36 -0500417 t.Sym = s
418 s.Def = typenod(t)
419 }
420
421 if s.Def.Type == nil {
Russ Cox17228f42015-04-17 12:03:22 -0400422 Yyerror("pkgtype %v", s)
Russ Cox8c195bd2015-02-13 14:40:36 -0500423 }
424 return s.Def.Type
425}
426
Russ Coxd0b59de2015-03-02 16:21:15 -0500427var numImport = make(map[string]int)
428
Russ Coxbed1f902015-03-02 16:03:26 -0500429func importimport(s *Sym, path string) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500430 // Informational: record package name
431 // associated with import path, for use in
432 // human-readable messages.
Russ Cox8c195bd2015-02-13 14:40:36 -0500433
Russ Coxbed1f902015-03-02 16:03:26 -0500434 if isbadimport(path) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500435 errorexit()
436 }
Russ Coxbed1f902015-03-02 16:03:26 -0500437 p := mkpkg(path)
Russ Cox8c195bd2015-02-13 14:40:36 -0500438 if p.Name == "" {
439 p.Name = s.Name
Russ Coxd0b59de2015-03-02 16:21:15 -0500440 numImport[s.Name]++
Russ Cox8c195bd2015-02-13 14:40:36 -0500441 } else if p.Name != s.Name {
Russ Coxbed1f902015-03-02 16:03:26 -0500442 Yyerror("conflicting names %s and %s for package %q", p.Name, s.Name, p.Path)
Russ Cox8c195bd2015-02-13 14:40:36 -0500443 }
444
Russ Coxbed1f902015-03-02 16:03:26 -0500445 if incannedimport == 0 && myimportpath != "" && path == myimportpath {
446 Yyerror("import %q: package depends on %q (import cycle)", importpkg.Path, path)
Russ Cox8c195bd2015-02-13 14:40:36 -0500447 errorexit()
448 }
449}
450
451func importconst(s *Sym, t *Type, n *Node) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500452 importsym(s, OLITERAL)
453 Convlit(&n, t)
454
455 if s.Def != nil { // TODO: check if already the same.
456 return
457 }
458
459 if n.Op != OLITERAL {
460 Yyerror("expression must be a constant")
461 return
462 }
463
464 if n.Sym != nil {
Russ Cox382b44e2015-02-23 16:07:24 -0500465 n1 := Nod(OXXX, nil, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -0500466 *n1 = *n
467 n = n1
468 }
469
470 n.Orig = newname(s)
471 n.Sym = s
472 declare(n, PEXTERN)
473
474 if Debug['E'] != 0 {
Russ Cox17228f42015-04-17 12:03:22 -0400475 fmt.Printf("import const %v\n", s)
Russ Cox8c195bd2015-02-13 14:40:36 -0500476 }
477}
478
479func importvar(s *Sym, t *Type) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500480 importsym(s, ONAME)
481 if s.Def != nil && s.Def.Op == ONAME {
482 if Eqtype(t, s.Def.Type) {
483 return
484 }
Russ Cox17228f42015-04-17 12:03:22 -0400485 Yyerror("inconsistent definition for var %v during import\n\t%v (in %q)\n\t%v (in %q)", s, s.Def.Type, s.Importdef.Path, t, importpkg.Path)
Russ Cox8c195bd2015-02-13 14:40:36 -0500486 }
487
Russ Cox382b44e2015-02-23 16:07:24 -0500488 n := newname(s)
Russ Cox8c195bd2015-02-13 14:40:36 -0500489 s.Importdef = importpkg
490 n.Type = t
491 declare(n, PEXTERN)
492
493 if Debug['E'] != 0 {
Russ Cox17228f42015-04-17 12:03:22 -0400494 fmt.Printf("import var %v %v\n", s, Tconv(t, obj.FmtLong))
Russ Cox8c195bd2015-02-13 14:40:36 -0500495 }
496}
497
498func importtype(pt *Type, t *Type) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500499 // override declaration in unsafe.go for Pointer.
500 // there is no way in Go code to define unsafe.Pointer
501 // so we have to supply it.
502 if incannedimport != 0 && importpkg.Name == "unsafe" && pt.Nod.Sym.Name == "Pointer" {
503 t = Types[TUNSAFEPTR]
504 }
505
506 if pt.Etype == TFORW {
Russ Cox382b44e2015-02-23 16:07:24 -0500507 n := pt.Nod
Russ Cox8c195bd2015-02-13 14:40:36 -0500508 copytype(pt.Nod, t)
509 pt.Nod = n // unzero nod
510 pt.Sym.Importdef = importpkg
511 pt.Sym.Lastlineno = int32(parserline())
512 declare(n, PEXTERN)
513 checkwidth(pt)
514 } else if !Eqtype(pt.Orig, t) {
Russ Cox17228f42015-04-17 12:03:22 -0400515 Yyerror("inconsistent definition for type %v during import\n\t%v (in %q)\n\t%v (in %q)", pt.Sym, Tconv(pt, obj.FmtLong), pt.Sym.Importdef.Path, Tconv(t, obj.FmtLong), importpkg.Path)
Russ Cox8c195bd2015-02-13 14:40:36 -0500516 }
517
518 if Debug['E'] != 0 {
Russ Cox17228f42015-04-17 12:03:22 -0400519 fmt.Printf("import type %v %v\n", pt, Tconv(t, obj.FmtLong))
Russ Cox8c195bd2015-02-13 14:40:36 -0500520 }
521}
522
523func dumpasmhdr() {
524 var b *obj.Biobuf
Russ Cox8c195bd2015-02-13 14:40:36 -0500525
526 b, err := obj.Bopenw(asmhdr)
527 if err != nil {
528 Fatal("%v", err)
529 }
530 fmt.Fprintf(b, "// generated by %cg -asmhdr from package %s\n\n", Thearch.Thechar, localpkg.Name)
Russ Cox382b44e2015-02-23 16:07:24 -0500531 var n *Node
532 var t *Type
533 for l := asmlist; l != nil; l = l.Next {
Russ Cox8c195bd2015-02-13 14:40:36 -0500534 n = l.N
535 if isblanksym(n.Sym) {
536 continue
537 }
538 switch n.Op {
539 case OLITERAL:
540 fmt.Fprintf(b, "#define const_%s %v\n", n.Sym.Name, Vconv(&n.Val, obj.FmtSharp))
541
542 case OTYPE:
543 t = n.Type
544 if t.Etype != TSTRUCT || t.Map != nil || t.Funarg != 0 {
545 break
546 }
547 fmt.Fprintf(b, "#define %s__size %d\n", t.Sym.Name, int(t.Width))
548 for t = t.Type; t != nil; t = t.Down {
549 if !isblanksym(t.Sym) {
550 fmt.Fprintf(b, "#define %s_%s %d\n", n.Sym.Name, t.Sym.Name, int(t.Width))
551 }
552 }
553 }
554 }
555
556 obj.Bterm(b)
557}