~john-koepi/ubuntu/trusty/golang/default

« back to all changes in this revision

Viewing changes to src/cmd/gc/reflect.c

  • Committer: Bazaar Package Importer
  • Author(s): Ondřej Surý
  • Date: 2011-04-20 17:36:48 UTC
  • Revision ID: james.westby@ubuntu.com-20110420173648-ifergoxyrm832trd
Tags: upstream-2011.03.07.1
Import upstream version 2011.03.07.1

Show diffs side-by-side

added added

removed removed

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