3 ** Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h
17 #include "lj_carith.h"
19 /* -- C data arithmetic --------------------------------------------------- */
21 /* Binary operands of an operator converted to ctypes. */
22 typedef struct CDArith
{
27 /* Check arguments for arithmetic metamethods. */
28 static int carith_checkarg(lua_State
*L
, CTState
*cts
, CDArith
*ca
)
34 lj_err_argt(L
, 1, LUA_TCDATA
);
35 for (i
= 0; i
< 2; i
++, o
++) {
37 GCcdata
*cd
= cdataV(o
);
38 CTypeID id
= (CTypeID
)cd
->typeid;
39 CType
*ct
= ctype_raw(cts
, id
);
40 uint8_t *p
= (uint8_t *)cdataptr(cd
);
41 if (ctype_isptr(ct
->info
)) {
42 p
= (uint8_t *)cdata_getptr(p
, ct
->size
);
43 if (ctype_isref(ct
->info
)) ct
= ctype_rawchild(cts
, ct
);
44 } else if (ctype_isfunc(ct
->info
)) {
45 p
= (uint8_t *)*(void **)p
;
47 lj_ctype_intern(cts
, CTINFO(CT_PTR
, CTALIGN_PTR
|id
), CTSIZE_PTR
));
51 } else if (tvisint(o
)) {
52 ca
->ct
[i
] = ctype_get(cts
, CTID_INT32
);
53 ca
->p
[i
] = (uint8_t *)&o
->i
;
54 } else if (tvisnum(o
)) {
55 ca
->ct
[i
] = ctype_get(cts
, CTID_DOUBLE
);
56 ca
->p
[i
] = (uint8_t *)&o
->n
;
57 } else if (tvisnil(o
)) {
58 ca
->ct
[i
] = ctype_get(cts
, CTID_P_VOID
);
59 ca
->p
[i
] = (uint8_t *)0;
69 /* Pointer arithmetic. */
70 static int carith_ptr(lua_State
*L
, CTState
*cts
, CDArith
*ca
, MMS mm
)
72 CType
*ctp
= ca
->ct
[0];
73 uint8_t *pp
= ca
->p
[0];
78 if (ctype_isptr(ctp
->info
) || ctype_isrefarray(ctp
->info
)) {
79 if ((mm
== MM_sub
|| mm
== MM_eq
|| mm
== MM_lt
|| mm
== MM_le
) &&
80 (ctype_isptr(ca
->ct
[1]->info
) || ctype_isrefarray(ca
->ct
[1]->info
))) {
81 uint8_t *pp2
= ca
->p
[1];
82 if (mm
== MM_eq
) { /* Pointer equality. Incompatible pointers are ok. */
83 setboolV(L
->top
-1, (pp
== pp2
));
86 if (!lj_cconv_compatptr(cts
, ctp
, ca
->ct
[1], CCF_IGNQUAL
))
88 if (mm
== MM_sub
) { /* Pointer difference. */
90 sz
= lj_ctype_size(cts
, ctype_cid(ctp
->info
)); /* Element size. */
91 if (sz
== 0 || sz
== CTSIZE_INVALID
)
93 diff
= ((intptr_t)pp
- (intptr_t)pp2
) / (int32_t)sz
;
94 /* All valid pointer differences on x64 are in (-2^47, +2^47),
95 ** which fits into a double without loss of precision.
97 setintptrV(L
->top
-1, (int32_t)diff
);
99 } else if (mm
== MM_lt
) { /* Pointer comparison (unsigned). */
100 setboolV(L
->top
-1, ((uintptr_t)pp
< (uintptr_t)pp2
));
103 lua_assert(mm
== MM_le
);
104 setboolV(L
->top
-1, ((uintptr_t)pp
<= (uintptr_t)pp2
));
108 if (!((mm
== MM_add
|| mm
== MM_sub
) && ctype_isnum(ca
->ct
[1]->info
)))
110 lj_cconv_ct_ct(cts
, ctype_get(cts
, CTID_INT_PSZ
), ca
->ct
[1],
111 (uint8_t *)&idx
, ca
->p
[1], 0);
112 if (mm
== MM_sub
) idx
= -idx
;
113 } else if (mm
== MM_add
&& ctype_isnum(ctp
->info
) &&
114 (ctype_isptr(ca
->ct
[1]->info
) || ctype_isrefarray(ca
->ct
[1]->info
))) {
115 /* Swap pointer and index. */
116 ctp
= ca
->ct
[1]; pp
= ca
->p
[1];
117 lj_cconv_ct_ct(cts
, ctype_get(cts
, CTID_INT_PSZ
), ca
->ct
[0],
118 (uint8_t *)&idx
, ca
->p
[0], 0);
122 sz
= lj_ctype_size(cts
, ctype_cid(ctp
->info
)); /* Element size. */
123 if (sz
== CTSIZE_INVALID
)
125 pp
+= idx
*(int32_t)sz
; /* Compute pointer + index. */
126 id
= lj_ctype_intern(cts
, CTINFO(CT_PTR
, CTALIGN_PTR
|ctype_cid(ctp
->info
)),
128 cd
= lj_cdata_new(cts
, id
, CTSIZE_PTR
);
129 *(uint8_t **)cdataptr(cd
) = pp
;
130 setcdataV(L
, L
->top
-1, cd
);
135 /* 64 bit integer arithmetic. */
136 static int carith_int64(lua_State
*L
, CTState
*cts
, CDArith
*ca
, MMS mm
)
138 if (ctype_isnum(ca
->ct
[0]->info
) && ca
->ct
[0]->size
<= 8 &&
139 ctype_isnum(ca
->ct
[1]->info
) && ca
->ct
[1]->size
<= 8) {
140 CTypeID id
= (((ca
->ct
[0]->info
& CTF_UNSIGNED
) && ca
->ct
[0]->size
== 8) ||
141 ((ca
->ct
[1]->info
& CTF_UNSIGNED
) && ca
->ct
[1]->size
== 8)) ?
142 CTID_UINT64
: CTID_INT64
;
143 CType
*ct
= ctype_get(cts
, id
);
145 uint64_t u0
, u1
, *up
;
146 lj_cconv_ct_ct(cts
, ct
, ca
->ct
[0], (uint8_t *)&u0
, ca
->p
[0], 0);
148 lj_cconv_ct_ct(cts
, ct
, ca
->ct
[1], (uint8_t *)&u1
, ca
->p
[1], 0);
151 setboolV(L
->top
-1, (u0
== u1
));
155 id
== CTID_INT64
? ((int64_t)u0
< (int64_t)u1
) : (u0
< u1
));
159 id
== CTID_INT64
? ((int64_t)u0
<= (int64_t)u1
) : (u0
<= u1
));
163 cd
= lj_cdata_new(cts
, id
, 8);
164 up
= (uint64_t *)cdataptr(cd
);
165 setcdataV(L
, L
->top
-1, cd
);
167 case MM_add
: *up
= u0
+ u1
; break;
168 case MM_sub
: *up
= u0
- u1
; break;
169 case MM_mul
: *up
= u0
* u1
; break;
171 if (id
== CTID_INT64
)
172 *up
= (uint64_t)lj_carith_divi64((int64_t)u0
, (int64_t)u1
);
174 *up
= lj_carith_divu64(u0
, u1
);
177 if (id
== CTID_INT64
)
178 *up
= (uint64_t)lj_carith_modi64((int64_t)u0
, (int64_t)u1
);
180 *up
= lj_carith_modu64(u0
, u1
);
183 if (id
== CTID_INT64
)
184 *up
= (uint64_t)lj_carith_powi64((int64_t)u0
, (int64_t)u1
);
186 *up
= lj_carith_powu64(u0
, u1
);
188 case MM_unm
: *up
= (uint64_t)-(int64_t)u0
; break;
189 default: lua_assert(0); break;
197 /* Handle ctype arithmetic metamethods. */
198 static int lj_carith_meta(lua_State
*L
, CTState
*cts
, CDArith
*ca
, MMS mm
)
201 if (tviscdata(L
->base
))
202 tv
= lj_ctype_meta(cts
, cdataV(L
->base
)->typeid, mm
);
203 if (!tv
&& L
->base
+1 < L
->top
&& tviscdata(L
->base
+1))
204 tv
= lj_ctype_meta(cts
, cdataV(L
->base
+1)->typeid, mm
);
208 for (i
= 0; i
< 2; i
++) {
210 repr
[i
] = strdata(lj_ctype_repr(L
, ctype_typeid(cts
, ca
->ct
[i
]), NULL
));
212 repr
[i
] = typename(&L
->base
[i
]);
214 lj_err_callerv(L
, mm
== MM_len
? LJ_ERR_FFI_BADLEN
:
215 mm
== MM_concat
? LJ_ERR_FFI_BADCONCAT
:
216 mm
< MM_add
? LJ_ERR_FFI_BADCOMP
: LJ_ERR_FFI_BADARITH
,
219 return lj_meta_tailcall(L
, tv
);
222 /* Arithmetic operators for cdata. */
223 int lj_carith_op(lua_State
*L
, MMS mm
)
225 CTState
*cts
= ctype_cts(L
);
227 if (carith_checkarg(L
, cts
, &ca
)) {
228 if (carith_int64(L
, cts
, &ca
, mm
) || carith_ptr(L
, cts
, &ca
, mm
)) {
229 copyTV(L
, &G(L
)->tmptv2
, L
->top
-1); /* Remember for trace recorder. */
233 return lj_carith_meta(L
, cts
, &ca
, mm
);
236 /* -- 64 bit integer arithmetic helpers ----------------------------------- */
238 #if LJ_32 && LJ_HASJIT
239 /* Signed/unsigned 64 bit multiplication. */
240 int64_t lj_carith_mul64(int64_t a
, int64_t b
)
246 /* Unsigned 64 bit division. */
247 uint64_t lj_carith_divu64(uint64_t a
, uint64_t b
)
249 if (b
== 0) return U64x(80000000,00000000);
253 /* Signed 64 bit division. */
254 int64_t lj_carith_divi64(int64_t a
, int64_t b
)
256 if (b
== 0 || (a
== (int64_t)U64x(80000000,00000000) && b
== -1))
257 return U64x(80000000,00000000);
261 /* Unsigned 64 bit modulo. */
262 uint64_t lj_carith_modu64(uint64_t a
, uint64_t b
)
264 if (b
== 0) return U64x(80000000,00000000);
268 /* Signed 64 bit modulo. */
269 int64_t lj_carith_modi64(int64_t a
, int64_t b
)
271 if (b
== 0) return U64x(80000000,00000000);
272 if (a
== (int64_t)U64x(80000000,00000000) && b
== -1) return 0;
276 /* Unsigned 64 bit x^k. */
277 uint64_t lj_carith_powu64(uint64_t x
, uint64_t k
)
282 for (; (k
& 1) == 0; k
>>= 1) x
*= x
;
284 if ((k
>>= 1) != 0) {
296 /* Signed 64 bit x^k. */
297 int64_t lj_carith_powi64(int64_t x
, int64_t k
)
303 return U64x(7fffffff
,ffffffff
);
307 return (k
& 1) ? -1 : 1;
311 return (int64_t)lj_carith_powu64((uint64_t)x
, (uint64_t)k
);