Mercurial > projects > ldc
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 |