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