FFI: Allow indexing a struct constructor to get constants.

Specialize to the CTypeID held by a constructor in all cases.
This commit is contained in:
Mike Pall 2011-01-16 18:32:33 +01:00
parent 0fa32e5d31
commit 6f746577d0
2 changed files with 26 additions and 1 deletions

View File

@ -127,6 +127,17 @@ collect_attrib:
return ct; 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); GCstr *s = lj_ctype_repr(cts->L, ctype_typeid(cts, ct), NULL);

View File

@ -374,6 +374,18 @@ doconv:
/* -- C data metamethods -------------------------------------------------- */ /* -- 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: /* This would be rather difficult in FOLD, so do it here:
** (base+k)+(idx*sz)+ofs ==> (base+idx*sz)+(ofs+k) ** (base+k)+(idx*sz)+ofs ==> (base+idx*sz)+(ofs+k)
** (base+(idx+k)*sz)+ofs ==> (base+idx*sz)+(ofs+k*sz) ** (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]); GCstr *name = strV(&rd->argv[1]);
/* Always specialize to the field name. */ /* Always specialize to the field name. */
emitir(IRTG(IR_EQ, IRT_STR), idx, lj_ir_kstr(J, 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 '->'. */ if (ctype_isptr(ct->info)) { /* Automatically perform '->'. */
CType *cct = ctype_rawchild(cts, ct); CType *cct = ctype_rawchild(cts, ct);
if (ctype_isstruct(cct->info)) { 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]); GCcdata *cd = argv2cdata(J, J->base[0], &rd->argv[0]);
if (cd->typeid == CTID_CTYPEID) { if (cd->typeid == CTID_CTYPEID) {
crec_alloc(J, rd, *(CTypeID *)cdataptr(cd)); crec_alloc(J, rd, crec_constructor(J, cd, J->base[0]));
} else { } else {
lj_trace_err(J, LJ_TRERR_BADTYPE); lj_trace_err(J, LJ_TRERR_BADTYPE);
} }