Mercurial > projects > ldc
annotate tango/lib/compiler/llvmdc/genobj.d @ 133:44a95ac7368a trunk
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
In particular, assertions has been fixed to include file/line info, and much more!
author | lindquist |
---|---|
date | Mon, 14 Jan 2008 05:11:54 +0100 |
parents | 1700239cab2e |
children | 7816aafeea3c |
rev | line source |
---|---|
132 | 1 /** |
2 * Part of the D programming language runtime library. | |
3 * Forms the symbols available to all D programs. Includes | |
4 * Object, which is the root of the class object hierarchy. | |
5 * | |
6 * This module is implicitly imported. | |
7 * Macros: | |
8 * WIKI = Object | |
9 */ | |
10 | |
11 /* | |
12 * Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com | |
13 * Written by Walter Bright | |
14 * | |
15 * This software is provided 'as-is', without any express or implied | |
16 * warranty. In no event will the authors be held liable for any damages | |
17 * arising from the use of this software. | |
18 * | |
19 * Permission is granted to anyone to use this software for any purpose, | |
20 * including commercial applications, and to alter it and redistribute it | |
21 * freely, in both source and binary form, subject to the following | |
22 * restrictions: | |
23 * | |
24 * o The origin of this software must not be misrepresented; you must not | |
25 * claim that you wrote the original software. If you use this software | |
26 * in a product, an acknowledgment in the product documentation would be | |
27 * appreciated but is not required. | |
28 * o Altered source versions must be plainly marked as such, and must not | |
29 * be misrepresented as being the original software. | |
30 * o This notice may not be removed or altered from any source | |
31 * distribution. | |
32 */ | |
33 | |
34 /* | |
35 * Modified by Sean Kelly <sean@f4.ca> for use with Tango. | |
36 */ | |
37 | |
38 module object; | |
39 | |
133
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
40 //debug=PRINTF; |
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
41 |
132 | 42 private |
43 { | |
44 import tango.stdc.string; // : memcmp, memcpy; | |
45 import tango.stdc.stdlib; // : calloc, realloc, free; | |
46 import util.string; | |
47 debug(PRINTF) import tango.stdc.stdio; // : printf; | |
48 | |
49 extern (C) void onOutOfMemoryError(); | |
50 extern (C) Object _d_newclass(ClassInfo ci); | |
51 } | |
52 | |
53 // NOTE: For some reason, this declaration method doesn't work | |
54 // in this particular file (and this file only). It must | |
55 // be a DMD thing. | |
56 //alias typeof(int.sizeof) size_t; | |
57 //alias typeof(cast(void*)0 - cast(void*)0) ptrdiff_t; | |
58 | |
59 version( X86_64 ) | |
60 { | |
61 alias ulong size_t; | |
62 alias long ptrdiff_t; | |
63 } | |
64 else | |
65 { | |
66 alias uint size_t; | |
67 alias int ptrdiff_t; | |
68 } | |
69 | |
70 alias size_t hash_t; | |
71 | |
72 /** | |
73 * All D class objects inherit from Object. | |
74 */ | |
75 class Object | |
76 { | |
77 /** | |
78 * Convert Object to a human readable string. | |
79 */ | |
80 char[] toString() | |
81 { | |
82 return this.classinfo.name; | |
83 } | |
84 | |
85 /** | |
86 * Compute hash function for Object. | |
87 */ | |
88 hash_t toHash() | |
89 { | |
90 // BUG: this prevents a compacting GC from working, needs to be fixed | |
91 return cast(hash_t)cast(void*)this; | |
92 } | |
93 | |
94 /** | |
95 * Compare with another Object obj. | |
96 * Returns: | |
97 * $(TABLE | |
98 * $(TR $(TD this < obj) $(TD < 0)) | |
99 * $(TR $(TD this == obj) $(TD 0)) | |
100 * $(TR $(TD this > obj) $(TD > 0)) | |
101 * ) | |
102 */ | |
103 int opCmp(Object o) | |
104 { | |
105 // BUG: this prevents a compacting GC from working, needs to be fixed | |
106 //return cast(int)cast(void*)this - cast(int)cast(void*)o; | |
107 | |
108 //throw new Exception("need opCmp for class " ~ this.classinfo.name); | |
109 return this !is o; | |
110 } | |
111 | |
112 /** | |
113 * Returns !=0 if this object does have the same contents as obj. | |
114 */ | |
115 int opEquals(Object o) | |
116 { | |
117 return cast(int)(this is o); | |
118 } | |
119 | |
120 interface Monitor | |
121 { | |
122 void lock(); | |
123 void unlock(); | |
124 } | |
125 } | |
126 | |
127 /** | |
128 * Information about an interface. | |
129 * A pointer to this appears as the first entry in the interface's vtbl[]. | |
130 */ | |
131 struct Interface | |
132 { | |
133 ClassInfo classinfo; /// .classinfo for this interface (not for containing class) | |
134 void*[] vtbl; | |
135 ptrdiff_t offset; /// offset to Interface 'this' from Object 'this' | |
136 } | |
137 | |
138 /** | |
139 * Runtime type information about a class. Can be retrieved for any class type | |
140 * or instance by using the .classinfo property. | |
141 * A pointer to this appears as the first entry in the class's vtbl[]. | |
142 */ | |
143 class ClassInfo : Object | |
144 { | |
145 byte[] init; /** class static initializer | |
146 * (init.length gives size in bytes of class) | |
147 */ | |
148 char[] name; /// class name | |
149 void*[] vtbl; /// virtual function pointer table | |
150 Interface[] interfaces; /// interfaces this class implements | |
151 ClassInfo base; /// base class | |
152 void* destructor; | |
153 void function(Object) classInvariant; | |
154 uint flags; | |
155 // 1: // IUnknown | |
156 // 2: // has no possible pointers into GC memory | |
157 // 4: // has offTi[] member | |
158 // 8: // has constructors | |
159 void* deallocator; | |
160 OffsetTypeInfo[] offTi; | |
161 void function(Object) defaultConstructor; // default Constructor | |
162 | |
163 /** | |
164 * Search all modules for ClassInfo corresponding to classname. | |
165 * Returns: null if not found | |
166 */ | |
167 static ClassInfo find(char[] classname) | |
168 { | |
169 foreach (m; ModuleInfo) | |
170 { | |
171 //writefln("module %s, %d", m.name, m.localClasses.length); | |
172 foreach (c; m.localClasses) | |
173 { | |
174 //writefln("\tclass %s", c.name); | |
175 if (c.name == classname) | |
176 return c; | |
177 } | |
178 } | |
179 return null; | |
180 } | |
181 | |
182 /** | |
183 * Create instance of Object represented by 'this'. | |
184 */ | |
185 Object create() | |
186 { | |
187 if (flags & 8 && !defaultConstructor) | |
188 return null; | |
189 Object o = _d_newclass(this); | |
190 if (flags & 8 && defaultConstructor) | |
191 { | |
192 defaultConstructor(o); | |
193 } | |
194 return o; | |
195 } | |
196 } | |
197 | |
198 /** | |
199 * Array of pairs giving the offset and type information for each | |
200 * member in an aggregate. | |
201 */ | |
202 struct OffsetTypeInfo | |
203 { | |
204 size_t offset; /// Offset of member from start of object | |
205 TypeInfo ti; /// TypeInfo for this member | |
206 } | |
207 | |
208 /** | |
209 * Runtime type information about a type. | |
210 * Can be retrieved for any type using a | |
211 * <a href="../expression.html#typeidexpression">TypeidExpression</a>. | |
212 */ | |
213 class TypeInfo | |
214 { | |
215 hash_t toHash() | |
216 { hash_t hash; | |
217 | |
218 foreach (char c; this.toString()) | |
219 hash = hash * 9 + c; | |
220 return hash; | |
221 } | |
222 | |
223 int opCmp(Object o) | |
224 { | |
225 if (this is o) | |
226 return 0; | |
227 TypeInfo ti = cast(TypeInfo)o; | |
228 if (ti is null) | |
229 return 1; | |
230 return stringCompare(this.toString(), ti.toString()); | |
231 } | |
232 | |
233 int opEquals(Object o) | |
234 { | |
235 /* TypeInfo instances are singletons, but duplicates can exist | |
236 * across DLL's. Therefore, comparing for a name match is | |
237 * sufficient. | |
238 */ | |
239 if (this is o) | |
240 return 1; | |
241 TypeInfo ti = cast(TypeInfo)o; | |
242 return cast(int)(ti && this.toString() == ti.toString()); | |
243 } | |
244 | |
245 /// Returns a hash of the instance of a type. | |
246 hash_t getHash(void *p) { return cast(hash_t)p; } | |
247 | |
248 /// Compares two instances for equality. | |
249 int equals(void *p1, void *p2) { return cast(int)(p1 == p2); } | |
250 | |
251 /// Compares two instances for <, ==, or >. | |
252 int compare(void *p1, void *p2) { return 0; } | |
253 | |
254 /// Returns size of the type. | |
255 size_t tsize() { return 0; } | |
256 | |
257 /// Swaps two instances of the type. | |
258 void swap(void *p1, void *p2) | |
259 { | |
260 size_t n = tsize(); | |
261 for (size_t i = 0; i < n; i++) | |
262 { byte t; | |
263 | |
264 t = (cast(byte *)p1)[i]; | |
265 (cast(byte *)p1)[i] = (cast(byte *)p2)[i]; | |
266 (cast(byte *)p2)[i] = t; | |
267 } | |
268 } | |
269 | |
270 /// Get TypeInfo for 'next' type, as defined by what kind of type this is, | |
271 /// null if none. | |
272 TypeInfo next() { return null; } | |
273 | |
274 /// Return default initializer, null if default initialize to 0 | |
275 void[] init() { return null; } | |
276 | |
277 /// Get flags for type: 1 means GC should scan for pointers | |
278 uint flags() { return 0; } | |
279 | |
280 /// Get type information on the contents of the type; null if not available | |
281 OffsetTypeInfo[] offTi() { return null; } | |
282 } | |
283 | |
284 class TypeInfo_Typedef : TypeInfo | |
285 { | |
286 char[] toString() { return name; } | |
287 | |
288 int opEquals(Object o) | |
289 { TypeInfo_Typedef c; | |
290 | |
291 return cast(int) | |
292 (this is o || | |
293 ((c = cast(TypeInfo_Typedef)o) !is null && | |
294 this.name == c.name && | |
295 this.base == c.base)); | |
296 } | |
297 | |
298 hash_t getHash(void *p) { return base.getHash(p); } | |
299 int equals(void *p1, void *p2) { return base.equals(p1, p2); } | |
300 int compare(void *p1, void *p2) { return base.compare(p1, p2); } | |
301 size_t tsize() { return base.tsize(); } | |
302 void swap(void *p1, void *p2) { return base.swap(p1, p2); } | |
303 | |
304 TypeInfo next() { return base.next(); } | |
305 uint flags() { return base.flags(); } | |
306 void[] init() { return m_init.length ? m_init : base.init(); } | |
307 | |
308 TypeInfo base; | |
309 char[] name; | |
310 void[] m_init; | |
311 } | |
312 | |
313 class TypeInfo_Enum : TypeInfo_Typedef | |
314 { | |
315 } | |
316 | |
317 class TypeInfo_Pointer : TypeInfo | |
318 { | |
319 char[] toString() { return m_next.toString() ~ "*"; } | |
320 | |
321 int opEquals(Object o) | |
322 { TypeInfo_Pointer c; | |
323 | |
324 return this is o || | |
325 ((c = cast(TypeInfo_Pointer)o) !is null && | |
326 this.m_next == c.m_next); | |
327 } | |
328 | |
329 hash_t getHash(void *p) | |
330 { | |
331 return cast(hash_t)*cast(void**)p; | |
332 } | |
333 | |
334 int equals(void *p1, void *p2) | |
335 { | |
336 return cast(int)(*cast(void* *)p1 == *cast(void* *)p2); | |
337 } | |
338 | |
339 int compare(void *p1, void *p2) | |
340 { | |
341 if (*cast(void* *)p1 < *cast(void* *)p2) | |
342 return -1; | |
343 else if (*cast(void* *)p1 > *cast(void* *)p2) | |
344 return 1; | |
345 else | |
346 return 0; | |
347 } | |
348 | |
349 size_t tsize() | |
350 { | |
351 return (void*).sizeof; | |
352 } | |
353 | |
354 void swap(void *p1, void *p2) | |
355 { void* tmp; | |
356 tmp = *cast(void**)p1; | |
357 *cast(void**)p1 = *cast(void**)p2; | |
358 *cast(void**)p2 = tmp; | |
359 } | |
360 | |
361 TypeInfo next() { return m_next; } | |
362 uint flags() { return 1; } | |
363 | |
364 TypeInfo m_next; | |
365 } | |
366 | |
367 class TypeInfo_Array : TypeInfo | |
368 { | |
369 char[] toString() { return value.toString() ~ "[]"; } | |
370 | |
371 int opEquals(Object o) | |
372 { TypeInfo_Array c; | |
373 | |
374 return cast(int) | |
375 (this is o || | |
376 ((c = cast(TypeInfo_Array)o) !is null && | |
377 this.value == c.value)); | |
378 } | |
379 | |
380 hash_t getHash(void *p) | |
381 { size_t sz = value.tsize(); | |
382 hash_t hash = 0; | |
383 void[] a = *cast(void[]*)p; | |
384 for (size_t i = 0; i < a.length; i++) | |
385 hash += value.getHash(a.ptr + i * sz); | |
386 return hash; | |
387 } | |
388 | |
389 int equals(void *p1, void *p2) | |
390 { | |
391 void[] a1 = *cast(void[]*)p1; | |
392 void[] a2 = *cast(void[]*)p2; | |
393 if (a1.length != a2.length) | |
394 return 0; | |
395 size_t sz = value.tsize(); | |
396 for (size_t i = 0; i < a1.length; i++) | |
397 { | |
398 if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz)) | |
399 return 0; | |
400 } | |
401 return 1; | |
402 } | |
403 | |
404 int compare(void *p1, void *p2) | |
405 { | |
406 void[] a1 = *cast(void[]*)p1; | |
407 void[] a2 = *cast(void[]*)p2; | |
408 size_t sz = value.tsize(); | |
409 size_t len = a1.length; | |
410 | |
411 if (a2.length < len) | |
412 len = a2.length; | |
413 for (size_t u = 0; u < len; u++) | |
414 { | |
415 int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz); | |
416 if (result) | |
417 return result; | |
418 } | |
419 return cast(int)a1.length - cast(int)a2.length; | |
420 } | |
421 | |
422 size_t tsize() | |
423 { | |
424 return (void[]).sizeof; | |
425 } | |
426 | |
427 void swap(void *p1, void *p2) | |
428 { void[] tmp; | |
429 tmp = *cast(void[]*)p1; | |
430 *cast(void[]*)p1 = *cast(void[]*)p2; | |
431 *cast(void[]*)p2 = tmp; | |
432 } | |
433 | |
434 TypeInfo value; | |
435 | |
436 TypeInfo next() | |
437 { | |
438 return value; | |
439 } | |
440 | |
441 uint flags() { return 1; } | |
442 } | |
443 | |
444 class TypeInfo_StaticArray : TypeInfo | |
445 { | |
446 char[] toString() | |
447 { | |
448 char [10] tmp = void; | |
449 return value.toString() ~ "[" ~ intToUtf8(tmp, len) ~ "]"; | |
450 } | |
451 | |
452 int opEquals(Object o) | |
453 { TypeInfo_StaticArray c; | |
454 | |
455 return cast(int) | |
456 (this is o || | |
457 ((c = cast(TypeInfo_StaticArray)o) !is null && | |
458 this.len == c.len && | |
459 this.value == c.value)); | |
460 } | |
461 | |
462 hash_t getHash(void *p) | |
463 { size_t sz = value.tsize(); | |
464 hash_t hash = 0; | |
465 for (size_t i = 0; i < len; i++) | |
466 hash += value.getHash(p + i * sz); | |
467 return hash; | |
468 } | |
469 | |
470 int equals(void *p1, void *p2) | |
471 { | |
472 size_t sz = value.tsize(); | |
473 | |
474 for (size_t u = 0; u < len; u++) | |
475 { | |
476 if (!value.equals(p1 + u * sz, p2 + u * sz)) | |
477 return 0; | |
478 } | |
479 return 1; | |
480 } | |
481 | |
482 int compare(void *p1, void *p2) | |
483 { | |
484 size_t sz = value.tsize(); | |
485 | |
486 for (size_t u = 0; u < len; u++) | |
487 { | |
488 int result = value.compare(p1 + u * sz, p2 + u * sz); | |
489 if (result) | |
490 return result; | |
491 } | |
492 return 0; | |
493 } | |
494 | |
495 size_t tsize() | |
496 { | |
497 return len * value.tsize(); | |
498 } | |
499 | |
500 void swap(void *p1, void *p2) | |
501 { void* tmp; | |
502 size_t sz = value.tsize(); | |
503 ubyte[16] buffer; | |
504 void* pbuffer; | |
505 | |
506 if (sz < buffer.sizeof) | |
507 tmp = buffer.ptr; | |
508 else | |
509 tmp = pbuffer = (new void[sz]).ptr; | |
510 | |
511 for (size_t u = 0; u < len; u += sz) | |
512 { size_t o = u * sz; | |
513 memcpy(tmp, p1 + o, sz); | |
514 memcpy(p1 + o, p2 + o, sz); | |
515 memcpy(p2 + o, tmp, sz); | |
516 } | |
517 if (pbuffer) | |
518 delete pbuffer; | |
519 } | |
520 | |
521 void[] init() { return value.init(); } | |
522 TypeInfo next() { return value; } | |
523 uint flags() { return value.flags(); } | |
524 | |
525 TypeInfo value; | |
526 size_t len; | |
527 } | |
528 | |
529 class TypeInfo_AssociativeArray : TypeInfo | |
530 { | |
531 char[] toString() | |
532 { | |
533 return next.toString() ~ "[" ~ key.toString() ~ "]"; | |
534 } | |
535 | |
536 int opEquals(Object o) | |
537 { TypeInfo_AssociativeArray c; | |
538 | |
539 return this is o || | |
540 ((c = cast(TypeInfo_AssociativeArray)o) !is null && | |
541 this.key == c.key && | |
542 this.value == c.value); | |
543 } | |
544 | |
545 // BUG: need to add the rest of the functions | |
546 | |
547 size_t tsize() | |
548 { | |
549 return (char[int]).sizeof; | |
550 } | |
551 | |
552 TypeInfo next() { return value; } | |
553 uint flags() { return 1; } | |
554 | |
555 TypeInfo value; | |
556 TypeInfo key; | |
557 } | |
558 | |
559 class TypeInfo_Function : TypeInfo | |
560 { | |
561 char[] toString() | |
562 { | |
563 return next.toString() ~ "()"; | |
564 } | |
565 | |
566 int opEquals(Object o) | |
567 { TypeInfo_Function c; | |
568 | |
569 return this is o || | |
570 ((c = cast(TypeInfo_Function)o) !is null && | |
571 this.next == c.next); | |
572 } | |
573 | |
574 // BUG: need to add the rest of the functions | |
575 | |
576 size_t tsize() | |
577 { | |
578 return 0; // no size for functions | |
579 } | |
580 | |
581 TypeInfo next; | |
582 } | |
583 | |
584 class TypeInfo_Delegate : TypeInfo | |
585 { | |
586 char[] toString() | |
587 { | |
588 return next.toString() ~ " delegate()"; | |
589 } | |
590 | |
591 int opEquals(Object o) | |
592 { TypeInfo_Delegate c; | |
593 | |
594 return this is o || | |
595 ((c = cast(TypeInfo_Delegate)o) !is null && | |
596 this.next == c.next); | |
597 } | |
598 | |
599 // BUG: need to add the rest of the functions | |
600 | |
601 size_t tsize() | |
602 { alias int delegate() dg; | |
603 return dg.sizeof; | |
604 } | |
605 | |
606 uint flags() { return 1; } | |
607 | |
608 TypeInfo next; | |
609 } | |
610 | |
611 class TypeInfo_Class : TypeInfo | |
612 { | |
613 char[] toString() { return info.name; } | |
614 | |
615 int opEquals(Object o) | |
616 { TypeInfo_Class c; | |
617 | |
618 return this is o || | |
619 ((c = cast(TypeInfo_Class)o) !is null && | |
620 this.info.name == c.classinfo.name); | |
621 } | |
622 | |
623 hash_t getHash(void *p) | |
624 { | |
625 Object o = *cast(Object*)p; | |
626 assert(o); | |
627 return o.toHash(); | |
628 } | |
629 | |
630 int equals(void *p1, void *p2) | |
631 { | |
632 Object o1 = *cast(Object*)p1; | |
633 Object o2 = *cast(Object*)p2; | |
634 | |
635 return (o1 is o2) || (o1 && o1.opEquals(o2)); | |
636 } | |
637 | |
638 int compare(void *p1, void *p2) | |
639 { | |
640 Object o1 = *cast(Object*)p1; | |
641 Object o2 = *cast(Object*)p2; | |
642 int c = 0; | |
643 | |
644 // Regard null references as always being "less than" | |
645 if (o1 !is o2) | |
646 { | |
647 if (o1) | |
648 { if (!o2) | |
649 c = 1; | |
650 else | |
651 c = o1.opCmp(o2); | |
652 } | |
653 else | |
654 c = -1; | |
655 } | |
656 return c; | |
657 } | |
658 | |
659 size_t tsize() | |
660 { | |
661 return Object.sizeof; | |
662 } | |
663 | |
664 uint flags() { return 1; } | |
665 | |
666 OffsetTypeInfo[] offTi() | |
667 { | |
668 return (info.flags & 4) ? info.offTi : null; | |
669 } | |
670 | |
671 ClassInfo info; | |
672 } | |
673 | |
674 class TypeInfo_Interface : TypeInfo | |
675 { | |
676 char[] toString() { return info.name; } | |
677 | |
678 int opEquals(Object o) | |
679 { TypeInfo_Interface c; | |
680 | |
681 return this is o || | |
682 ((c = cast(TypeInfo_Interface)o) !is null && | |
683 this.info.name == c.classinfo.name); | |
684 } | |
685 | |
686 hash_t getHash(void *p) | |
687 { | |
688 Interface* pi = **cast(Interface ***)*cast(void**)p; | |
689 Object o = cast(Object)(*cast(void**)p - pi.offset); | |
690 assert(o); | |
691 return o.toHash(); | |
692 } | |
693 | |
694 int equals(void *p1, void *p2) | |
695 { | |
696 Interface* pi = **cast(Interface ***)*cast(void**)p1; | |
697 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset); | |
698 pi = **cast(Interface ***)*cast(void**)p2; | |
699 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset); | |
700 | |
701 return o1 == o2 || (o1 && o1.opCmp(o2) == 0); | |
702 } | |
703 | |
704 int compare(void *p1, void *p2) | |
705 { | |
706 Interface* pi = **cast(Interface ***)*cast(void**)p1; | |
707 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset); | |
708 pi = **cast(Interface ***)*cast(void**)p2; | |
709 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset); | |
710 int c = 0; | |
711 | |
712 // Regard null references as always being "less than" | |
713 if (o1 != o2) | |
714 { | |
715 if (o1) | |
716 { if (!o2) | |
717 c = 1; | |
718 else | |
719 c = o1.opCmp(o2); | |
720 } | |
721 else | |
722 c = -1; | |
723 } | |
724 return c; | |
725 } | |
726 | |
727 size_t tsize() | |
728 { | |
729 return Object.sizeof; | |
730 } | |
731 | |
732 uint flags() { return 1; } | |
733 | |
734 ClassInfo info; | |
735 } | |
736 | |
737 class TypeInfo_Struct : TypeInfo | |
738 { | |
739 char[] toString() { return name; } | |
740 | |
741 int opEquals(Object o) | |
742 { TypeInfo_Struct s; | |
743 | |
744 return this is o || | |
745 ((s = cast(TypeInfo_Struct)o) !is null && | |
746 this.name == s.name && | |
747 this.init.length == s.init.length); | |
748 } | |
749 | |
750 hash_t getHash(void *p) | |
751 { hash_t h; | |
752 | |
753 assert(p); | |
754 if (xtoHash) | |
755 { debug(PRINTF) printf("getHash() using xtoHash\n"); | |
756 h = (*xtoHash)(p); | |
757 } | |
758 else | |
759 { | |
760 debug(PRINTF) printf("getHash() using default hash\n"); | |
761 // A sorry hash algorithm. | |
762 // Should use the one for strings. | |
763 // BUG: relies on the GC not moving objects | |
764 for (size_t i = 0; i < init.length; i++) | |
765 { h = h * 9 + *cast(ubyte*)p; | |
766 p++; | |
767 } | |
768 } | |
769 return h; | |
770 } | |
771 | |
772 int equals(void *p2, void *p1) | |
773 { int c; | |
774 | |
775 if (p1 == p2) | |
776 c = 1; | |
777 else if (!p1 || !p2) | |
778 c = 0; | |
779 else if (xopEquals) | |
780 c = (*xopEquals)(p1, p2); | |
781 else | |
782 // BUG: relies on the GC not moving objects | |
783 c = (memcmp(p1, p2, init.length) == 0); | |
784 return c; | |
785 } | |
786 | |
787 int compare(void *p2, void *p1) | |
788 { | |
789 int c = 0; | |
790 | |
791 // Regard null references as always being "less than" | |
792 if (p1 != p2) | |
793 { | |
794 if (p1) | |
795 { if (!p2) | |
796 c = 1; | |
797 else if (xopCmp) | |
798 c = (*xopCmp)(p1, p2); | |
799 else | |
800 // BUG: relies on the GC not moving objects | |
801 c = memcmp(p1, p2, init.length); | |
802 } | |
803 else | |
804 c = -1; | |
805 } | |
806 return c; | |
807 } | |
808 | |
809 size_t tsize() | |
810 { | |
811 return init.length; | |
812 } | |
813 | |
814 void[] init() { return m_init; } | |
815 | |
816 uint flags() { return m_flags; } | |
817 | |
818 char[] name; | |
819 void[] m_init; // initializer; init.ptr == null if 0 initialize | |
820 | |
821 hash_t function(void*) xtoHash; | |
822 int function(void*,void*) xopEquals; | |
823 int function(void*,void*) xopCmp; | |
824 char[] function(void*) xtoString; | |
825 | |
826 uint m_flags; | |
827 } | |
828 | |
829 class TypeInfo_Tuple : TypeInfo | |
830 { | |
831 TypeInfo[] elements; | |
832 | |
833 char[] toString() | |
834 { | |
835 char[] s; | |
836 s = "("; | |
837 foreach (i, element; elements) | |
838 { | |
839 if (i) | |
840 s ~= ','; | |
841 s ~= element.toString(); | |
842 } | |
843 s ~= ")"; | |
844 return s; | |
845 } | |
846 | |
847 int opEquals(Object o) | |
848 { | |
849 if (this is o) | |
850 return 1; | |
851 | |
852 auto t = cast(TypeInfo_Tuple)o; | |
853 if (t && elements.length == t.elements.length) | |
854 { | |
855 for (size_t i = 0; i < elements.length; i++) | |
856 { | |
857 if (elements[i] != t.elements[i]) | |
858 return 0; | |
859 } | |
860 return 1; | |
861 } | |
862 return 0; | |
863 } | |
864 | |
865 hash_t getHash(void *p) | |
866 { | |
867 assert(0); | |
868 } | |
869 | |
870 int equals(void *p1, void *p2) | |
871 { | |
872 assert(0); | |
873 } | |
874 | |
875 int compare(void *p1, void *p2) | |
876 { | |
877 assert(0); | |
878 } | |
879 | |
880 size_t tsize() | |
881 { | |
882 assert(0); | |
883 } | |
884 | |
885 void swap(void *p1, void *p2) | |
886 { | |
887 assert(0); | |
888 } | |
889 } | |
890 | |
891 class Exception : Object | |
892 { | |
893 char[] msg; | |
894 char[] file; | |
895 size_t line; | |
896 Exception next; | |
897 | |
898 this(char[] msg, Exception next = null) | |
899 { | |
900 this.msg = msg; | |
901 this.next = next; | |
902 } | |
903 | |
904 this(char[] msg, char[] file, size_t line, Exception next = null) | |
905 { | |
906 this(msg, next); | |
907 this.file = file; | |
908 this.line = line; | |
909 } | |
910 | |
911 char[] toString() | |
912 { | |
913 return msg; | |
914 } | |
915 } | |
916 | |
917 | |
918 //////////////////////////////////////////////////////////////////////////////// | |
919 // ModuleInfo | |
920 //////////////////////////////////////////////////////////////////////////////// | |
921 | |
922 | |
923 enum | |
924 { | |
925 MIctorstart = 1, // we've started constructing it | |
926 MIctordone = 2, // finished construction | |
927 MIstandalone = 4, // module ctor does not depend on other module | |
928 // ctors being done first | |
929 MIhasictor = 8, // has ictor member | |
930 } | |
931 | |
932 | |
933 class ModuleInfo | |
934 { | |
935 char[] name; | |
936 ModuleInfo[] importedModules; | |
937 ClassInfo[] localClasses; | |
938 uint flags; | |
939 | |
940 void function() ctor; // module static constructor (order dependent) | |
941 void function() dtor; // module static destructor | |
942 void function() unitTest; // module unit tests | |
943 | |
944 void* xgetMembers; // module getMembers() function | |
945 | |
946 void function() ictor; // module static constructor (order independent) | |
947 | |
948 static int opApply( int delegate( inout ModuleInfo ) dg ) | |
949 { | |
950 int ret = 0; | |
951 | |
952 foreach( m; _moduleinfo_array ) | |
953 { | |
954 ret = dg( m ); | |
955 if( ret ) | |
956 break; | |
957 } | |
958 return ret; | |
959 } | |
960 } | |
961 | |
962 | |
963 // Win32: this gets initialized by minit.asm | |
964 // linux: this gets initialized in _moduleCtor() | |
965 extern (C) ModuleInfo[] _moduleinfo_array; | |
966 | |
133
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
967 // llvmdc method |
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
968 extern (C) void** _d_get_moduleinfo_array(); |
132 | 969 |
970 ModuleInfo[] _moduleinfo_dtors; | |
971 uint _moduleinfo_dtors_i; | |
972 | |
973 // Register termination function pointers | |
974 extern (C) int _fatexit(void *); | |
975 | |
976 /** | |
977 * Initialize the modules. | |
978 */ | |
979 | |
980 extern (C) void _moduleCtor() | |
981 { | |
982 debug(PRINTF) printf("_moduleCtor()\n"); | |
133
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
983 |
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
984 ModuleInfo* mrbegin = cast(ModuleInfo*)_d_get_moduleinfo_array(); |
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
985 assert(mrbegin !is null); |
132 | 986 |
133
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
987 int len = 0; |
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
988 ModuleInfo* mr; |
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
989 for (mr = mrbegin; *mr !is null; ++mr) |
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
990 len++; |
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
991 _moduleinfo_array = new ModuleInfo[len]; |
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
992 |
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
993 len = 0; |
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
994 for (mr = mrbegin; *mr !is null; ++mr) |
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
995 { _moduleinfo_array[len] = *mr; |
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
996 len++; |
132 | 997 } |
998 | |
999 version (Win32) | |
1000 { | |
1001 // Ensure module destructors also get called on program termination | |
1002 //_fatexit(&_STD_moduleDtor); | |
1003 } | |
1004 | |
1005 _moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length]; | |
1006 debug(PRINTF) printf("_moduleinfo_dtors = x%x\n", cast(void *)_moduleinfo_dtors); | |
1007 _moduleIndependentCtors(); | |
1008 _moduleCtor2(_moduleinfo_array, 0); | |
133
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
1009 debug(PRINTF) printf("_moduleCtor() DONE\n"); |
132 | 1010 } |
1011 | |
1012 extern (C) void _moduleIndependentCtors() | |
1013 { | |
1014 debug(PRINTF) printf("_moduleIndependentCtors()\n"); | |
1015 foreach (m; _moduleinfo_array) | |
1016 { | |
1017 if (m && m.flags & MIhasictor && m.ictor) | |
1018 { | |
1019 (*m.ictor)(); | |
1020 } | |
1021 } | |
133
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
1022 debug(PRINTF) printf("_moduleIndependentCtors() DONE\n"); |
132 | 1023 } |
1024 | |
1025 void _moduleCtor2(ModuleInfo[] mi, int skip) | |
1026 { | |
1027 debug(PRINTF) printf("_moduleCtor2(): %d modules\n", mi.length); | |
1028 for (uint i = 0; i < mi.length; i++) | |
1029 { | |
1030 ModuleInfo m = mi[i]; | |
1031 | |
1032 debug(PRINTF) printf("\tmodule[%d] = '%p'\n", i, m); | |
1033 if (!m) | |
1034 continue; | |
133
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
1035 debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name.length, m.name.ptr); |
132 | 1036 if (m.flags & MIctordone) |
1037 continue; | |
133
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
1038 debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name.length, m.name.ptr, m); |
132 | 1039 |
1040 if (m.ctor || m.dtor) | |
1041 { | |
1042 if (m.flags & MIctorstart) | |
1043 { if (skip || m.flags & MIstandalone) | |
1044 continue; | |
1045 throw new Exception( "Cyclic dependency in module " ~ m.name ); | |
1046 } | |
1047 | |
1048 m.flags |= MIctorstart; | |
1049 _moduleCtor2(m.importedModules, 0); | |
1050 if (m.ctor) | |
1051 (*m.ctor)(); | |
1052 m.flags &= ~MIctorstart; | |
1053 m.flags |= MIctordone; | |
1054 | |
1055 // Now that construction is done, register the destructor | |
1056 //printf("\tadding module dtor x%x\n", m); | |
1057 assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length); | |
1058 _moduleinfo_dtors[_moduleinfo_dtors_i++] = m; | |
1059 } | |
1060 else | |
1061 { | |
1062 m.flags |= MIctordone; | |
1063 _moduleCtor2(m.importedModules, 1); | |
1064 } | |
1065 } | |
133
44a95ac7368a
[svn r137] Many fixes towards tango.io.Console working, but not quite there yet...
lindquist
parents:
132
diff
changeset
|
1066 debug(PRINTF) printf("_moduleCtor2() DONE\n"); |
132 | 1067 } |
1068 | |
1069 /** | |
1070 * Destruct the modules. | |
1071 */ | |
1072 | |
1073 // Starting the name with "_STD" means under linux a pointer to the | |
1074 // function gets put in the .dtors segment. | |
1075 | |
1076 extern (C) void _moduleDtor() | |
1077 { | |
1078 debug(PRINTF) printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i); | |
1079 | |
1080 for (uint i = _moduleinfo_dtors_i; i-- != 0;) | |
1081 { | |
1082 ModuleInfo m = _moduleinfo_dtors[i]; | |
1083 | |
1084 debug(PRINTF) printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m); | |
1085 if (m.dtor) | |
1086 { | |
1087 (*m.dtor)(); | |
1088 } | |
1089 } | |
1090 debug(PRINTF) printf("_moduleDtor() done\n"); | |
1091 } | |
1092 | |
1093 //////////////////////////////////////////////////////////////////////////////// | |
1094 // Monitor | |
1095 //////////////////////////////////////////////////////////////////////////////// | |
1096 | |
1097 alias Object.Monitor IMonitor; | |
1098 | |
1099 struct Monitor | |
1100 { | |
1101 IMonitor impl; | |
1102 /* stuff */ | |
1103 } | |
1104 | |
1105 Monitor* getMonitor(Object h) | |
1106 { | |
1107 return cast(Monitor*) (cast(void**) h)[1]; | |
1108 } | |
1109 | |
1110 void setMonitor(Object h, Monitor* m) | |
1111 { | |
1112 (cast(void**) h)[1] = m; | |
1113 } | |
1114 | |
1115 extern (C) void _d_monitor_create(Object); | |
1116 extern (C) void _d_monitor_destroy(Object); | |
1117 extern (C) void _d_monitor_lock(Object); | |
1118 extern (C) int _d_monitor_unlock(Object); | |
1119 | |
1120 extern (C) void _d_monitordelete(Object h, bool det) | |
1121 { | |
1122 Monitor* m = getMonitor(h); | |
1123 | |
1124 if (m !is null) | |
1125 { | |
1126 IMonitor i = m.impl; | |
1127 if (i is null) | |
1128 { | |
1129 _d_monitor_destroy(h); | |
1130 setMonitor(h, null); | |
1131 return; | |
1132 } | |
1133 if (det && (cast(void*) i) !is (cast(void*) h)) | |
1134 delete i; | |
1135 setMonitor(h, null); | |
1136 } | |
1137 } | |
1138 | |
1139 extern (C) void _d_monitorenter(Object h) | |
1140 { | |
1141 Monitor* m = getMonitor(h); | |
1142 | |
1143 if (m is null) | |
1144 { | |
1145 _d_monitor_create(h); | |
1146 m = getMonitor(h); | |
1147 } | |
1148 | |
1149 IMonitor i = m.impl; | |
1150 | |
1151 if (i is null) | |
1152 { | |
1153 _d_monitor_lock(h); | |
1154 return; | |
1155 } | |
1156 i.lock(); | |
1157 } | |
1158 | |
1159 extern (C) void _d_monitorexit(Object h) | |
1160 { | |
1161 Monitor* m = getMonitor(h); | |
1162 IMonitor i = m.impl; | |
1163 | |
1164 if (i is null) | |
1165 { | |
1166 _d_monitor_unlock(h); | |
1167 return; | |
1168 } | |
1169 i.unlock(); | |
1170 } |