1:
2: // Compiler implementation of the D programming language
3: // Copyright (c) 1999-2011 by Digital Mars
4: // All Rights Reserved
5: // written by Walter Bright
6: // http://www.digitalmars.com
7:
8: #include <stdio.h>
9: #include <stddef.h>
10: #include <time.h>
11: static char __file__[] = __FILE__; /* for tassert.h */
12: #include "tassert.h"
13:
14: #if __sun&&__SVR4
15: #include <alloca.h>
16: #endif
17:
18: #include "mars.h"
19: #include "module.h"
20: #include "mtype.h"
21: #include "declaration.h"
22: #include "statement.h"
23: #include "enum.h"
24: #include "aggregate.h"
25: #include "init.h"
26: #include "attrib.h"
27: #include "id.h"
28: #include "import.h"
29: #include "template.h"
30: #include "lib.h"
31:
32: #include "rmem.h"
33: #include "cc.h"
34: #include "global.h"
35: #include "oper.h"
36: #include "code.h"
37: #include "type.h"
38: #include "dt.h"
39: #include "cgcv.h"
40: #include "outbuf.h"
41: #include "irstate.h"
42:
43: struct Environment;
44:
45: Environment *benv;
46:
47: void out_config_init();
48: void slist_add(Symbol *s);
49: void slist_reset();
50: void clearStringTab();
51:
52: #define STATICCTOR 0
53:
54: elem *eictor;
55: symbol *ictorlocalgot;
56: elem *ector;
57: StaticDtorDeclarations ectorgates;
58: elem *edtor;
59: elem *etest;
60:
61: elem *esharedctor;
62: SharedStaticDtorDeclarations esharedctorgates;
63: elem *eshareddtor;
64:
65: int dtorcount;
66: int shareddtorcount;
67:
68: char *lastmname;
69:
70: /**************************************
71: * Append s to list of object files to generate later.
72: */
73:
74: Dsymbols obj_symbols_towrite;
75:
76: void obj_append(Dsymbol *s)
77: {
78: obj_symbols_towrite.push(s);
79: }
80:
81: void obj_write_deferred(Library *library)
82: {
83: for (int i = 0; i < obj_symbols_towrite.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
84: { Dsymbol *s = obj_symbols_towrite.tdata()[i];
85: Module *m = s->getModule();
86:
87: char *mname;
88: if (m)
89: { mname = m->srcfile->toChars();
90: lastmname = mname;
91: }
92: else
93: {
94: //mname = s->ident->toChars();
95: mname = lastmname;
96: assert(mname);
97: }
98:
99: obj_start(mname);
100:
101: static int count;
102: count++; // sequence for generating names
103:
104: /* Create a module that's a doppelganger of m, with just
105: * enough to be able to create the moduleinfo.
106: */
107: OutBuffer idbuf;
108: idbuf.printf("%s.%d", m ? m->ident->toChars() : mname, count);
109: char *idstr = idbuf.toChars();
110: idbuf.data = NULL;
111: Identifier *id = new Identifier(idstr, TOKidentifier);
112:
113: Module *md = new Module(mname, id, 0, 0);
warning C6211: Leaking memory 'md' due to an exception. Consider using a local catch block to clean up memory: Lines: 83, 84, 85, 87, 88, 89, 90, 99, 101, 102, 107, 108, 109, 110, 111, 113, 114
114: md->members = new Dsymbols();
115: md->members->push(s); // its only 'member' is s
116: if (m)
117: {
118: md->doppelganger = 1; // identify this module as doppelganger
119: md->md = m->md;
120: md->aimports.push(m); // it only 'imports' m
121: md->massert = m->massert;
122: md->munittest = m->munittest;
123: md->marray = m->marray;
124: }
125:
126: md->genobjfile(0);
127:
128: /* Set object file name to be source name with sequence number,
129: * as mangled symbol names get way too long.
130: */
131: char *fname = FileName::removeExt(mname);
132: OutBuffer namebuf;
133: unsigned hash = 0;
134: for (char *p = s->toChars(); *p; p++)
135: hash += *p;
136: namebuf.printf("%s_%x_%x.%s", fname, count, hash, global.obj_ext);
137: namebuf.writeByte(0);
138: mem.free(fname);
139: fname = (char *)namebuf.extractData();
140:
141: //printf("writing '%s'\n", fname);
142: File *objfile = new File(fname);
143: obj_end(library, objfile);
144: }
145: obj_symbols_towrite.dim = 0;
146: }
147:
148: /**************************************
149: * Prepare for generating obj file.
150: */
151:
152: Outbuffer objbuf;
153:
154: void obj_start(char *srcfile)
155: {
156: //printf("obj_start()\n");
157:
158: out_config_init();
159:
160: rtlsym_reset();
161: slist_reset();
162: clearStringTab();
163:
164: obj_init(&objbuf, srcfile, NULL);
165:
166: el_reset();
167: cg87_reset();
168: out_reset();
169: }
170:
171: void obj_end(Library *library, File *objfile)
172: {
173: obj_term();
174:
175: if (library)
176: {
177: // Transfer image to library
178: library->addObject(objfile->name->toChars(), objbuf.buf, objbuf.p - objbuf.buf);
179: objbuf.buf = NULL;
180: }
181: else
182: {
183: // Transfer image to file
184: objfile->setbuffer(objbuf.buf, objbuf.p - objbuf.buf);
185: objbuf.buf = NULL;
186:
187: char *p = FileName::path(objfile->name->toChars());
188: FileName::ensurePathExists(p);
189: //mem.free(p);
190:
191: //printf("write obj %s\n", objfile->name->toChars());
192: objfile->writev();
193: }
194: objbuf.pend = NULL;
195: objbuf.p = NULL;
196: objbuf.len = 0;
197: objbuf.inc = 0;
198: }
199:
200: /**************************************
201: * Generate .obj file for Module.
202: */
203:
204: void Module::genobjfile(int multiobj)
205: {
206: //EEcontext *ee = env->getEEcontext();
207:
208: //printf("Module::genobjfile(multiobj = %d) %s\n", multiobj, toChars());
209:
210: lastmname = srcfile->toChars();
211:
212: obj_initfile(lastmname, NULL, toPrettyChars());
213:
214: eictor = NULL;
215: ictorlocalgot = NULL;
216: ector = NULL;
217: ectorgates.setDim(0);
218: edtor = NULL;
219: esharedctor = NULL;
220: esharedctorgates.setDim(0);
221: eshareddtor = NULL;
222: etest = NULL;
223: dtorcount = 0;
224: shareddtorcount = 0;
225:
226: if (doppelganger)
227: {
228: /* Generate a reference to the moduleinfo, so the module constructors
229: * and destructors get linked in.
230: */
231: Module *m = aimports.tdata()[0];
232: assert(m);
233: if (m->sictor || m->sctor || m->sdtor || m->ssharedctor || m->sshareddtor)
234: {
235: Symbol *s = m->toSymbol();
236: //objextern(s);
237: //if (!s->Sxtrnnum) objextdef(s->Sident);
238: if (!s->Sxtrnnum)
239: {
240: //printf("%s\n", s->Sident);
241: #if 0 /* This should work, but causes optlink to fail in common/newlib.asm */
242: objextdef(s->Sident);
243: #else
244: #if ELFOBJ || MACHOBJ
245: int nbytes = reftoident(DATA, Offset(DATA), s, 0, CFoff);
246: Offset(DATA) += nbytes;
247: #else
248: int nbytes = reftoident(DATA, Doffset, s, 0, CFoff);
249: Doffset += nbytes;
250: #endif
251: #endif
252: }
253: }
254: }
255:
256: if (global.params.cov)
257: {
258: /* Create coverage identifier:
259: * private uint[numlines] __coverage;
260: */
261: cov = symbol_calloc("__coverage");
262: cov->Stype = type_fake(TYint);
263: cov->Stype->Tmangle = mTYman_c;
264: cov->Stype->Tcount++;
265: cov->Sclass = SCstatic;
266: cov->Sfl = FLdata;
267: #if ELFOBJ || MACHOBJ
268: cov->Sseg = UDATA;
269: #endif
270: dtnzeros(&cov->Sdt, 4 * numlines);
271: outdata(cov);
272: slist_add(cov);
273:
274: covb = (unsigned *)calloc((numlines + 32) / 32, sizeof(*covb));
275: }
276:
277: for (int i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
278: {
279: Dsymbol *member = members->tdata()[i];
280: member->toObjFile(multiobj);
281: }
282:
283: if (global.params.cov)
284: {
285: /* Generate
286: * bit[numlines] __bcoverage;
287: */
288: Symbol *bcov = symbol_calloc("__bcoverage");
289: bcov->Stype = type_fake(TYuint);
290: bcov->Stype->Tcount++;
291: bcov->Sclass = SCstatic;
292: bcov->Sfl = FLdata;
293: #if ELFOBJ || MACHOBJ
294: bcov->Sseg = DATA;
295: #endif
296: dtnbytes(&bcov->Sdt, (numlines + 32) / 32 * sizeof(*covb), (char *)covb);
297: outdata(bcov);
298:
299: free(covb);
300: covb = NULL;
301:
302: /* Generate:
303: * _d_cover_register(uint[] __coverage, BitArray __bcoverage, string filename);
304: * and prepend it to the static constructor.
305: */
306:
307: /* t will be the type of the functions generated:
308: * extern (C) void func();
309: */
310: type *t = type_alloc(TYnfunc);
311: t->Tflags |= TFprototype | TFfixed;
312: t->Tmangle = mTYman_c;
313: t->Tnext = tsvoid;
314: tsvoid->Tcount++;
315:
316: sictor = toSymbolX("__modictor", SCglobal, t, "FZv");
317: cstate.CSpsymtab = &sictor->Sfunc->Flocsym;
318: localgot = ictorlocalgot;
319: elem *e;
320:
321: e = el_params(el_pair(TYdarray, el_long(TYsize_t, numlines), el_ptr(cov)),
322: el_pair(TYdarray, el_long(TYsize_t, numlines), el_ptr(bcov)),
323: toEfilename(),
324: NULL);
325: e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_DCOVER]), e);
326: eictor = el_combine(e, eictor);
327: ictorlocalgot = localgot;
328: }
329:
330: // If coverage / static constructor / destructor / unittest calls
331: if (eictor || ector || ectorgates.dim || edtor ||
332: esharedctor || esharedctorgates.dim || eshareddtor || etest)
333: {
334: /* t will be the type of the functions generated:
335: * extern (C) void func();
336: */
337: type *t = type_alloc(TYnfunc);
338: t->Tflags |= TFprototype | TFfixed;
339: t->Tmangle = mTYman_c;
340: t->Tnext = tsvoid;
341: tsvoid->Tcount++;
342:
343: static char moddeco[] = "FZv";
344:
345: if (eictor)
346: {
347: localgot = ictorlocalgot;
348:
349: block *b = block_calloc();
350: b->BC = BCret;
351: b->Belem = eictor;
352: sictor->Sfunc->Fstartline.Sfilename = arg;
353: sictor->Sfunc->Fstartblock = b;
354: writefunc(sictor);
355: }
356:
357: if (ector || ectorgates.dim)
358: {
359: localgot = NULL;
360: sctor = toSymbolX("__modctor", SCglobal, t, moddeco);
361: #if DMDV2
362: cstate.CSpsymtab = &sctor->Sfunc->Flocsym;
363:
364: for (int i = 0; i < ectorgates.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
365: { StaticDtorDeclaration *f = ectorgates.tdata()[i];
366:
367: Symbol *s = f->vgate->toSymbol();
368: elem *e = el_var(s);
369: e = el_bin(OPaddass, TYint, e, el_long(TYint, 1));
370: ector = el_combine(ector, e);
371: }
372: #endif
373:
374: block *b = block_calloc();
375: b->BC = BCret;
376: b->Belem = ector;
377: sctor->Sfunc->Fstartline.Sfilename = arg;
378: sctor->Sfunc->Fstartblock = b;
379: writefunc(sctor);
380: #if STATICCTOR
381: obj_staticctor(sctor, dtorcount, 1);
382: #endif
383: }
384:
385: if (edtor)
386: {
387: localgot = NULL;
388: sdtor = toSymbolX("__moddtor", SCglobal, t, moddeco);
389:
390: block *b = block_calloc();
391: b->BC = BCret;
392: b->Belem = edtor;
393: sdtor->Sfunc->Fstartline.Sfilename = arg;
394: sdtor->Sfunc->Fstartblock = b;
395: writefunc(sdtor);
396: }
397:
398: #if DMDV2
399: if (esharedctor || esharedctorgates.dim)
400: {
401: localgot = NULL;
402: ssharedctor = toSymbolX("__modsharedctor", SCglobal, t, moddeco);
403: cstate.CSpsymtab = &ssharedctor->Sfunc->Flocsym;
404:
405: for (int i = 0; i < esharedctorgates.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
406: { SharedStaticDtorDeclaration *f = esharedctorgates.tdata()[i];
407:
408: Symbol *s = f->vgate->toSymbol();
409: elem *e = el_var(s);
410: e = el_bin(OPaddass, TYint, e, el_long(TYint, 1));
411: esharedctor = el_combine(esharedctor, e);
412: }
413:
414: block *b = block_calloc();
415: b->BC = BCret;
416: b->Belem = esharedctor;
417: ssharedctor->Sfunc->Fstartline.Sfilename = arg;
418: ssharedctor->Sfunc->Fstartblock = b;
419: writefunc(ssharedctor);
420: #if STATICCTOR
421: obj_staticctor(ssharedctor, shareddtorcount, 1);
422: #endif
423: }
424:
425: if (eshareddtor)
426: {
427: localgot = NULL;
428: sshareddtor = toSymbolX("__modshareddtor", SCglobal, t, moddeco);
429:
430: block *b = block_calloc();
431: b->BC = BCret;
432: b->Belem = eshareddtor;
433: sshareddtor->Sfunc->Fstartline.Sfilename = arg;
434: sshareddtor->Sfunc->Fstartblock = b;
435: writefunc(sshareddtor);
436: }
437: #endif
438:
439: if (etest)
440: {
441: localgot = NULL;
442: stest = toSymbolX("__modtest", SCglobal, t, moddeco);
443:
444: block *b = block_calloc();
445: b->BC = BCret;
446: b->Belem = etest;
447: stest->Sfunc->Fstartline.Sfilename = arg;
448: stest->Sfunc->Fstartblock = b;
449: writefunc(stest);
450: }
451:
452: if (doppelganger)
453: genmoduleinfo();
454: }
455:
456: if (doppelganger)
457: {
458: obj_termfile();
459: return;
460: }
461:
462: if (global.params.multiobj)
463: { /* This is necessary because the main .obj for this module is written
464: * first, but determining whether marray or massert or munittest are needed is done
465: * possibly later in the doppelganger modules.
466: * Another way to fix it is do the main one last.
467: */
468: toModuleAssert();
469: toModuleUnittest();
470: toModuleArray();
471: }
472:
473: #if 1
474: // Always generate module info, because of templates and -cov
475: if (1 || needModuleInfo())
warning C6286: (<non-zero constant> || <expression>) is always a non-zero constant. <expression> is never evaluated and might have side effects
476: genmoduleinfo();
477: #endif
478:
479: // If module assert
480: for (int i = 0; i < 3; i++)
481: {
482: Symbol *ma;
483: unsigned rt;
484: unsigned bc;
485: switch (i)
486: {
487: case 0: ma = marray; rt = RTLSYM_DARRAY; bc = BCexit; break;
488: case 1: ma = massert; rt = RTLSYM_DASSERTM; bc = BCexit; break;
489: case 2: ma = munittest; rt = RTLSYM_DUNITTESTM; bc = BCret; break;
490: default: assert(0);
491: }
492:
493: if (ma)
494: {
495: elem *elinnum;
496:
497: localgot = NULL;
498:
499: // Call dassert(filename, line)
500: // Get sole parameter, linnum
501: {
502: Symbol *sp = symbol_calloc("linnum");
503: sp->Stype = type_fake(TYint);
504: sp->Stype->Tcount++;
505: sp->Sclass = SCfastpar;
506: sp->Spreg = I64 ? DI : AX;
507: sp->Sflags &= ~SFLspill;
508: sp->Sfl = FLpara; // FLauto?
509: cstate.CSpsymtab = &ma->Sfunc->Flocsym;
510: symbol_add(sp);
511:
512: elinnum = el_var(sp);
513: }
514:
515: elem *efilename = el_ptr(toSymbol());
516:
517: elem *e = el_var(rtlsym[rt]);
518: e = el_bin(OPcall, TYvoid, e, el_param(elinnum, efilename));
519:
520: block *b = block_calloc();
521: b->BC = bc;
522: b->Belem = e;
523: ma->Sfunc->Fstartline.Sfilename = arg;
524: ma->Sfunc->Fstartblock = b;
525: ma->Sclass = SCglobal;
526: ma->Sfl = 0;
527: ma->Sflags |= rtlsym[rt]->Sflags & SFLexit;
528: writefunc(ma);
529: }
530: }
531:
532: obj_termfile();
533: }
534:
535:
536: /* ================================================================== */
537:
538: void FuncDeclaration::toObjFile(int multiobj)
539: {
540: Symbol *senter;
warning C4101: 'senter' : unreferenced local variable
541: Symbol *sexit;
warning C4101: 'sexit' : unreferenced local variable
542: FuncDeclaration *func = this;
543: ClassDeclaration *cd = func->parent->isClassDeclaration();
544: int reverse;
545: int i;
546: int has_arguments;
547:
548: //printf("FuncDeclaration::toObjFile(%p, %s.%s)\n", func, parent->toChars(), func->toChars());
549: //if (type) printf("type = %s\n", func->type->toChars());
550: #if 0
551: //printf("line = %d\n",func->getWhere() / LINEINC);
552: EEcontext *ee = env->getEEcontext();
553: if (ee->EEcompile == 2)
554: {
555: if (ee->EElinnum < (func->getWhere() / LINEINC) ||
556: ee->EElinnum > (func->endwhere / LINEINC)
557: )
558: return; // don't compile this function
559: ee->EEfunc = func->toSymbol();
560: }
561: #endif
562:
563: if (semanticRun >= PASSobj) // if toObjFile() already run
564: return;
565:
566: // If errors occurred compiling it, such as bugzilla 6118
567: if (type && type->ty == Tfunction && ((TypeFunction *)type)->next->ty == Terror)
568: return;
569:
570: if (!func->fbody)
571: {
572: return;
573: }
574: if (func->isUnitTestDeclaration() && !global.params.useUnitTests)
575: return;
576:
577: if (multiobj && !isStaticDtorDeclaration() && !isStaticCtorDeclaration())
578: { obj_append(this);
579: return;
580: }
581:
582: assert(semanticRun == PASSsemantic3done);
583: semanticRun = PASSobj;
584:
585: if (global.params.verbose)
586: printf("function %s\n",func->toChars());
587:
588: Symbol *s = func->toSymbol();
589: func_t *f = s->Sfunc;
590:
591: #if TARGET_WINDOS
592: /* This is done so that the 'this' pointer on the stack is the same
593: * distance away from the function parameters, so that an overriding
594: * function can call the nested fdensure or fdrequire of its overridden function
595: * and the stack offsets are the same.
596: */
597: if (isVirtual() && (fensure || frequire))
598: f->Fflags3 |= Ffakeeh;
599: #endif
600:
601: #if TARGET_OSX
602: s->Sclass = SCcomdat;
603: #else
604: s->Sclass = SCglobal;
605: #endif
606: for (Dsymbol *p = parent; p; p = p->parent)
607: {
608: if (p->isTemplateInstance())
609: {
610: s->Sclass = SCcomdat;
611: break;
612: }
613: }
614:
615: /* Vector operations should be comdat's
616: */
617: if (isArrayOp)
618: s->Sclass = SCcomdat;
619:
620: if (isNested())
621: {
622: // if (!(config.flags3 & CFG3pic))
623: // s->Sclass = SCstatic;
624: f->Fflags3 |= Fnested;
625: }
626: else
627: {
628: const char *libname = (global.params.symdebug)
629: ? global.params.debuglibname
630: : global.params.defaultlibname;
631:
632: // Pull in RTL startup code
633: if (func->isMain())
634: { objextdef("_main");
635: #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
636: obj_ehsections(); // initialize exception handling sections
637: #endif
638: #if TARGET_WINDOS
639: objextdef("__acrtused_con");
640: #endif
641: obj_includelib(libname);
642: s->Sclass = SCglobal;
643: }
644: else if (strcmp(s->Sident, "main") == 0 && linkage == LINKc)
645: {
646: #if TARGET_WINDOS
647: objextdef("__acrtused_con"); // bring in C startup code
648: obj_includelib("snn.lib"); // bring in C runtime library
649: #endif
650: s->Sclass = SCglobal;
651: }
652: else if (func->isWinMain())
653: {
654: objextdef("__acrtused");
655: obj_includelib(libname);
656: s->Sclass = SCglobal;
657: }
658:
659: // Pull in RTL startup code
660: else if (func->isDllMain())
661: {
662: objextdef("__acrtused_dll");
663: obj_includelib(libname);
664: s->Sclass = SCglobal;
665: }
666: }
667:
668: cstate.CSpsymtab = &f->Flocsym;
669:
670: // Find module m for this function
671: Module *m = NULL;
672: for (Dsymbol *p = parent; p; p = p->parent)
673: {
674: m = p->isModule();
675: if (m)
676: break;
677: }
678:
679: IRState irs(m, func);
680: Dsymbols deferToObj; // write these to OBJ file later
681: irs.deferToObj = &deferToObj;
682:
683: TypeFunction *tf;
684: enum RET retmethod;
685: symbol *shidden = NULL;
686: Symbol *sthis = NULL;
687: tym_t tyf;
688:
689: tyf = tybasic(s->Stype->Tty);
690: //printf("linkage = %d, tyf = x%x\n", linkage, tyf);
691: reverse = tyrevfunc(s->Stype->Tty);
692:
693: assert(func->type->ty == Tfunction);
694: tf = (TypeFunction *)(func->type);
695: has_arguments = (tf->linkage == LINKd) && (tf->varargs == 1);
696: retmethod = tf->retStyle();
697: if (retmethod == RETstack)
698: {
699: // If function returns a struct, put a pointer to that
700: // as the first argument
701: ::type *thidden = tf->next->pointerTo()->toCtype();
702: char hiddenparam[5+4+1];
703: static int hiddenparami; // how many we've generated so far
704:
705: sprintf(hiddenparam,"__HID%d",++hiddenparami);
warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
706: shidden = symbol_name(hiddenparam,SCparameter,thidden);
707: shidden->Sflags |= SFLtrue | SFLfree;
708: #if DMDV1
709: if (func->nrvo_can && func->nrvo_var && func->nrvo_var->nestedref)
710: #else
711: if (func->nrvo_can && func->nrvo_var && func->nrvo_var->nestedrefs.dim)
712: #endif
713: type_setcv(&shidden->Stype, shidden->Stype->Tty | mTYvolatile);
714: irs.shidden = shidden;
715: this->shidden = shidden;
716: }
717:
718: if (vthis)
719: {
720: assert(!vthis->csym);
721: sthis = vthis->toSymbol();
722: irs.sthis = sthis;
723: if (!(f->Fflags3 & Fnested))
724: f->Fflags3 |= Fmember;
725: }
726:
727: Symbol **params;
728: unsigned pi;
729:
730: // Estimate number of parameters, pi
731: pi = (v_arguments != NULL);
732: if (parameters)
733: pi += parameters->dim;
734: // Allow extra 2 for sthis and shidden
735: params = (Symbol **)alloca((pi + 2) * sizeof(Symbol *));
warning C6255: _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead
736:
737: // Get the actual number of parameters, pi, and fill in the params[]
738: pi = 0;
739: if (v_arguments)
740: {
741: params[pi] = v_arguments->toSymbol();
742: pi += 1;
743: }
744: if (parameters)
745: {
746: for (i = 0; i < parameters->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
747: { VarDeclaration *v = parameters->tdata()[i];
748: if (v->csym)
749: {
750: error("compiler error, parameter '%s', bugzilla 2962?", v->toChars());
751: assert(0);
752: }
753: params[pi + i] = v->toSymbol();
754: }
755: pi += i;
756: }
757:
758: if (reverse)
759: { // Reverse params[] entries
760: for (i = 0; i < pi/2; i++)
warning C4018: '<' : signed/unsigned mismatch
761: {
762: Symbol *sptmp = params[i];
763: params[i] = params[pi - 1 - i];
764: params[pi - 1 - i] = sptmp;
765: }
766: }
767:
768: if (shidden)
769: {
770: #if 0
771: // shidden becomes last parameter
772: params[pi] = shidden;
773: #else
774: // shidden becomes first parameter
775: memmove(params + 1, params, pi * sizeof(params[0]));
776: params[0] = shidden;
777: #endif
778: pi++;
779: }
780:
781:
782: if (sthis)
783: {
784: #if 0
785: // sthis becomes last parameter
786: params[pi] = sthis;
787: #else
788: // sthis becomes first parameter
789: memmove(params + 1, params, pi * sizeof(params[0]));
790: params[0] = sthis;
791: #endif
792: pi++;
793: }
794:
795: if ((global.params.isLinux || global.params.isOSX || global.params.isFreeBSD || global.params.isSolaris) &&
796: linkage != LINKd && shidden && sthis)
797: {
798: /* swap shidden and sthis
799: */
800: Symbol *sp = params[0];
801: params[0] = params[1];
802: params[1] = sp;
803: }
804:
805: for (i = 0; i < pi; i++)
warning C4018: '<' : signed/unsigned mismatch
806: { Symbol *sp = params[i];
807: sp->Sclass = SCparameter;
808: sp->Sflags &= ~SFLspill;
809: sp->Sfl = FLpara;
810: symbol_add(sp);
811: }
812:
813: // Determine register assignments
814: if (pi)
815: {
816: if (global.params.is64bit)
817: {
818: // Order of assignment of pointer or integer parameters
819: static const unsigned char argregs[6] = { DI,SI,DX,CX,R8,R9 };
820: int r = 0;
821: int xmmcnt = XMM0;
822:
823: for (int i = 0; i < pi; i++)
warning C4018: '<' : signed/unsigned mismatch
warning C6246: Local declaration of 'i' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '545' of 'c:\projects\extern\d\dmd\src\glue.c': Lines: 545
824: { Symbol *sp = params[i];
825: tym_t ty = tybasic(sp->Stype->Tty);
826: // BUG: doesn't work for structs
827: if (r < sizeof(argregs)/sizeof(argregs[0]))
828: {
829: if (type_jparam(sp->Stype))
830: {
831: sp->Sclass = SCfastpar;
832: sp->Spreg = argregs[r];
833: sp->Sfl = FLauto;
834: ++r;
835: }
836: }
837: if (xmmcnt < XMM7)
838: {
839: if (tyfloating(ty) && tysize(ty) <= 8)
840: {
841: sp->Sclass = SCfastpar;
842: sp->Spreg = xmmcnt;
843: sp->Sfl = FLauto;
844: ++xmmcnt;
845: }
846: }
847: }
848: }
849: else
850: {
851: // First parameter goes in register
852: Symbol *sp = params[0];
853: if ((tyf == TYjfunc || tyf == TYmfunc) &&
854: type_jparam(sp->Stype))
855: { sp->Sclass = SCfastpar;
856: sp->Spreg = (tyf == TYjfunc) ? AX : CX;
857: sp->Sfl = FLauto;
858: //printf("'%s' is SCfastpar\n",sp->Sident);
859: }
860: }
861: }
862:
863: if (func->fbody)
864: { block *b;
865: Blockx bx;
866: Statement *sbody;
867:
868: localgot = NULL;
869:
870: sbody = func->fbody;
871: memset(&bx,0,sizeof(bx));
872: bx.startblock = block_calloc();
873: bx.curblock = bx.startblock;
874: bx.funcsym = s;
875: bx.scope_index = -1;
876: bx.classdec = cd;
877: bx.member = func;
878: bx.module = getModule();
879: irs.blx = &bx;
880: #if DMDV2
881: buildClosure(&irs);
882: #endif
883:
884: #if 0
885: if (func->isSynchronized())
886: {
887: if (cd)
888: { elem *esync;
889: if (func->isStatic())
890: { // monitor is in ClassInfo
891: esync = el_ptr(cd->toSymbol());
892: }
893: else
894: { // 'this' is the monitor
895: esync = el_var(sthis);
896: }
897:
898: if (func->isStatic() || sbody->usesEH() ||
899: !(config.flags2 & CFG2seh))
900: { // BUG: what if frequire or fensure uses EH?
901:
902: sbody = new SynchronizedStatement(func->loc, esync, sbody);
903: }
904: else
905: {
906: #if TARGET_WINDOS
907: if (config.flags2 & CFG2seh)
908: {
909: /* The "jmonitor" uses an optimized exception handling frame
910: * which is a little shorter than the more general EH frame.
911: * It isn't strictly necessary.
912: */
913: s->Sfunc->Fflags3 |= Fjmonitor;
914: }
915: #endif
916: el_free(esync);
917: }
918: }
919: else
920: {
921: error("synchronized function %s must be a member of a class", func->toChars());
922: }
923: }
924: #elif TARGET_WINDOS
925: if (func->isSynchronized() && cd && config.flags2 & CFG2seh &&
926: !func->isStatic() && !sbody->usesEH())
927: {
928: /* The "jmonitor" hack uses an optimized exception handling frame
929: * which is a little shorter than the more general EH frame.
930: */
931: s->Sfunc->Fflags3 |= Fjmonitor;
932: }
933: #endif
934:
935: sbody->toIR(&irs);
936: bx.curblock->BC = BCret;
937:
938: f->Fstartblock = bx.startblock;
939: // einit = el_combine(einit,bx.init);
940:
941: if (isCtorDeclaration())
942: {
943: assert(sthis);
944: for (b = f->Fstartblock; b; b = b->Bnext)
945: {
946: if (b->BC == BCret)
947: {
948: b->BC = BCretexp;
949: b->Belem = el_combine(b->Belem, el_var(sthis));
950: }
951: }
952: }
953: }
954:
955: // If static constructor
956: #if DMDV2
957: if (isSharedStaticCtorDeclaration()) // must come first because it derives from StaticCtorDeclaration
958: {
959: elem *e = el_una(OPucall, TYvoid, el_var(s));
960: esharedctor = el_combine(esharedctor, e);
961: }
962: else
963: #endif
964: if (isStaticCtorDeclaration())
965: {
966: elem *e = el_una(OPucall, TYvoid, el_var(s));
967: ector = el_combine(ector, e);
968: }
969:
970: // If static destructor
971: #if DMDV2
972: if (isSharedStaticDtorDeclaration()) // must come first because it derives from StaticDtorDeclaration
973: {
974: elem *e;
975:
976: #if STATICCTOR
977: e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_FATEXIT]), el_ptr(s));
978: esharedctor = el_combine(esharedctor, e);
979: shareddtorcount++;
980: #else
981: SharedStaticDtorDeclaration *f = isSharedStaticDtorDeclaration();
warning C6246: Local declaration of 'f' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '589' of 'c:\projects\extern\d\dmd\src\glue.c': Lines: 589
982: assert(f);
983: if (f->vgate)
984: { /* Increment destructor's vgate at construction time
985: */
986: esharedctorgates.push(f);
987: }
988:
989: e = el_una(OPucall, TYvoid, el_var(s));
990: eshareddtor = el_combine(e, eshareddtor);
991: #endif
992: }
993: else
994: #endif
995: if (isStaticDtorDeclaration())
996: {
997: elem *e;
998:
999: #if STATICCTOR
1000: e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_FATEXIT]), el_ptr(s));
1001: ector = el_combine(ector, e);
1002: dtorcount++;
1003: #else
1004: StaticDtorDeclaration *f = isStaticDtorDeclaration();
warning C6246: Local declaration of 'f' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '589' of 'c:\projects\extern\d\dmd\src\glue.c': Lines: 589
1005: assert(f);
1006: if (f->vgate)
1007: { /* Increment destructor's vgate at construction time
1008: */
1009: ectorgates.push(f);
1010: }
1011:
1012: e = el_una(OPucall, TYvoid, el_var(s));
1013: edtor = el_combine(e, edtor);
1014: #endif
1015: }
1016:
1017: // If unit test
1018: if (isUnitTestDeclaration())
1019: {
1020: elem *e = el_una(OPucall, TYvoid, el_var(s));
1021: etest = el_combine(etest, e);
1022: }
1023:
1024: if (global.errors)
1025: return;
1026:
1027: writefunc(s);
1028: if (isExport())
1029: obj_export(s, Poffset);
1030:
1031: for (i = 0; i < irs.deferToObj->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1032: {
1033: Dsymbol *s = irs.deferToObj->tdata()[i];
warning C6246: Local declaration of 's' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '588' of 'c:\projects\extern\d\dmd\src\glue.c': Lines: 588
1034: s->toObjFile(0);
1035: }
1036:
1037: #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
1038: // A hack to get a pointer to this function put in the .dtors segment
1039: if (ident && memcmp(ident->toChars(), "_STD", 4) == 0)
1040: obj_staticdtor(s);
1041: #endif
1042: #if DMDV2
1043: if (irs.startaddress)
1044: {
1045: printf("Setting start address\n");
1046: obj_startaddress(irs.startaddress);
1047: }
1048: #endif
1049: }
1050:
1051: /* ================================================================== */
1052:
1053: /*****************************
1054: * Return back end type corresponding to D front end type.
1055: */
1056:
1057: unsigned Type::totym()
1058: { unsigned t;
1059:
1060: switch (ty)
1061: {
1062: case Tvoid: t = TYvoid; break;
1063: case Tint8: t = TYschar; break;
1064: case Tuns8: t = TYuchar; break;
1065: case Tint16: t = TYshort; break;
1066: case Tuns16: t = TYushort; break;
1067: case Tint32: t = TYint; break;
1068: case Tuns32: t = TYuint; break;
1069: case Tint64: t = TYllong; break;
1070: case Tuns64: t = TYullong; break;
1071: case Tfloat32: t = TYfloat; break;
1072: case Tfloat64: t = TYdouble; break;
1073: case Tfloat80: t = TYldouble; break;
1074: case Timaginary32: t = TYifloat; break;
1075: case Timaginary64: t = TYidouble; break;
1076: case Timaginary80: t = TYildouble; break;
1077: case Tcomplex32: t = TYcfloat; break;
1078: case Tcomplex64: t = TYcdouble; break;
1079: case Tcomplex80: t = TYcldouble; break;
1080: case Tbool: t = TYbool; break;
1081: case Tchar: t = TYchar; break;
1082: #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
1083: case Twchar: t = TYwchar_t; break;
1084: case Tdchar: t = TYdchar; break;
1085: #else
1086: case Twchar: t = TYwchar_t; break;
1087: case Tdchar:
1088: t = (global.params.symdebug == 1) ? TYdchar : TYulong;
1089: break;
1090: #endif
1091:
1092: case Taarray: t = TYaarray; break;
1093: case Tclass:
1094: case Treference:
1095: case Tpointer: t = TYnptr; break;
1096: case Tdelegate: t = TYdelegate; break;
1097: case Tarray: t = TYdarray; break;
1098: #if SARRAYVALUE
1099: case Tsarray: t = TYstruct; break;
1100: #else
1101: case Tsarray: t = TYarray; break;
1102: #endif
1103: case Tstruct: t = TYstruct; break;
1104:
1105: case Tenum:
1106: case Ttypedef:
1107: t = toBasetype()->totym();
1108: break;
1109:
1110: case Tident:
1111: case Ttypeof:
1112: #ifdef DEBUG
1113: printf("ty = %d, '%s'\n", ty, toChars());
1114: #endif
1115: error(0, "forward reference of %s", toChars());
1116: t = TYint;
1117: break;
1118:
1119: default:
1120: #ifdef DEBUG
1121: printf("ty = %d, '%s'\n", ty, toChars());
1122: halt();
1123: #endif
1124: assert(0);
1125: }
1126:
1127: #if DMDV2
1128: // Add modifiers
1129: switch (mod)
1130: {
1131: case 0:
1132: break;
1133: case MODconst:
1134: case MODwild:
1135: t |= mTYconst;
1136: break;
1137: case MODimmutable:
1138: t |= mTYimmutable;
1139: break;
1140: case MODshared:
1141: t |= mTYshared;
1142: break;
1143: case MODshared | MODwild:
1144: case MODshared | MODconst:
1145: t |= mTYshared | mTYconst;
1146: break;
1147: default:
1148: assert(0);
1149: }
1150: #endif
1151:
1152: return t;
1153: }
1154:
1155: unsigned TypeFunction::totym()
1156: {
1157: tym_t tyf;
1158:
1159: //printf("TypeFunction::totym(), linkage = %d\n", linkage);
1160: switch (linkage)
1161: {
1162: case LINKwindows:
1163: tyf = (varargs == 1) ? TYnfunc : TYnsfunc;
1164: break;
1165:
1166: case LINKpascal:
1167: tyf = (varargs == 1) ? TYnfunc : TYnpfunc;
1168: break;
1169:
1170: case LINKc:
1171: tyf = TYnfunc;
1172: #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
1173: if (I32 && retStyle() == RETstack)
1174: tyf = TYhfunc;
1175: #endif
1176: break;
1177:
1178: case LINKd:
1179: tyf = (varargs == 1) ? TYnfunc : TYjfunc;
1180: break;
1181:
1182: case LINKcpp:
1183: tyf = TYnfunc;
1184: break;
1185:
1186: default:
1187: printf("linkage = %d\n", linkage);
1188: assert(0);
1189: }
1190: #if DMDV2
1191: if (isnothrow)
1192: tyf |= mTYnothrow;
1193: #endif
1194: return tyf;
1195: }
1196:
1197: /**************************************
1198: */
1199:
1200: Symbol *Type::toSymbol()
1201: {
1202: assert(0);
1203: return NULL;
1204: }
1205:
1206: Symbol *TypeClass::toSymbol()
1207: {
1208: return sym->toSymbol();
1209: }
1210:
1211: /*************************************
1212: * Generate symbol in data segment for critical section.
1213: */
1214:
1215: Symbol *Module::gencritsec()
1216: {
1217: Symbol *s;
1218: type *t;
1219:
1220: t = Type::tint32->toCtype();
1221: s = symbol_name("critsec", SCstatic, t);
1222: s->Sfl = FLdata;
1223: /* Must match D_CRITICAL_SECTION in phobos/internal/critical.c
1224: */
1225: dtnzeros(&s->Sdt, PTRSIZE + (I64 ? os_critsecsize64() : os_critsecsize32()));
1226: #if ELFOBJ || MACHOBJ // Burton
1227: s->Sseg = DATA;
1228: #endif
1229: outdata(s);
1230: return s;
1231: }
1232:
1233: /**************************************
1234: * Generate elem that is a pointer to the module file name.
1235: */
1236:
1237: elem *Module::toEfilename()
1238: { elem *efilename;
1239:
1240: if (!sfilename)
1241: {
1242: dt_t *dt = NULL;
1243: char *id;
1244: int len;
1245:
1246: id = srcfile->toChars();
1247: len = strlen(id);
1248: dtsize_t(&dt, len);
1249: dtabytes(&dt,TYnptr, 0, len + 1, id);
1250:
1251: sfilename = symbol_generate(SCstatic,type_fake(TYdarray));
1252: sfilename->Sdt = dt;
1253: sfilename->Sfl = FLdata;
1254: #if ELFOBJ
1255: sfilename->Sseg = CDATA;
1256: #endif
1257: #if MACHOBJ
1258: // Because of PIC and CDATA being in the _TEXT segment, cannot
1259: // have pointers in CDATA
1260: sfilename->Sseg = DATA;
1261: #endif
1262: outdata(sfilename);
1263: }
1264:
1265: efilename = el_var(sfilename);
1266: return efilename;
1267: }
1268:
1269:
1270: