3 ** Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h
18 #include "lj_carith.h"
19 #include "lj_strscan.h"
21 /* -- C data arithmetic --------------------------------------------------- */
23 /* Binary operands of an operator converted to ctypes. */
24 typedef struct CDArith
{
29 /* Check arguments for arithmetic metamethods. */
30 static int carith_checkarg(lua_State
*L
, CTState
*cts
, CDArith
*ca
)
36 lj_err_argt(L
, 1, LUA_TCDATA
);
37 for (i
= 0; i
< 2; i
++, o
++) {
39 GCcdata
*cd
= cdataV(o
);
40 CTypeID id
= (CTypeID
)cd
->ctypeid
;
41 CType
*ct
= ctype_raw(cts
, id
);
42 uint8_t *p
= (uint8_t *)cdataptr(cd
);
43 if (ctype_isptr(ct
->info
)) {
44 p
= (uint8_t *)cdata_getptr(p
, ct
->size
);
45 if (ctype_isref(ct
->info
)) ct
= ctype_rawchild(cts
, ct
);
46 } else if (ctype_isfunc(ct
->info
)) {
47 CTypeID id0
= i
? ctype_typeid(cts
, ca
->ct
[0]) : 0;
48 p
= (uint8_t *)*(void **)p
;
50 lj_ctype_intern(cts
, CTINFO(CT_PTR
, CTALIGN_PTR
|id
), CTSIZE_PTR
));
51 if (i
) { /* cts->tab may have been reallocated. */
52 ca
->ct
[0] = ctype_get(cts
, id0
);
55 if (ctype_isenum(ct
->info
)) ct
= ctype_child(cts
, ct
);
58 } else if (tvisint(o
)) {
59 ca
->ct
[i
] = ctype_get(cts
, CTID_INT32
);
60 ca
->p
[i
] = (uint8_t *)&o
->i
;
61 } else if (tvisnum(o
)) {
62 ca
->ct
[i
] = ctype_get(cts
, CTID_DOUBLE
);
63 ca
->p
[i
] = (uint8_t *)&o
->n
;
64 } else if (tvisnil(o
)) {
65 ca
->ct
[i
] = ctype_get(cts
, CTID_P_VOID
);
66 ca
->p
[i
] = (uint8_t *)0;
67 } else if (tvisstr(o
)) {
68 TValue
*o2
= i
== 0 ? o
+1 : o
-1;
69 CType
*ct
= ctype_raw(cts
, cdataV(o2
)->ctypeid
);
71 ca
->p
[i
] = (uint8_t *)strVdata(o
);
73 if (ctype_isenum(ct
->info
)) {
75 CType
*cct
= lj_ctype_getfield(cts
, ct
, strV(o
), &ofs
);
76 if (cct
&& ctype_isconstval(cct
->info
)) {
77 ca
->ct
[i
] = ctype_child(cts
, cct
);
78 ca
->p
[i
] = (uint8_t *)&cct
->size
; /* Assumes ct does not grow. */
81 ca
->ct
[1-i
] = ct
; /* Use enum to improve error message. */
88 ca
->p
[i
] = (void *)(intptr_t)1; /* To make it unequal. */
95 /* Pointer arithmetic. */
96 static int carith_ptr(lua_State
*L
, CTState
*cts
, CDArith
*ca
, MMS mm
)
98 CType
*ctp
= ca
->ct
[0];
99 uint8_t *pp
= ca
->p
[0];
104 if (ctype_isptr(ctp
->info
) || ctype_isrefarray(ctp
->info
)) {
105 if ((mm
== MM_sub
|| mm
== MM_eq
|| mm
== MM_lt
|| mm
== MM_le
) &&
106 (ctype_isptr(ca
->ct
[1]->info
) || ctype_isrefarray(ca
->ct
[1]->info
))) {
107 uint8_t *pp2
= ca
->p
[1];
108 if (mm
== MM_eq
) { /* Pointer equality. Incompatible pointers are ok. */
109 setboolV(L
->top
-1, (pp
== pp2
));
112 if (!lj_cconv_compatptr(cts
, ctp
, ca
->ct
[1], CCF_IGNQUAL
))
114 if (mm
== MM_sub
) { /* Pointer difference. */
116 sz
= lj_ctype_size(cts
, ctype_cid(ctp
->info
)); /* Element size. */
117 if (sz
== 0 || sz
== CTSIZE_INVALID
)
119 diff
= ((intptr_t)pp
- (intptr_t)pp2
) / (int32_t)sz
;
120 /* All valid pointer differences on x64 are in (-2^47, +2^47),
121 ** which fits into a double without loss of precision.
123 setintptrV(L
->top
-1, (int32_t)diff
);
125 } else if (mm
== MM_lt
) { /* Pointer comparison (unsigned). */
126 setboolV(L
->top
-1, ((uintptr_t)pp
< (uintptr_t)pp2
));
129 lj_assertL(mm
== MM_le
, "bad metamethod %d", mm
);
130 setboolV(L
->top
-1, ((uintptr_t)pp
<= (uintptr_t)pp2
));
134 if (!((mm
== MM_add
|| mm
== MM_sub
) && ctype_isnum(ca
->ct
[1]->info
)))
136 lj_cconv_ct_ct(cts
, ctype_get(cts
, CTID_INT_PSZ
), ca
->ct
[1],
137 (uint8_t *)&idx
, ca
->p
[1], 0);
138 if (mm
== MM_sub
) idx
= -idx
;
139 } else if (mm
== MM_add
&& ctype_isnum(ctp
->info
) &&
140 (ctype_isptr(ca
->ct
[1]->info
) || ctype_isrefarray(ca
->ct
[1]->info
))) {
141 /* Swap pointer and index. */
142 ctp
= ca
->ct
[1]; pp
= ca
->p
[1];
143 lj_cconv_ct_ct(cts
, ctype_get(cts
, CTID_INT_PSZ
), ca
->ct
[0],
144 (uint8_t *)&idx
, ca
->p
[0], 0);
148 sz
= lj_ctype_size(cts
, ctype_cid(ctp
->info
)); /* Element size. */
149 if (sz
== CTSIZE_INVALID
)
151 pp
+= idx
*(int32_t)sz
; /* Compute pointer + index. */
152 id
= lj_ctype_intern(cts
, CTINFO(CT_PTR
, CTALIGN_PTR
|ctype_cid(ctp
->info
)),
154 cd
= lj_cdata_new(cts
, id
, CTSIZE_PTR
);
155 *(uint8_t **)cdataptr(cd
) = pp
;
156 setcdataV(L
, L
->top
-1, cd
);
161 /* 64 bit integer arithmetic. */
162 static int carith_int64(lua_State
*L
, CTState
*cts
, CDArith
*ca
, MMS mm
)
164 if (ctype_isnum(ca
->ct
[0]->info
) && ca
->ct
[0]->size
<= 8 &&
165 ctype_isnum(ca
->ct
[1]->info
) && ca
->ct
[1]->size
<= 8) {
166 CTypeID id
= (((ca
->ct
[0]->info
& CTF_UNSIGNED
) && ca
->ct
[0]->size
== 8) ||
167 ((ca
->ct
[1]->info
& CTF_UNSIGNED
) && ca
->ct
[1]->size
== 8)) ?
168 CTID_UINT64
: CTID_INT64
;
169 CType
*ct
= ctype_get(cts
, id
);
171 uint64_t u0
, u1
, *up
;
172 lj_cconv_ct_ct(cts
, ct
, ca
->ct
[0], (uint8_t *)&u0
, ca
->p
[0], 0);
174 lj_cconv_ct_ct(cts
, ct
, ca
->ct
[1], (uint8_t *)&u1
, ca
->p
[1], 0);
177 setboolV(L
->top
-1, (u0
== u1
));
181 id
== CTID_INT64
? ((int64_t)u0
< (int64_t)u1
) : (u0
< u1
));
185 id
== CTID_INT64
? ((int64_t)u0
<= (int64_t)u1
) : (u0
<= u1
));
189 cd
= lj_cdata_new(cts
, id
, 8);
190 up
= (uint64_t *)cdataptr(cd
);
191 setcdataV(L
, L
->top
-1, cd
);
193 case MM_add
: *up
= u0
+ u1
; break;
194 case MM_sub
: *up
= u0
- u1
; break;
195 case MM_mul
: *up
= u0
* u1
; break;
197 if (id
== CTID_INT64
)
198 *up
= (uint64_t)lj_carith_divi64((int64_t)u0
, (int64_t)u1
);
200 *up
= lj_carith_divu64(u0
, u1
);
203 if (id
== CTID_INT64
)
204 *up
= (uint64_t)lj_carith_modi64((int64_t)u0
, (int64_t)u1
);
206 *up
= lj_carith_modu64(u0
, u1
);
209 if (id
== CTID_INT64
)
210 *up
= (uint64_t)lj_carith_powi64((int64_t)u0
, (int64_t)u1
);
212 *up
= lj_carith_powu64(u0
, u1
);
214 case MM_unm
: *up
= ~u0
+1u; break;
216 lj_assertL(0, "bad metamethod %d", mm
);
225 /* Handle ctype arithmetic metamethods. */
226 static int lj_carith_meta(lua_State
*L
, CTState
*cts
, CDArith
*ca
, MMS mm
)
229 if (tviscdata(L
->base
)) {
230 CTypeID id
= cdataV(L
->base
)->ctypeid
;
231 CType
*ct
= ctype_raw(cts
, id
);
232 if (ctype_isptr(ct
->info
)) id
= ctype_cid(ct
->info
);
233 tv
= lj_ctype_meta(cts
, id
, mm
);
235 if (!tv
&& L
->base
+1 < L
->top
&& tviscdata(L
->base
+1)) {
236 CTypeID id
= cdataV(L
->base
+1)->ctypeid
;
237 CType
*ct
= ctype_raw(cts
, id
);
238 if (ctype_isptr(ct
->info
)) id
= ctype_cid(ct
->info
);
239 tv
= lj_ctype_meta(cts
, id
, mm
);
243 int i
, isenum
= -1, isstr
= -1;
244 if (mm
== MM_eq
) { /* Equality checks never raise an error. */
245 int eq
= ca
->p
[0] == ca
->p
[1];
246 setboolV(L
->top
-1, eq
);
247 setboolV(&G(L
)->tmptv2
, eq
); /* Remember for trace recorder. */
250 for (i
= 0; i
< 2; i
++) {
251 if (ca
->ct
[i
] && tviscdata(L
->base
+i
)) {
252 if (ctype_isenum(ca
->ct
[i
]->info
)) isenum
= i
;
253 repr
[i
] = strdata(lj_ctype_repr(L
, ctype_typeid(cts
, ca
->ct
[i
]), NULL
));
255 if (tvisstr(&L
->base
[i
])) isstr
= i
;
256 repr
[i
] = lj_typename(&L
->base
[i
]);
259 if ((isenum
^ isstr
) == 1)
260 lj_err_callerv(L
, LJ_ERR_FFI_BADCONV
, repr
[isstr
], repr
[isenum
]);
261 lj_err_callerv(L
, mm
== MM_len
? LJ_ERR_FFI_BADLEN
:
262 mm
== MM_concat
? LJ_ERR_FFI_BADCONCAT
:
263 mm
< MM_add
? LJ_ERR_FFI_BADCOMP
: LJ_ERR_FFI_BADARITH
,
266 return lj_meta_tailcall(L
, tv
);
269 /* Arithmetic operators for cdata. */
270 int lj_carith_op(lua_State
*L
, MMS mm
)
272 CTState
*cts
= ctype_cts(L
);
274 if (carith_checkarg(L
, cts
, &ca
) && mm
!= MM_len
&& mm
!= MM_concat
) {
275 if (carith_int64(L
, cts
, &ca
, mm
) || carith_ptr(L
, cts
, &ca
, mm
)) {
276 copyTV(L
, &G(L
)->tmptv2
, L
->top
-1); /* Remember for trace recorder. */
280 return lj_carith_meta(L
, cts
, &ca
, mm
);
283 /* -- 64 bit bit operations helpers --------------------------------------- */
286 #define B64DEF(name) \
287 static LJ_AINLINE uint64_t lj_carith_##name(uint64_t x, int32_t sh)
289 /* Not inlined on 32 bit archs, since some of these are quite lengthy. */
290 #define B64DEF(name) \
291 uint64_t LJ_NOINLINE lj_carith_##name(uint64_t x, int32_t sh)
294 B64DEF(shl64
) { return x
<< (sh
&63); }
295 B64DEF(shr64
) { return x
>> (sh
&63); }
296 B64DEF(sar64
) { return (uint64_t)((int64_t)x
>> (sh
&63)); }
297 B64DEF(rol64
) { return lj_rol(x
, (sh
&63)); }
298 B64DEF(ror64
) { return lj_ror(x
, (sh
&63)); }
302 uint64_t lj_carith_shift64(uint64_t x
, int32_t sh
, int op
)
305 case IR_BSHL
-IR_BSHL
: x
= lj_carith_shl64(x
, sh
); break;
306 case IR_BSHR
-IR_BSHL
: x
= lj_carith_shr64(x
, sh
); break;
307 case IR_BSAR
-IR_BSHL
: x
= lj_carith_sar64(x
, sh
); break;
308 case IR_BROL
-IR_BSHL
: x
= lj_carith_rol64(x
, sh
); break;
309 case IR_BROR
-IR_BSHL
: x
= lj_carith_ror64(x
, sh
); break;
311 lj_assertX(0, "bad shift op %d", op
);
317 /* Equivalent to lj_lib_checkbit(), but handles cdata. */
318 uint64_t lj_carith_check64(lua_State
*L
, int narg
, CTypeID
*id
)
320 TValue
*o
= L
->base
+ narg
-1;
323 lj_err_argt(L
, narg
, LUA_TNUMBER
);
324 } else if (LJ_LIKELY(tvisnumber(o
))) {
326 } else if (tviscdata(o
)) {
327 CTState
*cts
= ctype_cts(L
);
328 uint8_t *sp
= (uint8_t *)cdataptr(cdataV(o
));
329 CTypeID sid
= cdataV(o
)->ctypeid
;
330 CType
*s
= ctype_get(cts
, sid
);
332 if (ctype_isref(s
->info
)) {
334 sid
= ctype_cid(s
->info
);
336 s
= ctype_raw(cts
, sid
);
337 if (ctype_isenum(s
->info
)) s
= ctype_child(cts
, s
);
338 if ((s
->info
& (CTMASK_NUM
|CTF_BOOL
|CTF_FP
|CTF_UNSIGNED
)) ==
339 CTINFO(CT_NUM
, CTF_UNSIGNED
) && s
->size
== 8)
340 *id
= CTID_UINT64
; /* Use uint64_t, since it has the highest rank. */
342 *id
= CTID_INT64
; /* Use int64_t, unless already set. */
343 lj_cconv_ct_ct(cts
, ctype_get(cts
, *id
), s
,
344 (uint8_t *)&x
, sp
, CCF_ARG(narg
));
346 } else if (!(tvisstr(o
) && lj_strscan_number(strV(o
), o
))) {
349 if (LJ_LIKELY(tvisint(o
))) {
350 return (uint32_t)intV(o
);
352 int32_t i
= lj_num2bit(numV(o
));
353 if (LJ_DUALNUM
) setintV(o
, i
);
358 /* -- 64 bit integer arithmetic helpers ----------------------------------- */
360 #if LJ_32 && LJ_HASJIT
361 /* Signed/unsigned 64 bit multiplication. */
362 int64_t lj_carith_mul64(int64_t a
, int64_t b
)
368 /* Unsigned 64 bit division. */
369 uint64_t lj_carith_divu64(uint64_t a
, uint64_t b
)
371 if (b
== 0) return U64x(80000000,00000000);
375 /* Signed 64 bit division. */
376 int64_t lj_carith_divi64(int64_t a
, int64_t b
)
378 if (b
== 0 || (a
== (int64_t)U64x(80000000,00000000) && b
== -1))
379 return U64x(80000000,00000000);
383 /* Unsigned 64 bit modulo. */
384 uint64_t lj_carith_modu64(uint64_t a
, uint64_t b
)
386 if (b
== 0) return U64x(80000000,00000000);
390 /* Signed 64 bit modulo. */
391 int64_t lj_carith_modi64(int64_t a
, int64_t b
)
393 if (b
== 0) return U64x(80000000,00000000);
394 if (a
== (int64_t)U64x(80000000,00000000) && b
== -1) return 0;
398 /* Unsigned 64 bit x^k. */
399 uint64_t lj_carith_powu64(uint64_t x
, uint64_t k
)
404 for (; (k
& 1) == 0; k
>>= 1) x
*= x
;
406 if ((k
>>= 1) != 0) {
418 /* Signed 64 bit x^k. */
419 int64_t lj_carith_powi64(int64_t x
, int64_t k
)
425 return U64x(7fffffff
,ffffffff
);
429 return (k
& 1) ? -1 : 1;
433 return (int64_t)lj_carith_powu64((uint64_t)x
, (uint64_t)k
);