Fixed some lexing problems with DOS line-endings
[delight/core.git] / dmd2 / toobj.c
blob0f6f37a7b29d27ed83b7c6d130668ffb6e4a42df
2 // Copyright (c) 1999-2008 by Digital Mars
3 // All Rights Reserved
4 // written by Walter Bright
5 // http://www.digitalmars.com
6 // License for redistribution is by either the Artistic License
7 // in artistic.txt, or the GNU General Public License in gnu.txt.
8 // See the included readme.txt for details.
10 /* NOTE: This file has been patched from the original DMD distribution to
11 work with the GDC compiler.
13 Modified by David Friedman, September 2004
16 #include <stdio.h>
17 #include <stddef.h>
18 #include <time.h>
19 #include <assert.h>
21 #include "mars.h"
22 #include "module.h"
23 #include "mtype.h"
24 #include "declaration.h"
25 #include "statement.h"
26 #include "enum.h"
27 #include "aggregate.h"
28 #include "init.h"
29 #include "attrib.h"
30 #include "id.h"
31 #include "import.h"
32 #include "template.h"
34 #include <mem.h>
35 #ifndef IN_GCC
36 #include "cc.h"
37 #include "global.h"
38 #include "oper.h"
39 #include "code.h"
40 #include "type.h"
41 #include "dt.h"
42 #include "cgcv.h"
43 #include "outbuf.h"
44 #include "irstate.h"
45 #else
46 #include "dt.h"
47 #endif
49 #ifdef IN_GCC
50 #include "d-dmd-gcc.h"
51 #endif
53 void obj_lzext(Symbol *s1,Symbol *s2);
55 #ifdef IN_GCC
56 #if 0
57 static bool m_in_a(Module * m, Array * a) {
58 for (unsigned i = 0; i < a->dim; i++)
59 if ( m == (Module *) a->data[i] )
60 return true;
61 return false;
63 static void find_module_deps(Module * the_module, Array * out_deps)
65 Array work;
66 unsigned wi = 0;
68 work.push(the_module);
69 while (wi < work.dim) {
70 Module * a_module = (Module *) work.data[wi];
71 for (unsigned i = 0; i < a_module->aimports.dim; i++) {
72 Module * an_imp = (Module*) a_module->aimports.data[i];
73 if (! an_imp->needModuleInfo() ||
74 m_in_a(an_imp, & work) || m_in_a(an_imp, out_deps))
75 continue;
76 if (an_imp->strictlyneedmoduleinfo)
78 out_deps->push(an_imp);
79 fprintf(stderr, "idep: %s -> %s", the_module->toPrettyChars(),
80 an_imp->toPrettyChars());
81 if (a_module != the_module)
82 fprintf(stderr, " (via %s)", a_module->toPrettyChars());
83 fprintf(stderr, "\n");
85 else
86 work.push(an_imp);
88 wi++;
91 #endif
92 #endif
95 /* ================================================================== */
97 // Put out instance of ModuleInfo for this Module
99 void Module::genmoduleinfo()
101 //printf("Module::genmoduleinfo() %s\n", toChars());
103 Symbol *msym = toSymbol();
104 unsigned offset;
105 unsigned sizeof_ModuleInfo = 14 * PTRSIZE;
107 //////////////////////////////////////////////
109 csym->Sclass = SCglobal;
110 csym->Sfl = FLdata;
112 /* The layout is:
114 void **vptr;
115 monitor_t monitor;
116 char[] name; // class name
117 ModuleInfo importedModules[];
118 ClassInfo localClasses[];
119 uint flags; // initialization state
120 void *ctor;
121 void *dtor;
122 void *unitTest;
123 const(MemberInfo[]) function(string) xgetMembers; // module getMembers() function
124 void *ictor;
127 dt_t *dt = NULL;
129 if (moduleinfo)
130 dtxoff(&dt, moduleinfo->toVtblSymbol(), 0, TYnptr); // vtbl for ModuleInfo
131 else
132 { //printf("moduleinfo is null\n");
133 dtdword(&dt, 0); // BUG: should be an assert()
135 dtdword(&dt, 0); // monitor
137 // name[]
138 char *name = toPrettyChars();
139 size_t namelen = strlen(name);
140 dtdword(&dt, namelen);
141 dtabytes(&dt, TYnptr, 0, namelen + 1, name);
143 ClassDeclarations aclasses;
145 //printf("members->dim = %d\n", members->dim);
146 for (int i = 0; i < members->dim; i++)
147 { Dsymbol *member = (Dsymbol *)members->data[i];
149 //printf("\tmember '%s'\n", member->toChars());
150 member->addLocalClass(&aclasses);
153 // importedModules[]
154 int aimports_dim = aimports.dim;
155 #ifdef IN_GCC
156 #if 0
157 Array adeps;
159 if (! d_gcc_supports_weak())
161 find_module_deps(this, & adeps);
162 aimports_dim = adeps.dim;
164 else
165 #endif
166 #endif
167 for (int i = 0; i < aimports.dim; i++)
168 { Module *m = (Module *)aimports.data[i];
169 if (!m->needModuleInfo())
170 aimports_dim--;
172 dtdword(&dt, aimports_dim);
173 if (aimports.dim)
174 dtxoff(&dt, csym, sizeof_ModuleInfo, TYnptr);
175 else
176 dtdword(&dt, 0);
178 // localClasses[]
179 dtdword(&dt, aclasses.dim);
180 if (aclasses.dim)
181 dtxoff(&dt, csym, sizeof_ModuleInfo + aimports_dim * PTRSIZE, TYnptr);
182 else
183 dtdword(&dt, 0);
185 if (needmoduleinfo)
186 dti32(&dt, 8|0, true); // flags (4 means MIstandalone)
187 else
188 dti32(&dt, 8|4, true); // flags (4 means MIstandalone)
190 if (sctor)
191 dtxoff(&dt, sctor, 0, TYnptr);
192 else
193 dtdword(&dt, 0);
195 if (sdtor)
196 dtxoff(&dt, sdtor, 0, TYnptr);
197 else
198 dtdword(&dt, 0);
200 if (stest)
201 dtxoff(&dt, stest, 0, TYnptr);
202 else
203 dtdword(&dt, 0);
205 FuncDeclaration *sgetmembers = findGetMembers();
206 if (sgetmembers)
207 dtxoff(&dt, sgetmembers->toSymbol(), 0, TYnptr);
208 else
209 dtdword(&dt, 0); // xgetMembers
211 if (sictor)
212 dtxoff(&dt, sictor, 0, TYnptr);
213 else
214 dtdword(&dt, 0);
216 //////////////////////////////////////////////
218 #ifdef IN_GCC
219 #if 0
220 if (! d_gcc_supports_weak())
221 for (i = 0; i < adeps.dim; i++)
223 Module *m;
224 Symbol *s;
226 m = (Module *) adeps.data[i];
227 s = m->toSymbol();
228 s->Sflags |= SFLweak; // doesn't do anything yet, but see d-decls.cc:Module::toSymbol
229 dtxoff(&dt, s, 0, TYnptr);
231 else
232 #endif
233 #endif
234 for (int i = 0; i < aimports.dim; i++)
235 { Module *m = (Module *)aimports.data[i];
237 if (m->needModuleInfo())
238 { Symbol *s = m->toSymbol();
239 s->Sflags |= SFLweak;
240 dtxoff(&dt, s, 0, TYnptr);
244 for (int i = 0; i < aclasses.dim; i++)
246 ClassDeclaration *cd = (ClassDeclaration *)aclasses.data[i];
247 dtxoff(&dt, cd->toSymbol(), 0, TYnptr);
250 csym->Sdt = dt;
251 #if ELFOBJ
252 // Cannot be CONST because the startup code sets flag bits in it
253 csym->Sseg = DATA;
254 #endif
255 outdata(csym);
257 //////////////////////////////////////////////
259 obj_moduleinfo(msym);
262 /* ================================================================== */
263 void Dsymbol::toObjFile(int multiobj)
265 //printf("Dsymbol::toObjFile('%s')\n", toChars());
266 // ignore
267 #ifdef IN_GCC
268 TupleDeclaration * td = this->isTupleDeclaration();
269 if (td)
271 for (unsigned i = 0; i < td->objects->dim; i++)
273 Object * o = (Object *) td->objects->data[i];
274 Expression * e;
275 Dsymbol *ds;
276 Declaration *d;
277 if ((o->dyncast() == DYNCAST_EXPRESSION) &&
278 ((Expression *) o)->op == TOKdsymbol)
280 ds = ((DsymbolExp *) o)->s;
281 d = ds->isDeclaration();
282 if (d)
283 d->toObjFile(multiobj);
288 #endif
290 /* ================================================================== */
292 void ClassDeclaration::toObjFile(int multiobj)
293 { unsigned i;
294 unsigned offset;
295 Symbol *sinit;
296 enum_SC scclass;
298 //printf("ClassDeclaration::toObjFile('%s')\n", toChars());
300 if (!members)
301 return;
303 if (global.params.symdebug)
304 toDebug();
306 assert(!scope); // semantic() should have been run to completion
308 if (parent && parent->isTemplateInstance())
309 scclass = SCcomdat;
310 else
311 scclass = SCglobal;
313 // Put out the members
314 for (i = 0; i < members->dim; i++)
316 Dsymbol *member;
318 member = (Dsymbol *)members->data[i];
319 member->toObjFile(0);
322 #if 0
323 // Build destructor by aggregating dtors[]
324 Symbol *sdtor;
325 switch (dtors.dim)
326 { case 0:
327 // No destructors for this class
328 sdtor = NULL;
329 break;
331 case 1:
332 // One destructor, just use it directly
333 sdtor = ((DtorDeclaration *)dtors.data[0])->toSymbol();
334 break;
336 default:
337 { /* Build a destructor that calls all the
338 * other destructors in dtors[].
341 elem *edtor = NULL;
343 // Declare 'this' pointer for our new destructor
344 Symbol *sthis = symbol_calloc("this");
345 sthis->Stype = type_fake(TYnptr);
346 sthis->Stype->Tcount++;
347 sthis->Sclass = SCfastpar;
348 sthis->Spreg = AX;
349 sthis->Sfl = FLauto;
351 // Call each of the destructors in dtors[]
352 // in reverse order
353 for (i = 0; i < dtors.dim; i++)
354 { DtorDeclaration *d = (DtorDeclaration *)dtors.data[i];
355 Symbol *s = d->toSymbol();
356 elem *e;
358 e = el_bin(OPcall, TYvoid, el_var(s), el_var(sthis));
359 edtor = el_combine(e, edtor);
362 // Create type for the function
363 ::type *t = type_alloc(TYjfunc);
364 t->Tflags |= TFprototype | TFfixed;
365 t->Tmangle = mTYman_d;
366 t->Tnext = tsvoid;
367 tsvoid->Tcount++;
369 // Create the function, sdtor, and write it out
370 localgot = NULL;
371 sdtor = toSymbolX("__dtor", SCglobal, t, "FZv");
372 block *b = block_calloc();
373 b->BC = BCret;
374 b->Belem = edtor;
375 sdtor->Sfunc->Fstartblock = b;
376 cstate.CSpsymtab = &sdtor->Sfunc->Flocsym;
377 symbol_add(sthis);
378 writefunc(sdtor);
381 #endif
383 // Generate C symbols
384 toSymbol();
385 toVtblSymbol();
386 sinit = toInitializer();
388 //////////////////////////////////////////////
390 // Generate static initializer
391 sinit->Sclass = scclass;
392 sinit->Sfl = FLdata;
393 #if ELFOBJ // Burton
394 sinit->Sseg = CDATA;
395 #endif /* ELFOBJ */
396 toDt(&sinit->Sdt);
397 outdata(sinit);
399 //////////////////////////////////////////////
401 // Put out the ClassInfo
402 csym->Sclass = scclass;
403 csym->Sfl = FLdata;
405 /* The layout is:
407 void **vptr;
408 monitor_t monitor;
409 byte[] initializer; // static initialization data
410 char[] name; // class name
411 void *[] vtbl;
412 Interface[] interfaces;
413 ClassInfo *base; // base class
414 void *destructor;
415 void *invariant; // class invariant
416 uint flags;
417 void *deallocator;
418 OffsetTypeInfo[] offTi;
419 void *defaultConstructor;
420 const(MemberInfo[]) function(string) xgetMembers; // module getMembers() function
423 dt_t *dt = NULL;
424 offset = CLASSINFO_SIZE; // must be ClassInfo.size
425 if (classinfo)
427 if (classinfo->structsize != CLASSINFO_SIZE)
428 error("D compiler and phobos/object.d are mismatched");
431 if (classinfo)
432 dtxoff(&dt, classinfo->toVtblSymbol(), 0, TYnptr); // vtbl for ClassInfo
433 else
434 dtdword(&dt, 0); // BUG: should be an assert()
435 dtdword(&dt, 0); // monitor
437 // initializer[]
438 assert(structsize >= 8);
439 dtdword(&dt, structsize); // size
440 dtxoff(&dt, sinit, 0, TYnptr); // initializer
442 // name[]
443 char *name = ident->toChars();
444 size_t namelen = strlen(name);
445 if (!(namelen > 9 && memcmp(name, "TypeInfo_", 9) == 0))
446 { name = toPrettyChars();
447 namelen = strlen(name);
449 dtdword(&dt, namelen);
450 dtabytes(&dt, TYnptr, 0, namelen + 1, name);
452 // vtbl[]
453 dtdword(&dt, vtbl.dim);
454 dtxoff(&dt, vtblsym, 0, TYnptr);
456 // interfaces[]
457 dtdword(&dt, vtblInterfaces->dim);
458 if (vtblInterfaces->dim)
459 dtxoff(&dt, csym, offset, TYnptr); // (*)
460 else
461 dtdword(&dt, 0);
463 // base
464 if (baseClass)
465 dtxoff(&dt, baseClass->toSymbol(), 0, TYnptr);
466 else
467 dtdword(&dt, 0);
469 // destructor
470 if (dtor)
471 dtxoff(&dt, dtor->toSymbol(), 0, TYnptr);
472 else
473 dtdword(&dt, 0);
475 // invariant
476 if (inv)
477 dtxoff(&dt, inv->toSymbol(), 0, TYnptr);
478 else
479 dtdword(&dt, 0);
481 // flags
482 int flags = 16 | 4 | isCOMclass();
483 if (ctor)
484 flags |= 8;
485 for (ClassDeclaration *cd = this; cd; cd = cd->baseClass)
487 if (cd->members)
489 for (size_t i = 0; i < cd->members->dim; i++)
491 Dsymbol *sm = (Dsymbol *)cd->members->data[i];
492 //printf("sm = %s %s\n", sm->kind(), sm->toChars());
493 if (sm->hasPointers())
494 goto L2;
498 flags |= 2; // no pointers
500 dti32(&dt, flags, true);
503 // deallocator
504 if (aggDelete)
505 dtxoff(&dt, aggDelete->toSymbol(), 0, TYnptr);
506 else
507 dtdword(&dt, 0);
509 // offTi[]
510 dtdword(&dt, 0);
511 dtdword(&dt, 0); // null for now, fix later
513 // defaultConstructor
514 if (defaultCtor)
515 dtxoff(&dt, defaultCtor->toSymbol(), 0, TYnptr);
516 else
517 dtdword(&dt, 0);
519 FuncDeclaration *sgetmembers = findGetMembers();
520 if (sgetmembers)
521 dtxoff(&dt, sgetmembers->toSymbol(), 0, TYnptr);
522 else
523 dtdword(&dt, 0); // module getMembers() function
525 //////////////////////////////////////////////
527 // Put out vtblInterfaces->data[]. Must immediately follow csym, because
528 // of the fixup (*)
530 offset += vtblInterfaces->dim * (4 * PTRSIZE);
531 for (i = 0; i < vtblInterfaces->dim; i++)
532 { BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
533 ClassDeclaration *id = b->base;
535 /* The layout is:
537 * ClassInfo *interface;
538 * void *[] vtbl;
539 * unsigned offset;
543 // Fill in vtbl[]
544 b->fillVtbl(this, &b->vtbl, 1);
546 dtxoff(&dt, id->toSymbol(), 0, TYnptr); // ClassInfo
548 // vtbl[]
549 dtdword(&dt, id->vtbl.dim);
550 dtxoff(&dt, csym, offset, TYnptr);
552 dtdword(&dt, b->offset); // this offset
554 offset += id->vtbl.dim * PTRSIZE;
557 // Put out the vtblInterfaces->data[].vtbl[]
558 // This must be mirrored with ClassDeclaration::baseVtblOffset()
559 //printf("putting out %d interface vtbl[]s for '%s'\n", vtblInterfaces->dim, toChars());
560 for (i = 0; i < vtblInterfaces->dim; i++)
561 { BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
562 ClassDeclaration *id = b->base;
563 int j;
565 //printf(" interface[%d] is '%s'\n", i, id->toChars());
566 j = 0;
567 if (id->vtblOffset())
569 // First entry is ClassInfo reference
570 //dtxoff(&dt, id->toSymbol(), 0, TYnptr);
572 // First entry is struct Interface reference
573 dtxoff(&dt, csym, CLASSINFO_SIZE + i * (4 * PTRSIZE), TYnptr);
574 j = 1;
576 assert(id->vtbl.dim == b->vtbl.dim);
577 for (; j < id->vtbl.dim; j++)
579 FuncDeclaration *fd;
581 assert(j < b->vtbl.dim);
582 #if 0
583 Object *o = (Object *)b->vtbl.data[j];
584 if (o)
586 printf("o = %p\n", o);
587 assert(o->dyncast() == DYNCAST_DSYMBOL);
588 Dsymbol *s = (Dsymbol *)o;
589 printf("s->kind() = '%s'\n", s->kind());
591 #endif
592 fd = (FuncDeclaration *)b->vtbl.data[j];
593 if (fd)
594 dtxoff(&dt, fd->toThunkSymbol(b->offset), 0, TYnptr);
595 else
596 dtdword(&dt, 0);
600 #if 1
601 // Put out the overriding interface vtbl[]s.
602 // This must be mirrored with ClassDeclaration::baseVtblOffset()
603 //printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset);
604 ClassDeclaration *cd;
605 Array bvtbl;
607 for (cd = this->baseClass; cd; cd = cd->baseClass)
609 for (int k = 0; k < cd->vtblInterfaces->dim; k++)
610 { BaseClass *bs = (BaseClass *)cd->vtblInterfaces->data[k];
612 if (bs->fillVtbl(this, &bvtbl, 0))
614 //printf("\toverriding vtbl[] for %s\n", bs->base->toChars());
615 ClassDeclaration *id = bs->base;
616 int j;
618 j = 0;
619 if (id->vtblOffset())
621 // First entry is ClassInfo reference
622 //dtxoff(&dt, id->toSymbol(), 0, TYnptr);
624 // First entry is struct Interface reference
625 dtxoff(&dt, cd->toSymbol(), CLASSINFO_SIZE + k * (4 * PTRSIZE), TYnptr);
626 j = 1;
629 for (; j < id->vtbl.dim; j++)
631 FuncDeclaration *fd;
633 assert(j < bvtbl.dim);
634 fd = (FuncDeclaration *)bvtbl.data[j];
635 if (fd)
636 dtxoff(&dt, fd->toThunkSymbol(bs->offset), 0, TYnptr);
637 else
638 dtdword(&dt, 0);
643 #endif
644 #if INTERFACE_VIRTUAL
645 // Put out the overriding interface vtbl[]s.
646 // This must be mirrored with ClassDeclaration::baseVtblOffset()
647 //printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset);
648 for (i = 0; i < vtblInterfaces->dim; i++)
649 { BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
650 ClassDeclaration *cd;
652 for (cd = this->baseClass; cd; cd = cd->baseClass)
654 for (int k = 0; k < cd->vtblInterfaces->dim; k++)
655 { BaseClass *bs = (BaseClass *)cd->vtblInterfaces->data[k];
657 if (b->base == bs->base)
659 //printf("\toverriding vtbl[] for %s\n", b->base->toChars());
660 ClassDeclaration *id = b->base;
661 int j;
663 j = 0;
664 if (id->vtblOffset())
666 // First entry is ClassInfo reference
667 //dtxoff(&dt, id->toSymbol(), 0, TYnptr);
669 // First entry is struct Interface reference
670 dtxoff(&dt, cd->toSymbol(), CLASSINFO_SIZE + k * (4 * PTRSIZE), TYnptr);
671 j = 1;
674 for (; j < id->vtbl.dim; j++)
676 FuncDeclaration *fd;
678 assert(j < b->vtbl.dim);
679 fd = (FuncDeclaration *)b->vtbl.data[j];
680 if (fd)
681 dtxoff(&dt, fd->toThunkSymbol(bs->offset), 0, TYnptr);
682 else
683 dtdword(&dt, 0);
689 #endif
692 csym->Sdt = dt;
693 #if ELFOBJ // Burton
694 // ClassInfo cannot be const data, because we use the monitor on it
695 csym->Sseg = DATA;
696 #endif /* ELFOBJ */
697 outdata(csym);
698 if (isExport())
699 obj_export(csym,0);
701 //////////////////////////////////////////////
703 // Put out the vtbl[]
704 //printf("putting out %s.vtbl[]\n", toChars());
705 dt = NULL;
706 if (0)
707 i = 0;
708 else
709 { dtxoff(&dt, csym, 0, TYnptr); // first entry is ClassInfo reference
710 i = 1;
712 for (; i < vtbl.dim; i++)
714 FuncDeclaration *fd = ((Dsymbol *)vtbl.data[i])->isFuncDeclaration();
716 //printf("\tvtbl[%d] = %p\n", i, fd);
717 if (fd && (fd->fbody || !isAbstract()))
719 if (isFuncHidden(fd))
721 if (global.params.warnings)
722 { fprintf(stdmsg, "warning - ");
723 error("%s %s is hidden in %s\n", fd->toParent()->toChars(), fd->toChars(), toChars());
725 dtxoff(&dt, rtlsym[RTLSYM_DHIDDENFUNC], 0, TYnptr);
727 else
728 dtxoff(&dt, fd->toSymbol(), 0, TYnptr);
730 else
731 dtdword(&dt, 0);
733 vtblsym->Sdt = dt;
734 vtblsym->Sclass = scclass;
735 vtblsym->Sfl = FLdata;
736 #if ELFOBJ // Burton
737 vtblsym->Sseg = CDATA;
738 #endif /* ELFOBJ */
739 outdata(vtblsym);
740 if (isExport())
741 obj_export(vtblsym,0);
744 /******************************************
745 * Get offset of base class's vtbl[] initializer from start of csym.
746 * Returns ~0 if not this csym.
749 unsigned ClassDeclaration::baseVtblOffset(BaseClass *bc)
751 unsigned csymoffset;
752 int i;
754 //printf("ClassDeclaration::baseVtblOffset('%s', bc = %p)\n", toChars(), bc);
755 csymoffset = CLASSINFO_SIZE;
756 csymoffset += vtblInterfaces->dim * (4 * PTRSIZE);
758 for (i = 0; i < vtblInterfaces->dim; i++)
760 BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
762 if (b == bc)
763 return csymoffset;
764 csymoffset += b->base->vtbl.dim * PTRSIZE;
767 #if 1
768 // Put out the overriding interface vtbl[]s.
769 // This must be mirrored with ClassDeclaration::baseVtblOffset()
770 //printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset);
771 ClassDeclaration *cd;
772 Array bvtbl;
774 for (cd = this->baseClass; cd; cd = cd->baseClass)
776 for (int k = 0; k < cd->vtblInterfaces->dim; k++)
777 { BaseClass *bs = (BaseClass *)cd->vtblInterfaces->data[k];
779 if (bs->fillVtbl(this, NULL, 0))
781 if (bc == bs)
782 { //printf("\tcsymoffset = x%x\n", csymoffset);
783 return csymoffset;
785 csymoffset += bs->base->vtbl.dim * PTRSIZE;
789 #endif
790 #if INTERFACE_VIRTUAL
791 for (i = 0; i < vtblInterfaces->dim; i++)
792 { BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
793 ClassDeclaration *cd;
795 for (cd = this->baseClass; cd; cd = cd->baseClass)
797 //printf("\tbase class %s\n", cd->toChars());
798 for (int k = 0; k < cd->vtblInterfaces->dim; k++)
799 { BaseClass *bs = (BaseClass *)cd->vtblInterfaces->data[k];
801 if (bc == bs)
802 { //printf("\tcsymoffset = x%x\n", csymoffset);
803 return csymoffset;
805 if (b->base == bs->base)
806 csymoffset += bs->base->vtbl.dim * PTRSIZE;
810 #endif
812 return ~0;
815 /* ================================================================== */
817 void InterfaceDeclaration::toObjFile(int multiobj)
818 { unsigned i;
819 unsigned offset;
820 Symbol *sinit;
821 enum_SC scclass;
823 //printf("InterfaceDeclaration::toObjFile('%s')\n", toChars());
825 if (!members)
826 return;
828 if (global.params.symdebug)
829 toDebug();
831 if (parent && parent->isTemplateInstance())
832 scclass = SCcomdat;
833 else
834 scclass = SCglobal;
836 // Put out the members
837 for (i = 0; i < members->dim; i++)
839 Dsymbol *member;
841 member = (Dsymbol *)members->data[i];
842 if (!member->isFuncDeclaration())
843 member->toObjFile(0);
846 // Generate C symbols
847 toSymbol();
849 //////////////////////////////////////////////
851 // Put out the ClassInfo
852 csym->Sclass = scclass;
853 csym->Sfl = FLdata;
855 /* The layout is:
857 void **vptr;
858 monitor_t monitor;
859 byte[] initializer; // static initialization data
860 char[] name; // class name
861 void *[] vtbl;
862 Interface[] interfaces;
863 Object *base; // base class
864 void *destructor;
865 void *invariant; // class invariant
866 uint flags;
867 void *deallocator;
868 OffsetTypeInfo[] offTi;
869 void *defaultConstructor;
870 const(MemberInfo[]) function(string) xgetMembers; // module getMembers() function
873 dt_t *dt = NULL;
875 if (classinfo)
876 dtxoff(&dt, classinfo->toVtblSymbol(), 0, TYnptr); // vtbl for ClassInfo
877 else
878 dtdword(&dt, 0); // BUG: should be an assert()
879 dtdword(&dt, 0); // monitor
881 // initializer[]
882 dtdword(&dt, 0); // size
883 dtdword(&dt, 0); // initializer
885 // name[]
886 char *name = toPrettyChars();
887 size_t namelen = strlen(name);
888 dtdword(&dt, namelen);
889 dtabytes(&dt, TYnptr, 0, namelen + 1, name);
891 // vtbl[]
892 dtdword(&dt, 0);
893 dtdword(&dt, 0);
895 // vtblInterfaces->data[]
896 dtdword(&dt, vtblInterfaces->dim);
897 if (vtblInterfaces->dim)
899 if (classinfo)
900 assert(classinfo->structsize == CLASSINFO_SIZE);
901 offset = CLASSINFO_SIZE;
902 dtxoff(&dt, csym, offset, TYnptr); // (*)
904 else
905 dtdword(&dt, 0);
907 // base
908 assert(!baseClass);
909 dtdword(&dt, 0);
911 // dtor
912 dtdword(&dt, 0);
914 // invariant
915 dtdword(&dt, 0);
917 // flags
918 dti32(&dt, 4 | isCOMinterface(), true);
920 // deallocator
921 dtdword(&dt, 0);
923 // offTi[]
924 dtdword(&dt, 0);
925 dtdword(&dt, 0); // null for now, fix later
927 // defaultConstructor
928 dtdword(&dt, 0);
930 // xgetMembers
931 dtdword(&dt, 0);
933 //////////////////////////////////////////////
935 // Put out vtblInterfaces->data[]. Must immediately follow csym, because
936 // of the fixup (*)
938 offset += vtblInterfaces->dim * (4 * PTRSIZE);
939 for (i = 0; i < vtblInterfaces->dim; i++)
940 { BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
941 ClassDeclaration *id = b->base;
943 // ClassInfo
944 dtxoff(&dt, id->toSymbol(), 0, TYnptr);
946 // vtbl[]
947 dtdword(&dt, 0);
948 dtdword(&dt, 0);
950 // this offset
951 dtdword(&dt, b->offset);
954 csym->Sdt = dt;
955 #if ELFOBJ // Burton
956 csym->Sseg = CDATA;
957 #endif /* ELFOBJ */
958 outdata(csym);
959 if (isExport())
960 obj_export(csym,0);
963 /* ================================================================== */
965 void StructDeclaration::toObjFile(int multiobj)
966 { unsigned i;
968 //printf("StructDeclaration::toObjFile('%s')\n", toChars());
970 // Anonymous structs/unions only exist as part of others,
971 // do not output forward referenced structs's
972 if (!isAnonymous() && members)
974 if (global.params.symdebug)
975 toDebug();
977 type->getTypeInfo(NULL); // generate TypeInfo
979 if (1)
981 // Generate static initializer
982 toInitializer();
983 #if 0
984 sinit->Sclass = SCcomdat;
985 #else
986 if (parent && parent->isTemplateInstance())
987 sinit->Sclass = SCcomdat;
988 else
989 sinit->Sclass = SCglobal;
990 #endif
991 sinit->Sfl = FLdata;
992 toDt(&sinit->Sdt);
994 #if !ELFOBJ
995 /* For OMF, common blocks aren't pulled in from the library.
997 /* ELF comdef's generate multiple
998 * definition errors for them from the gnu linker.
999 * Need to figure out how to generate proper comdef's for ELF.
1001 // See if we can convert a comdat to a comdef,
1002 // which saves on exe file space.
1003 if (sinit->Sclass == SCcomdat &&
1004 sinit->Sdt &&
1005 sinit->Sdt->dt == DT_azeros &&
1006 sinit->Sdt->DTnext == NULL)
1008 sinit->Sclass = SCglobal;
1009 sinit->Sdt->dt = DT_common;
1011 #endif
1013 #if ELFOBJ // Burton
1014 sinit->Sseg = CDATA;
1015 #endif
1016 outdata(sinit);
1019 // Put out the members
1020 for (i = 0; i < members->dim; i++)
1022 Dsymbol *member;
1024 member = (Dsymbol *)members->data[i];
1025 member->toObjFile(0);
1030 /* ================================================================== */
1032 void VarDeclaration::toObjFile(int multiobj)
1034 Symbol *s;
1035 unsigned sz;
1036 Dsymbol *parent;
1038 //printf("VarDeclaration::toObjFile(%p '%s' type=%s) protection %d\n", this, toChars(), type->toChars(), protection);
1039 //printf("\talign = %d\n", type->alignsize());
1041 if (aliassym)
1042 { toAlias()->toObjFile(0);
1043 return;
1046 // Do not store variables we cannot take the address of
1047 if (!canTakeAddressOf())
1049 return;
1052 if (isDataseg() && !(storage_class & STCextern))
1054 s = toSymbol();
1055 sz = type->size();
1057 parent = this->toParent();
1058 #if 0 /* private statics should still get a global symbol, in case
1059 * another module inlines a function that references it.
1061 if (/*protection == PROTprivate ||*/
1062 !parent || parent->ident == NULL || parent->isFuncDeclaration())
1064 s->Sclass = SCstatic;
1066 else
1067 #endif
1069 if (storage_class & STCcomdat)
1070 s->Sclass = SCcomdat;
1071 else
1072 s->Sclass = SCglobal;
1076 /* Global template data members need to be in comdat's
1077 * in case multiple .obj files instantiate the same
1078 * template with the same types.
1080 if (parent->isTemplateInstance() && !parent->isTemplateMixin())
1082 #if 0
1083 /* These symbol constants have already been copied,
1084 * so no reason to output them.
1085 * Note that currently there is no way to take
1086 * the address of such a const.
1088 if (isConst() && type->toBasetype()->ty != Tsarray &&
1089 init && init->isExpInitializer())
1090 return;
1091 #endif
1092 s->Sclass = SCcomdat;
1093 break;
1095 parent = parent->parent;
1096 } while (parent);
1098 s->Sfl = FLdata;
1100 if (init)
1101 { s->Sdt = init->toDt();
1103 // Look for static array that is block initialized
1104 Type *tb;
1105 ExpInitializer *ie = init->isExpInitializer();
1107 tb = type->toBasetype();
1108 if (tb->ty == Tsarray && ie &&
1109 !tb->nextOf()->equals(ie->exp->type->toBasetype()->nextOf()) &&
1110 ie->exp->implicitConvTo(tb->nextOf())
1113 int dim;
1115 dim = ((TypeSArray *)tb)->dim->toInteger();
1117 // Duplicate Sdt 'dim-1' times, as we already have the first one
1118 while (--dim > 0)
1120 ie->exp->toDt(&s->Sdt);
1124 else if (storage_class & STCextern)
1126 s->Sclass = SCextern;
1127 s->Sfl = FLextern;
1128 s->Sdt = NULL;
1129 // BUG: if isExport(), shouldn't we make it dllimport?
1130 return;
1132 else
1134 type->toDt(&s->Sdt);
1136 dt_optimize(s->Sdt);
1138 // See if we can convert a comdat to a comdef,
1139 // which saves on exe file space.
1140 if (s->Sclass == SCcomdat &&
1141 s->Sdt &&
1142 s->Sdt->dt == DT_azeros &&
1143 s->Sdt->DTnext == NULL)
1145 s->Sclass = SCglobal;
1146 s->Sdt->dt = DT_common;
1149 #if ELFOBJ // Burton
1150 if (s->Sdt && s->Sdt->dt == DT_azeros && s->Sdt->DTnext == NULL)
1151 s->Sseg = UDATA;
1152 else
1153 s->Sseg = DATA;
1154 #endif /* ELFOBJ */
1155 if (sz)
1156 { outdata(s);
1157 if (isExport())
1158 obj_export(s,0);
1161 #ifdef IN_GCC
1162 else {
1163 // This is needed for VarDeclarations in mixins that are to be
1164 // local variables of a function. Otherwise, it would be
1165 // enough to make a check for isVarDeclaration() in
1166 // DeclarationExp::toElem.
1167 d_gcc_emit_local_variable(this);
1169 #endif
1172 /* ================================================================== */
1174 void TypedefDeclaration::toObjFile(int multiobj)
1176 //printf("TypedefDeclaration::toObjFile('%s')\n", toChars());
1178 if (global.params.symdebug)
1179 toDebug();
1181 type->getTypeInfo(NULL); // generate TypeInfo
1183 TypeTypedef *tc = (TypeTypedef *)type;
1184 if (type->isZeroInit() || !tc->sym->init)
1186 else
1188 enum_SC scclass = SCglobal;
1189 for (Dsymbol *parent = this->parent; parent; parent = parent->parent)
1191 if (parent->isTemplateInstance())
1193 scclass = SCcomdat;
1194 break;
1198 // Generate static initializer
1199 toInitializer();
1200 sinit->Sclass = scclass;
1201 sinit->Sfl = FLdata;
1202 #if ELFOBJ // Burton
1203 sinit->Sseg = CDATA;
1204 #endif /* ELFOBJ */
1205 if (! sinit->Sdt)
1206 sinit->Sdt = tc->sym->init->toDt();
1207 outdata(sinit);
1211 /* ================================================================== */
1213 void EnumDeclaration::toObjFile(int multiobj)
1215 //printf("EnumDeclaration::toObjFile('%s')\n", toChars());
1217 if (isAnonymous())
1218 return;
1220 if (global.params.symdebug)
1221 toDebug();
1223 type->getTypeInfo(NULL); // generate TypeInfo
1225 TypeEnum *tc = (TypeEnum *)type;
1226 if (!tc->sym->defaultval || type->isZeroInit())
1228 else
1230 enum_SC scclass = SCglobal;
1231 for (Dsymbol *parent = this->parent; parent; parent = parent->parent)
1233 if (parent->isTemplateInstance())
1235 scclass = SCcomdat;
1236 break;
1240 // Generate static initializer
1241 toInitializer();
1242 sinit->Sclass = scclass;
1243 sinit->Sfl = FLdata;
1244 #if ELFOBJ // Burton
1245 sinit->Sseg = CDATA;
1246 #endif /* ELFOBJ */
1247 tc->sym->defaultval->toDt(&sinit->Sdt);
1248 //sinit->Sdt = tc->sym->init->toDt();
1249 outdata(sinit);