aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2011-01-26 21:46:02 +0100
committerMike Pall <mike>2011-01-26 21:46:02 +0100
commit3184f1716925f96b3d56c2795a0769bb3463f54e (patch)
treec9364c781e88b321ac4caffa566ccb5fa6659f83 /src
parent2526498c7126f3e60d1f3a8d72c97bf20bf4a49e (diff)
downloadluajit-3184f1716925f96b3d56c2795a0769bb3463f54e.tar.gz
luajit-3184f1716925f96b3d56c2795a0769bb3463f54e.tar.bz2
luajit-3184f1716925f96b3d56c2795a0769bb3463f54e.zip
FFI: Move code for cdata arithmetic to lj_carith.c.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile3
-rw-r--r--src/Makefile.dep27
-rw-r--r--src/lib_ffi.c217
-rw-r--r--src/lj_carith.c260
-rw-r--r--src/lj_carith.h19
-rw-r--r--src/lj_cdata.c34
-rw-r--r--src/lj_cdata.h2
-rw-r--r--src/lj_crecord.c2
-rw-r--r--src/lj_ir.c1
-rw-r--r--src/lj_ir.h2
-rw-r--r--src/ljamalg.c1
11 files changed, 308 insertions, 260 deletions
diff --git a/src/Makefile b/src/Makefile
index fc7bbfcc..a2be1a18 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -334,7 +334,8 @@ LJCORE_O= lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o \
334 lj_opt_dce.o lj_opt_loop.o \ 334 lj_opt_dce.o lj_opt_loop.o \
335 lj_mcode.o lj_snap.o lj_record.o lj_crecord.o lj_ffrecord.o \ 335 lj_mcode.o lj_snap.o lj_record.o lj_crecord.o lj_ffrecord.o \
336 lj_asm.o lj_trace.o lj_gdbjit.o \ 336 lj_asm.o lj_trace.o lj_gdbjit.o \
337 lj_ctype.o lj_cdata.o lj_cconv.o lj_ccall.o lj_clib.o lj_cparse.o \ 337 lj_ctype.o lj_cdata.o lj_cconv.o lj_ccall.o lj_carith.o lj_clib.o \
338 lj_cparse.o \
338 lj_lib.o lj_alloc.o lib_aux.o \ 339 lj_lib.o lj_alloc.o lib_aux.o \
339 $(LJLIB_O) lib_init.o 340 $(LJLIB_O) lib_init.o
340 341
diff --git a/src/Makefile.dep b/src/Makefile.dep
index 8cebc39d..3d0c4239 100644
--- a/src/Makefile.dep
+++ b/src/Makefile.dep
@@ -22,8 +22,8 @@ lib_debug.o: lib_debug.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
22 lj_def.h lj_arch.h lj_err.h lj_errmsg.h lj_lib.h lj_libdef.h 22 lj_def.h lj_arch.h lj_err.h lj_errmsg.h lj_lib.h lj_libdef.h
23lib_ffi.o: lib_ffi.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ 23lib_ffi.o: lib_ffi.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
24 lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cparse.h \ 24 lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cparse.h \
25 lj_cdata.h lj_cconv.h lj_ccall.h lj_clib.h lj_ff.h lj_ffdef.h lj_lib.h \ 25 lj_cdata.h lj_cconv.h lj_carith.h lj_ccall.h lj_clib.h lj_ff.h \
26 lj_libdef.h 26 lj_ffdef.h lj_lib.h lj_libdef.h
27lib_init.o: lib_init.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h 27lib_init.o: lib_init.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h
28lib_io.o: lib_io.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ 28lib_io.o: lib_io.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
29 lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ff.h lj_ffdef.h \ 29 lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ff.h lj_ffdef.h \
@@ -56,6 +56,9 @@ lj_asm.o: lj_asm.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
56 lj_asm.h lj_vm.h lj_target.h lj_target_*.h 56 lj_asm.h lj_vm.h lj_target.h lj_target_*.h
57lj_bc.o: lj_bc.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_bc.h \ 57lj_bc.o: lj_bc.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_bc.h \
58 lj_bcdef.h 58 lj_bcdef.h
59lj_carith.o: lj_carith.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
60 lj_gc.h lj_err.h lj_errmsg.h lj_ctype.h lj_cconv.h lj_cdata.h \
61 lj_carith.h
59lj_ccall.o: lj_ccall.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 62lj_ccall.o: lj_ccall.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
60 lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cconv.h lj_cdata.h \ 63 lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cconv.h lj_cdata.h \
61 lj_ccall.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_bc.h \ 64 lj_ccall.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_bc.h \
@@ -99,7 +102,7 @@ lj_gdbjit.o: lj_gdbjit.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
99 lj_dispatch.h 102 lj_dispatch.h
100lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 103lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
101 lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_iropt.h lj_trace.h lj_dispatch.h \ 104 lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_iropt.h lj_trace.h lj_dispatch.h \
102 lj_bc.h lj_traceerr.h lj_ctype.h lj_cdata.h lj_lib.h 105 lj_bc.h lj_traceerr.h lj_ctype.h lj_cdata.h lj_carith.h lj_lib.h
103lj_lex.o: lj_lex.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 106lj_lex.o: lj_lex.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
104 lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h lj_cdata.h lualib.h \ 107 lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h lj_cdata.h lualib.h \
105 lj_state.h lj_lex.h lj_parse.h lj_char.h 108 lj_state.h lj_lex.h lj_parse.h lj_char.h
@@ -161,13 +164,13 @@ ljamalg.o: ljamalg.c lua.h luaconf.h lauxlib.h lj_gc.c lj_obj.h lj_def.h \
161 lj_func.c lj_udata.c lj_meta.c lj_state.c lj_lex.h lj_alloc.h \ 164 lj_func.c lj_udata.c lj_meta.c lj_state.c lj_lex.h lj_alloc.h \
162 lj_dispatch.c lj_ff.h lj_ffdef.h luajit.h lj_vmevent.c lj_vmevent.h \ 165 lj_dispatch.c lj_ff.h lj_ffdef.h luajit.h lj_vmevent.c lj_vmevent.h \
163 lj_api.c lj_parse.h lj_lex.c lualib.h lj_parse.c lj_ctype.c lj_cdata.c \ 166 lj_api.c lj_parse.h lj_lex.c lualib.h lj_parse.c lj_ctype.c lj_cdata.c \
164 lj_cconv.h lj_cconv.c lj_ccall.c lj_ccall.h lj_clib.c lj_clib.h \ 167 lj_cconv.h lj_cconv.c lj_ccall.c lj_ccall.h lj_carith.c lj_carith.h \
165 lj_cparse.c lj_cparse.h lj_lib.c lj_lib.h lj_ir.c lj_iropt.h \ 168 lj_clib.c lj_clib.h lj_cparse.c lj_cparse.h lj_lib.c lj_lib.h lj_ir.c \
166 lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c lj_opt_dce.c \ 169 lj_iropt.h lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c \
167 lj_opt_loop.c lj_snap.h lj_mcode.c lj_mcode.h lj_snap.c lj_target.h \ 170 lj_opt_dce.c lj_opt_loop.c lj_snap.h lj_mcode.c lj_mcode.h lj_snap.c \
168 lj_target_*.h lj_record.c lj_record.h lj_ffrecord.h lj_crecord.c \ 171 lj_target.h lj_target_*.h lj_record.c lj_record.h lj_ffrecord.h \
169 lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h lj_trace.c \ 172 lj_crecord.c lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h \
170 lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c lib_base.c lj_libdef.h \ 173 lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c lib_base.c \
171 lib_math.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c \ 174 lj_libdef.h lib_math.c lib_string.c lib_table.c lib_io.c lib_os.c \
172 lib_debug.c lib_bit.c lib_jit.c lib_ffi.c lib_init.c 175 lib_package.c lib_debug.c lib_bit.c lib_jit.c lib_ffi.c lib_init.c
173luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h 176luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h
diff --git a/src/lib_ffi.c b/src/lib_ffi.c
index 42d71153..ef5de029 100644
--- a/src/lib_ffi.c
+++ b/src/lib_ffi.c
@@ -21,6 +21,7 @@
21#include "lj_cparse.h" 21#include "lj_cparse.h"
22#include "lj_cdata.h" 22#include "lj_cdata.h"
23#include "lj_cconv.h" 23#include "lj_cconv.h"
24#include "lj_carith.h"
24#include "lj_ccall.h" 25#include "lj_ccall.h"
25#include "lj_clib.h" 26#include "lj_clib.h"
26#include "lj_ff.h" 27#include "lj_ff.h"
@@ -77,215 +78,6 @@ static void *ffi_checkptr(lua_State *L, int narg, CTypeID id)
77 return p; 78 return p;
78} 79}
79 80
80/* -- C data arithmetic --------------------------------------------------- */
81
82typedef struct FFIArith {
83 uint8_t *p[2];
84 CType *ct[2];
85} FFIArith;
86
87/* Check arguments for arithmetic metamethods. */
88static int ffi_checkarith(lua_State *L, CTState *cts, FFIArith *fa)
89{
90 TValue *o = L->base;
91 int ok = 1;
92 MSize i;
93 if (o+1 >= L->top)
94 lj_err_argt(L, 1, LUA_TCDATA);
95 for (i = 0; i < 2; i++, o++) {
96 if (tviscdata(o)) {
97 GCcdata *cd = cdataV(o);
98 CType *ct = ctype_raw(cts, (CTypeID)cd->typeid);
99 uint8_t *p = (uint8_t *)cdataptr(cd);
100 if (ctype_isptr(ct->info)) {
101 p = (uint8_t *)cdata_getptr(p, ct->size);
102 if (ctype_isref(ct->info)) ct = ctype_rawchild(cts, ct);
103 }
104 fa->ct[i] = ct;
105 fa->p[i] = p;
106 } else if (tvisnum(o)) {
107 fa->ct[i] = ctype_get(cts, CTID_DOUBLE);
108 fa->p[i] = (uint8_t *)&o->n;
109 } else if (tvisnil(o)) {
110 fa->ct[i] = ctype_get(cts, CTID_P_VOID);
111 fa->p[i] = (uint8_t *)0;
112 } else {
113 fa->ct[i] = NULL;
114 fa->p[i] = NULL;
115 ok = 0;
116 }
117 }
118 return ok;
119}
120
121/* Pointer arithmetic. */
122static int ffi_arith_ptr(lua_State *L, CTState *cts, FFIArith *fa, MMS mm)
123{
124 CType *ctp = fa->ct[0];
125 uint8_t *pp = fa->p[0];
126 ptrdiff_t idx;
127 CTSize sz;
128 CTypeID id;
129 GCcdata *cd;
130 if (ctype_isptr(ctp->info) || ctype_isrefarray(ctp->info)) {
131 if ((mm == MM_sub || mm == MM_eq || mm == MM_lt || mm == MM_le) &&
132 (ctype_isptr(fa->ct[1]->info) || ctype_isrefarray(fa->ct[1]->info))) {
133 uint8_t *pp2 = fa->p[1];
134 if (mm == MM_eq) { /* Pointer equality. Incompatible pointers are ok. */
135 setboolV(L->top-1, (pp == pp2));
136 return 1;
137 }
138 if (!lj_cconv_compatptr(cts, ctp, fa->ct[1], CCF_IGNQUAL))
139 return 0;
140 if (mm == MM_sub) { /* Pointer difference. */
141 intptr_t diff;
142 sz = lj_ctype_size(cts, ctype_cid(ctp->info)); /* Element size. */
143 if (sz == 0 || sz == CTSIZE_INVALID)
144 return 0;
145 diff = ((intptr_t)pp - (intptr_t)pp2) / (int32_t)sz;
146 /* All valid pointer differences on x64 are in (-2^47, +2^47),
147 ** which fits into a double without loss of precision.
148 */
149 setnumV(L->top-1, (lua_Number)diff);
150 return 1;
151 } else if (mm == MM_lt) { /* Pointer comparison (unsigned). */
152 setboolV(L->top-1, ((uintptr_t)pp < (uintptr_t)pp2));
153 return 1;
154 } else {
155 lua_assert(mm == MM_le);
156 setboolV(L->top-1, ((uintptr_t)pp <= (uintptr_t)pp2));
157 return 1;
158 }
159 }
160 if (!((mm == MM_add || mm == MM_sub) && ctype_isnum(fa->ct[1]->info)))
161 return 0;
162 lj_cconv_ct_ct(cts, ctype_get(cts, CTID_INT_PSZ), fa->ct[1],
163 (uint8_t *)&idx, fa->p[1], 0);
164 if (mm == MM_sub) idx = -idx;
165 } else if (mm == MM_add && ctype_isnum(ctp->info) &&
166 (ctype_isptr(fa->ct[1]->info) || ctype_isrefarray(fa->ct[1]->info))) {
167 /* Swap pointer and index. */
168 ctp = fa->ct[1]; pp = fa->p[1];
169 lj_cconv_ct_ct(cts, ctype_get(cts, CTID_INT_PSZ), fa->ct[0],
170 (uint8_t *)&idx, fa->p[0], 0);
171 } else {
172 return 0;
173 }
174 sz = lj_ctype_size(cts, ctype_cid(ctp->info)); /* Element size. */
175 if (sz == CTSIZE_INVALID)
176 return 0;
177 pp += idx*(int32_t)sz; /* Compute pointer + index. */
178 id = lj_ctype_intern(cts, CTINFO(CT_PTR, CTALIGN_PTR|ctype_cid(ctp->info)),
179 CTSIZE_PTR);
180 cd = lj_cdata_new(cts, id, CTSIZE_PTR);
181 *(uint8_t **)cdataptr(cd) = pp;
182 setcdataV(L, L->top-1, cd);
183 lj_gc_check(L);
184 return 1;
185}
186
187/* 64 bit integer arithmetic. */
188static int ffi_arith_int64(lua_State *L, CTState *cts, FFIArith *fa, MMS mm)
189{
190 if (ctype_isnum(fa->ct[0]->info) && fa->ct[0]->size <= 8 &&
191 ctype_isnum(fa->ct[1]->info) && fa->ct[1]->size <= 8) {
192 CTypeID id = (((fa->ct[0]->info & CTF_UNSIGNED) && fa->ct[0]->size == 8) ||
193 ((fa->ct[1]->info & CTF_UNSIGNED) && fa->ct[1]->size == 8)) ?
194 CTID_UINT64 : CTID_INT64;
195 CType *ct = ctype_get(cts, id);
196 GCcdata *cd;
197 uint64_t u0, u1, *up;
198 lj_cconv_ct_ct(cts, ct, fa->ct[0], (uint8_t *)&u0, fa->p[0], 0);
199 if (mm != MM_unm)
200 lj_cconv_ct_ct(cts, ct, fa->ct[1], (uint8_t *)&u1, fa->p[1], 0);
201 switch (mm) {
202 case MM_eq:
203 setboolV(L->top-1, (u0 == u1));
204 return 1;
205 case MM_lt:
206 setboolV(L->top-1,
207 id == CTID_INT64 ? ((int64_t)u0 < (int64_t)u1) : (u0 < u1));
208 return 1;
209 case MM_le:
210 setboolV(L->top-1,
211 id == CTID_INT64 ? ((int64_t)u0 <= (int64_t)u1) : (u0 <= u1));
212 return 1;
213 case MM_div: case MM_mod:
214 if (u1 == 0) { /* Division by zero. */
215 if (u0 == 0)
216 setnanV(L->top-1);
217 else if (id == CTID_INT64 && (int64_t)u0 < 0)
218 setminfV(L->top-1);
219 else
220 setpinfV(L->top-1);
221 return 1;
222 } else if (id == CTID_INT64 && (int64_t)u1 == -1 &&
223 u0 == U64x(80000000,00000000)) { /* MIN64 / -1. */
224 if (mm == MM_div) id = CTID_UINT64; else u0 = 0;
225 mm = MM_unm; /* Result is 0x8000000000000000ULL or 0LL. */
226 }
227 break;
228 default: break;
229 }
230 cd = lj_cdata_new(cts, id, 8);
231 up = (uint64_t *)cdataptr(cd);
232 setcdataV(L, L->top-1, cd);
233 switch (mm) {
234 case MM_add: *up = u0 + u1; break;
235 case MM_sub: *up = u0 - u1; break;
236 case MM_mul: *up = u0 * u1; break;
237 case MM_div:
238 if (id == CTID_INT64)
239 *up = (uint64_t)((int64_t)u0 / (int64_t)u1);
240 else
241 *up = u0 / u1;
242 break;
243 case MM_mod:
244 if (id == CTID_INT64)
245 *up = (uint64_t)((int64_t)u0 % (int64_t)u1);
246 else
247 *up = u0 % u1;
248 break;
249 case MM_pow: *up = lj_cdata_powi64(u0, u1, (id == CTID_UINT64)); break;
250 case MM_unm: *up = (uint64_t)-(int64_t)u0; break;
251 default: lua_assert(0); break;
252 }
253 lj_gc_check(L);
254 return 1;
255 }
256 return 0;
257}
258
259/* cdata arithmetic. */
260static int ffi_arith(lua_State *L)
261{
262 CTState *cts = ctype_cts(L);
263 FFIArith fa;
264 MMS mm = (MMS)(curr_func(L)->c.ffid - (int)FF_ffi_meta___eq + (int)MM_eq);
265 if (ffi_checkarith(L, cts, &fa)) {
266 if (ffi_arith_int64(L, cts, &fa, mm) || ffi_arith_ptr(L, cts, &fa, mm)) {
267 copyTV(L, &G(L)->tmptv2, L->top-1); /* Remember for trace recorder. */
268 return 1;
269 }
270 }
271 /* NYI: per-cdata metamethods. */
272 {
273 const char *repr[2];
274 int i;
275 for (i = 0; i < 2; i++) {
276 if (fa.ct[i])
277 repr[i] = strdata(lj_ctype_repr(L, ctype_typeid(cts, fa.ct[i]), NULL));
278 else
279 repr[i] = typename(&L->base[i]);
280 }
281 lj_err_callerv(L, mm == MM_len ? LJ_ERR_FFI_BADLEN :
282 mm == MM_concat ? LJ_ERR_FFI_BADCONCAT :
283 mm < MM_add ? LJ_ERR_FFI_BADCOMP : LJ_ERR_FFI_BADARITH,
284 repr[0], repr[1]);
285 }
286 return 0; /* unreachable */
287}
288
289/* -- C type metamethods -------------------------------------------------- */ 81/* -- C type metamethods -------------------------------------------------- */
290 82
291#define LJLIB_MODULE_ffi_meta 83#define LJLIB_MODULE_ffi_meta
@@ -319,6 +111,13 @@ LJLIB_CF(ffi_meta___newindex) LJLIB_REC(cdata_index 1)
319 return 0; 111 return 0;
320} 112}
321 113
114/* Common handler for cdata arithmetic. */
115static int ffi_arith(lua_State *L)
116{
117 MMS mm = (MMS)(curr_func(L)->c.ffid - (int)FF_ffi_meta___eq + (int)MM_eq);
118 return lj_carith_op(L, mm);
119}
120
322/* The following functions must be in contiguous ORDER MM. */ 121/* The following functions must be in contiguous ORDER MM. */
323LJLIB_CF(ffi_meta___eq) LJLIB_REC(cdata_arith MM_eq) 122LJLIB_CF(ffi_meta___eq) LJLIB_REC(cdata_arith MM_eq)
324{ 123{
diff --git a/src/lj_carith.c b/src/lj_carith.c
new file mode 100644
index 00000000..a7d92983
--- /dev/null
+++ b/src/lj_carith.c
@@ -0,0 +1,260 @@
1/*
2** C data arithmetic.
3** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h
4*/
5
6#include "lj_obj.h"
7
8#if LJ_HASFFI
9
10#include "lj_gc.h"
11#include "lj_err.h"
12#include "lj_ctype.h"
13#include "lj_cconv.h"
14#include "lj_cdata.h"
15#include "lj_carith.h"
16
17/* -- C data arithmetic --------------------------------------------------- */
18
19/* Binary operands of an operator converted to ctypes. */
20typedef struct CDArith {
21 uint8_t *p[2];
22 CType *ct[2];
23} CDArith;
24
25/* Check arguments for arithmetic metamethods. */
26static int carith_checkarg(lua_State *L, CTState *cts, CDArith *ca)
27{
28 TValue *o = L->base;
29 int ok = 1;
30 MSize i;
31 if (o+1 >= L->top)
32 lj_err_argt(L, 1, LUA_TCDATA);
33 for (i = 0; i < 2; i++, o++) {
34 if (tviscdata(o)) {
35 GCcdata *cd = cdataV(o);
36 CType *ct = ctype_raw(cts, (CTypeID)cd->typeid);
37 uint8_t *p = (uint8_t *)cdataptr(cd);
38 if (ctype_isptr(ct->info)) {
39 p = (uint8_t *)cdata_getptr(p, ct->size);
40 if (ctype_isref(ct->info)) ct = ctype_rawchild(cts, ct);
41 }
42 ca->ct[i] = ct;
43 ca->p[i] = p;
44 } else if (tvisnum(o)) {
45 ca->ct[i] = ctype_get(cts, CTID_DOUBLE);
46 ca->p[i] = (uint8_t *)&o->n;
47 } else if (tvisnil(o)) {
48 ca->ct[i] = ctype_get(cts, CTID_P_VOID);
49 ca->p[i] = (uint8_t *)0;
50 } else {
51 ca->ct[i] = NULL;
52 ca->p[i] = NULL;
53 ok = 0;
54 }
55 }
56 return ok;
57}
58
59/* Pointer arithmetic. */
60static int carith_ptr(lua_State *L, CTState *cts, CDArith *ca, MMS mm)
61{
62 CType *ctp = ca->ct[0];
63 uint8_t *pp = ca->p[0];
64 ptrdiff_t idx;
65 CTSize sz;
66 CTypeID id;
67 GCcdata *cd;
68 if (ctype_isptr(ctp->info) || ctype_isrefarray(ctp->info)) {
69 if ((mm == MM_sub || mm == MM_eq || mm == MM_lt || mm == MM_le) &&
70 (ctype_isptr(ca->ct[1]->info) || ctype_isrefarray(ca->ct[1]->info))) {
71 uint8_t *pp2 = ca->p[1];
72 if (mm == MM_eq) { /* Pointer equality. Incompatible pointers are ok. */
73 setboolV(L->top-1, (pp == pp2));
74 return 1;
75 }
76 if (!lj_cconv_compatptr(cts, ctp, ca->ct[1], CCF_IGNQUAL))
77 return 0;
78 if (mm == MM_sub) { /* Pointer difference. */
79 intptr_t diff;
80 sz = lj_ctype_size(cts, ctype_cid(ctp->info)); /* Element size. */
81 if (sz == 0 || sz == CTSIZE_INVALID)
82 return 0;
83 diff = ((intptr_t)pp - (intptr_t)pp2) / (int32_t)sz;
84 /* All valid pointer differences on x64 are in (-2^47, +2^47),
85 ** which fits into a double without loss of precision.
86 */
87 setnumV(L->top-1, (lua_Number)diff);
88 return 1;
89 } else if (mm == MM_lt) { /* Pointer comparison (unsigned). */
90 setboolV(L->top-1, ((uintptr_t)pp < (uintptr_t)pp2));
91 return 1;
92 } else {
93 lua_assert(mm == MM_le);
94 setboolV(L->top-1, ((uintptr_t)pp <= (uintptr_t)pp2));
95 return 1;
96 }
97 }
98 if (!((mm == MM_add || mm == MM_sub) && ctype_isnum(ca->ct[1]->info)))
99 return 0;
100 lj_cconv_ct_ct(cts, ctype_get(cts, CTID_INT_PSZ), ca->ct[1],
101 (uint8_t *)&idx, ca->p[1], 0);
102 if (mm == MM_sub) idx = -idx;
103 } else if (mm == MM_add && ctype_isnum(ctp->info) &&
104 (ctype_isptr(ca->ct[1]->info) || ctype_isrefarray(ca->ct[1]->info))) {
105 /* Swap pointer and index. */
106 ctp = ca->ct[1]; pp = ca->p[1];
107 lj_cconv_ct_ct(cts, ctype_get(cts, CTID_INT_PSZ), ca->ct[0],
108 (uint8_t *)&idx, ca->p[0], 0);
109 } else {
110 return 0;
111 }
112 sz = lj_ctype_size(cts, ctype_cid(ctp->info)); /* Element size. */
113 if (sz == CTSIZE_INVALID)
114 return 0;
115 pp += idx*(int32_t)sz; /* Compute pointer + index. */
116 id = lj_ctype_intern(cts, CTINFO(CT_PTR, CTALIGN_PTR|ctype_cid(ctp->info)),
117 CTSIZE_PTR);
118 cd = lj_cdata_new(cts, id, CTSIZE_PTR);
119 *(uint8_t **)cdataptr(cd) = pp;
120 setcdataV(L, L->top-1, cd);
121 lj_gc_check(L);
122 return 1;
123}
124
125/* 64 bit integer arithmetic. */
126static int carith_int64(lua_State *L, CTState *cts, CDArith *ca, MMS mm)
127{
128 if (ctype_isnum(ca->ct[0]->info) && ca->ct[0]->size <= 8 &&
129 ctype_isnum(ca->ct[1]->info) && ca->ct[1]->size <= 8) {
130 CTypeID id = (((ca->ct[0]->info & CTF_UNSIGNED) && ca->ct[0]->size == 8) ||
131 ((ca->ct[1]->info & CTF_UNSIGNED) && ca->ct[1]->size == 8)) ?
132 CTID_UINT64 : CTID_INT64;
133 CType *ct = ctype_get(cts, id);
134 GCcdata *cd;
135 uint64_t u0, u1, *up;
136 lj_cconv_ct_ct(cts, ct, ca->ct[0], (uint8_t *)&u0, ca->p[0], 0);
137 if (mm != MM_unm)
138 lj_cconv_ct_ct(cts, ct, ca->ct[1], (uint8_t *)&u1, ca->p[1], 0);
139 switch (mm) {
140 case MM_eq:
141 setboolV(L->top-1, (u0 == u1));
142 return 1;
143 case MM_lt:
144 setboolV(L->top-1,
145 id == CTID_INT64 ? ((int64_t)u0 < (int64_t)u1) : (u0 < u1));
146 return 1;
147 case MM_le:
148 setboolV(L->top-1,
149 id == CTID_INT64 ? ((int64_t)u0 <= (int64_t)u1) : (u0 <= u1));
150 return 1;
151 case MM_div: case MM_mod:
152 if (u1 == 0) { /* Division by zero. */
153 if (u0 == 0)
154 setnanV(L->top-1);
155 else if (id == CTID_INT64 && (int64_t)u0 < 0)
156 setminfV(L->top-1);
157 else
158 setpinfV(L->top-1);
159 return 1;
160 } else if (id == CTID_INT64 && (int64_t)u1 == -1 &&
161 u0 == U64x(80000000,00000000)) { /* MIN64 / -1. */
162 if (mm == MM_div) id = CTID_UINT64; else u0 = 0;
163 mm = MM_unm; /* Result is 0x8000000000000000ULL or 0LL. */
164 }
165 break;
166 default: break;
167 }
168 cd = lj_cdata_new(cts, id, 8);
169 up = (uint64_t *)cdataptr(cd);
170 setcdataV(L, L->top-1, cd);
171 switch (mm) {
172 case MM_add: *up = u0 + u1; break;
173 case MM_sub: *up = u0 - u1; break;
174 case MM_mul: *up = u0 * u1; break;
175 case MM_div:
176 if (id == CTID_INT64)
177 *up = (uint64_t)((int64_t)u0 / (int64_t)u1);
178 else
179 *up = u0 / u1;
180 break;
181 case MM_mod:
182 if (id == CTID_INT64)
183 *up = (uint64_t)((int64_t)u0 % (int64_t)u1);
184 else
185 *up = u0 % u1;
186 break;
187 case MM_pow: *up = lj_carith_powi64(u0, u1, (id == CTID_UINT64)); break;
188 case MM_unm: *up = (uint64_t)-(int64_t)u0; break;
189 default: lua_assert(0); break;
190 }
191 lj_gc_check(L);
192 return 1;
193 }
194 return 0;
195}
196
197/* Arithmetic operators for cdata. */
198int lj_carith_op(lua_State *L, MMS mm)
199{
200 CTState *cts = ctype_cts(L);
201 CDArith ca;
202 if (carith_checkarg(L, cts, &ca)) {
203 if (carith_int64(L, cts, &ca, mm) || carith_ptr(L, cts, &ca, mm)) {
204 copyTV(L, &G(L)->tmptv2, L->top-1); /* Remember for trace recorder. */
205 return 1;
206 }
207 }
208 /* NYI: per-cdata metamethods. */
209 {
210 const char *repr[2];
211 int i;
212 for (i = 0; i < 2; i++) {
213 if (ca.ct[i])
214 repr[i] = strdata(lj_ctype_repr(L, ctype_typeid(cts, ca.ct[i]), NULL));
215 else
216 repr[i] = typename(&L->base[i]);
217 }
218 lj_err_callerv(L, mm == MM_len ? LJ_ERR_FFI_BADLEN :
219 mm == MM_concat ? LJ_ERR_FFI_BADCONCAT :
220 mm < MM_add ? LJ_ERR_FFI_BADCOMP : LJ_ERR_FFI_BADARITH,
221 repr[0], repr[1]);
222 }
223 return 0; /* unreachable */
224}
225
226/* -- 64 bit integer arithmetic helpers ----------------------------------- */
227
228/* 64 bit integer x^k. */
229uint64_t lj_carith_powi64(uint64_t x, uint64_t k, int isunsigned)
230{
231 uint64_t y = 0;
232 if (k == 0)
233 return 1;
234 if (!isunsigned) {
235 if ((int64_t)k < 0) {
236 if (x == 0)
237 return U64x(7fffffff,ffffffff);
238 else if (x == 1)
239 return 1;
240 else if ((int64_t)x == -1)
241 return (k & 1) ? -1 : 1;
242 else
243 return 0;
244 }
245 }
246 for (; (k & 1) == 0; k >>= 1) x *= x;
247 y = x;
248 if ((k >>= 1) != 0) {
249 for (;;) {
250 x *= x;
251 if (k == 1) break;
252 if (k & 1) y *= x;
253 k >>= 1;
254 }
255 y *= x;
256 }
257 return y;
258}
259
260#endif
diff --git a/src/lj_carith.h b/src/lj_carith.h
new file mode 100644
index 00000000..acb095db
--- /dev/null
+++ b/src/lj_carith.h
@@ -0,0 +1,19 @@
1/*
2** C data arithmetic.
3** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h
4*/
5
6#ifndef _LJ_CARITH_H
7#define _LJ_CARITH_H
8
9#include "lj_obj.h"
10
11#if LJ_HASFFI
12
13LJ_FUNC int lj_carith_op(lua_State *L, MMS mm);
14
15LJ_FUNC uint64_t lj_carith_powi64(uint64_t x, uint64_t k, int isunsigned);
16
17#endif
18
19#endif
diff --git a/src/lj_cdata.c b/src/lj_cdata.c
index 9033d492..a3257249 100644
--- a/src/lj_cdata.c
+++ b/src/lj_cdata.c
@@ -251,38 +251,4 @@ void lj_cdata_set(CTState *cts, CType *d, uint8_t *dp, TValue *o, CTInfo qual)
251 lj_cconv_ct_tv(cts, d, dp, o, 0); 251 lj_cconv_ct_tv(cts, d, dp, o, 0);
252} 252}
253 253
254/* -- 64 bit integer arithmetic helpers ----------------------------------- */
255
256/* 64 bit integer x^k. */
257uint64_t lj_cdata_powi64(uint64_t x, uint64_t k, int isunsigned)
258{
259 uint64_t y = 0;
260 if (k == 0)
261 return 1;
262 if (!isunsigned) {
263 if ((int64_t)k < 0) {
264 if (x == 0)
265 return U64x(7fffffff,ffffffff);
266 else if (x == 1)
267 return 1;
268 else if ((int64_t)x == -1)
269 return (k & 1) ? -1 : 1;
270 else
271 return 0;
272 }
273 }
274 for (; (k & 1) == 0; k >>= 1) x *= x;
275 y = x;
276 if ((k >>= 1) != 0) {
277 for (;;) {
278 x *= x;
279 if (k == 1) break;
280 if (k & 1) y *= x;
281 k >>= 1;
282 }
283 y *= x;
284 }
285 return y;
286}
287
288#endif 254#endif
diff --git a/src/lj_cdata.h b/src/lj_cdata.h
index 5b6bd17b..74cdab42 100644
--- a/src/lj_cdata.h
+++ b/src/lj_cdata.h
@@ -69,8 +69,6 @@ LJ_FUNC int lj_cdata_get(CTState *cts, CType *s, TValue *o, uint8_t *sp);
69LJ_FUNC void lj_cdata_set(CTState *cts, CType *d, uint8_t *dp, TValue *o, 69LJ_FUNC void lj_cdata_set(CTState *cts, CType *d, uint8_t *dp, TValue *o,
70 CTInfo qual); 70 CTInfo qual);
71 71
72LJ_FUNC uint64_t lj_cdata_powi64(uint64_t x, uint64_t k, int isunsigned);
73
74#endif 72#endif
75 73
76#endif 74#endif
diff --git a/src/lj_crecord.c b/src/lj_crecord.c
index 3e429705..647c464a 100644
--- a/src/lj_crecord.c
+++ b/src/lj_crecord.c
@@ -689,7 +689,7 @@ static TRef crec_arith_int64(jit_State *J, TRef *sp, CType **s, MMS mm)
689 J->postproc = LJ_POST_FIXGUARD; 689 J->postproc = LJ_POST_FIXGUARD;
690 return TREF_TRUE; 690 return TREF_TRUE;
691 } else if (mm == MM_pow) { 691 } else if (mm == MM_pow) {
692 tr = lj_ir_call(J, IRCALL_lj_cdata_powi64, sp[0], sp[1], 692 tr = lj_ir_call(J, IRCALL_lj_carith_powi64, sp[0], sp[1],
693 lj_ir_kint(J, (int)dt-(int)IRT_I64)); 693 lj_ir_kint(J, (int)dt-(int)IRT_I64));
694 } else { 694 } else {
695 if (mm == MM_div || mm == MM_mod) 695 if (mm == MM_div || mm == MM_mod)
diff --git a/src/lj_ir.c b/src/lj_ir.c
index e1ce5839..1d57938e 100644
--- a/src/lj_ir.c
+++ b/src/lj_ir.c
@@ -24,6 +24,7 @@
24#if LJ_HASFFI 24#if LJ_HASFFI
25#include "lj_ctype.h" 25#include "lj_ctype.h"
26#include "lj_cdata.h" 26#include "lj_cdata.h"
27#include "lj_carith.h"
27#endif 28#endif
28#include "lj_lib.h" 29#include "lj_lib.h"
29 30
diff --git a/src/lj_ir.h b/src/lj_ir.h
index 68901325..6dee36c6 100644
--- a/src/lj_ir.h
+++ b/src/lj_ir.h
@@ -255,7 +255,7 @@ typedef struct CCallInfo {
255/* Function definitions for CALL* instructions. */ 255/* Function definitions for CALL* instructions. */
256#if LJ_HASFFI 256#if LJ_HASFFI
257#define IRCALLDEF_FFI(_) \ 257#define IRCALLDEF_FFI(_) \
258 _(lj_cdata_powi64, 3, N, U64, CCI_NOFPRCLOBBER) 258 _(lj_carith_powi64, 3, N, U64, CCI_NOFPRCLOBBER)
259#else 259#else
260#define IRCALLDEF_FFI(_) 260#define IRCALLDEF_FFI(_)
261#endif 261#endif
diff --git a/src/ljamalg.c b/src/ljamalg.c
index d273753a..4d5f7600 100644
--- a/src/ljamalg.c
+++ b/src/ljamalg.c
@@ -48,6 +48,7 @@
48#include "lj_cdata.c" 48#include "lj_cdata.c"
49#include "lj_cconv.c" 49#include "lj_cconv.c"
50#include "lj_ccall.c" 50#include "lj_ccall.c"
51#include "lj_carith.c"
51#include "lj_clib.c" 52#include "lj_clib.c"
52#include "lj_cparse.c" 53#include "lj_cparse.c"
53#include "lj_lib.c" 54#include "lj_lib.c"