root/trunk/src/tocsym.c

Revision 790, 18.4 kB (checked in by walter, 1 year ago)

more 64

  • Property svn:eol-style set to native
Line 
1 // Compiler implementation of the D programming language
2 // Copyright (c) 1999-2009 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 #include <assert.h>
14
15 #if __sun&&__SVR4
16 #include <alloca.h>
17 #endif
18
19 #include "mars.h"
20 #include "module.h"
21 #include "mtype.h"
22 #include "declaration.h"
23 #include "statement.h"
24 #include "enum.h"
25 #include "aggregate.h"
26 #include "init.h"
27 #include "attrib.h"
28 #include "lexer.h"
29 #include "dsymbol.h"
30 #include "id.h"
31
32 #include "rmem.h"
33
34 // Back end
35 #include "cc.h"
36 #include "global.h"
37 #include "oper.h"
38 #include "code.h"
39 #include "type.h"
40 #include "dt.h"
41 #include "cgcv.h"
42 #include "outbuf.h"
43 #include "irstate.h"
44
45 void slist_add(Symbol *s);
46 void slist_reset();
47
48 Classsym *fake_classsym(Identifier *id);
49
50 /********************************* SymbolDeclaration ****************************/
51
52 SymbolDeclaration::SymbolDeclaration(Loc loc, Symbol *s, StructDeclaration *dsym)
53     : Declaration(new Identifier(s->Sident, TOKidentifier))
54 {
55     this->loc = loc;
56     sym = s;
57     this->dsym = dsym;
58     storage_class |= STCconst;
59 }
60
61 Symbol *SymbolDeclaration::toSymbol()
62 {
63     return sym;
64 }
65
66 /*************************************
67  * Helper
68  */
69
70 Symbol *Dsymbol::toSymbolX(const char *prefix, int sclass, type *t, const char *suffix)
71 {
72     Symbol *s;
73     char *id;
74     const char *n;
75     size_t nlen;
76
77     //printf("Dsymbol::toSymbolX('%s')\n", prefix);
78     n = mangle();
79     assert(n);
80     nlen = strlen(n);
81 #if 0
82     if (nlen > 2 && n[0] == '_' && n[1] == 'D')
83     {
84         nlen -= 2;
85         n += 2;
86     }
87 #endif
88     id = (char *) alloca(2 + nlen + sizeof(size_t) * 3 + strlen(prefix) + strlen(suffix) + 1);
89     sprintf(id,"_D%s%zu%s%s", n, strlen(prefix), prefix, suffix);
90 #if 0
91     if (global.params.isWindows &&
92         (type_mangle(t) == mTYman_c || type_mangle(t) == mTYman_std))
93         id++;                   // Windows C mangling will put the '_' back in
94 #endif
95     s = symbol_name(id, sclass, t);
96     //printf("-Dsymbol::toSymbolX() %s\n", id);
97     return s;
98 }
99
100 /*************************************
101  */
102
103 Symbol *Dsymbol::toSymbol()
104 {
105     printf("Dsymbol::toSymbol() '%s', kind = '%s'\n", toChars(), kind());
106 #ifdef DEBUG
107     halt();
108 #endif
109     assert(0);          // BUG: implement
110     return NULL;
111 }
112
113 /*********************************
114  * Generate import symbol from symbol.
115  */
116
117 Symbol *Dsymbol::toImport()
118 {
119     if (!isym)
120     {
121         if (!csym)
122             csym = toSymbol();
123         isym = toImport(csym);
124     }
125     return isym;
126 }
127
128 /*************************************
129  */
130
131 Symbol *Dsymbol::toImport(Symbol *sym)
132 {
133     char *id;
134     char *n;
135     Symbol *s;
136     type *t;
137
138     //printf("Dsymbol::toImport('%s')\n", sym->Sident);
139     n = sym->Sident;
140     id = (char *) alloca(6 + strlen(n) + 1 + sizeof(type_paramsize(sym->Stype))*3 + 1);
141     if (sym->Stype->Tmangle == mTYman_std && tyfunc(sym->Stype->Tty))
142     {
143         sprintf(id,"_imp__%s@%lu",n,(unsigned long)type_paramsize(sym->Stype));
144     }
145     else if (sym->Stype->Tmangle == mTYman_d)
146         sprintf(id,"_imp_%s",n);
147     else
148         sprintf(id,"_imp__%s",n);
149     t = type_alloc(TYnptr | mTYconst);
150     t->Tnext = sym->Stype;
151     t->Tnext->Tcount++;
152     t->Tmangle = mTYman_c;
153     t->Tcount++;
154     s = symbol_calloc(id);
155     s->Stype = t;
156     s->Sclass = SCextern;
157     s->Sfl = FLextern;
158     slist_add(s);
159     return s;
160 }
161
162 /*************************************
163  */
164
165 Symbol *VarDeclaration::toSymbol()
166 {
167     //printf("VarDeclaration::toSymbol(%s)\n", toChars());
168     //if (needThis()) *(char*)0=0;
169     assert(!needThis());
170     if (!csym)
171     {   Symbol *s;
172         TYPE *t;
173         const char *id;
174
175         if (isDataseg())
176             id = mangle();
177         else
178             id = ident->toChars();
179         s = symbol_calloc(id);
180
181         if (storage_class & (STCout | STCref))
182         {
183             if (global.params.symdebug && storage_class & STCparameter)
184             {
185                 t = type_alloc(TYnptr);         // should be TYref, but problems in back end
186                 t->Tnext = type->toCtype();
187                 t->Tnext->Tcount++;
188             }
189             else
190                 t = type_fake(TYnptr);
191         }
192         else if (storage_class & STClazy)
193             t = type_fake(TYdelegate);          // Tdelegate as C type
194         else if (isParameter())
195             t = type->toCParamtype();
196         else
197             t = type->toCtype();
198         t->Tcount++;
199
200         if (isDataseg())
201         {
202             if (isThreadlocal())
203             {   /* Thread local storage
204                  */
205                 TYPE *ts = t;
206                 ts->Tcount++;   // make sure a different t is allocated
207                 type_setty(&t, t->Tty | mTYthread);
208                 ts->Tcount--;
209
210                 if (global.params.vtls)
211                 {
212                     char *p = loc.toChars();
213                     fprintf(stdmsg, "%s: %s is thread local\n", p ? p : "", toChars());
214                     if (p)
215                         mem.free(p);
216                 }
217             }
218             s->Sclass = SCextern;
219             s->Sfl = FLextern;
220             slist_add(s);
221         }
222         else
223         {
224             s->Sclass = SCauto;
225             s->Sfl = FLauto;
226
227             if (nestedrefs.dim)
228             {
229                 /* Symbol is accessed by a nested function. Make sure
230                  * it is not put in a register, and that the optimizer
231                  * assumes it is modified across function calls and pointer
232                  * dereferences.
233                  */
234                 //printf("\tnested ref, not register\n");
235                 type_setcv(&t, t->Tty | mTYvolatile);
236             }
237         }
238
239         if (ident == Id::va_argsave)
240             /* __va_argsave is set outside of the realm of the optimizer,
241              * so we tell the optimizer to leave it alone
242              */
243             type_setcv(&t, t->Tty | mTYvolatile);
244
245         mangle_t m = 0;
246         switch (linkage)
247         {
248             case LINKwindows:
249                 m = mTYman_std;
250                 break;
251
252             case LINKpascal:
253                 m = mTYman_pas;
254                 break;
255
256             case LINKc:
257                 m = mTYman_c;
258                 break;
259
260             case LINKd:
261                 m = mTYman_d;
262                 break;
263
264             case LINKcpp:
265                 m = mTYman_cpp;
266                 break;
267
268             default:
269                 printf("linkage = %d\n", linkage);
270                 assert(0);
271         }
272         type_setmangle(&t, m);
273         s->Stype = t;
274
275         csym = s;
276     }
277     return csym;
278 }
279
280 /*************************************
281  */
282
283 Symbol *ClassInfoDeclaration::toSymbol()
284 {
285     return cd->toSymbol();
286 }
287
288 /*************************************
289  */
290
291 Symbol *ModuleInfoDeclaration::toSymbol()
292 {
293     return mod->toSymbol();
294 }
295
296 /*************************************
297  */
298
299 Symbol *TypeInfoDeclaration::toSymbol()
300 {
301     //printf("TypeInfoDeclaration::toSymbol(%s), linkage = %d\n", toChars(), linkage);
302     return VarDeclaration::toSymbol();
303 }
304
305 /*************************************
306  */
307
308 Symbol *TypeInfoClassDeclaration::toSymbol()
309 {
310     //printf("TypeInfoClassDeclaration::toSymbol(%s), linkage = %d\n", toChars(), linkage);
311     assert(tinfo->ty == Tclass);
312     TypeClass *tc = (TypeClass *)tinfo;
313     return tc->sym->toSymbol();
314 }
315
316 /*************************************
317  */
318
319 Symbol *FuncAliasDeclaration::toSymbol()
320 {
321     return funcalias->toSymbol();
322 }
323
324 /*************************************
325  */
326
327 Symbol *FuncDeclaration::toSymbol()
328 {
329     if (!csym)
330     {   Symbol *s;
331         TYPE *t;
332         const char *id;
333
334 #if 0
335         id = ident->toChars();
336 #else
337         id = mangle();
338 #endif
339         //printf("FuncDeclaration::toSymbol(%s %s)\n", kind(), toChars());
340         //printf("\tid = '%s'\n", id);
341         //printf("\ttype = %s\n", type->toChars());
342         s = symbol_calloc(id);
343         slist_add(s);
344
345         {
346             s->prettyIdent = toPrettyChars();
347             s->Sclass = SCglobal;
348             symbol_func(s);
349             func_t *f = s->Sfunc;
350             if (isVirtual())
351                 f->Fflags |= Fvirtual;
352             else if (isMember2())
353                 f->Fflags |= Fstatic;
354             f->Fstartline.Slinnum = loc.linnum;
355             f->Fstartline.Sfilename = (char *)loc.filename;
356             if (endloc.linnum)
357             {   f->Fendline.Slinnum = endloc.linnum;
358                 f->Fendline.Sfilename = (char *)endloc.filename;
359             }
360             else
361             {   f->Fendline.Slinnum = loc.linnum;
362                 f->Fendline.Sfilename = (char *)loc.filename;
363             }
364             t = type->toCtype();
365         }
366
367         mangle_t msave = t->Tmangle;
368         if (isMain())
369         {
370             t->Tty = TYnfunc;
371             t->Tmangle = mTYman_c;
372         }
373         else
374         {
375             switch (linkage)
376             {
377                 case LINKwindows:
378                     t->Tmangle = mTYman_std;
379                     break;
380
381                 case LINKpascal:
382                     t->Tty = TYnpfunc;
383                     t->Tmangle = mTYman_pas;
384                     break;
385
386                 case LINKc:
387                     t->Tmangle = mTYman_c;
388                     break;
389
390                 case LINKd:
391                     t->Tmangle = mTYman_d;
392                     break;
393
394                 case LINKcpp:
395                 {   t->Tmangle = mTYman_cpp;
396 #if TARGET_WINDOS
397                     if (isThis())
398                         t->Tty = TYmfunc;
399 #endif
400                     s->Sflags |= SFLpublic;
401                     Dsymbol *parent = toParent();
402                     ClassDeclaration *cd = parent->isClassDeclaration();
403                     if (cd)
404                     {
405                         ::type *t = cd->type->toCtype();
406                         s->Sscope = t->Tnext->Ttag;
407                     }
408                     break;
409                 }
410                 default:
411                     printf("linkage = %d\n", linkage);
412                     assert(0);
413             }
414         }
415         if (msave)
416             assert(msave == t->Tmangle);
417         //printf("Tty = %x, mangle = x%x\n", t->Tty, t->Tmangle);
418         t->Tcount++;
419         s->Stype = t;
420         //s->Sfielddef = this;
421
422         csym = s;
423     }
424     return csym;
425 }
426
427 /*************************************
428  */
429
430 Symbol *FuncDeclaration::toThunkSymbol(int offset)
431 {
432     Symbol *sthunk;
433
434     toSymbol();
435
436 #if 0
437     char *id;
438     char *n;
439     type *t;
440
441     n = sym->Sident;
442     id = (char *) alloca(8 + 5 + strlen(n) + 1);
443     sprintf(id,"_thunk%d__%s", offset, n);
444     s = symbol_calloc(id);
445     slist_add(s);
446     s->Stype = csym->Stype;
447     s->Stype->Tcount++;
448 #endif
449     sthunk = symbol_generate(SCstatic, csym->Stype);
450     sthunk->Sflags |= SFLimplem;
451     cod3_thunk(sthunk, csym, 0, TYnptr, -offset, -1, 0);
452     return sthunk;
453 }
454
455
456 /****************************************
457  * Create a static symbol we can hang DT initializers onto.
458  */
459
460 Symbol *static_sym()
461 {
462     Symbol *s;
463     type *t;
464
465     t = type_alloc(TYint);
466     t->Tcount++;
467     s = symbol_calloc("internal");
468     s->Sclass = SCstatic;
469     s->Sfl = FLextern;
470     s->Sflags |= SFLnodebug;
471     s->Stype = t;
472 #if ELFOBJ || MACHOBJ
473     s->Sseg = DATA;
474 #endif
475     slist_add(s);
476     return s;
477 }
478
479 /**************************************
480  * Fake a struct symbol.
481  */
482
483 Classsym *fake_classsym(Identifier *id)
484 {   TYPE *t;
485     Classsym *scc;
486
487     scc = (Classsym *)symbol_calloc(id->toChars());
488     scc->Sclass = SCstruct;
489     scc->Sstruct = struct_calloc();
490     scc->Sstruct->Sstructalign = 8;
491     //scc->Sstruct->ptrtype = TYnptr;
492     scc->Sstruct->Sflags = STRglobal;
493
494     t = type_alloc(TYstruct);
495     t->Tflags |= TFsizeunknown | TFforward;
496     t->Ttag = scc;              // structure tag name
497     assert(t->Tmangle == 0);
498     t->Tmangle = mTYman_d;
499     t->Tcount++;
500     scc->Stype = t;
501     slist_add(scc);
502     return scc;
503 }
504
505 /*************************************
506  * Create the "ClassInfo" symbol
507  */
508
509 static Classsym *scc;
510
511 Symbol *ClassDeclaration::toSymbol()
512 {
513     if (!csym)
514     {
515         Symbol *s;
516
517         if (!scc)
518             scc = fake_classsym(Id::ClassInfo);
519
520         s = toSymbolX("__Class", SCextern, scc->Stype, "Z");
521         s->Sfl = FLextern;
522         s->Sflags |= SFLnodebug;
523         csym = s;
524         slist_add(s);
525     }
526     return csym;
527 }
528
529 /*************************************
530  * Create the "InterfaceInfo" symbol
531  */
532
533 Symbol *InterfaceDeclaration::toSymbol()
534 {
535     if (!csym)
536     {
537         Symbol *s;
538
539         if (!scc)
540             scc = fake_classsym(Id::ClassInfo);
541
542         s = toSymbolX("__Interface", SCextern, scc->Stype, "Z");
543         s->Sfl = FLextern;
544         s->Sflags |= SFLnodebug;
545         csym = s;
546         slist_add(s);
547     }
548     return csym;
549 }
550
551 /*************************************
552  * Create the "ModuleInfo" symbol
553  */
554
555 Symbol *Module::toSymbol()
556 {
557     if (!csym)
558     {
559         Symbol *s;
560         static Classsym *scc;
561
562         if (!scc)
563             scc = fake_classsym(Id::ClassInfo);
564
565         s = toSymbolX("__ModuleInfo", SCextern, scc->Stype, "Z");
566         s->Sfl = FLextern;
567         s->Sflags |= SFLnodebug;
568         csym = s;
569         slist_add(s);
570     }
571     return csym;
572 }
573
574 /*************************************
575  * This is accessible via the ClassData, but since it is frequently
576  * needed directly (like for rtti comparisons), make it directly accessible.
577  */
578
579 Symbol *ClassDeclaration::toVtblSymbol()
580 {
581     if (!vtblsym)
582     {
583         Symbol *s;
584         TYPE *t;
585
586         if (!csym)
587             toSymbol();
588
589         t = type_alloc(TYnptr | mTYconst);
590         t->Tnext = tsvoid;
591         t->Tnext->Tcount++;
592         t->Tmangle = mTYman_d;
593         s = toSymbolX("__vtbl", SCextern, t, "Z");
594         s->Sflags |= SFLnodebug;
595         s->Sfl = FLextern;
596         vtblsym = s;
597         slist_add(s);
598     }
599     return vtblsym;
600 }
601
602 /**********************************
603  * Create the static initializer for the struct/class.
604  */
605
606 Symbol *AggregateDeclaration::toInitializer()
607 {
608     Symbol *s;
609     Classsym *stag;
610
611     if (!sinit)
612     {
613         stag = fake_classsym(Id::ClassInfo);
614         s = toSymbolX("__init", SCextern, stag->Stype, "Z");
615         s->Sfl = FLextern;
616         s->Sflags |= SFLnodebug;
617         slist_add(s);
618         sinit = s;
619     }
620     return sinit;
621 }
622
623 Symbol *TypedefDeclaration::toInitializer()
624 {
625     Symbol *s;
626     Classsym *stag;
627
628     if (!sinit)
629     {
630         stag = fake_classsym(Id::ClassInfo);
631         s = toSymbolX("__init", SCextern, stag->Stype, "Z");
632         s->Sfl = FLextern;
633         s->Sflags |= SFLnodebug;
634         slist_add(s);
635         sinit = s;
636     }
637     return sinit;
638 }
639
640 Symbol *EnumDeclaration::toInitializer()
641 {
642     Symbol *s;
643     Classsym *stag;
644
645     if (!sinit)
646     {
647         stag = fake_classsym(Id::ClassInfo);
648         Identifier *ident_save = ident;
649         if (!ident)
650             ident = Lexer::uniqueId("__enum");
651         s = toSymbolX("__init", SCextern, stag->Stype, "Z");
652         ident = ident_save;
653         s->Sfl = FLextern;
654         s->Sflags |= SFLnodebug;
655         slist_add(s);
656         sinit = s;
657     }
658     return sinit;
659 }
660
661
662 /******************************************
663  */
664
665 Symbol *Module::toModuleAssert()
666 {
667     if (!massert)
668     {
669         type *t;
670
671         t = type_alloc(TYjfunc);
672         t->Tflags |= TFprototype | TFfixed;
673         t->Tmangle = mTYman_d;
674         t->Tnext = tsvoid;
675         tsvoid->Tcount++;
676
677         massert = toSymbolX("__assert", SCextern, t, "FiZv");
678         massert->Sfl = FLextern;
679         massert->Sflags |= SFLnodebug;
680         slist_add(massert);
681     }
682     return massert;
683 }
684
685 Symbol *Module::toModuleUnittest()
686 {
687     if (!munittest)
688     {
689         type *t;
690
691         t = type_alloc(TYjfunc);
692         t->Tflags |= TFprototype | TFfixed;
693         t->Tmangle = mTYman_d;
694         t->Tnext = tsvoid;
695         tsvoid->Tcount++;
696
697         munittest = toSymbolX("__unittest_fail", SCextern, t, "FiZv");
698         munittest->Sfl = FLextern;
699         munittest->Sflags |= SFLnodebug;
700         slist_add(munittest);
701     }
702     return munittest;
703 }
704
705 /******************************************
706  */
707
708 Symbol *Module::toModuleArray()
709 {
710     if (!marray)
711     {
712         type *t;
713
714         t = type_alloc(TYjfunc);
715         t->Tflags |= TFprototype | TFfixed;
716         t->Tmangle = mTYman_d;
717         t->Tnext = tsvoid;
718         tsvoid->Tcount++;
719
720         marray = toSymbolX("__array", SCextern, t, "Z");
721         marray->Sfl = FLextern;
722         marray->Sflags |= SFLnodebug;
723         slist_add(marray);
724     }
725     return marray;
726 }
727
728 /********************************************
729  * Determine the right symbol to look up
730  * an associative array element.
731  * Input:
732  *      flags   0       don't add value signature
733  *              1       add value signature
734  */
735
736 Symbol *TypeAArray::aaGetSymbol(const char *func, int flags)
737 #if __DMC__
738     __in
739     {
740         assert(func);
741         assert((flags & ~1) == 0);
742     }
743     __out (result)
744     {
745         assert(result);
746     }
747     __body
748 #endif
749     {
750         int sz;
751         char *id;
752         type *t;
753         Symbol *s;
754         int i;
755
756         // Dumb linear symbol table - should use associative array!
757         static Array *sarray = NULL;
758
759         //printf("aaGetSymbol(func = '%s', flags = %d, key = %p)\n", func, flags, key);
760 #if 0
761         OutBuffer buf;
762         key->toKeyBuffer(&buf);
763
764         sz = next->size();              // it's just data, so we only care about the size
765         sz = (sz + 3) & ~3;             // reduce proliferation of library routines
766         id = (char *)alloca(3 + strlen(func) + buf.offset + sizeof(sz) * 3 + 1);
767         buf.writeByte(0);
768         if (flags & 1)
769             sprintf(id, "_aa%s%s%d", func, buf.data, sz);
770         else
771             sprintf(id, "_aa%s%s", func, buf.data);
772 #else
773         id = (char *)alloca(3 + strlen(func) + 1);
774         sprintf(id, "_aa%s", func);
775 #endif
776         if (!sarray)
777             sarray = new Array();
778
779         // See if symbol is already in sarray
780         for (i = 0; i < sarray->dim; i++)
781         {   s = (Symbol *)sarray->data[i];
782             if (strcmp(id, s->Sident) == 0)
783                 return s;                       // use existing Symbol
784         }
785
786         // Create new Symbol
787
788         s = symbol_calloc(id);
789         slist_add(s);
790         s->Sclass = SCextern;
791         s->Ssymnum = -1;
792         symbol_func(s);
793
794         t = type_alloc(TYnfunc);
795         t->Tflags = TFprototype | TFfixed;
796         t->Tmangle = mTYman_c;
797         t->Tparamtypes = NULL;
798         t->Tnext = next->toCtype();
799         t->Tnext->Tcount++;
800         t->Tcount++;
801         s->Stype = t;
802
803         sarray->push(s);                        // remember it
804         return s;
805     }
Note: See TracBrowser for help on using the browser.