Allow returning something of type void in a function that returns void
[delight/core.git] / dmd2 / tocsym.c
blobcd02fe174c19e95e394dc9c7756d610d891e58a8
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 Classsym *fake_classsym(Identifier *id);
48 /********************************* SymbolDeclaration ****************************/
50 SymbolDeclaration::SymbolDeclaration(Loc loc, Symbol *s, StructDeclaration *dsym)
51 : Declaration(new Identifier(s->Sident, TOKidentifier))
53 this->loc = loc;
54 sym = s;
55 this->dsym = dsym;
56 storage_class |= STCconst;
59 Symbol *SymbolDeclaration::toSymbol()
61 return sym;
64 /*************************************
65 * Helper
68 Symbol *Dsymbol::toSymbolX(const char *prefix, int sclass, type *t, const char *suffix)
70 Symbol *s;
71 char *id;
72 char *n;
73 size_t nlen;
75 //printf("Dsymbol::toSymbolX('%s')\n", prefix);
76 n = mangle();
77 assert(n);
78 nlen = strlen(n);
79 #if 0
80 if (nlen > 2 && n[0] == '_' && n[1] == 'D')
82 nlen -= 2;
83 n += 2;
85 #endif
86 id = (char *) alloca(2 + nlen + sizeof(size_t) * 3 + strlen(prefix) + strlen(suffix) + 1);
87 sprintf(id,"_D%s%d%s%s", n, strlen(prefix), prefix, suffix);
88 #if 0
89 if (global.params.isWindows &&
90 (type_mangle(t) == mTYman_c || type_mangle(t) == mTYman_std))
91 id++; // Windows C mangling will put the '_' back in
92 #endif
93 s = symbol_name(id, sclass, t);
94 //printf("-Dsymbol::toSymbolX() %s\n", id);
95 return s;
98 /*************************************
101 Symbol *Dsymbol::toSymbol()
103 fprintf(stderr, "Dsymbol::toSymbol() '%s', kind = '%s'\n", toChars(), kind());
104 #ifdef DEBUG
105 halt();
106 #endif
107 assert(0); // BUG: implement
108 return NULL;
111 /*********************************
112 * Generate import symbol from symbol.
115 Symbol *Dsymbol::toImport()
117 if (!isym)
119 if (!csym)
120 csym = toSymbol();
121 isym = toImport(csym);
123 return isym;
126 /*************************************
129 Symbol *Dsymbol::toImport(Symbol *sym)
131 char *id;
132 char *n;
133 Symbol *s;
134 type *t;
136 //printf("Dsymbol::toImport('%s')\n", sym->Sident);
137 n = sym->Sident;
138 id = (char *) alloca(6 + strlen(n) + 1 + sizeof(type_paramsize(sym->Stype))*3 + 1);
139 if (sym->Stype->Tmangle == mTYman_std && tyfunc(sym->Stype->Tty))
141 sprintf(id,"_imp__%s@%d",n,type_paramsize(sym->Stype));
143 else if (sym->Stype->Tmangle == mTYman_d)
144 sprintf(id,"_imp_%s",n);
145 else
146 sprintf(id,"_imp__%s",n);
147 t = type_alloc(TYnptr | mTYconst);
148 t->Tnext = sym->Stype;
149 t->Tnext->Tcount++;
150 t->Tmangle = mTYman_c;
151 t->Tcount++;
152 s = symbol_calloc(id);
153 s->Stype = t;
154 s->Sclass = SCextern;
155 s->Sfl = FLextern;
156 slist_add(s);
157 return s;
160 /*************************************
163 Symbol *VarDeclaration::toSymbol()
165 //printf("VarDeclaration::toSymbol(%s)\n", toChars());
166 //if (needThis()) *(char*)0=0;
167 assert(!needThis());
168 if (!csym)
169 { Symbol *s;
170 TYPE *t;
171 const char *id;
172 mangle_t m = 0;
174 if (isDataseg())
175 id = mangle();
176 else
177 id = ident->toChars();
178 s = symbol_calloc(id);
180 if (storage_class & (STCout | STCref))
182 if (global.params.symdebug && storage_class & STCparameter)
184 t = type_alloc(TYnptr); // should be TYref, but problems in back end
185 t->Tnext = type->toCtype();
186 t->Tnext->Tcount++;
188 else
189 t = type_fake(TYnptr);
191 else if (storage_class & STClazy)
192 t = type_fake(TYullong); // Tdelegate as C type
193 else if (isParameter())
194 t = type->toCParamtype();
195 else
196 t = type->toCtype();
197 t->Tcount++;
199 if (isDataseg())
201 if (storage_class & STCtls)
202 { /* Thread local storage
204 type_setty(&t, t->Tty | mTYthread);
206 s->Sclass = SCextern;
207 s->Sfl = FLextern;
208 slist_add(s);
210 else
212 s->Sclass = SCauto;
213 s->Sfl = FLauto;
215 if (nestedrefs.dim)
217 /* Symbol is accessed by a nested function. Make sure
218 * it is not put in a register, and that the optimizer
219 * assumes it is modified across function calls and pointer
220 * dereferences.
222 //printf("\tnested ref, not register\n");
223 type_setcv(&t, t->Tty | mTYvolatile);
226 if (isConst() || isInvariant())
228 // Insert const modifiers
229 type_setcv(&t, t->Tty | mTYconst);
231 switch (linkage)
233 case LINKwindows:
234 m = mTYman_std;
235 break;
237 case LINKpascal:
238 m = mTYman_pas;
239 break;
241 case LINKc:
242 m = mTYman_c;
243 break;
245 case LINKd:
246 m = mTYman_d;
247 break;
249 case LINKcpp:
250 m = mTYman_cpp;
251 break;
253 default:
254 fprintf(stderr, "linkage = %d\n", linkage);
255 assert(0);
257 type_setmangle(&t, m);
258 s->Stype = t;
260 csym = s;
262 return csym;
265 /*************************************
268 Symbol *ClassInfoDeclaration::toSymbol()
270 return cd->toSymbol();
273 /*************************************
276 Symbol *ModuleInfoDeclaration::toSymbol()
278 return mod->toSymbol();
281 /*************************************
284 Symbol *TypeInfoDeclaration::toSymbol()
286 //printf("TypeInfoDeclaration::toSymbol(%s), linkage = %d\n", toChars(), linkage);
287 return VarDeclaration::toSymbol();
290 /*************************************
293 Symbol *FuncAliasDeclaration::toSymbol()
295 return funcalias->toSymbol();
298 /*************************************
301 Symbol *FuncDeclaration::toSymbol()
303 if (!csym)
304 { Symbol *s;
305 TYPE *t;
306 const char *id;
308 #if 0
309 id = ident->toChars();
310 #else
311 id = mangle();
312 #endif
313 //printf("FuncDeclaration::toSymbol(%s %s)\n", kind(), toChars());
314 //printf("\tid = '%s'\n", id);
315 //printf("\ttype = %s\n", type->toChars());
316 s = symbol_calloc(id);
317 slist_add(s);
320 s->Sclass = SCglobal;
321 symbol_func(s);
322 func_t *f = s->Sfunc;
323 if (isVirtual())
324 f->Fflags |= Fvirtual;
325 else if (isMember2())
326 f->Fflags |= Fstatic;
327 f->Fstartline.Slinnum = loc.linnum;
328 f->Fstartline.Sfilename = loc.filename;
329 if (endloc.linnum)
330 { f->Fendline.Slinnum = endloc.linnum;
331 f->Fendline.Sfilename = endloc.filename;
333 else
334 { f->Fendline.Slinnum = loc.linnum;
335 f->Fendline.Sfilename = loc.filename;
337 t = type->toCtype();
340 mangle_t msave = t->Tmangle;
341 if (isMain())
343 t->Tty = TYnfunc;
344 t->Tmangle = mTYman_c;
346 else
348 switch (linkage)
350 case LINKwindows:
351 t->Tmangle = mTYman_std;
352 break;
354 case LINKpascal:
355 t->Tty = TYnpfunc;
356 t->Tmangle = mTYman_pas;
357 break;
359 case LINKc:
360 t->Tmangle = mTYman_c;
361 break;
363 case LINKd:
364 t->Tmangle = mTYman_d;
365 break;
367 case LINKcpp:
368 { t->Tmangle = mTYman_cpp;
369 #if !TARGET_LINUX
370 if (isThis())
371 t->Tty = TYmfunc;
372 #endif
373 s->Sflags |= SFLpublic;
374 Dsymbol *parent = toParent();
375 ClassDeclaration *cd = parent->isClassDeclaration();
376 if (cd)
378 ::type *t = cd->type->toCtype();
379 s->Sscope = t->Tnext->Ttag;
381 break;
383 default:
384 fprintf(stderr, "linkage = %d\n", linkage);
385 assert(0);
388 if (msave)
389 assert(msave == t->Tmangle);
390 //printf("Tty = %x, mangle = x%x\n", t->Tty, t->Tmangle);
391 t->Tcount++;
392 s->Stype = t;
393 //s->Sfielddef = this;
395 csym = s;
397 return csym;
400 /*************************************
403 Symbol *FuncDeclaration::toThunkSymbol(int offset)
405 Symbol *sthunk;
407 toSymbol();
409 #if 0
410 char *id;
411 char *n;
412 type *t;
414 n = sym->Sident;
415 id = (char *) alloca(8 + 5 + strlen(n) + 1);
416 sprintf(id,"_thunk%d__%s", offset, n);
417 s = symbol_calloc(id);
418 slist_add(s);
419 s->Stype = csym->Stype;
420 s->Stype->Tcount++;
421 #endif
422 sthunk = symbol_generate(SCstatic, csym->Stype);
423 sthunk->Sflags |= SFLimplem;
424 cod3_thunk(sthunk, csym, 0, TYnptr, -offset, -1, 0);
425 return sthunk;
429 /****************************************
430 * Create a static symbol we can hang DT initializers onto.
433 Symbol *static_sym()
435 Symbol *s;
436 type *t;
438 t = type_alloc(TYint);
439 t->Tcount++;
440 s = symbol_calloc("internal");
441 s->Sclass = SCstatic;
442 s->Sfl = FLextern;
443 s->Sflags |= SFLnodebug;
444 s->Stype = t;
445 #if ELFOBJ // Burton
446 s->Sseg = DATA;
447 #endif /* ELFOBJ */
448 slist_add(s);
449 return s;
452 /**************************************
453 * Fake a struct symbol.
456 Classsym *fake_classsym(Identifier *id)
457 { TYPE *t;
458 Classsym *scc;
460 scc = (Classsym *)symbol_calloc(id->toChars());
461 scc->Sclass = SCstruct;
462 scc->Sstruct = struct_calloc();
463 scc->Sstruct->Sstructalign = 8;
464 //scc->Sstruct->ptrtype = TYnptr;
465 scc->Sstruct->Sflags = STRglobal;
467 t = type_alloc(TYstruct);
468 t->Tflags |= TFsizeunknown | TFforward;
469 t->Ttag = scc; // structure tag name
470 assert(t->Tmangle == 0);
471 t->Tmangle = mTYman_d;
472 t->Tcount++;
473 scc->Stype = t;
474 slist_add(scc);
475 return scc;
478 /*************************************
479 * Create the "ClassInfo" symbol
482 static Classsym *scc;
484 Symbol *ClassDeclaration::toSymbol()
486 if (!csym)
488 Symbol *s;
490 if (!scc)
491 scc = fake_classsym(Id::ClassInfo);
493 s = toSymbolX("__Class", SCextern, scc->Stype, "Z");
494 s->Sfl = FLextern;
495 s->Sflags |= SFLnodebug;
496 csym = s;
497 slist_add(s);
499 return csym;
502 /*************************************
503 * Create the "InterfaceInfo" symbol
506 Symbol *InterfaceDeclaration::toSymbol()
508 if (!csym)
510 Symbol *s;
512 if (!scc)
513 scc = fake_classsym(Id::ClassInfo);
515 s = toSymbolX("__Interface", SCextern, scc->Stype, "Z");
516 s->Sfl = FLextern;
517 s->Sflags |= SFLnodebug;
518 csym = s;
519 slist_add(s);
521 return csym;
524 /*************************************
525 * Create the "ModuleInfo" symbol
528 Symbol *Module::toSymbol()
530 if (!csym)
532 Symbol *s;
533 static Classsym *scc;
535 if (!scc)
536 scc = fake_classsym(Id::ClassInfo);
538 s = toSymbolX("__ModuleInfo", SCextern, scc->Stype, "Z");
539 s->Sfl = FLextern;
540 s->Sflags |= SFLnodebug;
541 csym = s;
542 slist_add(s);
544 return csym;
547 /*************************************
548 * This is accessible via the ClassData, but since it is frequently
549 * needed directly (like for rtti comparisons), make it directly accessible.
552 Symbol *ClassDeclaration::toVtblSymbol()
554 if (!vtblsym)
556 Symbol *s;
557 TYPE *t;
559 if (!csym)
560 toSymbol();
562 t = type_alloc(TYnptr | mTYconst);
563 t->Tnext = tsvoid;
564 t->Tnext->Tcount++;
565 t->Tmangle = mTYman_d;
566 s = toSymbolX("__vtbl", SCextern, t, "Z");
567 s->Sflags |= SFLnodebug;
568 s->Sfl = FLextern;
569 vtblsym = s;
570 slist_add(s);
572 return vtblsym;
575 /**********************************
576 * Create the static initializer for the struct/class.
579 Symbol *AggregateDeclaration::toInitializer()
581 Symbol *s;
582 Classsym *stag;
584 if (!sinit)
586 stag = fake_classsym(Id::ClassInfo);
587 s = toSymbolX("__init", SCextern, stag->Stype, "Z");
588 s->Sfl = FLextern;
589 s->Sflags |= SFLnodebug;
590 slist_add(s);
591 sinit = s;
593 return sinit;
596 Symbol *TypedefDeclaration::toInitializer()
598 Symbol *s;
599 Classsym *stag;
601 if (!sinit)
603 stag = fake_classsym(Id::ClassInfo);
604 s = toSymbolX("__init", SCextern, stag->Stype, "Z");
605 s->Sfl = FLextern;
606 s->Sflags |= SFLnodebug;
607 slist_add(s);
608 sinit = s;
610 return sinit;
613 Symbol *EnumDeclaration::toInitializer()
615 Symbol *s;
616 Classsym *stag;
618 if (!sinit)
620 stag = fake_classsym(Id::ClassInfo);
621 Identifier *ident_save = ident;
622 if (!ident)
623 ident = Lexer::uniqueId("__enum");
624 s = toSymbolX("__init", SCextern, stag->Stype, "Z");
625 ident = ident_save;
626 s->Sfl = FLextern;
627 s->Sflags |= SFLnodebug;
628 slist_add(s);
629 sinit = s;
631 return sinit;
635 /******************************************
638 Symbol *Module::toModuleAssert()
640 if (!massert)
642 type *t;
644 t = type_alloc(TYjfunc);
645 t->Tflags |= TFprototype | TFfixed;
646 t->Tmangle = mTYman_d;
647 t->Tnext = tsvoid;
648 tsvoid->Tcount++;
650 massert = toSymbolX("__assert", SCextern, t, "FiZv");
651 massert->Sfl = FLextern;
652 massert->Sflags |= SFLnodebug;
653 slist_add(massert);
655 return massert;
658 /******************************************
661 Symbol *Module::toModuleArray()
663 if (!marray)
665 type *t;
667 t = type_alloc(TYjfunc);
668 t->Tflags |= TFprototype | TFfixed;
669 t->Tmangle = mTYman_d;
670 t->Tnext = tsvoid;
671 tsvoid->Tcount++;
673 marray = toSymbolX("__array", SCextern, t, "Z");
674 marray->Sfl = FLextern;
675 marray->Sflags |= SFLnodebug;
676 slist_add(marray);
678 return marray;
681 /********************************************
682 * Determine the right symbol to look up
683 * an associative array element.
684 * Input:
685 * flags 0 don't add value signature
686 * 1 add value signature
689 Symbol *TypeAArray::aaGetSymbol(char *func, int flags)
690 #if __DMC__
691 __in
693 assert(func);
694 assert((flags & ~1) == 0);
696 __out (result)
698 assert(result);
700 __body
701 #endif
703 int sz;
704 char *id;
705 type *t;
706 Symbol *s;
707 int i;
709 // Dumb linear symbol table - should use associative array!
710 static Array *sarray = NULL;
712 //printf("aaGetSymbol(func = '%s', flags = %d, key = %p)\n", func, flags, key);
713 #if 0
714 OutBuffer buf;
715 key->toKeyBuffer(&buf);
717 sz = next->size(); // it's just data, so we only care about the size
718 sz = (sz + 3) & ~3; // reduce proliferation of library routines
719 id = (char *)alloca(3 + strlen(func) + buf.offset + sizeof(sz) * 3 + 1);
720 buf.writeByte(0);
721 if (flags & 1)
722 sprintf(id, "_aa%s%s%d", func, buf.data, sz);
723 else
724 sprintf(id, "_aa%s%s", func, buf.data);
725 #else
726 id = (char *)alloca(3 + strlen(func) + 1);
727 sprintf(id, "_aa%s", func);
728 #endif
729 if (!sarray)
730 sarray = new Array();
732 // See if symbol is already in sarray
733 for (i = 0; i < sarray->dim; i++)
734 { s = (Symbol *)sarray->data[i];
735 if (strcmp(id, s->Sident) == 0)
736 return s; // use existing Symbol
739 // Create new Symbol
741 s = symbol_calloc(id);
742 slist_add(s);
743 s->Sclass = SCextern;
744 s->Ssymnum = -1;
745 symbol_func(s);
747 t = type_alloc(TYnfunc);
748 t->Tflags = TFprototype | TFfixed;
749 t->Tmangle = mTYman_c;
750 t->Tparamtypes = NULL;
751 t->Tnext = next->toCtype();
752 t->Tnext->Tcount++;
753 t->Tcount++;
754 s->Stype = t;
756 sarray->push(s); // remember it
757 return s;