Mercurial > projects > ldc
diff gen/typinf.c @ 52:0c77619e803b trunk
[svn r56] Initial support for TypeInfo.
Enums not work.
Several other bugfixes.
author | lindquist |
---|---|
date | Tue, 23 Oct 2007 05:55:12 +0200 |
parents | e116aa1488e6 |
children | 28e99b04a132 |
line wrap: on
line diff
--- a/gen/typinf.c Mon Oct 22 17:25:44 2007 +0200 +++ b/gen/typinf.c Tue Oct 23 05:55:12 2007 +0200 @@ -11,6 +11,8 @@ #include <cstdio> #include <cassert> +#include "gen/llvm.h" + #include "mars.h" #include "module.h" #include "mtype.h" @@ -25,346 +27,170 @@ #include "import.h" #include "aggregate.h" +#include "gen/irstate.h" #include "gen/logger.h" +#include "gen/runtime.h" /******************************************* - * 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: - t = t->next->arrayOf(); // convert to corresponding dynamic array type - break; - - case Tclass: - if (((TypeClass *)t)->sym->isInterfaceDeclaration()) - break; - goto Linternal; - - case Tarray: - if (t->next->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 = 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) - { - Expression *e; - Type *t; - - //printf("Type::getTypeInfo() %p, %s\n", this, toChars()); - t = merge(); // do this since not all Type's are merge'd - if (!t->vtinfo) - { t->vtinfo = t->getTypeInfoDeclaration(); - assert(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(); - } - } - } - 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; - } - +enum RET TypeFunction::retStyle() +{ + return RETstack; +} TypeInfoDeclaration *Type::getTypeInfoDeclaration() - { - //printf("Type::getTypeInfoDeclaration() %s\n", toChars()); - return new TypeInfoDeclaration(this, 0); - -} - - - -TypeInfoDeclaration *TypeTypedef::getTypeInfoDeclaration() - -{ - - return new TypeInfoTypedefDeclaration(this); - } - - -TypeInfoDeclaration *TypePointer::getTypeInfoDeclaration() - +TypeInfoDeclaration *TypeTypedef::getTypeInfoDeclaration() { - - return new TypeInfoPointerDeclaration(this); - + 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 *TypeStruct::getTypeInfoDeclaration() +{ + return new TypeInfoStructDeclaration(this); +} TypeInfoDeclaration *TypeClass::getTypeInfoDeclaration() - { - if (sym->isInterfaceDeclaration()) - return new TypeInfoInterfaceDeclaration(this); - else - return new TypeInfoClassDeclaration(this); - } - - TypeInfoDeclaration *TypeEnum::getTypeInfoDeclaration() - { - return new TypeInfoEnumDeclaration(this); - } - - TypeInfoDeclaration *TypeFunction::getTypeInfoDeclaration() - { - return new TypeInfoFunctionDeclaration(this); - -} -enum RET TypeFunction::retStyle() - -{ - - return RETstack; - } - TypeInfoDeclaration *TypeDelegate::getTypeInfoDeclaration() - { - return new TypeInfoDelegateDeclaration(this); - } - - TypeInfoDeclaration *TypeTuple::getTypeInfoDeclaration() - { - return new TypeInfoTupleDeclaration(this); - -} - - -void TypeInfoDeclaration::toDt(dt_t **pdt) -{ -} - -void TypeInfoTypedefDeclaration::toDt(dt_t **pdt) -{ } -void TypeInfoStructDeclaration::toDt(dt_t **pdt) -{ -} - -void TypeInfoClassDeclaration::toDt(dt_t **pdt) -{ -} - -void TypeInfoDeclaration::toObjFile() -{ - Logger::println("TypeInfoDeclaration::toObjFile()"); - LOG_SCOPE; - Logger::println("type = '%s'", tinfo->toChars()); - - -} /* ========================================================================= */ @@ -384,7 +210,7 @@ int TypeDArray::builtinTypeInfo() { - return 0; + return next->isTypeBasic() != NULL; } /* ========================================================================= */ @@ -401,3 +227,511 @@ return 0; } +/* ========================================================================= */ + +////////////////////////////////////////////////////////////////////////////// +// MAGIC PLACE +////////////////////////////////////////////////////////////////////////////// + +void TypeInfoDeclaration::toObjFile() +{ + Logger::println("TypeInfoDeclaration::toObjFile()"); + LOG_SCOPE; + Logger::println("type = '%s'", tinfo->toChars()); + + if (llvmTouched) return; + else llvmTouched = true; + + Logger::println("Getting typeinfo var: %s", mangle()); + llvmValue = LLVM_D_GetRuntimeGlobal(gIR->module, mangle()); + assert(llvmValue); + Logger::cout() << "Got:" << '\n' << *llvmValue << '\n'; +} + +/* ========================================================================= */ + +void TypeInfoDeclaration::toDt(dt_t **pdt) +{ + assert(0 && "TypeInfoDeclaration"); +} + +void TypeInfoTypedefDeclaration::toDt(dt_t **pdt) +{ + assert(0 && "TypeInfoTypedefDeclaration"); +} + +void TypeInfoEnumDeclaration::toDt(dt_t **pdt) +{ + assert(0 && "TypeInfoEnumDeclaration"); +} + +void TypeInfoPointerDeclaration::toDt(dt_t **pdt) +{ + assert(0 && "TypeInfoPointerDeclaration"); +} + +void TypeInfoArrayDeclaration::toDt(dt_t **pdt) +{ + assert(0 && "TypeInfoArrayDeclaration"); +} + +void TypeInfoStaticArrayDeclaration::toDt(dt_t **pdt) +{ + assert(0 && "TypeInfoStaticArrayDeclaration"); +} + +void TypeInfoAssociativeArrayDeclaration::toDt(dt_t **pdt) +{ + assert(0 && "TypeInfoAssociativeArrayDeclaration"); +} + +void TypeInfoFunctionDeclaration::toDt(dt_t **pdt) +{ + assert(0 && "TypeInfoFunctionDeclaration"); +} + +void TypeInfoDelegateDeclaration::toDt(dt_t **pdt) +{ + assert(0 && "TypeInfoDelegateDeclaration"); +} + +void TypeInfoStructDeclaration::toDt(dt_t **pdt) +{ + assert(0 && "TypeInfoStructDeclaration"); +} + +void TypeInfoClassDeclaration::toDt(dt_t **pdt) +{ + assert(0 && "TypeInfoClassDeclaration"); +} + +void TypeInfoInterfaceDeclaration::toDt(dt_t **pdt) +{ + assert(0 && "TypeInfoInterfaceDeclaration"); +} + +void TypeInfoTupleDeclaration::toDt(dt_t **pdt) +{ + assert(0 && "TypeInfoTupleDeclaration"); +} + +// original dmdfe toDt code for reference + +#if 0 + +void TypeInfoDeclaration::toDt(dt_t **pdt) +{ + //printf("TypeInfoDeclaration::toDt() %s\n", toChars()); + dtxoff(pdt, Type::typeinfo->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo + dtdword(pdt, 0); // monitor +} + +void TypeInfoTypedefDeclaration::toDt(dt_t **pdt) +{ + //printf("TypeInfoTypedefDeclaration::toDt() %s\n", toChars()); + + dtxoff(pdt, Type::typeinfotypedef->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Typedef + dtdword(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 + + char *name = sd->toPrettyChars(); + size_t namelen = strlen(name); + dtdword(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 + dtdword(pdt, 0); // init.length + dtdword(pdt, 0); // init.ptr + } + else + { + dtdword(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 + dtdword(pdt, 0); // monitor + + assert(tinfo->ty == Tenum); + + TypeEnum *tc = (TypeEnum *)tinfo; + EnumDeclaration *sd = tc->sym; + + /* Put out: + * TypeInfo base; + * char[] name; + * void[] m_init; + */ + + sd->memtype->getTypeInfo(NULL); + dtxoff(pdt, sd->memtype->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for enum members + + char *name = sd->toPrettyChars(); + size_t namelen = strlen(name); + dtdword(pdt, namelen); + dtabytes(pdt, TYnptr, 0, namelen + 1, name); + + // void[] init; + if (tinfo->isZeroInit() || !sd->defaultval) + { // 0 initializer, or the same as the base type + dtdword(pdt, 0); // init.length + dtdword(pdt, 0); // init.ptr + } + else + { + dtdword(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 + dtdword(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 + dtdword(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 + dtdword(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 + + dtdword(pdt, tc->dim->toInteger()); // length +} + +void TypeInfoAssociativeArrayDeclaration::toDt(dt_t **pdt) +{ + //printf("TypeInfoAssociativeArrayDeclaration::toDt()\n"); + dtxoff(pdt, Type::typeinfoassociativearray->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_AssociativeArray + dtdword(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 +} + +void TypeInfoFunctionDeclaration::toDt(dt_t **pdt) +{ + //printf("TypeInfoFunctionDeclaration::toDt()\n"); + dtxoff(pdt, Type::typeinfofunction->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Function + dtdword(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 +} + +void TypeInfoDelegateDeclaration::toDt(dt_t **pdt) +{ + //printf("TypeInfoDelegateDeclaration::toDt()\n"); + dtxoff(pdt, Type::typeinfodelegate->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Delegate + dtdword(pdt, 0); // monitor + + assert(tinfo->ty == Tdelegate); + + TypeDelegate *tc = (TypeDelegate *)tinfo; + + tc->next->next->getTypeInfo(NULL); + dtxoff(pdt, tc->next->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for delegate return value +} + +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 + dtdword(pdt, 0); // monitor + + assert(tinfo->ty == Tstruct); + + TypeStruct *tc = (TypeStruct *)tinfo; + StructDeclaration *sd = tc->sym; + + /* Put out: + * char[] name; + * void[] init; + * hash_t function(void*) xtoHash; + * int function(void*,void*) xopEquals; + * int function(void*,void*) xopCmp; + * char[] function(void*) xtoString; + * uint m_flags; + * + * name[] + */ + + char *name = sd->toPrettyChars(); + size_t namelen = strlen(name); + dtdword(pdt, namelen); + //dtabytes(pdt, TYnptr, 0, namelen + 1, name); + dtxoff(pdt, toSymbol(), offset, TYnptr); + offset += namelen + 1; + + // void[] init; + dtdword(pdt, sd->structsize); // init.length + if (sd->zeroInit) + dtdword(pdt, 0); // NULL for 0 initialization + else + dtxoff(pdt, sd->toInitializer(), 0, TYnptr); // init.ptr + + FuncDeclaration *fd; + FuncDeclaration *fdx; + TypeFunction *tf; + Type *ta; + Dsymbol *s; + + static TypeFunction *tftohash; + static TypeFunction *tftostring; + + if (!tftohash) + { + Scope sc; + + tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd); + tftohash = (TypeFunction *)tftohash->semantic(0, &sc); + + tftostring = new TypeFunction(NULL, Type::tchar->arrayOf(), 0, LINKd); + tftostring = (TypeFunction *)tftostring->semantic(0, &sc); + } + + TypeFunction *tfeqptr; + { + Scope sc; + Arguments *arguments = new Arguments; + Argument *arg = new Argument(STCin, tc->pointerTo(), NULL, NULL); + + arguments->push(arg); + tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd); + tfeqptr = (TypeFunction *)tfeqptr->semantic(0, &sc); + } + +#if 0 + TypeFunction *tfeq; + { + Scope sc; + Array *arguments = new Array; + Argument *arg = new Argument(In, tc, NULL, NULL); + + arguments->push(arg); + tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd); + tfeq = (TypeFunction *)tfeq->semantic(0, &sc); + } +#endif + + 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); + else + //fdx->error("must be declared as extern (D) uint toHash()"); + dtdword(pdt, 0); + } + else + dtdword(pdt, 0); + + s = search_function(sd, Id::eq); + fdx = s ? s->isFuncDeclaration() : NULL; + for (int i = 0; i < 2; i++) + { + if (fdx) + { fd = fdx->overloadExactMatch(tfeqptr); + if (fd) + dtxoff(pdt, fd->toSymbol(), 0, TYnptr); + else + //fdx->error("must be declared as extern (D) int %s(%s*)", fdx->toChars(), sd->toChars()); + dtdword(pdt, 0); + } + else + dtdword(pdt, 0); + + s = search_function(sd, Id::cmp); + fdx = s ? s->isFuncDeclaration() : NULL; + } + + 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()"); + dtdword(pdt, 0); + } + else + dtdword(pdt, 0); + + // uint m_flags; + dtdword(pdt, tc->hasPointers()); + + // name[] + dtnbytes(pdt, namelen + 1, name); +} + +void TypeInfoClassDeclaration::toDt(dt_t **pdt) +{ + //printf("TypeInfoClassDeclaration::toDt() %s\n", tinfo->toChars()); + dtxoff(pdt, Type::typeinfoclass->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoClass + dtdword(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 +} + +void TypeInfoInterfaceDeclaration::toDt(dt_t **pdt) +{ + //printf("TypeInfoInterfaceDeclaration::toDt() %s\n", tinfo->toChars()); + dtxoff(pdt, Type::typeinfointerface->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoInterface + dtdword(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 +} + +void TypeInfoTupleDeclaration::toDt(dt_t **pdt) +{ + //printf("TypeInfoTupleDeclaration::toDt() %s\n", tinfo->toChars()); + dtxoff(pdt, Type::typeinfotypelist->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoInterface + dtdword(pdt, 0); // monitor + + assert(tinfo->ty == Ttuple); + + TypeTuple *tu = (TypeTuple *)tinfo; + + size_t dim = tu->arguments->dim; + dtdword(pdt, dim); // elements.length + + dt_t *d = NULL; + for (size_t i = 0; i < dim; i++) + { Argument *arg = (Argument *)tu->arguments->data[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() +{ + Symbol *s; + unsigned sz; + Dsymbol *parent; + + //printf("TypeInfoDeclaration::toObjFile(%p '%s') protection %d\n", this, toChars(), protection); + + 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 // Burton + if (s->Sdt && s->Sdt->dt == DT_azeros && s->Sdt->DTnext == NULL) + s->Sseg = UDATA; + else + s->Sseg = DATA; +#endif /* ELFOBJ */ + outdata(s); + if (isExport()) + obj_export(s,0); +} + +#endif