diff options
Diffstat (limited to 'src/lj_crecord.c')
-rw-r--r-- | src/lj_crecord.c | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/src/lj_crecord.c b/src/lj_crecord.c index 9457b519..313bee81 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "lj_trace.h" | 27 | #include "lj_trace.h" |
28 | #include "lj_record.h" | 28 | #include "lj_record.h" |
29 | #include "lj_ffrecord.h" | 29 | #include "lj_ffrecord.h" |
30 | #include "lj_snap.h" | ||
30 | #include "lj_crecord.h" | 31 | #include "lj_crecord.h" |
31 | #include "lj_dispatch.h" | 32 | #include "lj_dispatch.h" |
32 | 33 | ||
@@ -839,6 +840,26 @@ static TRef crec_call_args(jit_State *J, RecordFFData *rd, | |||
839 | return tr; | 840 | return tr; |
840 | } | 841 | } |
841 | 842 | ||
843 | /* Create a snapshot for the caller, simulating a 'false' return value. */ | ||
844 | static void crec_snap_caller(jit_State *J) | ||
845 | { | ||
846 | lua_State *L = J->L; | ||
847 | TValue *base = L->base, *top = L->top; | ||
848 | const BCIns *pc = J->pc; | ||
849 | TRef ftr = J->base[-1]; | ||
850 | ptrdiff_t delta; | ||
851 | if (!frame_islua(base-1)) | ||
852 | lj_trace_err(J, LJ_TRERR_NYICALL); | ||
853 | J->pc = frame_pc(base-1); delta = 1+bc_a(J->pc[-1]); | ||
854 | L->top = base; L->base = base - delta; | ||
855 | J->base[-1] = TREF_FALSE; | ||
856 | J->base -= delta; J->baseslot -= delta; J->maxslot = delta; J->framedepth--; | ||
857 | lj_snap_add(J); | ||
858 | L->base = base; L->top = top; | ||
859 | J->framedepth++; J->base += delta; J->baseslot += delta; J->maxslot = 1; | ||
860 | J->base[-1] = ftr; J->pc = pc; | ||
861 | } | ||
862 | |||
842 | /* Record function call. */ | 863 | /* Record function call. */ |
843 | static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd) | 864 | static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd) |
844 | { | 865 | { |
@@ -867,8 +888,7 @@ static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd) | |||
867 | ctr = ctype_child(cts, ctr); | 888 | ctr = ctype_child(cts, ctr); |
868 | } | 889 | } |
869 | if (!(ctype_isnum(ctr->info) || ctype_isptr(ctr->info) || | 890 | if (!(ctype_isnum(ctr->info) || ctype_isptr(ctr->info) || |
870 | ctype_isvoid(ctr->info)) || | 891 | ctype_isvoid(ctr->info)) || t == IRT_CDATA) |
871 | ctype_isbool(ctr->info) || t == IRT_CDATA) | ||
872 | lj_trace_err(J, LJ_TRERR_NYICALL); | 892 | lj_trace_err(J, LJ_TRERR_NYICALL); |
873 | if ((ct->info & CTF_VARARG) | 893 | if ((ct->info & CTF_VARARG) |
874 | #if LJ_TARGET_X86 | 894 | #if LJ_TARGET_X86 |
@@ -878,7 +898,12 @@ static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd) | |||
878 | func = emitir(IRT(IR_CARG, IRT_NIL), func, | 898 | func = emitir(IRT(IR_CARG, IRT_NIL), func, |
879 | lj_ir_kint(J, ctype_typeid(cts, ct))); | 899 | lj_ir_kint(J, ctype_typeid(cts, ct))); |
880 | tr = emitir(IRT(IR_CALLXS, t), crec_call_args(J, rd, cts, ct), func); | 900 | tr = emitir(IRT(IR_CALLXS, t), crec_call_args(J, rd, cts, ct), func); |
881 | if (t == IRT_FLOAT || t == IRT_U32) { | 901 | if (ctype_isbool(ctr->info)) { |
902 | crec_snap_caller(J); | ||
903 | lj_ir_set(J, IRTGI(IR_NE), tr, lj_ir_kint(J, 0)); | ||
904 | J->postproc = LJ_POST_FIXGUARDSNAP; | ||
905 | tr = TREF_TRUE; | ||
906 | } else if (t == IRT_FLOAT || t == IRT_U32) { | ||
882 | tr = emitconv(tr, IRT_NUM, t, 0); | 907 | tr = emitconv(tr, IRT_NUM, t, 0); |
883 | } else if (t == IRT_I8 || t == IRT_I16) { | 908 | } else if (t == IRT_I8 || t == IRT_I16) { |
884 | tr = emitconv(tr, IRT_INT, t, IRCONV_SEXT); | 909 | tr = emitconv(tr, IRT_INT, t, IRCONV_SEXT); |