root/trunk/src/toobj.c

Revision 798, 37.7 kB (checked in by walter, 1 year ago)

more 64

  • Property svn:eol-style set to native
Line 
1 // Copyright (c) 1999-2010 by Digital Mars
2 // All Rights Reserved
3 // written by Walter Bright
4 // http://www.digitalmars.com
5 // License for redistribution is by either the Artistic License
6 // in artistic.txt, or the GNU General Public License in gnu.txt.
7 // See the included readme.txt for details.
8
9 #include <stdio.h>
10 #include <stddef.h>
11 #include <time.h>
12 #include <assert.h>
13
14 #include "mars.h"
15 #include "module.h"
16 #include "mtype.h"
17 #include "declaration.h"
18 #include "statement.h"
19 #include "enum.h"
20 #include "aggregate.h"
21 #include "init.h"
22 #include "attrib.h"
23 #include "id.h"
24 #include "import.h"
25 #include "template.h"
26
27 #include "rmem.h"
28 #include "cc.h"
29 #include "global.h"
30 #include "oper.h"
31 #include "code.h"
32 #include "type.h"
33 #include "dt.h"
34 #include "cgcv.h"
35 #include "outbuf.h"
36 #include "irstate.h"
37
38 void obj_lzext(Symbol *s1,Symbol *s2);
39
40 /* ================================================================== */
41
42 // Put out instance of ModuleInfo for this Module
43
44 void Module::genmoduleinfo()
45 {
46     //printf("Module::genmoduleinfo() %s\n", toChars());
47
48     Symbol *msym = toSymbol();
49     unsigned offset;
50 #if DMDV2
51     unsigned sizeof_ModuleInfo = 16 * PTRSIZE;
52 #else
53     unsigned sizeof_ModuleInfo = 14 * PTRSIZE;
54 #endif
55 #if !MODULEINFO_IS_STRUCT
56     sizeof_ModuleInfo -= 2 * PTRSIZE;
57 #endif
58     //printf("moduleinfo size = x%x\n", sizeof_ModuleInfo);
59
60     //////////////////////////////////////////////
61
62     csym->Sclass = SCglobal;
63     csym->Sfl = FLdata;
64
65 #if 1
66     dt_t *dt = NULL;
67     ClassDeclarations aclasses;
68
69     //printf("members->dim = %d\n", members->dim);
70     for (int i = 0; i < members->dim; i++)
71     {   Dsymbol *member = (Dsymbol *)members->data[i];
72
73         //printf("\tmember '%s'\n", member->toChars());
74         member->addLocalClass(&aclasses);
75     }
76
77     // importedModules[]
78     int aimports_dim = aimports.dim;
79     for (int i = 0; i < aimports.dim; i++)
80     {   Module *m = (Module *)aimports.data[i];
81         if (!m->needmoduleinfo)
82             aimports_dim--;
83     }
84
85     FuncDeclaration *sgetmembers = findGetMembers();
86
87     // These must match the values in druntime/src/object_.d
88     #define MIstandalone      4
89     #define MItlsctor         8
90     #define MItlsdtor         0x10
91     #define MIctor            0x20
92     #define MIdtor            0x40
93     #define MIxgetMembers     0x80
94     #define MIictor           0x100
95     #define MIunitTest        0x200
96     #define MIimportedModules 0x400
97     #define MIlocalClasses    0x800
98     #define MInew             0x80000000   // it's the "new" layout
99
100     unsigned flags = MInew;
101     if (sctor)
102         flags |= MItlsctor;
103     if (sdtor)
104         flags |= MItlsdtor;
105     if (ssharedctor)
106         flags |= MIctor;
107     if (sshareddtor)
108         flags |= MIdtor;
109     if (sgetmembers)
110         flags |= MIxgetMembers;
111     if (sictor)
112         flags |= MIictor;
113     if (stest)
114         flags |= MIunitTest;
115     if (aimports_dim)
116         flags |= MIimportedModules;
117     if (aclasses.dim)
118         flags |= MIlocalClasses;
119
120     if (!needmoduleinfo)
121         flags |= MIstandalone;
122
123     dtdword(&dt, flags);        // n.flags
124     dtdword(&dt, 0);            // n.index
125
126     if (flags & MItlsctor)
127         dtxoff(&dt, sctor, 0, TYnptr);
128     if (flags & MItlsdtor)
129         dtxoff(&dt, sdtor, 0, TYnptr);
130     if (flags & MIctor)
131         dtxoff(&dt, ssharedctor, 0, TYnptr);
132     if (flags & MIdtor)
133         dtxoff(&dt, sshareddtor, 0, TYnptr);
134     if (flags & MIxgetMembers)
135         dtxoff(&dt, sgetmembers->toSymbol(), 0, TYnptr);
136     if (flags & MIictor)
137         dtxoff(&dt, sictor, 0, TYnptr);
138     if (flags & MIunitTest)
139         dtxoff(&dt, stest, 0, TYnptr);
140     if (flags & MIimportedModules)
141     {
142         dtsize_t(&dt, aimports_dim);
143         for (int i = 0; i < aimports.dim; i++)
144         {   Module *m = (Module *)aimports.data[i];
145
146             if (m->needmoduleinfo)
147             {   Symbol *s = m->toSymbol();
148
149                 /* Weak references don't pull objects in from the library,
150                  * they resolve to 0 if not pulled in by something else.
151                  * Don't pull in a module just because it was imported.
152                  */
153 #if !OMFOBJ // Optlink crashes with weak symbols at EIP 41AFE7, 402000
154                 s->Sflags |= SFLweak;
155 #endif
156                 dtxoff(&dt, s, 0, TYnptr);
157             }
158         }
159     }
160     if (flags & MIlocalClasses)
161     {
162         dtsize_t(&dt, aclasses.dim);
163         for (int i = 0; i < aclasses.dim; i++)
164         {
165             ClassDeclaration *cd = (ClassDeclaration *)aclasses.data[i];
166             dtxoff(&dt, cd->toSymbol(), 0, TYnptr);
167         }
168     }
169
170     // Put out module name as a 0-terminated string, to save bytes
171     nameoffset = dt_size(dt);
172     const char *name = toPrettyChars();
173     namelen = strlen(name);
174     dtnbytes(&dt, namelen + 1, name);
175     //printf("nameoffset = x%x\n", nameoffset);
176 #else
177     /* The layout is:
178        {
179             void **vptr;
180             monitor_t monitor;
181             char[] name;                // class name
182             ModuleInfo importedModules[];
183             ClassInfo localClasses[];
184             uint flags;                 // initialization state
185             void *ctor;
186             void *dtor;
187             void *unitTest;
188             const(MemberInfo[]) function(string) xgetMembers;   // module getMembers() function
189             void *ictor;
190             void *sharedctor;
191             void *shareddtor;
192             uint index;
193             void*[1] reserved;
194        }
195      */
196     dt_t *dt = NULL;
197
198 #if !MODULEINFO_IS_STRUCT
199     if (moduleinfo)
200         dtxoff(&dt, moduleinfo->toVtblSymbol(), 0, TYnptr); // vtbl for ModuleInfo
201     else
202     {   //printf("moduleinfo is null\n");
203         dtdword(&dt, 0);                // BUG: should be an assert()
204     }
205     dtdword(&dt, 0);                    // monitor
206 #endif
207
208     // name[]
209     const char *name = toPrettyChars();
210     size_t namelen = strlen(name);
211     dtdword(&dt, namelen);
212     dtabytes(&dt, TYnptr, 0, namelen + 1, name);
213
214     ClassDeclarations aclasses;
215
216     //printf("members->dim = %d\n", members->dim);
217     for (int i = 0; i < members->dim; i++)
218     {   Dsymbol *member = (Dsymbol *)members->data[i];
219
220         //printf("\tmember '%s'\n", member->toChars());
221         member->addLocalClass(&aclasses);
222     }
223
224     // importedModules[]
225     int aimports_dim = aimports.dim;
226     for (int i = 0; i < aimports.dim; i++)
227     {   Module *m = (Module *)aimports.data[i];
228         if (!m->needModuleInfo())
229             aimports_dim--;
230     }
231     dtdword(&dt, aimports_dim);
232     if (aimports_dim)
233         dtxoff(&dt, csym, sizeof_ModuleInfo, TYnptr);
234     else
235         dtdword(&dt, 0);
236
237     // localClasses[]
238     dtdword(&dt, aclasses.dim);
239     if (aclasses.dim)
240         dtxoff(&dt, csym, sizeof_ModuleInfo + aimports_dim * PTRSIZE, TYnptr);
241     else
242         dtdword(&dt, 0);
243
244     if (needmoduleinfo)
245         dtdword(&dt, 8);                        // flags
246     else
247         dtdword(&dt, 8 | MIstandalone);         // flags
248
249     if (ssharedctor)
250         dtxoff(&dt, ssharedctor, 0, TYnptr);
251     else
252         dtdword(&dt, 0);
253
254     if (sshareddtor)
255         dtxoff(&dt, sshareddtor, 0, TYnptr);
256     else
257         dtdword(&dt, 0);
258
259     if (stest)
260         dtxoff(&dt, stest, 0, TYnptr);
261     else
262         dtdword(&dt, 0);
263
264 #if DMDV2
265     FuncDeclaration *sgetmembers = findGetMembers();
266     if (sgetmembers)
267         dtxoff(&dt, sgetmembers->toSymbol(), 0, TYnptr);
268     else
269 #endif
270         dtdword(&dt, 0);                        // xgetMembers
271
272     if (sictor)
273         dtxoff(&dt, sictor, 0, TYnptr);
274     else
275         dtdword(&dt, 0);
276
277 #if DMDV2
278     if (sctor)
279         dtxoff(&dt, sctor, 0, TYnptr);
280     else
281         dtdword(&dt, 0);
282
283     if (sdtor)
284         dtxoff(&dt, sdtor, 0, TYnptr);
285     else
286         dtdword(&dt, 0);
287
288     dtdword(&dt, 0);                            // index
289
290     // void*[1] reserved;
291     dtdword(&dt, 0);
292 #endif
293     //////////////////////////////////////////////
294
295     for (int i = 0; i < aimports.dim; i++)
296     {   Module *m = (Module *)aimports.data[i];
297
298         if (m->needModuleInfo())
299         {   Symbol *s = m->toSymbol();
300
301             /* Weak references don't pull objects in from the library,
302              * they resolve to 0 if not pulled in by something else.
303              * Don't pull in a module just because it was imported.
304              */
305 #if !OMFOBJ // Optlink crashes with weak symbols at EIP 41AFE7, 402000
306             s->Sflags |= SFLweak;
307 #endif
308             dtxoff(&dt, s, 0, TYnptr);
309         }
310     }
311
312     for (int i = 0; i < aclasses.dim; i++)
313     {
314         ClassDeclaration *cd = (ClassDeclaration *)aclasses.data[i];
315         dtxoff(&dt, cd->toSymbol(), 0, TYnptr);
316     }
317 #endif
318
319     csym->Sdt = dt;
320 #if ELFOBJ || MACHOBJ
321     // Cannot be CONST because the startup code sets flag bits in it
322     csym->Sseg = DATA;
323 #endif
324     outdata(csym);
325
326     //////////////////////////////////////////////
327
328     obj_moduleinfo(msym);
329 }
330
331 /* ================================================================== */
332
333 void Dsymbol::toObjFile(int multiobj)
334 {
335     //printf("Dsymbol::toObjFile('%s')\n", toChars());
336     // ignore
337 }
338
339 /* ================================================================== */
340
341 void ClassDeclaration::toObjFile(int multiobj)
342 {   unsigned i;
343     unsigned offset;
344     Symbol *sinit;
345     enum_SC scclass;
346
347     //printf("ClassDeclaration::toObjFile('%s')\n", toChars());
348
349     if (!members)
350         return;
351
352     if (multiobj)
353     {   obj_append(this);
354         return;
355     }
356
357     if (global.params.symdebug)
358         toDebug();
359
360     assert(!scope);     // semantic() should have been run to completion
361
362     scclass = SCglobal;
363     if (inTemplateInstance())
364         scclass = SCcomdat;
365
366     // Put out the members
367     for (i = 0; i < members->dim; i++)
368     {
369         Dsymbol *member;
370
371         member = (Dsymbol *)members->data[i];
372         member->toObjFile(0);
373     }
374
375 #if 0
376     // Build destructor by aggregating dtors[]
377     Symbol *sdtor;
378     switch (dtors.dim)
379     {   case 0:
380             // No destructors for this class
381             sdtor = NULL;
382             break;
383
384         case 1:
385             // One destructor, just use it directly
386             sdtor = ((DtorDeclaration *)dtors.data[0])->toSymbol();
387             break;
388
389         default:
390         {   /* Build a destructor that calls all the
391              * other destructors in dtors[].
392              */
393
394             elem *edtor = NULL;
395
396             // Declare 'this' pointer for our new destructor
397             Symbol *sthis = symbol_calloc("this");
398             sthis->Stype = type_fake(TYnptr);
399             sthis->Stype->Tcount++;
400             sthis->Sclass = SCfastpar;
401             sthis->Spreg = AX;
402             sthis->Sfl = FLauto;
403
404             // Call each of the destructors in dtors[]
405             // in reverse order
406             for (i = 0; i < dtors.dim; i++)
407             {   DtorDeclaration *d = (DtorDeclaration *)dtors.data[i];
408                 Symbol *s = d->toSymbol();
409                 elem *e = el_bin(OPcall, TYvoid, el_var(s), el_var(sthis));
410                 edtor = el_combine(e, edtor);
411             }
412
413             // Create type for the function
414             ::type *t = type_alloc(TYjfunc);
415             t->Tflags |= TFprototype | TFfixed;
416             t->Tmangle = mTYman_d;
417             t->Tnext = tsvoid;
418             tsvoid->Tcount++;
419
420             // Create the function, sdtor, and write it out
421             localgot = NULL;
422             sdtor = toSymbolX("__dtor", SCglobal, t, "FZv");
423             block *b = block_calloc();
424             b->BC = BCret;
425             b->Belem = edtor;
426             sdtor->Sfunc->Fstartblock = b;
427             cstate.CSpsymtab = &sdtor->Sfunc->Flocsym;
428             symbol_add(sthis);
429             writefunc(sdtor);
430         }
431     }
432 #endif
433
434     // Generate C symbols
435     toSymbol();
436     toVtblSymbol();
437     sinit = toInitializer();
438
439     //////////////////////////////////////////////
440
441     // Generate static initializer
442     sinit->Sclass = scclass;
443     sinit->Sfl = FLdata;
444 #if ELFOBJ // Burton
445     sinit->Sseg = CDATA;
446 #endif
447 #if MACHOBJ
448     sinit->Sseg = DATA;
449 #endif
450     toDt(&sinit->Sdt);
451     outdata(sinit);
452
453     //////////////////////////////////////////////
454
455     // Put out the TypeInfo
456     type->getTypeInfo(NULL);
457     //type->vtinfo->toObjFile(multiobj);
458
459     //////////////////////////////////////////////
460
461     // Put out the ClassInfo
462     csym->Sclass = scclass;
463     csym->Sfl = FLdata;
464
465     /* The layout is:
466        {
467             void **vptr;
468             monitor_t monitor;
469             byte[] initializer;         // static initialization data
470             char[] name;                // class name
471             void *[] vtbl;
472             Interface[] interfaces;
473             ClassInfo *base;            // base class
474             void *destructor;
475             void *invariant;            // class invariant
476             uint flags;
477             void *deallocator;
478             OffsetTypeInfo[] offTi;
479             void *defaultConstructor;
480             const(MemberInfo[]) function(string) xgetMembers;   // module getMembers() function
481             //TypeInfo typeinfo;
482        }
483      */
484     dt_t *dt = NULL;
485     unsigned classinfo_size = global.params.isX86_64 ? CLASSINFO_SIZE_64 : CLASSINFO_SIZE;    // must be ClassInfo.size
486     offset = classinfo_size;
487     if (classinfo)
488     {
489         if (classinfo->structsize != classinfo_size)
490         {
491 #ifdef DEBUG
492             printf("CLASSINFO_SIZE = x%x, classinfo->structsize = x%x\n", offset, classinfo->structsize);
493 #endif
494             error("mismatch between dmd and object.d or object.di found. Check installation and import paths with -v compiler switch.");
495             fatal();
496         }
497     }
498
499     if (classinfo)
500         dtxoff(&dt, classinfo->toVtblSymbol(), 0, TYnptr); // vtbl for ClassInfo
501     else
502         dtsize_t(&dt, 0);                // BUG: should be an assert()
503     dtsize_t(&dt, 0);                    // monitor
504
505     // initializer[]
506     assert(structsize >= 8);
507     dtsize_t(&dt, structsize);           // size
508     dtxoff(&dt, sinit, 0, TYnptr);      // initializer
509
510     // name[]
511     const char *name = ident->toChars();
512     size_t namelen = strlen(name);
513     if (!(namelen > 9 && memcmp(name, "TypeInfo_", 9) == 0))
514     {   name = toPrettyChars();
515         namelen = strlen(name);
516     }
517     dtsize_t(&dt, namelen);
518     dtabytes(&dt, TYnptr, 0, namelen + 1, name);
519
520     // vtbl[]
521     dtsize_t(&dt, vtbl.dim);
522     dtxoff(&dt, vtblsym, 0, TYnptr);
523
524     // interfaces[]
525     dtsize_t(&dt, vtblInterfaces->dim);
526     if (vtblInterfaces->dim)
527         dtxoff(&dt, csym, offset, TYnptr);      // (*)
528     else
529         dtsize_t(&dt, 0);
530
531     // base
532     if (baseClass)
533         dtxoff(&dt, baseClass->toSymbol(), 0, TYnptr);
534     else
535         dtsize_t(&dt, 0);
536
537     // destructor
538     if (dtor)
539         dtxoff(&dt, dtor->toSymbol(), 0, TYnptr);
540     else
541         dtsize_t(&dt, 0);
542
543     // invariant
544     if (inv)
545         dtxoff(&dt, inv->toSymbol(), 0, TYnptr);
546     else
547         dtsize_t(&dt, 0);
548
549     // flags
550     int flags = 4 | isCOMclass();
551 #if DMDV2
552     flags |= 16;
553 #endif
554     flags |= 32;
555     if (ctor)
556         flags |= 8;
557     for (ClassDeclaration *cd = this; cd; cd = cd->baseClass)
558     {
559         if (cd->members)
560         {
561             for (size_t i = 0; i < cd->members->dim; i++)
562             {
563                 Dsymbol *sm = (Dsymbol *)cd->members->data[i];
564                 //printf("sm = %s %s\n", sm->kind(), sm->toChars());
565                 if (sm->hasPointers())
566                     goto L2;
567             }
568         }
569     }
570     flags |= 2;                 // no pointers
571   L2:
572     dtsize_t(&dt, flags);
573
574
575     // deallocator
576     if (aggDelete)
577         dtxoff(&dt, aggDelete->toSymbol(), 0, TYnptr);
578     else
579         dtsize_t(&dt, 0);
580
581     // offTi[]
582     dtsize_t(&dt, 0);
583     dtsize_t(&dt, 0);            // null for now, fix later
584
585     // defaultConstructor
586     if (defaultCtor)
587         dtxoff(&dt, defaultCtor->toSymbol(), 0, TYnptr);
588     else
589         dtsize_t(&dt, 0);
590
591 #if DMDV2
592     FuncDeclaration *sgetmembers = findGetMembers();
593     if (sgetmembers)
594         dtxoff(&dt, sgetmembers->toSymbol(), 0, TYnptr);
595     else
596         dtsize_t(&dt, 0);        // module getMembers() function
597 #endif
598
599     //dtxoff(&dt, type->vtinfo->toSymbol(), 0, TYnptr); // typeinfo
600
601     //////////////////////////////////////////////
602
603     // Put out vtblInterfaces->data[]. Must immediately follow csym, because
604     // of the fixup (*)
605
606     offset += vtblInterfaces->dim * (4 * PTRSIZE);
607     for (i = 0; i < vtblInterfaces->dim; i++)
608     {   BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
609         ClassDeclaration *id = b->base;
610
611         /* The layout is:
612          *  struct Interface
613          *  {
614          *      ClassInfo *interface;
615          *      void *[] vtbl;
616          *      ptrdiff_t offset;
617          *  }
618          */
619
620         // Fill in vtbl[]
621         b->fillVtbl(this, &b->vtbl, 1);
622
623         dtxoff(&dt, id->toSymbol(), 0, TYnptr);         // ClassInfo
624
625         // vtbl[]
626         dtsize_t(&dt, id->vtbl.dim);
627         dtxoff(&dt, csym, offset, TYnptr);
628
629         dtsize_t(&dt, b->offset);                        // this offset
630
631         offset += id->vtbl.dim * PTRSIZE;
632     }
633
634     // Put out the vtblInterfaces->data[].vtbl[]
635     // This must be mirrored with ClassDeclaration::baseVtblOffset()
636     //printf("putting out %d interface vtbl[]s for '%s'\n", vtblInterfaces->dim, toChars());
637     for (i = 0; i < vtblInterfaces->dim; i++)
638     {   BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
639         ClassDeclaration *id = b->base;
640
641         //printf("    interface[%d] is '%s'\n", i, id->toChars());
642         int j = 0;
643         if (id->vtblOffset())
644         {
645             // First entry is ClassInfo reference
646             //dtxoff(&dt, id->toSymbol(), 0, TYnptr);
647
648             // First entry is struct Interface reference
649             dtxoff(&dt, csym, classinfo_size + i * (4 * PTRSIZE), TYnptr);
650             j = 1;
651         }
652         assert(id->vtbl.dim == b->vtbl.dim);
653         for (; j < id->vtbl.dim; j++)
654         {
655             assert(j < b->vtbl.dim);
656 #if 0
657             Object *o = (Object *)b->vtbl.data[j];
658             if (o)
659             {
660                 printf("o = %p\n", o);
661                 assert(o->dyncast() == DYNCAST_DSYMBOL);
662                 Dsymbol *s = (Dsymbol *)o;
663                 printf("s->kind() = '%s'\n", s->kind());
664             }
665 #endif
666             FuncDeclaration *fd = (FuncDeclaration *)b->vtbl.data[j];
667             if (fd)
668                 dtxoff(&dt, fd->toThunkSymbol(b->offset), 0, TYnptr);
669             else
670                 dtsize_t(&dt, 0);
671         }
672     }
673
674 #if 1
675     // Put out the overriding interface vtbl[]s.
676     // This must be mirrored with ClassDeclaration::baseVtblOffset()
677     //printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset);
678     ClassDeclaration *cd;
679     Array bvtbl;
680
681     for (cd = this->baseClass; cd; cd = cd->baseClass)
682     {
683         for (int k = 0; k < cd->vtblInterfaces->dim; k++)
684         {   BaseClass *bs = (BaseClass *)cd->vtblInterfaces->data[k];
685
686             if (bs->fillVtbl(this, &bvtbl, 0))
687             {
688                 //printf("\toverriding vtbl[] for %s\n", bs->base->toChars());
689                 ClassDeclaration *id = bs->base;
690
691                 int j = 0;
692                 if (id->vtblOffset())
693                 {
694                     // First entry is ClassInfo reference
695                     //dtxoff(&dt, id->toSymbol(), 0, TYnptr);
696
697                     // First entry is struct Interface reference
698                     dtxoff(&dt, cd->toSymbol(), classinfo_size + k * (4 * PTRSIZE), TYnptr);
699                     j = 1;
700                 }
701
702                 for (; j < id->vtbl.dim; j++)
703                 {
704                     FuncDeclaration *fd;
705
706                     assert(j < bvtbl.dim);
707                     fd = (FuncDeclaration *)bvtbl.data[j];
708                     if (fd)
709                         dtxoff(&dt, fd->toThunkSymbol(bs->offset), 0, TYnptr);
710                     else
711                         dtsize_t(&dt, 0);
712                 }
713             }
714         }
715     }
716 #endif
717 #if INTERFACE_VIRTUAL
718     // Put out the overriding interface vtbl[]s.
719     // This must be mirrored with ClassDeclaration::baseVtblOffset()
720     //printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset);
721     for (i = 0; i < vtblInterfaces->dim; i++)
722     {   BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
723         ClassDeclaration *cd;
724
725         for (cd = this->baseClass; cd; cd = cd->baseClass)
726         {
727             for (int k = 0; k < cd->vtblInterfaces->dim; k++)
728             {   BaseClass *bs = (BaseClass *)cd->vtblInterfaces->data[k];
729
730                 if (b->base == bs->base)
731                 {
732                     //printf("\toverriding vtbl[] for %s\n", b->base->toChars());
733                     ClassDeclaration *id = b->base;
734
735                     int j = 0;
736                     if (id->vtblOffset())
737                     {
738                         // First entry is ClassInfo reference
739                         //dtxoff(&dt, id->toSymbol(), 0, TYnptr);
740
741                         // First entry is struct Interface reference
742                         dtxoff(&dt, cd->toSymbol(), classinfo_size + k * (4 * PTRSIZE), TYnptr);
743                         j = 1;
744                     }
745
746                     for (; j < id->vtbl.dim; j++)
747                     {
748                         assert(j < b->vtbl.dim);
749                         FuncDeclaration *fd = (FuncDeclaration *)b->vtbl.data[j];
750                         if (fd)
751                             dtxoff(&dt, fd->toThunkSymbol(bs->offset), 0, TYnptr);
752                         else
753                             dtsize_t(&dt, 0);
754                     }
755                 }
756             }
757         }
758     }
759 #endif
760
761
762     csym->Sdt = dt;
763 #if ELFOBJ || MACHOBJ // Burton
764     // ClassInfo cannot be const data, because we use the monitor on it
765     csym->Sseg = DATA;
766 #endif
767     outdata(csym);
768     if (isExport())
769         obj_export(csym,0);
770
771     //////////////////////////////////////////////
772
773     // Put out the vtbl[]
774     //printf("putting out %s.vtbl[]\n", toChars());
775     dt = NULL;
776     if (0)
777         i = 0;
778     else
779     {   dtxoff(&dt, csym, 0, TYnptr);           // first entry is ClassInfo reference
780         i = 1;
781     }
782     for (; i < vtbl.dim; i++)
783     {
784         FuncDeclaration *fd = ((Dsymbol *)vtbl.data[i])->isFuncDeclaration();
785
786         //printf("\tvtbl[%d] = %p\n", i, fd);
787         if (fd && (fd->fbody || !isAbstract()))
788         {
789             // Ensure function has a return value (Bugzilla 4869)
790             if (fd->type->ty == Tfunction && !((TypeFunction *)fd->type)->next)
791             {
792                 assert(fd->scope);
793                 fd->semantic3(fd->scope);
794             }
795
796             Symbol *s = fd->toSymbol();
797
798 #if DMDV2
799             if (isFuncHidden(fd))
800             {   /* fd is hidden from the view of this class.
801                  * If fd overlaps with any function in the vtbl[], then
802                  * issue 'hidden' error.
803                  */
804                 for (int j = 1; j < vtbl.dim; j++)
805                 {   if (j == i)
806                         continue;
807                     FuncDeclaration *fd2 = ((Dsymbol *)vtbl.data[j])->isFuncDeclaration();
808                     if (!fd2->ident->equals(fd->ident))
809                         continue;
810                     if (fd->leastAsSpecialized(fd2) || fd2->leastAsSpecialized(fd))
811                     {
812                         if (global.params.warnings)
813                         {
814                             TypeFunction *tf = (TypeFunction *)fd->type;
815                             if (tf->ty == Tfunction)
816                                 error("%s%s is hidden by %s\n", fd->toPrettyChars(), Parameter::argsTypesToChars(tf->parameters, tf->varargs), toChars());
817                             else
818                                 error("%s is hidden by %s\n", fd->toPrettyChars(), toChars());
819                         }
820                         s = rtlsym[RTLSYM_DHIDDENFUNC];
821                         break;
822                     }
823                 }
824             }
825 #endif
826             dtxoff(&dt, s, 0, TYnptr);
827         }
828         else
829             dtsize_t(&dt, 0);
830     }
831     vtblsym->Sdt = dt;
832     vtblsym->Sclass = scclass;
833     vtblsym->Sfl = FLdata;
834 #if ELFOBJ
835     vtblsym->Sseg = CDATA;
836 #endif
837 #if MACHOBJ
838     vtblsym->Sseg = DATA;
839 #endif
840     outdata(vtblsym);
841     if (isExport())
842         obj_export(vtblsym,0);
843 }
844
845 /******************************************
846  * Get offset of base class's vtbl[] initializer from start of csym.
847  * Returns ~0 if not this csym.
848  */
849
850 unsigned ClassDeclaration::baseVtblOffset(BaseClass *bc)
851 {
852     unsigned csymoffset;
853     int i;
854
855     //printf("ClassDeclaration::baseVtblOffset('%s', bc = %p)\n", toChars(), bc);
856     csymoffset = global.params.isX86_64 ? CLASSINFO_SIZE_64 : CLASSINFO_SIZE;    // must be ClassInfo.size
857     csymoffset += vtblInterfaces->dim * (4 * PTRSIZE);
858
859     for (i = 0; i < vtblInterfaces->dim; i++)
860     {
861         BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
862
863         if (b == bc)
864             return csymoffset;
865         csymoffset += b->base->vtbl.dim * PTRSIZE;
866     }
867
868 #if 1
869     // Put out the overriding interface vtbl[]s.
870     // This must be mirrored with ClassDeclaration::baseVtblOffset()
871     //printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset);
872     ClassDeclaration *cd;
873     Array bvtbl;
874
875     for (cd = this->baseClass; cd; cd = cd->baseClass)
876     {
877         for (int k = 0; k < cd->vtblInterfaces->dim; k++)
878         {   BaseClass *bs = (BaseClass *)cd->vtblInterfaces->data[k];
879
880             if (bs->fillVtbl(this, NULL, 0))
881             {
882                 if (bc == bs)
883                 {   //printf("\tcsymoffset = x%x\n", csymoffset);
884                     return csymoffset;
885                 }
886                 csymoffset += bs->base->vtbl.dim * PTRSIZE;
887             }
888         }
889     }
890 #endif
891 #if INTERFACE_VIRTUAL
892     for (i = 0; i < vtblInterfaces->dim; i++)
893     {   BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
894         ClassDeclaration *cd;
895
896         for (cd = this->baseClass; cd; cd = cd->baseClass)
897         {
898             //printf("\tbase class %s\n", cd->toChars());
899             for (int k = 0; k < cd->vtblInterfaces->dim; k++)
900             {   BaseClass *bs = (BaseClass *)cd->vtblInterfaces->data[k];
901
902                 if (bc == bs)
903                 {   //printf("\tcsymoffset = x%x\n", csymoffset);
904                     return csymoffset;
905                 }
906                 if (b->base == bs->base)
907                     csymoffset += bs->base->vtbl.dim * PTRSIZE;
908             }
909         }
910     }
911 #endif
912
913     return ~0;
914 }
915
916 /* ================================================================== */
917
918 void InterfaceDeclaration::toObjFile(int multiobj)
919 {   unsigned i;
920     unsigned offset;
921     Symbol *sinit;
922     enum_SC scclass;
923
924     //printf("InterfaceDeclaration::toObjFile('%s')\n", toChars());
925
926     if (!members)
927         return;
928
929     if (global.params.symdebug)
930         toDebug();
931
932     scclass = SCglobal;
933     if (inTemplateInstance())
934         scclass = SCcomdat;
935
936     // Put out the members
937     for (i = 0; i < members->dim; i++)
938     {   Dsymbol *member = (Dsymbol *)members->data[i];
939
940         member->toObjFile(0);
941     }
942
943     // Generate C symbols
944     toSymbol();
945
946     //////////////////////////////////////////////
947
948     // Put out the TypeInfo
949     type->getTypeInfo(NULL);
950     type->vtinfo->toObjFile(multiobj);
951
952     //////////////////////////////////////////////
953
954     // Put out the ClassInfo
955     csym->Sclass = scclass;
956     csym->Sfl = FLdata;
957
958     /* The layout is:
959        {
960             void **vptr;
961             monitor_t monitor;
962             byte[] initializer;         // static initialization data
963             char[] name;                // class name
964             void *[] vtbl;
965             Interface[] interfaces;
966             Object *base;               // base class
967             void *destructor;
968             void *invariant;            // class invariant
969             uint flags;
970             void *deallocator;
971             OffsetTypeInfo[] offTi;
972             void *defaultConstructor;
973 #if DMDV2
974             const(MemberInfo[]) function(string) xgetMembers;   // module getMembers() function
975 #endif
976             //TypeInfo typeinfo;
977        }
978      */
979     dt_t *dt = NULL;
980
981     if (classinfo)
982         dtxoff(&dt, classinfo->toVtblSymbol(), 0, TYnptr); // vtbl for ClassInfo
983     else
984         dtsize_t(&dt, 0);                // BUG: should be an assert()
985     dtsize_t(&dt, 0);                    // monitor
986
987     // initializer[]
988     dtsize_t(&dt, 0);                    // size
989     dtsize_t(&dt, 0);                    // initializer
990
991     // name[]
992     const char *name = toPrettyChars();
993     size_t namelen = strlen(name);
994     dtsize_t(&dt, namelen);
995     dtabytes(&dt, TYnptr, 0, namelen + 1, name);
996
997     // vtbl[]
998     dtsize_t(&dt, 0);
999     dtsize_t(&dt, 0);
1000
1001     // vtblInterfaces->data[]
1002     dtsize_t(&dt, vtblInterfaces->dim);
1003     if (vtblInterfaces->dim)
1004     {
1005         offset = global.params.isX86_64 ? CLASSINFO_SIZE_64 : CLASSINFO_SIZE;    // must be ClassInfo.size
1006         if (classinfo)
1007         {
1008             if (classinfo->structsize != offset)
1009             {
1010                 error("mismatch between dmd and object.d or object.di found. Check installation and import paths with -v compiler switch.");
1011                 fatal();
1012             }
1013         }
1014         dtxoff(&dt, csym, offset, TYnptr);      // (*)
1015     }
1016     else
1017         dtsize_t(&dt, 0);
1018
1019     // base
1020     assert(!baseClass);
1021     dtsize_t(&dt, 0);
1022
1023     // dtor
1024     dtsize_t(&dt, 0);
1025
1026     // invariant
1027     dtsize_t(&dt, 0);
1028
1029     // flags
1030     dtsize_t(&dt, 4 | isCOMinterface() | 32);
1031
1032     // deallocator
1033     dtsize_t(&dt, 0);
1034
1035     // offTi[]
1036     dtsize_t(&dt, 0);
1037     dtsize_t(&dt, 0);            // null for now, fix later
1038
1039     // defaultConstructor
1040     dtsize_t(&dt, 0);
1041
1042 #if DMDV2
1043     // xgetMembers
1044     dtsize_t(&dt, 0);
1045 #endif
1046
1047     //dtxoff(&dt, type->vtinfo->toSymbol(), 0, TYnptr); // typeinfo
1048
1049     //////////////////////////////////////////////
1050
1051     // Put out vtblInterfaces->data[]. Must immediately follow csym, because
1052     // of the fixup (*)
1053
1054     offset += vtblInterfaces->dim * (4 * PTRSIZE);
1055     for (i = 0; i < vtblInterfaces->dim; i++)
1056     {   BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
1057         ClassDeclaration *id = b->base;
1058
1059         // ClassInfo
1060         dtxoff(&dt, id->toSymbol(), 0, TYnptr);
1061
1062         // vtbl[]
1063         dtsize_t(&dt, 0);
1064         dtsize_t(&dt, 0);
1065
1066         // this offset
1067         dtsize_t(&dt, b->offset);
1068     }
1069
1070     csym->Sdt = dt;
1071 #if ELFOBJ
1072     csym->Sseg = CDATA;
1073 #endif
1074 #if MACHOBJ
1075     csym->Sseg = DATA;
1076 #endif
1077     outdata(csym);
1078     if (isExport())
1079         obj_export(csym,0);
1080 }
1081
1082 /* ================================================================== */
1083
1084 void StructDeclaration::toObjFile(int multiobj)
1085 {
1086     //printf("StructDeclaration::toObjFile('%s')\n", toChars());
1087
1088     if (multiobj)
1089     {   obj_append(this);
1090         return;
1091     }
1092
1093     // Anonymous structs/unions only exist as part of others,
1094     // do not output forward referenced structs's
1095     if (!isAnonymous() && members)
1096     {
1097         if (global.params.symdebug)
1098             toDebug();
1099
1100         type->getTypeInfo(NULL);        // generate TypeInfo
1101
1102         if (1)
1103         {
1104             // Generate static initializer
1105             toInitializer();
1106 #if 0
1107             sinit->Sclass = SCcomdat;
1108 #else
1109             if (inTemplateInstance())
1110             {
1111                 sinit->Sclass = SCcomdat;
1112             }
1113             else
1114             {
1115                 sinit->Sclass = SCglobal;
1116             }
1117 #endif
1118             sinit->Sfl = FLdata;
1119             toDt(&sinit->Sdt);
1120
1121 #if OMFOBJ
1122             /* For OMF, common blocks aren't pulled in from the library.
1123              */
1124             /* ELF comdef's generate multiple
1125              * definition errors for them from the gnu linker.
1126              * Need to figure out how to generate proper comdef's for ELF.
1127              */
1128             // See if we can convert a comdat to a comdef,
1129             // which saves on exe file space.
1130             if (0 &&  // causes multiple def problems with COMMON in one file and COMDAT in library
1131                 sinit->Sclass == SCcomdat &&
1132                 sinit->Sdt &&
1133                 sinit->Sdt->dt == DT_azeros &&
1134                 sinit->Sdt->DTnext == NULL &&
1135                 !global.params.multiobj)
1136             {
1137                 sinit->Sclass = SCglobal;
1138                 sinit->Sdt->dt = DT_common;
1139             }
1140 #endif
1141
1142 #if ELFOBJ
1143             sinit->Sseg = CDATA;
1144 #endif
1145 #if MACHOBJ
1146             sinit->Sseg = DATA;
1147 #endif
1148             outdata(sinit);
1149         }
1150
1151         // Put out the members
1152         for (unsigned i = 0; i < members->dim; i++)
1153         {
1154             Dsymbol *member;
1155
1156             member = (Dsymbol *)members->data[i];
1157             member->toObjFile(0);
1158         }
1159     }
1160 }
1161
1162 /* ================================================================== */
1163
1164 void VarDeclaration::toObjFile(int multiobj)
1165 {
1166     Symbol *s;
1167     unsigned sz;
1168     Dsymbol *parent;
1169
1170     //printf("VarDeclaration::toObjFile(%p '%s' type=%s) protection %d\n", this, toChars(), type->toChars(), protection);
1171     //printf("\talign = %d\n", type->alignsize());
1172
1173     if (aliassym)
1174     {   toAlias()->toObjFile(0);
1175         return;
1176     }
1177
1178 #if DMDV2
1179     // Do not store variables we cannot take the address of
1180     if (!canTakeAddressOf())
1181     {
1182         return;
1183     }
1184 #endif
1185
1186     if (isDataseg() && !(storage_class & STCextern))
1187     {
1188         s = toSymbol();
1189         sz = type->size();
1190
1191         parent = this->toParent();
1192 #if DMDV1       /* private statics should still get a global symbol, in case
1193          * another module inlines a function that references it.
1194          */
1195         if (/*protection == PROTprivate ||*/
1196             !parent || parent->ident == NULL || parent->isFuncDeclaration())
1197         {
1198             s->Sclass = SCstatic;
1199         }
1200         else
1201 #endif
1202         {
1203             if (storage_class & STCcomdat)
1204                 s->Sclass = SCcomdat;
1205             else
1206                 s->Sclass = SCglobal;
1207
1208             do
1209             {
1210                 /* Global template data members need to be in comdat's
1211                  * in case multiple .obj files instantiate the same
1212                  * template with the same types.
1213                  */
1214                 if (parent->isTemplateInstance() && !parent->isTemplateMixin())
1215                 {
1216 #if DMDV1
1217                     /* These symbol constants have already been copied,
1218                      * so no reason to output them.
1219                      * Note that currently there is no way to take
1220                      * the address of such a const.
1221                      */
1222                     if (isConst() && type->toBasetype()->ty != Tsarray &&
1223                         init && init->isExpInitializer())
1224                         return;
1225 #endif
1226                     s->Sclass = SCcomdat;
1227                     break;
1228                 }
1229                 parent = parent->parent;
1230             } while (parent);
1231         }
1232         s->Sfl = FLdata;
1233
1234         if (init)
1235         {   s->Sdt = init->toDt();
1236
1237             // Look for static array that is block initialized
1238             Type *tb;
1239             ExpInitializer *ie = init->isExpInitializer();
1240
1241             tb = type->toBasetype();
1242             if (tb->ty == Tsarray && ie &&
1243                 !tb->nextOf()->equals(ie->exp->type->toBasetype()->nextOf()) &&
1244                 ie->exp->implicitConvTo(tb->nextOf())
1245                 )
1246             {
1247                 size_t dim = ((TypeSArray *)tb)->dim->toInteger();
1248
1249                 // Duplicate Sdt 'dim-1' times, as we already have the first one
1250                 dt_t **pdt = &s->Sdt;
1251                 while (--dim > 0)
1252                 {
1253                     pdt = ie->exp->toDt(pdt);
1254                 }
1255             }
1256         }
1257         else if (storage_class & STCextern)
1258         {
1259             s->Sclass = SCextern;
1260             s->Sfl = FLextern;
1261             s->Sdt = NULL;
1262             // BUG: if isExport(), shouldn't we make it dllimport?
1263             return;
1264         }
1265         else
1266         {
1267             type->toDt(&s->Sdt);
1268         }
1269         dt_optimize(s->Sdt);
1270
1271         // See if we can convert a comdat to a comdef,
1272         // which saves on exe file space.
1273         if (s->Sclass == SCcomdat &&
1274             s->Sdt &&
1275             s->Sdt->dt == DT_azeros &&
1276             s->Sdt->DTnext == NULL &&
1277             !isThreadlocal())
1278         {
1279             s->Sclass = SCglobal;
1280             s->Sdt->dt = DT_common;
1281         }
1282
1283 #if ELFOBJ || MACHOBJ // Burton
1284         if (s->Sdt && s->Sdt->dt == DT_azeros && s->Sdt->DTnext == NULL)
1285             s->Sseg = UDATA;
1286         else
1287             s->Sseg = DATA;
1288 #endif
1289         if (sz)
1290         {   outdata(s);
1291             if (isExport())
1292                 obj_export(s,0);
1293         }
1294     }
1295 }
1296
1297 /* ================================================================== */
1298
1299 void TypedefDeclaration::toObjFile(int multiobj)
1300 {
1301     //printf("TypedefDeclaration::toObjFile('%s')\n", toChars());
1302
1303     if (global.params.symdebug)
1304         toDebug();
1305
1306     type->getTypeInfo(NULL);    // generate TypeInfo
1307
1308     TypeTypedef *tc = (TypeTypedef *)type;
1309     if (type->isZeroInit() || !tc->sym->init)
1310         ;
1311     else
1312     {
1313         enum_SC scclass = SCglobal;
1314         if (inTemplateInstance())
1315             scclass = SCcomdat;
1316
1317         // Generate static initializer
1318         toInitializer();
1319         sinit->Sclass = scclass;
1320         sinit->Sfl = FLdata;
1321 #if ELFOBJ // Burton
1322         sinit->Sseg = CDATA;
1323 #endif
1324 #if MACHOBJ
1325         sinit->Sseg = DATA;
1326 #endif
1327         sinit->Sdt = tc->sym->init->toDt();
1328         outdata(sinit);
1329     }
1330 }
1331
1332 /* ================================================================== */
1333
1334 void EnumDeclaration::toObjFile(int multiobj)
1335 {
1336     //printf("EnumDeclaration::toObjFile('%s')\n", toChars());
1337
1338 #if DMDV2
1339     if (isAnonymous())
1340         return;
1341 #endif
1342
1343     if (global.params.symdebug)
1344         toDebug();
1345
1346     type->getTypeInfo(NULL);    // generate TypeInfo
1347
1348     TypeEnum *tc = (TypeEnum *)type;
1349     if (!tc->sym->defaultval || type->isZeroInit())
1350         ;
1351     else
1352     {
1353         enum_SC scclass = SCglobal;
1354         if (inTemplateInstance())
1355             scclass = SCcomdat;
1356
1357         // Generate static initializer
1358         toInitializer();
1359         sinit->Sclass = scclass;
1360         sinit->Sfl = FLdata;
1361 #if ELFOBJ // Burton
1362         sinit->Sseg = CDATA;
1363 #endif
1364 #if MACHOBJ
1365         sinit->Sseg = DATA;
1366 #endif
1367 #if DMDV1
1368         dtnbytes(&sinit->Sdt, tc->size(0), (char *)&tc->sym->defaultval);
1369         //sinit->Sdt = tc->sym->init->toDt();
1370 #endif
1371 #if DMDV2
1372         tc->sym->defaultval->toDt(&sinit->Sdt);
1373 #endif
1374         outdata(sinit);
1375     }
1376 }
Note: See TracBrowser for help on using the browser.