diff options
author | Mike Pall <mike> | 2011-10-13 20:44:31 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2011-10-13 20:44:31 +0200 |
commit | bc95d54ec932fddca832e35344efbecf1344e984 (patch) | |
tree | efa14255e22a76dc92eef5d0935dbe759c40554c /src | |
parent | 120c3adbff2acbbee5932f28345cde292ef044ec (diff) | |
download | luajit-bc95d54ec932fddca832e35344efbecf1344e984.tar.gz luajit-bc95d54ec932fddca832e35344efbecf1344e984.tar.bz2 luajit-bc95d54ec932fddca832e35344efbecf1344e984.zip |
FFI: Fix call argument and return handling for I8/U8/I16/U16 types.
Diffstat (limited to 'src')
-rw-r--r-- | src/lj_ccall.c | 22 | ||||
-rw-r--r-- | src/lj_crecord.c | 13 |
2 files changed, 27 insertions, 8 deletions
diff --git a/src/lj_ccall.c b/src/lj_ccall.c index b5cfe616..281b45a6 100644 --- a/src/lj_ccall.c +++ b/src/lj_ccall.c | |||
@@ -515,11 +515,8 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | |||
515 | /* Find out how (by value/ref) and where (GPR/FPR) to pass an argument. */ | 515 | /* Find out how (by value/ref) and where (GPR/FPR) to pass an argument. */ |
516 | if (ctype_isnum(d->info)) { | 516 | if (ctype_isnum(d->info)) { |
517 | if (sz > 8) goto err_nyi; | 517 | if (sz > 8) goto err_nyi; |
518 | if ((d->info & CTF_FP)) { | 518 | if ((d->info & CTF_FP)) |
519 | isfp = 1; | 519 | isfp = 1; |
520 | } else if (sz < CTSIZE_PTR) { | ||
521 | d = ctype_get(cts, CTID_INT_PSZ); | ||
522 | } | ||
523 | } else if (ctype_isvector(d->info)) { | 520 | } else if (ctype_isvector(d->info)) { |
524 | if (CCALL_VECTOR_REG && (sz == 8 || sz == 16)) | 521 | if (CCALL_VECTOR_REG && (sz == 8 || sz == 16)) |
525 | isfp = 1; | 522 | isfp = 1; |
@@ -557,6 +554,15 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | |||
557 | dp = rp; | 554 | dp = rp; |
558 | } | 555 | } |
559 | lj_cconv_ct_tv(cts, d, (uint8_t *)dp, o, CCF_ARG(narg)); | 556 | lj_cconv_ct_tv(cts, d, (uint8_t *)dp, o, CCF_ARG(narg)); |
557 | /* Extend passed integers to 32 bits at least. */ | ||
558 | if (ctype_isinteger_or_bool(d->info) && d->size < 4) { | ||
559 | if (d->info & CTF_UNSIGNED) | ||
560 | *(uint32_t *)dp = d->size == 1 ? (uint32_t)*(uint8_t *)dp : | ||
561 | (uint32_t)*(uint16_t *)dp; | ||
562 | else | ||
563 | *(int32_t *)dp = d->size == 1 ? (int32_t)*(int8_t *)dp : | ||
564 | (int32_t)*(int16_t *)dp; | ||
565 | } | ||
560 | #if LJ_TARGET_X64 && LJ_ABI_WIN | 566 | #if LJ_TARGET_X64 && LJ_ABI_WIN |
561 | if (isva) { /* Windows/x64 mirrors varargs in both register sets. */ | 567 | if (isva) { /* Windows/x64 mirrors varargs in both register sets. */ |
562 | if (nfpr == ngpr) | 568 | if (nfpr == ngpr) |
@@ -593,7 +599,7 @@ static int ccall_get_results(lua_State *L, CTState *cts, CType *ct, | |||
593 | CCallState *cc, int *ret) | 599 | CCallState *cc, int *ret) |
594 | { | 600 | { |
595 | CType *ctr = ctype_rawchild(cts, ct); | 601 | CType *ctr = ctype_rawchild(cts, ct); |
596 | void *sp = &cc->gpr[0]; | 602 | uint8_t *sp = (uint8_t *)&cc->gpr[0]; |
597 | if (ctype_isvoid(ctr->info)) { | 603 | if (ctype_isvoid(ctr->info)) { |
598 | *ret = 0; /* Zero results. */ | 604 | *ret = 0; /* Zero results. */ |
599 | return 0; /* No additional GC step. */ | 605 | return 0; /* No additional GC step. */ |
@@ -613,17 +619,19 @@ static int ccall_get_results(lua_State *L, CTState *cts, CType *ct, | |||
613 | CCALL_HANDLE_COMPLEXRET2 | 619 | CCALL_HANDLE_COMPLEXRET2 |
614 | return 1; /* One GC step. */ | 620 | return 1; /* One GC step. */ |
615 | } | 621 | } |
622 | if (LJ_BE && ctype_isinteger_or_bool(ctr->info) && ctr->size < CTSIZE_PTR) | ||
623 | sp += (CTSIZE_PTR - ctr->size); | ||
616 | #ifdef CCALL_HANDLE_RET | 624 | #ifdef CCALL_HANDLE_RET |
617 | CCALL_HANDLE_RET | 625 | CCALL_HANDLE_RET |
618 | #endif | 626 | #endif |
619 | #if CCALL_NUM_FPR | 627 | #if CCALL_NUM_FPR |
620 | if (ctype_isfp(ctr->info) || ctype_isvector(ctr->info)) | 628 | if (ctype_isfp(ctr->info) || ctype_isvector(ctr->info)) |
621 | sp = &cc->fpr[0]; | 629 | sp = (uint8_t *)&cc->fpr[0]; |
622 | #endif | 630 | #endif |
623 | /* No reference types end up here, so there's no need for the CTypeID. */ | 631 | /* No reference types end up here, so there's no need for the CTypeID. */ |
624 | lua_assert(!(ctype_isrefarray(ctr->info) || ctype_isstruct(ctr->info))); | 632 | lua_assert(!(ctype_isrefarray(ctr->info) || ctype_isstruct(ctr->info))); |
625 | if (ctype_isenum(ctr->info)) ctr = ctype_child(cts, ctr); | 633 | if (ctype_isenum(ctr->info)) ctr = ctype_child(cts, ctr); |
626 | return lj_cconv_tv_ct(cts, ctr, 0, L->top-1, (uint8_t *)sp); | 634 | return lj_cconv_tv_ct(cts, ctr, 0, L->top-1, sp); |
627 | } | 635 | } |
628 | 636 | ||
629 | /* Call C function. */ | 637 | /* Call C function. */ |
diff --git a/src/lj_crecord.c b/src/lj_crecord.c index c688caa3..001cf600 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c | |||
@@ -759,7 +759,14 @@ static TRef crec_call_args(jit_State *J, RecordFFData *rd, | |||
759 | if (!(ctype_isnum(d->info) || ctype_isptr(d->info) || | 759 | if (!(ctype_isnum(d->info) || ctype_isptr(d->info) || |
760 | ctype_isenum(d->info))) | 760 | ctype_isenum(d->info))) |
761 | lj_trace_err(J, LJ_TRERR_NYICALL); | 761 | lj_trace_err(J, LJ_TRERR_NYICALL); |
762 | args[n] = crec_ct_tv(J, d, 0, J->base[n+1], &rd->argv[n+1]); | 762 | tr = crec_ct_tv(J, d, 0, J->base[n+1], &rd->argv[n+1]); |
763 | if (ctype_isinteger_or_bool(d->info) && d->size < 4) { | ||
764 | if ((d->info & CTF_UNSIGNED)) | ||
765 | tr = emitconv(tr, IRT_INT, d->size==1 ? IRT_U8 : IRT_U16, 0); | ||
766 | else | ||
767 | tr = emitconv(tr, IRT_INT, d->size==1 ? IRT_I8 : IRT_I16, IRCONV_SEXT); | ||
768 | } | ||
769 | args[n] = tr; | ||
763 | } | 770 | } |
764 | tr = args[0]; | 771 | tr = args[0]; |
765 | for (i = 1; i < n; i++) | 772 | for (i = 1; i < n; i++) |
@@ -799,6 +806,10 @@ static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd) | |||
799 | tr = emitir(IRT(IR_CALLXS, t), crec_call_args(J, rd, cts, ct), func); | 806 | tr = emitir(IRT(IR_CALLXS, t), crec_call_args(J, rd, cts, ct), func); |
800 | if (t == IRT_FLOAT || t == IRT_U32) { | 807 | if (t == IRT_FLOAT || t == IRT_U32) { |
801 | tr = emitconv(tr, IRT_NUM, t, 0); | 808 | tr = emitconv(tr, IRT_NUM, t, 0); |
809 | } else if (t == IRT_I8 || t == IRT_I16) { | ||
810 | tr = emitconv(tr, IRT_INT, t, IRCONV_SEXT); | ||
811 | } else if (t == IRT_U8 || t == IRT_U16) { | ||
812 | tr = emitconv(tr, IRT_INT, t, 0); | ||
802 | } else if (t == IRT_PTR || (LJ_64 && t == IRT_P32) || | 813 | } else if (t == IRT_PTR || (LJ_64 && t == IRT_P32) || |
803 | (t == IRT_I64 || t == IRT_U64)) { | 814 | (t == IRT_I64 || t == IRT_U64)) { |
804 | TRef trid = lj_ir_kint(J, ctype_cid(ct->info)); | 815 | TRef trid = lj_ir_kint(J, ctype_cid(ct->info)); |