comparison 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
comparison
equal deleted inserted replaced
88:058d3925950e 89:ccca1c13e13a
1 // Modified for LLVMDC
2
3 module std.moduleinit;
4
5 //debug = 1;
6
7 private
8 {
9 import object;
10 import std.c.stdio;
11 import std.c.stdlib;
12 }
13
14 enum
15 { MIctorstart = 1, // we've started constructing it
16 MIctordone = 2, // finished construction
17 MIstandalone = 4, // module ctor does not depend on other module
18 // ctors being done first
19 }
20
21 /***********************
22 * Information about each module.
23 */
24 class ModuleInfo
25 {
26 char[] name;
27 ModuleInfo[] importedModules;
28 ClassInfo[] localClasses;
29
30 uint flags; // initialization state
31
32 void function() ctor;
33 void function() dtor;
34 void function() unitTest;
35
36 /******************
37 * Return collection of all modules in the program.
38 */
39 static ModuleInfo[] modules()
40 {
41 return _moduleinfo_array;
42 }
43 }
44
45 class ModuleCtorError : Exception
46 {
47 this(ModuleInfo m)
48 {
49 super("circular initialization dependency with module " ~ m.name);
50 }
51 }
52
53
54 // Win32: this gets initialized by minit.asm
55 // linux: this gets initialized in _moduleCtor()
56 extern (C) ModuleInfo[] _moduleinfo_array;
57
58 version (linux)
59 {
60 // This linked list is created by a compiler generated function inserted
61 // into the .ctor list by the compiler.
62 struct ModuleReference
63 {
64 ModuleReference* next;
65 ModuleInfo mod;
66 }
67
68 extern (C) ModuleReference *_Dmodule_ref; // start of linked list
69 }
70
71 ModuleInfo[] _moduleinfo_dtors;
72 uint _moduleinfo_dtors_i;
73
74 // Register termination function pointers
75 extern (C) int _fatexit(void *);
76
77 /*************************************
78 * Initialize the modules.
79 */
80
81 extern (C) void _moduleCtor()
82 {
83 debug printf("_moduleCtor()\n");
84 version (linux)
85 {
86 int len = 0;
87 ModuleReference *mr;
88
89 for (mr = _Dmodule_ref; mr; mr = mr.next)
90 len++;
91 _moduleinfo_array = new ModuleInfo[len];
92 len = 0;
93 for (mr = _Dmodule_ref; mr; mr = mr.next)
94 { _moduleinfo_array[len] = mr.mod;
95 len++;
96 }
97 }
98
99 version (Win32)
100 {
101 // Ensure module destructors also get called on program termination
102 //_fatexit(&_STD_moduleDtor);
103 }
104
105 _moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length];
106 debug printf("_moduleinfo_dtors = x%x\n", cast(void *)_moduleinfo_dtors);
107 _moduleCtor2(_moduleinfo_array, 0);
108
109 version (none)
110 {
111 foreach (m; _moduleinfo_array)
112 {
113 writefln("module %s, %d", m.name, m.localClasses.length);
114 foreach (c; m.localClasses)
115 {
116 writefln("\tclass %s", c.name);
117 }
118 }
119 }
120 }
121
122 void _moduleCtor2(ModuleInfo[] mi, int skip)
123 {
124 debug printf("_moduleCtor2(): %d modules\n", mi.length);
125 for (uint i = 0; i < mi.length; i++)
126 {
127 ModuleInfo m = mi[i];
128
129 debug printf("\tmodule[%d] = '%p'\n", i, m);
130 if (!m)
131 continue;
132 debug printf("\tmodule[%d] = '%.*s'\n", i, m.name);
133 if (m.flags & MIctordone)
134 continue;
135 debug printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m);
136
137 if (m.ctor || m.dtor)
138 {
139 if (m.flags & MIctorstart)
140 { if (skip || m.flags & MIstandalone)
141 continue;
142 throw new ModuleCtorError(m);
143 }
144
145 m.flags |= MIctorstart;
146 _moduleCtor2(m.importedModules, 0);
147 if (m.ctor)
148 (*m.ctor)();
149 m.flags &= ~MIctorstart;
150 m.flags |= MIctordone;
151
152 // Now that construction is done, register the destructor
153 //printf("\tadding module dtor x%x\n", m);
154 assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length);
155 _moduleinfo_dtors[_moduleinfo_dtors_i++] = m;
156 }
157 else
158 {
159 m.flags |= MIctordone;
160 _moduleCtor2(m.importedModules, 1);
161 }
162 }
163 }
164
165
166 /**********************************
167 * Destruct the modules.
168 */
169
170 // Starting the name with "_STD" means under linux a pointer to the
171 // function gets put in the .dtors segment.
172
173 extern (C) void _moduleDtor()
174 {
175 debug printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i);
176 for (uint i = _moduleinfo_dtors_i; i-- != 0;)
177 {
178 ModuleInfo m = _moduleinfo_dtors[i];
179
180 debug printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m);
181 if (m.dtor)
182 {
183 (*m.dtor)();
184 }
185 }
186 debug printf("_moduleDtor() done\n");
187 }
188
189 /**********************************
190 * Run unit tests.
191 */
192
193 extern (C) void _moduleUnitTests()
194 {
195 debug printf("_moduleUnitTests()\n");
196 for (uint i = 0; i < _moduleinfo_array.length; i++)
197 {
198 ModuleInfo m = _moduleinfo_array[i];
199
200 if (!m)
201 continue;
202
203 debug printf("\tmodule[%d] = '%.*s'\n", i, m.name);
204 if (m.unitTest)
205 {
206 (*m.unitTest)();
207 }
208 }
209 }
210