FFI: Compile VLA/VLS and large cdata allocs with default initialization.

This commit is contained in:
Mike Pall
2013-05-24 00:45:44 +02:00
parent b3369f3c95
commit f1f7e40318
9 changed files with 139 additions and 61 deletions

View File

@@ -888,10 +888,8 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id)
CTSize sz;
CTInfo info = lj_ctype_info(cts, id, &sz);
CType *d = ctype_raw(cts, id);
TRef trid;
if (!sz || sz > 128 || (info & CTF_VLA) || ctype_align(info) > CT_MEMALIGN)
lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: large/special allocations. */
trid = lj_ir_kint(J, id);
TRef trcd, trid = lj_ir_kint(J, id);
cTValue *fin;
/* Use special instruction to box pointer or 32/64 bit integer. */
if (ctype_isptr(info) || (ctype_isinteger(info) && (sz == 4 || sz == 8))) {
TRef sp = J->base[1] ? crec_ct_tv(J, d, 0, J->base[1], &rd->argv[1]) :
@@ -899,11 +897,36 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id)
sz == 4 ? lj_ir_kint(J, 0) :
(lj_needsplit(J), lj_ir_kint64(J, 0));
J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), trid, sp);
return;
} else {
TRef trcd = emitir(IRTG(IR_CNEW, IRT_CDATA), trid, TREF_NIL);
cTValue *fin;
J->base[0] = trcd;
if (J->base[1] && !J->base[2] &&
TRef trsz = TREF_NIL;
if ((info & CTF_VLA)) { /* Calculate VLA/VLS size at runtime. */
CTSize sz0, sz1;
if (!J->base[1] || J->base[2])
lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: init VLA/VLS. */
trsz = crec_ct_tv(J, ctype_get(cts, CTID_INT32), 0,
J->base[1], &rd->argv[1]);
sz0 = lj_ctype_vlsize(cts, d, 0);
sz1 = lj_ctype_vlsize(cts, d, 1);
trsz = emitir(IRTGI(IR_MULOV), trsz, lj_ir_kint(J, (int32_t)(sz1-sz0)));
trsz = emitir(IRTGI(IR_ADDOV), trsz, lj_ir_kint(J, (int32_t)sz0));
J->base[1] = 0; /* Simplify logic below. */
} else if (ctype_align(info) > CT_MEMALIGN) {
trsz = lj_ir_kint(J, sz);
}
trcd = emitir(IRTG(IR_CNEW, IRT_CDATA), trid, trsz);
if (sz > 128 || (info & CTF_VLA)) {
TRef dp;
CTSize align;
special: /* Only handle bulk zero-fill for large/VLA/VLS types. */
if (J->base[1])
lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: init large/VLA/VLS types. */
dp = emitir(IRT(IR_ADD, IRT_PTR), trcd, lj_ir_kintp(J, sizeof(GCcdata)));
if (trsz == TREF_NIL) trsz = lj_ir_kint(J, sz);
align = ctype_align(info);
if (align < CT_MEMALIGN) align = CT_MEMALIGN;
crec_fill(J, dp, trsz, lj_ir_kint(J, 0), (1u << align));
} else if (J->base[1] && !J->base[2] &&
!lj_cconv_multi_init(cts, d, &rd->argv[1])) {
goto single_init;
} else if (ctype_isarray(d->info)) {
@@ -914,8 +937,9 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id)
TValue *sval = &tv;
MSize i;
tv.u64 = 0;
if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info)))
lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: init array of aggregates. */
if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info)) ||
esize * CREC_FILL_MAXUNROLL < sz)
goto special;
for (i = 1, ofs = 0; ofs < sz; ofs += esize) {
TRef dp = emitir(IRT(IR_ADD, IRT_PTR), trcd,
lj_ir_kintp(J, ofs + sizeof(GCcdata)));
@@ -972,11 +996,12 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id)
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, fin);
}
/* Record argument conversions. */