diff options
Diffstat (limited to 'src/lj_crecord.c')
-rw-r--r-- | src/lj_crecord.c | 53 |
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. */ |