diff options
author | Mike Pall <mike> | 2013-03-13 22:44:01 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2013-03-14 06:03:18 +0100 |
commit | a98aede37772797b4471e1a094452051edff5862 (patch) | |
tree | 6e8c86838e359b899ffa0021bf3149087caa71da | |
parent | 3e8f5ac7186ecac63e17688b9ba6e72697143dbb (diff) | |
download | luajit-a98aede37772797b4471e1a094452051edff5862.tar.gz luajit-a98aede37772797b4471e1a094452051edff5862.tar.bz2 luajit-a98aede37772797b4471e1a094452051edff5862.zip |
FFI: Add 64 bit bitwise operations.
-rw-r--r-- | doc/ext_ffi_semantics.html | 17 | ||||
-rw-r--r-- | doc/extensions.html | 3 | ||||
-rw-r--r-- | src/Makefile.dep | 9 | ||||
-rw-r--r-- | src/lib_bit.c | 98 | ||||
-rw-r--r-- | src/lj_carith.c | 76 | ||||
-rw-r--r-- | src/lj_carith.h | 10 | ||||
-rw-r--r-- | src/lj_crecord.c | 95 | ||||
-rw-r--r-- | src/lj_crecord.h | 6 | ||||
-rw-r--r-- | src/lj_ffrecord.c | 66 | ||||
-rw-r--r-- | src/lj_ircall.h | 7 | ||||
-rw-r--r-- | src/lj_opt_fold.c | 41 | ||||
-rw-r--r-- | src/lj_opt_split.c | 127 |
12 files changed, 495 insertions, 60 deletions
diff --git a/doc/ext_ffi_semantics.html b/doc/ext_ffi_semantics.html index 03229012..15c9a6db 100644 --- a/doc/ext_ffi_semantics.html +++ b/doc/ext_ffi_semantics.html | |||
@@ -730,6 +730,22 @@ You'll have to explicitly convert a 64 bit integer to a Lua | |||
730 | number (e.g. for regular floating-point calculations) with | 730 | number (e.g. for regular floating-point calculations) with |
731 | <tt>tonumber()</tt>. But note this may incur a precision loss.</li> | 731 | <tt>tonumber()</tt>. But note this may incur a precision loss.</li> |
732 | 732 | ||
733 | <li><b>64 bit bitwise operations</b>: the rules for 64 bit | ||
734 | arithmetic operators apply analogously.<br> | ||
735 | |||
736 | Unlike the other <tt>bit.*</tt> operations, <tt>bit.tobit()</tt> | ||
737 | converts a cdata number via <tt>int64_t</tt> to <tt>int32_t</tt> and | ||
738 | returns a Lua number.<br> | ||
739 | |||
740 | For <tt>bit.band()</tt>, <tt>bit.bor()</tt> and <tt>bit.bxor()</tt>, the | ||
741 | conversion to <tt>int64_t</tt> or <tt>uint64_t</tt> applies to | ||
742 | <em>all</em> arguments, if <em>any</em> argument is a cdata number.<br> | ||
743 | |||
744 | For all other operations, only the first argument is used to determine | ||
745 | the output type. This implies that a cdata number as a shift count for | ||
746 | shifts and rotates is accepted, but that alone does <em>not</em> cause | ||
747 | a cdata number output. | ||
748 | |||
733 | </ul> | 749 | </ul> |
734 | 750 | ||
735 | <h3 id="cdata_comp">Comparisons of cdata objects</h3> | 751 | <h3 id="cdata_comp">Comparisons of cdata objects</h3> |
@@ -1222,7 +1238,6 @@ value.</li> | |||
1222 | Other missing features: | 1238 | Other missing features: |
1223 | </p> | 1239 | </p> |
1224 | <ul> | 1240 | <ul> |
1225 | <li>Bit operations for 64 bit types.</li> | ||
1226 | <li>Arithmetic for <tt>complex</tt> numbers.</li> | 1241 | <li>Arithmetic for <tt>complex</tt> numbers.</li> |
1227 | <li>Passing structs by value to vararg C functions.</li> | 1242 | <li>Passing structs by value to vararg C functions.</li> |
1228 | <li><a href="extensions.html#exceptions">C++ exception interoperability</a> | 1243 | <li><a href="extensions.html#exceptions">C++ exception interoperability</a> |
diff --git a/doc/extensions.html b/doc/extensions.html index 2bfcc76c..f288fbde 100644 --- a/doc/extensions.html +++ b/doc/extensions.html | |||
@@ -113,6 +113,9 @@ bit.lshift bit.rshift bit.arshift bit.rol bit.ror bit.bswap | |||
113 | This module is a LuaJIT built-in — you don't need to download or | 113 | This module is a LuaJIT built-in — you don't need to download or |
114 | install Lua BitOp. The Lua BitOp site has full documentation for all | 114 | install Lua BitOp. The Lua BitOp site has full documentation for all |
115 | <a href="http://bitop.luajit.org/api.html"><span class="ext">»</span> Lua BitOp API functions</a>. | 115 | <a href="http://bitop.luajit.org/api.html"><span class="ext">»</span> Lua BitOp API functions</a>. |
116 | The FFI adds support for | ||
117 | <a href="ext_ffi_semantics.html#cdata_arith">64 bit bitwise operations<a>, | ||
118 | using the same API functions. | ||
116 | </p> | 119 | </p> |
117 | <p> | 120 | <p> |
118 | Please make sure to <tt>require</tt> the module before using any of | 121 | Please make sure to <tt>require</tt> the module before using any of |
diff --git a/src/Makefile.dep b/src/Makefile.dep index f841767b..902d2912 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep | |||
@@ -7,7 +7,8 @@ lib_base.o: lib_base.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ | |||
7 | lj_ffdef.h lj_dispatch.h lj_jit.h lj_ir.h lj_char.h lj_strscan.h \ | 7 | lj_ffdef.h lj_dispatch.h lj_jit.h lj_ir.h lj_char.h lj_strscan.h \ |
8 | lj_lib.h lj_libdef.h | 8 | lj_lib.h lj_libdef.h |
9 | lib_bit.o: lib_bit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ | 9 | lib_bit.o: lib_bit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ |
10 | lj_arch.h lj_err.h lj_errmsg.h lj_str.h lj_lib.h lj_libdef.h | 10 | lj_arch.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_gc.h lj_cdata.h \ |
11 | lj_cconv.h lj_carith.h lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h | ||
11 | lib_debug.o: lib_debug.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ | 12 | lib_debug.o: lib_debug.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ |
12 | lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_lib.h \ | 13 | lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_lib.h \ |
13 | lj_libdef.h | 14 | lj_libdef.h |
@@ -17,7 +18,7 @@ lib_ffi.o: lib_ffi.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ | |||
17 | lj_ccallback.h lj_clib.h lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h | 18 | lj_ccallback.h lj_clib.h lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h |
18 | lib_init.o: lib_init.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h | 19 | lib_init.o: lib_init.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h |
19 | lib_io.o: lib_io.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ | 20 | lib_io.o: lib_io.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ |
20 | lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_state.h \ | 21 | lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_state.h \ |
21 | lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h | 22 | lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h |
22 | lib_jit.o: lib_jit.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h \ | 23 | lib_jit.o: lib_jit.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h \ |
23 | lj_obj.h lj_def.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h \ | 24 | lj_obj.h lj_def.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h \ |
@@ -58,8 +59,8 @@ lj_bcwrite.o: lj_bcwrite.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | |||
58 | lj_buf.o: lj_buf.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | 59 | lj_buf.o: lj_buf.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ |
59 | lj_err.h lj_errmsg.h lj_buf.h lj_str.h | 60 | lj_err.h lj_errmsg.h lj_buf.h lj_str.h |
60 | lj_carith.o: lj_carith.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 61 | lj_carith.o: lj_carith.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
61 | lj_gc.h lj_err.h lj_errmsg.h lj_tab.h lj_meta.h lj_ctype.h lj_cconv.h \ | 62 | lj_gc.h lj_err.h lj_errmsg.h lj_tab.h lj_meta.h lj_ir.h lj_ctype.h \ |
62 | lj_cdata.h lj_carith.h | 63 | lj_cconv.h lj_cdata.h lj_carith.h lj_strscan.h |
63 | lj_ccall.o: lj_ccall.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 64 | lj_ccall.o: lj_ccall.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
64 | lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h lj_cconv.h \ | 65 | lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h lj_cconv.h \ |
65 | lj_cdata.h lj_ccall.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_bc.h \ | 66 | lj_cdata.h lj_ccall.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_bc.h \ |
diff --git a/src/lib_bit.c b/src/lib_bit.c index 93fead92..85821b81 100644 --- a/src/lib_bit.c +++ b/src/lib_bit.c | |||
@@ -13,25 +13,82 @@ | |||
13 | #include "lj_obj.h" | 13 | #include "lj_obj.h" |
14 | #include "lj_err.h" | 14 | #include "lj_err.h" |
15 | #include "lj_str.h" | 15 | #include "lj_str.h" |
16 | #if LJ_HASFFI | ||
17 | #include "lj_ctype.h" | ||
18 | #include "lj_cdata.h" | ||
19 | #include "lj_cconv.h" | ||
20 | #include "lj_carith.h" | ||
21 | #endif | ||
22 | #include "lj_ff.h" | ||
16 | #include "lj_lib.h" | 23 | #include "lj_lib.h" |
17 | 24 | ||
18 | /* ------------------------------------------------------------------------ */ | 25 | /* ------------------------------------------------------------------------ */ |
19 | 26 | ||
20 | #define LJLIB_MODULE_bit | 27 | #define LJLIB_MODULE_bit |
21 | 28 | ||
22 | LJLIB_ASM(bit_tobit) LJLIB_REC(bit_unary IR_TOBIT) | 29 | #if LJ_HASFFI |
30 | static int bit_result64(lua_State *L, CTypeID id, uint64_t x) | ||
23 | { | 31 | { |
32 | GCcdata *cd = lj_cdata_new_(L, id, 8); | ||
33 | *(uint64_t *)cdataptr(cd) = x; | ||
34 | setcdataV(L, L->base-1, cd); | ||
35 | return FFH_RES(1); | ||
36 | } | ||
37 | #endif | ||
38 | |||
39 | LJLIB_ASM(bit_tobit) LJLIB_REC(bit_tobit) | ||
40 | { | ||
41 | #if LJ_HASFFI | ||
42 | CTypeID id = 0; | ||
43 | setintV(L->base-1, (int32_t)lj_carith_check64(L, 1, &id)); | ||
44 | return FFH_RES(1); | ||
45 | #else | ||
46 | lj_lib_checknumber(L, 1); | ||
47 | return FFH_RETRY; | ||
48 | #endif | ||
49 | } | ||
50 | |||
51 | LJLIB_ASM(bit_bnot) LJLIB_REC(bit_unary IR_BNOT) | ||
52 | { | ||
53 | #if LJ_HASFFI | ||
54 | CTypeID id = 0; | ||
55 | uint64_t x = lj_carith_check64(L, 1, &id); | ||
56 | return id ? bit_result64(L, id, ~x) : FFH_RETRY; | ||
57 | #else | ||
58 | lj_lib_checknumber(L, 1); | ||
59 | return FFH_RETRY; | ||
60 | #endif | ||
61 | } | ||
62 | |||
63 | LJLIB_ASM(bit_bswap) LJLIB_REC(bit_unary IR_BSWAP) | ||
64 | { | ||
65 | #if LJ_HASFFI | ||
66 | CTypeID id = 0; | ||
67 | uint64_t x = lj_carith_check64(L, 1, &id); | ||
68 | return id ? bit_result64(L, id, lj_bswap64(x)) : FFH_RETRY; | ||
69 | #else | ||
24 | lj_lib_checknumber(L, 1); | 70 | lj_lib_checknumber(L, 1); |
25 | return FFH_RETRY; | 71 | return FFH_RETRY; |
72 | #endif | ||
26 | } | 73 | } |
27 | LJLIB_ASM_(bit_bnot) LJLIB_REC(bit_unary IR_BNOT) | ||
28 | LJLIB_ASM_(bit_bswap) LJLIB_REC(bit_unary IR_BSWAP) | ||
29 | 74 | ||
30 | LJLIB_ASM(bit_lshift) LJLIB_REC(bit_shift IR_BSHL) | 75 | LJLIB_ASM(bit_lshift) LJLIB_REC(bit_shift IR_BSHL) |
31 | { | 76 | { |
77 | #if LJ_HASFFI | ||
78 | CTypeID id = 0, id2 = 0; | ||
79 | uint64_t x = lj_carith_check64(L, 1, &id); | ||
80 | int32_t sh = (int32_t)lj_carith_check64(L, 2, &id2); | ||
81 | if (id) { | ||
82 | x = lj_carith_shift64(x, sh, curr_func(L)->c.ffid - (int)FF_bit_lshift); | ||
83 | return bit_result64(L, id, x); | ||
84 | } | ||
85 | if (id2) setintV(L->base+1, sh); | ||
86 | return FFH_RETRY; | ||
87 | #else | ||
32 | lj_lib_checknumber(L, 1); | 88 | lj_lib_checknumber(L, 1); |
33 | lj_lib_checkbit(L, 2); | 89 | lj_lib_checkbit(L, 2); |
34 | return FFH_RETRY; | 90 | return FFH_RETRY; |
91 | #endif | ||
35 | } | 92 | } |
36 | LJLIB_ASM_(bit_rshift) LJLIB_REC(bit_shift IR_BSHR) | 93 | LJLIB_ASM_(bit_rshift) LJLIB_REC(bit_shift IR_BSHR) |
37 | LJLIB_ASM_(bit_arshift) LJLIB_REC(bit_shift IR_BSAR) | 94 | LJLIB_ASM_(bit_arshift) LJLIB_REC(bit_shift IR_BSAR) |
@@ -40,9 +97,29 @@ LJLIB_ASM_(bit_ror) LJLIB_REC(bit_shift IR_BROR) | |||
40 | 97 | ||
41 | LJLIB_ASM(bit_band) LJLIB_REC(bit_nary IR_BAND) | 98 | LJLIB_ASM(bit_band) LJLIB_REC(bit_nary IR_BAND) |
42 | { | 99 | { |
100 | #if LJ_HASFFI | ||
101 | CTypeID id = 0; | ||
102 | TValue *o = L->base, *top = L->top; | ||
103 | int i = 0; | ||
104 | do { lj_carith_check64(L, ++i, &id); } while (++o < top); | ||
105 | if (id) { | ||
106 | CTState *cts = ctype_cts(L); | ||
107 | CType *ct = ctype_get(cts, id); | ||
108 | int op = curr_func(L)->c.ffid - (int)FF_bit_bor; | ||
109 | uint64_t x, y = op >= 0 ? 0 : ~(uint64_t)0; | ||
110 | o = L->base; | ||
111 | do { | ||
112 | lj_cconv_ct_tv(cts, ct, (uint8_t *)&x, o, 0); | ||
113 | if (op < 0) y &= x; else if (op == 0) y |= x; else y ^= x; | ||
114 | } while (++o < top); | ||
115 | return bit_result64(L, id, y); | ||
116 | } | ||
117 | return FFH_RETRY; | ||
118 | #else | ||
43 | int i = 0; | 119 | int i = 0; |
44 | do { lj_lib_checknumber(L, ++i); } while (L->base+i < L->top); | 120 | do { lj_lib_checknumber(L, ++i); } while (L->base+i < L->top); |
45 | return FFH_RETRY; | 121 | return FFH_RETRY; |
122 | #endif | ||
46 | } | 123 | } |
47 | LJLIB_ASM_(bit_bor) LJLIB_REC(bit_nary IR_BOR) | 124 | LJLIB_ASM_(bit_bor) LJLIB_REC(bit_nary IR_BOR) |
48 | LJLIB_ASM_(bit_bxor) LJLIB_REC(bit_nary IR_BXOR) | 125 | LJLIB_ASM_(bit_bxor) LJLIB_REC(bit_nary IR_BXOR) |
@@ -51,12 +128,21 @@ LJLIB_ASM_(bit_bxor) LJLIB_REC(bit_nary IR_BXOR) | |||
51 | 128 | ||
52 | LJLIB_CF(bit_tohex) | 129 | LJLIB_CF(bit_tohex) |
53 | { | 130 | { |
131 | #if LJ_HASFFI | ||
132 | CTypeID id = 0, id2 = 0; | ||
133 | uint64_t b = lj_carith_check64(L, 1, &id); | ||
134 | int32_t i, dig = id ? 16 : 8; | ||
135 | int32_t n = L->base+1>=L->top ? dig : (int32_t)lj_carith_check64(L, 2, &id2); | ||
136 | char buf[16]; | ||
137 | #else | ||
54 | uint32_t b = (uint32_t)lj_lib_checkbit(L, 1); | 138 | uint32_t b = (uint32_t)lj_lib_checkbit(L, 1); |
55 | int32_t i, n = L->base+1 >= L->top ? 8 : lj_lib_checkbit(L, 2); | 139 | int32_t i, dig = 8; |
56 | const char *hexdigits = "0123456789abcdef"; | 140 | int32_t n = L->base+1>=L->top ? dig : lj_lib_checkbit(L, 2); |
57 | char buf[8]; | 141 | char buf[8]; |
142 | #endif | ||
143 | const char *hexdigits = "0123456789abcdef"; | ||
58 | if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; } | 144 | if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; } |
59 | if (n > 8) n = 8; | 145 | if (n > dig) n = dig; |
60 | for (i = n; --i >= 0; ) { buf[i] = hexdigits[b & 15]; b >>= 4; } | 146 | for (i = n; --i >= 0; ) { buf[i] = hexdigits[b & 15]; b >>= 4; } |
61 | lua_pushlstring(L, buf, (size_t)n); | 147 | lua_pushlstring(L, buf, (size_t)n); |
62 | return 1; | 148 | return 1; |
diff --git a/src/lj_carith.c b/src/lj_carith.c index 18708d66..9f3208a8 100644 --- a/src/lj_carith.c +++ b/src/lj_carith.c | |||
@@ -11,10 +11,12 @@ | |||
11 | #include "lj_err.h" | 11 | #include "lj_err.h" |
12 | #include "lj_tab.h" | 12 | #include "lj_tab.h" |
13 | #include "lj_meta.h" | 13 | #include "lj_meta.h" |
14 | #include "lj_ir.h" | ||
14 | #include "lj_ctype.h" | 15 | #include "lj_ctype.h" |
15 | #include "lj_cconv.h" | 16 | #include "lj_cconv.h" |
16 | #include "lj_cdata.h" | 17 | #include "lj_cdata.h" |
17 | #include "lj_carith.h" | 18 | #include "lj_carith.h" |
19 | #include "lj_strscan.h" | ||
18 | 20 | ||
19 | /* -- C data arithmetic --------------------------------------------------- */ | 21 | /* -- C data arithmetic --------------------------------------------------- */ |
20 | 22 | ||
@@ -270,6 +272,80 @@ int lj_carith_op(lua_State *L, MMS mm) | |||
270 | return lj_carith_meta(L, cts, &ca, mm); | 272 | return lj_carith_meta(L, cts, &ca, mm); |
271 | } | 273 | } |
272 | 274 | ||
275 | /* -- 64 bit bit operations helpers --------------------------------------- */ | ||
276 | |||
277 | #if LJ_64 | ||
278 | #define B64DEF(name) \ | ||
279 | static LJ_AINLINE uint64_t lj_carith_##name(uint64_t x, int32_t sh) | ||
280 | #else | ||
281 | /* Not inlined on 32 bit archs, since some of these are quite lengthy. */ | ||
282 | #define B64DEF(name) \ | ||
283 | uint64_t LJ_NOINLINE lj_carith_##name(uint64_t x, int32_t sh) | ||
284 | #endif | ||
285 | |||
286 | B64DEF(shl64) { return x << (sh&63); } | ||
287 | B64DEF(shr64) { return x >> (sh&63); } | ||
288 | B64DEF(sar64) { return (uint64_t)((int64_t)x >> (sh&63)); } | ||
289 | B64DEF(rol64) { return lj_rol(x, (sh&63)); } | ||
290 | B64DEF(ror64) { return lj_ror(x, (sh&63)); } | ||
291 | |||
292 | #undef B64DEF | ||
293 | |||
294 | uint64_t lj_carith_shift64(uint64_t x, int32_t sh, int op) | ||
295 | { | ||
296 | switch (op) { | ||
297 | case IR_BSHL-IR_BSHL: x = lj_carith_shl64(x, sh); break; | ||
298 | case IR_BSHR-IR_BSHL: x = lj_carith_shr64(x, sh); break; | ||
299 | case IR_BSAR-IR_BSHL: x = lj_carith_sar64(x, sh); break; | ||
300 | case IR_BROL-IR_BSHL: x = lj_carith_rol64(x, sh); break; | ||
301 | case IR_BROR-IR_BSHL: x = lj_carith_ror64(x, sh); break; | ||
302 | default: lua_assert(0); break; | ||
303 | } | ||
304 | return x; | ||
305 | } | ||
306 | |||
307 | /* Equivalent to lj_lib_checkbit(), but handles cdata. */ | ||
308 | uint64_t lj_carith_check64(lua_State *L, int narg, CTypeID *id) | ||
309 | { | ||
310 | TValue *o = L->base + narg-1; | ||
311 | if (o >= L->top) { | ||
312 | err: | ||
313 | lj_err_argt(L, narg, LUA_TNUMBER); | ||
314 | } else if (LJ_LIKELY(tvisnumber(o))) { | ||
315 | /* Handled below. */ | ||
316 | } else if (tviscdata(o)) { | ||
317 | CTState *cts = ctype_cts(L); | ||
318 | uint8_t *sp = (uint8_t *)cdataptr(cdataV(o)); | ||
319 | CTypeID sid = cdataV(o)->ctypeid; | ||
320 | CType *s = ctype_get(cts, sid); | ||
321 | uint64_t x; | ||
322 | if (ctype_isref(s->info)) { | ||
323 | sp = *(void **)sp; | ||
324 | sid = ctype_cid(s->info); | ||
325 | } | ||
326 | s = ctype_raw(cts, sid); | ||
327 | if (ctype_isenum(s->info)) s = ctype_child(cts, s); | ||
328 | if ((s->info & (CTMASK_NUM|CTF_BOOL|CTF_FP|CTF_UNSIGNED)) == | ||
329 | CTINFO(CT_NUM, CTF_UNSIGNED) && s->size == 8) | ||
330 | *id = CTID_UINT64; /* Use uint64_t, since it has the highest rank. */ | ||
331 | else if (!*id) | ||
332 | *id = CTID_INT64; /* Use int64_t, unless already set. */ | ||
333 | lj_cconv_ct_ct(cts, ctype_get(cts, *id), s, | ||
334 | (uint8_t *)&x, sp, CCF_ARG(narg)); | ||
335 | return x; | ||
336 | } else if (!(tvisstr(o) && lj_strscan_number(strV(o), o))) { | ||
337 | goto err; | ||
338 | } | ||
339 | if (LJ_LIKELY(tvisint(o))) { | ||
340 | return intV(o); | ||
341 | } else { | ||
342 | int32_t i = lj_num2bit(numV(o)); | ||
343 | if (LJ_DUALNUM) setintV(o, i); | ||
344 | return i; | ||
345 | } | ||
346 | } | ||
347 | |||
348 | |||
273 | /* -- 64 bit integer arithmetic helpers ----------------------------------- */ | 349 | /* -- 64 bit integer arithmetic helpers ----------------------------------- */ |
274 | 350 | ||
275 | #if LJ_32 && LJ_HASJIT | 351 | #if LJ_32 && LJ_HASJIT |
diff --git a/src/lj_carith.h b/src/lj_carith.h index ae17df00..b1a65d35 100644 --- a/src/lj_carith.h +++ b/src/lj_carith.h | |||
@@ -12,6 +12,16 @@ | |||
12 | 12 | ||
13 | LJ_FUNC int lj_carith_op(lua_State *L, MMS mm); | 13 | LJ_FUNC int lj_carith_op(lua_State *L, MMS mm); |
14 | 14 | ||
15 | #if LJ_32 | ||
16 | LJ_FUNC uint64_t lj_carith_shl64(uint64_t x, int32_t sh); | ||
17 | LJ_FUNC uint64_t lj_carith_shr64(uint64_t x, int32_t sh); | ||
18 | LJ_FUNC uint64_t lj_carith_sar64(uint64_t x, int32_t sh); | ||
19 | LJ_FUNC uint64_t lj_carith_rol64(uint64_t x, int32_t sh); | ||
20 | LJ_FUNC uint64_t lj_carith_ror64(uint64_t x, int32_t sh); | ||
21 | #endif | ||
22 | LJ_FUNC uint64_t lj_carith_shift64(uint64_t x, int32_t sh, int op); | ||
23 | LJ_FUNC uint64_t lj_carith_check64(lua_State *L, int narg, CTypeID *id); | ||
24 | |||
15 | #if LJ_32 && LJ_HASJIT | 25 | #if LJ_32 && LJ_HASJIT |
16 | LJ_FUNC int64_t lj_carith_mul64(int64_t x, int64_t k); | 26 | LJ_FUNC int64_t lj_carith_mul64(int64_t x, int64_t k); |
17 | #endif | 27 | #endif |
diff --git a/src/lj_crecord.c b/src/lj_crecord.c index a5d896eb..2bf0bc1d 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c | |||
@@ -1626,6 +1626,101 @@ void LJ_FASTCALL recff_ffi_gc(jit_State *J, RecordFFData *rd) | |||
1626 | crec_finalizer(J, J->base[0], &rd->argv[1]); | 1626 | crec_finalizer(J, J->base[0], &rd->argv[1]); |
1627 | } | 1627 | } |
1628 | 1628 | ||
1629 | /* -- 64 bit bit.* library functions -------------------------------------- */ | ||
1630 | |||
1631 | /* Determine bit operation type from argument type. */ | ||
1632 | static CTypeID crec_bit64_type(CTState *cts, cTValue *tv) | ||
1633 | { | ||
1634 | if (tviscdata(tv)) { | ||
1635 | CType *ct = lj_ctype_rawref(cts, cdataV(tv)->ctypeid); | ||
1636 | if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct); | ||
1637 | if ((ct->info & (CTMASK_NUM|CTF_BOOL|CTF_FP|CTF_UNSIGNED)) == | ||
1638 | CTINFO(CT_NUM, CTF_UNSIGNED) && ct->size == 8) | ||
1639 | return CTID_UINT64; /* Use uint64_t, since it has the highest rank. */ | ||
1640 | return CTID_INT64; /* Otherwise use int64_t. */ | ||
1641 | } | ||
1642 | return 0; /* Use regular 32 bit ops. */ | ||
1643 | } | ||
1644 | |||
1645 | void LJ_FASTCALL recff_bit64_tobit(jit_State *J, RecordFFData *rd) | ||
1646 | { | ||
1647 | CTState *cts = ctype_ctsG(J2G(J)); | ||
1648 | TRef tr = crec_ct_tv(J, ctype_get(cts, CTID_INT64), 0, | ||
1649 | J->base[0], &rd->argv[0]); | ||
1650 | if (!tref_isinteger(tr)) | ||
1651 | tr = emitconv(tr, IRT_INT, tref_type(tr), 0); | ||
1652 | J->base[0] = tr; | ||
1653 | } | ||
1654 | |||
1655 | int LJ_FASTCALL recff_bit64_unary(jit_State *J, RecordFFData *rd) | ||
1656 | { | ||
1657 | CTState *cts = ctype_ctsG(J2G(J)); | ||
1658 | CTypeID id = crec_bit64_type(cts, &rd->argv[0]); | ||
1659 | if (id) { | ||
1660 | TRef tr = crec_ct_tv(J, ctype_get(cts, id), 0, J->base[0], &rd->argv[0]); | ||
1661 | tr = emitir(IRT(rd->data, id-CTID_INT64+IRT_I64), tr, 0); | ||
1662 | J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr); | ||
1663 | return 1; | ||
1664 | } | ||
1665 | return 0; | ||
1666 | } | ||
1667 | |||
1668 | int LJ_FASTCALL recff_bit64_nary(jit_State *J, RecordFFData *rd) | ||
1669 | { | ||
1670 | CTState *cts = ctype_ctsG(J2G(J)); | ||
1671 | CTypeID id = 0; | ||
1672 | MSize i; | ||
1673 | for (i = 0; J->base[i] != 0; i++) { | ||
1674 | CTypeID aid = crec_bit64_type(cts, &rd->argv[i]); | ||
1675 | if (id < aid) id = aid; /* Determine highest type rank of all arguments. */ | ||
1676 | } | ||
1677 | if (id) { | ||
1678 | CType *ct = ctype_get(cts, id); | ||
1679 | uint32_t ot = IRT(rd->data, id-CTID_INT64+IRT_I64); | ||
1680 | TRef tr = crec_ct_tv(J, ct, 0, J->base[0], &rd->argv[0]); | ||
1681 | for (i = 1; J->base[i] != 0; i++) { | ||
1682 | TRef tr2 = crec_ct_tv(J, ct, 0, J->base[i], &rd->argv[i]); | ||
1683 | tr = emitir(ot, tr, tr2); | ||
1684 | } | ||
1685 | J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr); | ||
1686 | return 1; | ||
1687 | } | ||
1688 | return 0; | ||
1689 | } | ||
1690 | |||
1691 | int LJ_FASTCALL recff_bit64_shift(jit_State *J, RecordFFData *rd) | ||
1692 | { | ||
1693 | CTState *cts = ctype_ctsG(J2G(J)); | ||
1694 | CTypeID id; | ||
1695 | TRef tsh = 0; | ||
1696 | if (J->base[0] && tref_iscdata(J->base[1])) { | ||
1697 | tsh = crec_ct_tv(J, ctype_get(cts, CTID_INT64), 0, | ||
1698 | J->base[1], &rd->argv[1]); | ||
1699 | if (!tref_isinteger(tsh)) | ||
1700 | tsh = emitconv(tsh, IRT_INT, tref_type(tsh), 0); | ||
1701 | J->base[1] = tsh; | ||
1702 | } | ||
1703 | id = crec_bit64_type(cts, &rd->argv[0]); | ||
1704 | if (id) { | ||
1705 | TRef tr = crec_ct_tv(J, ctype_get(cts, id), 0, J->base[0], &rd->argv[0]); | ||
1706 | uint32_t op = rd->data; | ||
1707 | if (!tsh) tsh = lj_opt_narrow_tobit(J, J->base[1]); | ||
1708 | if (!(op < IR_BROL ? LJ_TARGET_MASKSHIFT : LJ_TARGET_MASKROT) && | ||
1709 | !tref_isk(tsh)) | ||
1710 | tsh = emitir(IRTI(IR_BAND), tsh, lj_ir_kint(J, 63)); | ||
1711 | #ifdef LJ_TARGET_UNIFYROT | ||
1712 | if (op == (LJ_TARGET_UNIFYROT == 1 ? IR_BROR : IR_BROL)) { | ||
1713 | op = LJ_TARGET_UNIFYROT == 1 ? IR_BROL : IR_BROR; | ||
1714 | tsh = emitir(IRTI(IR_NEG), tsh, tsh); | ||
1715 | } | ||
1716 | #endif | ||
1717 | tr = emitir(IRT(op, id-CTID_INT64+IRT_I64), tr, tsh); | ||
1718 | J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr); | ||
1719 | return 1; | ||
1720 | } | ||
1721 | return 0; | ||
1722 | } | ||
1723 | |||
1629 | /* -- Miscellaneous library functions ------------------------------------- */ | 1724 | /* -- Miscellaneous library functions ------------------------------------- */ |
1630 | 1725 | ||
1631 | void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd) | 1726 | void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd) |
diff --git a/src/lj_crecord.h b/src/lj_crecord.h index dea05f78..92d777b8 100644 --- a/src/lj_crecord.h +++ b/src/lj_crecord.h | |||
@@ -25,6 +25,12 @@ LJ_FUNC void LJ_FASTCALL recff_ffi_istype(jit_State *J, RecordFFData *rd); | |||
25 | LJ_FUNC void LJ_FASTCALL recff_ffi_abi(jit_State *J, RecordFFData *rd); | 25 | LJ_FUNC void LJ_FASTCALL recff_ffi_abi(jit_State *J, RecordFFData *rd); |
26 | LJ_FUNC void LJ_FASTCALL recff_ffi_xof(jit_State *J, RecordFFData *rd); | 26 | LJ_FUNC void LJ_FASTCALL recff_ffi_xof(jit_State *J, RecordFFData *rd); |
27 | LJ_FUNC void LJ_FASTCALL recff_ffi_gc(jit_State *J, RecordFFData *rd); | 27 | LJ_FUNC void LJ_FASTCALL recff_ffi_gc(jit_State *J, RecordFFData *rd); |
28 | |||
29 | LJ_FUNC void LJ_FASTCALL recff_bit64_tobit(jit_State *J, RecordFFData *rd); | ||
30 | LJ_FUNC int LJ_FASTCALL recff_bit64_unary(jit_State *J, RecordFFData *rd); | ||
31 | LJ_FUNC int LJ_FASTCALL recff_bit64_nary(jit_State *J, RecordFFData *rd); | ||
32 | LJ_FUNC int LJ_FASTCALL recff_bit64_shift(jit_State *J, RecordFFData *rd); | ||
33 | |||
28 | LJ_FUNC void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd); | 34 | LJ_FUNC void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd); |
29 | #endif | 35 | #endif |
30 | 36 | ||
diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c index 730d5c39..4f6aeb37 100644 --- a/src/lj_ffrecord.c +++ b/src/lj_ffrecord.c | |||
@@ -584,40 +584,66 @@ static void LJ_FASTCALL recff_math_random(jit_State *J, RecordFFData *rd) | |||
584 | 584 | ||
585 | /* -- Bit library fast functions ------------------------------------------ */ | 585 | /* -- Bit library fast functions ------------------------------------------ */ |
586 | 586 | ||
587 | /* Record unary bit.tobit, bit.bnot, bit.bswap. */ | 587 | /* Record bit.tobit. */ |
588 | static void LJ_FASTCALL recff_bit_tobit(jit_State *J, RecordFFData *rd) | ||
589 | { | ||
590 | TRef tr = J->base[0]; | ||
591 | #if LJ_HASFFI | ||
592 | if (tref_iscdata(tr)) { recff_bit64_tobit(J, rd); return; } | ||
593 | #endif | ||
594 | J->base[0] = lj_opt_narrow_tobit(J, tr); | ||
595 | UNUSED(rd); | ||
596 | } | ||
597 | |||
598 | /* Record unary bit.bnot, bit.bswap. */ | ||
588 | static void LJ_FASTCALL recff_bit_unary(jit_State *J, RecordFFData *rd) | 599 | static void LJ_FASTCALL recff_bit_unary(jit_State *J, RecordFFData *rd) |
589 | { | 600 | { |
590 | TRef tr = lj_opt_narrow_tobit(J, J->base[0]); | 601 | #if LJ_HASFFI |
591 | J->base[0] = (rd->data == IR_TOBIT) ? tr : emitir(IRTI(rd->data), tr, 0); | 602 | if (recff_bit64_unary(J, rd)) |
603 | return; | ||
604 | #endif | ||
605 | J->base[0] = emitir(IRTI(rd->data), lj_opt_narrow_tobit(J, J->base[0]), 0); | ||
592 | } | 606 | } |
593 | 607 | ||
594 | /* Record N-ary bit.band, bit.bor, bit.bxor. */ | 608 | /* Record N-ary bit.band, bit.bor, bit.bxor. */ |
595 | static void LJ_FASTCALL recff_bit_nary(jit_State *J, RecordFFData *rd) | 609 | static void LJ_FASTCALL recff_bit_nary(jit_State *J, RecordFFData *rd) |
596 | { | 610 | { |
597 | TRef tr = lj_opt_narrow_tobit(J, J->base[0]); | 611 | #if LJ_HASFFI |
598 | uint32_t op = rd->data; | 612 | if (recff_bit64_nary(J, rd)) |
599 | BCReg i; | 613 | return; |
600 | for (i = 1; J->base[i] != 0; i++) | 614 | #endif |
601 | tr = emitir(IRTI(op), tr, lj_opt_narrow_tobit(J, J->base[i])); | 615 | { |
602 | J->base[0] = tr; | 616 | TRef tr = lj_opt_narrow_tobit(J, J->base[0]); |
617 | uint32_t ot = IRTI(rd->data); | ||
618 | BCReg i; | ||
619 | for (i = 1; J->base[i] != 0; i++) | ||
620 | tr = emitir(ot, tr, lj_opt_narrow_tobit(J, J->base[i])); | ||
621 | J->base[0] = tr; | ||
622 | } | ||
603 | } | 623 | } |
604 | 624 | ||
605 | /* Record bit shifts. */ | 625 | /* Record bit shifts. */ |
606 | static void LJ_FASTCALL recff_bit_shift(jit_State *J, RecordFFData *rd) | 626 | static void LJ_FASTCALL recff_bit_shift(jit_State *J, RecordFFData *rd) |
607 | { | 627 | { |
608 | TRef tr = lj_opt_narrow_tobit(J, J->base[0]); | 628 | #if LJ_HASFFI |
609 | TRef tsh = lj_opt_narrow_tobit(J, J->base[1]); | 629 | if (recff_bit64_shift(J, rd)) |
610 | IROp op = (IROp)rd->data; | 630 | return; |
611 | if (!(op < IR_BROL ? LJ_TARGET_MASKSHIFT : LJ_TARGET_MASKROT) && | 631 | #endif |
612 | !tref_isk(tsh)) | 632 | { |
613 | tsh = emitir(IRTI(IR_BAND), tsh, lj_ir_kint(J, 31)); | 633 | TRef tr = lj_opt_narrow_tobit(J, J->base[0]); |
634 | TRef tsh = lj_opt_narrow_tobit(J, J->base[1]); | ||
635 | IROp op = (IROp)rd->data; | ||
636 | if (!(op < IR_BROL ? LJ_TARGET_MASKSHIFT : LJ_TARGET_MASKROT) && | ||
637 | !tref_isk(tsh)) | ||
638 | tsh = emitir(IRTI(IR_BAND), tsh, lj_ir_kint(J, 31)); | ||
614 | #ifdef LJ_TARGET_UNIFYROT | 639 | #ifdef LJ_TARGET_UNIFYROT |
615 | if (op == (LJ_TARGET_UNIFYROT == 1 ? IR_BROR : IR_BROL)) { | 640 | if (op == (LJ_TARGET_UNIFYROT == 1 ? IR_BROR : IR_BROL)) { |
616 | op = LJ_TARGET_UNIFYROT == 1 ? IR_BROL : IR_BROR; | 641 | op = LJ_TARGET_UNIFYROT == 1 ? IR_BROL : IR_BROR; |
617 | tsh = emitir(IRTI(IR_NEG), tsh, tsh); | 642 | tsh = emitir(IRTI(IR_NEG), tsh, tsh); |
618 | } | 643 | } |
619 | #endif | 644 | #endif |
620 | J->base[0] = emitir(IRTI(op), tr, tsh); | 645 | J->base[0] = emitir(IRTI(op), tr, tsh); |
646 | } | ||
621 | } | 647 | } |
622 | 648 | ||
623 | /* -- String library fast functions --------------------------------------- */ | 649 | /* -- String library fast functions --------------------------------------- */ |
diff --git a/src/lj_ircall.h b/src/lj_ircall.h index 7fcc532e..2c160bdf 100644 --- a/src/lj_ircall.h +++ b/src/lj_ircall.h | |||
@@ -172,7 +172,12 @@ typedef struct CCallInfo { | |||
172 | _(FFI, memcpy, 3, S, PTR, 0) \ | 172 | _(FFI, memcpy, 3, S, PTR, 0) \ |
173 | _(FFI, memset, 3, S, PTR, 0) \ | 173 | _(FFI, memset, 3, S, PTR, 0) \ |
174 | _(FFI, lj_vm_errno, 0, S, INT, CCI_NOFPRCLOBBER) \ | 174 | _(FFI, lj_vm_errno, 0, S, INT, CCI_NOFPRCLOBBER) \ |
175 | _(FFI32, lj_carith_mul64, ARG2_64, N, I64, CCI_NOFPRCLOBBER) | 175 | _(FFI32, lj_carith_mul64, ARG2_64, N, I64, CCI_NOFPRCLOBBER) \ |
176 | _(FFI32, lj_carith_shl64, 3, N, U64, CCI_NOFPRCLOBBER) \ | ||
177 | _(FFI32, lj_carith_shr64, 3, N, U64, CCI_NOFPRCLOBBER) \ | ||
178 | _(FFI32, lj_carith_sar64, 3, N, U64, CCI_NOFPRCLOBBER) \ | ||
179 | _(FFI32, lj_carith_rol64, 3, N, U64, CCI_NOFPRCLOBBER) \ | ||
180 | _(FFI32, lj_carith_ror64, 3, N, U64, CCI_NOFPRCLOBBER) \ | ||
176 | \ | 181 | \ |
177 | /* End of list. */ | 182 | /* End of list. */ |
178 | 183 | ||
diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c index e67f3ee6..75db47df 100644 --- a/src/lj_opt_fold.c +++ b/src/lj_opt_fold.c | |||
@@ -22,8 +22,8 @@ | |||
22 | #include "lj_trace.h" | 22 | #include "lj_trace.h" |
23 | #if LJ_HASFFI | 23 | #if LJ_HASFFI |
24 | #include "lj_ctype.h" | 24 | #include "lj_ctype.h" |
25 | #endif | ||
26 | #include "lj_carith.h" | 25 | #include "lj_carith.h" |
26 | #endif | ||
27 | #include "lj_vm.h" | 27 | #include "lj_vm.h" |
28 | #include "lj_strscan.h" | 28 | #include "lj_strscan.h" |
29 | 29 | ||
@@ -336,11 +336,9 @@ LJFOLDF(kfold_intcomp0) | |||
336 | static uint64_t kfold_int64arith(uint64_t k1, uint64_t k2, IROp op) | 336 | static uint64_t kfold_int64arith(uint64_t k1, uint64_t k2, IROp op) |
337 | { | 337 | { |
338 | switch (op) { | 338 | switch (op) { |
339 | #if LJ_64 || LJ_HASFFI | 339 | #if LJ_HASFFI |
340 | case IR_ADD: k1 += k2; break; | 340 | case IR_ADD: k1 += k2; break; |
341 | case IR_SUB: k1 -= k2; break; | 341 | case IR_SUB: k1 -= k2; break; |
342 | #endif | ||
343 | #if LJ_HASFFI | ||
344 | case IR_MUL: k1 *= k2; break; | 342 | case IR_MUL: k1 *= k2; break; |
345 | case IR_BAND: k1 &= k2; break; | 343 | case IR_BAND: k1 &= k2; break; |
346 | case IR_BOR: k1 |= k2; break; | 344 | case IR_BOR: k1 |= k2; break; |
@@ -392,20 +390,10 @@ LJFOLD(BROL KINT64 KINT) | |||
392 | LJFOLD(BROR KINT64 KINT) | 390 | LJFOLD(BROR KINT64 KINT) |
393 | LJFOLDF(kfold_int64shift) | 391 | LJFOLDF(kfold_int64shift) |
394 | { | 392 | { |
395 | #if LJ_HASFFI || LJ_64 | 393 | #if LJ_HASFFI |
396 | uint64_t k = ir_k64(fleft)->u64; | 394 | uint64_t k = ir_k64(fleft)->u64; |
397 | int32_t sh = (fright->i & 63); | 395 | int32_t sh = (fright->i & 63); |
398 | switch ((IROp)fins->o) { | 396 | return INT64FOLD(lj_carith_shift64(k, sh, fins->o - IR_BSHL)); |
399 | case IR_BSHL: k <<= sh; break; | ||
400 | #if LJ_HASFFI | ||
401 | case IR_BSHR: k >>= sh; break; | ||
402 | case IR_BSAR: k = (uint64_t)((int64_t)k >> sh); break; | ||
403 | case IR_BROL: k = lj_rol(k, sh); break; | ||
404 | case IR_BROR: k = lj_ror(k, sh); break; | ||
405 | #endif | ||
406 | default: lua_assert(0); break; | ||
407 | } | ||
408 | return INT64FOLD(k); | ||
409 | #else | 397 | #else |
410 | UNUSED(J); lua_assert(0); return FAILFOLD; | 398 | UNUSED(J); lua_assert(0); return FAILFOLD; |
411 | #endif | 399 | #endif |
@@ -1192,7 +1180,9 @@ static TRef simplify_intmul_k(jit_State *J, int32_t k) | |||
1192 | ** But this is mainly intended for simple address arithmetic. | 1180 | ** But this is mainly intended for simple address arithmetic. |
1193 | ** Also it's easier for the backend to optimize the original multiplies. | 1181 | ** Also it's easier for the backend to optimize the original multiplies. |
1194 | */ | 1182 | */ |
1195 | if (k == 1) { /* i * 1 ==> i */ | 1183 | if (k == 0) { /* i * 0 ==> 0 */ |
1184 | return RIGHTFOLD; | ||
1185 | } else if (k == 1) { /* i * 1 ==> i */ | ||
1196 | return LEFTFOLD; | 1186 | return LEFTFOLD; |
1197 | } else if ((k & (k-1)) == 0) { /* i * 2^k ==> i << k */ | 1187 | } else if ((k & (k-1)) == 0) { /* i * 2^k ==> i << k */ |
1198 | fins->o = IR_BSHL; | 1188 | fins->o = IR_BSHL; |
@@ -1205,9 +1195,7 @@ static TRef simplify_intmul_k(jit_State *J, int32_t k) | |||
1205 | LJFOLD(MUL any KINT) | 1195 | LJFOLD(MUL any KINT) |
1206 | LJFOLDF(simplify_intmul_k32) | 1196 | LJFOLDF(simplify_intmul_k32) |
1207 | { | 1197 | { |
1208 | if (fright->i == 0) /* i * 0 ==> 0 */ | 1198 | if (fright->i >= 0) |
1209 | return INTFOLD(0); | ||
1210 | else if (fright->i > 0) | ||
1211 | return simplify_intmul_k(J, fright->i); | 1199 | return simplify_intmul_k(J, fright->i); |
1212 | return NEXTFOLD; | 1200 | return NEXTFOLD; |
1213 | } | 1201 | } |
@@ -1215,14 +1203,13 @@ LJFOLDF(simplify_intmul_k32) | |||
1215 | LJFOLD(MUL any KINT64) | 1203 | LJFOLD(MUL any KINT64) |
1216 | LJFOLDF(simplify_intmul_k64) | 1204 | LJFOLDF(simplify_intmul_k64) |
1217 | { | 1205 | { |
1218 | if (ir_kint64(fright)->u64 == 0) /* i * 0 ==> 0 */ | 1206 | #if LJ_HASFFI |
1219 | return INT64FOLD(0); | 1207 | if (ir_kint64(fright)->u64 < 0x80000000u) |
1220 | #if LJ_64 | ||
1221 | /* NYI: SPLIT for BSHL and 32 bit backend support. */ | ||
1222 | else if (ir_kint64(fright)->u64 < 0x80000000u) | ||
1223 | return simplify_intmul_k(J, (int32_t)ir_kint64(fright)->u64); | 1208 | return simplify_intmul_k(J, (int32_t)ir_kint64(fright)->u64); |
1224 | #endif | ||
1225 | return NEXTFOLD; | 1209 | return NEXTFOLD; |
1210 | #else | ||
1211 | UNUSED(J); lua_assert(0); return FAILFOLD; | ||
1212 | #endif | ||
1226 | } | 1213 | } |
1227 | 1214 | ||
1228 | LJFOLD(MOD any KINT) | 1215 | LJFOLD(MOD any KINT) |
@@ -1522,7 +1509,7 @@ LJFOLD(BOR BOR KINT64) | |||
1522 | LJFOLD(BXOR BXOR KINT64) | 1509 | LJFOLD(BXOR BXOR KINT64) |
1523 | LJFOLDF(reassoc_intarith_k64) | 1510 | LJFOLDF(reassoc_intarith_k64) |
1524 | { | 1511 | { |
1525 | #if LJ_HASFFI || LJ_64 | 1512 | #if LJ_HASFFI |
1526 | IRIns *irk = IR(fleft->op2); | 1513 | IRIns *irk = IR(fleft->op2); |
1527 | if (irk->o == IR_KINT64) { | 1514 | if (irk->o == IR_KINT64) { |
1528 | uint64_t k = kfold_int64arith(ir_k64(irk)->u64, | 1515 | uint64_t k = kfold_int64arith(ir_k64(irk)->u64, |
diff --git a/src/lj_opt_split.c b/src/lj_opt_split.c index 2b04e77d..a0526c9d 100644 --- a/src/lj_opt_split.c +++ b/src/lj_opt_split.c | |||
@@ -140,6 +140,7 @@ static IRRef split_call_l(jit_State *J, IRRef1 *hisubst, IRIns *oir, | |||
140 | ir->prev = tmp = split_emit(J, IRTI(IR_CALLN), tmp, id); | 140 | ir->prev = tmp = split_emit(J, IRTI(IR_CALLN), tmp, id); |
141 | return split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), tmp, tmp); | 141 | return split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), tmp, tmp); |
142 | } | 142 | } |
143 | #endif | ||
143 | 144 | ||
144 | /* Emit a CALLN with one split 64 bit argument and a 32 bit argument. */ | 145 | /* Emit a CALLN with one split 64 bit argument and a 32 bit argument. */ |
145 | static IRRef split_call_li(jit_State *J, IRRef1 *hisubst, IRIns *oir, | 146 | static IRRef split_call_li(jit_State *J, IRRef1 *hisubst, IRIns *oir, |
@@ -156,7 +157,6 @@ static IRRef split_call_li(jit_State *J, IRRef1 *hisubst, IRIns *oir, | |||
156 | ir->prev = tmp = split_emit(J, IRTI(IR_CALLN), tmp, id); | 157 | ir->prev = tmp = split_emit(J, IRTI(IR_CALLN), tmp, id); |
157 | return split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), tmp, tmp); | 158 | return split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), tmp, tmp); |
158 | } | 159 | } |
159 | #endif | ||
160 | 160 | ||
161 | /* Emit a CALLN with two split 64 bit arguments. */ | 161 | /* Emit a CALLN with two split 64 bit arguments. */ |
162 | static IRRef split_call_ll(jit_State *J, IRRef1 *hisubst, IRIns *oir, | 162 | static IRRef split_call_ll(jit_State *J, IRRef1 *hisubst, IRIns *oir, |
@@ -196,6 +196,118 @@ static IRRef split_ptr(jit_State *J, IRIns *oir, IRRef ref) | |||
196 | return split_emit(J, IRTI(IR_ADD), nref, lj_ir_kint(J, ofs)); | 196 | return split_emit(J, IRTI(IR_ADD), nref, lj_ir_kint(J, ofs)); |
197 | } | 197 | } |
198 | 198 | ||
199 | #if LJ_HASFFI | ||
200 | static IRRef split_bitshift(jit_State *J, IRRef1 *hisubst, | ||
201 | IRIns *oir, IRIns *nir, IRIns *ir) | ||
202 | { | ||
203 | IROp op = ir->o; | ||
204 | IRRef kref = nir->op2; | ||
205 | if (irref_isk(kref)) { /* Optimize constant shifts. */ | ||
206 | int32_t k = (IR(kref)->i & 63); | ||
207 | IRRef lo = nir->op1, hi = hisubst[ir->op1]; | ||
208 | if (op == IR_BROL || op == IR_BROR) { | ||
209 | if (op == IR_BROR) k = (-k & 63); | ||
210 | if (k >= 32) { IRRef t = lo; lo = hi; hi = t; k -= 32; } | ||
211 | if (k == 0) { | ||
212 | passthrough: | ||
213 | J->cur.nins--; | ||
214 | ir->prev = lo; | ||
215 | return hi; | ||
216 | } else { | ||
217 | TRef k1, k2; | ||
218 | IRRef t1, t2, t3, t4; | ||
219 | J->cur.nins--; | ||
220 | k1 = lj_ir_kint(J, k); | ||
221 | k2 = lj_ir_kint(J, (-k & 31)); | ||
222 | t1 = split_emit(J, IRTI(IR_BSHL), lo, k1); | ||
223 | t2 = split_emit(J, IRTI(IR_BSHL), hi, k1); | ||
224 | t3 = split_emit(J, IRTI(IR_BSHR), lo, k2); | ||
225 | t4 = split_emit(J, IRTI(IR_BSHR), hi, k2); | ||
226 | ir->prev = split_emit(J, IRTI(IR_BOR), t1, t4); | ||
227 | return split_emit(J, IRTI(IR_BOR), t2, t3); | ||
228 | } | ||
229 | } else if (k == 0) { | ||
230 | goto passthrough; | ||
231 | } else if (k < 32) { | ||
232 | if (op == IR_BSHL) { | ||
233 | IRRef t1 = split_emit(J, IRTI(IR_BSHL), hi, kref); | ||
234 | IRRef t2 = split_emit(J, IRTI(IR_BSHR), lo, lj_ir_kint(J, (-k&31))); | ||
235 | return split_emit(J, IRTI(IR_BOR), t1, t2); | ||
236 | } else { | ||
237 | IRRef t1 = ir->prev, t2; | ||
238 | lua_assert(op == IR_BSHR || op == IR_BSAR); | ||
239 | nir->o = IR_BSHR; | ||
240 | t2 = split_emit(J, IRTI(IR_BSHL), hi, lj_ir_kint(J, (-k&31))); | ||
241 | ir->prev = split_emit(J, IRTI(IR_BOR), t1, t2); | ||
242 | return split_emit(J, IRTI(op), hi, kref); | ||
243 | } | ||
244 | } else { | ||
245 | if (op == IR_BSHL) { | ||
246 | if (k == 32) | ||
247 | J->cur.nins--; | ||
248 | else | ||
249 | lo = ir->prev; | ||
250 | ir->prev = lj_ir_kint(J, 0); | ||
251 | return lo; | ||
252 | } else { | ||
253 | lua_assert(op == IR_BSHR || op == IR_BSAR); | ||
254 | if (k == 32) { | ||
255 | J->cur.nins--; | ||
256 | ir->prev = hi; | ||
257 | } else { | ||
258 | nir->op1 = hi; | ||
259 | } | ||
260 | if (op == IR_BSHR) | ||
261 | return lj_ir_kint(J, 0); | ||
262 | else | ||
263 | return split_emit(J, IRTI(IR_BSAR), hi, lj_ir_kint(J, 31)); | ||
264 | } | ||
265 | } | ||
266 | } | ||
267 | return split_call_li(J, hisubst, oir, ir, | ||
268 | op - IR_BSHL + IRCALL_lj_carith_shl64); | ||
269 | } | ||
270 | |||
271 | static IRRef split_bitop(jit_State *J, IRRef1 *hisubst, | ||
272 | IRIns *nir, IRIns *ir) | ||
273 | { | ||
274 | IROp op = ir->o; | ||
275 | IRRef hi, kref = nir->op2; | ||
276 | if (irref_isk(kref)) { /* Optimize bit operations with lo constant. */ | ||
277 | int32_t k = IR(kref)->i; | ||
278 | if (k == 0 || k == -1) { | ||
279 | if (op == IR_BAND) k = ~k; | ||
280 | if (k == 0) { | ||
281 | J->cur.nins--; | ||
282 | ir->prev = nir->op1; | ||
283 | } else if (op == IR_BXOR) { | ||
284 | nir->o = IR_BNOT; | ||
285 | nir->op2 = 0; | ||
286 | } else { | ||
287 | J->cur.nins--; | ||
288 | ir->prev = kref; | ||
289 | } | ||
290 | } | ||
291 | } | ||
292 | hi = hisubst[ir->op1]; | ||
293 | kref = hisubst[ir->op2]; | ||
294 | if (irref_isk(kref)) { /* Optimize bit operations with hi constant. */ | ||
295 | int32_t k = IR(kref)->i; | ||
296 | if (k == 0 || k == -1) { | ||
297 | if (op == IR_BAND) k = ~k; | ||
298 | if (k == 0) { | ||
299 | return hi; | ||
300 | } else if (op == IR_BXOR) { | ||
301 | return split_emit(J, IRTI(IR_BNOT), hi, 0); | ||
302 | } else { | ||
303 | return kref; | ||
304 | } | ||
305 | } | ||
306 | } | ||
307 | return split_emit(J, IRTI(op), hi, kref); | ||
308 | } | ||
309 | #endif | ||
310 | |||
199 | /* Transform the old IR to the new IR. */ | 311 | /* Transform the old IR to the new IR. */ |
200 | static void split_ir(jit_State *J) | 312 | static void split_ir(jit_State *J) |
201 | { | 313 | { |
@@ -417,6 +529,19 @@ static void split_ir(jit_State *J) | |||
417 | irt_isi64(ir->t) ? IRCALL_lj_carith_powi64 : | 529 | irt_isi64(ir->t) ? IRCALL_lj_carith_powi64 : |
418 | IRCALL_lj_carith_powu64); | 530 | IRCALL_lj_carith_powu64); |
419 | break; | 531 | break; |
532 | case IR_BNOT: | ||
533 | hi = split_emit(J, IRTI(IR_BNOT), hiref, 0); | ||
534 | break; | ||
535 | case IR_BSWAP: | ||
536 | ir->prev = split_emit(J, IRTI(IR_BSWAP), hiref, 0); | ||
537 | hi = nref; | ||
538 | break; | ||
539 | case IR_BAND: case IR_BOR: case IR_BXOR: | ||
540 | hi = split_bitop(J, hisubst, nir, ir); | ||
541 | break; | ||
542 | case IR_BSHL: case IR_BSHR: case IR_BSAR: case IR_BROL: case IR_BROR: | ||
543 | hi = split_bitshift(J, hisubst, oir, nir, ir); | ||
544 | break; | ||
420 | case IR_FLOAD: | 545 | case IR_FLOAD: |
421 | lua_assert(ir->op2 == IRFL_CDATA_INT64); | 546 | lua_assert(ir->op2 == IRFL_CDATA_INT64); |
422 | hi = split_emit(J, IRTI(IR_FLOAD), nir->op1, IRFL_CDATA_INT64_4); | 547 | hi = split_emit(J, IRTI(IR_FLOAD), nir->op1, IRFL_CDATA_INT64_4); |