diff --git a/src/lj_cdata.c b/src/lj_cdata.c index 5bd55237..1d0aea85 100644 --- a/src/lj_cdata.c +++ b/src/lj_cdata.c @@ -127,6 +127,17 @@ collect_attrib: return ct; } } + } else if (cd->typeid == CTID_CTYPEID) { + /* Allow indexing a (pointer to) struct constructor to get constants. */ + CType *sct = ct = ctype_raw(cts, *(CTypeID *)p); + if (ctype_isptr(sct->info)) + sct = ctype_rawchild(cts, sct); + if (ctype_isstruct(sct->info)) { + CTSize ofs; + CType *fct = lj_ctype_getfield(cts, sct, name, &ofs); + if (fct && ctype_isconstval(fct->info)) + return fct; + } } { GCstr *s = lj_ctype_repr(cts->L, ctype_typeid(cts, ct), NULL); diff --git a/src/lj_crecord.c b/src/lj_crecord.c index 6027f5a5..95c32222 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c @@ -374,6 +374,18 @@ doconv: /* -- C data metamethods -------------------------------------------------- */ +/* Specialize to the CTypeID held by a cdata constructor. */ +static CTypeID crec_constructor(jit_State *J, GCcdata *cd, TRef tr) +{ + CTypeID id; + lua_assert(tref_iscdata(tr) && cd->typeid == CTID_CTYPEID); + id = *(CTypeID *)cdataptr(cd); + tr = emitir(IRT(IR_ADD, IRT_PTR), tr, lj_ir_kintp(J, sizeof(GCcdata))); + tr = emitir(IRT(IR_XLOAD, IRT_INT), tr, 0); + emitir(IRTG(IR_EQ, IRT_INT), tr, lj_ir_kint(J, (int32_t)id)); + return id; +} + /* This would be rather difficult in FOLD, so do it here: ** (base+k)+(idx*sz)+ofs ==> (base+idx*sz)+(ofs+k) ** (base+(idx+k)*sz)+ofs ==> (base+idx*sz)+(ofs+k*sz) @@ -435,6 +447,8 @@ void LJ_FASTCALL recff_cdata_index(jit_State *J, RecordFFData *rd) GCstr *name = strV(&rd->argv[1]); /* Always specialize to the field name. */ emitir(IRTG(IR_EQ, IRT_STR), idx, lj_ir_kstr(J, name)); + if (cd->typeid == CTID_CTYPEID) + ct = ctype_raw(cts, crec_constructor(J, cd, ptr)); if (ctype_isptr(ct->info)) { /* Automatically perform '->'. */ CType *cct = ctype_rawchild(cts, ct); if (ctype_isstruct(cct->info)) { @@ -575,7 +589,7 @@ void LJ_FASTCALL recff_cdata_call(jit_State *J, RecordFFData *rd) { GCcdata *cd = argv2cdata(J, J->base[0], &rd->argv[0]); if (cd->typeid == CTID_CTYPEID) { - crec_alloc(J, rd, *(CTypeID *)cdataptr(cd)); + crec_alloc(J, rd, crec_constructor(J, cd, J->base[0])); } else { lj_trace_err(J, LJ_TRERR_BADTYPE); }