Mercurial > projects > ldc
annotate tango/lib/compiler/llvmdc/adi.d @ 237:a168a2c3ea48 trunk
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
Tried adding a stack trace print when compiler crashes, not sure it's working though.
Changed data layouts to match that of llvm-gcc.
Fixed casting function pointers.
Added support checks in AsmStatement.
author | lindquist |
---|---|
date | Sun, 08 Jun 2008 19:09:24 +0200 |
parents | 8f43f5c43c95 |
children | 0db62b770a49 |
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 | |
70 extern (C) long _adReverseChar(char[] a) | |
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 } | |
130 return *cast(long*)(&a); | |
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 | |
165 extern (C) long _adReverseWchar(wchar[] a) | |
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 } | |
223 return *cast(long*)(&a); | |
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 | |
248 extern (C) long _adReverse(Array a, size_t szelem) | |
249 out (result) | |
250 { | |
251 assert(result is *cast(long*)(&a)); | |
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 } | |
290 return *cast(long*)(&a); | |
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 | |
334 extern (C) long _adSortChar(char[] a) | |
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 } | |
349 return *cast(long*)(&a); | |
350 } | |
351 | |
352 /********************************************** | |
353 * Sort array of wchars. | |
354 */ | |
355 | |
356 extern (C) long _adSortWchar(wchar[] a) | |
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 } | |
371 return *cast(long*)(&a); | |
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); | |
381 if (a1.length != a2.length) | |
382 return 0; // not equal | |
383 auto sz = ti.tsize(); | |
384 auto p1 = a1.ptr; | |
385 auto p2 = a2.ptr; | |
386 | |
387 /+ | |
388 for (int i = 0; i < a1.length; i++) | |
389 { | |
390 printf("%4x %4x\n", (cast(short*)p1)[i], (cast(short*)p2)[i]); | |
391 } | |
392 +/ | |
393 | |
394 if (sz == 1) | |
395 // We should really have a ti.isPOD() check for this | |
396 return (memcmp(p1, p2, a1.length) == 0); | |
397 | |
398 for (size_t i = 0; i < a1.length; i++) | |
399 { | |
400 if (!ti.equals(p1 + i * sz, p2 + i * sz)) | |
401 return 0; // not equal | |
402 } | |
403 return 1; // equal | |
404 } | |
405 | |
406 unittest | |
407 { | |
408 debug(adi) printf("array.Eq unittest\n"); | |
409 | |
410 auto a = "hello"c; | |
411 | |
412 assert(a != "hel"); | |
413 assert(a != "helloo"); | |
414 assert(a != "betty"); | |
415 assert(a == "hello"); | |
416 assert(a != "hxxxx"); | |
417 } | |
418 | |
419 /*************************************** | |
420 * Support for array compare test. | |
421 */ | |
422 | |
423 extern (C) int _adCmp(Array a1, Array a2, TypeInfo ti) | |
424 { | |
425 debug(adi) printf("adCmp()\n"); | |
426 auto len = a1.length; | |
427 if (a2.length < len) | |
428 len = a2.length; | |
429 auto sz = ti.tsize(); | |
430 void *p1 = a1.ptr; | |
431 void *p2 = a2.ptr; | |
432 | |
433 if (sz == 1) | |
434 { // We should really have a ti.isPOD() check for this | |
435 auto c = memcmp(p1, p2, len); | |
436 if (c) | |
437 return c; | |
438 } | |
439 else | |
440 { | |
441 for (size_t i = 0; i < len; i++) | |
442 { | |
443 auto c = ti.compare(p1 + i * sz, p2 + i * sz); | |
444 if (c) | |
445 return c; | |
446 } | |
447 } | |
448 if (a1.length == a2.length) | |
449 return 0; | |
450 return (a1.length > a2.length) ? 1 : -1; | |
451 } | |
452 | |
453 unittest | |
454 { | |
455 debug(adi) printf("array.Cmp unittest\n"); | |
456 | |
457 auto a = "hello"c; | |
458 | |
459 assert(a > "hel"); | |
460 assert(a >= "hel"); | |
461 assert(a < "helloo"); | |
462 assert(a <= "helloo"); | |
463 assert(a > "betty"); | |
464 assert(a >= "betty"); | |
465 assert(a == "hello"); | |
466 assert(a <= "hello"); | |
467 assert(a >= "hello"); | |
468 } | |
469 | |
470 /*************************************** | |
471 * Support for array compare test. | |
472 */ | |
473 | |
474 extern (C) int _adCmpChar(Array a1, Array a2) | |
475 { | |
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
|
476 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
|
477 { |
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
|
478 //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
|
479 } |
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
|
480 version (Asm86) |
132 | 481 { |
482 asm | |
483 { naked ; | |
484 | |
485 push EDI ; | |
486 push ESI ; | |
487 | |
488 mov ESI,a1+4[4+ESP] ; | |
489 mov EDI,a2+4[4+ESP] ; | |
490 | |
491 mov ECX,a1[4+ESP] ; | |
492 mov EDX,a2[4+ESP] ; | |
493 | |
494 cmp ECX,EDX ; | |
495 jb GotLength ; | |
496 | |
497 mov ECX,EDX ; | |
498 | |
499 GotLength: | |
500 cmp ECX,4 ; | |
501 jb DoBytes ; | |
502 | |
503 // Do alignment if neither is dword aligned | |
504 test ESI,3 ; | |
505 jz Aligned ; | |
506 | |
507 test EDI,3 ; | |
508 jz Aligned ; | |
509 DoAlign: | |
510 mov AL,[ESI] ; //align ESI to dword bounds | |
511 mov DL,[EDI] ; | |
512 | |
513 cmp AL,DL ; | |
514 jnz Unequal ; | |
515 | |
516 inc ESI ; | |
517 inc EDI ; | |
518 | |
519 test ESI,3 ; | |
520 | |
521 lea ECX,[ECX-1] ; | |
522 jnz DoAlign ; | |
523 Aligned: | |
524 mov EAX,ECX ; | |
525 | |
526 // do multiple of 4 bytes at a time | |
527 | |
528 shr ECX,2 ; | |
529 jz TryOdd ; | |
530 | |
531 repe ; | |
532 cmpsd ; | |
533 | |
534 jnz UnequalQuad ; | |
535 | |
536 TryOdd: | |
537 mov ECX,EAX ; | |
538 DoBytes: | |
539 // if still equal and not end of string, do up to 3 bytes slightly | |
540 // slower. | |
541 | |
542 and ECX,3 ; | |
543 jz Equal ; | |
544 | |
545 repe ; | |
546 cmpsb ; | |
547 | |
548 jnz Unequal ; | |
549 Equal: | |
550 mov EAX,a1[4+ESP] ; | |
551 mov EDX,a2[4+ESP] ; | |
552 | |
553 sub EAX,EDX ; | |
554 pop ESI ; | |
555 | |
556 pop EDI ; | |
557 ret ; | |
558 | |
559 UnequalQuad: | |
560 mov EDX,[EDI-4] ; | |
561 mov EAX,[ESI-4] ; | |
562 | |
563 cmp AL,DL ; | |
564 jnz Unequal ; | |
565 | |
566 cmp AH,DH ; | |
567 jnz Unequal ; | |
568 | |
569 shr EAX,16 ; | |
570 | |
571 shr EDX,16 ; | |
572 | |
573 cmp AL,DL ; | |
574 jnz Unequal ; | |
575 | |
576 cmp AH,DH ; | |
577 Unequal: | |
578 sbb EAX,EAX ; | |
579 pop ESI ; | |
580 | |
581 or EAX,1 ; | |
582 pop EDI ; | |
583 | |
584 ret ; | |
585 } | |
586 } | |
587 else | |
588 { | |
589 int len; | |
590 int c; | |
591 | |
592 debug(adi) printf("adCmpChar()\n"); | |
593 len = cast(int)a1.length; | |
594 if (a2.length < len) | |
595 len = cast(int)a2.length; | |
596 c = memcmp(cast(char *)a1.ptr, cast(char *)a2.ptr, len); | |
597 if (!c) | |
598 c = cast(int)a1.length - cast(int)a2.length; | |
599 return c; | |
600 } | |
601 } | |
602 | |
603 unittest | |
604 { | |
605 debug(adi) printf("array.CmpChar unittest\n"); | |
606 | |
607 auto a = "hello"c; | |
608 | |
609 assert(a > "hel"); | |
610 assert(a >= "hel"); | |
611 assert(a < "helloo"); | |
612 assert(a <= "helloo"); | |
613 assert(a > "betty"); | |
614 assert(a >= "betty"); | |
615 assert(a == "hello"); | |
616 assert(a <= "hello"); | |
617 assert(a >= "hello"); | |
618 } |