diff lphobos/std/moduleinit.d @ 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
children fd7ad91fd713
line wrap: on
line diff
--- /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)();
+	}
+    }
+}
+