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.
11 /* NOTE: This file has been patched from the original DMD distribution to
12 work with the GDC compiler.
14 Modified by David Friedman, September 2004
27 #include "expression.h"
29 #include "declaration.h"
34 #include "aggregate.h"
50 #include "d-dmd-gcc.h"
53 extern Symbol
*static_sym();
55 /*******************************************
56 * Get a canonicalized form of the TypeInfo for use with the internal
57 * runtime library routines. Canonicalized in that static arrays are
58 * represented as dynamic arrays, enums are represented by their
59 * underlying type, etc. This reduces the number of TypeInfo's needed,
60 * so we can use the custom internal ones more.
63 Expression
*Type::getInternalTypeInfo(Scope
*sc
)
64 { TypeInfoDeclaration
*tid
;
67 static TypeInfoDeclaration
*internalTI
[TMAX
];
69 //printf("Type::getInternalTypeInfo() %s\n", toChars());
75 t
= t
->next
->arrayOf(); // convert to corresponding dynamic array type
80 if (((TypeClass
*)t
)->sym
->isInterfaceDeclaration())
85 if (t
->next
->ty
!= Tclass
)
93 tid
= internalTI
[t
->ty
];
95 { tid
= new TypeInfoDeclaration(t
, 1);
96 internalTI
[t
->ty
] = tid
;
98 e
= new VarExp(0, tid
);
100 e
->type
= tid
->type
; // do this so we don't get redundant dereference
106 //printf("\tcalling getTypeInfo() %s\n", t->toChars());
107 return t
->getTypeInfo(sc
);
111 /****************************************************
112 * Get the exact TypeInfo.
115 Expression
*Type::getTypeInfo(Scope
*sc
)
120 //printf("Type::getTypeInfo() %p, %s\n", this, toChars());
121 t
= merge(); // do this since not all Type's are merge'd
123 { t
->vtinfo
= t
->getTypeInfoDeclaration();
126 /* If this has a custom implementation in std/typeinfo, then
127 * do not generate a COMDAT for it.
129 if (!t
->builtinTypeInfo())
131 if (sc
) // if in semantic() pass
132 { // Find module that will go all the way to an object file
133 Module
*m
= sc
->module
->importedFrom
;
134 m
->members
->push(t
->vtinfo
);
136 else // if in obj generation pass
138 t
->vtinfo
->toObjFile(global
.params
.multiobj
);
142 e
= new VarExp(0, t
->vtinfo
);
143 e
= e
->addressOf(sc
);
144 e
->type
= t
->vtinfo
->type
; // do this so we don't get redundant dereference
148 TypeInfoDeclaration
*Type::getTypeInfoDeclaration()
150 //printf("Type::getTypeInfoDeclaration() %s\n", toChars());
151 return new TypeInfoDeclaration(this, 0);
154 TypeInfoDeclaration
*TypeTypedef::getTypeInfoDeclaration()
156 return new TypeInfoTypedefDeclaration(this);
159 TypeInfoDeclaration
*TypePointer::getTypeInfoDeclaration()
161 return new TypeInfoPointerDeclaration(this);
164 TypeInfoDeclaration
*TypeMaybe::getTypeInfoDeclaration()
166 return new TypeInfoMaybeDeclaration(this);
169 TypeInfoDeclaration
*TypeDArray::getTypeInfoDeclaration()
171 return new TypeInfoArrayDeclaration(this);
174 TypeInfoDeclaration
*TypeSArray::getTypeInfoDeclaration()
176 return new TypeInfoStaticArrayDeclaration(this);
179 TypeInfoDeclaration
*TypeAArray::getTypeInfoDeclaration()
181 return new TypeInfoAssociativeArrayDeclaration(this);
184 TypeInfoDeclaration
*TypeStruct::getTypeInfoDeclaration()
186 return new TypeInfoStructDeclaration(this);
189 TypeInfoDeclaration
*TypeClass::getTypeInfoDeclaration()
191 if (sym
->isInterfaceDeclaration())
192 return new TypeInfoInterfaceDeclaration(this);
194 return new TypeInfoClassDeclaration(this);
197 TypeInfoDeclaration
*TypeEnum::getTypeInfoDeclaration()
199 return new TypeInfoEnumDeclaration(this);
202 TypeInfoDeclaration
*TypeFunction::getTypeInfoDeclaration()
204 return new TypeInfoFunctionDeclaration(this);
207 TypeInfoDeclaration
*TypeDelegate::getTypeInfoDeclaration()
209 return new TypeInfoDelegateDeclaration(this);
212 TypeInfoDeclaration
*TypeTuple::getTypeInfoDeclaration()
214 return new TypeInfoTupleDeclaration(this);
218 /****************************************************
223 void TypeInfoDeclaration::toDt(dt_t
**pdt
)
225 //printf("TypeInfoDeclaration::toDt() %s\n", toChars());
226 dtxoff(pdt
, Type::typeinfo
->toVtblSymbol(), 0, TYnptr
); // vtbl for TypeInfo
227 dtdword(pdt
, 0); // monitor
230 void TypeInfoTypedefDeclaration::toDt(dt_t
**pdt
)
232 //printf("TypeInfoTypedefDeclaration::toDt() %s\n", toChars());
234 dtxoff(pdt
, Type::typeinfotypedef
->toVtblSymbol(), 0, TYnptr
); // vtbl for TypeInfo_Typedef
235 dtdword(pdt
, 0); // monitor
237 assert(tinfo
->ty
== Ttypedef
);
239 TypeTypedef
*tc
= (TypeTypedef
*)tinfo
;
240 TypedefDeclaration
*sd
= tc
->sym
;
241 //printf("basetype = %s\n", sd->basetype->toChars());
249 sd
->basetype
= sd
->basetype
->merge();
250 sd
->basetype
->getTypeInfo(NULL
); // generate vtinfo
251 assert(sd
->basetype
->vtinfo
);
252 dtxoff(pdt
, sd
->basetype
->vtinfo
->toSymbol(), 0, TYnptr
); // TypeInfo for basetype
254 char *name
= sd
->toPrettyChars();
255 size_t namelen
= strlen(name
);
256 dtdword(pdt
, namelen
);
257 dtabytes(pdt
, TYnptr
, 0, namelen
+ 1, name
);
260 if (tinfo
->isZeroInit() || !sd
->init
)
261 { // 0 initializer, or the same as the base type
262 dtdword(pdt
, 0); // init.length
263 dtdword(pdt
, 0); // init.ptr
267 dtdword(pdt
, sd
->type
->size()); // init.length
268 dtxoff(pdt
, sd
->toInitializer(), 0, TYnptr
); // init.ptr
272 void TypeInfoEnumDeclaration::toDt(dt_t
**pdt
)
274 //printf("TypeInfoEnumDeclaration::toDt()\n");
275 dtxoff(pdt
, Type::typeinfoenum
->toVtblSymbol(), 0, TYnptr
); // vtbl for TypeInfo_Enum
276 dtdword(pdt
, 0); // monitor
278 assert(tinfo
->ty
== Tenum
);
280 TypeEnum
*tc
= (TypeEnum
*)tinfo
;
281 EnumDeclaration
*sd
= tc
->sym
;
289 sd
->memtype
->getTypeInfo(NULL
);
290 dtxoff(pdt
, sd
->memtype
->vtinfo
->toSymbol(), 0, TYnptr
); // TypeInfo for enum members
292 char *name
= sd
->toPrettyChars();
293 size_t namelen
= strlen(name
);
294 dtdword(pdt
, namelen
);
295 dtabytes(pdt
, TYnptr
, 0, namelen
+ 1, name
);
298 if (tinfo
->isZeroInit() || !sd
->defaultval
)
299 { // 0 initializer, or the same as the base type
300 dtdword(pdt
, 0); // init.length
301 dtdword(pdt
, 0); // init.ptr
305 dtdword(pdt
, sd
->type
->size()); // init.length
306 dtxoff(pdt
, sd
->toInitializer(), 0, TYnptr
); // init.ptr
310 void TypeInfoPointerDeclaration::toDt(dt_t
**pdt
)
312 //printf("TypeInfoPointerDeclaration::toDt()\n");
313 dtxoff(pdt
, Type::typeinfopointer
->toVtblSymbol(), 0, TYnptr
); // vtbl for TypeInfo_Pointer
314 dtdword(pdt
, 0); // monitor
316 assert(tinfo
->ty
== Tpointer
);
318 TypePointer
*tc
= (TypePointer
*)tinfo
;
320 tc
->next
->getTypeInfo(NULL
);
321 dtxoff(pdt
, tc
->next
->vtinfo
->toSymbol(), 0, TYnptr
); // TypeInfo for type being pointed to
324 void TypeInfoMaybeDeclaration::toDt(dt_t
**pdt
)
326 //printf("TypeInfoMaybeDeclaration::toDt()\n");
327 dtxoff(pdt
, Type::typeinfomaybe
->toVtblSymbol(), 0, TYnptr
); // vtbl for TypeInfo_Maybe
328 dtdword(pdt
, 0); // monitor
330 assert(tinfo
->ty
== Tmaybe
);
332 TypeMaybe
*tc
= (TypeMaybe
*)tinfo
;
334 tc
->next
->getTypeInfo(NULL
);
335 dtxoff(pdt
, tc
->next
->vtinfo
->toSymbol(), 0, TYnptr
); // TypeInfo for pointer type
338 void TypeInfoArrayDeclaration::toDt(dt_t
**pdt
)
340 //printf("TypeInfoArrayDeclaration::toDt()\n");
341 dtxoff(pdt
, Type::typeinfoarray
->toVtblSymbol(), 0, TYnptr
); // vtbl for TypeInfo_Array
342 dtdword(pdt
, 0); // monitor
344 assert(tinfo
->ty
== Tarray
);
346 TypeDArray
*tc
= (TypeDArray
*)tinfo
;
348 tc
->next
->getTypeInfo(NULL
);
349 dtxoff(pdt
, tc
->next
->vtinfo
->toSymbol(), 0, TYnptr
); // TypeInfo for array of type
352 void TypeInfoStaticArrayDeclaration::toDt(dt_t
**pdt
)
354 //printf("TypeInfoStaticArrayDeclaration::toDt()\n");
355 dtxoff(pdt
, Type::typeinfostaticarray
->toVtblSymbol(), 0, TYnptr
); // vtbl for TypeInfo_StaticArray
356 dtdword(pdt
, 0); // monitor
358 assert(tinfo
->ty
== Tsarray
);
360 TypeSArray
*tc
= (TypeSArray
*)tinfo
;
362 tc
->next
->getTypeInfo(NULL
);
363 dtxoff(pdt
, tc
->next
->vtinfo
->toSymbol(), 0, TYnptr
); // TypeInfo for array of type
365 dtdword(pdt
, tc
->dim
->toInteger()); // length
368 void TypeInfoAssociativeArrayDeclaration::toDt(dt_t
**pdt
)
370 //printf("TypeInfoAssociativeArrayDeclaration::toDt()\n");
371 dtxoff(pdt
, Type::typeinfoassociativearray
->toVtblSymbol(), 0, TYnptr
); // vtbl for TypeInfo_AssociativeArray
372 dtdword(pdt
, 0); // monitor
374 assert(tinfo
->ty
== Taarray
);
376 TypeAArray
*tc
= (TypeAArray
*)tinfo
;
378 tc
->next
->getTypeInfo(NULL
);
379 dtxoff(pdt
, tc
->next
->vtinfo
->toSymbol(), 0, TYnptr
); // TypeInfo for array of type
381 tc
->index
->getTypeInfo(NULL
);
382 dtxoff(pdt
, tc
->index
->vtinfo
->toSymbol(), 0, TYnptr
); // TypeInfo for array of type
385 void TypeInfoFunctionDeclaration::toDt(dt_t
**pdt
)
387 //printf("TypeInfoFunctionDeclaration::toDt()\n");
388 dtxoff(pdt
, Type::typeinfofunction
->toVtblSymbol(), 0, TYnptr
); // vtbl for TypeInfo_Function
389 dtdword(pdt
, 0); // monitor
391 assert(tinfo
->ty
== Tfunction
);
393 TypeFunction
*tc
= (TypeFunction
*)tinfo
;
395 tc
->next
->getTypeInfo(NULL
);
396 dtxoff(pdt
, tc
->next
->vtinfo
->toSymbol(), 0, TYnptr
); // TypeInfo for function return value
399 void TypeInfoDelegateDeclaration::toDt(dt_t
**pdt
)
401 //printf("TypeInfoDelegateDeclaration::toDt()\n");
402 dtxoff(pdt
, Type::typeinfodelegate
->toVtblSymbol(), 0, TYnptr
); // vtbl for TypeInfo_Delegate
403 dtdword(pdt
, 0); // monitor
405 assert(tinfo
->ty
== Tdelegate
);
407 TypeDelegate
*tc
= (TypeDelegate
*)tinfo
;
409 tc
->next
->next
->getTypeInfo(NULL
);
410 dtxoff(pdt
, tc
->next
->next
->vtinfo
->toSymbol(), 0, TYnptr
); // TypeInfo for delegate return value
413 void TypeInfoStructDeclaration::toDt(dt_t
**pdt
)
415 //printf("TypeInfoStructDeclaration::toDt() '%s'\n", toChars());
417 unsigned offset
= Type::typeinfostruct
->structsize
;
419 dtxoff(pdt
, Type::typeinfostruct
->toVtblSymbol(), 0, TYnptr
); // vtbl for TypeInfo_Struct
420 dtdword(pdt
, 0); // monitor
422 assert(tinfo
->ty
== Tstruct
);
424 TypeStruct
*tc
= (TypeStruct
*)tinfo
;
425 StructDeclaration
*sd
= tc
->sym
;
430 * hash_t function(void*) xtoHash;
431 * int function(void*,void*) xopEquals;
432 * int function(void*,void*) xopCmp;
433 * char[] function(void*) xtoString;
439 char *name
= sd
->toPrettyChars();
440 size_t namelen
= strlen(name
);
441 dtdword(pdt
, namelen
);
442 //dtabytes(pdt, TYnptr, 0, namelen + 1, name);
443 dtxoff(pdt
, toSymbol(), offset
, TYnptr
);
444 offset
+= namelen
+ 1;
447 dtdword(pdt
, sd
->structsize
); // init.length
449 dtdword(pdt
, 0); // NULL for 0 initialization
451 dtxoff(pdt
, sd
->toInitializer(), 0, TYnptr
); // init.ptr
454 FuncDeclaration
*fdx
;
459 static TypeFunction
*tftohash
;
460 static TypeFunction
*tftostring
;
466 tftohash
= new TypeFunction(NULL
, Type::thash_t
, 0, LINKd
);
467 tftohash
= (TypeFunction
*)tftohash
->semantic(0, &sc
);
469 tftostring
= new TypeFunction(NULL
, Type::tchar
->arrayOf(), 0, LINKd
);
470 tftostring
= (TypeFunction
*)tftostring
->semantic(0, &sc
);
473 TypeFunction
*tfeqptr
;
476 Arguments
*arguments
= new Arguments
;
477 Argument
*arg
= new Argument(STCin
, tc
->pointerTo(), NULL
, NULL
);
479 arguments
->push(arg
);
480 tfeqptr
= new TypeFunction(arguments
, Type::tint32
, 0, LINKd
);
481 tfeqptr
= (TypeFunction
*)tfeqptr
->semantic(0, &sc
);
488 Array
*arguments
= new Array
;
489 Argument
*arg
= new Argument(In
, tc
, NULL
, NULL
);
491 arguments
->push(arg
);
492 tfeq
= new TypeFunction(arguments
, Type::tint32
, 0, LINKd
);
493 tfeq
= (TypeFunction
*)tfeq
->semantic(0, &sc
);
497 s
= search_function(sd
, Id::tohash
);
498 fdx
= s
? s
->isFuncDeclaration() : NULL
;
500 { fd
= fdx
->overloadExactMatch(tftohash
);
502 dtxoff(pdt
, fd
->toSymbol(), 0, TYnptr
);
504 //fdx->error("must be declared as extern (D) uint toHash()");
510 s
= search_function(sd
, Id::eq
);
511 fdx
= s
? s
->isFuncDeclaration() : NULL
;
512 for (int i
= 0; i
< 2; i
++)
515 { fd
= fdx
->overloadExactMatch(tfeqptr
);
517 dtxoff(pdt
, fd
->toSymbol(), 0, TYnptr
);
519 //fdx->error("must be declared as extern (D) int %s(%s*)", fdx->toChars(), sd->toChars());
525 s
= search_function(sd
, Id::cmp
);
526 fdx
= s
? s
->isFuncDeclaration() : NULL
;
529 s
= search_function(sd
, Id::tostring
);
530 fdx
= s
? s
->isFuncDeclaration() : NULL
;
532 { fd
= fdx
->overloadExactMatch(tftostring
);
534 dtxoff(pdt
, fd
->toSymbol(), 0, TYnptr
);
536 //fdx->error("must be declared as extern (D) char[] toString()");
543 dti32(pdt
, tc
->hasPointers(), false);
546 dtnbytes(pdt
, namelen
+ 1, name
);
549 void TypeInfoClassDeclaration::toDt(dt_t
**pdt
)
551 //printf("TypeInfoClassDeclaration::toDt() %s\n", tinfo->toChars());
552 dtxoff(pdt
, Type::typeinfoclass
->toVtblSymbol(), 0, TYnptr
); // vtbl for TypeInfoClass
553 dtdword(pdt
, 0); // monitor
555 assert(tinfo
->ty
== Tclass
);
557 TypeClass
*tc
= (TypeClass
*)tinfo
;
560 if (!tc
->sym
->vclassinfo
)
561 tc
->sym
->vclassinfo
= new ClassInfoDeclaration(tc
->sym
);
562 s
= tc
->sym
->vclassinfo
->toSymbol();
563 dtxoff(pdt
, s
, 0, TYnptr
); // ClassInfo for tinfo
566 void TypeInfoInterfaceDeclaration::toDt(dt_t
**pdt
)
568 //printf("TypeInfoInterfaceDeclaration::toDt() %s\n", tinfo->toChars());
569 dtxoff(pdt
, Type::typeinfointerface
->toVtblSymbol(), 0, TYnptr
); // vtbl for TypeInfoInterface
570 dtdword(pdt
, 0); // monitor
572 assert(tinfo
->ty
== Tclass
);
574 TypeClass
*tc
= (TypeClass
*)tinfo
;
577 if (!tc
->sym
->vclassinfo
)
578 tc
->sym
->vclassinfo
= new ClassInfoDeclaration(tc
->sym
);
579 s
= tc
->sym
->vclassinfo
->toSymbol();
580 dtxoff(pdt
, s
, 0, TYnptr
); // ClassInfo for tinfo
583 void TypeInfoTupleDeclaration::toDt(dt_t
**pdt
)
585 //printf("TypeInfoTupleDeclaration::toDt() %s\n", tinfo->toChars());
586 dtxoff(pdt
, Type::typeinfotypelist
->toVtblSymbol(), 0, TYnptr
); // vtbl for TypeInfoInterface
587 dtdword(pdt
, 0); // monitor
589 assert(tinfo
->ty
== Ttuple
);
591 TypeTuple
*tu
= (TypeTuple
*)tinfo
;
593 size_t dim
= tu
->arguments
->dim
;
594 dtdword(pdt
, dim
); // elements.length
597 for (size_t i
= 0; i
< dim
; i
++)
598 { Argument
*arg
= (Argument
*)tu
->arguments
->data
[i
];
599 Expression
*e
= arg
->type
->getTypeInfo(NULL
);
600 e
= e
->optimize(WANTvalue
);
609 dtxoff(pdt
, s
, 0, TYnptr
); // elements.ptr
612 void TypeInfoDeclaration::toObjFile(int multiobj
)
618 //printf("TypeInfoDeclaration::toObjFile(%p '%s') protection %d\n", this, toChars(), protection);
629 parent
= this->toParent();
630 s
->Sclass
= SCcomdat
;
637 // See if we can convert a comdat to a comdef,
638 // which saves on exe file space.
639 if (s
->Sclass
== SCcomdat
&&
640 s
->Sdt
->dt
== DT_azeros
&&
641 s
->Sdt
->DTnext
== NULL
)
643 s
->Sclass
= SCglobal
;
644 s
->Sdt
->dt
= DT_common
;
648 if (s
->Sdt
&& s
->Sdt
->dt
== DT_azeros
&& s
->Sdt
->DTnext
== NULL
)
660 /* ========================================================================= */
662 /* These decide if there's an instance for them already in std.typeinfo,
663 * because then the compiler doesn't need to build one.
666 int Type::builtinTypeInfo()
671 int TypeBasic::builtinTypeInfo()
676 int TypeDArray::builtinTypeInfo()
678 return next
->isTypeBasic() != NULL
;
681 /* ========================================================================= */
683 /***************************************
684 * Create a static array of TypeInfo references
685 * corresponding to an array of Expression's.
686 * Used to supply hidden _arguments[] value for variadic D functions.
689 Expression
*createTypeInfoArray(Scope
*sc
, Expression
*exps
[], int dim
)
692 /* Get the corresponding TypeInfo_Tuple and
693 * point at its elements[].
696 /* Create the TypeTuple corresponding to the types of args[]
698 Arguments
*args
= new Arguments
;
700 for (size_t i
= 0; i
< dim
; i
++)
701 { Argument
*arg
= new Argument(STCin
, exps
[i
]->type
, NULL
, NULL
);
702 args
->data
[i
] = (void *)arg
;
704 TypeTuple
*tup
= new TypeTuple(args
);
705 Expression
*e
= tup
->getTypeInfo(sc
);
706 e
= e
->optimize(WANTvalue
);
707 assert(e
->op
== TOKsymoff
); // should be SymOffExp
711 * Should just pass a reference to TypeInfo_Tuple instead,
712 * but that would require existing code to be recompiled.
713 * Source compatibility can be maintained by computing _arguments[]
714 * at the start of the called function by offseting into the
715 * TypeInfo_Tuple reference.
719 // Advance to elements[] member of TypeInfo_Tuple
720 SymOffExp
*se
= (SymOffExp
*)e
;
721 se
->offset
+= PTRSIZE
+ PTRSIZE
;
723 // Set type to TypeInfo[]*
724 se
->type
= Type::typeinfo
->type
->arrayOf()->pointerTo();
726 // Indirect to get the _arguments[] value
727 e
= new PtrExp(0, se
);
728 e
->type
= se
->type
->next
;
733 * 1) create an array literal instead,
734 * as it would eliminate the extra dereference of loading the
738 ArrayInitializer
*ai
= new ArrayInitializer(0);
746 // Generate identifier for _arguments[]
747 buf
.writestring("_arguments_");
748 for (int i
= 0; i
< dim
; i
++)
750 t
->toDecoBuffer(&buf
);
753 id
= Lexer::idPool((char *)buf
.data
);
756 Module
*m
= d_gcc_get_output_module();
758 Module
*m
= sc
->module
;
760 Dsymbol
*s
= m
->symtab
->lookup(id
);
762 if (s
&& s
->parent
== m
)
763 { // Use existing one
764 v
= s
->isVarDeclaration();
768 { // Generate new one
770 for (int i
= 0; i
< dim
; i
++)
772 e
= t
->getTypeInfo(sc
);
773 ai
->addInit(new IntegerExp(i
), new ExpInitializer(0, e
));
776 t
= Type::typeinfo
->type
->arrayOf();
778 v
= new VarDeclaration(0, t
, id
, ai
);
780 m
->symtab
->insert(v
);
783 sc
->stc
= STCstatic
| STCcomdat
;
789 e
= new VarExp(0, v
);