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 Classsym
*fake_classsym(Identifier
*id
);
48 /********************************* SymbolDeclaration ****************************/
50 SymbolDeclaration::SymbolDeclaration(Loc loc
, Symbol
*s
, StructDeclaration
*dsym
)
51 : Declaration(new Identifier(s
->Sident
, TOKidentifier
))
56 storage_class
|= STCconst
;
59 Symbol
*SymbolDeclaration::toSymbol()
64 /*************************************
68 Symbol
*Dsymbol::toSymbolX(const char *prefix
, int sclass
, type
*t
, const char *suffix
)
75 //printf("Dsymbol::toSymbolX('%s')\n", prefix);
80 if (nlen
> 2 && n
[0] == '_' && n
[1] == 'D')
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
);
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
93 s
= symbol_name(id
, sclass
, t
);
94 //printf("-Dsymbol::toSymbolX() %s\n", id);
98 /*************************************
101 Symbol
*Dsymbol::toSymbol()
103 fprintf(stderr
, "Dsymbol::toSymbol() '%s', kind = '%s'\n", toChars(), kind());
107 assert(0); // BUG: implement
111 /*********************************
112 * Generate import symbol from symbol.
115 Symbol
*Dsymbol::toImport()
121 isym
= toImport(csym
);
126 /*************************************
129 Symbol
*Dsymbol::toImport(Symbol
*sym
)
136 //printf("Dsymbol::toImport('%s')\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
);
146 sprintf(id
,"_imp__%s",n
);
147 t
= type_alloc(TYnptr
| mTYconst
);
148 t
->Tnext
= sym
->Stype
;
150 t
->Tmangle
= mTYman_c
;
152 s
= symbol_calloc(id
);
154 s
->Sclass
= SCextern
;
160 /*************************************
163 Symbol
*VarDeclaration::toSymbol()
165 //printf("VarDeclaration::toSymbol(%s)\n", toChars());
166 //if (needThis()) *(char*)0=0;
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();
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();
201 if (storage_class
& STCtls
)
202 { /* Thread local storage
204 type_setty(&t
, t
->Tty
| mTYthread
);
206 s
->Sclass
= SCextern
;
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
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
);
254 fprintf(stderr
, "linkage = %d\n", linkage
);
257 type_setmangle(&t
, m
);
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()
309 id
= ident
->toChars();
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
);
320 s
->Sclass
= SCglobal
;
322 func_t
*f
= s
->Sfunc
;
324 f
->Fflags
|= Fvirtual
;
325 else if (isMember2())
326 f
->Fflags
|= Fstatic
;
327 f
->Fstartline
.Slinnum
= loc
.linnum
;
328 f
->Fstartline
.Sfilename
= loc
.filename
;
330 { f
->Fendline
.Slinnum
= endloc
.linnum
;
331 f
->Fendline
.Sfilename
= endloc
.filename
;
334 { f
->Fendline
.Slinnum
= loc
.linnum
;
335 f
->Fendline
.Sfilename
= loc
.filename
;
340 mangle_t msave
= t
->Tmangle
;
344 t
->Tmangle
= mTYman_c
;
351 t
->Tmangle
= mTYman_std
;
356 t
->Tmangle
= mTYman_pas
;
360 t
->Tmangle
= mTYman_c
;
364 t
->Tmangle
= mTYman_d
;
368 { t
->Tmangle
= mTYman_cpp
;
373 s
->Sflags
|= SFLpublic
;
374 Dsymbol
*parent
= toParent();
375 ClassDeclaration
*cd
= parent
->isClassDeclaration();
378 ::type
*t
= cd
->type
->toCtype();
379 s
->Sscope
= t
->Tnext
->Ttag
;
384 fprintf(stderr
, "linkage = %d\n", linkage
);
389 assert(msave
== t
->Tmangle
);
390 //printf("Tty = %x, mangle = x%x\n", t->Tty, t->Tmangle);
393 //s->Sfielddef = this;
400 /*************************************
403 Symbol
*FuncDeclaration::toThunkSymbol(int offset
)
415 id
= (char *) alloca(8 + 5 + strlen(n
) + 1);
416 sprintf(id
,"_thunk%d__%s", offset
, n
);
417 s
= symbol_calloc(id
);
419 s
->Stype
= csym
->Stype
;
422 sthunk
= symbol_generate(SCstatic
, csym
->Stype
);
423 sthunk
->Sflags
|= SFLimplem
;
424 cod3_thunk(sthunk
, csym
, 0, TYnptr
, -offset
, -1, 0);
429 /****************************************
430 * Create a static symbol we can hang DT initializers onto.
438 t
= type_alloc(TYint
);
440 s
= symbol_calloc("internal");
441 s
->Sclass
= SCstatic
;
443 s
->Sflags
|= SFLnodebug
;
452 /**************************************
453 * Fake a struct symbol.
456 Classsym
*fake_classsym(Identifier
*id
)
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
;
478 /*************************************
479 * Create the "ClassInfo" symbol
482 static Classsym
*scc
;
484 Symbol
*ClassDeclaration::toSymbol()
491 scc
= fake_classsym(Id::ClassInfo
);
493 s
= toSymbolX("__Class", SCextern
, scc
->Stype
, "Z");
495 s
->Sflags
|= SFLnodebug
;
502 /*************************************
503 * Create the "InterfaceInfo" symbol
506 Symbol
*InterfaceDeclaration::toSymbol()
513 scc
= fake_classsym(Id::ClassInfo
);
515 s
= toSymbolX("__Interface", SCextern
, scc
->Stype
, "Z");
517 s
->Sflags
|= SFLnodebug
;
524 /*************************************
525 * Create the "ModuleInfo" symbol
528 Symbol
*Module::toSymbol()
533 static Classsym
*scc
;
536 scc
= fake_classsym(Id::ClassInfo
);
538 s
= toSymbolX("__ModuleInfo", SCextern
, scc
->Stype
, "Z");
540 s
->Sflags
|= SFLnodebug
;
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()
562 t
= type_alloc(TYnptr
| mTYconst
);
565 t
->Tmangle
= mTYman_d
;
566 s
= toSymbolX("__vtbl", SCextern
, t
, "Z");
567 s
->Sflags
|= SFLnodebug
;
575 /**********************************
576 * Create the static initializer for the struct/class.
579 Symbol
*AggregateDeclaration::toInitializer()
586 stag
= fake_classsym(Id::ClassInfo
);
587 s
= toSymbolX("__init", SCextern
, stag
->Stype
, "Z");
589 s
->Sflags
|= SFLnodebug
;
596 Symbol
*TypedefDeclaration::toInitializer()
603 stag
= fake_classsym(Id::ClassInfo
);
604 s
= toSymbolX("__init", SCextern
, stag
->Stype
, "Z");
606 s
->Sflags
|= SFLnodebug
;
613 Symbol
*EnumDeclaration::toInitializer()
620 stag
= fake_classsym(Id::ClassInfo
);
621 Identifier
*ident_save
= ident
;
623 ident
= Lexer::uniqueId("__enum");
624 s
= toSymbolX("__init", SCextern
, stag
->Stype
, "Z");
627 s
->Sflags
|= SFLnodebug
;
635 /******************************************
638 Symbol
*Module::toModuleAssert()
644 t
= type_alloc(TYjfunc
);
645 t
->Tflags
|= TFprototype
| TFfixed
;
646 t
->Tmangle
= mTYman_d
;
650 massert
= toSymbolX("__assert", SCextern
, t
, "FiZv");
651 massert
->Sfl
= FLextern
;
652 massert
->Sflags
|= SFLnodebug
;
658 /******************************************
661 Symbol
*Module::toModuleArray()
667 t
= type_alloc(TYjfunc
);
668 t
->Tflags
|= TFprototype
| TFfixed
;
669 t
->Tmangle
= mTYman_d
;
673 marray
= toSymbolX("__array", SCextern
, t
, "Z");
674 marray
->Sfl
= FLextern
;
675 marray
->Sflags
|= SFLnodebug
;
681 /********************************************
682 * Determine the right symbol to look up
683 * an associative array element.
685 * flags 0 don't add value signature
686 * 1 add value signature
689 Symbol
*TypeAArray::aaGetSymbol(char *func
, int flags
)
694 assert((flags
& ~1) == 0);
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);
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);
722 sprintf(id
, "_aa%s%s%d", func
, buf
.data
, sz
);
724 sprintf(id
, "_aa%s%s", func
, buf
.data
);
726 id
= (char *)alloca(3 + strlen(func
) + 1);
727 sprintf(id
, "_aa%s", func
);
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
741 s
= symbol_calloc(id
);
743 s
->Sclass
= SCextern
;
747 t
= type_alloc(TYnfunc
);
748 t
->Tflags
= TFprototype
| TFfixed
;
749 t
->Tmangle
= mTYman_c
;
750 t
->Tparamtypes
= NULL
;
751 t
->Tnext
= next
->toCtype();
756 sarray
->push(s
); // remember it