Mercurial > projects > ddmd
annotate dmd/Library.d @ 183:190ba98276b3
Several changes to make it build on posix systems.
I've only tried to build on Mac OS X but it should build on Linux now as well.
This should also fix ticket #9.
author | Jacob Carlborg <doob@me.com> |
---|---|
date | Mon, 25 Oct 2010 15:36:13 +0200 |
parents | e3afd1303184 |
children | eb38fdcb3e62 |
rev | line source |
---|---|
0 | 1 module dmd.Library; |
2 | |
114 | 3 import dmd.common; |
0 | 4 import dmd.File; |
5 import dmd.Array; | |
6 import dmd.StringTable; | |
7 import dmd.OutBuffer; | |
8 import dmd.ObjModule; | |
9 import dmd.String; | |
10 import dmd.Global; | |
11 import dmd.File; | |
12 import dmd.FileName; | |
13 import dmd.Util; | |
14 import dmd.StringValue; | |
15 import dmd.String; | |
16 | |
17 import core.stdc.string; | |
18 import core.stdc.stdlib; | |
19 | |
20 import std.string; | |
21 | |
4 | 22 import core.memory; |
2 | 23 |
0 | 24 align(1) |
25 struct LibHeader | |
26 { | |
27 ubyte recTyp; // 0xF0 | |
28 ushort pagesize; | |
29 int lSymSeek; | |
30 ushort ndicpages; | |
31 ubyte flags; | |
32 } | |
33 | |
34 align(1) | |
35 struct Libheader | |
36 { | |
37 ubyte recTyp; | |
38 ushort recLen; | |
39 int trailerPosn; | |
40 ushort ndicpages; | |
41 ubyte flags; | |
42 char[6] filler; | |
43 } | |
44 | |
45 struct ObjSymbol | |
46 { | |
47 string name; | |
48 ObjModule* om; | |
49 } | |
50 | |
51 /************************** | |
52 * Record types: | |
53 */ | |
54 | |
55 enum HASHMOD = 0x25; | |
56 enum BUCKETPAGE = 512; | |
57 enum BUCKETSIZE = (BUCKETPAGE - HASHMOD - 1); | |
58 | |
59 /+ | |
60 #define RHEADR 0x6E | |
61 #define REGINT 0x70 | |
62 #define REDATA 0x72 | |
63 #define RIDATA 0x74 | |
64 #define OVLDEF 0x76 | |
65 #define ENDREC 0x78 | |
66 #define BLKDEF 0x7A | |
67 #define BLKEND 0x7C | |
68 #define DEBSYM 0x7E | |
69 +/ | |
70 enum THEADR = 0x80; | |
71 enum LHEADR = 0x82; | |
72 /+#define PEDATA 0x84 | |
73 #define PIDATA 0x86 | |
74 +/ | |
75 enum COMENT = 0x88; | |
76 enum MODEND = 0x8A; | |
77 enum M386END = 0x8B; /* 32 bit module end record */ | |
78 /+ | |
79 #define EXTDEF 0x8C | |
80 #define TYPDEF 0x8E | |
81 +/ | |
82 enum PUBDEF = 0x90; | |
83 enum PUB386 = 0x91; | |
84 /+ | |
85 #define LOCSYM 0x92 | |
86 #define LINNUM 0x94 | |
87 +/ | |
88 enum LNAMES = 0x96; | |
89 /+ | |
90 #define SEGDEF 0x98 | |
91 #define GRPDEF 0x9A | |
92 #define FIXUPP 0x9C | |
93 /*#define (none) 0x9E */ | |
94 #define LEDATA 0xA0 | |
95 #define LIDATA 0xA2 | |
96 #define LIBHED 0xA4 | |
97 #define LIBNAM 0xA6 | |
98 #define LIBLOC 0xA8 | |
99 #define LIBDIC 0xAA | |
100 #define COMDEF 0xB0 | |
101 #define LEXTDEF 0xB4 | |
102 #define LPUBDEF 0xB6 | |
103 #define LCOMDEF 0xB8 | |
104 #define CEXTDEF 0xBC | |
105 +/ | |
106 enum COMDAT = 0xC2; | |
107 /+#define LINSYM 0xC4 | |
108 +/ | |
109 enum ALIAS = 0xC6; | |
110 enum LLNAMES = 0xCA; | |
111 | |
112 | |
113 enum LIBIDMAX = (512 - 0x25 - 3 - 4); // max size that will fit in dictionary | |
114 | |
115 extern (C) extern char* strdup(const(char)* ptr); | |
116 | |
117 static uint parseName(ubyte** pp, char* name) | |
118 { | |
119 ubyte* p = *pp; | |
120 uint len = *p++; | |
121 | |
122 if (len == 0xFF && *p == 0) // if long name | |
123 { | |
124 len = p[1] & 0xFF; | |
125 len |= cast(uint)p[2] << 8; | |
126 p += 3; | |
127 assert(len <= LIBIDMAX); | |
128 } | |
129 | |
130 memcpy(name, p, len); | |
131 name[len] = 0; | |
132 *pp = p + len; | |
178 | 133 |
0 | 134 return len; |
135 } | |
136 | |
137 static ushort parseIdx(ubyte** pp) | |
138 { | |
139 ubyte* p = *pp; | |
140 ubyte c = *p++; | |
141 | |
142 ushort idx = cast(ushort)((0x80 & c) ? ((0x7F & c) << 8) + *p++ : c); | |
143 *pp = p; | |
144 return idx; | |
145 } | |
146 | |
147 extern (C) int D_NameCompare(const(void*) a, const(void*) b) | |
148 { | |
149 ObjSymbol** p1 = cast(ObjSymbol**)a; | |
150 ObjSymbol** p2 = cast(ObjSymbol**)b; | |
178 | 151 |
0 | 152 return cmp((*p1).name, (*p2).name); |
153 } | |
14
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
154 version (Windows) |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
155 { |
0 | 156 /******************************************* |
157 * Write a single entry into dictionary. | |
158 * Returns: | |
159 * 0 failure | |
160 */ | |
178 | 161 |
0 | 162 extern (C) extern uint _rotl(uint value, int shift); |
163 extern (C) extern uint _rotr(uint value, int shift); | |
164 | |
165 static int EnterDict(ubyte* bucketsP, ushort ndicpages, ubyte* entry, uint entrylen) | |
166 { | |
167 ushort uStartIndex; | |
168 ushort uStep; | |
169 ushort uStartPage; | |
170 ushort uPageStep; | |
171 ushort uIndex; | |
172 ushort uPage; | |
173 ushort n; | |
174 uint u; | |
175 uint nbytes; | |
176 ubyte* aP; | |
177 ubyte* zP; | |
178 | |
179 aP = entry; | |
180 zP = aP + entrylen; // point at last char in identifier | |
181 | |
182 uStartPage = 0; | |
183 uPageStep = 0; | |
184 uStartIndex = 0; | |
185 uStep = 0; | |
186 | |
187 u = entrylen; | |
188 while ( u-- ) | |
189 { | |
190 uStartPage = cast(ushort)_rotl( uStartPage, 2 ) ^ ( *aP | 0x20 ); | |
191 uStep = cast(ushort)_rotr( uStep, 2 ) ^ ( *aP++ | 0x20 ); | |
192 uStartIndex = cast(ushort)_rotr( uStartIndex, 2 ) ^ ( *zP | 0x20 ); | |
193 uPageStep = cast(ushort)_rotl( uPageStep, 2 ) ^ ( *zP-- | 0x20 ); | |
194 } | |
195 | |
196 uStartPage %= ndicpages; | |
197 uPageStep %= ndicpages; | |
198 if ( uPageStep == 0 ) | |
199 uPageStep++; | |
200 uStartIndex %= HASHMOD; | |
201 uStep %= HASHMOD; | |
202 if ( uStep == 0 ) | |
203 uStep++; | |
204 | |
205 uPage = uStartPage; | |
206 uIndex = uStartIndex; | |
207 | |
208 // number of bytes in entry | |
209 nbytes = 1 + entrylen + 2; | |
210 if (entrylen > 255) | |
211 nbytes += 2; | |
212 | |
213 while (1) | |
214 { | |
215 aP = &bucketsP[uPage * BUCKETPAGE]; | |
216 uStartIndex = uIndex; | |
217 while (1) | |
218 { | |
219 if ( 0 == aP[ uIndex ] ) | |
220 { | |
221 // n = next available position in this page | |
222 n = aP[ HASHMOD ] << 1; | |
223 assert(n > HASHMOD); | |
224 | |
225 // if off end of this page | |
226 if (n + nbytes > BUCKETPAGE ) | |
227 { aP[ HASHMOD ] = 0xFF; | |
228 break; // next page | |
229 } | |
230 else | |
231 { | |
232 aP[ uIndex ] = cast(ubyte)(n >> 1); | |
233 memcpy( (aP + n), entry, nbytes ); | |
234 aP[ HASHMOD ] += (nbytes + 1) >> 1; | |
235 if (aP[HASHMOD] == 0) | |
236 aP[HASHMOD] = 0xFF; | |
237 return 1; | |
238 } | |
239 } | |
240 uIndex += uStep; | |
241 uIndex %= 0x25; | |
242 /*if (uIndex > 0x25) | |
243 uIndex -= 0x25;*/ | |
244 if( uIndex == uStartIndex ) | |
245 break; | |
246 } | |
247 uPage += uPageStep; | |
248 if (uPage >= ndicpages) | |
249 uPage -= ndicpages; | |
250 if( uPage == uStartPage ) | |
251 break; | |
252 } | |
253 | |
254 return 0; | |
255 } | |
256 | |
178 | 257 import dmd.TObject; |
258 | |
259 class Library : TObject | |
0 | 260 { |
261 File libfile; | |
262 Array objmodules; // ObjModule[] | |
263 Array objsymbols; // ObjSymbol[] | |
264 | |
265 StringTable tab; | |
266 | |
267 this() | |
268 { | |
178 | 269 register(); |
0 | 270 libfile = null; |
178 | 271 |
0 | 272 objmodules = new Array(); |
273 objsymbols = new Array(); | |
274 } | |
275 | |
276 /*********************************** | |
277 * Set the library file name based on the output directory | |
278 * and the filename. | |
279 * Add default library file name extension. | |
280 */ | |
281 void setFilename(string dir, string filename) | |
282 { | |
283 string arg = filename; | |
284 if (arg.length == 0) | |
178 | 285 { |
0 | 286 // Generate lib file name from first obj name |
287 string n = (cast(String)global.params.objfiles.data[0]).str; | |
288 | |
289 n = FileName.name(n); | |
290 FileName fn = FileName.forceExt(n, global.lib_ext); | |
291 arg = fn.toChars(); | |
292 } | |
293 if (!FileName.absolute(arg)) | |
294 arg = FileName.combine(dir, arg); | |
295 | |
296 FileName libfilename = FileName.defaultExt(arg, global.lib_ext); | |
297 libfile = new File(libfilename); | |
298 } | |
299 | |
300 /*************************************** | |
301 * Add object module or library to the library. | |
302 * Examine the buffer to see which it is. | |
303 * If the buffer is null, use module_name as the file name | |
304 * and load the file. | |
305 */ | |
306 void addObject(string module_name, void *buf, size_t buflen) | |
307 { | |
308 version (LOG) { | |
309 printf("Library.addObject(%s)\n", module_name ? module_name : ""); | |
310 } | |
311 if (!buf) | |
312 { | |
313 assert(module_name); | |
314 scope FileName f = new FileName(module_name); | |
315 scope File file = new File(f); | |
316 file.readv(); | |
317 buf = file.buffer; | |
318 buflen = file.len; | |
319 file.ref_ = 1; | |
320 } | |
321 | |
322 uint g_page_size; | |
323 ubyte* pstart = cast(ubyte*)buf; | |
324 int islibrary = 0; | |
325 | |
326 /* See if it's an OMF library. | |
327 * Don't go by file extension. | |
328 */ | |
329 | |
330 /* Determine if it is an OMF library, an OMF object module, | |
331 * or something else. | |
332 */ | |
333 if (buflen < LibHeader.sizeof) | |
334 { | |
335 Lcorrupt: | |
336 error("corrupt object module"); | |
337 } | |
338 LibHeader* lh = cast(LibHeader*)buf; | |
339 if (lh.recTyp == 0xF0) | |
340 { /* OMF library | |
341 * The modules are all at buf[g_page_size .. lh.lSymSeek] | |
342 */ | |
343 islibrary = 1; | |
344 g_page_size = lh.pagesize + 3; | |
345 buf = cast(void*)(pstart + g_page_size); | |
346 if (lh.lSymSeek > buflen || | |
347 g_page_size > buflen) | |
348 goto Lcorrupt; | |
349 buflen = lh.lSymSeek - g_page_size; | |
350 } | |
351 else if (lh.recTyp == '!' && memcmp(lh, "!<arch>\n".ptr, 8) == 0) | |
352 { | |
353 error("COFF libraries not supported"); | |
354 return; | |
355 } | |
356 else | |
178 | 357 { |
0 | 358 // Not a library, assume OMF object module |
359 g_page_size = 16; | |
360 } | |
361 | |
362 /* Split up the buffer buf[0..buflen] into multiple object modules, | |
363 * each aligned on a g_page_size boundary. | |
364 */ | |
365 | |
366 ObjModule* om = null; | |
367 int first_module = 1; | |
368 | |
369 ubyte* p = cast(ubyte*)buf; | |
370 ubyte* pend = p + buflen; | |
371 ubyte* pnext; | |
372 for (; p < pend; p = pnext) // for each OMF record | |
373 { | |
374 if (p + 3 >= pend) | |
375 goto Lcorrupt; | |
376 ubyte recTyp = *p; | |
377 ushort recLen = *cast(ushort*)(p + 1); | |
378 pnext = p + 3 + recLen; | |
379 if (pnext > pend) | |
380 goto Lcorrupt; | |
381 recLen--; /* forget the checksum */ | |
382 | |
383 switch (recTyp) | |
384 { | |
385 case LHEADR : | |
386 case THEADR : | |
387 if (!om) | |
178 | 388 { |
0 | 389 char name[LIBIDMAX + 1]; |
390 om = new ObjModule(); | |
391 om.flags = 0; | |
392 om.base = p; | |
393 p += 3; | |
394 parseName(&p, name.ptr); | |
395 if (first_module && module_name && !islibrary) | |
178 | 396 { |
0 | 397 // Remove path and extension |
398 string fname = FileName.name(module_name); | |
399 string ext = FileName.ext(fname); | |
400 if (ext.length != 0) { | |
401 fname = fname[0..$-ext.length-1]; | |
402 } | |
403 | |
404 om.name = fname; | |
405 } | |
406 else | |
178 | 407 { |
0 | 408 /* Use THEADR name as module name, |
409 * removing path and extension. | |
410 */ | |
411 string fname = FileName.name(fromStringz(name.ptr)); | |
412 string ext = FileName.ext(fname); | |
413 if (ext.length != 0) { | |
414 fname = fname[0..$-ext.length-1]; | |
415 } | |
178 | 416 |
0 | 417 om.name = fname; |
418 om.flags |= MFtheadr; | |
419 } | |
420 if (strcmp(name.ptr, "C".ptr) == 0) // old C compilers did this | |
178 | 421 { |
0 | 422 om.flags |= MFgentheadr; // generate our own THEADR |
423 om.base = pnext; // skip past THEADR | |
424 } | |
425 objmodules.push(cast(void*)om); | |
426 first_module = 0; | |
427 } | |
428 break; | |
429 | |
430 case MODEND : | |
431 case M386END: | |
432 if (om) | |
178 | 433 { |
0 | 434 om.page = cast(ushort)((om.base - pstart) / g_page_size); |
435 om.length = pnext - om.base; | |
436 om = null; | |
437 } | |
438 // Round up to next page | |
439 uint t = pnext - pstart; | |
440 t = (t + g_page_size - 1) & ~cast(uint)(g_page_size - 1); | |
441 pnext = pstart + t; | |
442 break; | |
178 | 443 |
0 | 444 default: |
178 | 445 // ignore |
0 | 446 ; |
447 } | |
448 } | |
449 | |
450 if (om) | |
451 goto Lcorrupt; // missing MODEND record | |
452 } | |
453 | |
454 void addLibrary(void *buf, size_t buflen) | |
455 { | |
456 assert(false); | |
457 } | |
458 | |
459 void write() | |
460 { | |
461 if (global.params.verbose) | |
462 writef("library %s\n", libfile.name.toChars()); | |
463 | |
464 scope OutBuffer libbuf = new OutBuffer(); | |
465 WriteLibToBuffer(libbuf); | |
466 | |
467 // Transfer image to file | |
468 libfile.setbuffer(libbuf.data, libbuf.offset); | |
469 libbuf.extractData(); | |
470 | |
471 string p = FileName.path(libfile.name.toChars()); | |
472 FileName.ensurePathExists(p); | |
473 | |
474 libfile.writev(); | |
475 } | |
476 | |
477 private: | |
478 void addSymbol(ObjModule* om, string name, int pickAny = 0) | |
479 { | |
480 version (LOG) { | |
481 printf("Library.addSymbol(%s, %s, %d)\n", om.name, name, pickAny); | |
482 } | |
178 | 483 Object* s = tab.insert(name); |
0 | 484 if (!s) |
178 | 485 { |
0 | 486 // already in table |
487 if (!pickAny) | |
178 | 488 { |
0 | 489 s = tab.lookup(name); |
490 assert(s); | |
178 | 491 ObjSymbol* os = *cast(ObjSymbol**)s; |
0 | 492 error("multiple definition of %s: %s and %s: %s", |
493 om.name, name, os.om.name, os.name); | |
494 } | |
495 } | |
496 else | |
497 { | |
498 ObjSymbol* os = new ObjSymbol(); | |
499 os.name = name; | |
500 os.om = om; | |
178 | 501 *s = cast(Object)cast(void*)os; /// !!!! |
0 | 502 |
503 objsymbols.push(os); | |
504 } | |
505 } | |
178 | 506 |
0 | 507 void scanObjModule(ObjModule* om) |
508 { | |
509 int easyomf; | |
510 uint u; | |
511 ubyte result = 0; | |
512 char name[LIBIDMAX + 1]; | |
513 | |
514 scope Array names = new Array(); | |
515 names.push(null); // don't use index 0 | |
516 | |
517 assert(om); | |
518 easyomf = 0; // assume not EASY-OMF | |
519 ubyte* pend = om.base + om.length; | |
520 | |
521 ubyte* pnext; | |
522 for (ubyte* p = om.base; 1; p = pnext) | |
523 { | |
524 assert(p < pend); | |
525 ubyte recTyp = *p++; | |
526 ushort recLen = *cast(ushort*)p; | |
527 p += 2; | |
528 pnext = p + recLen; | |
529 recLen--; // forget the checksum | |
530 | |
531 switch (recTyp) | |
532 { | |
533 case LNAMES: | |
534 case LLNAMES: | |
535 while (p + 1 < pnext) | |
536 { | |
537 uint len = parseName(&p, name.ptr); | |
538 names.push(cast(void*)new String(name[0..len].idup)); | |
539 } | |
540 break; | |
541 | |
542 case PUBDEF: | |
543 if (easyomf) | |
544 recTyp = PUB386; // convert to MS format | |
545 case PUB386: | |
546 if (!(parseIdx(&p) | parseIdx(&p))) | |
547 p += 2; // skip seg, grp, frame | |
548 while (p + 1 < pnext) | |
549 { | |
550 uint len = parseName(&p, name.ptr); | |
551 p += (recTyp == PUBDEF) ? 2 : 4; // skip offset | |
552 parseIdx(&p); // skip type index | |
553 addSymbol(om, name[0..len].idup); | |
554 } | |
555 break; | |
556 | |
557 case COMDAT: | |
558 if (easyomf) | |
559 recTyp = COMDAT+1; // convert to MS format | |
560 case COMDAT+1: | |
561 int pickAny = 0; | |
562 | |
563 if (*p++ & 5) // if continuation or local comdat | |
564 break; | |
565 | |
566 ubyte attr = *p++; | |
567 if (attr & 0xF0) // attr: if multiple instances allowed | |
568 pickAny = 1; | |
569 p++; // align | |
570 | |
571 p += 2; // enum data offset | |
572 if (recTyp == COMDAT+1) | |
573 p += 2; // enum data offset | |
574 | |
575 parseIdx(&p); // type index | |
576 | |
577 if ((attr & 0x0F) == 0) // if explicit allocation | |
578 { parseIdx(&p); // base group | |
579 parseIdx(&p); // base segment | |
580 } | |
581 | |
582 uint idx = parseIdx(&p); // public name index | |
583 if( idx == 0 || idx >= names.dim) | |
584 { | |
585 //debug(printf("[s] name idx=%d, uCntNames=%d\n", idx, uCntNames)); | |
586 error("corrupt COMDAT"); | |
587 return; | |
588 } | |
589 | |
590 //printf("[s] name='%s'\n",name); | |
591 addSymbol(om, (cast(String)names.data[idx]).str, pickAny); | |
592 break; | |
593 | |
594 case ALIAS: | |
595 while (p + 1 < pnext) | |
596 { | |
597 uint len = parseName(&p, name.ptr); | |
598 addSymbol(om, name[0..len].idup); | |
599 parseName(&p, name.ptr); | |
600 } | |
601 break; | |
602 | |
603 case MODEND: | |
604 case M386END: | |
605 result = 1; | |
606 goto Ret; | |
607 | |
608 case COMENT: | |
609 // Recognize Phar Lap EASY-OMF format | |
178 | 610 { |
169 | 611 enum ubyte[7] omfstr = [0x80,0xAA,'8','0','3','8','6']; |
0 | 612 |
613 if (recLen == omfstr.sizeof) | |
614 { | |
615 for (uint i = 0; i < omfstr.sizeof; i++) | |
616 if (*p++ != omfstr[i]) | |
617 goto L1; | |
618 easyomf = 1; | |
619 break; | |
620 L1: ; | |
621 } | |
622 } | |
623 // Recognize .IMPDEF Import Definition Records | |
178 | 624 { |
169 | 625 enum ubyte[3] omfstr = [0, 0xA0, 1]; |
0 | 626 |
627 if (recLen >= 7) | |
628 { | |
629 p++; | |
630 for (uint i = 1; i < omfstr.sizeof; i++) | |
631 if (*p++ != omfstr[i]) | |
632 goto L2; | |
633 p++; // skip OrdFlag field | |
634 uint len = parseName(&p, name.ptr); | |
635 addSymbol(om, name[0..len].idup); | |
636 break; | |
637 L2: ; | |
638 } | |
639 } | |
640 break; | |
641 | |
642 default: | |
178 | 643 // ignore |
0 | 644 ; |
645 } | |
646 } | |
647 | |
648 Ret: | |
649 ; | |
650 ///for (u = 1; u < names.dim; u++) | |
651 /// free(names.data[u]); | |
652 } | |
178 | 653 |
0 | 654 /*********************************** |
655 * Calculates number of pages needed for dictionary | |
656 * Returns: | |
657 * number of pages | |
658 */ | |
659 ushort numDictPages(uint padding) | |
660 { | |
661 ushort ndicpages; | |
662 ushort bucksForHash; | |
663 ushort bucksForSize; | |
664 uint symSize = 0; | |
665 | |
666 for (int i = 0; i < objsymbols.dim; i++) | |
178 | 667 { |
0 | 668 ObjSymbol* s = cast(ObjSymbol*)objsymbols.data[i]; |
669 symSize += ( s.name.length + 4 ) & ~1; | |
670 } | |
671 | |
672 for (int i = 0; i < objmodules.dim; i++) | |
178 | 673 { |
0 | 674 ObjModule* om = cast(ObjModule*)objmodules.data[i]; |
675 | |
676 size_t len = om.name.length; | |
677 if (len > 0xFF) | |
678 len += 2; // Digital Mars long name extension | |
679 symSize += ( len + 4 + 1 ) & ~1; | |
680 } | |
681 | |
682 bucksForHash = cast(ushort)((objsymbols.dim + objmodules.dim + HASHMOD - 3) / (HASHMOD - 2)); | |
683 bucksForSize = cast(ushort)((symSize + BUCKETSIZE - padding - padding - 1) / (BUCKETSIZE - padding)); | |
684 | |
685 ndicpages = (bucksForHash > bucksForSize ) ? bucksForHash : bucksForSize; | |
686 //printf("ndicpages = %u\n",ndicpages); | |
687 | |
688 // Find prime number greater than ndicpages | |
169 | 689 enum uint[] primes = |
0 | 690 [ 1,2,3,5,7,11,13,17,19,23,29,31,37,41,43, |
691 47,53,59,61,67,71,73,79,83,89,97,101,103, | |
692 107,109,113,127,131,137,139,149,151,157, | |
693 163,167,173,179,181,191,193,197,199,211, | |
694 223,227,229,233,239,241,251,257,263,269, | |
695 271,277,281,283,293,307,311,313,317,331, | |
696 337,347,349,353,359,367,373,379,383,389, | |
697 397,401,409,419,421,431,433,439,443,449, | |
698 457,461,463,467,479,487,491,499,503,509, | |
699 //521,523,541,547, | |
700 0 | |
701 ]; | |
702 | |
703 for (int i = 0; 1; i++) | |
704 { | |
705 if ( primes[i] == 0 ) | |
178 | 706 { |
0 | 707 // Quick and easy way is out. |
708 // Now try and find first prime number > ndicpages | |
709 uint prime; | |
710 | |
711 for (prime = (ndicpages + 1) | 1; 1; prime += 2) | |
712 { // Determine if prime is prime | |
713 for (uint u = 3; u < prime / 2; u += 2) | |
714 { | |
715 if ((prime / u) * u == prime) | |
716 goto L1; | |
717 } | |
718 break; | |
719 | |
720 L1: ; | |
721 } | |
722 ndicpages = cast(ushort)prime; | |
723 break; | |
724 } | |
725 | |
726 if (primes[i] > ndicpages) | |
727 { | |
728 ndicpages = cast(ushort)primes[i]; | |
729 break; | |
730 } | |
731 } | |
732 | |
733 return ndicpages; | |
734 } | |
178 | 735 |
0 | 736 /******************************************* |
737 * Write the module and symbol names to the dictionary. | |
738 * Returns: | |
739 * 0 failure | |
740 */ | |
741 int FillDict(ubyte* bucketsP, ushort ndicpages) | |
742 { | |
743 ubyte entry[4 + LIBIDMAX + 2 + 1]; | |
744 | |
745 //printf("FillDict()\n"); | |
746 | |
747 // Add each of the module names | |
748 for (int i = 0; i < objmodules.dim; i++) | |
178 | 749 { |
0 | 750 ObjModule* om = cast(ObjModule*)objmodules.data[i]; |
751 | |
752 ushort n = cast(ushort)om.name.length; | |
753 if (n > 255) | |
178 | 754 { |
0 | 755 entry[0] = 0xFF; |
756 entry[1] = 0; | |
757 *cast(ushort*)(entry.ptr + 2) = cast(ushort)(n + 1); | |
758 memcpy(entry.ptr + 4, om.name.ptr, n); | |
759 n += 3; | |
760 } | |
761 else | |
178 | 762 { |
0 | 763 entry[ 0 ] = cast(ubyte)(1 + n); |
764 memcpy(entry.ptr + 1, om.name.ptr, n ); | |
765 } | |
766 entry[ n + 1 ] = '!'; | |
767 *(cast(ushort*)( n + 2 + entry.ptr )) = om.page; | |
768 if ( n & 1 ) | |
769 entry[ n + 2 + 2 ] = 0; | |
770 if ( !EnterDict( bucketsP, ndicpages, entry.ptr, n + 1 ) ) | |
771 return 0; | |
772 } | |
773 | |
774 // Sort the symbols | |
775 qsort( objsymbols.data, objsymbols.dim, 4, /*(cmpfunc_t)*/&D_NameCompare ); | |
776 | |
777 // Add each of the symbols | |
778 for (int i = 0; i < objsymbols.dim; i++) | |
178 | 779 { |
0 | 780 ObjSymbol* os = cast(ObjSymbol*)objsymbols.data[i]; |
781 | |
782 ushort n = cast(ushort)os.name.length; | |
783 if (n > 255) | |
178 | 784 { |
0 | 785 entry[0] = 0xFF; |
786 entry[1] = 0; | |
787 *cast(ushort*)(entry.ptr + 2) = n; | |
788 memcpy(entry.ptr + 4, os.name.ptr, n); | |
789 n += 3; | |
790 } | |
791 else | |
178 | 792 { |
0 | 793 entry[ 0 ] = cast(ubyte)n; |
794 memcpy( entry.ptr + 1, os.name.ptr, n ); | |
795 } | |
796 *(cast(ushort*)( n + 1 + entry.ptr )) = os.om.page; | |
797 if ( (n & 1) == 0 ) | |
798 entry[ n + 3] = 0; | |
799 if ( !EnterDict( bucketsP, ndicpages, entry.ptr, n ) ) | |
800 { | |
801 return 0; | |
802 } | |
803 } | |
804 | |
805 return 1; | |
806 } | |
178 | 807 |
0 | 808 /********************************************** |
809 * Create and write library to libbuf. | |
810 * The library consists of: | |
811 * library header | |
812 * object modules... | |
813 * dictionary header | |
814 * dictionary pages... | |
815 */ | |
816 void WriteLibToBuffer(OutBuffer libbuf) | |
817 { | |
818 /* Scan each of the object modules for symbols | |
819 * to go into the dictionary | |
820 */ | |
821 for (int i = 0; i < objmodules.dim; i++) | |
178 | 822 { |
0 | 823 ObjModule* om = cast(ObjModule*)objmodules.data[i]; |
824 scanObjModule(om); | |
825 } | |
826 | |
827 uint g_page_size = 16; | |
828 | |
829 /* Calculate page size so that the number of pages | |
830 * fits in 16 bits. This is because object modules | |
831 * are indexed by page number, stored as an unsigned short. | |
832 */ | |
833 while (1) | |
834 { | |
835 Lagain: | |
836 version (LOG) { | |
837 printf("g_page_size = %d\n", g_page_size); | |
838 } | |
839 uint offset = g_page_size; | |
840 | |
841 for (int i = 0; i < objmodules.dim; i++) | |
178 | 842 { |
0 | 843 ObjModule* om = cast(ObjModule*)objmodules.data[i]; |
844 | |
845 uint page = offset / g_page_size; | |
846 if (page > 0xFFFF) | |
847 { | |
848 // Page size is too small, double it and try again | |
849 g_page_size *= 2; | |
850 goto Lagain; | |
851 } | |
852 | |
853 // Write out the object module m | |
854 if (om.flags & MFgentheadr) // if generate THEADR record | |
855 { | |
856 size_t size = om.name.length; | |
857 assert(size <= LIBIDMAX); | |
858 | |
859 offset += size + 5; | |
860 //offset += om.length - (size + 5); | |
861 offset += om.length; | |
862 } | |
863 else | |
864 offset += om.length; | |
865 | |
866 // Round the size of the file up to the next page size | |
867 // by filling with 0s | |
868 uint n = (g_page_size - 1) & offset; | |
869 if (n) | |
870 offset += g_page_size - n; | |
871 } | |
872 break; | |
873 } | |
874 | |
875 | |
876 /* Leave one page of 0s at start as a dummy library header. | |
877 * Fill it in later with the real data. | |
878 */ | |
879 libbuf.fill0(g_page_size); | |
880 | |
881 /* Write each object module into the library | |
882 */ | |
883 for (int i = 0; i < objmodules.dim; i++) | |
178 | 884 { |
0 | 885 ObjModule* om = cast(ObjModule*)objmodules.data[i]; |
886 | |
887 uint page = libbuf.offset / g_page_size; | |
888 assert(page <= 0xFFFF); | |
889 om.page = cast(ushort)page; | |
890 | |
891 // Write out the object module om | |
892 if (om.flags & MFgentheadr) // if generate THEADR record | |
893 { | |
894 uint size = om.name.length; | |
895 ubyte header[4 + LIBIDMAX + 1]; | |
896 | |
897 header [0] = THEADR; | |
898 header [1] = cast(ubyte)(2 + size); | |
899 header [2] = 0; | |
900 header [3] = cast(ubyte)size; | |
901 assert(size <= 0xFF - 2); | |
902 | |
903 memcpy(4 + header.ptr, om.name.ptr, size); | |
904 | |
905 // Compute and store record checksum | |
906 uint n = size + 4; | |
907 ubyte checksum = 0; | |
908 ubyte* p = header.ptr; | |
909 while (n--) | |
178 | 910 { |
0 | 911 checksum -= *p; |
912 p++; | |
913 } | |
914 *p = checksum; | |
915 | |
916 libbuf.write(header.ptr, size + 5); | |
917 //libbuf.write(om.base, om.length - (size + 5)); | |
918 libbuf.write(om.base, om.length); | |
919 } | |
920 else | |
921 libbuf.write(om.base, om.length); | |
922 | |
923 // Round the size of the file up to the next page size | |
924 // by filling with 0s | |
925 uint n = (g_page_size - 1) & libbuf.offset; | |
926 if (n) | |
927 libbuf.fill0(g_page_size - n); | |
928 } | |
929 | |
930 // File offset of start of dictionary | |
931 uint offset = libbuf.offset; | |
932 | |
933 // Write dictionary header, then round it to a BUCKETPAGE boundary | |
934 ushort size = (BUCKETPAGE - (cast(short)offset + 3)) & (BUCKETPAGE - 1); | |
935 libbuf.writeByte(0xF1); | |
936 libbuf.writeword(size); | |
937 libbuf.fill0(size); | |
938 | |
939 // Create dictionary | |
940 ubyte* bucketsP = null; | |
941 ushort ndicpages; | |
942 ushort padding = 32; | |
943 for (;;) | |
944 { | |
945 ndicpages = numDictPages(padding); | |
946 | |
947 version (LOG) { | |
948 printf("ndicpages = %d\n", ndicpages); | |
949 } | |
950 // Allocate dictionary | |
951 if (bucketsP) | |
2 | 952 bucketsP = cast(ubyte*)GC.realloc(bucketsP, ndicpages * BUCKETPAGE); |
0 | 953 else |
2 | 954 bucketsP = cast(ubyte*)GC.malloc(ndicpages * BUCKETPAGE); |
0 | 955 assert(bucketsP); |
956 memset(bucketsP, 0, ndicpages * BUCKETPAGE); | |
957 for (uint u = 0; u < ndicpages; u++) | |
958 { | |
959 // 'next available' slot | |
960 bucketsP[u * BUCKETPAGE + HASHMOD] = (HASHMOD + 1) >> 1; | |
961 } | |
962 | |
178 | 963 if (FillDict(bucketsP, ndicpages)) |
0 | 964 break; |
965 padding += 16; // try again with more margins | |
966 } | |
967 | |
968 // Write dictionary | |
969 libbuf.write(bucketsP, ndicpages * BUCKETPAGE); | |
2 | 970 ///if (bucketsP) |
971 /// free(bucketsP); | |
0 | 972 |
973 // Create library header | |
974 Libheader libHeader; | |
975 memset(&libHeader, 0, Libheader.sizeof); | |
976 libHeader.recTyp = 0xF0; | |
977 libHeader.recLen = 0x0D; | |
978 libHeader.trailerPosn = offset + (3 + size); | |
979 libHeader.recLen = cast(ushort)(g_page_size - 3); | |
980 libHeader.ndicpages = ndicpages; | |
981 libHeader.flags = 1; // always case sensitive | |
982 | |
983 // Write library header at start of buffer | |
984 memcpy(libbuf.data, &libHeader, libHeader.sizeof); | |
985 } | |
14
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
986 } |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
987 } // version (Windows) |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
988 else version(TARGET_LINUX) |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
989 { |
178 | 990 |
991 import dmd.TObject; | |
992 | |
993 class Library : TObject | |
14
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
994 { |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
995 void setFilename(string dir, string filename) |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
996 { |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
997 assert(0); |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
998 } |
178 | 999 |
14
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
1000 void addObject(string module_name, void *buf, size_t buflen) |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
1001 { |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
1002 assert(0); |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
1003 } |
178 | 1004 |
14
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
1005 void write() |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
1006 { |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
1007 assert(0); |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
1008 } |
178 | 1009 |
14
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
1010 } |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
1011 } |
183
190ba98276b3
Several changes to make it build on posix systems.
Jacob Carlborg <doob@me.com>
parents:
178
diff
changeset
|
1012 |
190ba98276b3
Several changes to make it build on posix systems.
Jacob Carlborg <doob@me.com>
parents:
178
diff
changeset
|
1013 else version (TARGET_OSX) |
190ba98276b3
Several changes to make it build on posix systems.
Jacob Carlborg <doob@me.com>
parents:
178
diff
changeset
|
1014 { |
190ba98276b3
Several changes to make it build on posix systems.
Jacob Carlborg <doob@me.com>
parents:
178
diff
changeset
|
1015 import dmd.TObject; |
190ba98276b3
Several changes to make it build on posix systems.
Jacob Carlborg <doob@me.com>
parents:
178
diff
changeset
|
1016 |
190ba98276b3
Several changes to make it build on posix systems.
Jacob Carlborg <doob@me.com>
parents:
178
diff
changeset
|
1017 class Library : TObject |
190ba98276b3
Several changes to make it build on posix systems.
Jacob Carlborg <doob@me.com>
parents:
178
diff
changeset
|
1018 { |
190ba98276b3
Several changes to make it build on posix systems.
Jacob Carlborg <doob@me.com>
parents:
178
diff
changeset
|
1019 void setFilename(string dir, string filename) |
190ba98276b3
Several changes to make it build on posix systems.
Jacob Carlborg <doob@me.com>
parents:
178
diff
changeset
|
1020 { |
190ba98276b3
Several changes to make it build on posix systems.
Jacob Carlborg <doob@me.com>
parents:
178
diff
changeset
|
1021 assert(0); |
190ba98276b3
Several changes to make it build on posix systems.
Jacob Carlborg <doob@me.com>
parents:
178
diff
changeset
|
1022 } |
190ba98276b3
Several changes to make it build on posix systems.
Jacob Carlborg <doob@me.com>
parents:
178
diff
changeset
|
1023 |
190ba98276b3
Several changes to make it build on posix systems.
Jacob Carlborg <doob@me.com>
parents:
178
diff
changeset
|
1024 void addObject(string module_name, void *buf, size_t buflen) |
190ba98276b3
Several changes to make it build on posix systems.
Jacob Carlborg <doob@me.com>
parents:
178
diff
changeset
|
1025 { |
190ba98276b3
Several changes to make it build on posix systems.
Jacob Carlborg <doob@me.com>
parents:
178
diff
changeset
|
1026 assert(0); |
190ba98276b3
Several changes to make it build on posix systems.
Jacob Carlborg <doob@me.com>
parents:
178
diff
changeset
|
1027 } |
190ba98276b3
Several changes to make it build on posix systems.
Jacob Carlborg <doob@me.com>
parents:
178
diff
changeset
|
1028 |
190ba98276b3
Several changes to make it build on posix systems.
Jacob Carlborg <doob@me.com>
parents:
178
diff
changeset
|
1029 void write() |
190ba98276b3
Several changes to make it build on posix systems.
Jacob Carlborg <doob@me.com>
parents:
178
diff
changeset
|
1030 { |
190ba98276b3
Several changes to make it build on posix systems.
Jacob Carlborg <doob@me.com>
parents:
178
diff
changeset
|
1031 assert(0); |
190ba98276b3
Several changes to make it build on posix systems.
Jacob Carlborg <doob@me.com>
parents:
178
diff
changeset
|
1032 } |
190ba98276b3
Several changes to make it build on posix systems.
Jacob Carlborg <doob@me.com>
parents:
178
diff
changeset
|
1033 } |
190ba98276b3
Several changes to make it build on posix systems.
Jacob Carlborg <doob@me.com>
parents:
178
diff
changeset
|
1034 } |