Mercurial > projects > ddmd
comparison dmd/Library.d @ 178:e3afd1303184
Many small bugs fixed
Made all classes derive from TObject to detect memory leaks (functionality is disabled for now)
Began work on overriding backend memory allocations (to avoid memory leaks)
author | korDen |
---|---|
date | Sun, 17 Oct 2010 07:42:00 +0400 |
parents | e7769d53e750 |
children | 190ba98276b3 |
comparison
equal
deleted
inserted
replaced
177:1475fd394c9e | 178:e3afd1303184 |
---|---|
128 } | 128 } |
129 | 129 |
130 memcpy(name, p, len); | 130 memcpy(name, p, len); |
131 name[len] = 0; | 131 name[len] = 0; |
132 *pp = p + len; | 132 *pp = p + len; |
133 | 133 |
134 return len; | 134 return len; |
135 } | 135 } |
136 | 136 |
137 static ushort parseIdx(ubyte** pp) | 137 static ushort parseIdx(ubyte** pp) |
138 { | 138 { |
146 | 146 |
147 extern (C) int D_NameCompare(const(void*) a, const(void*) b) | 147 extern (C) int D_NameCompare(const(void*) a, const(void*) b) |
148 { | 148 { |
149 ObjSymbol** p1 = cast(ObjSymbol**)a; | 149 ObjSymbol** p1 = cast(ObjSymbol**)a; |
150 ObjSymbol** p2 = cast(ObjSymbol**)b; | 150 ObjSymbol** p2 = cast(ObjSymbol**)b; |
151 | 151 |
152 return cmp((*p1).name, (*p2).name); | 152 return cmp((*p1).name, (*p2).name); |
153 } | 153 } |
154 version (Windows) | 154 version (Windows) |
155 { | 155 { |
156 /******************************************* | 156 /******************************************* |
157 * Write a single entry into dictionary. | 157 * Write a single entry into dictionary. |
158 * Returns: | 158 * Returns: |
159 * 0 failure | 159 * 0 failure |
160 */ | 160 */ |
161 | 161 |
162 extern (C) extern uint _rotl(uint value, int shift); | 162 extern (C) extern uint _rotl(uint value, int shift); |
163 extern (C) extern uint _rotr(uint value, int shift); | 163 extern (C) extern uint _rotr(uint value, int shift); |
164 | 164 |
165 static int EnterDict(ubyte* bucketsP, ushort ndicpages, ubyte* entry, uint entrylen) | 165 static int EnterDict(ubyte* bucketsP, ushort ndicpages, ubyte* entry, uint entrylen) |
166 { | 166 { |
252 } | 252 } |
253 | 253 |
254 return 0; | 254 return 0; |
255 } | 255 } |
256 | 256 |
257 class Library | 257 import dmd.TObject; |
258 | |
259 class Library : TObject | |
258 { | 260 { |
259 File libfile; | 261 File libfile; |
260 Array objmodules; // ObjModule[] | 262 Array objmodules; // ObjModule[] |
261 Array objsymbols; // ObjSymbol[] | 263 Array objsymbols; // ObjSymbol[] |
262 | 264 |
263 StringTable tab; | 265 StringTable tab; |
264 | 266 |
265 this() | 267 this() |
266 { | 268 { |
269 register(); | |
267 libfile = null; | 270 libfile = null; |
268 | 271 |
269 objmodules = new Array(); | 272 objmodules = new Array(); |
270 objsymbols = new Array(); | 273 objsymbols = new Array(); |
271 tab = new StringTable(); | |
272 } | 274 } |
273 | 275 |
274 /*********************************** | 276 /*********************************** |
275 * Set the library file name based on the output directory | 277 * Set the library file name based on the output directory |
276 * and the filename. | 278 * and the filename. |
278 */ | 280 */ |
279 void setFilename(string dir, string filename) | 281 void setFilename(string dir, string filename) |
280 { | 282 { |
281 string arg = filename; | 283 string arg = filename; |
282 if (arg.length == 0) | 284 if (arg.length == 0) |
283 { | 285 { |
284 // Generate lib file name from first obj name | 286 // Generate lib file name from first obj name |
285 string n = (cast(String)global.params.objfiles.data[0]).str; | 287 string n = (cast(String)global.params.objfiles.data[0]).str; |
286 | 288 |
287 n = FileName.name(n); | 289 n = FileName.name(n); |
288 FileName fn = FileName.forceExt(n, global.lib_ext); | 290 FileName fn = FileName.forceExt(n, global.lib_ext); |
350 { | 352 { |
351 error("COFF libraries not supported"); | 353 error("COFF libraries not supported"); |
352 return; | 354 return; |
353 } | 355 } |
354 else | 356 else |
355 { | 357 { |
356 // Not a library, assume OMF object module | 358 // Not a library, assume OMF object module |
357 g_page_size = 16; | 359 g_page_size = 16; |
358 } | 360 } |
359 | 361 |
360 /* Split up the buffer buf[0..buflen] into multiple object modules, | 362 /* Split up the buffer buf[0..buflen] into multiple object modules, |
381 switch (recTyp) | 383 switch (recTyp) |
382 { | 384 { |
383 case LHEADR : | 385 case LHEADR : |
384 case THEADR : | 386 case THEADR : |
385 if (!om) | 387 if (!om) |
386 { | 388 { |
387 char name[LIBIDMAX + 1]; | 389 char name[LIBIDMAX + 1]; |
388 om = new ObjModule(); | 390 om = new ObjModule(); |
389 om.flags = 0; | 391 om.flags = 0; |
390 om.base = p; | 392 om.base = p; |
391 p += 3; | 393 p += 3; |
392 parseName(&p, name.ptr); | 394 parseName(&p, name.ptr); |
393 if (first_module && module_name && !islibrary) | 395 if (first_module && module_name && !islibrary) |
394 { | 396 { |
395 // Remove path and extension | 397 // Remove path and extension |
396 string fname = FileName.name(module_name); | 398 string fname = FileName.name(module_name); |
397 string ext = FileName.ext(fname); | 399 string ext = FileName.ext(fname); |
398 if (ext.length != 0) { | 400 if (ext.length != 0) { |
399 fname = fname[0..$-ext.length-1]; | 401 fname = fname[0..$-ext.length-1]; |
400 } | 402 } |
401 | 403 |
402 om.name = fname; | 404 om.name = fname; |
403 } | 405 } |
404 else | 406 else |
405 { | 407 { |
406 /* Use THEADR name as module name, | 408 /* Use THEADR name as module name, |
407 * removing path and extension. | 409 * removing path and extension. |
408 */ | 410 */ |
409 string fname = FileName.name(fromStringz(name.ptr)); | 411 string fname = FileName.name(fromStringz(name.ptr)); |
410 string ext = FileName.ext(fname); | 412 string ext = FileName.ext(fname); |
411 if (ext.length != 0) { | 413 if (ext.length != 0) { |
412 fname = fname[0..$-ext.length-1]; | 414 fname = fname[0..$-ext.length-1]; |
413 } | 415 } |
414 | 416 |
415 om.name = fname; | 417 om.name = fname; |
416 om.flags |= MFtheadr; | 418 om.flags |= MFtheadr; |
417 } | 419 } |
418 if (strcmp(name.ptr, "C".ptr) == 0) // old C compilers did this | 420 if (strcmp(name.ptr, "C".ptr) == 0) // old C compilers did this |
419 { | 421 { |
420 om.flags |= MFgentheadr; // generate our own THEADR | 422 om.flags |= MFgentheadr; // generate our own THEADR |
421 om.base = pnext; // skip past THEADR | 423 om.base = pnext; // skip past THEADR |
422 } | 424 } |
423 objmodules.push(cast(void*)om); | 425 objmodules.push(cast(void*)om); |
424 first_module = 0; | 426 first_module = 0; |
426 break; | 428 break; |
427 | 429 |
428 case MODEND : | 430 case MODEND : |
429 case M386END: | 431 case M386END: |
430 if (om) | 432 if (om) |
431 { | 433 { |
432 om.page = cast(ushort)((om.base - pstart) / g_page_size); | 434 om.page = cast(ushort)((om.base - pstart) / g_page_size); |
433 om.length = pnext - om.base; | 435 om.length = pnext - om.base; |
434 om = null; | 436 om = null; |
435 } | 437 } |
436 // Round up to next page | 438 // Round up to next page |
437 uint t = pnext - pstart; | 439 uint t = pnext - pstart; |
438 t = (t + g_page_size - 1) & ~cast(uint)(g_page_size - 1); | 440 t = (t + g_page_size - 1) & ~cast(uint)(g_page_size - 1); |
439 pnext = pstart + t; | 441 pnext = pstart + t; |
440 break; | 442 break; |
441 | 443 |
442 default: | 444 default: |
443 // ignore | 445 // ignore |
444 ; | 446 ; |
445 } | 447 } |
446 } | 448 } |
447 | 449 |
448 if (om) | 450 if (om) |
476 void addSymbol(ObjModule* om, string name, int pickAny = 0) | 478 void addSymbol(ObjModule* om, string name, int pickAny = 0) |
477 { | 479 { |
478 version (LOG) { | 480 version (LOG) { |
479 printf("Library.addSymbol(%s, %s, %d)\n", om.name, name, pickAny); | 481 printf("Library.addSymbol(%s, %s, %d)\n", om.name, name, pickAny); |
480 } | 482 } |
481 StringValue* s = tab.insert(name); | 483 Object* s = tab.insert(name); |
482 if (!s) | 484 if (!s) |
483 { | 485 { |
484 // already in table | 486 // already in table |
485 if (!pickAny) | 487 if (!pickAny) |
486 { | 488 { |
487 s = tab.lookup(name); | 489 s = tab.lookup(name); |
488 assert(s); | 490 assert(s); |
489 ObjSymbol* os = cast(ObjSymbol*)s.ptrvalue; | 491 ObjSymbol* os = *cast(ObjSymbol**)s; |
490 error("multiple definition of %s: %s and %s: %s", | 492 error("multiple definition of %s: %s and %s: %s", |
491 om.name, name, os.om.name, os.name); | 493 om.name, name, os.om.name, os.name); |
492 } | 494 } |
493 } | 495 } |
494 else | 496 else |
495 { | 497 { |
496 ObjSymbol* os = new ObjSymbol(); | 498 ObjSymbol* os = new ObjSymbol(); |
497 os.name = name; | 499 os.name = name; |
498 os.om = om; | 500 os.om = om; |
499 s.ptrvalue = cast(void*)os; | 501 *s = cast(Object)cast(void*)os; /// !!!! |
500 | 502 |
501 objsymbols.push(os); | 503 objsymbols.push(os); |
502 } | 504 } |
503 } | 505 } |
504 | 506 |
505 void scanObjModule(ObjModule* om) | 507 void scanObjModule(ObjModule* om) |
506 { | 508 { |
507 int easyomf; | 509 int easyomf; |
508 uint u; | 510 uint u; |
509 ubyte result = 0; | 511 ubyte result = 0; |
603 result = 1; | 605 result = 1; |
604 goto Ret; | 606 goto Ret; |
605 | 607 |
606 case COMENT: | 608 case COMENT: |
607 // Recognize Phar Lap EASY-OMF format | 609 // Recognize Phar Lap EASY-OMF format |
608 { | 610 { |
609 enum ubyte[7] omfstr = [0x80,0xAA,'8','0','3','8','6']; | 611 enum ubyte[7] omfstr = [0x80,0xAA,'8','0','3','8','6']; |
610 | 612 |
611 if (recLen == omfstr.sizeof) | 613 if (recLen == omfstr.sizeof) |
612 { | 614 { |
613 for (uint i = 0; i < omfstr.sizeof; i++) | 615 for (uint i = 0; i < omfstr.sizeof; i++) |
617 break; | 619 break; |
618 L1: ; | 620 L1: ; |
619 } | 621 } |
620 } | 622 } |
621 // Recognize .IMPDEF Import Definition Records | 623 // Recognize .IMPDEF Import Definition Records |
622 { | 624 { |
623 enum ubyte[3] omfstr = [0, 0xA0, 1]; | 625 enum ubyte[3] omfstr = [0, 0xA0, 1]; |
624 | 626 |
625 if (recLen >= 7) | 627 if (recLen >= 7) |
626 { | 628 { |
627 p++; | 629 p++; |
636 } | 638 } |
637 } | 639 } |
638 break; | 640 break; |
639 | 641 |
640 default: | 642 default: |
641 // ignore | 643 // ignore |
642 ; | 644 ; |
643 } | 645 } |
644 } | 646 } |
645 | 647 |
646 Ret: | 648 Ret: |
647 ; | 649 ; |
648 ///for (u = 1; u < names.dim; u++) | 650 ///for (u = 1; u < names.dim; u++) |
649 /// free(names.data[u]); | 651 /// free(names.data[u]); |
650 } | 652 } |
651 | 653 |
652 /*********************************** | 654 /*********************************** |
653 * Calculates number of pages needed for dictionary | 655 * Calculates number of pages needed for dictionary |
654 * Returns: | 656 * Returns: |
655 * number of pages | 657 * number of pages |
656 */ | 658 */ |
660 ushort bucksForHash; | 662 ushort bucksForHash; |
661 ushort bucksForSize; | 663 ushort bucksForSize; |
662 uint symSize = 0; | 664 uint symSize = 0; |
663 | 665 |
664 for (int i = 0; i < objsymbols.dim; i++) | 666 for (int i = 0; i < objsymbols.dim; i++) |
665 { | 667 { |
666 ObjSymbol* s = cast(ObjSymbol*)objsymbols.data[i]; | 668 ObjSymbol* s = cast(ObjSymbol*)objsymbols.data[i]; |
667 symSize += ( s.name.length + 4 ) & ~1; | 669 symSize += ( s.name.length + 4 ) & ~1; |
668 } | 670 } |
669 | 671 |
670 for (int i = 0; i < objmodules.dim; i++) | 672 for (int i = 0; i < objmodules.dim; i++) |
671 { | 673 { |
672 ObjModule* om = cast(ObjModule*)objmodules.data[i]; | 674 ObjModule* om = cast(ObjModule*)objmodules.data[i]; |
673 | 675 |
674 size_t len = om.name.length; | 676 size_t len = om.name.length; |
675 if (len > 0xFF) | 677 if (len > 0xFF) |
676 len += 2; // Digital Mars long name extension | 678 len += 2; // Digital Mars long name extension |
699 ]; | 701 ]; |
700 | 702 |
701 for (int i = 0; 1; i++) | 703 for (int i = 0; 1; i++) |
702 { | 704 { |
703 if ( primes[i] == 0 ) | 705 if ( primes[i] == 0 ) |
704 { | 706 { |
705 // Quick and easy way is out. | 707 // Quick and easy way is out. |
706 // Now try and find first prime number > ndicpages | 708 // Now try and find first prime number > ndicpages |
707 uint prime; | 709 uint prime; |
708 | 710 |
709 for (prime = (ndicpages + 1) | 1; 1; prime += 2) | 711 for (prime = (ndicpages + 1) | 1; 1; prime += 2) |
728 } | 730 } |
729 } | 731 } |
730 | 732 |
731 return ndicpages; | 733 return ndicpages; |
732 } | 734 } |
733 | 735 |
734 /******************************************* | 736 /******************************************* |
735 * Write the module and symbol names to the dictionary. | 737 * Write the module and symbol names to the dictionary. |
736 * Returns: | 738 * Returns: |
737 * 0 failure | 739 * 0 failure |
738 */ | 740 */ |
742 | 744 |
743 //printf("FillDict()\n"); | 745 //printf("FillDict()\n"); |
744 | 746 |
745 // Add each of the module names | 747 // Add each of the module names |
746 for (int i = 0; i < objmodules.dim; i++) | 748 for (int i = 0; i < objmodules.dim; i++) |
747 { | 749 { |
748 ObjModule* om = cast(ObjModule*)objmodules.data[i]; | 750 ObjModule* om = cast(ObjModule*)objmodules.data[i]; |
749 | 751 |
750 ushort n = cast(ushort)om.name.length; | 752 ushort n = cast(ushort)om.name.length; |
751 if (n > 255) | 753 if (n > 255) |
752 { | 754 { |
753 entry[0] = 0xFF; | 755 entry[0] = 0xFF; |
754 entry[1] = 0; | 756 entry[1] = 0; |
755 *cast(ushort*)(entry.ptr + 2) = cast(ushort)(n + 1); | 757 *cast(ushort*)(entry.ptr + 2) = cast(ushort)(n + 1); |
756 memcpy(entry.ptr + 4, om.name.ptr, n); | 758 memcpy(entry.ptr + 4, om.name.ptr, n); |
757 n += 3; | 759 n += 3; |
758 } | 760 } |
759 else | 761 else |
760 { | 762 { |
761 entry[ 0 ] = cast(ubyte)(1 + n); | 763 entry[ 0 ] = cast(ubyte)(1 + n); |
762 memcpy(entry.ptr + 1, om.name.ptr, n ); | 764 memcpy(entry.ptr + 1, om.name.ptr, n ); |
763 } | 765 } |
764 entry[ n + 1 ] = '!'; | 766 entry[ n + 1 ] = '!'; |
765 *(cast(ushort*)( n + 2 + entry.ptr )) = om.page; | 767 *(cast(ushort*)( n + 2 + entry.ptr )) = om.page; |
772 // Sort the symbols | 774 // Sort the symbols |
773 qsort( objsymbols.data, objsymbols.dim, 4, /*(cmpfunc_t)*/&D_NameCompare ); | 775 qsort( objsymbols.data, objsymbols.dim, 4, /*(cmpfunc_t)*/&D_NameCompare ); |
774 | 776 |
775 // Add each of the symbols | 777 // Add each of the symbols |
776 for (int i = 0; i < objsymbols.dim; i++) | 778 for (int i = 0; i < objsymbols.dim; i++) |
777 { | 779 { |
778 ObjSymbol* os = cast(ObjSymbol*)objsymbols.data[i]; | 780 ObjSymbol* os = cast(ObjSymbol*)objsymbols.data[i]; |
779 | 781 |
780 ushort n = cast(ushort)os.name.length; | 782 ushort n = cast(ushort)os.name.length; |
781 if (n > 255) | 783 if (n > 255) |
782 { | 784 { |
783 entry[0] = 0xFF; | 785 entry[0] = 0xFF; |
784 entry[1] = 0; | 786 entry[1] = 0; |
785 *cast(ushort*)(entry.ptr + 2) = n; | 787 *cast(ushort*)(entry.ptr + 2) = n; |
786 memcpy(entry.ptr + 4, os.name.ptr, n); | 788 memcpy(entry.ptr + 4, os.name.ptr, n); |
787 n += 3; | 789 n += 3; |
788 } | 790 } |
789 else | 791 else |
790 { | 792 { |
791 entry[ 0 ] = cast(ubyte)n; | 793 entry[ 0 ] = cast(ubyte)n; |
792 memcpy( entry.ptr + 1, os.name.ptr, n ); | 794 memcpy( entry.ptr + 1, os.name.ptr, n ); |
793 } | 795 } |
794 *(cast(ushort*)( n + 1 + entry.ptr )) = os.om.page; | 796 *(cast(ushort*)( n + 1 + entry.ptr )) = os.om.page; |
795 if ( (n & 1) == 0 ) | 797 if ( (n & 1) == 0 ) |
800 } | 802 } |
801 } | 803 } |
802 | 804 |
803 return 1; | 805 return 1; |
804 } | 806 } |
805 | 807 |
806 /********************************************** | 808 /********************************************** |
807 * Create and write library to libbuf. | 809 * Create and write library to libbuf. |
808 * The library consists of: | 810 * The library consists of: |
809 * library header | 811 * library header |
810 * object modules... | 812 * object modules... |
815 { | 817 { |
816 /* Scan each of the object modules for symbols | 818 /* Scan each of the object modules for symbols |
817 * to go into the dictionary | 819 * to go into the dictionary |
818 */ | 820 */ |
819 for (int i = 0; i < objmodules.dim; i++) | 821 for (int i = 0; i < objmodules.dim; i++) |
820 { | 822 { |
821 ObjModule* om = cast(ObjModule*)objmodules.data[i]; | 823 ObjModule* om = cast(ObjModule*)objmodules.data[i]; |
822 scanObjModule(om); | 824 scanObjModule(om); |
823 } | 825 } |
824 | 826 |
825 uint g_page_size = 16; | 827 uint g_page_size = 16; |
835 printf("g_page_size = %d\n", g_page_size); | 837 printf("g_page_size = %d\n", g_page_size); |
836 } | 838 } |
837 uint offset = g_page_size; | 839 uint offset = g_page_size; |
838 | 840 |
839 for (int i = 0; i < objmodules.dim; i++) | 841 for (int i = 0; i < objmodules.dim; i++) |
840 { | 842 { |
841 ObjModule* om = cast(ObjModule*)objmodules.data[i]; | 843 ObjModule* om = cast(ObjModule*)objmodules.data[i]; |
842 | 844 |
843 uint page = offset / g_page_size; | 845 uint page = offset / g_page_size; |
844 if (page > 0xFFFF) | 846 if (page > 0xFFFF) |
845 { | 847 { |
877 libbuf.fill0(g_page_size); | 879 libbuf.fill0(g_page_size); |
878 | 880 |
879 /* Write each object module into the library | 881 /* Write each object module into the library |
880 */ | 882 */ |
881 for (int i = 0; i < objmodules.dim; i++) | 883 for (int i = 0; i < objmodules.dim; i++) |
882 { | 884 { |
883 ObjModule* om = cast(ObjModule*)objmodules.data[i]; | 885 ObjModule* om = cast(ObjModule*)objmodules.data[i]; |
884 | 886 |
885 uint page = libbuf.offset / g_page_size; | 887 uint page = libbuf.offset / g_page_size; |
886 assert(page <= 0xFFFF); | 888 assert(page <= 0xFFFF); |
887 om.page = cast(ushort)page; | 889 om.page = cast(ushort)page; |
903 // Compute and store record checksum | 905 // Compute and store record checksum |
904 uint n = size + 4; | 906 uint n = size + 4; |
905 ubyte checksum = 0; | 907 ubyte checksum = 0; |
906 ubyte* p = header.ptr; | 908 ubyte* p = header.ptr; |
907 while (n--) | 909 while (n--) |
908 { | 910 { |
909 checksum -= *p; | 911 checksum -= *p; |
910 p++; | 912 p++; |
911 } | 913 } |
912 *p = checksum; | 914 *p = checksum; |
913 | 915 |
956 { | 958 { |
957 // 'next available' slot | 959 // 'next available' slot |
958 bucketsP[u * BUCKETPAGE + HASHMOD] = (HASHMOD + 1) >> 1; | 960 bucketsP[u * BUCKETPAGE + HASHMOD] = (HASHMOD + 1) >> 1; |
959 } | 961 } |
960 | 962 |
961 if (FillDict(bucketsP, ndicpages)) | 963 if (FillDict(bucketsP, ndicpages)) |
962 break; | 964 break; |
963 padding += 16; // try again with more margins | 965 padding += 16; // try again with more margins |
964 } | 966 } |
965 | 967 |
966 // Write dictionary | 968 // Write dictionary |
983 } | 985 } |
984 } | 986 } |
985 } // version (Windows) | 987 } // version (Windows) |
986 else version(TARGET_LINUX) | 988 else version(TARGET_LINUX) |
987 { | 989 { |
988 class Library | 990 |
991 import dmd.TObject; | |
992 | |
993 class Library : TObject | |
989 { | 994 { |
990 void setFilename(string dir, string filename) | 995 void setFilename(string dir, string filename) |
991 { | 996 { |
992 assert(0); | 997 assert(0); |
993 } | 998 } |
994 | 999 |
995 void addObject(string module_name, void *buf, size_t buflen) | 1000 void addObject(string module_name, void *buf, size_t buflen) |
996 { | 1001 { |
997 assert(0); | 1002 assert(0); |
998 } | 1003 } |
999 | 1004 |
1000 void write() | 1005 void write() |
1001 { | 1006 { |
1002 assert(0); | 1007 assert(0); |
1003 } | 1008 } |
1004 | 1009 |
1005 } | 1010 } |
1006 } | 1011 } |