/* Classify a struct based on its fields. */ static unsigned int ccall_classify_struct(CTState *cts, CType *ct, CType *ctf) { CTSize sz = ct->size; unsigned int r = 0, n = 0, isu = (ct->info & CTF_UNION); if ((ctf->info & CTF_VARARG)) goto noth; 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)) { r |= sct->size; if (!isu) n++; else if (n == 0) n = 1; } else if (ctype_iscomplex(sct->info)) { r |= (sct->size >> 1); if (!isu) n += 2; else if (n < 2) n = 2; } else { goto noth;
/* Convert CType to IRType. */ static IRType crec_ct2irt(CType *ct) { if (LJ_LIKELY(ctype_isnum(ct->info))) { if ((ct->info & CTF_FP)) { if (ct->size == sizeof(double)) return IRT_NUM; else if (ct->size == sizeof(float)) return IRT_FLOAT; } else { uint32_t b = lj_fls(ct->size); if (b <= 3) return IRT_I8 + 2*b + ((ct->info & CTF_UNSIGNED) ? 1 : 0); } } else if (ctype_isptr(ct->info)) { return (LJ_64 && ct->size == 8) ? IRT_P64 : IRT_P32; } else if (ctype_iscomplex(ct->info)) { if (ct->size == 2*sizeof(double)) return IRT_NUM; else if (ct->size == 2*sizeof(float)) return IRT_FLOAT; } return IRT_CDATA; }
/* Index C data by a TValue. Return CType and pointer. */ CType *lj_cdata_index(CTState *cts, GCcdata *cd, cTValue *key, uint8_t **pp, CTInfo *qual) { uint8_t *p = (uint8_t *)cdataptr(cd); CType *ct = ctype_get(cts, cd->ctypeid); ptrdiff_t idx; /* Resolve reference for cdata object. */ if (ctype_isref(ct->info)) { lua_assert(ct->size == CTSIZE_PTR); p = *(uint8_t **)p; ct = ctype_child(cts, ct); } collect_attrib: /* Skip attributes and collect qualifiers. */ while (ctype_isattrib(ct->info)) { if (ctype_attrib(ct->info) == CTA_QUAL) *qual |= ct->size; ct = ctype_child(cts, ct); } lua_assert(!ctype_isref(ct->info)); /* Interning rejects refs to refs. */ if (tvisint(key)) { idx = (ptrdiff_t)intV(key); goto integer_key; } else if (tvisnum(key)) { /* Numeric key. */ #ifdef _MSC_VER /* Workaround for MSVC bug. */ volatile #endif lua_Number n = numV(key); idx = LJ_64 ? (ptrdiff_t)n : (ptrdiff_t)lj_num2int(n); integer_key: if (ctype_ispointer(ct->info)) { CTSize sz = lj_ctype_size(cts, ctype_cid(ct->info)); /* Element size. */ if (sz == CTSIZE_INVALID) lj_err_caller(cts->L, LJ_ERR_FFI_INVSIZE); if (ctype_isptr(ct->info)) { p = (uint8_t *)cdata_getptr(p, ct->size); } else if ((ct->info & (CTF_VECTOR|CTF_COMPLEX))) { if ((ct->info & CTF_COMPLEX)) idx &= 1; *qual |= CTF_CONST; /* Valarray elements are constant. */ } *pp = p + idx*(int32_t)sz; return ct; } } else if (tviscdata(key)) { /* Integer cdata key. */ GCcdata *cdk = cdataV(key); CType *ctk = ctype_raw(cts, cdk->ctypeid); if (ctype_isenum(ctk->info)) ctk = ctype_child(cts, ctk); if (ctype_isinteger(ctk->info)) { lj_cconv_ct_ct(cts, ctype_get(cts, CTID_INT_PSZ), ctk, (uint8_t *)&idx, cdataptr(cdk), 0); goto integer_key; } } else if (tvisstr(key)) { /* String key. */ GCstr *name = strV(key); if (ctype_isstruct(ct->info)) { CTSize ofs; CType *fct = lj_ctype_getfieldq(cts, ct, name, &ofs, qual); if (fct) { *pp = p + ofs; return fct; } } else if (ctype_iscomplex(ct->info)) { if (name->len == 2) { *qual |= CTF_CONST; /* Complex fields are constant. */ if (strdata(name)[0] == 'r' && strdata(name)[1] == 'e') { *pp = p; return ct; } else if (strdata(name)[0] == 'i' && strdata(name)[1] == 'm') { *pp = p + (ct->size >> 1); return ct; } } } else if (cd->ctypeid == CTID_CTYPEID) {