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 #include "go.h"
6
7 /*
8 * runtime interface and reflection data structures
9 */
10
11 static NodeList* signatlist;
12 static Sym* dtypesym(Type*);
13 static Sym* weaktypesym(Type*);
14
15 static int
16 sigcmp(Sig *a, Sig *b)
17 {
18 int i;
19
20 i = strcmp(a->name, b->name);
21 if(i != 0)
22 return i;
23 if(a->pkg == b->pkg)
24 return 0;
25 if(a->pkg == nil)
26 return -1;
27 if(b->pkg == nil)
28 return +1;
29 return strcmp(a->pkg->path->s, b->pkg->path->s);
30 }
31
32 static Sig*
33 lsort(Sig *l, int(*f)(Sig*, Sig*))
34 {
35 Sig *l1, *l2, *le;
36
37 if(l == 0 || l->link == 0)
38 return l;
39
40 l1 = l;
41 l2 = l;
42 for(;;) {
43 l2 = l2->link;
44 if(l2 == 0)
45 break;
46 l2 = l2->link;
47 if(l2 == 0)
48 break;
49 l1 = l1->link;
50 }
51
52 l2 = l1->link;
53 l1->link = 0;
54 l1 = lsort(l, f);
55 l2 = lsort(l2, f);
56
57 /* set up lead element */
58 if((*f)(l1, l2) < 0) {
59 l = l1;
60 l1 = l1->link;
61 } else {
62 l = l2;
63 l2 = l2->link;
64 }
65 le = l;
66
67 for(;;) {
68 if(l1 == 0) {
69 while(l2) {
70 le->link = l2;
71 le = l2;
72 l2 = l2->link;
73 }
74 le->link = 0;
75 break;
76 }
77 if(l2 == 0) {
78 while(l1) {
79 le->link = l1;
80 le = l1;
81 l1 = l1->link;
82 }
83 break;
84 }
85 if((*f)(l1, l2) < 0) {
86 le->link = l1;
87 le = l1;
88 l1 = l1->link;
89 } else {
90 le->link = l2;
91 le = l2;
92 l2 = l2->link;
93 }
94 }
95 le->link = 0;
96 return l;
97 }
98
99 /*
100 * f is method type, with receiver.
101 * return function type, receiver as first argument (or not).
102 */
103 Type*
104 methodfunc(Type *f, Type *receiver)
105 {
106 NodeList *in, *out;
107 Node *d;
108 Type *t;
109
110 in = nil;
111 if(receiver) {
112 d = nod(ODCLFIELD, N, N);
113 d->type = receiver;
114 in = list(in, d);
115 }
116 for(t=getinargx(f)->type; t; t=t->down) {
117 d = nod(ODCLFIELD, N, N);
118 d->type = t->type;
119 d->isddd = t->isddd;
120 in = list(in, d);
121 }
122
123 out = nil;
124 for(t=getoutargx(f)->type; t; t=t->down) {
125 d = nod(ODCLFIELD, N, N);
126 d->type = t->type;
127 out = list(out, d);
128 }
129
130 return functype(N, in, out);
131 }
132
133 /*
134 * return methods of non-interface type t, sorted by name.
135 * generates stub functions as needed.
136 */
137 static Sig*
138 methods(Type *t)
139 {
140 Type *f, *mt, *it, *this;
141 Sig *a, *b;
142 Sym *method;
143 Prog *oldlist;
144
145 // named method type
146 mt = methtype(t);
147 if(mt == T)
148 return nil;
149 expandmeth(mt->sym, mt);
150
151 // type stored in interface word
152 it = t;
153 if(it->width > widthptr)
154 it = ptrto(t);
155
156 // make list of methods for t,
157 // generating code if necessary.
158 a = nil;
159 oldlist = nil;
160 for(f=mt->xmethod; f; f=f->down) {
161 if(f->type->etype != TFUNC)
162 continue;
163 if(f->etype != TFIELD)
164 fatal("methods: not field");
165 method = f->sym;
166 if(method == nil)
167 continue;
168
169 // get receiver type for this particular method.
170 // if pointer receiver but non-pointer t and
171 // this is not an embedded pointer inside a struct,
172 // method does not apply.
173 this = getthisx(f->type)->type->type;
174 if(isptr[this->etype] && this->type == t)
175 continue;
176 if(isptr[this->etype] && !isptr[t->etype]
177 && f->embedded != 2 && !isifacemethod(f->type))
178 continue;
179
180 b = mal(sizeof(*b));
181 b->link = a;
182 a = b;
183
184 a->name = method->name;
185 if(!exportname(method->name)) {
186 if(method->pkg == nil)
187 fatal("methods: missing package");
188 a->pkg = method->pkg;
189 }
190 a->isym = methodsym(method, it, 1);
191 a->tsym = methodsym(method, t, 0);
192 a->type = methodfunc(f->type, t);
193 a->mtype = methodfunc(f->type, nil);
194
195 if(!(a->isym->flags & SymSiggen)) {
196 a->isym->flags |= SymSiggen;
197 if(!eqtype(this, it) || this->width < types[tptr]->width) {
198 if(oldlist == nil)
199 oldlist = pc;
200 // Is okay to call genwrapper here always,
201 // but we can generate more efficient code
202 // using genembedtramp if all that is necessary
203 // is a pointer adjustment and a JMP.
204 if(isptr[it->etype] && isptr[this->etype]
205 && f->embedded && !isifacemethod(f->type))
206 genembedtramp(it, f, a->isym, 1);
207 else
208 genwrapper(it, f, a->isym, 1);
209 }
210 }
211
212 if(!(a->tsym->flags & SymSiggen)) {
213 a->tsym->flags |= SymSiggen;
214 if(!eqtype(this, t)) {
215 if(oldlist == nil)
216 oldlist = pc;
217 if(isptr[t->etype] && isptr[this->etype]
218 && f->embedded && !isifacemethod(f->type))
219 genembedtramp(t, f, a->tsym, 0);
220 else
221 genwrapper(t, f, a->tsym, 0);
222 }
223 }
224 }
225
226 // restore data output
227 if(oldlist) {
228 // old list ended with AEND; change to ANOP
229 // so that the trampolines that follow can be found.
230 nopout(oldlist);
231
232 // start new data list
233 newplist();
234 }
235
236 return lsort(a, sigcmp);
237 }
238
239 /*
240 * return methods of interface type t, sorted by name.
241 */
242 static Sig*
243 imethods(Type *t)
244 {
245 Sig *a, *all, *last;
246 Type *f;
247 Sym *method, *isym;
248 Prog *oldlist;
249
250 all = nil;
251 last = nil;
252 oldlist = nil;
253 for(f=t->type; f; f=f->down) {
254 if(f->etype != TFIELD)
255 fatal("imethods: not field");
256 if(f->type->etype != TFUNC || f->sym == nil)
257 continue;
258 method = f->sym;
259 a = mal(sizeof(*a));
260 a->name = method->name;
261 if(!exportname(method->name)) {
262 if(method->pkg == nil)
263 fatal("imethods: missing package");
264 a->pkg = method->pkg;
265 }
266 a->mtype = f->type;
267 a->offset = 0;
268 a->type = methodfunc(f->type, nil);
269
270 if(last && sigcmp(last, a) >= 0)
271 fatal("sigcmp vs sortinter %s %s", last->name, a->name);
272 if(last == nil)
273 all = a;
274 else
275 last->link = a;
276 last = a;
277
278 // Compiler can only refer to wrappers for
279 // named interface types.
280 if(t->sym == S)
281 continue;
282
283 // NOTE(rsc): Perhaps an oversight that
284 // IfaceType.Method is not in the reflect data.
285 // Generate the method body, so that compiled
286 // code can refer to it.
287 isym = methodsym(method, t, 0);
288 if(!(isym->flags & SymSiggen)) {
289 isym->flags |= SymSiggen;
290 if(oldlist == nil)
291 oldlist = pc;
292 genwrapper(t, f, isym, 0);
293 }
294 }
295
296 if(oldlist) {
297 // old list ended with AEND; change to ANOP
298 // so that the trampolines that follow can be found.
299 nopout(oldlist);
300
301 // start new data list
302 newplist();
303 }
304
305 return all;
306 }
307
308 static void
309 dimportpath(Pkg *p)
310 {
311 static Pkg *gopkg;
312 char *nam;
313 Node *n;
314
315 if(p->pathsym != S)
316 return;
317
318 if(gopkg == nil) {
319 gopkg = mkpkg(strlit("go"));
320 gopkg->name = "go";
321 }
322 nam = smprint("importpath.%s.", p->prefix);
323
324 n = nod(ONAME, N, N);
325 n->sym = pkglookup(nam, gopkg);
326 free(nam);
327 n->class = PEXTERN;
328 n->xoffset = 0;
329 p->pathsym = n->sym;
330
331 gdatastring(n, p->path);
332 ggloblsym(n->sym, types[TSTRING]->width, 1);
333 }
334
335 static int
336 dgopkgpath(Sym *s, int ot, Pkg *pkg)
337 {
338 if(pkg == nil)
339 return dgostringptr(s, ot, nil);
340
341 // Emit reference to go.importpath.""., which 6l will
342 // rewrite using the correct import path. Every package
343 // that imports this one directly defines the symbol.
344 if(pkg == localpkg) {
345 static Sym *ns;
346
347 if(ns == nil)
348 ns = pkglookup("importpath.\"\".", mkpkg(strlit("go")));
349 return dsymptr(s, ot, ns, 0);
350 }
351
352 dimportpath(pkg);
353 return dsymptr(s, ot, pkg->pathsym, 0);
354 }
355
356 /*
357 * uncommonType
358 * ../../pkg/runtime/type.go:/uncommonType
359 */
360 static int
361 dextratype(Sym *sym, int off, Type *t, int ptroff)
362 {
363 int ot, n;
364 Sym *s;
365 Sig *a, *m;
366
367 m = methods(t);
368 if(t->sym == nil && m == nil)
369 return off;
370
371 // fill in *extraType pointer in header
372 dsymptr(sym, ptroff, sym, off);
373
374 n = 0;
375 for(a=m; a; a=a->link) {
376 dtypesym(a->type);
377 n++;
378 }
379
380 ot = off;
381 s = sym;
382 if(t->sym) {
383 ot = dgostringptr(s, ot, t->sym->name);
384 if(t != types[t->etype])
385 ot = dgopkgpath(s, ot, t->sym->pkg);
386 else
387 ot = dgostringptr(s, ot, nil);
388 } else {
389 ot = dgostringptr(s, ot, nil);
390 ot = dgostringptr(s, ot, nil);
391 }
392
393 // slice header
394 ot = dsymptr(s, ot, s, ot + widthptr + 2*4);
395 ot = duint32(s, ot, n);
396 ot = duint32(s, ot, n);
397
398 // methods
399 for(a=m; a; a=a->link) {
400 // method
401 // ../../pkg/runtime/type.go:/method
402 ot = dgostringptr(s, ot, a->name);
403 ot = dgopkgpath(s, ot, a->pkg);
404 ot = dsymptr(s, ot, dtypesym(a->mtype), 0);
405 ot = dsymptr(s, ot, dtypesym(a->type), 0);
406 if(a->isym)
407 ot = dsymptr(s, ot, a->isym, 0);
408 else
409 ot = duintptr(s, ot, 0);
410 if(a->tsym)
411 ot = dsymptr(s, ot, a->tsym, 0);
412 else
413 ot = duintptr(s, ot, 0);
414 }
415
416 return ot;
417 }
418
419 enum {
420 KindBool = 1,
421 KindInt,
422 KindInt8,
423 KindInt16,
424 KindInt32,
425 KindInt64,
426 KindUint,
427 KindUint8,
428 KindUint16,
429 KindUint32,
430 KindUint64,
431 KindUintptr,
432 KindFloat32,
433 KindFloat64,
434 KindComplex64,
435 KindComplex128,
436 KindArray,
437 KindChan,
438 KindFunc,
439 KindInterface,
440 KindMap,
441 KindPtr,
442 KindSlice,
443 KindString,
444 KindStruct,
445 KindUnsafePointer,
446
447 KindNoPointers = 1<<7,
448 };
449
450 static int
451 kinds[] =
452 {
453 [TINT] = KindInt,
454 [TUINT] = KindUint,
455 [TINT8] = KindInt8,
456 [TUINT8] = KindUint8,
457 [TINT16] = KindInt16,
458 [TUINT16] = KindUint16,
459 [TINT32] = KindInt32,
460 [TUINT32] = KindUint32,
461 [TINT64] = KindInt64,
462 [TUINT64] = KindUint64,
463 [TUINTPTR] = KindUintptr,
464 [TFLOAT32] = KindFloat32,
465 [TFLOAT64] = KindFloat64,
466 [TBOOL] = KindBool,
467 [TSTRING] = KindString,
468 [TPTR32] = KindPtr,
469 [TPTR64] = KindPtr,
470 [TSTRUCT] = KindStruct,
471 [TINTER] = KindInterface,
472 [TCHAN] = KindChan,
473 [TMAP] = KindMap,
474 [TARRAY] = KindArray,
475 [TFUNC] = KindFunc,
476 [TCOMPLEX64] = KindComplex64,
477 [TCOMPLEX128] = KindComplex128,
478 [TUNSAFEPTR] = KindUnsafePointer,
479 };
480
481 static char*
482 structnames[] =
483 {
484 [TINT] = "*runtime.IntType",
485 [TUINT] = "*runtime.UintType",
486 [TINT8] = "*runtime.IntType",
487 [TUINT8] = "*runtime.UintType",
488 [TINT16] = "*runtime.IntType",
489 [TUINT16] = "*runtime.UintType",
490 [TINT32] = "*runtime.IntType",
491 [TUINT32] = "*runtime.UintType",
492 [TINT64] = "*runtime.IntType",
493 [TUINT64] = "*runtime.UintType",
494 [TUINTPTR] = "*runtime.UintType",
495 [TCOMPLEX64] = "*runtime.ComplexType",
496 [TCOMPLEX128] = "*runtime.ComplexType",
497 [TFLOAT32] = "*runtime.FloatType",
498 [TFLOAT64] = "*runtime.FloatType",
499 [TBOOL] = "*runtime.BoolType",
500 [TSTRING] = "*runtime.StringType",
501 [TUNSAFEPTR] = "*runtime.UnsafePointerType",
502
503 [TPTR32] = "*runtime.PtrType",
504 [TPTR64] = "*runtime.PtrType",
505 [TSTRUCT] = "*runtime.StructType",
506 [TINTER] = "*runtime.InterfaceType",
507 [TCHAN] = "*runtime.ChanType",
508 [TMAP] = "*runtime.MapType",
509 [TARRAY] = "*runtime.ArrayType",
510 [TFUNC] = "*runtime.FuncType",
511 };
512
513 static Sym*
514 typestruct(Type *t)
515 {
516 char *name;
517 int et;
518
519 et = t->etype;
520 if(et < 0 || et >= nelem(structnames) || (name = structnames[et]) == nil) {
521 fatal("typestruct %lT", t);
522 return nil; // silence gcc
523 }
524
525 if(isslice(t))
526 name = "*runtime.SliceType";
527
528 return pkglookup(name, typepkg);
529 }
530
531 static int
532 haspointers(Type *t)
533 {
534 Type *t1;
535
536 switch(t->etype) {
537 case TINT:
538 case TUINT:
539 case TINT8:
540 case TUINT8:
541 case TINT16:
542 case TUINT16:
543 case TINT32:
544 case TUINT32:
545 case TINT64:
546 case TUINT64:
547 case TUINTPTR:
548 case TFLOAT32:
549 case TFLOAT64:
550 case TBOOL:
551 return 0;
552 case TARRAY:
553 if(t->bound < 0) // slice
554 return 1;
555 return haspointers(t->type);
556 case TSTRUCT:
557 for(t1=t->type; t1!=T; t1=t1->down)
558 if(haspointers(t1->type))
559 return 1;
560 return 0;
561 case TSTRING:
562 case TPTR32:
563 case TPTR64:
564 case TUNSAFEPTR:
565 case TINTER:
566 case TCHAN:
567 case TMAP:
568 case TFUNC:
569 default:
570 return 1;
571 }
572 }
573
574 /*
575 * commonType
576 * ../../pkg/runtime/type.go:/commonType
577 */
578 static int
579 dcommontype(Sym *s, int ot, Type *t)
580 {
581 int i;
582 Sym *sptr;
583 char *p;
584
585 dowidth(t);
586
587 sptr = nil;
588 if(t->sym != nil && !isptr[t->etype])
589 sptr = dtypesym(ptrto(t));
590 else
591 sptr = weaktypesym(ptrto(t));
592
593 // empty interface pointing at this type.
594 // all the references that we emit are *interface{};
595 // they point here.
596 ot = rnd(ot, widthptr);
597 ot = dsymptr(s, ot, typestruct(t), 0);
598 ot = dsymptr(s, ot, s, 2*widthptr);
599
600 // ../../pkg/runtime/type.go:/commonType
601 // actual type structure
602 // type commonType struct {
603 // size uintptr;
604 // hash uint32;
605 // alg uint8;
606 // align uint8;
607 // fieldAlign uint8;
608 // kind uint8;
609 // string *string;
610 // *extraType;
611 // ptrToThis *Type
612 // }
613 ot = duintptr(s, ot, t->width);
614 ot = duint32(s, ot, typehash(t));
615 ot = duint8(s, ot, algtype(t));
616 ot = duint8(s, ot, t->align); // align
617 ot = duint8(s, ot, t->align); // fieldAlign
618 i = kinds[t->etype];
619 if(t->etype == TARRAY && t->bound < 0)
620 i = KindSlice;
621 if(!haspointers(t))
622 i |= KindNoPointers;
623 ot = duint8(s, ot, i); // kind
624 longsymnames = 1;
625 p = smprint("%-T", t);
626 longsymnames = 0;
627 ot = dgostringptr(s, ot, p); // string
628 free(p);
629
630 // skip pointer to extraType,
631 // which follows the rest of this type structure.
632 // caller will fill in if needed.
633 // otherwise linker will assume 0.
634 ot += widthptr;
635
636 ot = dsymptr(s, ot, sptr, 0); // ptrto type
637 return ot;
638 }
639
640 Sym*
641 typesym(Type *t)
642 {
643 char *p;
644 Sym *s;
645
646 p = smprint("%#-T", t);
647 s = pkglookup(p, typepkg);
648 free(p);
649 return s;
650 }
651
652 Node*
653 typename(Type *t)
654 {
655 Sym *s;
656 Node *n;
657
658 if(t == T || (isptr[t->etype] && t->type == T) || isideal(t))
659 fatal("typename %T", t);
660 s = typesym(t);
661 if(s->def == N) {
662 n = nod(ONAME, N, N);
663 n->sym = s;
664 n->type = types[TUINT8];
665 n->addable = 1;
666 n->ullman = 1;
667 n->class = PEXTERN;
668 n->xoffset = 0;
669 s->def = n;
670
671 signatlist = list(signatlist, typenod(t));
672 }
673
674 n = nod(OADDR, s->def, N);
675 n->type = ptrto(s->def->type);
676 n->addable = 1;
677 n->ullman = 2;
678 return n;
679 }
680
681 static Sym*
682 weaktypesym(Type *t)
683 {
684 char *p;
685 Sym *s;
686 static Pkg *weak;
687
688 if(weak == nil) {
689 weak = mkpkg(strlit("weak.type"));
690 weak->name = "weak.type";
691 weak->prefix = "weak.type"; // not weak%2etype
692 }
693
694 p = smprint("%#-T", t);
695 s = pkglookup(p, weak);
696 free(p);
697 return s;
698 }
699
700 static Sym*
701 dtypesym(Type *t)
702 {
703 int ot, xt, n, isddd, dupok;
704 Sym *s, *s1, *s2;
705 Sig *a, *m;
706 Type *t1, *tbase, *t2;
707
708 if(isideal(t))
709 fatal("dtypesym %T", t);
710
711 s = typesym(t);
712 if(s->flags & SymSiggen)
713 return s;
714 s->flags |= SymSiggen;
715
716 // special case (look for runtime below):
717 // when compiling package runtime,
718 // emit the type structures for int, float, etc.
719 tbase = t;
720 if(isptr[t->etype] && t->sym == S && t->type->sym != S)
721 tbase = t->type;
722 dupok = tbase->sym == S;
723
724 if(compiling_runtime && tbase == types[tbase->etype]) // int, float, etc
725 goto ok;
726
727 // named types from other files are defined only by those files
728 if(tbase->sym && !tbase->local)
729 return s;
730 if(isforw[tbase->etype])
731 return s;
732
733 ok:
734 ot = 0;
735 xt = 0;
736 switch(t->etype) {
737 default:
738 ot = dcommontype(s, ot, t);
739 xt = ot - 2*widthptr;
740 break;
741
742 case TARRAY:
743 if(t->bound >= 0) {
744 // ../../pkg/runtime/type.go:/ArrayType
745 s1 = dtypesym(t->type);
746 t2 = typ(TARRAY);
747 t2->type = t->type;
748 t2->bound = -1; // slice
749 s2 = dtypesym(t2);
750 ot = dcommontype(s, ot, t);
751 xt = ot - 2*widthptr;
752 ot = dsymptr(s, ot, s1, 0);
753 ot = dsymptr(s, ot, s2, 0);
754 ot = duintptr(s, ot, t->bound);
755 } else {
756 // ../../pkg/runtime/type.go:/SliceType
757 s1 = dtypesym(t->type);
758 ot = dcommontype(s, ot, t);
759 xt = ot - 2*widthptr;
760 ot = dsymptr(s, ot, s1, 0);
761 }
762 break;
763
764 case TCHAN:
765 // ../../pkg/runtime/type.go:/ChanType
766 s1 = dtypesym(t->type);
767 ot = dcommontype(s, ot, t);
768 xt = ot - 2*widthptr;
769 ot = dsymptr(s, ot, s1, 0);
770 ot = duintptr(s, ot, t->chan);
771 break;
772
773 case TFUNC:
774 for(t1=getthisx(t)->type; t1; t1=t1->down)
775 dtypesym(t1->type);
776 isddd = 0;
777 for(t1=getinargx(t)->type; t1; t1=t1->down) {
778 isddd = t1->isddd;
779 dtypesym(t1->type);
780 }
781 for(t1=getoutargx(t)->type; t1; t1=t1->down)
782 dtypesym(t1->type);
783
784 ot = dcommontype(s, ot, t);
785 xt = ot - 2*widthptr;
786 ot = duint8(s, ot, isddd);
787
788 // two slice headers: in and out.
789 ot = rnd(ot, widthptr);
790 ot = dsymptr(s, ot, s, ot+2*(widthptr+2*4));
791 n = t->thistuple + t->intuple;
792 ot = duint32(s, ot, n);
793 ot = duint32(s, ot, n);
794 ot = dsymptr(s, ot, s, ot+1*(widthptr+2*4)+n*widthptr);
795 ot = duint32(s, ot, t->outtuple);
796 ot = duint32(s, ot, t->outtuple);
797
798 // slice data
799 for(t1=getthisx(t)->type; t1; t1=t1->down, n++)
800 ot = dsymptr(s, ot, dtypesym(t1->type), 0);
801 for(t1=getinargx(t)->type; t1; t1=t1->down, n++)
802 ot = dsymptr(s, ot, dtypesym(t1->type), 0);
803 for(t1=getoutargx(t)->type; t1; t1=t1->down, n++)
804 ot = dsymptr(s, ot, dtypesym(t1->type), 0);
805 break;
806
807 case TINTER:
808 m = imethods(t);
809 n = 0;
810 for(a=m; a; a=a->link) {
811 dtypesym(a->type);
812 n++;
813 }
814
815 // ../../pkg/runtime/type.go:/InterfaceType
816 ot = dcommontype(s, ot, t);
817 xt = ot - 2*widthptr;
818 ot = dsymptr(s, ot, s, ot+widthptr+2*4);
819 ot = duint32(s, ot, n);
820 ot = duint32(s, ot, n);
821 for(a=m; a; a=a->link) {
822 // ../../pkg/runtime/type.go:/imethod
823 ot = dgostringptr(s, ot, a->name);
824 ot = dgopkgpath(s, ot, a->pkg);
825 ot = dsymptr(s, ot, dtypesym(a->type), 0);
826 }
827 break;
828
829 case TMAP:
830 // ../../pkg/runtime/type.go:/MapType
831 s1 = dtypesym(t->down);
832 s2 = dtypesym(t->type);
833 ot = dcommontype(s, ot, t);
834 xt = ot - 2*widthptr;
835 ot = dsymptr(s, ot, s1, 0);
836 ot = dsymptr(s, ot, s2, 0);
837 break;
838
839 case TPTR32:
840 case TPTR64:
841 if(t->type->etype == TANY) {
842 // ../../pkg/runtime/type.go:/UnsafePointerType
843 ot = dcommontype(s, ot, t);
844 break;
845 }
846 // ../../pkg/runtime/type.go:/PtrType
847 s1 = dtypesym(t->type);
848 ot = dcommontype(s, ot, t);
849 xt = ot - 2*widthptr;
850 ot = dsymptr(s, ot, s1, 0);
851 break;
852
853 case TSTRUCT:
854 // ../../pkg/runtime/type.go:/StructType
855 // for security, only the exported fields.
856 n = 0;
857 for(t1=t->type; t1!=T; t1=t1->down) {
858 dtypesym(t1->type);
859 n++;
860 }
861 ot = dcommontype(s, ot, t);
862 xt = ot - 2*widthptr;
863 ot = dsymptr(s, ot, s, ot+widthptr+2*4);
864 ot = duint32(s, ot, n);
865 ot = duint32(s, ot, n);
866 for(t1=t->type; t1!=T; t1=t1->down) {
867 // ../../pkg/runtime/type.go:/structField
868 if(t1->sym && !t1->embedded) {
869 ot = dgostringptr(s, ot, t1->sym->name);
870 if(exportname(t1->sym->name))
871 ot = dgostringptr(s, ot, nil);
872 else
873 ot = dgopkgpath(s, ot, t1->sym->pkg);
874 } else {
875 ot = dgostringptr(s, ot, nil);
876 ot = dgostringptr(s, ot, nil);
877 }
878 ot = dsymptr(s, ot, dtypesym(t1->type), 0);
879 ot = dgostrlitptr(s, ot, t1->note);
880 ot = duintptr(s, ot, t1->width); // field offset
881 }
882 break;
883 }
884 ot = dextratype(s, ot, t, xt);
885 ggloblsym(s, ot, dupok);
886 return s;
887 }
888
889 void
890 dumptypestructs(void)
891 {
892 int i;
893 NodeList *l;
894 Node *n;
895 Type *t;
896 Pkg *p;
897
898 // copy types from externdcl list to signatlist
899 for(l=externdcl; l; l=l->next) {
900 n = l->n;
901 if(n->op != OTYPE)
902 continue;
903 signatlist = list(signatlist, n);
904 }
905
906 // process signatlist
907 for(l=signatlist; l; l=l->next) {
908 n = l->n;
909 if(n->op != OTYPE)
910 continue;
911 t = n->type;
912 dtypesym(t);
913 if(t->sym)
914 dtypesym(ptrto(t));
915 }
916
917 // generate import strings for imported packages
918 for(i=0; i<nelem(phash); i++)
919 for(p=phash[i]; p; p=p->link)
920 if(p->direct)
921 dimportpath(p);
922
923 // do basic types if compiling package runtime.
924 // they have to be in at least one package,
925 // and runtime is always loaded implicitly,
926 // so this is as good as any.
927 // another possible choice would be package main,
928 // but using runtime means fewer copies in .6 files.
929 if(compiling_runtime) {
930 for(i=1; i<=TBOOL; i++)
931 dtypesym(ptrto(types[i]));
932 dtypesym(ptrto(types[TSTRING]));
933 dtypesym(ptrto(types[TUNSAFEPTR]));
934
935 // add paths for runtime and main, which 6l imports implicitly.
936 dimportpath(runtimepkg);
937 dimportpath(mkpkg(strlit("main")));
938 }
939 }