diff test/callf/main.c @ 533:71c884e610f0

- integration of patches from Raphael Luba, Thekla, Inc.: * integration of aggregate-by-value (struct, union) support patch for x64 (win and sysv) * windows/x64 asm additions to specify how stack unwinds (help for debuggers, exception handling, etc.) * see Changelog for details - new calling convention modes for thiscalls (platform agnostic, was specific before) * new signature character for platform agnostic thiscalls ('*' / DC_SIGCHAR_CC_THISCALL) - dcCallF(), dcVCallF(), dcArgF() and dcVArgF(): * added support for aggregates-by-value (wasn't part of patch) * change that those functions don't implicitly call dcReset() anymore, which was unflexible (breaking change) - added macros to feature test implementation for aggregate-by-value and syscall support - changed libdyncall_s.lib and libdyncallback_s.lib order in callback test makefiles, as some toolchains are picky about order - doc: * man page updates to describe aggregate interface * manual overview changes to highlight platforms with aggregate-by-value support - test/plain: replaced tests w/ old/stale sctruct interface with new aggregate one
author Tassilo Philipp
date Thu, 21 Apr 2022 13:35:47 +0200
parents 7608e34098b0
children d9558c1555df
line wrap: on
line diff
--- a/test/callf/main.c	Sat Apr 16 15:00:58 2022 +0200
+++ b/test/callf/main.c	Thu Apr 21 13:35:47 2022 +0200
@@ -6,7 +6,7 @@
  Description:
  License:
 
-   Copyright (c) 2007-2021 Daniel Adler <dadler@uni-goettingen.de>,
+   Copyright (c) 2007-2022 Daniel Adler <dadler@uni-goettingen.de>,
                            Tassilo Philipp <tphilipp@potion-studios.com>
 
    Permission to use, copy, modify, and distribute this software for any
@@ -39,21 +39,21 @@
 
 /* sample void function */
 
-int vf_iii(int x,int y,int z)
+int i_iii(int x,int y,int z)
 {
   int r = (x == 1 && y == 2 && z == 3);
   printf("%d %d %d: %d", x, y, z, r);
   return r;
 }
 
-int vf_ffiffiffi(float a, float b, int c, float d, float e, int f, float g, float h, int i)
+int i_ffiffiffi(float a, float b, int c, float d, float e, int f, float g, float h, int i)
 {
   int r = (a == 1.f && b == 2.f && c == 3 && d == 4.f && e == 5.f && f == 6 && g == 7.f && h == 8.f && i == 9);
   printf("%f %f %d %f %f %d %f %f %d: %d", a, b, c, d, e, f, g, h, i, r);
   return r;
 }
 
-int vf_ffiV(float a, float b, int c, ...)
+int i_ffiV(float a, float b, int c, ...)
 {
   va_list ap;
   double d, e, g, h;
@@ -74,6 +74,32 @@
   return r;
 }
 
+
+#if defined(DC__Feature_AggrByVal)
+struct A { int i; char x[7]; long long dummy_too_big_for_regs[50]; }; /* returned via hidden ptr arg on x64/sysv */
+struct A A_cc(char a, char b)
+{
+  int i;
+  struct A r = { (int)a-(int)b, { 3, a|b } };
+  for(i=2; i<7; ++i)
+    r.x[i] = r.x[i-2]+r.x[i-1];
+  printf("%d %d: ", a, b);
+  return r;
+}
+
+struct B { int i; unsigned char x[7]; }; /* returned via regs on x64/sysv */
+struct B A_CC(unsigned char a, unsigned char b)
+{
+  int i;
+  struct B r = { (int)a-(int)b, { 3, a|b } };
+  for(i=2; i<7; ++i)
+    r.x[i] = r.x[i-2]+r.x[i-1];
+  printf("%d %d: ", a, b);
+  return r;
+}
+#endif
+
+
 /* main */
 
 int main(int argc, char* argv[])
@@ -91,24 +117,24 @@
   /* calls using 'formatted' API */
   dcReset(vm);
   printf("callf iii)i:       ");
-  dcCallF(vm, &ret, (void*)&vf_iii, "iii)i", 1, 2, 3);
+  dcCallF(vm, &ret, (void*)&i_iii, "iii)i", 1, 2, 3);
   r = ret.i && r;
 
   dcReset(vm);
   printf("\ncallf ffiffiffi)i: ");
-  dcCallF(vm, &ret, (void*)&vf_ffiffiffi, "ffiffiffi)i", 1.f, 2.f, 3, 4.f, 5.f, 6, 7.f, 8.f, 9);
+  dcCallF(vm, &ret, (void*)&i_ffiffiffi, "ffiffiffi)i", 1.f, 2.f, 3, 4.f, 5.f, 6, 7.f, 8.f, 9);
   r = ret.i && r;
 
   /* same but with calling convention prefix */
   dcReset(vm);
   printf("\ncallf _:ffiffiffi)i: ");
-  dcCallF(vm, &ret, (void*)&vf_ffiffiffi, "_:ffiffiffi)i", 1.f, 2.f, 3, 4.f, 5.f, 6, 7.f, 8.f, 9);
+  dcCallF(vm, &ret, (void*)&i_ffiffiffi, "_:ffiffiffi)i", 1.f, 2.f, 3, 4.f, 5.f, 6, 7.f, 8.f, 9);
   r = ret.i && r;
 
   /* vararg call */
   dcReset(vm);
   printf("\ncallf _effi_.ddiddi)i: ");
-  dcCallF(vm, &ret, (void*)&vf_ffiV, "_effi_.ddiddi)i", 1.f, 2.f, 3, 4., 5., 6, 7., 8., 9);
+  dcCallF(vm, &ret, (void*)&i_ffiV, "_effi_.ddiddi)i", 1.f, 2.f, 3, 4., 5., 6, 7., 8., 9);
   r = ret.i && r;
 
   /* arg binding then call using 'formatted' API */
@@ -117,30 +143,75 @@
   dcMode(vm, DC_CALL_C_DEFAULT);
   printf("\nargf iii)i       then call: ");
   dcArgF(vm, "iii)i", 1, 2, 3);
-  r = r && dcCallInt(vm, (void*)&vf_iii);
+  r = r && dcCallInt(vm, (void*)&i_iii);
 
   dcReset(vm);
   printf("\nargf iii         then call: ");
   dcArgF(vm, "iii", 1, 2, 3);
-  r = r && dcCallInt(vm, (void*)&vf_iii);
+  r = r && dcCallInt(vm, (void*)&i_iii);
 
   dcReset(vm);
   printf("\nargf ffiffiffi)i then call: ");
   dcArgF(vm, "ffiffiffi)i", 1.f, 2.f, 3, 4.f, 5.f, 6, 7.f, 8.f, 9);
-  r = r && dcCallInt(vm, (void*)&vf_ffiffiffi);
+  r = r && dcCallInt(vm, (void*)&i_ffiffiffi);
 
   dcReset(vm);
   printf("\nargf ffiffiffi   then call: ");
   dcArgF(vm, "ffiffiffi", 1.f, 2.f, 3, 4.f, 5.f, 6, 7.f, 8.f, 9);
-  r = r && dcCallInt(vm, (void*)&vf_ffiffiffi);
+  r = r && dcCallInt(vm, (void*)&i_ffiffiffi);
 
-#if defined(DC_UNIX) && !defined(DC__OS_MacOSX) && !defined(DC__OS_SunOS) && !defined(DC__OS_BeOS)
+#if defined(DC__Feature_Syscall)
+#  if defined(DC_UNIX)
   /* testing syscall using calling convention prefix - not available on all platforms */
   dcReset(vm);
   printf("\ncallf _$iZi)i");
   fflush(NULL); /* needed before syscall write as it's immediate, or order might be incorrect */
   dcCallF(vm, &ret, (DCpointer)(ptrdiff_t)SYS_write, "_$iZi)i", 1/*stdout*/, " = syscall: 1", 13);
   r = ret.i == 13 && r;
+#  else
+/*@@@*/
+#  endif
+#endif
+
+#if defined(DC__Feature_AggrByVal)
+  /* aggregate return value test */
+  {
+    int r_;
+    struct A a;
+    DCaggr *s = dcNewAggr(1, sizeof(struct A));
+    dcAggrField(s, DC_SIGCHAR_INT,  offsetof(struct A, i), 1);
+    dcAggrField(s, DC_SIGCHAR_CHAR, offsetof(struct A, x), 7);
+    dcCloseAggr(s);
+  
+    dcReset(vm);
+    printf("\ncallf _:cc)A (A={ic[7]l[50]}): ");
+    dcCallF(vm, &ret, (void*)&A_cc, "_:cc)A", 3, 16, s, &a);
+    r_ = ret.p == &a && a.i == -13 && a.x[0] == 3 && a.x[1] == 19 && a.x[2] == 22 && a.x[3] == 41 && a.x[4] == 63 && a.x[5] == 104 && a.x[6] == -89;
+    printf("%d %d %d %d %d %d %d %d: %d", a.i, a.x[0], a.x[1], a.x[2], a.x[3], a.x[4], a.x[5], a.x[6], r_);
+
+    dcFreeAggr(s);
+
+    r = r_ && r;
+  }
+  /* aggregate return value test */
+  {
+    int r_;
+    struct B b;
+    DCaggr *s = dcNewAggr(1, sizeof(struct B));
+    dcAggrField(s, DC_SIGCHAR_INT,   offsetof(struct B, i), 1);
+    dcAggrField(s, DC_SIGCHAR_UCHAR, offsetof(struct B, x), 7);
+    dcCloseAggr(s);
+  
+    dcReset(vm);
+    printf("\ncallf _:cc)A (A={iC[7]}): ");
+    dcCallF(vm, &ret, (void*)&A_CC, "_:CC)A", 3, 16, s, &b);
+    r_ = ret.p == &b && b.i == -13 && b.x[0] == 3 && b.x[1] == 19 && b.x[2] == 22 && b.x[3] == 41 && b.x[4] == 63 && b.x[5] == 104 && b.x[6] == 167;
+    printf("%d %d %d %d %d %d %d %d: %d", b.i, b.x[0], b.x[1], b.x[2], b.x[3], b.x[4], b.x[5], b.x[6], r_);
+
+    dcFreeAggr(s);
+
+    r = r_ && r;
+  }
 #endif
 
   /* free vm */