diff options
author | Mike Pall <mike> | 2011-01-13 02:35:29 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2011-01-13 02:35:29 +0100 |
commit | 0ec7f5ed92b6b9720c80669b2de3aa3c40967153 (patch) | |
tree | d4ea028d9db343d77985df658b4370b838050523 /src/lib_ffi.c | |
parent | e7b08b2361dd9e3f945dfd4b7e34c4aad2243582 (diff) | |
download | luajit-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.c | 126 |
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. */ |
88 | static void ffi_checkarith(lua_State *L, CTState *cts, FFIArith *fa) | 88 | static 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. */ | ||
322 | LJLIB_CF(ffi_meta___eq) | ||
323 | { | ||
324 | return ffi_arith(L); | ||
325 | } | ||
326 | |||
327 | LJLIB_CF(ffi_meta___len) | ||
328 | { | ||
329 | return ffi_arith(L); | ||
330 | } | ||
331 | |||
332 | LJLIB_CF(ffi_meta___lt) | ||
333 | { | ||
334 | return ffi_arith(L); | ||
335 | } | ||
336 | |||
337 | LJLIB_CF(ffi_meta___le) | ||
338 | { | ||
339 | return ffi_arith(L); | ||
340 | } | ||
341 | |||
342 | LJLIB_CF(ffi_meta___concat) | ||
343 | { | ||
344 | return ffi_arith(L); | ||
345 | } | ||
346 | |||
278 | /* Forward declaration. */ | 347 | /* Forward declaration. */ |
279 | static int lj_cf_ffi_new(lua_State *L); | 348 | static 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 | ||
328 | LJLIB_CF(ffi_meta___tostring) | 398 | LJLIB_CF(ffi_meta___tostring) |
329 | { | 399 | { |