diff options
| -rw-r--r-- | src/lib_ffi.c | 14 | ||||
| -rw-r--r-- | src/lj_crecord.c | 106 | ||||
| -rw-r--r-- | src/lj_crecord.h | 1 |
3 files changed, 114 insertions, 7 deletions
diff --git a/src/lib_ffi.c b/src/lib_ffi.c index 414f1d2f..44ece1e7 100644 --- a/src/lib_ffi.c +++ b/src/lib_ffi.c | |||
| @@ -291,37 +291,37 @@ static int ffi_arith(lua_State *L) | |||
| 291 | return 1; | 291 | return 1; |
| 292 | } | 292 | } |
| 293 | 293 | ||
| 294 | LJLIB_CF(ffi_meta___add) | 294 | LJLIB_CF(ffi_meta___add) LJLIB_REC(cdata_arith MM_add) |
| 295 | { | 295 | { |
| 296 | return ffi_arith(L); | 296 | return ffi_arith(L); |
| 297 | } | 297 | } |
| 298 | 298 | ||
| 299 | LJLIB_CF(ffi_meta___sub) | 299 | LJLIB_CF(ffi_meta___sub) LJLIB_REC(cdata_arith MM_sub) |
| 300 | { | 300 | { |
| 301 | return ffi_arith(L); | 301 | return ffi_arith(L); |
| 302 | } | 302 | } |
| 303 | 303 | ||
| 304 | LJLIB_CF(ffi_meta___mul) | 304 | LJLIB_CF(ffi_meta___mul) LJLIB_REC(cdata_arith MM_mul) |
| 305 | { | 305 | { |
| 306 | return ffi_arith(L); | 306 | return ffi_arith(L); |
| 307 | } | 307 | } |
| 308 | 308 | ||
| 309 | LJLIB_CF(ffi_meta___div) | 309 | LJLIB_CF(ffi_meta___div) LJLIB_REC(cdata_arith MM_div) |
| 310 | { | 310 | { |
| 311 | return ffi_arith(L); | 311 | return ffi_arith(L); |
| 312 | } | 312 | } |
| 313 | 313 | ||
| 314 | LJLIB_CF(ffi_meta___mod) | 314 | LJLIB_CF(ffi_meta___mod) LJLIB_REC(cdata_arith MM_mod) |
| 315 | { | 315 | { |
| 316 | return ffi_arith(L); | 316 | return ffi_arith(L); |
| 317 | } | 317 | } |
| 318 | 318 | ||
| 319 | LJLIB_CF(ffi_meta___pow) | 319 | LJLIB_CF(ffi_meta___pow) LJLIB_REC(cdata_arith MM_pow) |
| 320 | { | 320 | { |
| 321 | return ffi_arith(L); | 321 | return ffi_arith(L); |
| 322 | } | 322 | } |
| 323 | 323 | ||
| 324 | LJLIB_CF(ffi_meta___unm) | 324 | LJLIB_CF(ffi_meta___unm) LJLIB_REC(cdata_arith MM_unm) |
| 325 | { | 325 | { |
| 326 | return ffi_arith(L); | 326 | return ffi_arith(L); |
| 327 | } | 327 | } |
diff --git a/src/lj_crecord.c b/src/lj_crecord.c index b474a6b9..81d53dfc 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c | |||
| @@ -562,6 +562,112 @@ void LJ_FASTCALL recff_cdata_call(jit_State *J, RecordFFData *rd) | |||
| 562 | } /* else: Interpreter will throw. */ | 562 | } /* else: Interpreter will throw. */ |
| 563 | } | 563 | } |
| 564 | 564 | ||
| 565 | static TRef crec_arith_int64(jit_State *J, TRef *sp, CType **s, MMS mm) | ||
| 566 | { | ||
| 567 | UNUSED(J); UNUSED(sp); UNUSED(s); UNUSED(mm); | ||
| 568 | return 0; /* NYI: 64 bit integer arithmetic. */ | ||
| 569 | } | ||
| 570 | |||
| 571 | static TRef crec_arith_ptr(jit_State *J, TRef *sp, CType **s, MMS mm) | ||
| 572 | { | ||
| 573 | CTState *cts = ctype_ctsG(J2G(J)); | ||
| 574 | CType *ctp = s[0]; | ||
| 575 | CTSize sz; | ||
| 576 | if (!(mm == MM_add || mm == MM_sub)) | ||
| 577 | return 0; | ||
| 578 | if (ctype_ispointer(ctp->info)) { | ||
| 579 | sz = lj_ctype_size(cts, ctype_cid(ctp->info)); | ||
| 580 | if (mm == MM_sub && ctype_ispointer(s[1]->info)) { | ||
| 581 | /* Pointer difference. */ | ||
| 582 | TRef tr; | ||
| 583 | if (sz == 0 || (sz & (sz-1)) != 0) | ||
| 584 | return 0; /* NYI: integer division. */ | ||
| 585 | tr = emitir(IRT(IR_SUB, IRT_PTR), sp[0], sp[1]); | ||
| 586 | tr = emitir(IRT(IR_BSAR, IRT_INTP), tr, lj_ir_kint(J, lj_fls(sz))); | ||
| 587 | #if LJ_64 | ||
| 588 | tr = emitconv(tr, IRT_NUM, IRT_INTP, 0); | ||
| 589 | #endif | ||
| 590 | return tr; | ||
| 591 | } | ||
| 592 | if (!ctype_isnum(s[1]->info)) return 0; | ||
| 593 | } else if (mm == MM_add && | ||
| 594 | ctype_isnum(ctp->info) && ctype_ispointer(s[1]->info)) { | ||
| 595 | TRef tr = sp[0]; sp[0] = sp[1]; sp[1] = tr; /* Swap pointer and index. */ | ||
| 596 | ctp = s[1]; | ||
| 597 | sz = lj_ctype_size(cts, ctype_cid(ctp->info)); | ||
| 598 | } else { | ||
| 599 | return 0; | ||
| 600 | } | ||
| 601 | { | ||
| 602 | TRef tr = sp[1]; | ||
| 603 | IRType t = tref_type(tr); | ||
| 604 | CTypeID id; | ||
| 605 | #if LJ_64 | ||
| 606 | if (t == IRT_NUM || t == IRT_FLOAT) | ||
| 607 | tr = emitconv(tr, IRT_INTP, t, IRCONV_TRUNC|IRCONV_ANY); | ||
| 608 | else if (!(t == IRT_I64 || t == IRT_U64)) | ||
| 609 | tr = emitconv(tr, IRT_INTP, IRT_INT, | ||
| 610 | ((t - IRT_I8) & 1) ? 0 : IRCONV_SEXT); | ||
| 611 | #else | ||
| 612 | if (!tref_typerange(sp[1], IRT_I8, IRT_U32)) | ||
| 613 | tr = emitconv(tr, IRT_INTP, t, | ||
| 614 | (t == IRT_NUM || t == IRT_FLOAT) ? | ||
| 615 | IRCONV_TRUNC|IRCONV_ANY : 0); | ||
| 616 | #endif | ||
| 617 | tr = emitir(IRT(IR_MUL, IRT_INTP), tr, lj_ir_kintp(J, sz)); | ||
| 618 | tr = emitir(IRT(IR_ADD, IRT_PTR), sp[0], tr); | ||
| 619 | id = lj_ctype_intern(cts, CTINFO(CT_PTR, CTALIGN_PTR|ctype_cid(ctp->info)), | ||
| 620 | CTSIZE_PTR); | ||
| 621 | return emitir(IRTG(IR_CNEWP, IRT_CDATA), lj_ir_kint(J, id), tr); | ||
| 622 | } | ||
| 623 | } | ||
| 624 | |||
| 625 | void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd) | ||
| 626 | { | ||
| 627 | CTState *cts = ctype_ctsG(J2G(J)); | ||
| 628 | TRef sp[2]; | ||
| 629 | CType *s[2]; | ||
| 630 | MSize i; | ||
| 631 | for (i = 0; i < 2; i++) { | ||
| 632 | TRef tr = J->base[i]; | ||
| 633 | CType *ct = ctype_get(cts, CTID_DOUBLE); | ||
| 634 | if (tref_iscdata(tr)) { | ||
| 635 | CTypeID id = argv2cdata(J, tr, &rd->argv[i])->typeid; | ||
| 636 | ct = ctype_raw(cts, id); | ||
| 637 | if (ctype_isptr(ct->info)) { /* Resolve pointer or reference. */ | ||
| 638 | IRType t = (LJ_64 && ct->size == 8) ? IRT_P64 : IRT_P32; | ||
| 639 | if (ctype_isref(ct->info)) ct = ctype_rawchild(cts, ct); | ||
| 640 | tr = emitir(IRT(IR_FLOAD, t), tr, IRFL_CDATA_PTR); | ||
| 641 | } else { | ||
| 642 | tr = emitir(IRT(IR_ADD, IRT_PTR), tr, lj_ir_kintp(J, sizeof(GCcdata))); | ||
| 643 | } | ||
| 644 | if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct); | ||
| 645 | if (ctype_isnum(ct->info)) { | ||
| 646 | IRType t = crec_ct2irt(ct); | ||
| 647 | if (t == IRT_CDATA) goto err_type; | ||
| 648 | tr = emitir(IRT(IR_XLOAD, t), tr, 0); | ||
| 649 | } else if (!(ctype_isptr(ct->info) || ctype_isrefarray(ct->info))) { | ||
| 650 | goto err_type; | ||
| 651 | } | ||
| 652 | } else if (tref_isinteger(tr)) { | ||
| 653 | ct = ctype_get(cts, CTID_INT32); | ||
| 654 | } else if (!tref_isnum(tr)) { | ||
| 655 | goto err_type; | ||
| 656 | } | ||
| 657 | s[i] = ct; | ||
| 658 | sp[i] = tr; | ||
| 659 | } | ||
| 660 | { | ||
| 661 | TRef tr; | ||
| 662 | if (!(tr = crec_arith_int64(J, sp, s, (MMS)rd->data)) && | ||
| 663 | !(tr = crec_arith_ptr(J, sp, s, (MMS)rd->data))) { | ||
| 664 | err_type: | ||
| 665 | lj_trace_err(J, LJ_TRERR_BADTYPE); | ||
| 666 | } | ||
| 667 | J->base[0] = tr; | ||
| 668 | } | ||
| 669 | } | ||
| 670 | |||
| 565 | /* -- FFI library functions ----------------------------------------------- */ | 671 | /* -- FFI library functions ----------------------------------------------- */ |
| 566 | 672 | ||
| 567 | void LJ_FASTCALL recff_ffi_new(jit_State *J, RecordFFData *rd) | 673 | void LJ_FASTCALL recff_ffi_new(jit_State *J, RecordFFData *rd) |
diff --git a/src/lj_crecord.h b/src/lj_crecord.h index 05ef6110..f0b7045b 100644 --- a/src/lj_crecord.h +++ b/src/lj_crecord.h | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #if LJ_HASJIT && LJ_HASFFI | 13 | #if LJ_HASJIT && LJ_HASFFI |
| 14 | LJ_FUNC void LJ_FASTCALL recff_cdata_index(jit_State *J, RecordFFData *rd); | 14 | LJ_FUNC void LJ_FASTCALL recff_cdata_index(jit_State *J, RecordFFData *rd); |
| 15 | LJ_FUNC void LJ_FASTCALL recff_cdata_call(jit_State *J, RecordFFData *rd); | 15 | LJ_FUNC void LJ_FASTCALL recff_cdata_call(jit_State *J, RecordFFData *rd); |
| 16 | LJ_FUNC void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd); | ||
| 16 | LJ_FUNC void LJ_FASTCALL recff_ffi_new(jit_State *J, RecordFFData *rd); | 17 | LJ_FUNC void LJ_FASTCALL recff_ffi_new(jit_State *J, RecordFFData *rd); |
| 17 | LJ_FUNC void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd); | 18 | LJ_FUNC void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd); |
| 18 | #else | 19 | #else |
