diff options
author | Mike Pall <mike> | 2011-01-03 01:30:58 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2011-01-03 01:59:26 +0100 |
commit | 3291bb62e0052df598a7fcf4138ae3973c08982e (patch) | |
tree | abb269e45af25ee66820a69d483e591949a9b364 /src | |
parent | b2c74c52cc9e850d53f2f7b06ffe2b096884f77a (diff) | |
download | luajit-3291bb62e0052df598a7fcf4138ae3973c08982e.tar.gz luajit-3291bb62e0052df598a7fcf4138ae3973c08982e.tar.bz2 luajit-3291bb62e0052df598a7fcf4138ae3973c08982e.zip |
FFI: Record pointer arithmetic.
Diffstat (limited to 'src')
-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 |