summaryrefslogtreecommitdiff
path: root/src/lj_crecord.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_crecord.c')
-rw-r--r--src/lj_crecord.c103
1 files changed, 83 insertions, 20 deletions
diff --git a/src/lj_crecord.c b/src/lj_crecord.c
index 4e6a644a..3dd6f495 100644
--- a/src/lj_crecord.c
+++ b/src/lj_crecord.c
@@ -18,6 +18,7 @@
18#include "lj_cparse.h" 18#include "lj_cparse.h"
19#include "lj_cconv.h" 19#include "lj_cconv.h"
20#include "lj_clib.h" 20#include "lj_clib.h"
21#include "lj_ccall.h"
21#include "lj_ir.h" 22#include "lj_ir.h"
22#include "lj_jit.h" 23#include "lj_jit.h"
23#include "lj_ircall.h" 24#include "lj_ircall.h"
@@ -364,7 +365,7 @@ static TRef crec_tv_ct(jit_State *J, CType *s, CTypeID sid, TRef sp)
364 365
365/* -- Convert TValue to C type (store) ------------------------------------ */ 366/* -- Convert TValue to C type (store) ------------------------------------ */
366 367
367static TRef crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, TValue *sval) 368static TRef crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, cTValue *sval)
368{ 369{
369 CTState *cts = ctype_ctsG(J2G(J)); 370 CTState *cts = ctype_ctsG(J2G(J));
370 CTypeID sid = CTID_P_VOID; 371 CTypeID sid = CTID_P_VOID;
@@ -747,29 +748,88 @@ static TRef crec_call_args(jit_State *J, RecordFFData *rd,
747 CTState *cts, CType *ct) 748 CTState *cts, CType *ct)
748{ 749{
749 TRef args[CCI_NARGS_MAX]; 750 TRef args[CCI_NARGS_MAX];
751 CTypeID fid;
750 MSize i, n; 752 MSize i, n;
751 TRef tr; 753 TRef tr, *base;
754 cTValue *o;
755#if LJ_TARGET_X86
756#if LJ_ABI_WIN
757 TRef *arg0 = NULL, *arg1 = NULL;
758#endif
759 int ngpr = 0;
760 if (ctype_cconv(ct->info) == CTCC_THISCALL)
761 ngpr = 1;
762 else if (ctype_cconv(ct->info) == CTCC_FASTCALL)
763 ngpr = 2;
764#endif
765
766 /* Skip initial attributes. */
767 fid = ct->sib;
768 while (fid) {
769 CType *ctf = ctype_get(cts, fid);
770 if (!ctype_isattrib(ctf->info)) break;
771 fid = ctf->sib;
772 }
752 args[0] = TREF_NIL; 773 args[0] = TREF_NIL;
753 for (n = 0; J->base[n+1]; n++) { 774 for (n = 0, base = J->base+1, o = rd->argv+1; *base; n++, base++, o++) {
775 CTypeID did;
754 CType *d; 776 CType *d;
755 do { 777
756 if (!ct->sib || n >= CCI_NARGS_MAX) 778 if (n >= CCI_NARGS_MAX)
757 lj_trace_err(J, LJ_TRERR_NYICALL);
758 ct = ctype_get(cts, ct->sib);
759 } while (ctype_isattrib(ct->info));
760 if (!ctype_isfield(ct->info))
761 lj_trace_err(J, LJ_TRERR_NYICALL); 779 lj_trace_err(J, LJ_TRERR_NYICALL);
762 d = ctype_rawchild(cts, ct); 780
781 if (fid) { /* Get argument type from field. */
782 CType *ctf = ctype_get(cts, fid);
783 fid = ctf->sib;
784 lua_assert(ctype_isfield(ctf->info));
785 did = ctype_cid(ctf->info);
786 } else {
787 if (!(ct->info & CTF_VARARG))
788 lj_trace_err(J, LJ_TRERR_NYICALL); /* Too many arguments. */
789 did = lj_ccall_ctid_vararg(cts, o); /* Infer vararg type. */
790 }
791 d = ctype_raw(cts, did);
763 if (!(ctype_isnum(d->info) || ctype_isptr(d->info) || 792 if (!(ctype_isnum(d->info) || ctype_isptr(d->info) ||
764 ctype_isenum(d->info))) 793 ctype_isenum(d->info)))
765 lj_trace_err(J, LJ_TRERR_NYICALL); 794 lj_trace_err(J, LJ_TRERR_NYICALL);
766 tr = crec_ct_tv(J, d, 0, J->base[n+1], &rd->argv[n+1]); 795 tr = crec_ct_tv(J, d, 0, *base, o);
767 if (ctype_isinteger_or_bool(d->info) && d->size < 4) { 796 if (ctype_isinteger_or_bool(d->info)) {
768 if ((d->info & CTF_UNSIGNED)) 797 if (d->size < 4) {
769 tr = emitconv(tr, IRT_INT, d->size==1 ? IRT_U8 : IRT_U16, 0); 798 if ((d->info & CTF_UNSIGNED))
770 else 799 tr = emitconv(tr, IRT_INT, d->size==1 ? IRT_U8 : IRT_U16, 0);
771 tr = emitconv(tr, IRT_INT, d->size==1 ? IRT_I8 : IRT_I16, IRCONV_SEXT); 800 else
801 tr = emitconv(tr, IRT_INT, d->size==1 ? IRT_I8 : IRT_I16,IRCONV_SEXT);
802 }
772 } 803 }
804#if LJ_TARGET_X86
805 /* 64 bit args must not end up in registers for fastcall/thiscall. */
806#if LJ_ABI_WIN
807 if (!ctype_isfp(d->info)) {
808 /* Sigh, the Windows/x86 ABI allows reordering across 64 bit args. */
809 if (tref_typerange(tr, IRT_I64, IRT_U64)) {
810 if (ngpr) {
811 arg0 = &args[n]; args[n++] = TREF_NIL; ngpr--;
812 if (ngpr) {
813 arg1 = &args[n]; args[n++] = TREF_NIL; ngpr--;
814 }
815 }
816 } else {
817 if (arg0) { *arg0 = tr; arg0 = NULL; n--; continue; }
818 if (arg1) { *arg1 = tr; arg1 = NULL; n--; continue; }
819 if (ngpr) ngpr--;
820 }
821 }
822#else
823 if (!ctype_isfp(d->info) && ngpr) {
824 if (tref_typerange(tr, IRT_I64, IRT_U64)) {
825 /* No reordering for other x86 ABIs. Simply add alignment args. */
826 do { args[n++] = TREF_NIL; } while (--ngpr);
827 } else {
828 ngpr--;
829 }
830 }
831#endif
832#endif
773 args[n] = tr; 833 args[n] = tr;
774 } 834 }
775 tr = args[0]; 835 tr = args[0];
@@ -801,12 +861,15 @@ static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd)
801 } 861 }
802 if (!(ctype_isnum(ctr->info) || ctype_isptr(ctr->info) || 862 if (!(ctype_isnum(ctr->info) || ctype_isptr(ctr->info) ||
803 ctype_isvoid(ctr->info)) || 863 ctype_isvoid(ctr->info)) ||
804 ctype_isbool(ctr->info) || (ct->info & CTF_VARARG) || 864 ctype_isbool(ctr->info) || t == IRT_CDATA)
865 lj_trace_err(J, LJ_TRERR_NYICALL);
866 if ((ct->info & CTF_VARARG)
805#if LJ_TARGET_X86 867#if LJ_TARGET_X86
806 ctype_cconv(ct->info) != CTCC_CDECL || 868 || ctype_cconv(ct->info) != CTCC_CDECL
807#endif 869#endif
808 t == IRT_CDATA) 870 )
809 lj_trace_err(J, LJ_TRERR_NYICALL); 871 func = emitir(IRT(IR_CARG, IRT_NIL), func,
872 lj_ir_kint(J, ctype_typeid(cts, ct)));
810 tr = emitir(IRT(IR_CALLXS, t), crec_call_args(J, rd, cts, ct), func); 873 tr = emitir(IRT(IR_CALLXS, t), crec_call_args(J, rd, cts, ct), func);
811 if (t == IRT_FLOAT || t == IRT_U32) { 874 if (t == IRT_FLOAT || t == IRT_U32) {
812 tr = emitconv(tr, IRT_NUM, t, 0); 875 tr = emitconv(tr, IRT_NUM, t, 0);