changeset 89:ccca1c13e13a trunk

[svn r93] a few fixes, some phobos additions. some very rough groundwork for moduleinfo and classinfo support
author lindquist
date Wed, 07 Nov 2007 02:45:47 +0100
parents 058d3925950e
children 16e88334bba7
files gen/tollvm.h gen/toobj.cpp gen/typinf.cpp lphobos/internal/objectimpl.d lphobos/phobos.d lphobos/std/moduleinit.d lphobos/std/outofmemory.d test/bug52.d test/moduleinfo1.d
diffstat 9 files changed, 569 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- 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);
--- 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);
 }
 
 /******************************************
--- 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<llvm::Constant*> 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<llvm::StructType>(cinfo->llvmInitZ->getType());
+    llvm::Constant* finalinit = llvm::ConstantStruct::get(st, inits);
+    Logger::cout() << "built the classinfo initializer:\n" << *finalinit <<'\n';
+
+    assert(0);
+    */
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- 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
--- 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,
--- /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)();
+	}
+    }
+}
+
--- /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()
+{
+}
--- /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() {}
--- /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;
+}
+