# HG changeset patch # User lindquist # Date 1194399947 -3600 # Node ID ccca1c13e13a8661b12e8be413b8661434482ddd # Parent 058d3925950e4cdeefcfdf44617d4c3a61397c49 [svn r93] a few fixes, some phobos additions. some very rough groundwork for moduleinfo and classinfo support diff -r 058d3925950e -r ccca1c13e13a gen/tollvm.h --- a/gen/tollvm.h Tue Nov 06 10:03:14 2007 +0100 +++ b/gen/tollvm.h Wed Nov 07 02:45:47 2007 +0100 @@ -64,6 +64,8 @@ void DtoLazyStaticInit(bool istempl, llvm::Value* gvar, Initializer* init, Type* t); +void DtoClassInfo(ClassDeclaration* cd); + // llvm wrappers void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes); bool DtoCanLoad(llvm::Value* ptr); diff -r 058d3925950e -r ccca1c13e13a gen/toobj.cpp --- a/gen/toobj.cpp Tue Nov 06 10:03:14 2007 +0100 +++ b/gen/toobj.cpp Wed Nov 07 02:45:47 2007 +0100 @@ -91,6 +91,9 @@ dsym->toObjFile(); } + // generate ModuleInfo + genmoduleinfo(); + gTargetData = 0; // emit the llvm main function if necessary @@ -139,6 +142,152 @@ void Module::genmoduleinfo() { +// The layout is: +// { +// void **vptr; +// monitor_t monitor; +// char[] name; // class name +// ModuleInfo importedModules[]; +// ClassInfo localClasses[]; +// uint flags; // initialization state +// void *ctor; +// void *dtor; +// void *unitTest; +// } + + if (moduleinfo) { + Logger::println("moduleinfo"); + } + if (vmoduleinfo) { + Logger::println("vmoduleinfo"); + } + if (needModuleInfo()) { + Logger::println("**** ATTENTION: module info is needed but skipped"); + } + + + /* + Symbol *msym = toSymbol(); + unsigned offset; + unsigned sizeof_ModuleInfo = 12 * PTRSIZE; + + ////////////////////////////////////////////// + + csym->Sclass = SCglobal; + csym->Sfl = FLdata; + +// The layout is: +// { +// void **vptr; +// monitor_t monitor; +// char[] name; // class name +// ModuleInfo importedModules[]; +// ClassInfo localClasses[]; +// uint flags; // initialization state +// void *ctor; +// void *dtor; +// void *unitTest; +// } + dt_t *dt = NULL; + + if (moduleinfo) + dtxoff(&dt, moduleinfo->toVtblSymbol(), 0, TYnptr); // vtbl for ModuleInfo + else + dtdword(&dt, 0); // BUG: should be an assert() + dtdword(&dt, 0); // monitor + + // name[] + char *name = toPrettyChars(); + size_t namelen = strlen(name); + dtdword(&dt, namelen); + dtabytes(&dt, TYnptr, 0, namelen + 1, name); + + ClassDeclarations aclasses; + int i; + + //printf("members->dim = %d\n", members->dim); + for (i = 0; i < members->dim; i++) + { + Dsymbol *member; + + member = (Dsymbol *)members->data[i]; + //printf("\tmember '%s'\n", member->toChars()); + member->addLocalClass(&aclasses); + } + + // importedModules[] + int aimports_dim = aimports.dim; + for (i = 0; i < aimports.dim; i++) + { Module *m = (Module *)aimports.data[i]; + if (!m->needModuleInfo()) + aimports_dim--; + } + dtdword(&dt, aimports_dim); + if (aimports.dim) + dtxoff(&dt, csym, sizeof_ModuleInfo, TYnptr); + else + dtdword(&dt, 0); + + // localClasses[] + dtdword(&dt, aclasses.dim); + if (aclasses.dim) + dtxoff(&dt, csym, sizeof_ModuleInfo + aimports_dim * PTRSIZE, TYnptr); + else + dtdword(&dt, 0); + + if (needmoduleinfo) + dtdword(&dt, 0); // flags (4 means MIstandalone) + else + dtdword(&dt, 4); // flags (4 means MIstandalone) + + if (sctor) + dtxoff(&dt, sctor, 0, TYnptr); + else + dtdword(&dt, 0); + + if (sdtor) + dtxoff(&dt, sdtor, 0, TYnptr); + else + dtdword(&dt, 0); + + if (stest) + dtxoff(&dt, stest, 0, TYnptr); + else + dtdword(&dt, 0); + + ////////////////////////////////////////////// + + for (i = 0; i < aimports.dim; i++) + { + Module *m; + + m = (Module *)aimports.data[i]; + if (m->needModuleInfo()) + { Symbol *s = m->toSymbol(); + s->Sflags |= SFLweak; + dtxoff(&dt, s, 0, TYnptr); + } + } + + for (i = 0; i < aclasses.dim; i++) + { + ClassDeclaration *cd; + + cd = (ClassDeclaration *)aclasses.data[i]; + dtxoff(&dt, cd->toSymbol(), 0, TYnptr); + } + + csym->Sdt = dt; +#if ELFOBJ + // Cannot be CONST because the startup code sets flag bits in it + csym->Sseg = DATA; +#endif + outdata(csym); + + ////////////////////////////////////////////// + + obj_moduleinfo(msym); + */ } /* ================================================================== */ @@ -553,6 +702,9 @@ gIR->structs.pop_back(); llvmInProgress = false; + + // if (ClassDeclaration::classinfo != this) + // DtoClassInfo(this); } /****************************************** diff -r 058d3925950e -r ccca1c13e13a gen/typinf.cpp --- a/gen/typinf.cpp Tue Nov 06 10:03:14 2007 +0100 +++ b/gen/typinf.cpp Wed Nov 07 02:45:47 2007 +0100 @@ -533,6 +533,7 @@ assert(tinfo->ty == Tstruct); TypeStruct *tc = (TypeStruct *)tinfo; StructDeclaration *sd = tc->sym; + sd->toObjFile(); ClassDeclaration* base = Type::typeinfostruct; base->toObjFile(); @@ -773,3 +774,131 @@ dtxoff(pdt, s, 0, TYnptr); // elements.ptr */ } + +/* ========================================================================= */ +/* ========================================================================= */ +/* CLASS INFO STUFF */ +/* ========================================================================= */ +/* ========================================================================= */ + +void DtoClassInfo(ClassDeclaration* cd) +{ +// The layout is: +// { +// void **vptr; +// monitor_t monitor; +// byte[] initializer; // static initialization data +// char[] name; // class name +// void *[] vtbl; +// Interface[] interfaces; +// ClassInfo *base; // base class +// void *destructor; +// void *invariant; // class invariant +// uint flags; +// void *deallocator; +// OffsetTypeInfo[] offTi; +// void *defaultConstructor; +// } + + // holds the list of initializers for llvm + std::vector inits; + + ClassDeclaration* cinfo = ClassDeclaration::classinfo; + assert(cinfo); + Logger::println("cinfo toObj"); + cinfo->toObjFile(); + + Logger::println("cinfo toObj done"); + assert(cinfo->type->ty == Tclass); + TypeClass* tc = (TypeClass*)cinfo->type; + //assert(tc->llvmInit); + //assert(cinfo->llvmInitZ); + + cinfo = ClassDeclaration::classinfo; + assert(cinfo->llvmInitZ); + + /* + llvm::Constant* c; + + // own vtable + c = cinfo->llvmInitZ->getOperand(0); + assert(c); + inits.push_back(c); + + // monitor + // TODO no monitors yet + + // initializer + c = cinfo->llvmInitZ->getOperand(1); + inits.push_back(c); + + // class name + // from dmd + char *name = cd->ident->toChars(); + size_t namelen = strlen(name); + if (!(namelen > 9 && memcmp(name, "TypeInfo_", 9) == 0)) + { + name = cd->toPrettyChars(); + namelen = strlen(name); + } + c = DtoConstString(name); + inits.push_back(c); + + // vtbl array + c = cinfo->llvmInitZ->getOperand(3); + inits.push_back(c); + + // interfaces array + c = cinfo->llvmInitZ->getOperand(4); + inits.push_back(c); + + // base classinfo + c = cinfo->llvmInitZ->getOperand(5); + inits.push_back(c); + + // destructor + c = cinfo->llvmInitZ->getOperand(5); + inits.push_back(c); + + // invariant + c = cinfo->llvmInitZ->getOperand(6); + inits.push_back(c); + + // flags + c = cinfo->llvmInitZ->getOperand(7); + inits.push_back(c); + + // allocator + c = cinfo->llvmInitZ->getOperand(8); + inits.push_back(c); + + // offset typeinfo + c = cinfo->llvmInitZ->getOperand(9); + inits.push_back(c); + + // default constructor + c = cinfo->llvmInitZ->getOperand(10); + inits.push_back(c); + + // build the initializer + const llvm::StructType* st = llvm::cast(cinfo->llvmInitZ->getType()); + llvm::Constant* finalinit = llvm::ConstantStruct::get(st, inits); + Logger::cout() << "built the classinfo initializer:\n" << *finalinit <<'\n'; + + assert(0); + */ +} + + + + + + + + + + + + + + diff -r 058d3925950e -r ccca1c13e13a lphobos/internal/objectimpl.d --- a/lphobos/internal/objectimpl.d Tue Nov 06 10:03:14 2007 +0100 +++ b/lphobos/internal/objectimpl.d Wed Nov 07 02:45:47 2007 +0100 @@ -32,10 +32,13 @@ * distribution. */ +/* + * This copy is modified to work with LLVMDC by Tomas Lindquist Olsen 2007 + */ module object; -//import std.outofmemory; +import std.outofmemory; /** * An unsigned integral type large enough to span the memory space. Use for @@ -260,6 +263,8 @@ } } ++/ + /** * Information about an interface. * A pointer to this appears as the first entry in the interface's vtbl[]. @@ -272,6 +277,7 @@ } import std.moduleinit; + /** * Runtime type information about a class. Can be retrieved for any class type * or instance by using the .classinfo property. @@ -287,7 +293,7 @@ Interface[] interfaces; /// interfaces this class implements ClassInfo base; /// base class void *destructor; - void (*classInvariant)(Object); + void function(Object) classInvariant; uint flags; // 1: // IUnknown // 2: // has no possible pointers into GC memory @@ -303,7 +309,7 @@ */ static ClassInfo find(char[] classname) { - foreach (m; ModuleInfo.modules()) + /+foreach (m; ModuleInfo.modules()) { //writefln("module %s, %d", m.name, m.localClasses.length); foreach (c; m.localClasses) @@ -312,7 +318,7 @@ if (c.name == classname) return c; } - } + }+/ return null; } @@ -321,7 +327,7 @@ */ Object create() { - if (flags & 8 && !defaultConstructor) + /+if (flags & 8 && !defaultConstructor) return null; Object o = _d_newclass(this); if (flags & 8 && defaultConstructor) @@ -329,12 +335,13 @@ defaultConstructor(o); } return o; + +/ + return null; } } -private import std.string; +//private import std.string; -+/ /** * Array of pairs giving the offset and type information for each diff -r 058d3925950e -r ccca1c13e13a lphobos/phobos.d --- a/lphobos/phobos.d Tue Nov 06 10:03:14 2007 +0100 +++ b/lphobos/phobos.d Wed Nov 07 02:45:47 2007 +0100 @@ -4,6 +4,8 @@ std.array, std.ctype, std.intrinsic, +std.moduleinit, +std.outofmemory, std.stdint, std.stdio, std.stdarg, diff -r 058d3925950e -r ccca1c13e13a lphobos/std/moduleinit.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lphobos/std/moduleinit.d Wed Nov 07 02:45:47 2007 +0100 @@ -0,0 +1,210 @@ +// Modified for LLVMDC + +module std.moduleinit; + +//debug = 1; + +private +{ + import object; + import std.c.stdio; + import std.c.stdlib; +} + +enum +{ MIctorstart = 1, // we've started constructing it + MIctordone = 2, // finished construction + MIstandalone = 4, // module ctor does not depend on other module + // ctors being done first +} + +/*********************** + * Information about each module. + */ +class ModuleInfo +{ + char[] name; + ModuleInfo[] importedModules; + ClassInfo[] localClasses; + + uint flags; // initialization state + + void function() ctor; + void function() dtor; + void function() unitTest; + + /****************** + * Return collection of all modules in the program. + */ + static ModuleInfo[] modules() + { + return _moduleinfo_array; + } +} + +class ModuleCtorError : Exception +{ + this(ModuleInfo m) + { + super("circular initialization dependency with module " ~ m.name); + } +} + + +// Win32: this gets initialized by minit.asm +// linux: this gets initialized in _moduleCtor() +extern (C) ModuleInfo[] _moduleinfo_array; + +version (linux) +{ + // This linked list is created by a compiler generated function inserted + // into the .ctor list by the compiler. + struct ModuleReference + { + ModuleReference* next; + ModuleInfo mod; + } + + extern (C) ModuleReference *_Dmodule_ref; // start of linked list +} + +ModuleInfo[] _moduleinfo_dtors; +uint _moduleinfo_dtors_i; + +// Register termination function pointers +extern (C) int _fatexit(void *); + +/************************************* + * Initialize the modules. + */ + +extern (C) void _moduleCtor() +{ + debug printf("_moduleCtor()\n"); + version (linux) + { + int len = 0; + ModuleReference *mr; + + for (mr = _Dmodule_ref; mr; mr = mr.next) + len++; + _moduleinfo_array = new ModuleInfo[len]; + len = 0; + for (mr = _Dmodule_ref; mr; mr = mr.next) + { _moduleinfo_array[len] = mr.mod; + len++; + } + } + + version (Win32) + { + // Ensure module destructors also get called on program termination + //_fatexit(&_STD_moduleDtor); + } + + _moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length]; + debug printf("_moduleinfo_dtors = x%x\n", cast(void *)_moduleinfo_dtors); + _moduleCtor2(_moduleinfo_array, 0); + + version (none) + { + foreach (m; _moduleinfo_array) + { + writefln("module %s, %d", m.name, m.localClasses.length); + foreach (c; m.localClasses) + { + writefln("\tclass %s", c.name); + } + } + } +} + +void _moduleCtor2(ModuleInfo[] mi, int skip) +{ + debug printf("_moduleCtor2(): %d modules\n", mi.length); + for (uint i = 0; i < mi.length; i++) + { + ModuleInfo m = mi[i]; + + debug printf("\tmodule[%d] = '%p'\n", i, m); + if (!m) + continue; + debug printf("\tmodule[%d] = '%.*s'\n", i, m.name); + if (m.flags & MIctordone) + continue; + debug printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m); + + if (m.ctor || m.dtor) + { + if (m.flags & MIctorstart) + { if (skip || m.flags & MIstandalone) + continue; + throw new ModuleCtorError(m); + } + + m.flags |= MIctorstart; + _moduleCtor2(m.importedModules, 0); + if (m.ctor) + (*m.ctor)(); + m.flags &= ~MIctorstart; + m.flags |= MIctordone; + + // Now that construction is done, register the destructor + //printf("\tadding module dtor x%x\n", m); + assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length); + _moduleinfo_dtors[_moduleinfo_dtors_i++] = m; + } + else + { + m.flags |= MIctordone; + _moduleCtor2(m.importedModules, 1); + } + } +} + + +/********************************** + * Destruct the modules. + */ + +// Starting the name with "_STD" means under linux a pointer to the +// function gets put in the .dtors segment. + +extern (C) void _moduleDtor() +{ + debug printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i); + for (uint i = _moduleinfo_dtors_i; i-- != 0;) + { + ModuleInfo m = _moduleinfo_dtors[i]; + + debug printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m); + if (m.dtor) + { + (*m.dtor)(); + } + } + debug printf("_moduleDtor() done\n"); +} + +/********************************** + * Run unit tests. + */ + +extern (C) void _moduleUnitTests() +{ + debug printf("_moduleUnitTests()\n"); + for (uint i = 0; i < _moduleinfo_array.length; i++) + { + ModuleInfo m = _moduleinfo_array[i]; + + if (!m) + continue; + + debug printf("\tmodule[%d] = '%.*s'\n", i, m.name); + if (m.unitTest) + { + (*m.unitTest)(); + } + } +} + diff -r 058d3925950e -r ccca1c13e13a lphobos/std/outofmemory.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lphobos/std/outofmemory.d Wed Nov 07 02:45:47 2007 +0100 @@ -0,0 +1,44 @@ +/** + * Macros: + * WIKI=Phobos/StdOutOfMemory + * Copyright: + * Placed into public domain. + * www.digitalmars.com + */ + + +module std.outofmemory; + +/****** + * This exception is thrown when out of memory errors happen. + */ + +class OutOfMemoryException : Exception +{ + static char[] s = "Out of memory"; + + /** + * Default constructor + */ + this() + { + super(s); + } + + char[] toString() + { + return s; + } +} + +extern (C) void _d_OutOfMemory() +{ + assert(0); + /*throw cast(OutOfMemoryException) + cast(void *) + OutOfMemoryException.classinfo.init;*/ +} + +static this() +{ +} diff -r 058d3925950e -r ccca1c13e13a test/bug52.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/bug52.d Wed Nov 07 02:45:47 2007 +0100 @@ -0,0 +1,5 @@ +module bug52; +struct Vec { double x,y,z; } +struct Pair(T, U) { T first; U second; } +typedef Pair!(double, Vec) Hit; +void main() {} diff -r 058d3925950e -r ccca1c13e13a test/moduleinfo1.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/moduleinfo1.d Wed Nov 07 02:45:47 2007 +0100 @@ -0,0 +1,11 @@ +module moduleinfo1; + +class C +{ +} + +void main() +{ + C c; +} +