blob: 66ae8816c344245064121cc680b9dd435f39605b [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 }
Russ Cox3c3019a2015-05-27 00:44:05 -040067 if n.Name.Param != nil && n.Name.Param.Ntype != nil && n.Name.Param.Ntype.Op == OTFUNC && n.Name.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 Cox81d58102015-05-27 00:47:05 -0400219 fmt.Fprintf(bout, "\tconst %v %v = %v\n", Sconv(s, obj.FmtSharp), Tconv(t, obj.FmtSharp), Vconv(n.Val(), obj.FmtSharp))
Russ Cox8c195bd2015-02-13 14:40:36 -0500220 } else {
Russ Cox81d58102015-05-27 00:47:05 -0400221 fmt.Fprintf(bout, "\tconst %v = %v\n", Sconv(s, obj.FmtSharp), Vconv(n.Val(), obj.FmtSharp))
Russ Cox8c195bd2015-02-13 14:40:36 -0500222 }
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
Russ Cox0f6da892015-04-19 23:56:30 -0400364 if buildid != "" {
365 fmt.Fprintf(bout, "build id %q\n", buildid)
366 }
Russ Cox8c195bd2015-02-13 14:40:36 -0500367 fmt.Fprintf(bout, "\n$$\npackage %s", localpkg.Name)
368 if safemode != 0 {
369 fmt.Fprintf(bout, " safe")
370 }
371 fmt.Fprintf(bout, "\n")
372
Russ Coxd0b59de2015-03-02 16:21:15 -0500373 for _, p := range pkgs {
374 if p.Direct != 0 {
375 dumppkg(p)
Russ Cox8c195bd2015-02-13 14:40:36 -0500376 }
377 }
378
Russ Cox382b44e2015-02-23 16:07:24 -0500379 for l := exportlist; l != nil; l = l.Next {
Russ Cox8c195bd2015-02-13 14:40:36 -0500380 lineno = l.N.Lineno
381 dumpsym(l.N.Sym)
382 }
383
384 fmt.Fprintf(bout, "\n$$\n")
385 lineno = lno
386}
387
388/*
389 * import
390 */
391
392/*
393 * return the sym for ss, which should match lexical
394 */
395func importsym(s *Sym, op int) *Sym {
Russ Cox8c195bd2015-02-13 14:40:36 -0500396 if s.Def != nil && int(s.Def.Op) != op {
Russ Coxbed1f902015-03-02 16:03:26 -0500397 pkgstr := fmt.Sprintf("during import %q", importpkg.Path)
Russ Cox8c195bd2015-02-13 14:40:36 -0500398 redeclare(s, pkgstr)
399 }
400
401 // mark the symbol so it is not reexported
402 if s.Def == nil {
Russ Coxdc7b54b2015-02-17 22:13:49 -0500403 if exportname(s.Name) || initname(s.Name) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500404 s.Flags |= SymExport
405 } else {
406 s.Flags |= SymPackage // package scope
407 }
408 }
409
410 return s
411}
412
413/*
414 * return the type pkg.name, forward declaring if needed
415 */
416func pkgtype(s *Sym) *Type {
Russ Cox8c195bd2015-02-13 14:40:36 -0500417 importsym(s, OTYPE)
418 if s.Def == nil || s.Def.Op != OTYPE {
Russ Cox382b44e2015-02-23 16:07:24 -0500419 t := typ(TFORW)
Russ Cox8c195bd2015-02-13 14:40:36 -0500420 t.Sym = s
421 s.Def = typenod(t)
Russ Cox140ef3c2015-05-26 23:08:39 -0400422 s.Def.Name = new(Name)
Russ Cox8c195bd2015-02-13 14:40:36 -0500423 }
424
425 if s.Def.Type == nil {
Russ Cox17228f42015-04-17 12:03:22 -0400426 Yyerror("pkgtype %v", s)
Russ Cox8c195bd2015-02-13 14:40:36 -0500427 }
428 return s.Def.Type
429}
430
Russ Coxd0b59de2015-03-02 16:21:15 -0500431var numImport = make(map[string]int)
432
Russ Coxbed1f902015-03-02 16:03:26 -0500433func importimport(s *Sym, path string) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500434 // Informational: record package name
435 // associated with import path, for use in
436 // human-readable messages.
Russ Cox8c195bd2015-02-13 14:40:36 -0500437
Russ Coxbed1f902015-03-02 16:03:26 -0500438 if isbadimport(path) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500439 errorexit()
440 }
Russ Coxbed1f902015-03-02 16:03:26 -0500441 p := mkpkg(path)
Russ Cox8c195bd2015-02-13 14:40:36 -0500442 if p.Name == "" {
443 p.Name = s.Name
Russ Coxd0b59de2015-03-02 16:21:15 -0500444 numImport[s.Name]++
Russ Cox8c195bd2015-02-13 14:40:36 -0500445 } else if p.Name != s.Name {
Russ Coxbed1f902015-03-02 16:03:26 -0500446 Yyerror("conflicting names %s and %s for package %q", p.Name, s.Name, p.Path)
Russ Cox8c195bd2015-02-13 14:40:36 -0500447 }
448
Russ Coxbed1f902015-03-02 16:03:26 -0500449 if incannedimport == 0 && myimportpath != "" && path == myimportpath {
450 Yyerror("import %q: package depends on %q (import cycle)", importpkg.Path, path)
Russ Cox8c195bd2015-02-13 14:40:36 -0500451 errorexit()
452 }
453}
454
455func importconst(s *Sym, t *Type, n *Node) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500456 importsym(s, OLITERAL)
457 Convlit(&n, t)
458
459 if s.Def != nil { // TODO: check if already the same.
460 return
461 }
462
463 if n.Op != OLITERAL {
464 Yyerror("expression must be a constant")
465 return
466 }
467
468 if n.Sym != nil {
Russ Cox382b44e2015-02-23 16:07:24 -0500469 n1 := Nod(OXXX, nil, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -0500470 *n1 = *n
471 n = n1
472 }
473
474 n.Orig = newname(s)
475 n.Sym = s
476 declare(n, PEXTERN)
477
478 if Debug['E'] != 0 {
Russ Cox17228f42015-04-17 12:03:22 -0400479 fmt.Printf("import const %v\n", s)
Russ Cox8c195bd2015-02-13 14:40:36 -0500480 }
481}
482
483func importvar(s *Sym, t *Type) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500484 importsym(s, ONAME)
485 if s.Def != nil && s.Def.Op == ONAME {
486 if Eqtype(t, s.Def.Type) {
487 return
488 }
Russ Cox17228f42015-04-17 12:03:22 -0400489 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 -0500490 }
491
Russ Cox382b44e2015-02-23 16:07:24 -0500492 n := newname(s)
Russ Cox8c195bd2015-02-13 14:40:36 -0500493 s.Importdef = importpkg
494 n.Type = t
495 declare(n, PEXTERN)
496
497 if Debug['E'] != 0 {
Russ Cox17228f42015-04-17 12:03:22 -0400498 fmt.Printf("import var %v %v\n", s, Tconv(t, obj.FmtLong))
Russ Cox8c195bd2015-02-13 14:40:36 -0500499 }
500}
501
502func importtype(pt *Type, t *Type) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500503 // override declaration in unsafe.go for Pointer.
504 // there is no way in Go code to define unsafe.Pointer
505 // so we have to supply it.
506 if incannedimport != 0 && importpkg.Name == "unsafe" && pt.Nod.Sym.Name == "Pointer" {
507 t = Types[TUNSAFEPTR]
508 }
509
510 if pt.Etype == TFORW {
Russ Cox382b44e2015-02-23 16:07:24 -0500511 n := pt.Nod
Russ Cox8c195bd2015-02-13 14:40:36 -0500512 copytype(pt.Nod, t)
513 pt.Nod = n // unzero nod
514 pt.Sym.Importdef = importpkg
515 pt.Sym.Lastlineno = int32(parserline())
516 declare(n, PEXTERN)
517 checkwidth(pt)
518 } else if !Eqtype(pt.Orig, t) {
Russ Cox17228f42015-04-17 12:03:22 -0400519 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 -0500520 }
521
522 if Debug['E'] != 0 {
Russ Cox17228f42015-04-17 12:03:22 -0400523 fmt.Printf("import type %v %v\n", pt, Tconv(t, obj.FmtLong))
Russ Cox8c195bd2015-02-13 14:40:36 -0500524 }
525}
526
527func dumpasmhdr() {
528 var b *obj.Biobuf
Russ Cox8c195bd2015-02-13 14:40:36 -0500529
530 b, err := obj.Bopenw(asmhdr)
531 if err != nil {
532 Fatal("%v", err)
533 }
534 fmt.Fprintf(b, "// generated by %cg -asmhdr from package %s\n\n", Thearch.Thechar, localpkg.Name)
Russ Cox382b44e2015-02-23 16:07:24 -0500535 var n *Node
536 var t *Type
537 for l := asmlist; l != nil; l = l.Next {
Russ Cox8c195bd2015-02-13 14:40:36 -0500538 n = l.N
539 if isblanksym(n.Sym) {
540 continue
541 }
542 switch n.Op {
543 case OLITERAL:
Russ Cox81d58102015-05-27 00:47:05 -0400544 fmt.Fprintf(b, "#define const_%s %v\n", n.Sym.Name, Vconv(n.Val(), obj.FmtSharp))
Russ Cox8c195bd2015-02-13 14:40:36 -0500545
546 case OTYPE:
547 t = n.Type
548 if t.Etype != TSTRUCT || t.Map != nil || t.Funarg != 0 {
549 break
550 }
551 fmt.Fprintf(b, "#define %s__size %d\n", t.Sym.Name, int(t.Width))
552 for t = t.Type; t != nil; t = t.Down {
553 if !isblanksym(t.Sym) {
554 fmt.Fprintf(b, "#define %s_%s %d\n", n.Sym.Name, t.Sym.Name, int(t.Width))
555 }
556 }
557 }
558 }
559
560 obj.Bterm(b)
561}