Mercurial > projects > ldc
annotate tango/lib/compiler/llvmdc/adi.d @ 323:0d52412d5b1a trunk
[svn r344] Fixed some very minor issues with the usage listing when calling llvmdc with no arguments.
Changed the way moduleinfo is registered to use the same approach as DMD, this eliminates the need for correct linking order and should make the way for using a natively compiled runtime library. This should speed up linking tremendously and should now be possible.
Fixed the llvm.used array to only be emitted if really necessary.
author | lindquist |
---|---|
date | Wed, 09 Jul 2008 23:43:51 +0200 |
parents | 068cb3c60afb |
children | eb110c4730c0 |
rev | line source |
---|---|
132 | 1 //_ adi.d |
2 | |
3 /** | |
4 * Part of the D programming language runtime library. | |
5 * Dynamic array property support routines | |
6 */ | |
7 | |
8 /* | |
9 * Copyright (C) 2000-2006 by Digital Mars, www.digitalmars.com | |
10 * Written by Walter Bright | |
11 * | |
12 * This software is provided 'as-is', without any express or implied | |
13 * warranty. In no event will the authors be held liable for any damages | |
14 * arising from the use of this software. | |
15 * | |
16 * Permission is granted to anyone to use this software for any purpose, | |
17 * including commercial applications, and to alter it and redistribute it | |
18 * freely, in both source and binary form, subject to the following | |
19 * restrictions: | |
20 * | |
21 * o The origin of this software must not be misrepresented; you must not | |
22 * claim that you wrote the original software. If you use this software | |
23 * in a product, an acknowledgment in the product documentation would be | |
24 * appreciated but is not required. | |
25 * o Altered source versions must be plainly marked as such, and must not | |
26 * be misrepresented as being the original software. | |
27 * o This notice may not be removed or altered from any source | |
28 * distribution. | |
29 */ | |
30 | |
31 /* | |
32 * Modified by Sean Kelly <sean@f4.ca> for use with Tango. | |
33 */ | |
34 | |
35 | |
36 //debug=adi; // uncomment to turn on debugging printf's | |
37 | |
38 private | |
39 { | |
40 import tango.stdc.string; | |
41 import tango.stdc.stdlib; | |
42 import util.utf; | |
43 | |
44 enum BlkAttr : uint | |
45 { | |
46 FINALIZE = 0b0000_0001, | |
47 NO_SCAN = 0b0000_0010, | |
48 NO_MOVE = 0b0000_0100, | |
49 ALL_BITS = 0b1111_1111 | |
50 } | |
51 | |
52 extern (C) void* gc_malloc( size_t sz, uint ba = 0 ); | |
53 extern (C) void* gc_calloc( size_t sz, uint ba = 0 ); | |
54 extern (C) void gc_free( void* p ); | |
55 } | |
56 | |
57 | |
58 struct Array | |
59 { | |
60 size_t length; | |
61 void* ptr; | |
62 } | |
63 | |
64 /********************************************** | |
65 * Reverse array of chars. | |
66 * Handled separately because embedded multibyte encodings should not be | |
67 * reversed. | |
68 */ | |
69 | |
240
0db62b770a49
[svn r257] Fixed: array .sort and .reverse runtime code was incorrect.
lindquist
parents:
237
diff
changeset
|
70 extern (C) Array _adReverseChar(char[] a) |
132 | 71 { |
72 if (a.length > 1) | |
73 { | |
74 char[6] tmp; | |
75 char[6] tmplo; | |
76 char* lo = a.ptr; | |
77 char* hi = &a[length - 1]; | |
78 | |
79 while (lo < hi) | |
80 { auto clo = *lo; | |
81 auto chi = *hi; | |
82 | |
83 debug(adi) printf("lo = %d, hi = %d\n", lo, hi); | |
84 if (clo <= 0x7F && chi <= 0x7F) | |
85 { | |
86 debug(adi) printf("\tascii\n"); | |
87 *lo = chi; | |
88 *hi = clo; | |
89 lo++; | |
90 hi--; | |
91 continue; | |
92 } | |
93 | |
94 uint stridelo = UTF8stride[clo]; | |
95 | |
96 uint stridehi = 1; | |
97 while ((chi & 0xC0) == 0x80) | |
98 { | |
99 chi = *--hi; | |
100 stridehi++; | |
101 assert(hi >= lo); | |
102 } | |
103 if (lo == hi) | |
104 break; | |
105 | |
106 debug(adi) printf("\tstridelo = %d, stridehi = %d\n", stridelo, stridehi); | |
107 if (stridelo == stridehi) | |
108 { | |
109 | |
110 memcpy(tmp.ptr, lo, stridelo); | |
111 memcpy(lo, hi, stridelo); | |
112 memcpy(hi, tmp.ptr, stridelo); | |
113 lo += stridelo; | |
114 hi--; | |
115 continue; | |
116 } | |
117 | |
118 /* Shift the whole array. This is woefully inefficient | |
119 */ | |
120 memcpy(tmp.ptr, hi, stridehi); | |
121 memcpy(tmplo.ptr, lo, stridelo); | |
122 memmove(lo + stridehi, lo + stridelo , cast(size_t)(hi - lo) - stridelo); | |
123 memcpy(lo, tmp.ptr, stridehi); | |
124 memcpy(hi + stridehi - stridelo, tmplo.ptr, stridelo); | |
125 | |
126 lo += stridehi; | |
127 hi = hi - 1 + (stridehi - stridelo); | |
128 } | |
129 } | |
240
0db62b770a49
[svn r257] Fixed: array .sort and .reverse runtime code was incorrect.
lindquist
parents:
237
diff
changeset
|
130 return Array(a.length, a.ptr); |
132 | 131 } |
132 | |
133 unittest | |
134 { | |
135 auto a = "abcd"c; | |
136 | |
137 auto r = a.dup.reverse; | |
138 //writefln(r); | |
139 assert(r == "dcba"); | |
140 | |
141 a = "a\u1235\u1234c"; | |
142 //writefln(a); | |
143 r = a.dup.reverse; | |
144 //writefln(r); | |
145 assert(r == "c\u1234\u1235a"); | |
146 | |
147 a = "ab\u1234c"; | |
148 //writefln(a); | |
149 r = a.dup.reverse; | |
150 //writefln(r); | |
151 assert(r == "c\u1234ba"); | |
152 | |
153 a = "\u3026\u2021\u3061\n"; | |
154 r = a.dup.reverse; | |
155 assert(r == "\n\u3061\u2021\u3026"); | |
156 } | |
157 | |
158 | |
159 /********************************************** | |
160 * Reverse array of wchars. | |
161 * Handled separately because embedded multiword encodings should not be | |
162 * reversed. | |
163 */ | |
164 | |
240
0db62b770a49
[svn r257] Fixed: array .sort and .reverse runtime code was incorrect.
lindquist
parents:
237
diff
changeset
|
165 extern (C) Array _adReverseWchar(wchar[] a) |
132 | 166 { |
167 if (a.length > 1) | |
168 { | |
169 wchar[2] tmp; | |
170 wchar* lo = a.ptr; | |
171 wchar* hi = &a[length - 1]; | |
172 | |
173 while (lo < hi) | |
174 { auto clo = *lo; | |
175 auto chi = *hi; | |
176 | |
177 if ((clo < 0xD800 || clo > 0xDFFF) && | |
178 (chi < 0xD800 || chi > 0xDFFF)) | |
179 { | |
180 *lo = chi; | |
181 *hi = clo; | |
182 lo++; | |
183 hi--; | |
184 continue; | |
185 } | |
186 | |
187 int stridelo = 1 + (clo >= 0xD800 && clo <= 0xDBFF); | |
188 | |
189 int stridehi = 1; | |
190 if (chi >= 0xDC00 && chi <= 0xDFFF) | |
191 { | |
192 chi = *--hi; | |
193 stridehi++; | |
194 assert(hi >= lo); | |
195 } | |
196 if (lo == hi) | |
197 break; | |
198 | |
199 if (stridelo == stridehi) | |
200 { int stmp; | |
201 | |
202 assert(stridelo == 2); | |
203 assert(stmp.sizeof == 2 * (*lo).sizeof); | |
204 stmp = *cast(int*)lo; | |
205 *cast(int*)lo = *cast(int*)hi; | |
206 *cast(int*)hi = stmp; | |
207 lo += stridelo; | |
208 hi--; | |
209 continue; | |
210 } | |
211 | |
212 /* Shift the whole array. This is woefully inefficient | |
213 */ | |
214 memcpy(tmp.ptr, hi, stridehi * wchar.sizeof); | |
215 memcpy(hi + stridehi - stridelo, lo, stridelo * wchar.sizeof); | |
216 memmove(lo + stridehi, lo + stridelo , (hi - (lo + stridelo)) * wchar.sizeof); | |
217 memcpy(lo, tmp.ptr, stridehi * wchar.sizeof); | |
218 | |
219 lo += stridehi; | |
220 hi = hi - 1 + (stridehi - stridelo); | |
221 } | |
222 } | |
240
0db62b770a49
[svn r257] Fixed: array .sort and .reverse runtime code was incorrect.
lindquist
parents:
237
diff
changeset
|
223 return Array(a.length, a.ptr); |
132 | 224 } |
225 | |
226 unittest | |
227 { | |
228 wstring a = "abcd"; | |
229 wstring r; | |
230 | |
231 r = a.dup.reverse; | |
232 assert(r == "dcba"); | |
233 | |
234 a = "a\U00012356\U00012346c"; | |
235 r = a.dup.reverse; | |
236 assert(r == "c\U00012346\U00012356a"); | |
237 | |
238 a = "ab\U00012345c"; | |
239 r = a.dup.reverse; | |
240 assert(r == "c\U00012345ba"); | |
241 } | |
242 | |
243 | |
244 /********************************************** | |
245 * Support for array.reverse property. | |
246 */ | |
247 | |
240
0db62b770a49
[svn r257] Fixed: array .sort and .reverse runtime code was incorrect.
lindquist
parents:
237
diff
changeset
|
248 extern (C) Array _adReverse(Array a, size_t szelem) |
132 | 249 out (result) |
250 { | |
240
0db62b770a49
[svn r257] Fixed: array .sort and .reverse runtime code was incorrect.
lindquist
parents:
237
diff
changeset
|
251 assert(result.ptr is a.ptr); |
132 | 252 } |
253 body | |
254 { | |
255 if (a.length >= 2) | |
256 { | |
257 byte* tmp; | |
258 byte[16] buffer; | |
259 | |
260 void* lo = a.ptr; | |
261 void* hi = a.ptr + (a.length - 1) * szelem; | |
262 | |
263 tmp = buffer.ptr; | |
264 if (szelem > 16) | |
265 { | |
266 //version (Win32) | |
267 tmp = cast(byte*) alloca(szelem); | |
268 //else | |
269 //tmp = gc_malloc(szelem); | |
270 } | |
271 | |
272 for (; lo < hi; lo += szelem, hi -= szelem) | |
273 { | |
274 memcpy(tmp, lo, szelem); | |
275 memcpy(lo, hi, szelem); | |
276 memcpy(hi, tmp, szelem); | |
277 } | |
278 | |
279 version (Win32) | |
280 { | |
281 } | |
282 else | |
283 { | |
284 //if (szelem > 16) | |
285 // BUG: bad code is generate for delete pointer, tries | |
286 // to call delclass. | |
287 //gc_free(tmp); | |
288 } | |
289 } | |
240
0db62b770a49
[svn r257] Fixed: array .sort and .reverse runtime code was incorrect.
lindquist
parents:
237
diff
changeset
|
290 return Array(a.length, a.ptr); |
132 | 291 } |
292 | |
293 unittest | |
294 { | |
295 debug(adi) printf("array.reverse.unittest\n"); | |
296 | |
297 int[] a = new int[5]; | |
298 int[] b; | |
299 size_t i; | |
300 | |
301 for (i = 0; i < 5; i++) | |
302 a[i] = i; | |
303 b = a.reverse; | |
304 assert(b is a); | |
305 for (i = 0; i < 5; i++) | |
306 assert(a[i] == 4 - i); | |
307 | |
308 struct X20 | |
309 { // More than 16 bytes in size | |
310 int a; | |
311 int b, c, d, e; | |
312 } | |
313 | |
314 X20[] c = new X20[5]; | |
315 X20[] d; | |
316 | |
317 for (i = 0; i < 5; i++) | |
318 { c[i].a = i; | |
319 c[i].e = 10; | |
320 } | |
321 d = c.reverse; | |
322 assert(d is c); | |
323 for (i = 0; i < 5; i++) | |
324 { | |
325 assert(c[i].a == 4 - i); | |
326 assert(c[i].e == 10); | |
327 } | |
328 } | |
329 | |
330 /********************************************** | |
331 * Sort array of chars. | |
332 */ | |
333 | |
240
0db62b770a49
[svn r257] Fixed: array .sort and .reverse runtime code was incorrect.
lindquist
parents:
237
diff
changeset
|
334 extern (C) Array _adSortChar(char[] a) |
132 | 335 { |
336 if (a.length > 1) | |
337 { | |
338 dchar[] da = toUTF32(a); | |
339 da.sort; | |
340 size_t i = 0; | |
341 foreach (dchar d; da) | |
342 { char[4] buf; | |
343 auto t = toUTF8(buf, d); | |
344 a[i .. i + t.length] = t[]; | |
345 i += t.length; | |
346 } | |
347 delete da; | |
348 } | |
240
0db62b770a49
[svn r257] Fixed: array .sort and .reverse runtime code was incorrect.
lindquist
parents:
237
diff
changeset
|
349 return Array(a.length, a.ptr); |
132 | 350 } |
351 | |
352 /********************************************** | |
353 * Sort array of wchars. | |
354 */ | |
355 | |
240
0db62b770a49
[svn r257] Fixed: array .sort and .reverse runtime code was incorrect.
lindquist
parents:
237
diff
changeset
|
356 extern (C) Array _adSortWchar(wchar[] a) |
132 | 357 { |
358 if (a.length > 1) | |
359 { | |
360 dchar[] da = toUTF32(a); | |
361 da.sort; | |
362 size_t i = 0; | |
363 foreach (dchar d; da) | |
364 { wchar[2] buf; | |
365 auto t = toUTF16(buf, d); | |
366 a[i .. i + t.length] = t[]; | |
367 i += t.length; | |
368 } | |
369 delete da; | |
370 } | |
240
0db62b770a49
[svn r257] Fixed: array .sort and .reverse runtime code was incorrect.
lindquist
parents:
237
diff
changeset
|
371 return Array(a.length, a.ptr); |
132 | 372 } |
373 | |
374 /*************************************** | |
375 * Support for array equality test. | |
376 */ | |
377 | |
378 extern (C) int _adEq(Array a1, Array a2, TypeInfo ti) | |
379 { | |
380 debug(adi) printf("_adEq(a1.length = %d, a2.length = %d)\n", a1.length, a2.length); | |
291
068cb3c60afb
[svn r312] Changed assert codegen to insert an unreachable terminator after the call to the assert function, which currently calls abort().
lindquist
parents:
240
diff
changeset
|
381 |
132 | 382 if (a1.length != a2.length) |
383 return 0; // not equal | |
291
068cb3c60afb
[svn r312] Changed assert codegen to insert an unreachable terminator after the call to the assert function, which currently calls abort().
lindquist
parents:
240
diff
changeset
|
384 else if (a1.ptr == a2.ptr) |
068cb3c60afb
[svn r312] Changed assert codegen to insert an unreachable terminator after the call to the assert function, which currently calls abort().
lindquist
parents:
240
diff
changeset
|
385 return 1; // equal |
132 | 386 |
291
068cb3c60afb
[svn r312] Changed assert codegen to insert an unreachable terminator after the call to the assert function, which currently calls abort().
lindquist
parents:
240
diff
changeset
|
387 // let typeinfo decide |
068cb3c60afb
[svn r312] Changed assert codegen to insert an unreachable terminator after the call to the assert function, which currently calls abort().
lindquist
parents:
240
diff
changeset
|
388 return ti.equals(&a1, &a2); |
132 | 389 } |
390 | |
391 unittest | |
392 { | |
393 debug(adi) printf("array.Eq unittest\n"); | |
394 | |
395 auto a = "hello"c; | |
396 | |
397 assert(a != "hel"); | |
398 assert(a != "helloo"); | |
399 assert(a != "betty"); | |
400 assert(a == "hello"); | |
401 assert(a != "hxxxx"); | |
402 } | |
403 | |
404 /*************************************** | |
405 * Support for array compare test. | |
406 */ | |
407 | |
408 extern (C) int _adCmp(Array a1, Array a2, TypeInfo ti) | |
409 { | |
410 debug(adi) printf("adCmp()\n"); | |
291
068cb3c60afb
[svn r312] Changed assert codegen to insert an unreachable terminator after the call to the assert function, which currently calls abort().
lindquist
parents:
240
diff
changeset
|
411 |
068cb3c60afb
[svn r312] Changed assert codegen to insert an unreachable terminator after the call to the assert function, which currently calls abort().
lindquist
parents:
240
diff
changeset
|
412 if (a1.ptr == a2.ptr && |
068cb3c60afb
[svn r312] Changed assert codegen to insert an unreachable terminator after the call to the assert function, which currently calls abort().
lindquist
parents:
240
diff
changeset
|
413 a1.length == a2.length) |
068cb3c60afb
[svn r312] Changed assert codegen to insert an unreachable terminator after the call to the assert function, which currently calls abort().
lindquist
parents:
240
diff
changeset
|
414 return 0; |
068cb3c60afb
[svn r312] Changed assert codegen to insert an unreachable terminator after the call to the assert function, which currently calls abort().
lindquist
parents:
240
diff
changeset
|
415 |
132 | 416 auto len = a1.length; |
417 if (a2.length < len) | |
418 len = a2.length; | |
419 | |
291
068cb3c60afb
[svn r312] Changed assert codegen to insert an unreachable terminator after the call to the assert function, which currently calls abort().
lindquist
parents:
240
diff
changeset
|
420 // let typeinfo decide |
068cb3c60afb
[svn r312] Changed assert codegen to insert an unreachable terminator after the call to the assert function, which currently calls abort().
lindquist
parents:
240
diff
changeset
|
421 return ti.compare(&a1, &a2); |
132 | 422 } |
423 | |
424 unittest | |
425 { | |
426 debug(adi) printf("array.Cmp unittest\n"); | |
427 | |
428 auto a = "hello"c; | |
429 | |
430 assert(a > "hel"); | |
431 assert(a >= "hel"); | |
432 assert(a < "helloo"); | |
433 assert(a <= "helloo"); | |
434 assert(a > "betty"); | |
435 assert(a >= "betty"); | |
436 assert(a == "hello"); | |
437 assert(a <= "hello"); | |
438 assert(a >= "hello"); | |
439 } | |
440 | |
441 /*************************************** | |
442 * Support for array compare test. | |
443 */ | |
444 | |
445 extern (C) int _adCmpChar(Array a1, Array a2) | |
446 { | |
237
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
141
diff
changeset
|
447 version(D_InlineAsm_X86) |
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
141
diff
changeset
|
448 { |
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
141
diff
changeset
|
449 //version = Asm86; |
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
141
diff
changeset
|
450 } |
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
141
diff
changeset
|
451 version (Asm86) |
132 | 452 { |
453 asm | |
454 { naked ; | |
455 | |
456 push EDI ; | |
457 push ESI ; | |
458 | |
459 mov ESI,a1+4[4+ESP] ; | |
460 mov EDI,a2+4[4+ESP] ; | |
461 | |
462 mov ECX,a1[4+ESP] ; | |
463 mov EDX,a2[4+ESP] ; | |
464 | |
465 cmp ECX,EDX ; | |
466 jb GotLength ; | |
467 | |
468 mov ECX,EDX ; | |
469 | |
470 GotLength: | |
471 cmp ECX,4 ; | |
472 jb DoBytes ; | |
473 | |
474 // Do alignment if neither is dword aligned | |
475 test ESI,3 ; | |
476 jz Aligned ; | |
477 | |
478 test EDI,3 ; | |
479 jz Aligned ; | |
480 DoAlign: | |
481 mov AL,[ESI] ; //align ESI to dword bounds | |
482 mov DL,[EDI] ; | |
483 | |
484 cmp AL,DL ; | |
485 jnz Unequal ; | |
486 | |
487 inc ESI ; | |
488 inc EDI ; | |
489 | |
490 test ESI,3 ; | |
491 | |
492 lea ECX,[ECX-1] ; | |
493 jnz DoAlign ; | |
494 Aligned: | |
495 mov EAX,ECX ; | |
496 | |
497 // do multiple of 4 bytes at a time | |
498 | |
499 shr ECX,2 ; | |
500 jz TryOdd ; | |
501 | |
502 repe ; | |
503 cmpsd ; | |
504 | |
505 jnz UnequalQuad ; | |
506 | |
507 TryOdd: | |
508 mov ECX,EAX ; | |
509 DoBytes: | |
510 // if still equal and not end of string, do up to 3 bytes slightly | |
511 // slower. | |
512 | |
513 and ECX,3 ; | |
514 jz Equal ; | |
515 | |
516 repe ; | |
517 cmpsb ; | |
518 | |
519 jnz Unequal ; | |
520 Equal: | |
521 mov EAX,a1[4+ESP] ; | |
522 mov EDX,a2[4+ESP] ; | |
523 | |
524 sub EAX,EDX ; | |
525 pop ESI ; | |
526 | |
527 pop EDI ; | |
528 ret ; | |
529 | |
530 UnequalQuad: | |
531 mov EDX,[EDI-4] ; | |
532 mov EAX,[ESI-4] ; | |
533 | |
534 cmp AL,DL ; | |
535 jnz Unequal ; | |
536 | |
537 cmp AH,DH ; | |
538 jnz Unequal ; | |
539 | |
540 shr EAX,16 ; | |
541 | |
542 shr EDX,16 ; | |
543 | |
544 cmp AL,DL ; | |
545 jnz Unequal ; | |
546 | |
547 cmp AH,DH ; | |
548 Unequal: | |
549 sbb EAX,EAX ; | |
550 pop ESI ; | |
551 | |
552 or EAX,1 ; | |
553 pop EDI ; | |
554 | |
555 ret ; | |
556 } | |
557 } | |
558 else | |
559 { | |
560 int len; | |
561 int c; | |
562 | |
563 debug(adi) printf("adCmpChar()\n"); | |
564 len = cast(int)a1.length; | |
565 if (a2.length < len) | |
566 len = cast(int)a2.length; | |
567 c = memcmp(cast(char *)a1.ptr, cast(char *)a2.ptr, len); | |
568 if (!c) | |
569 c = cast(int)a1.length - cast(int)a2.length; | |
570 return c; | |
571 } | |
572 } | |
573 | |
574 unittest | |
575 { | |
576 debug(adi) printf("array.CmpChar unittest\n"); | |
577 | |
578 auto a = "hello"c; | |
579 | |
580 assert(a > "hel"); | |
581 assert(a >= "hel"); | |
582 assert(a < "helloo"); | |
583 assert(a <= "helloo"); | |
584 assert(a > "betty"); | |
585 assert(a >= "betty"); | |
586 assert(a == "hello"); | |
587 assert(a <= "hello"); | |
588 assert(a >= "hello"); | |
589 } |