// Compiler implementation of the D programming language // Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com // License for redistribution is by either the Artistic License // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. #include #include //#include "mem.h" #include "mars.h" #include "module.h" #include "mtype.h" #include "scope.h" #include "init.h" #include "expression.h" #include "attrib.h" #include "declaration.h" #include "template.h" #include "id.h" #include "enum.h" #include "import.h" #include "aggregate.h" #ifndef TARGET_NET #include "rmem.h" #include "cc.h" #include "global.h" #include "oper.h" #include "code.h" #include "type.h" #include "dt.h" #include "cgcv.h" #include "outbuf.h" #include "irstate.h" #endif extern Symbol *static_sym(); /******************************************* * Get a canonicalized form of the TypeInfo for use with the internal * runtime library routines. Canonicalized in that static arrays are * represented as dynamic arrays, enums are represented by their * underlying type, etc. This reduces the number of TypeInfo's needed, * so we can use the custom internal ones more. */ Expression *Type::getInternalTypeInfo(Scope *sc) { TypeInfoDeclaration *tid; Expression *e; Type *t; static TypeInfoDeclaration *internalTI[TMAX]; //printf("Type::getInternalTypeInfo() %s\n", toChars()); t = toBasetype(); switch (t->ty) { case Tsarray: #if 0 // convert to corresponding dynamic array type t = t->nextOf()->mutableOf()->arrayOf(); #endif break; case Tclass: if (((TypeClass *)t)->sym->isInterfaceDeclaration()) break; goto Linternal; case Tarray: // convert to corresponding dynamic array type t = t->nextOf()->mutableOf()->arrayOf(); if (t->nextOf()->ty != Tclass) break; goto Linternal; case Tfunction: case Tdelegate: case Tpointer: Linternal: tid = internalTI[t->ty]; if (!tid) { tid = new TypeInfoDeclaration(t, 1); internalTI[t->ty] = tid; } e = new VarExp(0, tid); e = e->addressOf(sc); e->type = tid->type; // do this so we don't get redundant dereference return e; default: break; } //printf("\tcalling getTypeInfo() %s\n", t->toChars()); return t->getTypeInfo(sc); } /**************************************************** * Get the exact TypeInfo. */ Expression *Type::getTypeInfo(Scope *sc) { //printf("Type::getTypeInfo() %p, %s\n", this, toChars()); if (!Type::typeinfo) { error(0, "TypeInfo not found. object.d may be incorrectly installed or corrupt, compile with -v switch"); fatal(); } Type *t = merge2(); // do this since not all Type's are merge'd if (!t->vtinfo) { #if DMDV2 if (t->isShared()) // does both 'shared' and 'shared const' t->vtinfo = new TypeInfoSharedDeclaration(t); else if (t->isConst()) t->vtinfo = new TypeInfoConstDeclaration(t); else if (t->isImmutable()) t->vtinfo = new TypeInfoInvariantDeclaration(t); else if (t->isWild()) t->vtinfo = new TypeInfoWildDeclaration(t); else #endif t->vtinfo = t->getTypeInfoDeclaration(); assert(t->vtinfo); vtinfo = t->vtinfo; /* If this has a custom implementation in std/typeinfo, then * do not generate a COMDAT for it. */ if (!t->builtinTypeInfo()) { // Generate COMDAT if (sc) // if in semantic() pass { // Find module that will go all the way to an object file Module *m = sc->module->importedFrom; m->members->push(t->vtinfo); } else // if in obj generation pass { t->vtinfo->toObjFile(global.params.multiobj); } } } if (!vtinfo) vtinfo = t->vtinfo; // Types aren't merged, but we can share the vtinfo's Expression *e = new VarExp(0, t->vtinfo); e = e->addressOf(sc); e->type = t->vtinfo->type; // do this so we don't get redundant dereference return e; } TypeInfoDeclaration *Type::getTypeInfoDeclaration() { //printf("Type::getTypeInfoDeclaration() %s\n", toChars()); return new TypeInfoDeclaration(this, 0); } TypeInfoDeclaration *TypeTypedef::getTypeInfoDeclaration() { return new TypeInfoTypedefDeclaration(this); } TypeInfoDeclaration *TypePointer::getTypeInfoDeclaration() { return new TypeInfoPointerDeclaration(this); } TypeInfoDeclaration *TypeDArray::getTypeInfoDeclaration() { return new TypeInfoArrayDeclaration(this); } TypeInfoDeclaration *TypeSArray::getTypeInfoDeclaration() { return new TypeInfoStaticArrayDeclaration(this); } TypeInfoDeclaration *TypeAArray::getTypeInfoDeclaration() { return new TypeInfoAssociativeArrayDeclaration(this); } TypeInfoDeclaration *TypeStruct::getTypeInfoDeclaration() { return new TypeInfoStructDeclaration(this); } TypeInfoDeclaration *TypeClass::getTypeInfoDeclaration() { if (sym->isInterfaceDeclaration()) return new TypeInfoInterfaceDeclaration(this); else return new TypeInfoClassDeclaration(this); } TypeInfoDeclaration *TypeVector::getTypeInfoDeclaration() { return new TypeInfoVectorDeclaration(this); } TypeInfoDeclaration *TypeEnum::getTypeInfoDeclaration() { return new TypeInfoEnumDeclaration(this); } TypeInfoDeclaration *TypeFunction::getTypeInfoDeclaration() { return new TypeInfoFunctionDeclaration(this); } TypeInfoDeclaration *TypeDelegate::getTypeInfoDeclaration() { return new TypeInfoDelegateDeclaration(this); } TypeInfoDeclaration *TypeTuple::getTypeInfoDeclaration() { return new TypeInfoTupleDeclaration(this); } #ifndef TARGET_NET /**************************************************** */ #if 1 void TypeInfoDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoDeclaration::toDt() %s\n", toChars()); dtxoff(pdt, Type::typeinfo->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo dtsize_t(pdt, 0); // monitor } #if DMDV2 void TypeInfoConstDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoConstDeclaration::toDt() %s\n", toChars()); dtxoff(pdt, Type::typeinfoconst->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Const dtsize_t(pdt, 0); // monitor Type *tm = tinfo->mutableOf(); tm = tm->merge(); tm->getTypeInfo(NULL); dtxoff(pdt, tm->vtinfo->toSymbol(), 0, TYnptr); } void TypeInfoInvariantDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoInvariantDeclaration::toDt() %s\n", toChars()); dtxoff(pdt, Type::typeinfoinvariant->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Invariant dtsize_t(pdt, 0); // monitor Type *tm = tinfo->mutableOf(); tm = tm->merge(); tm->getTypeInfo(NULL); dtxoff(pdt, tm->vtinfo->toSymbol(), 0, TYnptr); } void TypeInfoSharedDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoSharedDeclaration::toDt() %s\n", toChars()); dtxoff(pdt, Type::typeinfoshared->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Shared dtsize_t(pdt, 0); // monitor Type *tm = tinfo->unSharedOf(); tm = tm->merge(); tm->getTypeInfo(NULL); dtxoff(pdt, tm->vtinfo->toSymbol(), 0, TYnptr); } void TypeInfoWildDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoWildDeclaration::toDt() %s\n", toChars()); dtxoff(pdt, Type::typeinfowild->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Wild dtsize_t(pdt, 0); // monitor Type *tm = tinfo->mutableOf(); tm = tm->merge(); tm->getTypeInfo(NULL); dtxoff(pdt, tm->vtinfo->toSymbol(), 0, TYnptr); } #endif void TypeInfoTypedefDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoTypedefDeclaration::toDt() %s\n", toChars()); dtxoff(pdt, Type::typeinfotypedef->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Typedef dtsize_t(pdt, 0); // monitor assert(tinfo->ty == Ttypedef); TypeTypedef *tc = (TypeTypedef *)tinfo; TypedefDeclaration *sd = tc->sym; //printf("basetype = %s\n", sd->basetype->toChars()); /* Put out: * TypeInfo base; * char[] name; * void[] m_init; */ sd->basetype = sd->basetype->merge(); sd->basetype->getTypeInfo(NULL); // generate vtinfo assert(sd->basetype->vtinfo); dtxoff(pdt, sd->basetype->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for basetype const char *name = sd->toPrettyChars(); size_t namelen = strlen(name); dtsize_t(pdt, namelen); dtabytes(pdt, TYnptr, 0, namelen + 1, name); // void[] init; if (tinfo->isZeroInit() || !sd->init) { // 0 initializer, or the same as the base type dtsize_t(pdt, 0); // init.length dtsize_t(pdt, 0); // init.ptr } else { dtsize_t(pdt, sd->type->size()); // init.length dtxoff(pdt, sd->toInitializer(), 0, TYnptr); // init.ptr } } void TypeInfoEnumDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoEnumDeclaration::toDt()\n"); dtxoff(pdt, Type::typeinfoenum->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Enum dtsize_t(pdt, 0); // monitor assert(tinfo->ty == Tenum); TypeEnum *tc = (TypeEnum *)tinfo; EnumDeclaration *sd = tc->sym; /* Put out: * TypeInfo base; * char[] name; * void[] m_init; */ if (sd->memtype) { sd->memtype->getTypeInfo(NULL); dtxoff(pdt, sd->memtype->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for enum members } else dtsize_t(pdt, 0); const char *name = sd->toPrettyChars(); size_t namelen = strlen(name); dtsize_t(pdt, namelen); dtabytes(pdt, TYnptr, 0, namelen + 1, name); // void[] init; if (!sd->defaultval || tinfo->isZeroInit()) { // 0 initializer, or the same as the base type dtsize_t(pdt, 0); // init.length dtsize_t(pdt, 0); // init.ptr } else { dtsize_t(pdt, sd->type->size()); // init.length dtxoff(pdt, sd->toInitializer(), 0, TYnptr); // init.ptr } } void TypeInfoPointerDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoPointerDeclaration::toDt()\n"); dtxoff(pdt, Type::typeinfopointer->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Pointer dtsize_t(pdt, 0); // monitor assert(tinfo->ty == Tpointer); TypePointer *tc = (TypePointer *)tinfo; tc->next->getTypeInfo(NULL); dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for type being pointed to } void TypeInfoArrayDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoArrayDeclaration::toDt()\n"); dtxoff(pdt, Type::typeinfoarray->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Array dtsize_t(pdt, 0); // monitor assert(tinfo->ty == Tarray); TypeDArray *tc = (TypeDArray *)tinfo; tc->next->getTypeInfo(NULL); dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type } void TypeInfoStaticArrayDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoStaticArrayDeclaration::toDt()\n"); dtxoff(pdt, Type::typeinfostaticarray->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_StaticArray dtsize_t(pdt, 0); // monitor assert(tinfo->ty == Tsarray); TypeSArray *tc = (TypeSArray *)tinfo; tc->next->getTypeInfo(NULL); dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type dtsize_t(pdt, tc->dim->toInteger()); // length } void TypeInfoVectorDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoVectorDeclaration::toDt()\n"); dtxoff(pdt, Type::typeinfovector->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Vector dtsize_t(pdt, 0); // monitor assert(tinfo->ty == Tvector); TypeVector *tc = (TypeVector *)tinfo; tc->basetype->getTypeInfo(NULL); dtxoff(pdt, tc->basetype->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for equivalent static array } void TypeInfoAssociativeArrayDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoAssociativeArrayDeclaration::toDt()\n"); dtxoff(pdt, Type::typeinfoassociativearray->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_AssociativeArray dtsize_t(pdt, 0); // monitor assert(tinfo->ty == Taarray); TypeAArray *tc = (TypeAArray *)tinfo; tc->next->getTypeInfo(NULL); dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type tc->index->getTypeInfo(NULL); dtxoff(pdt, tc->index->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type #if DMDV2 tc->getImpl()->type->getTypeInfo(NULL); dtxoff(pdt, tc->getImpl()->type->vtinfo->toSymbol(), 0, TYnptr); // impl #endif } void TypeInfoFunctionDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoFunctionDeclaration::toDt()\n"); dtxoff(pdt, Type::typeinfofunction->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Function dtsize_t(pdt, 0); // monitor assert(tinfo->ty == Tfunction); TypeFunction *tc = (TypeFunction *)tinfo; tc->next->getTypeInfo(NULL); dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for function return value const char *name = tinfo->deco; assert(name); size_t namelen = strlen(name); dtsize_t(pdt, namelen); dtabytes(pdt, TYnptr, 0, namelen + 1, name); } void TypeInfoDelegateDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoDelegateDeclaration::toDt()\n"); dtxoff(pdt, Type::typeinfodelegate->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Delegate dtsize_t(pdt, 0); // monitor assert(tinfo->ty == Tdelegate); TypeDelegate *tc = (TypeDelegate *)tinfo; tc->next->nextOf()->getTypeInfo(NULL); dtxoff(pdt, tc->next->nextOf()->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for delegate return value const char *name = tinfo->deco; assert(name); size_t namelen = strlen(name); dtsize_t(pdt, namelen); dtabytes(pdt, TYnptr, 0, namelen + 1, name); } void TypeInfoStructDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoStructDeclaration::toDt() '%s'\n", toChars()); unsigned offset = Type::typeinfostruct->structsize; dtxoff(pdt, Type::typeinfostruct->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Struct dtsize_t(pdt, 0); // monitor assert(tinfo->ty == Tstruct); TypeStruct *tc = (TypeStruct *)tinfo; StructDeclaration *sd = tc->sym; /* Put out: * char[] name; * void[] init; * hash_t function(in void*) xtoHash; * bool function(in void*, in void*) xopEquals; * int function(in void*, in void*) xopCmp; * string function(const(void)*) xtoString; * uint m_flags; * xgetMembers; * xdtor; * xpostblit; * uint m_align; * version (X86_64) * TypeInfo m_arg1; * TypeInfo m_arg2; * * name[] */ const char *name = sd->toPrettyChars(); size_t namelen = strlen(name); dtsize_t(pdt, namelen); //dtabytes(pdt, TYnptr, 0, namelen + 1, name); dtxoff(pdt, toSymbol(), offset, TYnptr); offset += namelen + 1; // void[] init; dtsize_t(pdt, sd->structsize); // init.length if (sd->zeroInit) dtsize_t(pdt, 0); // NULL for 0 initialization else dtxoff(pdt, sd->toInitializer(), 0, TYnptr); // init.ptr FuncDeclaration *fd; FuncDeclaration *fdx; Dsymbol *s; static TypeFunction *tftohash; static TypeFunction *tftostring; if (!tftohash) { Scope sc; /* const hash_t toHash(); */ tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd); tftohash->mod = MODconst; tftohash = (TypeFunction *)tftohash->semantic(0, &sc); tftostring = new TypeFunction(NULL, Type::tchar->invariantOf()->arrayOf(), 0, LINKd); tftostring = (TypeFunction *)tftostring->semantic(0, &sc); } TypeFunction *tfcmpptr; { Scope sc; /* const int opCmp(ref const KeyType s); */ Parameters *arguments = new Parameters; #if STRUCTTHISREF // arg type is ref const T Parameter *arg = new Parameter(STCref, tc->constOf(), NULL, NULL); #else // arg type is const T* Parameter *arg = new Parameter(STCin, tc->pointerTo(), NULL, NULL); #endif arguments->push(arg); tfcmpptr = new TypeFunction(arguments, Type::tint32, 0, LINKd); tfcmpptr->mod = MODconst; tfcmpptr = (TypeFunction *)tfcmpptr->semantic(0, &sc); } s = search_function(sd, Id::tohash); fdx = s ? s->isFuncDeclaration() : NULL; if (fdx) { fd = fdx->overloadExactMatch(tftohash); if (fd) { dtxoff(pdt, fd->toSymbol(), 0, TYnptr); TypeFunction *tf = (TypeFunction *)fd->type; assert(tf->ty == Tfunction); if (global.params.warnings) { /* I'm a little unsure this is the right way to do it. Perhaps a better * way would to automatically add these attributes to any struct member * function with the name "toHash". * So I'm leaving this here as an experiment for the moment. */ if (!tf->isnothrow || tf->trust == TRUSTsystem /*|| tf->purity == PUREimpure*/) { warning(fd->loc, "toHash() must be declared as extern (D) uint toHash() const nothrow @safe, not %s", tf->toChars()); if (global.params.warnings == 1) global.errors++; } } } else { //fdx->error("must be declared as extern (D) uint toHash()"); dtsize_t(pdt, 0); } } else dtsize_t(pdt, 0); if (sd->xeq) dtxoff(pdt, sd->xeq->toSymbol(), 0, TYnptr); else dtsize_t(pdt, 0); s = search_function(sd, Id::cmp); fdx = s ? s->isFuncDeclaration() : NULL; if (fdx) { //printf("test1 %s, %s, %s\n", fdx->toChars(), fdx->type->toChars(), tfeqptr->toChars()); fd = fdx->overloadExactMatch(tfcmpptr); if (fd) { dtxoff(pdt, fd->toSymbol(), 0, TYnptr); //printf("test2\n"); } else //fdx->error("must be declared as extern (D) int %s(%s*)", fdx->toChars(), sd->toChars()); dtsize_t(pdt, 0); } else dtsize_t(pdt, 0); s = search_function(sd, Id::tostring); fdx = s ? s->isFuncDeclaration() : NULL; if (fdx) { fd = fdx->overloadExactMatch(tftostring); if (fd) dtxoff(pdt, fd->toSymbol(), 0, TYnptr); else //fdx->error("must be declared as extern (D) char[] toString()"); dtsize_t(pdt, 0); } else dtsize_t(pdt, 0); // uint m_flags; dtsize_t(pdt, tc->hasPointers()); #if DMDV2 // xgetMembers FuncDeclaration *sgetmembers = sd->findGetMembers(); if (sgetmembers) dtxoff(pdt, sgetmembers->toSymbol(), 0, TYnptr); else dtsize_t(pdt, 0); // xgetMembers // xdtor FuncDeclaration *sdtor = sd->dtor; if (sdtor) dtxoff(pdt, sdtor->toSymbol(), 0, TYnptr); else dtsize_t(pdt, 0); // xdtor // xpostblit FuncDeclaration *spostblit = sd->postblit; if (spostblit && !(spostblit->storage_class & STCdisable)) dtxoff(pdt, spostblit->toSymbol(), 0, TYnptr); else dtsize_t(pdt, 0); // xpostblit #endif // uint m_align; dtsize_t(pdt, tc->alignsize()); if (global.params.is64bit) { TypeTuple *tup = tc->toArgTypes(); assert(tup->arguments->dim <= 2); for (size_t i = 0; i < 2; i++) { if (i < tup->arguments->dim) { Type *targ = (tup->arguments->tdata()[i])->type; targ = targ->merge(); targ->getTypeInfo(NULL); dtxoff(pdt, targ->vtinfo->toSymbol(), 0, TYnptr); // m_argi } else dtsize_t(pdt, 0); // m_argi } } // name[] dtnbytes(pdt, namelen + 1, name); } void TypeInfoClassDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoClassDeclaration::toDt() %s\n", tinfo->toChars()); #if DMDV1 dtxoff(pdt, Type::typeinfoclass->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoClass dtsize_t(pdt, 0); // monitor assert(tinfo->ty == Tclass); TypeClass *tc = (TypeClass *)tinfo; Symbol *s; if (!tc->sym->vclassinfo) tc->sym->vclassinfo = new ClassInfoDeclaration(tc->sym); s = tc->sym->vclassinfo->toSymbol(); dtxoff(pdt, s, 0, TYnptr); // ClassInfo for tinfo #else assert(0); #endif } void TypeInfoInterfaceDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoInterfaceDeclaration::toDt() %s\n", tinfo->toChars()); dtxoff(pdt, Type::typeinfointerface->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoInterface dtsize_t(pdt, 0); // monitor assert(tinfo->ty == Tclass); TypeClass *tc = (TypeClass *)tinfo; Symbol *s; if (!tc->sym->vclassinfo) #if DMDV1 tc->sym->vclassinfo = new ClassInfoDeclaration(tc->sym); #else tc->sym->vclassinfo = new TypeInfoClassDeclaration(tc); #endif s = tc->sym->vclassinfo->toSymbol(); dtxoff(pdt, s, 0, TYnptr); // ClassInfo for tinfo } void TypeInfoTupleDeclaration::toDt(dt_t **pdt) { //printf("TypeInfoTupleDeclaration::toDt() %s\n", tinfo->toChars()); dtxoff(pdt, Type::typeinfotypelist->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoInterface dtsize_t(pdt, 0); // monitor assert(tinfo->ty == Ttuple); TypeTuple *tu = (TypeTuple *)tinfo; size_t dim = tu->arguments->dim; dtsize_t(pdt, dim); // elements.length dt_t *d = NULL; for (size_t i = 0; i < dim; i++) { Parameter *arg = tu->arguments->tdata()[i]; Expression *e = arg->type->getTypeInfo(NULL); e = e->optimize(WANTvalue); e->toDt(&d); } Symbol *s; s = static_sym(); s->Sdt = d; outdata(s); dtxoff(pdt, s, 0, TYnptr); // elements.ptr } void TypeInfoDeclaration::toObjFile(int multiobj) { Symbol *s; unsigned sz; Dsymbol *parent; //printf("TypeInfoDeclaration::toObjFile(%p '%s') protection %d\n", this, toChars(), protection); if (multiobj) { obj_append(this); return; } s = toSymbol(); sz = type->size(); parent = this->toParent(); s->Sclass = SCcomdat; s->Sfl = FLdata; toDt(&s->Sdt); dt_optimize(s->Sdt); // See if we can convert a comdat to a comdef, // which saves on exe file space. if (s->Sclass == SCcomdat && s->Sdt->dt == DT_azeros && s->Sdt->DTnext == NULL) { s->Sclass = SCglobal; s->Sdt->dt = DT_common; } #if ELFOBJ || MACHOBJ // Burton if (s->Sdt && s->Sdt->dt == DT_azeros && s->Sdt->DTnext == NULL) s->Sseg = UDATA; else s->Sseg = DATA; #endif outdata(s); if (isExport()) obj_export(s,0); } #endif #endif // TARGET_NET /* ========================================================================= */ /* These decide if there's an instance for them already in std.typeinfo, * because then the compiler doesn't need to build one. */ int Type::builtinTypeInfo() { return 0; } int TypeBasic::builtinTypeInfo() { #if DMDV2 return mod ? 0 : 1; #else return 1; #endif } int TypeDArray::builtinTypeInfo() { #if DMDV2 return !mod && (next->isTypeBasic() != NULL && !next->mod || // strings are so common, make them builtin next->ty == Tchar && next->mod == MODimmutable); #else return next->isTypeBasic() != NULL; #endif } int TypeClass::builtinTypeInfo() { /* This is statically put out with the ClassInfo, so * claim it is built in so it isn't regenerated by each module. */ #if DMDV2 return mod ? 0 : 1; #else return 1; #endif } /* ========================================================================= */ /*************************************** * Create a static array of TypeInfo references * corresponding to an array of Expression's. * Used to supply hidden _arguments[] value for variadic D functions. */ Expression *createTypeInfoArray(Scope *sc, Expression *exps[], unsigned dim) { #if 1 /* Get the corresponding TypeInfo_Tuple and * point at its elements[]. */ /* Create the TypeTuple corresponding to the types of args[] */ Parameters *args = new Parameters; args->setDim(dim); for (size_t i = 0; i < dim; i++) { Parameter *arg = new Parameter(STCin, exps[i]->type, NULL, NULL); args->tdata()[i] = arg; } TypeTuple *tup = new TypeTuple(args); Expression *e = tup->getTypeInfo(sc); e = e->optimize(WANTvalue); assert(e->op == TOKsymoff); // should be SymOffExp #if BREAKABI /* * Should just pass a reference to TypeInfo_Tuple instead, * but that would require existing code to be recompiled. * Source compatibility can be maintained by computing _arguments[] * at the start of the called function by offseting into the * TypeInfo_Tuple reference. */ #else // Advance to elements[] member of TypeInfo_Tuple SymOffExp *se = (SymOffExp *)e; se->offset += PTRSIZE + PTRSIZE; // Set type to TypeInfo[]* se->type = Type::typeinfo->type->arrayOf()->pointerTo(); // Indirect to get the _arguments[] value e = new PtrExp(0, se); e->type = se->type->next; #endif return e; #else /* Improvements: * 1) create an array literal instead, * as it would eliminate the extra dereference of loading the * static variable. */ ArrayInitializer *ai = new ArrayInitializer(0); VarDeclaration *v; Type *t; Expression *e; OutBuffer buf; Identifier *id; char *name; // Generate identifier for _arguments[] buf.writestring("_arguments_"); for (int i = 0; i < dim; i++) { t = exps[i]->type; t->toDecoBuffer(&buf); } buf.writeByte(0); id = Lexer::idPool((char *)buf.data); Module *m = sc->module; Dsymbol *s = m->symtab->lookup(id); if (s && s->parent == m) { // Use existing one v = s->isVarDeclaration(); assert(v); } else { // Generate new one for (int i = 0; i < dim; i++) { t = exps[i]->type; e = t->getTypeInfo(sc); ai->addInit(new IntegerExp(i), new ExpInitializer(0, e)); } t = Type::typeinfo->type->arrayOf(); ai->type = t; v = new VarDeclaration(0, t, id, ai); m->members->push(v); m->symtabInsert(v); sc = sc->push(); sc->linkage = LINKc; sc->stc = STCstatic | STCcomdat; ai->semantic(sc, t); v->semantic(sc); v->parent = m; sc = sc->pop(); } e = new VarExp(0, v); e = e->semantic(sc); return e; #endif }