blob: c50dfbd0ba6062449712611912cc587fe006a5a9 [file] [log] [blame]
// PERMUTE_ARGS: -release -g
version(Windows) {}
else version(X86_64)
{
/* uncomment to enable tests! */
//version = Run_X86_64_Tests;
}
extern (C) int printf(const char*, ...);
template tuple(A...) { alias A tuple; }
alias byte B;
alias short S;
alias int I;
alias long L;
alias float F;
alias double D;
alias real R;
// Single Type
struct b { B a; }
struct bb { B a,b; }
struct bbb { B a,b,c; }
struct bbbb { B a,b,c,d; }
struct bbbbb { B a,b,c,d, e; }
struct b6 { B a,b,c,d, e,f; }
struct b7 { B a,b,c,d, e,f,g; }
struct b8 { B a,b,c,d, e,f,g,h; }
struct b9 { B a,b,c,d, e,f,g,h, i; }
struct b10 { B a,b,c,d, e,f,g,h, i,j; }
struct b11 { B a,b,c,d, e,f,g,h, i,j,k; }
struct b12 { B a,b,c,d, e,f,g,h, i,j,k,l; }
struct b13 { B a,b,c,d, e,f,g,h, i,j,k,l, m; }
struct b14 { B a,b,c,d, e,f,g,h, i,j,k,l, m,n; }
struct b15 { B a,b,c,d, e,f,g,h, i,j,k,l, m,n,o; }
struct b16 { B a,b,c,d, e,f,g,h, i,j,k,l, m,n,o,p; }
struct b17 { B a,b,c,d, e,f,g,h, i,j,k,l, m,n,o,p, q; }
struct b18 { B a,b,c,d, e,f,g,h, i,j,k,l, m,n,o,p, q,r; }
struct b19 { B a,b,c,d, e,f,g,h, i,j,k,l, m,n,o,p, q,r,s; }
struct b20 { B a,b,c,d, e,f,g,h, i,j,k,l, m,n,o,p, q,r,s,t;}
struct s { S a; }
struct ss { S a,b; }
struct sss { S a,b,c; }
struct ssss { S a,b,c,d; }
struct sssss { S a,b,c,d, e; }
struct s6 { S a,b,c,d, e,f; }
struct s7 { S a,b,c,d, e,f,g; }
struct s8 { S a,b,c,d, e,f,g,h; }
struct s9 { S a,b,c,d, e,f,g,h, i; }
struct s10 { S a,b,c,d, e,f,g,h, i,j;}
struct i { I a; } struct l { L a; }
struct ii { I a,b; } struct ll { L a,b; }
struct iii { I a,b,c; } struct lll { L a,b,c; }
struct iiii { I a,b,c,d; } struct llll { L a,b,c,d; }
struct iiiii { I a,b,c,d,e; } struct lllll { L a,b,c,d,e; }
struct f { F a; } struct d { D a; }
struct ff { F a,b; } struct dd { D a,b; }
struct fff { F a,b,c; } struct ddd { D a,b,c; }
struct ffff { F a,b,c,d; } struct dddd { D a,b,c,d; }
struct fffff { F a,b,c,d,e; } struct ddddd { D a,b,c,d,e; }
// Mixed Size
struct js { I a; S b; }
struct iss { I a; S b,c; }
struct si { S a; I b; }
struct ssi { S a,b; I c; }
struct sis { S a; I b; S c; }
struct ls { L a; S b; }
struct lss { L a; S b,c; }
struct sl { S a; L b; }
struct ssl { S a,b; L c; }
struct sls { S a; L b; S c; }
struct li { L a; I b; }
struct lii { L a; I b,c; }
struct il { I a; L b; }
struct iil { I a,b; L c; }
struct ili { I a; L b; I c; }
struct df { D a; F b; }
struct dff { D a; F b,c; }
struct fd { F a; D b; }
struct ffd { F a,b; D c; }
struct fdf { F a; D b; F c; }
// Mixed Types
struct fi { F a; I b; }
struct fii { F a; I b,c; }
struct jf { I a; F b; }
struct iif { I a,b; F c; }
struct ifi { I a; F b; I c; }
struct ffi { F a,b; I c; }
struct ffii { F a,b; I c,d; }
struct iff { I a; F b,c; }
struct iiff { I a,b; F c,d; }
struct ifif { I a; F b; I c; F d;}
struct di { D a; I b; }
struct dii { D a; I b,c; }
struct id { I a; D b; }
struct iid { I a,b; D c; }
struct idi { I a; D b; I c; }
// Real ( long double )
struct r { R a; }
struct rr { R a,b; }
struct rb { R a; B b; }
struct rf { R a; F b; }
struct fr { F a; R b; }
// Int Registers only
alias tuple!( b,bb,bbb,bbbb,bbbbb,
b6, b7, b8, b9, b10,
b11,b12,b13,b14,b15,
b16,b17,b18,b19,b20,
s,ss,sss,ssss,sssss,
s6, s7, s8, s9, s10,
i,ii,iii,iiii,iiiii,
l,ll,lll,llll,lllll,
//
js,iss,si,ssi, sis,
ls,lss,sl,ssl, sls,
li,lii,il,iil, ili,
fi,fii,jf,iif, ifi,
ffi,ffii,iff,iiff,ifif, // INT_END
// SSE registers only
f,ff,fff,ffff,fffff,
d,dd,ddd,dddd,ddddd,
//
df,dff,fd,ffd, fdf, // SSE_END
// Int and SSE
di, dii,id, iid, idi, // MIX_END
// ---
) ALL_T;
enum INT_END = 65;
enum SSE_END = 80;
enum MIX_END = ALL_T.length;
// x87
alias tuple!( r,rr,rb,rf,fr,
// ---
) R_T;
//"r","rr","rb","rf","fr",
string[] ALL_S=[
"b","bb","bbb","bbbb","bbbbb",
"b6", "b7", "b8", "b9", "b10",
"b11","b12","b13","b14","b15",
"b16","b17","b18","b19","b20",
"s","ss","sss","ssss","sssss",
"s6","s7","s8","s9" , "s10",
"i","ii","iii","iiii","iiiii",
"l","ll","lll","llll","lllll",
// ---
"js","iss","si","ssi", "sis",
"ls","lss","sl","ssl", "sls",
"li","lii","il","iil", "ili",
"fi","fii","jf","iif", "ifi",
"ffi","ffii","iff","iiff","ifif",
// ---
"f","ff","fff","ffff","fffff",
"d","dd","ddd","dddd","ddddd",
"df","dff","fd","ffd", "dfd",
// ---
"di","dii","id","iid","idi",
];
/* ***********************************************************************
All
************************************************************************/
// test1 Struct passing and return
int[MIX_END] results_1;
T test1_out(T)( )
{
T t;
foreach( i, ref e; t.tupleof ) e = i+1;
return t;
}
T test1_inout(T)( T t)
{
foreach( i, ref e; t.tupleof ) e += 10;
return t;
}
void test1_call_out(T)( int n )
{
T t1;
foreach( i, ref e; t1.tupleof ) e = i+1;
T t2 = test1_out!(T)();
if( t1 == t2 ) results_1[n] |= 1;
}
void test1_call_inout(T)( int n )
{
T t1;
foreach( i, ref e; t1.tupleof ) e = i+1;
T t2 = test1_inout!(T)( t1 );
foreach( i, ref e; t1.tupleof ) e += 10;
if( t1 == t2 ) results_1[n] |= 2;
}
void D_test1( )
{
// Run Tests
foreach( n, T; ALL_T )
{
test1_call_out!(T)(n);
test1_call_inout!(T)(n);
}
bool pass = true;
foreach( i, r; results_1 )
{
if( ~r & 1 )
{
pass = false;
printf( "Test1 out %s \tFail\n", ALL_S[i].ptr );
}
if( ~r & 2 )
{
pass = false;
printf( "Test1 inout %s \tFail\n", ALL_S[i].ptr );
}
}
assert( pass );
results_1[0..5] = 0;
foreach( n, T; R_T )
{
test1_call_out!(T)(n);
test1_call_inout!(T)(n);
}
}
/************************************************************************/
// based on runnable/test23.d : test44()
// Return Struct into an Array
struct S1
{ int i,j;
static S1 foo(int x)
{ S1 s;
s.i = x;
return s;
} }
struct S2
{ int i,j,k;
static S2 foo(int x)
{ S2 s;
s.i = x;
return s;
} }
struct S3
{ float i,j;
static S3 foo(int x)
{ S3 s;
s.i = x;
return s;
} }
struct S4
{ float i,j,k;
static S4 foo(int x)
{ S4 s;
s.i = x;
return s;
} }
struct S5
{ float i,j;
int k;
static S5 foo(float x)
{ S5 s;
s.i = x;
return s;
} }
void D_test2()
{
S1[] s1;
S2[] s2;
S3[] s3;
S4[] s4;
S5[] s5;
s1 = s1 ~ S1.foo(6); s1 = s1 ~ S1.foo(1);
s2 = s2 ~ S2.foo(6); s2 = s2 ~ S2.foo(1);
s3 = s3 ~ S3.foo(6); s3 = s3 ~ S3.foo(1);
s4 = s4 ~ S4.foo(6); s4 = s4 ~ S4.foo(1);
s5 = s5 ~ S5.foo(6); s5 = s5 ~ S5.foo(1);
assert( s1.length == 2 );
assert( s1[0].i == 6 );
assert( s1[1].i == 1 );
assert( s2.length == 2 );
assert( s2[0].i == 6 );
assert( s2[1].i == 1 );
/+ // These Fail on Mainline DMD64 ( Should pass! )
assert( s3.length == 2 );
assert( s3[0].i == 6 );
assert( s3[1].i == 1 );
assert( s4.length == 2 );
assert( s4[0].i == 6 );
assert( s4[1].i == 1 );
+/
assert( s5.length == 2 );
assert( s5[0].i == 6 );
assert( s5[1].i == 1 );
}
/* ***********************************************************************
X86_64
************************************************************************/
version(Run_X86_64_Tests)
{
struct TEST
{
immutable int num;
immutable string desc;
bool[MIX_END] result;
}
/**
* 0 = Should Fail
* 1 = Should Pass
*/
immutable int[MIX_END] expected =
[
1,1,1,1,1, // b
1,1,1,1,1, // b6
1,1,1,1,1, // b11
1,0,0,0,0, // b16
1,1,1,1,1, // s
1,1,1,0,0, // s6
1,1,1,1,0, // i
1,1,0,0,0, // l
1,1,1,1,1, // si mix
1,1,1,1,0, // sl
1,1,1,1,0, // il
1,1,1,1,1, // int and float
1,1,1,1,1, // int and float
// SSE regs only
1,1,1,1,0, // f
1,1,0,0,0, // d
1,1,1,1,0, // float and double
// SSE + INT regs
1,1,1,1,0, // int and double
];
/**
* Describes value expected in registers
*
* null means do not test
* ( because value is passed on the stack ).
*/
immutable long[][] RegValue =
[
/* 0 b */ [ 0x0000000000000001, ],
/* 1 bb */ [ 0x0000000000000201, ],
/* 2 bbb */ [ 0x0000000000030201, ],
/* 3 bbbb */ [ 0x0000000004030201, ],
/* 4 bbbbb */ [ 0x0000000504030201, ],
/* 5 b6 */ [ 0x0000060504030201, ],
/* 6 b7 */ [ 0x0007060504030201, ],
/* 7 b8 */ [ 0x0807060504030201, ],
/* 8 b9 */ [ 0x0807060504030201, 0x0000000000000009 ],
/* 9 b10 */ [ 0x0807060504030201, 0x0000000000000a09 ],
/* 10 b11 */ [ 0x0807060504030201, 0x00000000000b0a09 ],
/* 11 b12 */ [ 0x0807060504030201, 0x000000000c0b0a09 ],
/* 12 b13 */ [ 0x0807060504030201, 0x0000000d0c0b0a09 ],
/* 13 b14 */ [ 0x0807060504030201, 0x00000e0d0c0b0a09 ],
/* 14 b15 */ [ 0x0807060504030201, 0x000f0e0d0c0b0a09 ],
/* 15 b16 */ [ 0x0807060504030201, 0x100f0e0d0c0b0a09 ],
/* 16 b17 */ null,
/* 17 b18 */ null,
/* 18 b19 */ null,
/* 19 b20 */ null,
/* 20 s */ [ 0x0000000000000001, ],
/* 21 ss */ [ 0x0000000000020001, ],
/* 22 sss */ [ 0x0000000300020001, ],
/* 23 ssss */ [ 0x0004000300020001, ],
/* 24 sssss */ [ 0x0004000300020001, 0x0000000000000005 ],
/* 25 s6 */ [ 0x0004000300020001, 0x0000000000060005 ],
/* 26 s7 */ [ 0x0004000300020001, 0x0000000700060005 ],
/* 27 s8 */ [ 0x0004000300020001, 0x0008000700060005 ],
/* 28 s9 */ null,
/* 29 s10 */ null,
/* 30 i */ [ 0x0000000000000001, ],
/* 31 ii */ [ 0x0000000200000001, ],
/* 32 iii */ [ 0x0000000200000001, 0x0000000000000003 ],
/* 33 iiii */ [ 0x0000000200000001, 0x0000000400000003 ],
/* 34 iiiii */ null,
/* 35 l */ [ 0x0000000000000001, ],
/* 36 ll */ [ 0x0000000000000001, 0x0000000000000002 ],
/* 37 lll */ null,
/* 38 llll */ null,
/* 39 lllll */ null,
/* 40 js */ [ 0x0000000200000001, ],
/* 41 iss */ [ 0x0003000200000001, ],
/* 42 si */ [ 0x0000000200000001, ],
/* 43 ssi */ [ 0x0000000300020001, ],
/* 44 sis */ [ 0x0000000200000001, 0x0000000000000003 ],
/* 45 ls */ [ 0x0000000000000001, 0x0000000000000002 ],
/* 46 lss */ [ 0x0000000000000001, 0x0000000000030002 ],
/* 47 sl */ [ 0x0000000000000001, 0x0000000000000002 ],
/* 48 ssl */ [ 0x0000000000020001, 0x0000000000000003 ],
/* 49 sls */ null,
/* 50 li */ [ 0x0000000000000001, 0x0000000000000002 ],
/* 51 lii */ [ 0x0000000000000001, 0x0000000300000002 ],
/* 52 il */ [ 0x0000000000000001, 0x0000000000000002 ],
/* 53 iil */ [ 0x0000000200000001, 0x0000000000000003 ],
/* 54 ili */ null,
/* 55 fi */ [ 0x000000023f800000, ],
/* 56 fii */ [ 0x000000023f800000, 0x0000000000000003 ],
/* 57 jf */ [ 0x4000000000000001, ],
/* 58 iif */ [ 0x0000000200000001, 0x0000000040400000 ],
/* 59 ifi */ [ 0x4000000000000001, 0x0000000000000003 ],
/* 60 ffi */ [ 0x0000000000000003, 0x400000003f800000 ],
/* 61 ffii */ [ 0x0000000400000003, 0x400000003f800000 ],
/* 62 iff */ [ 0x4000000000000001, 0x0000000040400000 ],
/* 63 iiff */ [ 0x0000000200000001, 0x4080000040400000 ],
/* 64 ifif */ [ 0x4000000000000001, 0x4080000000000003 ],
/* 65 f */ [ 0x000000003f800000, ],
/* 66 ff */ [ 0x400000003f800000, ],
/* 67 fff */ [ 0x400000003f800000, 0x0000000040400000 ],
/* 68 ffff */ [ 0x400000003f800000, 0x4080000040400000 ],
/* 69 fffff */ null,
/* 70 d */ [ 0x3ff0000000000000, ],
/* 71 dd */ [ 0x3ff0000000000000, 0x4000000000000000 ],
/* 72 ddd */ null,
/* 73 dddd */ null,
/* 74 ddddd */ null,
/* 75 df */ [ 0x3ff0000000000000, 0x0000000040000000 ],
/* 76 dff */ [ 0x3ff0000000000000, 0x4040000040000000 ],
/* 77 fd */ [ 0x000000003f800000, 0x4000000000000000 ],
/* 78 ffd */ [ 0x400000003f800000, 0x4008000000000000 ],
/* 79 fdf */ null,
/* 80 di */ [ 0x3ff0000000000000, 0x0000000000000002 ],
/* 81 dii */ [ 0x3ff0000000000000, 0x0000000300000002 ],
/* 82 id */ [ 0x4000000000000000, 0x0000000000000001 ],
/* 83 iid */ [ 0x4008000000000000, 0x0000000200000001 ],
/* 84 idi */ null,
];
/* Have to do it this way for OSX: Issue 7354 */
__gshared long[2] dump;
/**
* Generate Register capture
*/
string gen_reg_capture( int n, string registers )( )
{
if( RegValue[n] == null ) return "return;";
string[] REG = mixin(registers); // ["RDI","RSI"];
// Which type of compare
static if(n < INT_END)
enum MODE = 1; // Int
else static if(n < SSE_END)
enum MODE = 2; // Float
else enum MODE = 3; // Mix
/* Begin */
string code = "asm {\n";
final switch( MODE )
{
case 1: code ~= "mov [dump], "~REG[0]~";\n";
REG = REG[1..$];
break;
case 2:
case 3: code ~= "movq [dump], XMM0;\n";
}
if( RegValue[n].length == 2 )
final switch( MODE )
{
case 1:
case 3: code ~= "mov [dump+8], "~REG[0]~";\n";
break;
case 2: code ~= "movq [dump+8], XMM1;\n";
} else {
code ~= "xor R8, R8;\n";
code ~= "mov [dump+8], R8;\n";
}
return code ~ "}\n";
}
/**
* Check the results
*/
bool check( TEST data )
{
bool pass = true;
foreach( i, e; expected )
{
if( data.result[i] != (e & 1) )
{
printf( "Test%d %s \tFail\n", data.num, ALL_S[i].ptr);
pass = false;
}
}
return pass;
}
/************************************************************************/
// test1 Return Struct in Registers
// ( if RDI == 12 we have no hidden pointer )
TEST data1 = { 1, "RDI hidden pointer" };
T test1_asm( T, int n )( int i )
{
asm {
cmp EDI, 12;
je L1;
leave; ret;
}
L1:
data1.result[n] = true;
}
void test1()
{
printf("\nRunning iasm Test 1 ( %s )\n", data1.desc.ptr);
foreach( int n, T; ALL_T )
test1_asm!(T,n)(12);
check( data1 );
}
/************************************************************************/
// test2 Pass Struct in Registers
// ( if RDI == 0 we have no stack pointer )
TEST data2 = { 2, "RDI struct pointer" };
T test2_asm( T, int n )( T t )
{
asm {
mov [dump], RDI;
mov [dump+8], RSP;
cmp EDI, 0; // TODO test RDI is a ptr to stack ? ?
je L1;
leave; ret;
}
L1:
data2.result[n] = true;
}
T test2f_asm( T, int n )( T t, int x )
{
asm {
cmp EDI, 12;
je L1;
leave; ret;
}
L1:
data2.result[n] = true;
}
void test2()
{
printf("\nRunning iasm Test 2 ( %s )\n", data2.desc.ptr);
// Integer
foreach( int n, T; ALL_T ) {
T t = { 0 };
test2_asm!(T,n)( t );
}
// float alternative test
foreach( int n, T; ALL_T[INT_END..SSE_END] )
{
enum n2 = n + INT_END;
data2.result[n2] = false;
test2f_asm!(T,n2)( T.init, 12 );
}
check( data2 );
}
/************************************************************************/
// test3
TEST data3 = { 3, "Check Return Register value" };
void test3_run( T, int n )( )
{
test3_ret!T();
mixin( gen_reg_capture!(n,`["RAX","RDX"]`)() );
//dbg!(T,n)( );
enum len = RegValue[n].length;
if( dump[0..len] == RegValue[n] )
data3.result[n] = true;
}
T test3_ret( T )( )
{
T t;
foreach( i, ref e; t.tupleof ) e = i+1;
return t;
}
void test3()
{
printf("\nRunning iasm Test 3 ( %s )\n", data3.desc.ptr);
foreach( int n, T; ALL_T )
test3_run!(T,n)( );
check( data3 );
}
/************************************************************************/
// test4
TEST data4 = { 4, "Check Input Register value" };
void test4_run( T, int n )( T t )
{
mixin( gen_reg_capture!(n,`["RDI","RSI"]`)() );
//dbg!(T,n)( );
enum len = RegValue[n].length;
if( dump[0..len] == RegValue[n] )
data4.result[n] = true;
}
void dbg( T, int n )( )
{
import std.stdio;
writefln( "D %s\t[ %16x, %16x ]", T.stringof, dump[0], dump[1], );
writef( "C %s\t[ %16x", T.stringof, RegValue[n][0] );
if( RegValue[n].length == 2 )
writef( ", %16x", RegValue[n][1] );
writefln( " ]" );
}
void test4()
{
printf("\nRunning iasm Test 4 ( %s )\n", data4.desc.ptr);
foreach( int n, T; ALL_T )
{
T t;
foreach( i, ref e; t.tupleof ) e = i+1;
test4_run!(T,n)( t );
}
check( data4 );
}
} // end version(Run_X86_64_Tests)
/************************************************************************/
void main()
{
D_test1();
D_test2();
version(Run_X86_64_Tests)
{
test1();
test2();
test3();
test4();
}
}
/+
/**
* C code to generate the table RegValue
*/
string c_generate_returns()
{
string value = " 1, 2, 3, 4, 5, 6, 7, 8, 9,10,"
"11,12,13,14,15,16,17,18,19,20,";
string code = "#include \"cgen.h\"\n";
// Generate return functions
foreach( int n, T; ALL_T )
{
auto Ts = T.stringof;
auto len = T.tupleof.length;
code ~= "struct "~Ts~" func_ret_"~Ts~"(void) { \n";
code ~= "struct "~Ts~" x = { ";
code ~= value[0..len*3] ~ " };\n";
code ~= "return x;\n}\n";
}
return code;
}
string c_generate_pass()
{
string value = " 1, 2, 3, 4, 5, 6, 7, 8, 9,10,"
"11,12,13,14,15,16,17,18,19,20,";
string code;
// Generate return functions
foreach( int n, T; ALL_T )
{
auto Ts = T.stringof;
auto len = T.tupleof.length;
code ~= "void func_pass_"~Ts~"( struct "~Ts~" x ) {\n";
////////////////
// Which type of compare
static if(n < INT_END)
enum MODE = 1; // Int
else static if(n < SSE_END)
enum MODE = 2; // Float
else enum MODE = 3; // Mix
auto nn = n.stringof;
/* Begin */
code ~= "asm(\n";
final switch( MODE )
{
case 1:
code ~= `"movq %rdi, reg\n" "movq %rsi, reg+8\n"`;
break;
case 2:
code ~= `"movq %xmm0, reg\n" "movq %xmm1, reg+8\n"`;
break;
case 3:
code ~= `"movq %xmm0, reg\n" "movq %rdi, reg+8\n"`;
}
code ~= "\n);\n";
code ~= "}\n";
////////////////
code ~= "void func_call_"~Ts~"( void ) {\n";
code ~= "struct "~Ts~" x = { ";
code ~= value[0..len*3] ~ " };\n";
code ~= "func_pass_"~Ts~"( x );\n}\n";
}
return code;
}
string c_generate_main()
{
string code = "void main() {\n";
foreach( int n, T; ALL_T )
{
// Which type of compare
static if(n < INT_END)
enum MODE = 1; // Int
else static if(n < SSE_END)
enum MODE = 2; // Float
else enum MODE = 3; // Mix
auto nn = n.stringof;
auto Ts = T.stringof;
/* Begin */
code ~= `printf("/* %3d `~Ts~`\t*/ ", `~nn~`);`"\n";
if( !(expected[n] & 1) )
{
code ~= `printf("null,\n");`"\n";
continue;
}
code ~= "asm(\n";
code ~= `"call func_ret_`~Ts~`\n"`"\n";
final switch( MODE )
{
case 1:
code ~= `"movq %rax, reg\n" "movq %rdx, reg+8\n"`;
break;
case 2:
code ~= `"movq %xmm0, reg\n" "movq %xmm1, reg+8\n"`;
break;
case 3:
code ~= `"movq %xmm0, reg\n" "movq %rax, reg+8\n"`;
}
code ~= "\n);\n";
code ~= `printf("[ 0x%016lx", reg.r1 );`"\n";
if( T.sizeof > 8 || MODE == 3 )
code ~= `printf(", 0x%016lx ],\n", reg.r2 );`"\n";
else code ~= `printf(", %015c ],\n", ' ' );`"\n";
}
foreach( int n, T; ALL_T )
{
// Which type of compare
static if(n < INT_END)
enum MODE = 1; // Int
else static if(n < SSE_END)
enum MODE = 2; // Float
else enum MODE = 3; // Mix
auto nn = n.stringof;
auto Ts = T.stringof;
/* Begin */
code ~= `printf("/* %3d `~Ts~`\t*/ ", `~nn~`);`"\n";
if( !(expected[n] & 1) )
{
code ~= `printf("null,\n");`"\n";
continue;
}
code ~= "func_call_"~Ts~"();\n";
code ~= `printf("[ 0x%016lx", reg.r1 );`"\n";
if( T.sizeof > 8 || MODE == 3 )
code ~= `printf(", 0x%016lx ],\n", reg.r2 );`"\n";
else code ~= `printf(", %015c ],\n", ' ' );`"\n";
}
return code ~ "}";
}
pragma(msg, c_generate_returns() );
pragma(msg, c_generate_pass() );
pragma(msg, c_generate_main() );
// +/
/+
/**
* Generate Functions that pass/return each Struct type
*
* ( Easier to look at objdump this way )
*/
string d_generate_functions( )
{
string code = "extern(C) {";
// pass
foreach( s; ALL_T )
{
string ss = s.stringof;
code ~= "void func_in_"~ss~"( "~ss~" t ) { t.a = 12; }\n";
}
// return
foreach( s; ALL_T[0..10] )
{
string ss = s.stringof;
code ~= `
auto func_out_`~ss~`()
{
`~ss~` t;
foreach( i, ref e; t.tupleof ) e = i+1;
return t;
}`;
}
// pass & return
foreach( s; ALL_T[0..10] )
{
string ss = s.stringof;
code ~= `
auto func_inout_`~ss~`( `~ss~` t )
{
foreach( i, ref e; t.tupleof ) e += 10;
return t;
}`;
}
return code ~ "\n} // extern(C)\n";
}
//pragma( msg, d_generate_functions() );
mixin( d_generate_functions() );
// +/