2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2007 by Digital Mars
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.
15 #include "gdc_alloca.h"
20 #include "declaration.h"
21 #include "statement.h"
23 #include "aggregate.h"
43 void slist_add(Symbol
*s
);
46 /********************************* SymbolDeclaration ****************************/
48 SymbolDeclaration::SymbolDeclaration(Loc loc
, Symbol
*s
, StructDeclaration
*dsym
)
49 : Declaration(new Identifier(s
->Sident
, TOKidentifier
))
54 storage_class
|= STCconst
;
57 Symbol
*SymbolDeclaration::toSymbol()
62 /*************************************
66 Symbol
*Dsymbol::toSymbolX(const char *prefix
, int sclass
, type
*t
, const char *suffix
)
73 //printf("Dsymbol::toSymbolX('%s')\n", prefix);
78 if (nlen
> 2 && n
[0] == '_' && n
[1] == 'D')
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
);
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
91 s
= symbol_name(id
, sclass
, t
);
92 //printf("-Dsymbol::toSymbolX() %s\n", id);
96 /*************************************
99 Symbol
*Dsymbol::toSymbol()
101 fprintf(stderr
, "Dsymbol::toSymbol() '%s', kind = '%s'\n", toChars(), kind());
105 assert(0); // BUG: implement
109 /*********************************
110 * Generate import symbol from symbol.
113 Symbol
*Dsymbol::toImport()
119 isym
= toImport(csym
);
124 /*************************************
127 Symbol
*Dsymbol::toImport(Symbol
*sym
)
134 //printf("Dsymbol::toImport('%s')\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
);
144 sprintf(id
,"_imp__%s",n
);
145 t
= type_alloc(TYnptr
| mTYconst
);
146 t
->Tnext
= sym
->Stype
;
148 t
->Tmangle
= mTYman_c
;
150 s
= symbol_calloc(id
);
152 s
->Sclass
= SCextern
;
158 /*************************************
161 Symbol
*VarDeclaration::toSymbol()
163 //printf("VarDeclaration::toSymbol(%s)\n", toChars());
164 //if (needThis()) *(char*)0=0;
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();
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();
199 s
->Sclass
= SCextern
;
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
215 //printf("\tnested ref, not register\n");
216 type_setcv(&t
, t
->Tty
| mTYvolatile
);
219 if (storage_class
& STCconst
)
221 // Insert const modifiers
224 if (storage_class
& STCconst
)
251 fprintf(stderr
, "linkage = %d\n", linkage
);
254 type_setmangle(&t
, m
);
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()
306 id
= ident
->toChars();
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
);
318 s
->Sclass
= SCglobal
;
321 f
->Fstartline
.Slinnum
= loc
.linnum
;
322 f
->Fstartline
.Sfilename
= loc
.filename
;
324 { f
->Fendline
.Slinnum
= endloc
.linnum
;
325 f
->Fendline
.Sfilename
= endloc
.filename
;
328 { f
->Fendline
.Slinnum
= loc
.linnum
;
329 f
->Fendline
.Sfilename
= loc
.filename
;
334 mangle_t msave
= t
->Tmangle
;
338 t
->Tmangle
= mTYman_c
;
345 t
->Tmangle
= mTYman_std
;
350 t
->Tmangle
= mTYman_pas
;
354 t
->Tmangle
= mTYman_c
;
358 t
->Tmangle
= mTYman_d
;
362 t
->Tmangle
= mTYman_cpp
;
366 fprintf(stderr
, "linkage = %d\n", linkage
);
371 assert(msave
== t
->Tmangle
);
372 //printf("Tty = %d, mangle = x%x\n", t->Tty, t->Tmangle);
375 //s->Sfielddef = this;
382 /*************************************
385 Symbol
*FuncDeclaration::toThunkSymbol(int offset
)
397 id
= (char *) alloca(8 + 5 + strlen(n
) + 1);
398 sprintf(id
,"_thunk%d__%s", offset
, n
);
399 s
= symbol_calloc(id
);
401 s
->Stype
= csym
->Stype
;
404 sthunk
= symbol_generate(SCstatic
, csym
->Stype
);
405 sthunk
->Sflags
|= SFLimplem
;
406 cod3_thunk(sthunk
, csym
, 0, TYnptr
, -offset
, -1, 0);
411 /****************************************
412 * Create a static symbol we can hang DT initializers onto.
420 t
= type_alloc(TYint
);
422 s
= symbol_calloc("internal");
423 s
->Sclass
= SCstatic
;
425 s
->Sflags
|= SFLnodebug
;
434 /**************************************
435 * Fake a struct symbol.
438 Classsym
*fake_classsym(char *name
)
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
;
460 /*************************************
461 * Create the "ClassInfo" symbol
464 static Classsym
*scc
;
466 Symbol
*ClassDeclaration::toSymbol()
473 scc
= fake_classsym("ClassInfo");
475 s
= toSymbolX("__Class", SCextern
, scc
->Stype
, "Z");
477 s
->Sflags
|= SFLnodebug
;
484 /*************************************
485 * Create the "InterfaceInfo" symbol
488 Symbol
*InterfaceDeclaration::toSymbol()
495 scc
= fake_classsym("ClassInfo");
497 s
= toSymbolX("__Interface", SCextern
, scc
->Stype
, "Z");
499 s
->Sflags
|= SFLnodebug
;
506 /*************************************
507 * Create the "ModuleInfo" symbol
510 Symbol
*Module::toSymbol()
515 static Classsym
*scc
;
518 scc
= fake_classsym("ModuleInfo");
520 s
= toSymbolX("__ModuleInfo", SCextern
, scc
->Stype
, "Z");
522 s
->Sflags
|= SFLnodebug
;
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()
544 t
= type_alloc(TYnptr
| mTYconst
);
547 t
->Tmangle
= mTYman_d
;
548 s
= toSymbolX("__vtbl", SCextern
, t
, "Z");
549 s
->Sflags
|= SFLnodebug
;
557 /**********************************
558 * Create the static initializer for the struct/class.
561 Symbol
*AggregateDeclaration::toInitializer()
568 stag
= fake_classsym(NULL
);
569 s
= toSymbolX("__init", SCextern
, stag
->Stype
, "Z");
571 s
->Sflags
|= SFLnodebug
;
578 Symbol
*TypedefDeclaration::toInitializer()
585 stag
= fake_classsym(NULL
);
586 s
= toSymbolX("__init", SCextern
, stag
->Stype
, "Z");
588 s
->Sflags
|= SFLnodebug
;
595 Symbol
*EnumDeclaration::toInitializer()
602 stag
= fake_classsym(NULL
);
603 Identifier
*ident_save
= ident
;
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");
613 s
->Sflags
|= SFLnodebug
;
621 /******************************************
624 Symbol
*Module::toModuleAssert()
630 t
= type_alloc(TYjfunc
);
631 t
->Tflags
|= TFprototype
| TFfixed
;
632 t
->Tmangle
= mTYman_d
;
636 massert
= toSymbolX("__assert", SCextern
, t
, "FiZv");
637 massert
->Sfl
= FLextern
;
638 massert
->Sflags
|= SFLnodebug
;
644 /******************************************
647 Symbol
*Module::toModuleArray()
653 t
= type_alloc(TYjfunc
);
654 t
->Tflags
|= TFprototype
| TFfixed
;
655 t
->Tmangle
= mTYman_d
;
659 marray
= toSymbolX("__array", SCextern
, t
, "Z");
660 marray
->Sfl
= FLextern
;
661 marray
->Sflags
|= SFLnodebug
;
667 /********************************************
668 * Determine the right symbol to look up
669 * an associative array element.
671 * flags 0 don't add value signature
672 * 1 add value signature
675 Symbol
*TypeAArray::aaGetSymbol(char *func
, int flags
)
680 assert((flags
& ~1) == 0);
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);
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);
708 sprintf(id
, "_aa%s%s%d", func
, buf
.data
, sz
);
710 sprintf(id
, "_aa%s%s", func
, buf
.data
);
712 id
= (char *)alloca(3 + strlen(func
) + 1);
713 sprintf(id
, "_aa%s", func
);
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
727 s
= symbol_calloc(id
);
729 s
->Sclass
= SCextern
;
733 t
= type_alloc(TYnfunc
);
734 t
->Tflags
= TFprototype
| TFfixed
;
735 t
->Tmangle
= mTYman_c
;
736 t
->Tparamtypes
= NULL
;
737 t
->Tnext
= next
->toCtype();
742 sarray
->push(s
); // remember it