summaryrefslogtreecommitdiff
path: root/src/lib_ffi.c
diff options
context:
space:
mode:
authorMike Pall <mike>2011-01-13 02:35:29 +0100
committerMike Pall <mike>2011-01-13 02:35:29 +0100
commit0ec7f5ed92b6b9720c80669b2de3aa3c40967153 (patch)
treed4ea028d9db343d77985df658b4370b838050523 /src/lib_ffi.c
parente7b08b2361dd9e3f945dfd4b7e34c4aad2243582 (diff)
downloadluajit-0ec7f5ed92b6b9720c80669b2de3aa3c40967153.tar.gz
luajit-0ec7f5ed92b6b9720c80669b2de3aa3c40967153.tar.bz2
luajit-0ec7f5ed92b6b9720c80669b2de3aa3c40967153.zip
FFI: Add 64 bit integer comparisons and pointer comparisons.
Diffstat (limited to 'src/lib_ffi.c')
-rw-r--r--src/lib_ffi.c126
1 files changed, 98 insertions, 28 deletions
diff --git a/src/lib_ffi.c b/src/lib_ffi.c
index aeeb0bc1..89baa356 100644
--- a/src/lib_ffi.c
+++ b/src/lib_ffi.c
@@ -85,9 +85,10 @@ typedef struct FFIArith {
85} FFIArith; 85} FFIArith;
86 86
87/* Check arguments for arithmetic metamethods. */ 87/* Check arguments for arithmetic metamethods. */
88static void ffi_checkarith(lua_State *L, CTState *cts, FFIArith *fa) 88static int ffi_checkarith(lua_State *L, CTState *cts, FFIArith *fa)
89{ 89{
90 TValue *o = L->base; 90 TValue *o = L->base;
91 int ok = 1;
91 MSize i; 92 MSize i;
92 if (o+1 >= L->top) 93 if (o+1 >= L->top)
93 lj_err_argt(L, 1, LUA_TCDATA); 94 lj_err_argt(L, 1, LUA_TCDATA);
@@ -105,10 +106,16 @@ static void ffi_checkarith(lua_State *L, CTState *cts, FFIArith *fa)
105 } else if (tvisnum(o)) { 106 } else if (tvisnum(o)) {
106 fa->ct[i] = ctype_get(cts, CTID_DOUBLE); 107 fa->ct[i] = ctype_get(cts, CTID_DOUBLE);
107 fa->p[i] = (uint8_t *)&o->n; 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;
108 } else { 112 } else {
109 lj_err_optype(L, o, LJ_ERR_OPARITH); 113 fa->ct[i] = NULL;
114 fa->p[i] = NULL;
115 ok = 0;
110 } 116 }
111 } 117 }
118 return ok;
112} 119}
113 120
114/* Pointer arithmetic. */ 121/* Pointer arithmetic. */
@@ -120,26 +127,38 @@ static int ffi_arith_ptr(lua_State *L, CTState *cts, FFIArith *fa, MMS mm)
120 CTSize sz; 127 CTSize sz;
121 CTypeID id; 128 CTypeID id;
122 GCcdata *cd; 129 GCcdata *cd;
123 if (!(mm == MM_add || mm == MM_sub))
124 return 0;
125 if (ctype_isptr(ctp->info) || ctype_isrefarray(ctp->info)) { 130 if (ctype_isptr(ctp->info) || ctype_isrefarray(ctp->info)) {
126 if (mm == MM_sub && 131 if ((mm == MM_sub || mm == MM_eq || mm == MM_lt || mm == MM_le) &&
127 (ctype_isptr(fa->ct[1]->info) || ctype_isrefarray(fa->ct[1]->info))) { 132 (ctype_isptr(fa->ct[1]->info) || ctype_isrefarray(fa->ct[1]->info))) {
128 /* Pointer difference. */ 133 uint8_t *pp2 = fa->p[1];
129 intptr_t diff; 134 if (mm == MM_eq) { /* Pointer equality. Incompatible pointers are ok. */
135 setboolV(L->top-1, (pp == pp2));
136 return 1;
137 }
130 if (!lj_cconv_compatptr(cts, ctp, fa->ct[1], CCF_IGNQUAL)) 138 if (!lj_cconv_compatptr(cts, ctp, fa->ct[1], CCF_IGNQUAL))
131 lj_err_caller(L, LJ_ERR_FFI_INVTYPE); 139 return 0;
132 sz = lj_ctype_size(cts, ctype_cid(ctp->info)); /* Element size. */ 140 if (mm == MM_sub) { /* Pointer difference. */
133 if (sz == 0 || sz == CTSIZE_INVALID) 141 intptr_t diff;
134 lj_err_caller(L, LJ_ERR_FFI_INVSIZE); 142 sz = lj_ctype_size(cts, ctype_cid(ctp->info)); /* Element size. */
135 diff = ((intptr_t)pp - (intptr_t)fa->p[1]) / (int32_t)sz; 143 if (sz == 0 || sz == CTSIZE_INVALID)
136 /* All valid pointer differences on x64 are in (-2^47, +2^47), 144 return 0;
137 ** which fits into a double without loss of precision. 145 diff = ((intptr_t)pp - (intptr_t)pp2) / (int32_t)sz;
138 */ 146 /* All valid pointer differences on x64 are in (-2^47, +2^47),
139 setnumV(L->top-1, (lua_Number)diff); 147 ** which fits into a double without loss of precision.
140 return 1; 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 }
141 } 159 }
142 if (!ctype_isnum(fa->ct[1]->info)) return 0; 160 if (!((mm == MM_add || mm == MM_sub) &&
161 ctype_isnum(fa->ct[1]->info))) return 0;
143 lj_cconv_ct_ct(cts, ctype_get(cts, CTID_INT_PSZ), fa->ct[1], 162 lj_cconv_ct_ct(cts, ctype_get(cts, CTID_INT_PSZ), fa->ct[1],
144 (uint8_t *)&idx, fa->p[1], 0); 163 (uint8_t *)&idx, fa->p[1], 0);
145 if (mm == MM_sub) idx = -idx; 164 if (mm == MM_sub) idx = -idx;
@@ -155,7 +174,7 @@ static int ffi_arith_ptr(lua_State *L, CTState *cts, FFIArith *fa, MMS mm)
155 } 174 }
156 sz = lj_ctype_size(cts, ctype_cid(ctp->info)); /* Element size. */ 175 sz = lj_ctype_size(cts, ctype_cid(ctp->info)); /* Element size. */
157 if (sz == CTSIZE_INVALID) 176 if (sz == CTSIZE_INVALID)
158 lj_err_caller(L, LJ_ERR_FFI_INVSIZE); 177 return 0;
159 pp += idx*(int32_t)sz; /* Compute pointer + index. */ 178 pp += idx*(int32_t)sz; /* Compute pointer + index. */
160 id = lj_ctype_intern(cts, CTINFO(CT_PTR, CTALIGN_PTR|ctype_cid(ctp->info)), 179 id = lj_ctype_intern(cts, CTINFO(CT_PTR, CTALIGN_PTR|ctype_cid(ctp->info)),
161 CTSIZE_PTR); 180 CTSIZE_PTR);
@@ -180,7 +199,19 @@ static int ffi_arith_int64(lua_State *L, CTState *cts, FFIArith *fa, MMS mm)
180 lj_cconv_ct_ct(cts, ct, fa->ct[0], (uint8_t *)&u0, fa->p[0], 0); 199 lj_cconv_ct_ct(cts, ct, fa->ct[0], (uint8_t *)&u0, fa->p[0], 0);
181 if (mm != MM_unm) 200 if (mm != MM_unm)
182 lj_cconv_ct_ct(cts, ct, fa->ct[1], (uint8_t *)&u1, fa->p[1], 0); 201 lj_cconv_ct_ct(cts, ct, fa->ct[1], (uint8_t *)&u1, fa->p[1], 0);
183 if ((mm == MM_div || mm == MM_mod)) { 202 switch (mm) {
203 case MM_eq:
204 setboolV(L->top-1, (u0 == u1));
205 return 1;
206 case MM_lt:
207 setboolV(L->top-1,
208 id == CTID_INT64 ? ((int64_t)u0 < (int64_t)u1) : (u0 < u1));
209 return 1;
210 case MM_le:
211 setboolV(L->top-1,
212 id == CTID_INT64 ? ((int64_t)u0 <= (int64_t)u1) : (u0 <= u1));
213 return 1;
214 case MM_div: case MM_mod:
184 if (u1 == 0) { /* Division by zero. */ 215 if (u1 == 0) { /* Division by zero. */
185 if (u0 == 0) 216 if (u0 == 0)
186 setnanV(L->top-1); 217 setnanV(L->top-1);
@@ -194,6 +225,8 @@ static int ffi_arith_int64(lua_State *L, CTState *cts, FFIArith *fa, MMS mm)
194 if (mm == MM_div) id = CTID_UINT64; else u0 = 0; 225 if (mm == MM_div) id = CTID_UINT64; else u0 = 0;
195 mm = MM_unm; /* Result is 0x8000000000000000ULL or 0LL. */ 226 mm = MM_unm; /* Result is 0x8000000000000000ULL or 0LL. */
196 } 227 }
228 break;
229 default: break;
197 } 230 }
198 cd = lj_cdata_new(cts, id, 8); 231 cd = lj_cdata_new(cts, id, 8);
199 up = (uint64_t *)cdataptr(cd); 232 up = (uint64_t *)cdataptr(cd);
@@ -229,17 +262,27 @@ static int ffi_arith(lua_State *L)
229{ 262{
230 CTState *cts = ctype_cts(L); 263 CTState *cts = ctype_cts(L);
231 FFIArith fa; 264 FFIArith fa;
232 MMS mm = (MMS)(curr_func(L)->c.ffid - (int)FF_ffi_meta___add + (int)MM_add); 265 MMS mm = (MMS)(curr_func(L)->c.ffid - (int)FF_ffi_meta___eq + (int)MM_eq);
233 ffi_checkarith(L, cts, &fa); 266 if (ffi_checkarith(L, cts, &fa)) {
234 if (!ffi_arith_int64(L, cts, &fa, mm) && 267 if (ffi_arith_int64(L, cts, &fa, mm) || ffi_arith_ptr(L, cts, &fa, mm))
235 !ffi_arith_ptr(L, cts, &fa, mm)) { 268 return 1;
269 }
270 /* NYI: per-cdata metamethods. */
271 {
236 const char *repr[2]; 272 const char *repr[2];
237 int i; 273 int i;
238 for (i = 0; i < 2; i++) 274 for (i = 0; i < 2; i++) {
239 repr[i] = strdata(lj_ctype_repr(L, ctype_typeid(cts, fa.ct[i]), NULL)); 275 if (fa.ct[i])
240 lj_err_callerv(L, LJ_ERR_FFI_BADARITH, repr[0], repr[1]); 276 repr[i] = strdata(lj_ctype_repr(L, ctype_typeid(cts, fa.ct[i]), NULL));
277 else
278 repr[i] = typename(&L->base[i]);
279 }
280 lj_err_callerv(L, mm == MM_len ? LJ_ERR_FFI_BADLEN :
281 mm == MM_concat ? LJ_ERR_FFI_BADCONCAT :
282 mm < MM_add ? LJ_ERR_FFI_BADCOMP : LJ_ERR_FFI_BADARITH,
283 repr[0], repr[1]);
241 } 284 }
242 return 1; 285 return 0; /* unreachable */
243} 286}
244 287
245/* -- C type metamethods -------------------------------------------------- */ 288/* -- C type metamethods -------------------------------------------------- */
@@ -275,6 +318,32 @@ LJLIB_CF(ffi_meta___newindex) LJLIB_REC(cdata_index 1)
275 return 0; 318 return 0;
276} 319}
277 320
321/* The following functions must be in contiguous ORDER MM. */
322LJLIB_CF(ffi_meta___eq)
323{
324 return ffi_arith(L);
325}
326
327LJLIB_CF(ffi_meta___len)
328{
329 return ffi_arith(L);
330}
331
332LJLIB_CF(ffi_meta___lt)
333{
334 return ffi_arith(L);
335}
336
337LJLIB_CF(ffi_meta___le)
338{
339 return ffi_arith(L);
340}
341
342LJLIB_CF(ffi_meta___concat)
343{
344 return ffi_arith(L);
345}
346
278/* Forward declaration. */ 347/* Forward declaration. */
279static int lj_cf_ffi_new(lua_State *L); 348static int lj_cf_ffi_new(lua_State *L);
280 349
@@ -324,6 +393,7 @@ LJLIB_CF(ffi_meta___unm) LJLIB_REC(cdata_arith MM_unm)
324{ 393{
325 return ffi_arith(L); 394 return ffi_arith(L);
326} 395}
396/* End of contiguous ORDER MM. */
327 397
328LJLIB_CF(ffi_meta___tostring) 398LJLIB_CF(ffi_meta___tostring)
329{ 399{