Allow implicit conversion "foo*?" to "void*"
[delight/core.git] / dmd / tocsym.c
blob2b28ae6f6faa68c815512d999ecd4ca2c6aff280
2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2007 by Digital Mars
4 // All Rights Reserved
5 // written by Walter Bright
6 // http://www.digitalmars.com
7 // License for redistribution is by either the Artistic License
8 // in artistic.txt, or the GNU General Public License in gnu.txt.
9 // See the included readme.txt for details.
11 #include <stdio.h>
12 #include <stddef.h>
13 #include <time.h>
14 #include <assert.h>
15 #include "gdc_alloca.h"
17 #include "mars.h"
18 #include "module.h"
19 #include "mtype.h"
20 #include "declaration.h"
21 #include "statement.h"
22 #include "enum.h"
23 #include "aggregate.h"
24 #include "init.h"
25 #include "attrib.h"
26 #include "lexer.h"
27 #include "dsymbol.h"
28 #include "id.h"
30 #include <mem.h>
32 // Back end
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"
43 void slist_add(Symbol *s);
44 void slist_reset();
46 /********************************* SymbolDeclaration ****************************/
48 SymbolDeclaration::SymbolDeclaration(Loc loc, Symbol *s, StructDeclaration *dsym)
49 : Declaration(new Identifier(s->Sident, TOKidentifier))
51 this->loc = loc;
52 sym = s;
53 this->dsym = dsym;
54 storage_class |= STCconst;
57 Symbol *SymbolDeclaration::toSymbol()
59 return sym;
62 /*************************************
63 * Helper
66 Symbol *Dsymbol::toSymbolX(const char *prefix, int sclass, type *t, const char *suffix)
68 Symbol *s;
69 char *id;
70 char *n;
71 size_t nlen;
73 //printf("Dsymbol::toSymbolX('%s')\n", prefix);
74 n = mangle();
75 assert(n);
76 nlen = strlen(n);
77 #if 0
78 if (nlen > 2 && n[0] == '_' && n[1] == 'D')
80 nlen -= 2;
81 n += 2;
83 #endif
84 id = (char *) alloca(2 + nlen + sizeof(size_t) * 3 + strlen(prefix) + strlen(suffix) + 1);
85 sprintf(id,"_D%s%d%s%s", n, strlen(prefix), prefix, suffix);
86 #if 0
87 if (global.params.isWindows &&
88 (type_mangle(t) == mTYman_c || type_mangle(t) == mTYman_std))
89 id++; // Windows C mangling will put the '_' back in
90 #endif
91 s = symbol_name(id, sclass, t);
92 //printf("-Dsymbol::toSymbolX() %s\n", id);
93 return s;
96 /*************************************
99 Symbol *Dsymbol::toSymbol()
101 fprintf(stderr, "Dsymbol::toSymbol() '%s', kind = '%s'\n", toChars(), kind());
102 #ifdef DEBUG
103 halt();
104 #endif
105 assert(0); // BUG: implement
106 return NULL;
109 /*********************************
110 * Generate import symbol from symbol.
113 Symbol *Dsymbol::toImport()
115 if (!isym)
117 if (!csym)
118 csym = toSymbol();
119 isym = toImport(csym);
121 return isym;
124 /*************************************
127 Symbol *Dsymbol::toImport(Symbol *sym)
129 char *id;
130 char *n;
131 Symbol *s;
132 type *t;
134 //printf("Dsymbol::toImport('%s')\n", sym->Sident);
135 n = sym->Sident;
136 id = (char *) alloca(6 + strlen(n) + 1 + sizeof(type_paramsize(sym->Stype))*3 + 1);
137 if (sym->Stype->Tmangle == mTYman_std && tyfunc(sym->Stype->Tty))
139 sprintf(id,"_imp__%s@%d",n,type_paramsize(sym->Stype));
141 else if (sym->Stype->Tmangle == mTYman_d)
142 sprintf(id,"_imp_%s",n);
143 else
144 sprintf(id,"_imp__%s",n);
145 t = type_alloc(TYnptr | mTYconst);
146 t->Tnext = sym->Stype;
147 t->Tnext->Tcount++;
148 t->Tmangle = mTYman_c;
149 t->Tcount++;
150 s = symbol_calloc(id);
151 s->Stype = t;
152 s->Sclass = SCextern;
153 s->Sfl = FLextern;
154 slist_add(s);
155 return s;
158 /*************************************
161 Symbol *VarDeclaration::toSymbol()
163 //printf("VarDeclaration::toSymbol(%s)\n", toChars());
164 //if (needThis()) *(char*)0=0;
165 assert(!needThis());
166 if (!csym)
167 { Symbol *s;
168 TYPE *t;
169 const char *id;
170 mangle_t m = 0;
172 if (isDataseg())
173 id = mangle();
174 else
175 id = ident->toChars();
176 s = symbol_calloc(id);
178 if (storage_class & (STCout | STCref))
180 if (global.params.symdebug && storage_class & STCparameter)
182 t = type_alloc(TYnptr); // should be TYref, but problems in back end
183 t->Tnext = type->toCtype();
184 t->Tnext->Tcount++;
186 else
187 t = type_fake(TYnptr);
189 else if (storage_class & STClazy)
190 t = type_fake(TYullong); // Tdelegate as C type
191 else if (isParameter())
192 t = type->toCParamtype();
193 else
194 t = type->toCtype();
195 t->Tcount++;
197 if (isDataseg())
199 s->Sclass = SCextern;
200 s->Sfl = FLextern;
201 slist_add(s);
203 else
205 s->Sclass = SCauto;
206 s->Sfl = FLauto;
208 if (nestedref)
210 /* Symbol is accessed by a nested function. Make sure
211 * it is not put in a register, and that the optimizer
212 * assumes it is modified across function calls and pointer
213 * dereferences.
215 //printf("\tnested ref, not register\n");
216 type_setcv(&t, t->Tty | mTYvolatile);
219 if (storage_class & STCconst)
221 // Insert const modifiers
222 tym_t tym = 0;
224 if (storage_class & STCconst)
225 tym |= mTYconst;
226 type_setcv(&t, tym);
228 switch (linkage)
230 case LINKwindows:
231 m = mTYman_std;
232 break;
234 case LINKpascal:
235 m = mTYman_pas;
236 break;
238 case LINKc:
239 m = mTYman_c;
240 break;
242 case LINKd:
243 m = mTYman_d;
244 break;
246 case LINKcpp:
247 m = mTYman_cpp;
248 break;
250 default:
251 fprintf(stderr, "linkage = %d\n", linkage);
252 assert(0);
254 type_setmangle(&t, m);
255 s->Stype = t;
257 csym = s;
259 return csym;
262 /*************************************
265 Symbol *ClassInfoDeclaration::toSymbol()
267 return cd->toSymbol();
270 /*************************************
273 Symbol *ModuleInfoDeclaration::toSymbol()
275 return mod->toSymbol();
278 /*************************************
281 Symbol *TypeInfoDeclaration::toSymbol()
283 //printf("TypeInfoDeclaration::toSymbol(%s), linkage = %d\n", toChars(), linkage);
284 return VarDeclaration::toSymbol();
287 /*************************************
290 Symbol *FuncAliasDeclaration::toSymbol()
292 return funcalias->toSymbol();
295 /*************************************
298 Symbol *FuncDeclaration::toSymbol()
300 if (!csym)
301 { Symbol *s;
302 TYPE *t;
303 const char *id;
305 #if 0
306 id = ident->toChars();
307 #else
308 id = mangle();
309 #endif
310 //printf("FuncDeclaration::toSymbol(%s %s)\n", kind(), toChars());
311 //printf("\tid = '%s'\n", id);
312 //printf("\ttype = %s\n", type->toChars());
313 s = symbol_calloc(id);
314 slist_add(s);
316 { func_t *f;
318 s->Sclass = SCglobal;
319 symbol_func(s);
320 f = s->Sfunc;
321 f->Fstartline.Slinnum = loc.linnum;
322 f->Fstartline.Sfilename = loc.filename;
323 if (endloc.linnum)
324 { f->Fendline.Slinnum = endloc.linnum;
325 f->Fendline.Sfilename = endloc.filename;
327 else
328 { f->Fendline.Slinnum = loc.linnum;
329 f->Fendline.Sfilename = loc.filename;
331 t = type->toCtype();
334 mangle_t msave = t->Tmangle;
335 if (isMain())
337 t->Tty = TYnfunc;
338 t->Tmangle = mTYman_c;
340 else
342 switch (linkage)
344 case LINKwindows:
345 t->Tmangle = mTYman_std;
346 break;
348 case LINKpascal:
349 t->Tty = TYnpfunc;
350 t->Tmangle = mTYman_pas;
351 break;
353 case LINKc:
354 t->Tmangle = mTYman_c;
355 break;
357 case LINKd:
358 t->Tmangle = mTYman_d;
359 break;
361 case LINKcpp:
362 t->Tmangle = mTYman_cpp;
363 break;
365 default:
366 fprintf(stderr, "linkage = %d\n", linkage);
367 assert(0);
370 if (msave)
371 assert(msave == t->Tmangle);
372 //printf("Tty = %d, mangle = x%x\n", t->Tty, t->Tmangle);
373 t->Tcount++;
374 s->Stype = t;
375 //s->Sfielddef = this;
377 csym = s;
379 return csym;
382 /*************************************
385 Symbol *FuncDeclaration::toThunkSymbol(int offset)
387 Symbol *sthunk;
389 toSymbol();
391 #if 0
392 char *id;
393 char *n;
394 type *t;
396 n = sym->Sident;
397 id = (char *) alloca(8 + 5 + strlen(n) + 1);
398 sprintf(id,"_thunk%d__%s", offset, n);
399 s = symbol_calloc(id);
400 slist_add(s);
401 s->Stype = csym->Stype;
402 s->Stype->Tcount++;
403 #endif
404 sthunk = symbol_generate(SCstatic, csym->Stype);
405 sthunk->Sflags |= SFLimplem;
406 cod3_thunk(sthunk, csym, 0, TYnptr, -offset, -1, 0);
407 return sthunk;
411 /****************************************
412 * Create a static symbol we can hang DT initializers onto.
415 Symbol *static_sym()
417 Symbol *s;
418 type *t;
420 t = type_alloc(TYint);
421 t->Tcount++;
422 s = symbol_calloc("internal");
423 s->Sclass = SCstatic;
424 s->Sfl = FLextern;
425 s->Sflags |= SFLnodebug;
426 s->Stype = t;
427 #if ELFOBJ // Burton
428 s->Sseg = DATA;
429 #endif /* ELFOBJ */
430 slist_add(s);
431 return s;
434 /**************************************
435 * Fake a struct symbol.
438 Classsym *fake_classsym(char *name)
439 { TYPE *t;
440 Classsym *scc;
442 scc = (Classsym *)symbol_calloc("ClassInfo");
443 scc->Sclass = SCstruct;
444 scc->Sstruct = struct_calloc();
445 scc->Sstruct->Sstructalign = 8;
446 //scc->Sstruct->ptrtype = TYnptr;
447 scc->Sstruct->Sflags = STRglobal;
449 t = type_alloc(TYstruct);
450 t->Tflags |= TFsizeunknown | TFforward;
451 t->Ttag = scc; // structure tag name
452 assert(t->Tmangle == 0);
453 t->Tmangle = mTYman_d;
454 t->Tcount++;
455 scc->Stype = t;
456 slist_add(scc);
457 return scc;
460 /*************************************
461 * Create the "ClassInfo" symbol
464 static Classsym *scc;
466 Symbol *ClassDeclaration::toSymbol()
468 if (!csym)
470 Symbol *s;
472 if (!scc)
473 scc = fake_classsym("ClassInfo");
475 s = toSymbolX("__Class", SCextern, scc->Stype, "Z");
476 s->Sfl = FLextern;
477 s->Sflags |= SFLnodebug;
478 csym = s;
479 slist_add(s);
481 return csym;
484 /*************************************
485 * Create the "InterfaceInfo" symbol
488 Symbol *InterfaceDeclaration::toSymbol()
490 if (!csym)
492 Symbol *s;
494 if (!scc)
495 scc = fake_classsym("ClassInfo");
497 s = toSymbolX("__Interface", SCextern, scc->Stype, "Z");
498 s->Sfl = FLextern;
499 s->Sflags |= SFLnodebug;
500 csym = s;
501 slist_add(s);
503 return csym;
506 /*************************************
507 * Create the "ModuleInfo" symbol
510 Symbol *Module::toSymbol()
512 if (!csym)
514 Symbol *s;
515 static Classsym *scc;
517 if (!scc)
518 scc = fake_classsym("ModuleInfo");
520 s = toSymbolX("__ModuleInfo", SCextern, scc->Stype, "Z");
521 s->Sfl = FLextern;
522 s->Sflags |= SFLnodebug;
523 csym = s;
524 slist_add(s);
526 return csym;
529 /*************************************
530 * This is accessible via the ClassData, but since it is frequently
531 * needed directly (like for rtti comparisons), make it directly accessible.
534 Symbol *ClassDeclaration::toVtblSymbol()
536 if (!vtblsym)
538 Symbol *s;
539 TYPE *t;
541 if (!csym)
542 toSymbol();
544 t = type_alloc(TYnptr | mTYconst);
545 t->Tnext = tsvoid;
546 t->Tnext->Tcount++;
547 t->Tmangle = mTYman_d;
548 s = toSymbolX("__vtbl", SCextern, t, "Z");
549 s->Sflags |= SFLnodebug;
550 s->Sfl = FLextern;
551 vtblsym = s;
552 slist_add(s);
554 return vtblsym;
557 /**********************************
558 * Create the static initializer for the struct/class.
561 Symbol *AggregateDeclaration::toInitializer()
563 Symbol *s;
564 Classsym *stag;
566 if (!sinit)
568 stag = fake_classsym(NULL);
569 s = toSymbolX("__init", SCextern, stag->Stype, "Z");
570 s->Sfl = FLextern;
571 s->Sflags |= SFLnodebug;
572 slist_add(s);
573 sinit = s;
575 return sinit;
578 Symbol *TypedefDeclaration::toInitializer()
580 Symbol *s;
581 Classsym *stag;
583 if (!sinit)
585 stag = fake_classsym(NULL);
586 s = toSymbolX("__init", SCextern, stag->Stype, "Z");
587 s->Sfl = FLextern;
588 s->Sflags |= SFLnodebug;
589 slist_add(s);
590 sinit = s;
592 return sinit;
595 Symbol *EnumDeclaration::toInitializer()
597 Symbol *s;
598 Classsym *stag;
600 if (!sinit)
602 stag = fake_classsym(NULL);
603 Identifier *ident_save = ident;
604 if (!ident)
605 { static int num;
606 char name[6 + sizeof(num) * 3 + 1];
607 sprintf(name, "__enum%d", ++num);
608 ident = Lexer::idPool(name);
610 s = toSymbolX("__init", SCextern, stag->Stype, "Z");
611 ident = ident_save;
612 s->Sfl = FLextern;
613 s->Sflags |= SFLnodebug;
614 slist_add(s);
615 sinit = s;
617 return sinit;
621 /******************************************
624 Symbol *Module::toModuleAssert()
626 if (!massert)
628 type *t;
630 t = type_alloc(TYjfunc);
631 t->Tflags |= TFprototype | TFfixed;
632 t->Tmangle = mTYman_d;
633 t->Tnext = tsvoid;
634 tsvoid->Tcount++;
636 massert = toSymbolX("__assert", SCextern, t, "FiZv");
637 massert->Sfl = FLextern;
638 massert->Sflags |= SFLnodebug;
639 slist_add(massert);
641 return massert;
644 /******************************************
647 Symbol *Module::toModuleArray()
649 if (!marray)
651 type *t;
653 t = type_alloc(TYjfunc);
654 t->Tflags |= TFprototype | TFfixed;
655 t->Tmangle = mTYman_d;
656 t->Tnext = tsvoid;
657 tsvoid->Tcount++;
659 marray = toSymbolX("__array", SCextern, t, "Z");
660 marray->Sfl = FLextern;
661 marray->Sflags |= SFLnodebug;
662 slist_add(marray);
664 return marray;
667 /********************************************
668 * Determine the right symbol to look up
669 * an associative array element.
670 * Input:
671 * flags 0 don't add value signature
672 * 1 add value signature
675 Symbol *TypeAArray::aaGetSymbol(char *func, int flags)
676 #if __DMC__
677 __in
679 assert(func);
680 assert((flags & ~1) == 0);
682 __out (result)
684 assert(result);
686 __body
687 #endif
689 int sz;
690 char *id;
691 type *t;
692 Symbol *s;
693 int i;
695 // Dumb linear symbol table - should use associative array!
696 static Array *sarray = NULL;
698 //printf("aaGetSymbol(func = '%s', flags = %d, key = %p)\n", func, flags, key);
699 #if 0
700 OutBuffer buf;
701 key->toKeyBuffer(&buf);
703 sz = next->size(); // it's just data, so we only care about the size
704 sz = (sz + 3) & ~3; // reduce proliferation of library routines
705 id = (char *)alloca(3 + strlen(func) + buf.offset + sizeof(sz) * 3 + 1);
706 buf.writeByte(0);
707 if (flags & 1)
708 sprintf(id, "_aa%s%s%d", func, buf.data, sz);
709 else
710 sprintf(id, "_aa%s%s", func, buf.data);
711 #else
712 id = (char *)alloca(3 + strlen(func) + 1);
713 sprintf(id, "_aa%s", func);
714 #endif
715 if (!sarray)
716 sarray = new Array();
718 // See if symbol is already in sarray
719 for (i = 0; i < sarray->dim; i++)
720 { s = (Symbol *)sarray->data[i];
721 if (strcmp(id, s->Sident) == 0)
722 return s; // use existing Symbol
725 // Create new Symbol
727 s = symbol_calloc(id);
728 slist_add(s);
729 s->Sclass = SCextern;
730 s->Ssymnum = -1;
731 symbol_func(s);
733 t = type_alloc(TYnfunc);
734 t->Tflags = TFprototype | TFfixed;
735 t->Tmangle = mTYman_c;
736 t->Tparamtypes = NULL;
737 t->Tnext = next->toCtype();
738 t->Tnext->Tcount++;
739 t->Tcount++;
740 s->Stype = t;
742 sarray->push(s); // remember it
743 return s;