aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2012-06-14 19:54:07 +0200
committerMike Pall <mike>2012-06-14 19:54:07 +0200
commit946c7418d59dd201386ee66686075595754cd86d (patch)
tree1930adb8b7f969b8b69ed3b634fd1736e7d5944e /src
parentca6bf2d9a41fb2c0c80bafdbaf2e29421b2cb55d (diff)
downloadluajit-946c7418d59dd201386ee66686075595754cd86d.tar.gz
luajit-946c7418d59dd201386ee66686075595754cd86d.tar.bz2
luajit-946c7418d59dd201386ee66686075595754cd86d.zip
FFI: Add support for parameterized C types.
Diffstat (limited to 'src')
-rw-r--r--src/lib_ffi.c21
-rw-r--r--src/lj_cparse.c44
-rw-r--r--src/lj_cparse.h1
-rw-r--r--src/lj_errmsg.h1
4 files changed, 57 insertions, 10 deletions
diff --git a/src/lib_ffi.c b/src/lib_ffi.c
index 2a674b88..f4097041 100644
--- a/src/lib_ffi.c
+++ b/src/lib_ffi.c
@@ -35,7 +35,7 @@
35/* -- C type checks ------------------------------------------------------- */ 35/* -- C type checks ------------------------------------------------------- */
36 36
37/* Check first argument for a C type and returns its ID. */ 37/* Check first argument for a C type and returns its ID. */
38static CTypeID ffi_checkctype(lua_State *L, CTState *cts) 38static CTypeID ffi_checkctype(lua_State *L, CTState *cts, TValue *param)
39{ 39{
40 TValue *o = L->base; 40 TValue *o = L->base;
41 if (!(o < L->top)) { 41 if (!(o < L->top)) {
@@ -50,6 +50,7 @@ static CTypeID ffi_checkctype(lua_State *L, CTState *cts)
50 cp.cts = cts; 50 cp.cts = cts;
51 cp.srcname = strdata(s); 51 cp.srcname = strdata(s);
52 cp.p = strdata(s); 52 cp.p = strdata(s);
53 cp.param = param;
53 cp.mode = CPARSE_MODE_ABSTRACT|CPARSE_MODE_NOIMPLICIT; 54 cp.mode = CPARSE_MODE_ABSTRACT|CPARSE_MODE_NOIMPLICIT;
54 errcode = lj_cparse(&cp); 55 errcode = lj_cparse(&cp);
55 if (errcode) lj_err_throw(L, errcode); /* Propagate errors. */ 56 if (errcode) lj_err_throw(L, errcode); /* Propagate errors. */
@@ -57,6 +58,7 @@ static CTypeID ffi_checkctype(lua_State *L, CTState *cts)
57 } else { 58 } else {
58 GCcdata *cd; 59 GCcdata *cd;
59 if (!tviscdata(o)) goto err_argtype; 60 if (!tviscdata(o)) goto err_argtype;
61 if (param && param < L->top) lj_err_arg(L, 1, LJ_ERR_FFI_NUMPARAM);
60 cd = cdataV(o); 62 cd = cdataV(o);
61 return cd->typeid == CTID_CTYPEID ? *(CTypeID *)cdataptr(cd) : cd->typeid; 63 return cd->typeid == CTID_CTYPEID ? *(CTypeID *)cdataptr(cd) : cd->typeid;
62 } 64 }
@@ -442,6 +444,7 @@ LJLIB_CF(ffi_cdef)
442 cp.cts = ctype_cts(L); 444 cp.cts = ctype_cts(L);
443 cp.srcname = strdata(s); 445 cp.srcname = strdata(s);
444 cp.p = strdata(s); 446 cp.p = strdata(s);
447 cp.param = L->base+1;
445 cp.mode = CPARSE_MODE_MULTI|CPARSE_MODE_DIRECT; 448 cp.mode = CPARSE_MODE_MULTI|CPARSE_MODE_DIRECT;
446 errcode = lj_cparse(&cp); 449 errcode = lj_cparse(&cp);
447 if (errcode) lj_err_throw(L, errcode); /* Propagate errors. */ 450 if (errcode) lj_err_throw(L, errcode); /* Propagate errors. */
@@ -452,7 +455,7 @@ LJLIB_CF(ffi_cdef)
452LJLIB_CF(ffi_new) LJLIB_REC(.) 455LJLIB_CF(ffi_new) LJLIB_REC(.)
453{ 456{
454 CTState *cts = ctype_cts(L); 457 CTState *cts = ctype_cts(L);
455 CTypeID id = ffi_checkctype(L, cts); 458 CTypeID id = ffi_checkctype(L, cts, NULL);
456 CType *ct = ctype_raw(cts, id); 459 CType *ct = ctype_raw(cts, id);
457 CTSize sz; 460 CTSize sz;
458 CTInfo info = lj_ctype_info(cts, id, &sz); 461 CTInfo info = lj_ctype_info(cts, id, &sz);
@@ -492,7 +495,7 @@ LJLIB_CF(ffi_new) LJLIB_REC(.)
492LJLIB_CF(ffi_cast) LJLIB_REC(ffi_new) 495LJLIB_CF(ffi_cast) LJLIB_REC(ffi_new)
493{ 496{
494 CTState *cts = ctype_cts(L); 497 CTState *cts = ctype_cts(L);
495 CTypeID id = ffi_checkctype(L, cts); 498 CTypeID id = ffi_checkctype(L, cts, NULL);
496 CType *d = ctype_raw(cts, id); 499 CType *d = ctype_raw(cts, id);
497 TValue *o = lj_lib_checkany(L, 2); 500 TValue *o = lj_lib_checkany(L, 2);
498 L->top = o+1; /* Make sure this is the last item on the stack. */ 501 L->top = o+1; /* Make sure this is the last item on the stack. */
@@ -510,7 +513,7 @@ LJLIB_CF(ffi_cast) LJLIB_REC(ffi_new)
510LJLIB_CF(ffi_typeof) 513LJLIB_CF(ffi_typeof)
511{ 514{
512 CTState *cts = ctype_cts(L); 515 CTState *cts = ctype_cts(L);
513 CTypeID id = ffi_checkctype(L, cts); 516 CTypeID id = ffi_checkctype(L, cts, L->base+1);
514 GCcdata *cd = lj_cdata_new(cts, CTID_CTYPEID, 4); 517 GCcdata *cd = lj_cdata_new(cts, CTID_CTYPEID, 4);
515 *(CTypeID *)cdataptr(cd) = id; 518 *(CTypeID *)cdataptr(cd) = id;
516 setcdataV(L, L->top-1, cd); 519 setcdataV(L, L->top-1, cd);
@@ -521,7 +524,7 @@ LJLIB_CF(ffi_typeof)
521LJLIB_CF(ffi_istype) LJLIB_REC(ffi_istype) 524LJLIB_CF(ffi_istype) LJLIB_REC(ffi_istype)
522{ 525{
523 CTState *cts = ctype_cts(L); 526 CTState *cts = ctype_cts(L);
524 CTypeID id1 = ffi_checkctype(L, cts); 527 CTypeID id1 = ffi_checkctype(L, cts, NULL);
525 TValue *o = lj_lib_checkany(L, 2); 528 TValue *o = lj_lib_checkany(L, 2);
526 int b = 0; 529 int b = 0;
527 if (tviscdata(o)) { 530 if (tviscdata(o)) {
@@ -551,7 +554,7 @@ LJLIB_CF(ffi_istype) LJLIB_REC(ffi_istype)
551LJLIB_CF(ffi_sizeof) 554LJLIB_CF(ffi_sizeof)
552{ 555{
553 CTState *cts = ctype_cts(L); 556 CTState *cts = ctype_cts(L);
554 CTypeID id = ffi_checkctype(L, cts); 557 CTypeID id = ffi_checkctype(L, cts, NULL);
555 CTSize sz; 558 CTSize sz;
556 if (LJ_UNLIKELY(tviscdata(L->base) && cdataisv(cdataV(L->base)))) { 559 if (LJ_UNLIKELY(tviscdata(L->base) && cdataisv(cdataV(L->base)))) {
557 sz = cdatavlen(cdataV(L->base)); 560 sz = cdatavlen(cdataV(L->base));
@@ -573,7 +576,7 @@ LJLIB_CF(ffi_sizeof)
573LJLIB_CF(ffi_alignof) 576LJLIB_CF(ffi_alignof)
574{ 577{
575 CTState *cts = ctype_cts(L); 578 CTState *cts = ctype_cts(L);
576 CTypeID id = ffi_checkctype(L, cts); 579 CTypeID id = ffi_checkctype(L, cts, NULL);
577 CTSize sz = 0; 580 CTSize sz = 0;
578 CTInfo info = lj_ctype_info(cts, id, &sz); 581 CTInfo info = lj_ctype_info(cts, id, &sz);
579 setintV(L->top-1, 1 << ctype_align(info)); 582 setintV(L->top-1, 1 << ctype_align(info));
@@ -583,7 +586,7 @@ LJLIB_CF(ffi_alignof)
583LJLIB_CF(ffi_offsetof) 586LJLIB_CF(ffi_offsetof)
584{ 587{
585 CTState *cts = ctype_cts(L); 588 CTState *cts = ctype_cts(L);
586 CTypeID id = ffi_checkctype(L, cts); 589 CTypeID id = ffi_checkctype(L, cts, NULL);
587 GCstr *name = lj_lib_checkstr(L, 2); 590 GCstr *name = lj_lib_checkstr(L, 2);
588 CType *ct = lj_ctype_rawref(cts, id); 591 CType *ct = lj_ctype_rawref(cts, id);
589 CTSize ofs; 592 CTSize ofs;
@@ -700,7 +703,7 @@ LJLIB_PUSH(top-8) LJLIB_SET(!) /* Store reference to miscmap table. */
700LJLIB_CF(ffi_metatype) 703LJLIB_CF(ffi_metatype)
701{ 704{
702 CTState *cts = ctype_cts(L); 705 CTState *cts = ctype_cts(L);
703 CTypeID id = ffi_checkctype(L, cts); 706 CTypeID id = ffi_checkctype(L, cts, NULL);
704 GCtab *mt = lj_lib_checktab(L, 2); 707 GCtab *mt = lj_lib_checktab(L, 2);
705 GCtab *t = cts->miscmap; 708 GCtab *t = cts->miscmap;
706 CType *ct = ctype_get(cts, id); /* Only allow raw types. */ 709 CType *ct = ctype_get(cts, id); /* Only allow raw types. */
diff --git a/src/lj_cparse.c b/src/lj_cparse.c
index ff5abc70..0f8c2857 100644
--- a/src/lj_cparse.c
+++ b/src/lj_cparse.c
@@ -121,6 +121,7 @@ LJ_NORET static void cp_errmsg(CPState *cp, CPToken tok, ErrMsg em, ...)
121 tokstr = NULL; 121 tokstr = NULL;
122 } else if (tok == CTOK_IDENT || tok == CTOK_INTEGER || tok == CTOK_STRING || 122 } else if (tok == CTOK_IDENT || tok == CTOK_INTEGER || tok == CTOK_STRING ||
123 tok >= CTOK_FIRSTDECL) { 123 tok >= CTOK_FIRSTDECL) {
124 if (cp->sb.n == 0) cp_save(cp, '$');
124 cp_save(cp, '\0'); 125 cp_save(cp, '\0');
125 tokstr = cp->sb.buf; 126 tokstr = cp->sb.buf;
126 } else { 127 } else {
@@ -203,6 +204,38 @@ static CPToken cp_ident(CPState *cp)
203 return CTOK_IDENT; 204 return CTOK_IDENT;
204} 205}
205 206
207/* Parse parameter. */
208static CPToken cp_param(CPState *cp)
209{
210 CPChar c = cp_get(cp);
211 TValue *o = cp->param;
212 if (lj_char_isident(c) || c == '$') /* Reserve $xyz for future extensions. */
213 cp_errmsg(cp, c, LJ_ERR_XSYNTAX);
214 if (!o || o >= cp->L->top)
215 cp_err(cp, LJ_ERR_FFI_NUMPARAM);
216 cp->param = o+1;
217 if (tvisstr(o)) {
218 cp->str = strV(o);
219 cp->val.id = lj_ctype_getname(cp->cts, &cp->ct, cp->str, cp->tmask);
220 if (ctype_type(cp->ct->info) == CT_KW)
221 return ctype_cid(cp->ct->info);
222 return CTOK_IDENT;
223 } else if (tvisnumber(o)) {
224 cp->val.i32 = numberVint(o);
225 cp->val.id = CTID_INT32;
226 return CTOK_INTEGER;
227 } else {
228 GCcdata *cd;
229 if (!tviscdata(o)) lj_err_argtype(cp->L, o-cp->L->base+1, "type parameter");
230 cd = cdataV(o);
231 if (cd->typeid == CTID_CTYPEID)
232 cp->val.id = *(CTypeID *)cdataptr(cd);
233 else
234 cp->val.id = cd->typeid;
235 return '$';
236 }
237}
238
206/* Parse string or character constant. */ 239/* Parse string or character constant. */
207static CPToken cp_string(CPState *cp) 240static CPToken cp_string(CPState *cp)
208{ 241{
@@ -317,6 +350,8 @@ static CPToken cp_next_(CPState *cp)
317 return '>'; 350 return '>';
318 case '-': 351 case '-':
319 cp_get(cp); if (cp->c != '>') return '-'; cp_get(cp); return CTOK_DEREF; 352 cp_get(cp); if (cp->c != '>') return '-'; cp_get(cp); return CTOK_DEREF;
353 case '$':
354 return cp_param(cp);
320 case '\0': return CTOK_EOF; 355 case '\0': return CTOK_EOF;
321 default: { CPToken c = cp->c; cp_get(cp); return c; } 356 default: { CPToken c = cp->c; cp_get(cp); return c; }
322 } 357 }
@@ -403,6 +438,7 @@ static int cp_istypedecl(CPState *cp)
403{ 438{
404 if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECL) return 1; 439 if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECL) return 1;
405 if (cp->tok == CTOK_IDENT && ctype_istypedef(cp->ct->info)) return 1; 440 if (cp->tok == CTOK_IDENT && ctype_istypedef(cp->ct->info)) return 1;
441 if (cp->tok == '$') return 1;
406 return 0; 442 return 0;
407} 443}
408 444
@@ -1441,7 +1477,7 @@ static CTypeID cp_decl_enum(CPState *cp, CPDecl *sdecl)
1441static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl) 1477static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl)
1442{ 1478{
1443 uint32_t cds = 0, sz = 0; 1479 uint32_t cds = 0, sz = 0;
1444 CTInfo tdef = 0; 1480 CTypeID tdef = 0;
1445 1481
1446 decl->cp = cp; 1482 decl->cp = cp;
1447 decl->mode = cp->mode; 1483 decl->mode = cp->mode;
@@ -1471,6 +1507,10 @@ static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl)
1471 tdef = ctype_cid(cp->ct->info); /* Get typedef. */ 1507 tdef = ctype_cid(cp->ct->info); /* Get typedef. */
1472 cp_next(cp); 1508 cp_next(cp);
1473 break; 1509 break;
1510 case '$':
1511 tdef = cp->val.id;
1512 cp_next(cp);
1513 break;
1474 default: 1514 default:
1475 if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECLFLAG) { 1515 if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECLFLAG) {
1476 uint32_t cbit; 1516 uint32_t cbit;
@@ -1826,6 +1866,8 @@ static TValue *cpcparser(lua_State *L, lua_CFunction dummy, void *ud)
1826 cp_decl_multi(cp); 1866 cp_decl_multi(cp);
1827 else 1867 else
1828 cp_decl_single(cp); 1868 cp_decl_single(cp);
1869 if (cp->param && cp->param != cp->L->top)
1870 cp_err(cp, LJ_ERR_FFI_NUMPARAM);
1829 lua_assert(cp->depth == 0); 1871 lua_assert(cp->depth == 0);
1830 return NULL; 1872 return NULL;
1831} 1873}
diff --git a/src/lj_cparse.h b/src/lj_cparse.h
index eaa1bdb5..29188c69 100644
--- a/src/lj_cparse.h
+++ b/src/lj_cparse.h
@@ -48,6 +48,7 @@ typedef struct CPState {
48 SBuf sb; /* String buffer for tokens. */ 48 SBuf sb; /* String buffer for tokens. */
49 lua_State *L; /* Lua state. */ 49 lua_State *L; /* Lua state. */
50 CTState *cts; /* C type state. */ 50 CTState *cts; /* C type state. */
51 TValue *param; /* C type parameters. */
51 const char *srcname; /* Current source name. */ 52 const char *srcname; /* Current source name. */
52 BCLine linenumber; /* Input line counter. */ 53 BCLine linenumber; /* Input line counter. */
53 int depth; /* Recursive declaration depth. */ 54 int depth; /* Recursive declaration depth. */
diff --git a/src/lj_errmsg.h b/src/lj_errmsg.h
index 5ba619bf..2d677cca 100644
--- a/src/lj_errmsg.h
+++ b/src/lj_errmsg.h
@@ -149,6 +149,7 @@ ERRDEF(FFI_BADSCL, "bad storage class")
149ERRDEF(FFI_DECLSPEC, "declaration specifier expected") 149ERRDEF(FFI_DECLSPEC, "declaration specifier expected")
150ERRDEF(FFI_BADTAG, "undeclared or implicit tag " LUA_QS) 150ERRDEF(FFI_BADTAG, "undeclared or implicit tag " LUA_QS)
151ERRDEF(FFI_REDEF, "attempt to redefine " LUA_QS) 151ERRDEF(FFI_REDEF, "attempt to redefine " LUA_QS)
152ERRDEF(FFI_NUMPARAM, "wrong number of type parameters")
152ERRDEF(FFI_INITOV, "too many initializers for " LUA_QS) 153ERRDEF(FFI_INITOV, "too many initializers for " LUA_QS)
153ERRDEF(FFI_BADCONV, "cannot convert " LUA_QS " to " LUA_QS) 154ERRDEF(FFI_BADCONV, "cannot convert " LUA_QS " to " LUA_QS)
154ERRDEF(FFI_BADLEN, "attempt to get length of " LUA_QS) 155ERRDEF(FFI_BADLEN, "attempt to get length of " LUA_QS)