1 // PERMUTE_ARGS: -release -g
2
version(Windows)3 version(Windows) {}
version(X86_64)4 else version(X86_64)
5 {
6 /* uncomment to enable tests! */
7 //version = Run_X86_64_Tests;
8 }
9
10 extern (C) int printf(const char*, ...);
11
tuple(A...)12 template tuple(A...) { alias A tuple; }
13
14 alias byte B;
15 alias short S;
16 alias int I;
17 alias long L;
18 alias float F;
19 alias double D;
20 alias real R;
21
22 // Single Type
23
24 struct b { B a; }
25 struct bb { B a,b; }
26 struct bbb { B a,b,c; }
27 struct bbbb { B a,b,c,d; }
28 struct bbbbb { B a,b,c,d, e; }
29 struct b6 { B a,b,c,d, e,f; }
30 struct b7 { B a,b,c,d, e,f,g; }
31 struct b8 { B a,b,c,d, e,f,g,h; }
32 struct b9 { B a,b,c,d, e,f,g,h, i; }
33 struct b10 { B a,b,c,d, e,f,g,h, i,j; }
34 struct b11 { B a,b,c,d, e,f,g,h, i,j,k; }
35 struct b12 { B a,b,c,d, e,f,g,h, i,j,k,l; }
36 struct b13 { B a,b,c,d, e,f,g,h, i,j,k,l, m; }
37 struct b14 { B a,b,c,d, e,f,g,h, i,j,k,l, m,n; }
38 struct b15 { B a,b,c,d, e,f,g,h, i,j,k,l, m,n,o; }
39 struct b16 { B a,b,c,d, e,f,g,h, i,j,k,l, m,n,o,p; }
40 struct b17 { B a,b,c,d, e,f,g,h, i,j,k,l, m,n,o,p, q; }
41 struct b18 { B a,b,c,d, e,f,g,h, i,j,k,l, m,n,o,p, q,r; }
42 struct b19 { B a,b,c,d, e,f,g,h, i,j,k,l, m,n,o,p, q,r,s; }
43 struct b20 { B a,b,c,d, e,f,g,h, i,j,k,l, m,n,o,p, q,r,s,t;}
44
45 struct s { S a; }
46 struct ss { S a,b; }
47 struct sss { S a,b,c; }
48 struct ssss { S a,b,c,d; }
49 struct sssss { S a,b,c,d, e; }
50 struct s6 { S a,b,c,d, e,f; }
51 struct s7 { S a,b,c,d, e,f,g; }
52 struct s8 { S a,b,c,d, e,f,g,h; }
53 struct s9 { S a,b,c,d, e,f,g,h, i; }
54 struct s10 { S a,b,c,d, e,f,g,h, i,j;}
55
56 struct i { I a; } struct l { L a; }
57 struct ii { I a,b; } struct ll { L a,b; }
58 struct iii { I a,b,c; } struct lll { L a,b,c; }
59 struct iiii { I a,b,c,d; } struct llll { L a,b,c,d; }
60 struct iiiii { I a,b,c,d,e; } struct lllll { L a,b,c,d,e; }
61
62 struct f { F a; } struct d { D a; }
63 struct ff { F a,b; } struct dd { D a,b; }
64 struct fff { F a,b,c; } struct ddd { D a,b,c; }
65 struct ffff { F a,b,c,d; } struct dddd { D a,b,c,d; }
66 struct fffff { F a,b,c,d,e; } struct ddddd { D a,b,c,d,e; }
67
68 // Mixed Size
69
70 struct js { I a; S b; }
71 struct iss { I a; S b,c; }
72 struct si { S a; I b; }
73 struct ssi { S a,b; I c; }
74 struct sis { S a; I b; S c; }
75
76 struct ls { L a; S b; }
77 struct lss { L a; S b,c; }
78 struct sl { S a; L b; }
79 struct ssl { S a,b; L c; }
80 struct sls { S a; L b; S c; }
81
82 struct li { L a; I b; }
83 struct lii { L a; I b,c; }
84 struct il { I a; L b; }
85 struct iil { I a,b; L c; }
86 struct ili { I a; L b; I c; }
87
88 struct df { D a; F b; }
89 struct dff { D a; F b,c; }
90 struct fd { F a; D b; }
91 struct ffd { F a,b; D c; }
92 struct fdf { F a; D b; F c; }
93
94 // Mixed Types
95
96 struct fi { F a; I b; }
97 struct fii { F a; I b,c; }
98 struct jf { I a; F b; }
99 struct iif { I a,b; F c; }
100 struct ifi { I a; F b; I c; }
101
102 struct ffi { F a,b; I c; }
103 struct ffii { F a,b; I c,d; }
104 struct iff { I a; F b,c; }
105 struct iiff { I a,b; F c,d; }
106 struct ifif { I a; F b; I c; F d;}
107
108 struct di { D a; I b; }
109 struct dii { D a; I b,c; }
110 struct id { I a; D b; }
111 struct iid { I a,b; D c; }
112 struct idi { I a; D b; I c; }
113
114 // Real ( long double )
115
116 struct r { R a; }
117 struct rr { R a,b; }
118 struct rb { R a; B b; }
119 struct rf { R a; F b; }
120 struct fr { F a; R b; }
121
122 // Int Registers only
123 alias tuple!( b,bb,bbb,bbbb,bbbbb,
124 b6, b7, b8, b9, b10,
125 b11,b12,b13,b14,b15,
126 b16,b17,b18,b19,b20,
127 s,ss,sss,ssss,sssss,
128 s6, s7, s8, s9, s10,
129 i,ii,iii,iiii,iiiii,
130 l,ll,lll,llll,lllll,
131 //
132 js,iss,si,ssi, sis,
133 ls,lss,sl,ssl, sls,
134 li,lii,il,iil, ili,
135 fi,fii,jf,iif, ifi,
136 ffi,ffii,iff,iiff,ifif, // INT_END
137
138 // SSE registers only
139 f,ff,fff,ffff,fffff,
140 d,dd,ddd,dddd,ddddd,
141 //
142 df,dff,fd,ffd, fdf, // SSE_END
143
144 // Int and SSE
145 di, dii,id, iid, idi, // MIX_END
146 // ---
147 ) ALL_T;
148
149 enum INT_END = 65;
150 enum SSE_END = 80;
151 enum MIX_END = ALL_T.length;
152
153 // x87
154 alias tuple!( r,rr,rb,rf,fr,
155 // ---
156 ) R_T;
157 //"r","rr","rb","rf","fr",
158
159
160 string[] ALL_S=[
161 "b","bb","bbb","bbbb","bbbbb",
162 "b6", "b7", "b8", "b9", "b10",
163 "b11","b12","b13","b14","b15",
164 "b16","b17","b18","b19","b20",
165 "s","ss","sss","ssss","sssss",
166 "s6","s7","s8","s9" , "s10",
167 "i","ii","iii","iiii","iiiii",
168 "l","ll","lll","llll","lllll",
169 // ---
170 "js","iss","si","ssi", "sis",
171 "ls","lss","sl","ssl", "sls",
172 "li","lii","il","iil", "ili",
173 "fi","fii","jf","iif", "ifi",
174 "ffi","ffii","iff","iiff","ifif",
175 // ---
176 "f","ff","fff","ffff","fffff",
177 "d","dd","ddd","dddd","ddddd",
178 "df","dff","fd","ffd", "dfd",
179 // ---
180 "di","dii","id","iid","idi",
181 ];
182
183 /* ***********************************************************************
184 All
185 ************************************************************************/
186 // test1 Struct passing and return
187
188 int[MIX_END] results_1;
189
test1_out(T)190 T test1_out(T)( )
191 {
192 T t;
193 foreach( i, ref e; t.tupleof ) e = i+1;
194 return t;
195 }
test1_inout(T)196 T test1_inout(T)( T t)
197 {
198 foreach( i, ref e; t.tupleof ) e += 10;
199 return t;
200 }
201
test1_call_out(T)202 void test1_call_out(T)( int n )
203 {
204 T t1;
205 foreach( i, ref e; t1.tupleof ) e = i+1;
206 T t2 = test1_out!(T)();
207
208 if( t1 == t2 ) results_1[n] |= 1;
209 }
test1_call_inout(T)210 void test1_call_inout(T)( int n )
211 {
212 T t1;
213 foreach( i, ref e; t1.tupleof ) e = i+1;
214 T t2 = test1_inout!(T)( t1 );
215 foreach( i, ref e; t1.tupleof ) e += 10;
216
217 if( t1 == t2 ) results_1[n] |= 2;
218 }
219
D_test1()220 void D_test1( )
221 {
222 // Run Tests
223 foreach( n, T; ALL_T )
224 {
225 test1_call_out!(T)(n);
226 test1_call_inout!(T)(n);
227 }
228
229 bool pass = true;
230 foreach( i, r; results_1 )
231 {
232 if( ~r & 1 )
233 {
234 pass = false;
235 printf( "Test1 out %s \tFail\n", ALL_S[i].ptr );
236 }
237 if( ~r & 2 )
238 {
239 pass = false;
240 printf( "Test1 inout %s \tFail\n", ALL_S[i].ptr );
241 }
242 }
243 assert( pass );
244
245 results_1[0..5] = 0;
246 foreach( n, T; R_T )
247 {
248 test1_call_out!(T)(n);
249 test1_call_inout!(T)(n);
250 }
251 }
252
253 /************************************************************************/
254 // based on runnable/test23.d : test44()
255 // Return Struct into an Array
256
257 struct S1
258 { int i,j;
259
fooS1260 static S1 foo(int x)
261 { S1 s;
262 s.i = x;
263 return s;
264 } }
265 struct S2
266 { int i,j,k;
267
foo(int x)268 static S2 foo(int x)
269 { S2 s;
270 s.i = x;
271 return s;
272 } }
273 struct S3
274 { float i,j;
275
fooS3276 static S3 foo(int x)
277 { S3 s;
278 s.i = x;
279 return s;
280 } }
281 struct S4
282 { float i,j,k;
283
foo(int x)284 static S4 foo(int x)
285 { S4 s;
286 s.i = x;
287 return s;
288 } }
289 struct S5
290 { float i,j;
291 int k;
292
fooS5293 static S5 foo(float x)
294 { S5 s;
295 s.i = x;
296 return s;
297 } }
298
D_test2()299 void D_test2()
300 {
301 S1[] s1;
302 S2[] s2;
303 S3[] s3;
304 S4[] s4;
305 S5[] s5;
306
307 s1 = s1 ~ S1.foo(6); s1 = s1 ~ S1.foo(1);
308 s2 = s2 ~ S2.foo(6); s2 = s2 ~ S2.foo(1);
309 s3 = s3 ~ S3.foo(6); s3 = s3 ~ S3.foo(1);
310 s4 = s4 ~ S4.foo(6); s4 = s4 ~ S4.foo(1);
311 s5 = s5 ~ S5.foo(6); s5 = s5 ~ S5.foo(1);
312
313 assert( s1.length == 2 );
314 assert( s1[0].i == 6 );
315 assert( s1[1].i == 1 );
316
317 assert( s2.length == 2 );
318 assert( s2[0].i == 6 );
319 assert( s2[1].i == 1 );
320
321 /+ // These Fail on Mainline DMD64 ( Should pass! )
322 assert( s3.length == 2 );
323 assert( s3[0].i == 6 );
324 assert( s3[1].i == 1 );
325
326 assert( s4.length == 2 );
327 assert( s4[0].i == 6 );
328 assert( s4[1].i == 1 );
329 +/
330 assert( s5.length == 2 );
331 assert( s5[0].i == 6 );
332 assert( s5[1].i == 1 );
333
334 }
335
336 /* ***********************************************************************
337 X86_64
338 ************************************************************************/
339
version(Run_X86_64_Tests)340 version(Run_X86_64_Tests)
341 {
342
343
344 struct TEST
345 {
346 immutable int num;
347 immutable string desc;
348 bool[MIX_END] result;
349 }
350
351 /**
352 * 0 = Should Fail
353 * 1 = Should Pass
354 */
355 immutable int[MIX_END] expected =
356 [
357 1,1,1,1,1, // b
358 1,1,1,1,1, // b6
359 1,1,1,1,1, // b11
360 1,0,0,0,0, // b16
361
362 1,1,1,1,1, // s
363 1,1,1,0,0, // s6
364 1,1,1,1,0, // i
365 1,1,0,0,0, // l
366 1,1,1,1,1, // si mix
367 1,1,1,1,0, // sl
368 1,1,1,1,0, // il
369 1,1,1,1,1, // int and float
370 1,1,1,1,1, // int and float
371
372 // SSE regs only
373 1,1,1,1,0, // f
374 1,1,0,0,0, // d
375 1,1,1,1,0, // float and double
376
377 // SSE + INT regs
378 1,1,1,1,0, // int and double
379 ];
380
381
382 /**
383 * Describes value expected in registers
384 *
385 * null means do not test
386 * ( because value is passed on the stack ).
387 */
388
389 immutable long[][] RegValue =
390 [
391 /* 0 b */ [ 0x0000000000000001, ],
392 /* 1 bb */ [ 0x0000000000000201, ],
393 /* 2 bbb */ [ 0x0000000000030201, ],
394 /* 3 bbbb */ [ 0x0000000004030201, ],
395 /* 4 bbbbb */ [ 0x0000000504030201, ],
396 /* 5 b6 */ [ 0x0000060504030201, ],
397 /* 6 b7 */ [ 0x0007060504030201, ],
398 /* 7 b8 */ [ 0x0807060504030201, ],
399 /* 8 b9 */ [ 0x0807060504030201, 0x0000000000000009 ],
400 /* 9 b10 */ [ 0x0807060504030201, 0x0000000000000a09 ],
401 /* 10 b11 */ [ 0x0807060504030201, 0x00000000000b0a09 ],
402 /* 11 b12 */ [ 0x0807060504030201, 0x000000000c0b0a09 ],
403 /* 12 b13 */ [ 0x0807060504030201, 0x0000000d0c0b0a09 ],
404 /* 13 b14 */ [ 0x0807060504030201, 0x00000e0d0c0b0a09 ],
405 /* 14 b15 */ [ 0x0807060504030201, 0x000f0e0d0c0b0a09 ],
406 /* 15 b16 */ [ 0x0807060504030201, 0x100f0e0d0c0b0a09 ],
407 /* 16 b17 */ null,
408 /* 17 b18 */ null,
409 /* 18 b19 */ null,
410 /* 19 b20 */ null,
411 /* 20 s */ [ 0x0000000000000001, ],
412 /* 21 ss */ [ 0x0000000000020001, ],
413 /* 22 sss */ [ 0x0000000300020001, ],
414 /* 23 ssss */ [ 0x0004000300020001, ],
415 /* 24 sssss */ [ 0x0004000300020001, 0x0000000000000005 ],
416 /* 25 s6 */ [ 0x0004000300020001, 0x0000000000060005 ],
417 /* 26 s7 */ [ 0x0004000300020001, 0x0000000700060005 ],
418 /* 27 s8 */ [ 0x0004000300020001, 0x0008000700060005 ],
419 /* 28 s9 */ null,
420 /* 29 s10 */ null,
421 /* 30 i */ [ 0x0000000000000001, ],
422 /* 31 ii */ [ 0x0000000200000001, ],
423 /* 32 iii */ [ 0x0000000200000001, 0x0000000000000003 ],
424 /* 33 iiii */ [ 0x0000000200000001, 0x0000000400000003 ],
425 /* 34 iiiii */ null,
426 /* 35 l */ [ 0x0000000000000001, ],
427 /* 36 ll */ [ 0x0000000000000001, 0x0000000000000002 ],
428 /* 37 lll */ null,
429 /* 38 llll */ null,
430 /* 39 lllll */ null,
431
432 /* 40 js */ [ 0x0000000200000001, ],
433 /* 41 iss */ [ 0x0003000200000001, ],
434 /* 42 si */ [ 0x0000000200000001, ],
435 /* 43 ssi */ [ 0x0000000300020001, ],
436 /* 44 sis */ [ 0x0000000200000001, 0x0000000000000003 ],
437 /* 45 ls */ [ 0x0000000000000001, 0x0000000000000002 ],
438 /* 46 lss */ [ 0x0000000000000001, 0x0000000000030002 ],
439 /* 47 sl */ [ 0x0000000000000001, 0x0000000000000002 ],
440 /* 48 ssl */ [ 0x0000000000020001, 0x0000000000000003 ],
441 /* 49 sls */ null,
442 /* 50 li */ [ 0x0000000000000001, 0x0000000000000002 ],
443 /* 51 lii */ [ 0x0000000000000001, 0x0000000300000002 ],
444 /* 52 il */ [ 0x0000000000000001, 0x0000000000000002 ],
445 /* 53 iil */ [ 0x0000000200000001, 0x0000000000000003 ],
446 /* 54 ili */ null,
447
448 /* 55 fi */ [ 0x000000023f800000, ],
449 /* 56 fii */ [ 0x000000023f800000, 0x0000000000000003 ],
450 /* 57 jf */ [ 0x4000000000000001, ],
451 /* 58 iif */ [ 0x0000000200000001, 0x0000000040400000 ],
452 /* 59 ifi */ [ 0x4000000000000001, 0x0000000000000003 ],
453
454 /* 60 ffi */ [ 0x0000000000000003, 0x400000003f800000 ],
455 /* 61 ffii */ [ 0x0000000400000003, 0x400000003f800000 ],
456 /* 62 iff */ [ 0x4000000000000001, 0x0000000040400000 ],
457 /* 63 iiff */ [ 0x0000000200000001, 0x4080000040400000 ],
458 /* 64 ifif */ [ 0x4000000000000001, 0x4080000000000003 ],
459
460 /* 65 f */ [ 0x000000003f800000, ],
461 /* 66 ff */ [ 0x400000003f800000, ],
462 /* 67 fff */ [ 0x400000003f800000, 0x0000000040400000 ],
463 /* 68 ffff */ [ 0x400000003f800000, 0x4080000040400000 ],
464 /* 69 fffff */ null,
465 /* 70 d */ [ 0x3ff0000000000000, ],
466 /* 71 dd */ [ 0x3ff0000000000000, 0x4000000000000000 ],
467 /* 72 ddd */ null,
468 /* 73 dddd */ null,
469 /* 74 ddddd */ null,
470
471 /* 75 df */ [ 0x3ff0000000000000, 0x0000000040000000 ],
472 /* 76 dff */ [ 0x3ff0000000000000, 0x4040000040000000 ],
473 /* 77 fd */ [ 0x000000003f800000, 0x4000000000000000 ],
474 /* 78 ffd */ [ 0x400000003f800000, 0x4008000000000000 ],
475 /* 79 fdf */ null,
476
477 /* 80 di */ [ 0x3ff0000000000000, 0x0000000000000002 ],
478 /* 81 dii */ [ 0x3ff0000000000000, 0x0000000300000002 ],
479 /* 82 id */ [ 0x4000000000000000, 0x0000000000000001 ],
480 /* 83 iid */ [ 0x4008000000000000, 0x0000000200000001 ],
481 /* 84 idi */ null,
482 ];
483
484 /* Have to do it this way for OSX: Issue 7354 */
485 __gshared long[2] dump;
486
487 /**
488 * Generate Register capture
489 */
490 string gen_reg_capture( int n, string registers )( )
491 {
492 if( RegValue[n] == null ) return "return;";
493
494 string[] REG = mixin(registers); // ["RDI","RSI"];
495
496 // Which type of compare
497 static if(n < INT_END)
498 enum MODE = 1; // Int
499 else static if(n < SSE_END)
500 enum MODE = 2; // Float
501 else enum MODE = 3; // Mix
502
503 /* Begin */
504
505 string code = "asm {\n";
506
507 final switch( MODE )
508 {
509 case 1: code ~= "mov [dump], "~REG[0]~";\n";
510 REG = REG[1..$];
511 break;
512 case 2:
513 case 3: code ~= "movq [dump], XMM0;\n";
514 }
515
516 if( RegValue[n].length == 2 )
517 final switch( MODE )
518 {
519 case 1:
520 case 3: code ~= "mov [dump+8], "~REG[0]~";\n";
521 break;
522 case 2: code ~= "movq [dump+8], XMM1;\n";
523 } else {
524 code ~= "xor R8, R8;\n";
525 code ~= "mov [dump+8], R8;\n";
526 }
527
528 return code ~ "}\n";
529 }
530
531 /**
532 * Check the results
533 */
534 bool check( TEST data )
535 {
536 bool pass = true;
537 foreach( i, e; expected )
538 {
539 if( data.result[i] != (e & 1) )
540 {
541 printf( "Test%d %s \tFail\n", data.num, ALL_S[i].ptr);
542 pass = false;
543 }
544 }
545 return pass;
546 }
547
548 /************************************************************************/
549
550 // test1 Return Struct in Registers
551 // ( if RDI == 12 we have no hidden pointer )
552
553 TEST data1 = { 1, "RDI hidden pointer" };
554
555 T test1_asm( T, int n )( int i )
556 {
557 asm {
558
559 cmp EDI, 12;
560 je L1;
561
562 leave; ret;
563 }
564 L1:
565 data1.result[n] = true;
566 }
567
568 void test1()
569 {
570 printf("\nRunning iasm Test 1 ( %s )\n", data1.desc.ptr);
571
572 foreach( int n, T; ALL_T )
573 test1_asm!(T,n)(12);
574
575 check( data1 );
576 }
577
578 /************************************************************************/
579 // test2 Pass Struct in Registers
580 // ( if RDI == 0 we have no stack pointer )
581
582 TEST data2 = { 2, "RDI struct pointer" };
583
584 T test2_asm( T, int n )( T t )
585 {
586 asm {
587
588 mov [dump], RDI;
589 mov [dump+8], RSP;
590 cmp EDI, 0; // TODO test RDI is a ptr to stack ? ?
591 je L1;
592
593 leave; ret;
594 }
595 L1:
596 data2.result[n] = true;
597 }
598 T test2f_asm( T, int n )( T t, int x )
599 {
600 asm {
601
602 cmp EDI, 12;
603 je L1;
604
605 leave; ret;
606 }
607 L1:
608 data2.result[n] = true;
609 }
610
611 void test2()
612 {
613 printf("\nRunning iasm Test 2 ( %s )\n", data2.desc.ptr);
614
615 // Integer
616 foreach( int n, T; ALL_T ) {
617 T t = { 0 };
618 test2_asm!(T,n)( t );
619 }
620
621 // float alternative test
622 foreach( int n, T; ALL_T[INT_END..SSE_END] )
623 {
624 enum n2 = n + INT_END;
625 data2.result[n2] = false;
626 test2f_asm!(T,n2)( T.init, 12 );
627 }
628
629 check( data2 );
630 }
631
632 /************************************************************************/
633 // test3
634
635 TEST data3 = { 3, "Check Return Register value" };
636
637 void test3_run( T, int n )( )
638 {
639 test3_ret!T();
640 mixin( gen_reg_capture!(n,`["RAX","RDX"]`)() );
641
642 //dbg!(T,n)( );
643
644 enum len = RegValue[n].length;
645 if( dump[0..len] == RegValue[n] )
646 data3.result[n] = true;
647 }
648
649 T test3_ret( T )( )
650 {
651 T t;
652 foreach( i, ref e; t.tupleof ) e = i+1;
653 return t;
654 }
655
656 void test3()
657 {
658 printf("\nRunning iasm Test 3 ( %s )\n", data3.desc.ptr);
659
660 foreach( int n, T; ALL_T )
661 test3_run!(T,n)( );
662
663 check( data3 );
664 }
665
666 /************************************************************************/
667 // test4
668
669 TEST data4 = { 4, "Check Input Register value" };
670
671 void test4_run( T, int n )( T t )
672 {
673 mixin( gen_reg_capture!(n,`["RDI","RSI"]`)() );
674
675 //dbg!(T,n)( );
676
677 enum len = RegValue[n].length;
678 if( dump[0..len] == RegValue[n] )
679 data4.result[n] = true;
680 }
681
682 void dbg( T, int n )( )
683 {
684 import std.stdio;
685 writefln( "D %s\t[ %16x, %16x ]", T.stringof, dump[0], dump[1], );
686 writef( "C %s\t[ %16x", T.stringof, RegValue[n][0] );
687 if( RegValue[n].length == 2 )
688 writef( ", %16x", RegValue[n][1] );
689 writefln( " ]" );
690 }
691 void test4()
692 {
693 printf("\nRunning iasm Test 4 ( %s )\n", data4.desc.ptr);
694
695 foreach( int n, T; ALL_T )
696 {
697 T t;
698 foreach( i, ref e; t.tupleof ) e = i+1;
699 test4_run!(T,n)( t );
700 }
701 check( data4 );
702 }
703
704
705 } // end version(Run_X86_64_Tests)
706
707 /************************************************************************/
708
709
main()710 void main()
711 {
712 D_test1();
713 D_test2();
714
715 version(Run_X86_64_Tests)
716 {
717 test1();
718 test2();
719 test3();
720 test4();
721 }
722 }
723
724 /+
725 /**
726 * C code to generate the table RegValue
727 */
728 string c_generate_returns()
729 {
730 string value = " 1, 2, 3, 4, 5, 6, 7, 8, 9,10,"
731 "11,12,13,14,15,16,17,18,19,20,";
732
733 string code = "#include \"cgen.h\"\n";
734
735 // Generate return functions
736 foreach( int n, T; ALL_T )
737 {
738 auto Ts = T.stringof;
739 auto len = T.tupleof.length;
740
741 code ~= "struct "~Ts~" func_ret_"~Ts~"(void) { \n";
742 code ~= "struct "~Ts~" x = { ";
743 code ~= value[0..len*3] ~ " };\n";
744 code ~= "return x;\n}\n";
745 }
746 return code;
747 }
748 string c_generate_pass()
749 {
750 string value = " 1, 2, 3, 4, 5, 6, 7, 8, 9,10,"
751 "11,12,13,14,15,16,17,18,19,20,";
752
753 string code;
754
755 // Generate return functions
756 foreach( int n, T; ALL_T )
757 {
758 auto Ts = T.stringof;
759 auto len = T.tupleof.length;
760
761 code ~= "void func_pass_"~Ts~"( struct "~Ts~" x ) {\n";
762 ////////////////
763 // Which type of compare
764 static if(n < INT_END)
765 enum MODE = 1; // Int
766 else static if(n < SSE_END)
767 enum MODE = 2; // Float
768 else enum MODE = 3; // Mix
769
770 auto nn = n.stringof;
771
772 /* Begin */
773
774 code ~= "asm(\n";
775 final switch( MODE )
776 {
777 case 1:
778 code ~= `"movq %rdi, reg\n" "movq %rsi, reg+8\n"`;
779 break;
780 case 2:
781 code ~= `"movq %xmm0, reg\n" "movq %xmm1, reg+8\n"`;
782 break;
783 case 3:
784 code ~= `"movq %xmm0, reg\n" "movq %rdi, reg+8\n"`;
785 }
786 code ~= "\n);\n";
787 code ~= "}\n";
788
789 ////////////////
790 code ~= "void func_call_"~Ts~"( void ) {\n";
791 code ~= "struct "~Ts~" x = { ";
792 code ~= value[0..len*3] ~ " };\n";
793 code ~= "func_pass_"~Ts~"( x );\n}\n";
794 }
795 return code;
796 }
797 string c_generate_main()
798 {
799 string code = "void main() {\n";
800
801 foreach( int n, T; ALL_T )
802 {
803 // Which type of compare
804 static if(n < INT_END)
805 enum MODE = 1; // Int
806 else static if(n < SSE_END)
807 enum MODE = 2; // Float
808 else enum MODE = 3; // Mix
809
810 auto nn = n.stringof;
811 auto Ts = T.stringof;
812
813 /* Begin */
814
815 code ~= `printf("/* %3d `~Ts~`\t*/ ", `~nn~`);`"\n";
816 if( !(expected[n] & 1) )
817 {
818 code ~= `printf("null,\n");`"\n";
819 continue;
820 }
821 code ~= "asm(\n";
822 code ~= `"call func_ret_`~Ts~`\n"`"\n";
823 final switch( MODE )
824 {
825 case 1:
826 code ~= `"movq %rax, reg\n" "movq %rdx, reg+8\n"`;
827 break;
828 case 2:
829 code ~= `"movq %xmm0, reg\n" "movq %xmm1, reg+8\n"`;
830 break;
831 case 3:
832 code ~= `"movq %xmm0, reg\n" "movq %rax, reg+8\n"`;
833 }
834 code ~= "\n);\n";
835
836 code ~= `printf("[ 0x%016lx", reg.r1 );`"\n";
837
838 if( T.sizeof > 8 || MODE == 3 )
839 code ~= `printf(", 0x%016lx ],\n", reg.r2 );`"\n";
840 else code ~= `printf(", %015c ],\n", ' ' );`"\n";
841 }
842
843 foreach( int n, T; ALL_T )
844 {
845 // Which type of compare
846 static if(n < INT_END)
847 enum MODE = 1; // Int
848 else static if(n < SSE_END)
849 enum MODE = 2; // Float
850 else enum MODE = 3; // Mix
851
852 auto nn = n.stringof;
853 auto Ts = T.stringof;
854
855 /* Begin */
856
857 code ~= `printf("/* %3d `~Ts~`\t*/ ", `~nn~`);`"\n";
858 if( !(expected[n] & 1) )
859 {
860 code ~= `printf("null,\n");`"\n";
861 continue;
862 }
863 code ~= "func_call_"~Ts~"();\n";
864
865 code ~= `printf("[ 0x%016lx", reg.r1 );`"\n";
866
867 if( T.sizeof > 8 || MODE == 3 )
868 code ~= `printf(", 0x%016lx ],\n", reg.r2 );`"\n";
869 else code ~= `printf(", %015c ],\n", ' ' );`"\n";
870 }
871
872
873 return code ~ "}";
874 }
875 pragma(msg, c_generate_returns() );
876 pragma(msg, c_generate_pass() );
877 pragma(msg, c_generate_main() );
878 // +/
879
880 /+
881 /**
882 * Generate Functions that pass/return each Struct type
883 *
884 * ( Easier to look at objdump this way )
885 */
886 string d_generate_functions( )
887 {
888 string code = "extern(C) {";
889
890 // pass
891 foreach( s; ALL_T )
892 {
893 string ss = s.stringof;
894
895 code ~= "void func_in_"~ss~"( "~ss~" t ) { t.a = 12; }\n";
896 }
897 // return
898 foreach( s; ALL_T[0..10] )
899 {
900 string ss = s.stringof;
901
902 code ~= `
903 auto func_out_`~ss~`()
904 {
905 `~ss~` t;
906 foreach( i, ref e; t.tupleof ) e = i+1;
907 return t;
908 }`;
909 }
910 // pass & return
911 foreach( s; ALL_T[0..10] )
912 {
913 string ss = s.stringof;
914
915 code ~= `
916 auto func_inout_`~ss~`( `~ss~` t )
917 {
918 foreach( i, ref e; t.tupleof ) e += 10;
919 return t;
920 }`;
921 }
922 return code ~ "\n} // extern(C)\n";
923 }
924 //pragma( msg, d_generate_functions() );
925 mixin( d_generate_functions() );
926 // +/
927