aboutsummaryrefslogtreecommitdiff
path: root/src/lj_crecord.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_crecord.c')
-rw-r--r--src/lj_crecord.c53
1 files changed, 39 insertions, 14 deletions
diff --git a/src/lj_crecord.c b/src/lj_crecord.c
index e88e3579..ef6e5f82 100644
--- a/src/lj_crecord.c
+++ b/src/lj_crecord.c
@@ -888,10 +888,8 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id)
888 CTSize sz; 888 CTSize sz;
889 CTInfo info = lj_ctype_info(cts, id, &sz); 889 CTInfo info = lj_ctype_info(cts, id, &sz);
890 CType *d = ctype_raw(cts, id); 890 CType *d = ctype_raw(cts, id);
891 TRef trid; 891 TRef trcd, trid = lj_ir_kint(J, id);
892 if (!sz || sz > 128 || (info & CTF_VLA) || ctype_align(info) > CT_MEMALIGN) 892 cTValue *fin;
893 lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: large/special allocations. */
894 trid = lj_ir_kint(J, id);
895 /* Use special instruction to box pointer or 32/64 bit integer. */ 893 /* Use special instruction to box pointer or 32/64 bit integer. */
896 if (ctype_isptr(info) || (ctype_isinteger(info) && (sz == 4 || sz == 8))) { 894 if (ctype_isptr(info) || (ctype_isinteger(info) && (sz == 4 || sz == 8))) {
897 TRef sp = J->base[1] ? crec_ct_tv(J, d, 0, J->base[1], &rd->argv[1]) : 895 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)
899 sz == 4 ? lj_ir_kint(J, 0) : 897 sz == 4 ? lj_ir_kint(J, 0) :
900 (lj_needsplit(J), lj_ir_kint64(J, 0)); 898 (lj_needsplit(J), lj_ir_kint64(J, 0));
901 J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), trid, sp); 899 J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), trid, sp);
900 return;
902 } else { 901 } else {
903 TRef trcd = emitir(IRTG(IR_CNEW, IRT_CDATA), trid, TREF_NIL); 902 TRef trsz = TREF_NIL;
904 cTValue *fin; 903 if ((info & CTF_VLA)) { /* Calculate VLA/VLS size at runtime. */
905 J->base[0] = trcd; 904 CTSize sz0, sz1;
906 if (J->base[1] && !J->base[2] && 905 if (!J->base[1] || J->base[2])
906 lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: init VLA/VLS. */
907 trsz = crec_ct_tv(J, ctype_get(cts, CTID_INT32), 0,
908 J->base[1], &rd->argv[1]);
909 sz0 = lj_ctype_vlsize(cts, d, 0);
910 sz1 = lj_ctype_vlsize(cts, d, 1);
911 trsz = emitir(IRTGI(IR_MULOV), trsz, lj_ir_kint(J, (int32_t)(sz1-sz0)));
912 trsz = emitir(IRTGI(IR_ADDOV), trsz, lj_ir_kint(J, (int32_t)sz0));
913 J->base[1] = 0; /* Simplify logic below. */
914 } else if (ctype_align(info) > CT_MEMALIGN) {
915 trsz = lj_ir_kint(J, sz);
916 }
917 trcd = emitir(IRTG(IR_CNEW, IRT_CDATA), trid, trsz);
918 if (sz > 128 || (info & CTF_VLA)) {
919 TRef dp;
920 CTSize align;
921 special: /* Only handle bulk zero-fill for large/VLA/VLS types. */
922 if (J->base[1])
923 lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: init large/VLA/VLS types. */
924 dp = emitir(IRT(IR_ADD, IRT_PTR), trcd, lj_ir_kintp(J, sizeof(GCcdata)));
925 if (trsz == TREF_NIL) trsz = lj_ir_kint(J, sz);
926 align = ctype_align(info);
927 if (align < CT_MEMALIGN) align = CT_MEMALIGN;
928 crec_fill(J, dp, trsz, lj_ir_kint(J, 0), (1u << align));
929 } else if (J->base[1] && !J->base[2] &&
907 !lj_cconv_multi_init(cts, d, &rd->argv[1])) { 930 !lj_cconv_multi_init(cts, d, &rd->argv[1])) {
908 goto single_init; 931 goto single_init;
909 } else if (ctype_isarray(d->info)) { 932 } else if (ctype_isarray(d->info)) {
@@ -914,8 +937,9 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id)
914 TValue *sval = &tv; 937 TValue *sval = &tv;
915 MSize i; 938 MSize i;
916 tv.u64 = 0; 939 tv.u64 = 0;
917 if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info))) 940 if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info)) ||
918 lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: init array of aggregates. */ 941 esize * CREC_FILL_MAXUNROLL < sz)
942 goto special;
919 for (i = 1, ofs = 0; ofs < sz; ofs += esize) { 943 for (i = 1, ofs = 0; ofs < sz; ofs += esize) {
920 TRef dp = emitir(IRT(IR_ADD, IRT_PTR), trcd, 944 TRef dp = emitir(IRT(IR_ADD, IRT_PTR), trcd,
921 lj_ir_kintp(J, ofs + sizeof(GCcdata))); 945 lj_ir_kintp(J, ofs + sizeof(GCcdata)));
@@ -972,11 +996,12 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id)
972 crec_ct_tv(J, d, dp, lj_ir_kint(J, 0), &tv); 996 crec_ct_tv(J, d, dp, lj_ir_kint(J, 0), &tv);
973 } 997 }
974 } 998 }
975 /* Handle __gc metamethod. */
976 fin = lj_ctype_meta(cts, id, MM_gc);
977 if (fin)
978 crec_finalizer(J, trcd, fin);
979 } 999 }
1000 J->base[0] = trcd;
1001 /* Handle __gc metamethod. */
1002 fin = lj_ctype_meta(cts, id, MM_gc);
1003 if (fin)
1004 crec_finalizer(J, trcd, fin);
980} 1005}
981 1006
982/* Record argument conversions. */ 1007/* Record argument conversions. */