diff options
Diffstat (limited to 'src/lj_cconv.c')
-rw-r--r-- | src/lj_cconv.c | 66 |
1 files changed, 41 insertions, 25 deletions
diff --git a/src/lj_cconv.c b/src/lj_cconv.c index 8556952f..3bbfd3f1 100644 --- a/src/lj_cconv.c +++ b/src/lj_cconv.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #if LJ_HASFFI | 8 | #if LJ_HASFFI |
9 | 9 | ||
10 | #include "lj_err.h" | 10 | #include "lj_err.h" |
11 | #include "lj_buf.h" | ||
11 | #include "lj_tab.h" | 12 | #include "lj_tab.h" |
12 | #include "lj_ctype.h" | 13 | #include "lj_ctype.h" |
13 | #include "lj_cdata.h" | 14 | #include "lj_cdata.h" |
@@ -122,19 +123,25 @@ void lj_cconv_ct_ct(CTState *cts, CType *d, CType *s, | |||
122 | CTInfo dinfo = d->info, sinfo = s->info; | 123 | CTInfo dinfo = d->info, sinfo = s->info; |
123 | void *tmpptr; | 124 | void *tmpptr; |
124 | 125 | ||
125 | lua_assert(!ctype_isenum(dinfo) && !ctype_isenum(sinfo)); | 126 | lj_assertCTS(!ctype_isenum(dinfo) && !ctype_isenum(sinfo), |
126 | lua_assert(!ctype_isattrib(dinfo) && !ctype_isattrib(sinfo)); | 127 | "unresolved enum"); |
128 | lj_assertCTS(!ctype_isattrib(dinfo) && !ctype_isattrib(sinfo), | ||
129 | "unstripped attribute"); | ||
127 | 130 | ||
128 | if (ctype_type(dinfo) > CT_MAYCONVERT || ctype_type(sinfo) > CT_MAYCONVERT) | 131 | if (ctype_type(dinfo) > CT_MAYCONVERT || ctype_type(sinfo) > CT_MAYCONVERT) |
129 | goto err_conv; | 132 | goto err_conv; |
130 | 133 | ||
131 | /* Some basic sanity checks. */ | 134 | /* Some basic sanity checks. */ |
132 | lua_assert(!ctype_isnum(dinfo) || dsize > 0); | 135 | lj_assertCTS(!ctype_isnum(dinfo) || dsize > 0, "bad size for number type"); |
133 | lua_assert(!ctype_isnum(sinfo) || ssize > 0); | 136 | lj_assertCTS(!ctype_isnum(sinfo) || ssize > 0, "bad size for number type"); |
134 | lua_assert(!ctype_isbool(dinfo) || dsize == 1 || dsize == 4); | 137 | lj_assertCTS(!ctype_isbool(dinfo) || dsize == 1 || dsize == 4, |
135 | lua_assert(!ctype_isbool(sinfo) || ssize == 1 || ssize == 4); | 138 | "bad size for bool type"); |
136 | lua_assert(!ctype_isinteger(dinfo) || (1u<<lj_fls(dsize)) == dsize); | 139 | lj_assertCTS(!ctype_isbool(sinfo) || ssize == 1 || ssize == 4, |
137 | lua_assert(!ctype_isinteger(sinfo) || (1u<<lj_fls(ssize)) == ssize); | 140 | "bad size for bool type"); |
141 | lj_assertCTS(!ctype_isinteger(dinfo) || (1u<<lj_fls(dsize)) == dsize, | ||
142 | "bad size for integer type"); | ||
143 | lj_assertCTS(!ctype_isinteger(sinfo) || (1u<<lj_fls(ssize)) == ssize, | ||
144 | "bad size for integer type"); | ||
138 | 145 | ||
139 | switch (cconv_idx2(dinfo, sinfo)) { | 146 | switch (cconv_idx2(dinfo, sinfo)) { |
140 | /* Destination is a bool. */ | 147 | /* Destination is a bool. */ |
@@ -357,7 +364,7 @@ void lj_cconv_ct_ct(CTState *cts, CType *d, CType *s, | |||
357 | if ((flags & CCF_CAST) || (d->info & CTF_VLA) || d != s) | 364 | if ((flags & CCF_CAST) || (d->info & CTF_VLA) || d != s) |
358 | goto err_conv; /* Must be exact same type. */ | 365 | goto err_conv; /* Must be exact same type. */ |
359 | copyval: /* Copy value. */ | 366 | copyval: /* Copy value. */ |
360 | lua_assert(dsize == ssize); | 367 | lj_assertCTS(dsize == ssize, "value copy with different sizes"); |
361 | memcpy(dp, sp, dsize); | 368 | memcpy(dp, sp, dsize); |
362 | break; | 369 | break; |
363 | 370 | ||
@@ -389,7 +396,7 @@ int lj_cconv_tv_ct(CTState *cts, CType *s, CTypeID sid, | |||
389 | lj_cconv_ct_ct(cts, ctype_get(cts, CTID_DOUBLE), s, | 396 | lj_cconv_ct_ct(cts, ctype_get(cts, CTID_DOUBLE), s, |
390 | (uint8_t *)&o->n, sp, 0); | 397 | (uint8_t *)&o->n, sp, 0); |
391 | /* Numbers are NOT canonicalized here! Beware of uninitialized data. */ | 398 | /* Numbers are NOT canonicalized here! Beware of uninitialized data. */ |
392 | lua_assert(tvisnum(o)); | 399 | lj_assertCTS(tvisnum(o), "non-canonical NaN passed"); |
393 | } | 400 | } |
394 | } else { | 401 | } else { |
395 | uint32_t b = s->size == 1 ? (*sp != 0) : (*(int *)sp != 0); | 402 | uint32_t b = s->size == 1 ? (*sp != 0) : (*(int *)sp != 0); |
@@ -406,7 +413,7 @@ int lj_cconv_tv_ct(CTState *cts, CType *s, CTypeID sid, | |||
406 | CTSize sz; | 413 | CTSize sz; |
407 | copyval: /* Copy value. */ | 414 | copyval: /* Copy value. */ |
408 | sz = s->size; | 415 | sz = s->size; |
409 | lua_assert(sz != CTSIZE_INVALID); | 416 | lj_assertCTS(sz != CTSIZE_INVALID, "value copy with invalid size"); |
410 | /* Attributes are stripped, qualifiers are kept (but mostly ignored). */ | 417 | /* Attributes are stripped, qualifiers are kept (but mostly ignored). */ |
411 | cd = lj_cdata_new(cts, ctype_typeid(cts, s), sz); | 418 | cd = lj_cdata_new(cts, ctype_typeid(cts, s), sz); |
412 | setcdataV(cts->L, o, cd); | 419 | setcdataV(cts->L, o, cd); |
@@ -421,19 +428,22 @@ int lj_cconv_tv_bf(CTState *cts, CType *s, TValue *o, uint8_t *sp) | |||
421 | CTInfo info = s->info; | 428 | CTInfo info = s->info; |
422 | CTSize pos, bsz; | 429 | CTSize pos, bsz; |
423 | uint32_t val; | 430 | uint32_t val; |
424 | lua_assert(ctype_isbitfield(info)); | 431 | lj_assertCTS(ctype_isbitfield(info), "bitfield expected"); |
425 | /* NYI: packed bitfields may cause misaligned reads. */ | 432 | /* NYI: packed bitfields may cause misaligned reads. */ |
426 | switch (ctype_bitcsz(info)) { | 433 | switch (ctype_bitcsz(info)) { |
427 | case 4: val = *(uint32_t *)sp; break; | 434 | case 4: val = *(uint32_t *)sp; break; |
428 | case 2: val = *(uint16_t *)sp; break; | 435 | case 2: val = *(uint16_t *)sp; break; |
429 | case 1: val = *(uint8_t *)sp; break; | 436 | case 1: val = *(uint8_t *)sp; break; |
430 | default: lua_assert(0); val = 0; break; | 437 | default: |
438 | lj_assertCTS(0, "bad bitfield container size %d", ctype_bitcsz(info)); | ||
439 | val = 0; | ||
440 | break; | ||
431 | } | 441 | } |
432 | /* Check if a packed bitfield crosses a container boundary. */ | 442 | /* Check if a packed bitfield crosses a container boundary. */ |
433 | pos = ctype_bitpos(info); | 443 | pos = ctype_bitpos(info); |
434 | bsz = ctype_bitbsz(info); | 444 | bsz = ctype_bitbsz(info); |
435 | lua_assert(pos < 8*ctype_bitcsz(info)); | 445 | lj_assertCTS(pos < 8*ctype_bitcsz(info), "bad bitfield position"); |
436 | lua_assert(bsz > 0 && bsz <= 8*ctype_bitcsz(info)); | 446 | lj_assertCTS(bsz > 0 && bsz <= 8*ctype_bitcsz(info), "bad bitfield size"); |
437 | if (pos + bsz > 8*ctype_bitcsz(info)) | 447 | if (pos + bsz > 8*ctype_bitcsz(info)) |
438 | lj_err_caller(cts->L, LJ_ERR_FFI_NYIPACKBIT); | 448 | lj_err_caller(cts->L, LJ_ERR_FFI_NYIPACKBIT); |
439 | if (!(info & CTF_BOOL)) { | 449 | if (!(info & CTF_BOOL)) { |
@@ -448,8 +458,10 @@ int lj_cconv_tv_bf(CTState *cts, CType *s, TValue *o, uint8_t *sp) | |||
448 | setintV(o, (int32_t)val); | 458 | setintV(o, (int32_t)val); |
449 | } | 459 | } |
450 | } else { | 460 | } else { |
451 | lua_assert(bsz == 1); | 461 | uint32_t b = (val >> pos) & 1; |
452 | setboolV(o, (val >> pos) & 1); | 462 | lj_assertCTS(bsz == 1, "bad bool bitfield size"); |
463 | setboolV(o, b); | ||
464 | setboolV(&cts->g->tmptv2, b); /* Remember for trace recorder. */ | ||
453 | } | 465 | } |
454 | return 0; /* No GC step needed. */ | 466 | return 0; /* No GC step needed. */ |
455 | } | 467 | } |
@@ -551,7 +563,7 @@ void lj_cconv_ct_tv(CTState *cts, CType *d, | |||
551 | sid = cdataV(o)->ctypeid; | 563 | sid = cdataV(o)->ctypeid; |
552 | s = ctype_get(cts, sid); | 564 | s = ctype_get(cts, sid); |
553 | if (ctype_isref(s->info)) { /* Resolve reference for value. */ | 565 | if (ctype_isref(s->info)) { /* Resolve reference for value. */ |
554 | lua_assert(s->size == CTSIZE_PTR); | 566 | lj_assertCTS(s->size == CTSIZE_PTR, "ref is not pointer-sized"); |
555 | sp = *(void **)sp; | 567 | sp = *(void **)sp; |
556 | sid = ctype_cid(s->info); | 568 | sid = ctype_cid(s->info); |
557 | } | 569 | } |
@@ -571,7 +583,7 @@ void lj_cconv_ct_tv(CTState *cts, CType *d, | |||
571 | CType *cct = lj_ctype_getfield(cts, d, str, &ofs); | 583 | CType *cct = lj_ctype_getfield(cts, d, str, &ofs); |
572 | if (!cct || !ctype_isconstval(cct->info)) | 584 | if (!cct || !ctype_isconstval(cct->info)) |
573 | goto err_conv; | 585 | goto err_conv; |
574 | lua_assert(d->size == 4); | 586 | lj_assertCTS(d->size == 4, "only 32 bit enum supported"); /* NYI */ |
575 | sp = (uint8_t *)&cct->size; | 587 | sp = (uint8_t *)&cct->size; |
576 | sid = ctype_cid(cct->info); | 588 | sid = ctype_cid(cct->info); |
577 | } else if (ctype_isrefarray(d->info)) { /* Copy string to array. */ | 589 | } else if (ctype_isrefarray(d->info)) { /* Copy string to array. */ |
@@ -610,8 +622,10 @@ void lj_cconv_ct_tv(CTState *cts, CType *d, | |||
610 | tmpptr = uddata(ud); | 622 | tmpptr = uddata(ud); |
611 | if (ud->udtype == UDTYPE_IO_FILE) | 623 | if (ud->udtype == UDTYPE_IO_FILE) |
612 | tmpptr = *(void **)tmpptr; | 624 | tmpptr = *(void **)tmpptr; |
625 | else if (ud->udtype == UDTYPE_BUFFER) | ||
626 | tmpptr = ((SBufExt *)tmpptr)->r; | ||
613 | } else if (tvislightud(o)) { | 627 | } else if (tvislightud(o)) { |
614 | tmpptr = lightudV(o); | 628 | tmpptr = lightudV(cts->g, o); |
615 | } else if (tvisfunc(o)) { | 629 | } else if (tvisfunc(o)) { |
616 | void *p = lj_ccallback_new(cts, d, funcV(o)); | 630 | void *p = lj_ccallback_new(cts, d, funcV(o)); |
617 | if (p) { | 631 | if (p) { |
@@ -635,10 +649,10 @@ void lj_cconv_bf_tv(CTState *cts, CType *d, uint8_t *dp, TValue *o) | |||
635 | CTInfo info = d->info; | 649 | CTInfo info = d->info; |
636 | CTSize pos, bsz; | 650 | CTSize pos, bsz; |
637 | uint32_t val, mask; | 651 | uint32_t val, mask; |
638 | lua_assert(ctype_isbitfield(info)); | 652 | lj_assertCTS(ctype_isbitfield(info), "bitfield expected"); |
639 | if ((info & CTF_BOOL)) { | 653 | if ((info & CTF_BOOL)) { |
640 | uint8_t tmpbool; | 654 | uint8_t tmpbool; |
641 | lua_assert(ctype_bitbsz(info) == 1); | 655 | lj_assertCTS(ctype_bitbsz(info) == 1, "bad bool bitfield size"); |
642 | lj_cconv_ct_tv(cts, ctype_get(cts, CTID_BOOL), &tmpbool, o, 0); | 656 | lj_cconv_ct_tv(cts, ctype_get(cts, CTID_BOOL), &tmpbool, o, 0); |
643 | val = tmpbool; | 657 | val = tmpbool; |
644 | } else { | 658 | } else { |
@@ -647,8 +661,8 @@ void lj_cconv_bf_tv(CTState *cts, CType *d, uint8_t *dp, TValue *o) | |||
647 | } | 661 | } |
648 | pos = ctype_bitpos(info); | 662 | pos = ctype_bitpos(info); |
649 | bsz = ctype_bitbsz(info); | 663 | bsz = ctype_bitbsz(info); |
650 | lua_assert(pos < 8*ctype_bitcsz(info)); | 664 | lj_assertCTS(pos < 8*ctype_bitcsz(info), "bad bitfield position"); |
651 | lua_assert(bsz > 0 && bsz <= 8*ctype_bitcsz(info)); | 665 | lj_assertCTS(bsz > 0 && bsz <= 8*ctype_bitcsz(info), "bad bitfield size"); |
652 | /* Check if a packed bitfield crosses a container boundary. */ | 666 | /* Check if a packed bitfield crosses a container boundary. */ |
653 | if (pos + bsz > 8*ctype_bitcsz(info)) | 667 | if (pos + bsz > 8*ctype_bitcsz(info)) |
654 | lj_err_caller(cts->L, LJ_ERR_FFI_NYIPACKBIT); | 668 | lj_err_caller(cts->L, LJ_ERR_FFI_NYIPACKBIT); |
@@ -659,7 +673,9 @@ void lj_cconv_bf_tv(CTState *cts, CType *d, uint8_t *dp, TValue *o) | |||
659 | case 4: *(uint32_t *)dp = (*(uint32_t *)dp & ~mask) | (uint32_t)val; break; | 673 | case 4: *(uint32_t *)dp = (*(uint32_t *)dp & ~mask) | (uint32_t)val; break; |
660 | case 2: *(uint16_t *)dp = (*(uint16_t *)dp & ~mask) | (uint16_t)val; break; | 674 | case 2: *(uint16_t *)dp = (*(uint16_t *)dp & ~mask) | (uint16_t)val; break; |
661 | case 1: *(uint8_t *)dp = (*(uint8_t *)dp & ~mask) | (uint8_t)val; break; | 675 | case 1: *(uint8_t *)dp = (*(uint8_t *)dp & ~mask) | (uint8_t)val; break; |
662 | default: lua_assert(0); break; | 676 | default: |
677 | lj_assertCTS(0, "bad bitfield container size %d", ctype_bitcsz(info)); | ||
678 | break; | ||
663 | } | 679 | } |
664 | } | 680 | } |
665 | 681 | ||