]> git.ipfire.org Git - thirdparty/LuaJIT.git/commitdiff
FFI: Fix calling conventions for 32 bit OSX and iOS simulator.
authorMike Pall <mike>
Thu, 16 May 2013 12:35:00 +0000 (14:35 +0200)
committerMike Pall <mike>
Thu, 16 May 2013 12:35:00 +0000 (14:35 +0200)
OSX uses -freg-struct-return, which returns small structs in regs.
Thanks to Adriano Bertucci.

src/lj_ccall.c

index 92c52252ff476495c4522e3abcdaac1d55e6bd66..299098910e27c1354b100cff92d520fe6016153e 100644 (file)
 
 #else
 
+#if LJ_TARGET_OSX
+
+#define CCALL_HANDLE_STRUCTRET \
+  /* Return structs of size 1, 2, 4 or 8 in registers. */ \
+  cc->retref = !(sz == 1 || sz == 2 || sz == 4 || sz == 8); \
+  if (cc->retref) { \
+    if (ngpr < maxgpr) \
+      cc->gpr[ngpr++] = (GPRArg)dp; \
+    else \
+      cc->stack[nsp++] = (GPRArg)dp; \
+  } else {  /* Struct with single FP field ends up in FPR. */ \
+    cc->resx87 = ccall_classify_struct(cts, ctr); \
+  }
+
+#define CCALL_HANDLE_STRUCTRET2 \
+  if (cc->resx87) sp = (uint8_t *)&cc->fpr[0]; \
+  memcpy(dp, sp, ctr->size);
+
+#else
+
 #define CCALL_HANDLE_STRUCTRET \
   cc->retref = 1;  /* Return all structs by reference (in reg or on stack). */ \
   if (ngpr < maxgpr) \
@@ -39,6 +59,8 @@
   else \
     cc->stack[nsp++] = (GPRArg)dp;
 
+#endif
+
 #define CCALL_HANDLE_COMPLEXRET \
   /* Return complex float in GPRs and complex double by reference. */ \
   cc->retref = (sz > 8); \
   memcpy(dp, sp, ctr->size);  /* Copy struct return value from GPRs. */
 #endif
 
+/* -- x86 OSX ABI struct classification ----------------------------------- */
+
+#if LJ_TARGET_X86 && LJ_TARGET_OSX
+
+/* Check for struct with single FP field. */
+static int ccall_classify_struct(CTState *cts, CType *ct)
+{
+  CTSize sz = ct->size;
+  if (!(sz == sizeof(float) || sz == sizeof(double))) return 0;
+  if ((ct->info & CTF_UNION)) return 0;
+  while (ct->sib) {
+    ct = ctype_get(cts, ct->sib);
+    if (ctype_isfield(ct->info)) {
+      CType *sct = ctype_rawchild(cts, ct);
+      if (ctype_isfp(sct->info)) {
+       if (sct->size == sz)
+         return (sz >> 2);  /* Return 1 for float or 2 for double. */
+      } else if (ctype_isstruct(sct->info)) {
+       if (sct->size)
+         return ccall_classify_struct(cts, sct);
+      } else {
+       break;
+      }
+    } else if (ctype_isbitfield(ct->info)) {
+      break;
+    } else if (ctype_isxattrib(ct->info, CTA_SUBTYPE)) {
+      CType *sct = ctype_rawchild(cts, ct);
+      if (sct->size)
+       return ccall_classify_struct(cts, sct);
+    }
+  }
+  return 0;
+}
+
+#endif
+
 /* -- x64 struct classification ------------------------------------------- */
 
 #if LJ_TARGET_X64 && !LJ_ABI_WIN