]> git.ipfire.org Git - thirdparty/LuaJIT.git/commitdiff
Merge branch 'master' into v2.1
authorMike Pall <mike>
Wed, 28 May 2025 18:39:05 +0000 (20:39 +0200)
committerMike Pall <mike>
Wed, 28 May 2025 18:39:05 +0000 (20:39 +0200)
1  2 
src/lj_ccall.c
src/lj_crecord.c

diff --cc src/lj_ccall.c
index f003d75674f8b8060ef8f3fe4d5e28ee914bdd4e,5d6bb03d50ec82ade646c8fe443cb837b9c5bec2..d5f092ea5ee385b85d971b7918877e0a31d3db41
@@@ -772,136 -621,11 +772,138 @@@ noth:  /* Not a homogeneous float/doubl
  
  #endif
  
 +/* -- ARM64 ABI struct classification ------------------------------------- */
 +
 +#if LJ_TARGET_ARM64
 +
 +/* Classify a struct based on its fields. */
 +static unsigned int ccall_classify_struct(CTState *cts, CType *ct)
 +{
 +  CTSize sz = ct->size;
 +  unsigned int r = 0, n = 0, isu = (ct->info & CTF_UNION);
 +  while (ct->sib && n <= 4) {
 +    unsigned int m = 1;
 +    CType *sct;
 +    ct = ctype_get(cts, ct->sib);
 +    if (ctype_isfield(ct->info)) {
 +      sct = ctype_rawchild(cts, ct);
 +      if (ctype_isarray(sct->info)) {
 +      CType *cct = ctype_rawchild(cts, sct);
 +      if (!cct->size) continue;
 +      m = sct->size / cct->size;
 +      sct = cct;
 +      }
 +      if (ctype_isfp(sct->info)) {
 +      r |= sct->size;
 +      if (!isu) n += m; else if (n < m) n = m;
 +      } else if (ctype_iscomplex(sct->info)) {
 +      r |= (sct->size >> 1);
 +      if (!isu) n += 2*m; else if (n < 2*m) n = 2*m;
 +      } else if (ctype_isstruct(sct->info)) {
 +      goto substruct;
 +      } else {
 +      goto noth;
 +      }
 +    } else if (ctype_isbitfield(ct->info)) {
 +      goto noth;
 +    } else if (ctype_isxattrib(ct->info, CTA_SUBTYPE)) {
 +      sct = ctype_rawchild(cts, ct);
 +    substruct:
 +      if (sct->size > 0) {
 +      unsigned int s = ccall_classify_struct(cts, sct), sn;
 +      if (s <= 1) goto noth;
 +      r |= (s & 255);
 +      sn = (s >> 8) * m;
 +      if (!isu) n += sn; else if (n < sn) n = sn;
 +      }
 +    }
 +  }
 +  if ((r == 4 || r == 8) && n <= 4)
 +    return r + (n << 8);
 +noth:  /* Not a homogeneous float/double aggregate. */
 +  return (sz <= 16);  /* Return structs of size <= 16 in GPRs. */
 +}
 +
 +#endif
 +
 +/* -- MIPS64 ABI struct classification ---------------------------- */
 +
 +#if LJ_TARGET_MIPS64
 +
 +#define FTYPE_FLOAT   1
 +#define FTYPE_DOUBLE  2
 +
 +/* Classify FP fields (max. 2) and their types. */
 +static unsigned int ccall_classify_struct(CTState *cts, CType *ct, CType *ctf)
 +{
 +  int n = 0, ft = 0;
 +  if ((ctf->info & CTF_VARARG) || (ct->info & CTF_UNION))
 +    goto noth;
 +  while (ct->sib) {
 +    CType *sct;
 +    ct = ctype_get(cts, ct->sib);
 +    if (n == 2) {
 +      goto noth;
 +    } else if (ctype_isfield(ct->info)) {
 +      sct = ctype_rawchild(cts, ct);
 +      if (ctype_isfp(sct->info)) {
 +      ft |= (sct->size == 4 ? FTYPE_FLOAT : FTYPE_DOUBLE) << 2*n;
 +      n++;
 +      } else {
 +      goto noth;
 +      }
 +    } else if (ctype_isbitfield(ct->info) ||
 +             ctype_isxattrib(ct->info, CTA_SUBTYPE)) {
 +      goto noth;
 +    }
 +  }
 +  if (n <= 2)
 +    return ft;
 +noth:  /* Not a homogeneous float/double aggregate. */
 +  return 0;  /* Struct is in GPRs. */
 +}
 +
 +static void ccall_copy_struct(CCallState *cc, CType *ctr, void *dp, void *sp,
 +                            int ft)
 +{
 +  if (LJ_ABI_SOFTFP ? ft :
 +      ((ft & 3) == FTYPE_FLOAT || (ft >> 2) == FTYPE_FLOAT)) {
 +    int i, ofs = 0;
 +    for (i = 0; ft != 0; i++, ft >>= 2) {
 +      if ((ft & 3) == FTYPE_FLOAT) {
 +#if LJ_ABI_SOFTFP
 +      /* The 2nd FP struct result is in CARG1 (gpr[2]) and not CRET2. */
 +      memcpy((uint8_t *)dp + ofs,
 +             (uint8_t *)&cc->gpr[2*i] + LJ_ENDIAN_SELECT(0, 4), 4);
 +#else
 +      *(float *)((uint8_t *)dp + ofs) = cc->fpr[i].f;
 +#endif
 +      ofs += 4;
 +      } else {
 +      ofs = (ofs + 7) & ~7;  /* 64 bit alignment. */
 +#if LJ_ABI_SOFTFP
 +      *(intptr_t *)((uint8_t *)dp + ofs) = cc->gpr[2*i];
 +#else
 +      *(double *)((uint8_t *)dp + ofs) = cc->fpr[i].d;
 +#endif
 +      ofs += 8;
 +      }
 +    }
 +  } else {
 +#if !LJ_ABI_SOFTFP
 +    if (ft) sp = (uint8_t *)&cc->fpr[0];
 +#endif
 +    memcpy(dp, sp, ctr->size);
 +  }
 +}
 +
 +#endif
 +
  /* -- Common C call handling ---------------------------------------------- */
  
- /* Infer the destination CTypeID for a vararg argument. */
+ /* Infer the destination CTypeID for a vararg argument.
+ ** Note: may reallocate cts->tab and invalidate CType pointers.
+ */
  CTypeID lj_ccall_ctid_vararg(CTState *cts, cTValue *o)
  {
    if (tvisnumber(o)) {
@@@ -993,14 -720,6 +998,14 @@@ static int ccall_set_args(lua_State *L
      fid = ctf->sib;
    }
  
-   if ((ct->info & CTF_VARARG)) {
 +#if LJ_TARGET_ARM64 && LJ_ABI_WIN
++  if ((info & CTF_VARARG)) {
 +    nsp -= maxgpr * CTSIZE_PTR;  /* May end up with negative nsp. */
 +    ngpr = maxgpr;
 +    nfpr = CCALL_NARG_FPR;
 +  }
 +#endif
 +
    /* Walk through all passed arguments. */
    for (o = L->base+1, narg = 1; o < top; o++, narg++) {
      CTypeID did;
      if (fid) {  /* Get argument type from field. */
        CType *ctf = ctype_get(cts, fid);
        fid = ctf->sib;
 -      lua_assert(ctype_isfield(ctf->info));
 +      lj_assertL(ctype_isfield(ctf->info), "field expected");
        did = ctype_cid(ctf->info);
      } else {
-       if (!(ct->info & CTF_VARARG))
+       if (!(info & CTF_VARARG))
        lj_err_caller(L, LJ_ERR_FFI_NUMARG);  /* Too many arguments. */
        did = lj_ccall_ctid_vararg(cts, o);  /* Infer vararg type. */
        isva = 1;
@@@ -1195,10 -883,10 +1200,10 @@@ int lj_ccall_func(lua_State *L, GCcdat
      lj_vm_ffi_call(&cc);
      if (cts->cb.slot != ~0u) {  /* Blacklist function that called a callback. */
        TValue tv;
 -      setlightudV(&tv, (void *)cc.func);
 +      tv.u64 = ((uintptr_t)(void *)cc.func >> 2) | U64x(800000000, 00000000);
        setboolV(lj_tab_set(L, cts->miscmap, &tv), 1);
      }
-     ct = (CType *)((intptr_t)ct+(intptr_t)cts->tab);  /* May be reallocated. */
+     ct = ctype_get(cts, id);  /* Table may have been reallocated. */
      gcsteps += ccall_get_results(L, cts, ct, &cc, &ret);
  #if LJ_TARGET_X86 && LJ_ABI_WIN
      /* Automatically detect __stdcall and fix up C function declaration. */
index f88cddfd95c2517a71650bc3ca9aab289b5c16a2,f686b35f2124f35684141c8b4b67ef59873bda2d..bbf002bd7c27366d58454cddb6c4c8581e0714c9
@@@ -1093,15 -981,16 +1093,17 @@@ static void crec_alloc(jit_State *J, Re
        crec_ct_tv(J, d, dp, lj_ir_kint(J, 0), &tv);
        }
      }
 -    /* Handle __gc metamethod. */
 -    fin = lj_ctype_meta(cts, id, MM_gc);
 -    if (fin)
 -      crec_finalizer(J, trcd, fin);
    }
 +  J->base[0] = trcd;
 +  /* Handle __gc metamethod. */
 +  fin = lj_ctype_meta(cts, id, MM_gc);
 +  if (fin)
 +    crec_finalizer(J, trcd, 0, fin);
  }
  
- /* Record argument conversions. */
+ /* Record argument conversions.
+ ** Note: may reallocate cts->tab and invalidate CType pointers.
+ */
  static TRef crec_call_args(jit_State *J, RecordFFData *rd,
                           CTState *cts, CType *ct)
  {
    TRef *arg0 = NULL, *arg1 = NULL;
  #endif
    int ngpr = 0;
-   if (ctype_cconv(ct->info) == CTCC_THISCALL)
+   if (ctype_cconv(info) == CTCC_THISCALL)
      ngpr = 1;
-   else if (ctype_cconv(ct->info) == CTCC_FASTCALL)
+   else if (ctype_cconv(info) == CTCC_FASTCALL)
      ngpr = 2;
 +#elif LJ_TARGET_ARM64 && LJ_TARGET_OSX
 +  int ngpr = CCALL_NARG_GPR;
  #endif
  
    /* Skip initial attributes. */
      if (fid) {  /* Get argument type from field. */
        CType *ctf = ctype_get(cts, fid);
        fid = ctf->sib;
 -      lua_assert(ctype_isfield(ctf->info));
 +      lj_assertJ(ctype_isfield(ctf->info), "field expected");
        did = ctype_cid(ctf->info);
      } else {
-       if (!(ct->info & CTF_VARARG))
+       if (!(info & CTF_VARARG))
        lj_trace_err(J, LJ_TRERR_NYICALL);  /* Too many arguments. */
 +#if LJ_TARGET_ARM64 && LJ_TARGET_OSX
 +      if (ngpr >= 0) {
 +      ngpr = -1;
 +      args[n++] = TREF_NIL;  /* Marker for start of varargs. */
 +      if (n >= CCI_NARGS_MAX)
 +        lj_trace_err(J, LJ_TRERR_NYICALL);
 +      }
 +#endif
        did = lj_ccall_ctid_vararg(cts, o);  /* Infer vararg type. */
      }
      d = ctype_raw(cts, did);