root/trunk/src/glue.c

Revision 837, 32.3 kB (checked in by walter, 1 year ago)

coverage analyzer now works in 64 bits

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