FFI: Compile array/struct copies.
[luajit-2.0.git] / src / lj_crecord.c
blob6a22544a3ad6f034a12175ce3883679ea7ae5ddf
1 /*
2 ** Trace recorder for C data operations.
3 ** Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h
4 */
6 #define lj_ffrecord_c
7 #define LUA_CORE
9 #include "lj_obj.h"
11 #if LJ_HASJIT && LJ_HASFFI
13 #include "lj_err.h"
14 #include "lj_str.h"
15 #include "lj_tab.h"
16 #include "lj_frame.h"
17 #include "lj_ctype.h"
18 #include "lj_cdata.h"
19 #include "lj_cparse.h"
20 #include "lj_cconv.h"
21 #include "lj_clib.h"
22 #include "lj_ccall.h"
23 #include "lj_ir.h"
24 #include "lj_jit.h"
25 #include "lj_ircall.h"
26 #include "lj_iropt.h"
27 #include "lj_trace.h"
28 #include "lj_record.h"
29 #include "lj_ffrecord.h"
30 #include "lj_snap.h"
31 #include "lj_crecord.h"
32 #include "lj_dispatch.h"
34 /* Some local macros to save typing. Undef'd at the end. */
35 #define IR(ref) (&J->cur.ir[(ref)])
37 /* Pass IR on to next optimization in chain (FOLD). */
38 #define emitir(ot, a, b) (lj_ir_set(J, (ot), (a), (b)), lj_opt_fold(J))
40 #define emitconv(a, dt, st, flags) \
41 emitir(IRT(IR_CONV, (dt)), (a), (st)|((dt) << 5)|(flags))
43 /* -- C type checks ------------------------------------------------------- */
45 static GCcdata *argv2cdata(jit_State *J, TRef tr, cTValue *o)
47 GCcdata *cd;
48 TRef trtypeid;
49 if (!tref_iscdata(tr))
50 lj_trace_err(J, LJ_TRERR_BADTYPE);
51 cd = cdataV(o);
52 /* Specialize to the CTypeID. */
53 trtypeid = emitir(IRT(IR_FLOAD, IRT_U16), tr, IRFL_CDATA_CTYPEID);
54 emitir(IRTG(IR_EQ, IRT_INT), trtypeid, lj_ir_kint(J, (int32_t)cd->ctypeid));
55 return cd;
58 /* Specialize to the CTypeID held by a cdata constructor. */
59 static CTypeID crec_constructor(jit_State *J, GCcdata *cd, TRef tr)
61 CTypeID id;
62 lua_assert(tref_iscdata(tr) && cd->ctypeid == CTID_CTYPEID);
63 id = *(CTypeID *)cdataptr(cd);
64 tr = emitir(IRT(IR_FLOAD, IRT_INT), tr, IRFL_CDATA_INT);
65 emitir(IRTG(IR_EQ, IRT_INT), tr, lj_ir_kint(J, (int32_t)id));
66 return id;
69 static CTypeID argv2ctype(jit_State *J, TRef tr, cTValue *o)
71 if (tref_isstr(tr)) {
72 GCstr *s = strV(o);
73 CPState cp;
74 CTypeID oldtop;
75 /* Specialize to the string containing the C type declaration. */
76 emitir(IRTG(IR_EQ, IRT_STR), tr, lj_ir_kstr(J, s));
77 cp.L = J->L;
78 cp.cts = ctype_ctsG(J2G(J));
79 oldtop = cp.cts->top;
80 cp.srcname = strdata(s);
81 cp.p = strdata(s);
82 cp.param = NULL;
83 cp.mode = CPARSE_MODE_ABSTRACT|CPARSE_MODE_NOIMPLICIT;
84 if (lj_cparse(&cp) || cp.cts->top > oldtop) /* Avoid new struct defs. */
85 lj_trace_err(J, LJ_TRERR_BADTYPE);
86 return cp.val.id;
87 } else {
88 GCcdata *cd = argv2cdata(J, tr, o);
89 return cd->ctypeid == CTID_CTYPEID ? crec_constructor(J, cd, tr) :
90 cd->ctypeid;
94 /* Convert CType to IRType (if possible). */
95 static IRType crec_ct2irt(CTState *cts, CType *ct)
97 if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct);
98 if (LJ_LIKELY(ctype_isnum(ct->info))) {
99 if ((ct->info & CTF_FP)) {
100 if (ct->size == sizeof(double))
101 return IRT_NUM;
102 else if (ct->size == sizeof(float))
103 return IRT_FLOAT;
104 } else {
105 uint32_t b = lj_fls(ct->size);
106 if (b <= 3)
107 return IRT_I8 + 2*b + ((ct->info & CTF_UNSIGNED) ? 1 : 0);
109 } else if (ctype_isptr(ct->info)) {
110 return (LJ_64 && ct->size == 8) ? IRT_P64 : IRT_P32;
111 } else if (ctype_iscomplex(ct->info)) {
112 if (ct->size == 2*sizeof(double))
113 return IRT_NUM;
114 else if (ct->size == 2*sizeof(float))
115 return IRT_FLOAT;
117 return IRT_CDATA;
120 /* -- Optimized memory fill and copy -------------------------------------- */
122 /* Maximum length and unroll of inlined copy/fill. */
123 #define CREC_COPY_MAXUNROLL 16
124 #define CREC_COPY_MAXLEN 128
126 #define CREC_FILL_MAXUNROLL 16
127 #if LJ_TARGET_UNALIGNED
128 #define CREC_FILL_MAXLEN (CTSIZE_PTR * CREC_FILL_MAXUNROLL)
129 #else
130 #define CREC_FILL_MAXLEN CREC_FILL_MAXUNROLL
131 #endif
133 /* Number of windowed registers used for optimized memory copy. */
134 #if LJ_TARGET_X86
135 #define CREC_COPY_REGWIN 2
136 #elif LJ_TARGET_PPC || LJ_TARGET_MIPS
137 #define CREC_COPY_REGWIN 8
138 #else
139 #define CREC_COPY_REGWIN 4
140 #endif
142 /* List of memory offsets for copy/fill. */
143 typedef struct CRecMemList {
144 CTSize ofs; /* Offset in bytes. */
145 IRType tp; /* Type of load/store. */
146 TRef trofs; /* TRef of interned offset. */
147 TRef trval; /* TRef of load value. */
148 } CRecMemList;
150 /* Generate copy list for element-wise struct copy. */
151 static MSize crec_copy_struct(CRecMemList *ml, CTState *cts, CType *ct)
153 CTypeID fid = ct->sib;
154 MSize mlp = 0;
155 while (fid) {
156 CType *df = ctype_get(cts, fid);
157 fid = df->sib;
158 if (ctype_isfield(df->info)) {
159 CType *cct;
160 IRType tp;
161 if (!gcref(df->name)) continue; /* Ignore unnamed fields. */
162 cct = ctype_rawchild(cts, df); /* Field type. */
163 tp = crec_ct2irt(cts, cct);
164 if (tp == IRT_CDATA) return 0; /* NYI: aggregates. */
165 if (mlp >= CREC_COPY_MAXUNROLL) return 0;
166 ml[mlp].ofs = df->size;
167 ml[mlp].tp = tp;
168 mlp++;
169 if (ctype_iscomplex(cct->info)) {
170 if (mlp >= CREC_COPY_MAXUNROLL) return 0;
171 ml[mlp].ofs = df->size + (cct->size >> 1);
172 ml[mlp].tp = tp;
173 mlp++;
175 } else if (!ctype_isconstval(df->info)) {
176 /* NYI: bitfields and sub-structures. */
177 return 0;
180 return mlp;
183 /* Generate unrolled copy list, from highest to lowest step size/alignment. */
184 static MSize crec_copy_unroll(CRecMemList *ml, CTSize len, CTSize step,
185 IRType tp)
187 CTSize ofs = 0;
188 MSize mlp = 0;
189 if (tp == IRT_CDATA) tp = IRT_U8 + 2*lj_fls(step);
190 do {
191 while (ofs + step <= len) {
192 if (mlp >= CREC_COPY_MAXUNROLL) return 0;
193 ml[mlp].ofs = ofs;
194 ml[mlp].tp = tp;
195 mlp++;
196 ofs += step;
198 step >>= 1;
199 tp -= 2;
200 } while (ofs < len);
201 return mlp;
205 ** Emit copy list with windowed loads/stores.
206 ** LJ_TARGET_UNALIGNED: may emit unaligned loads/stores (not marked as such).
208 static void crec_copy_emit(jit_State *J, CRecMemList *ml, MSize mlp,
209 TRef trdst, TRef trsrc)
211 MSize i, j, rwin = 0;
212 for (i = 0, j = 0; i < mlp; ) {
213 TRef trofs = lj_ir_kintp(J, ml[i].ofs);
214 TRef trsptr = emitir(IRT(IR_ADD, IRT_PTR), trsrc, trofs);
215 ml[i].trval = emitir(IRT(IR_XLOAD, ml[i].tp), trsptr, 0);
216 ml[i].trofs = trofs;
217 i++;
218 rwin += (LJ_SOFTFP && ml[i].tp == IRT_NUM) ? 2 : 1;
219 if (rwin >= CREC_COPY_REGWIN || i >= mlp) { /* Flush buffered stores. */
220 rwin = 0;
221 for ( ; j < i; j++) {
222 TRef trdptr = emitir(IRT(IR_ADD, IRT_PTR), trdst, ml[j].trofs);
223 emitir(IRT(IR_XSTORE, ml[j].tp), trdptr, ml[j].trval);
229 /* Optimized memory copy. */
230 static void crec_copy(jit_State *J, TRef trdst, TRef trsrc, TRef trlen,
231 CType *ct)
233 if (tref_isk(trlen)) { /* Length must be constant. */
234 CRecMemList ml[CREC_COPY_MAXUNROLL];
235 MSize mlp = 0;
236 CTSize step = 1, len = (CTSize)IR(tref_ref(trlen))->i;
237 IRType tp = IRT_CDATA;
238 int needxbar = 0;
239 if (len == 0) return; /* Shortcut. */
240 if (len > CREC_COPY_MAXLEN) goto fallback;
241 if (ct) {
242 CTState *cts = ctype_ctsG(J2G(J));
243 lua_assert(ctype_isarray(ct->info) || ctype_isstruct(ct->info));
244 if (ctype_isarray(ct->info)) {
245 CType *cct = ctype_rawchild(cts, ct);
246 tp = crec_ct2irt(cts, cct);
247 if (tp == IRT_CDATA) goto rawcopy;
248 step = lj_ir_type_size[tp];
249 lua_assert((len & (step-1)) == 0);
250 } else if ((ct->info & CTF_UNION)) {
251 step = (1u << ctype_align(ct->info));
252 goto rawcopy;
253 } else {
254 mlp = crec_copy_struct(ml, cts, ct);
255 goto emitcopy;
257 } else {
258 rawcopy:
259 needxbar = 1;
260 if (LJ_TARGET_UNALIGNED || step >= CTSIZE_PTR)
261 step = CTSIZE_PTR;
263 mlp = crec_copy_unroll(ml, len, step, tp);
264 emitcopy:
265 if (mlp) {
266 crec_copy_emit(J, ml, mlp, trdst, trsrc);
267 if (needxbar)
268 emitir(IRT(IR_XBAR, IRT_NIL), 0, 0);
269 return;
272 fallback:
273 /* Call memcpy. Always needs a barrier to disable alias analysis. */
274 lj_ir_call(J, IRCALL_memcpy, trdst, trsrc, trlen);
275 emitir(IRT(IR_XBAR, IRT_NIL), 0, 0);
278 /* Generate unrolled fill list, from highest to lowest step size/alignment. */
279 static MSize crec_fill_unroll(CRecMemList *ml, CTSize len, CTSize step)
281 CTSize ofs = 0;
282 MSize mlp = 0;
283 IRType tp = IRT_U8 + 2*lj_fls(step);
284 do {
285 while (ofs + step <= len) {
286 if (mlp >= CREC_COPY_MAXUNROLL) return 0;
287 ml[mlp].ofs = ofs;
288 ml[mlp].tp = tp;
289 mlp++;
290 ofs += step;
292 step >>= 1;
293 tp -= 2;
294 } while (ofs < len);
295 return mlp;
299 ** Emit stores for fill list.
300 ** LJ_TARGET_UNALIGNED: may emit unaligned stores (not marked as such).
302 static void crec_fill_emit(jit_State *J, CRecMemList *ml, MSize mlp,
303 TRef trdst, TRef trfill)
305 MSize i;
306 for (i = 0; i < mlp; i++) {
307 TRef trofs = lj_ir_kintp(J, ml[i].ofs);
308 TRef trdptr = emitir(IRT(IR_ADD, IRT_PTR), trdst, trofs);
309 emitir(IRT(IR_XSTORE, ml[i].tp), trdptr, trfill);
313 /* Optimized memory fill. */
314 static void crec_fill(jit_State *J, TRef trdst, TRef trlen, TRef trfill,
315 CTSize step)
317 if (tref_isk(trlen)) { /* Length must be constant. */
318 CRecMemList ml[CREC_FILL_MAXUNROLL];
319 MSize mlp;
320 CTSize len = (CTSize)IR(tref_ref(trlen))->i;
321 if (len == 0) return; /* Shortcut. */
322 if (len > CREC_FILL_MAXLEN) goto fallback;
323 if (LJ_TARGET_UNALIGNED || step >= CTSIZE_PTR)
324 step = CTSIZE_PTR;
325 mlp = crec_fill_unroll(ml, len, step);
326 if (!mlp) goto fallback;
327 if (tref_isk(trfill) || ml[0].tp != IRT_U8)
328 trfill = emitconv(trfill, IRT_INT, IRT_U8, 0);
329 if (ml[0].tp != IRT_U8) { /* Scatter U8 to U16/U32/U64. */
330 if (CTSIZE_PTR == 8 && ml[0].tp == IRT_U64) {
331 if (tref_isk(trfill)) /* Pointless on x64 with zero-extended regs. */
332 trfill = emitconv(trfill, IRT_U64, IRT_U32, 0);
333 trfill = emitir(IRT(IR_MUL, IRT_U64), trfill,
334 lj_ir_kint64(J, U64x(01010101,01010101)));
335 } else {
336 trfill = emitir(IRTI(IR_MUL), trfill,
337 lj_ir_kint(J, ml[0].tp == IRT_U16 ? 0x0101 : 0x01010101));
340 crec_fill_emit(J, ml, mlp, trdst, trfill);
341 } else {
342 fallback:
343 /* Call memset. Always needs a barrier to disable alias analysis. */
344 lj_ir_call(J, IRCALL_memset, trdst, trfill, trlen); /* Note: arg order! */
346 emitir(IRT(IR_XBAR, IRT_NIL), 0, 0);
349 /* -- Convert C type to C type -------------------------------------------- */
352 ** This code mirrors the code in lj_cconv.c. It performs the same steps
353 ** for the trace recorder that lj_cconv.c does for the interpreter.
355 ** One major difference is that we can get away with much fewer checks
356 ** here. E.g. checks for casts, constness or correct types can often be
357 ** omitted, even if they might fail. The interpreter subsequently throws
358 ** an error, which aborts the trace.
360 ** All operations are specialized to their C types, so the on-trace
361 ** outcome must be the same as the outcome in the interpreter. If the
362 ** interpreter doesn't throw an error, then the trace is correct, too.
363 ** Care must be taken not to generate invalid (temporary) IR or to
364 ** trigger asserts.
367 /* Determine whether a passed number or cdata number is non-zero. */
368 static int crec_isnonzero(CType *s, void *p)
370 if (p == (void *)0)
371 return 0;
372 if (p == (void *)1)
373 return 1;
374 if ((s->info & CTF_FP)) {
375 if (s->size == sizeof(float))
376 return (*(float *)p != 0);
377 else
378 return (*(double *)p != 0);
379 } else {
380 if (s->size == 1)
381 return (*(uint8_t *)p != 0);
382 else if (s->size == 2)
383 return (*(uint16_t *)p != 0);
384 else if (s->size == 4)
385 return (*(uint32_t *)p != 0);
386 else
387 return (*(uint64_t *)p != 0);
391 static TRef crec_ct_ct(jit_State *J, CType *d, CType *s, TRef dp, TRef sp,
392 void *svisnz)
394 IRType dt = crec_ct2irt(ctype_ctsG(J2G(J)), d);
395 IRType st = crec_ct2irt(ctype_ctsG(J2G(J)), s);
396 CTSize dsize = d->size, ssize = s->size;
397 CTInfo dinfo = d->info, sinfo = s->info;
399 if (ctype_type(dinfo) > CT_MAYCONVERT || ctype_type(sinfo) > CT_MAYCONVERT)
400 goto err_conv;
403 ** Note: Unlike lj_cconv_ct_ct(), sp holds the _value_ of pointers and
404 ** numbers up to 8 bytes. Otherwise sp holds a pointer.
407 switch (cconv_idx2(dinfo, sinfo)) {
408 /* Destination is a bool. */
409 case CCX(B, B):
410 goto xstore; /* Source operand is already normalized. */
411 case CCX(B, I):
412 case CCX(B, F):
413 if (st != IRT_CDATA) {
414 /* Specialize to the result of a comparison against 0. */
415 TRef zero = (st == IRT_NUM || st == IRT_FLOAT) ? lj_ir_knum(J, 0) :
416 (st == IRT_I64 || st == IRT_U64) ? lj_ir_kint64(J, 0) :
417 lj_ir_kint(J, 0);
418 int isnz = crec_isnonzero(s, svisnz);
419 emitir(IRTG(isnz ? IR_NE : IR_EQ, st), sp, zero);
420 sp = lj_ir_kint(J, isnz);
421 goto xstore;
423 goto err_nyi;
425 /* Destination is an integer. */
426 case CCX(I, B):
427 case CCX(I, I):
428 conv_I_I:
429 if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi;
430 /* Extend 32 to 64 bit integer. */
431 if (dsize == 8 && ssize < 8 && !(LJ_64 && (sinfo & CTF_UNSIGNED)))
432 sp = emitconv(sp, dt, ssize < 4 ? IRT_INT : st,
433 (sinfo & CTF_UNSIGNED) ? 0 : IRCONV_SEXT);
434 else if (dsize < 8 && ssize == 8) /* Truncate from 64 bit integer. */
435 sp = emitconv(sp, dsize < 4 ? IRT_INT : dt, st, 0);
436 else if (st == IRT_INT)
437 sp = lj_opt_narrow_toint(J, sp);
438 xstore:
439 if (dt == IRT_I64 || dt == IRT_U64) lj_needsplit(J);
440 if (dp == 0) return sp;
441 emitir(IRT(IR_XSTORE, dt), dp, sp);
442 break;
443 case CCX(I, C):
444 sp = emitir(IRT(IR_XLOAD, st), sp, 0); /* Load re. */
445 /* fallthrough */
446 case CCX(I, F):
447 if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi;
448 sp = emitconv(sp, dsize < 4 ? IRT_INT : dt, st, IRCONV_TRUNC|IRCONV_ANY);
449 goto xstore;
450 case CCX(I, P):
451 case CCX(I, A):
452 sinfo = CTINFO(CT_NUM, CTF_UNSIGNED);
453 ssize = CTSIZE_PTR;
454 st = IRT_UINTP;
455 goto conv_I_I;
457 /* Destination is a floating-point number. */
458 case CCX(F, B):
459 case CCX(F, I):
460 conv_F_I:
461 if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi;
462 sp = emitconv(sp, dt, ssize < 4 ? IRT_INT : st, 0);
463 goto xstore;
464 case CCX(F, C):
465 sp = emitir(IRT(IR_XLOAD, st), sp, 0); /* Load re. */
466 /* fallthrough */
467 case CCX(F, F):
468 conv_F_F:
469 if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi;
470 if (dt != st) sp = emitconv(sp, dt, st, 0);
471 goto xstore;
473 /* Destination is a complex number. */
474 case CCX(C, I):
475 case CCX(C, F):
476 { /* Clear im. */
477 TRef ptr = emitir(IRT(IR_ADD, IRT_PTR), dp, lj_ir_kintp(J, (dsize >> 1)));
478 emitir(IRT(IR_XSTORE, dt), ptr, lj_ir_knum(J, 0));
480 /* Convert to re. */
481 if ((sinfo & CTF_FP)) goto conv_F_F; else goto conv_F_I;
483 case CCX(C, C):
484 if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi;
486 TRef re, im, ptr;
487 re = emitir(IRT(IR_XLOAD, st), sp, 0);
488 ptr = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, (ssize >> 1)));
489 im = emitir(IRT(IR_XLOAD, st), ptr, 0);
490 if (dt != st) {
491 re = emitconv(re, dt, st, 0);
492 im = emitconv(im, dt, st, 0);
494 emitir(IRT(IR_XSTORE, dt), dp, re);
495 ptr = emitir(IRT(IR_ADD, IRT_PTR), dp, lj_ir_kintp(J, (dsize >> 1)));
496 emitir(IRT(IR_XSTORE, dt), ptr, im);
498 break;
500 /* Destination is a vector. */
501 case CCX(V, I):
502 case CCX(V, F):
503 case CCX(V, C):
504 case CCX(V, V):
505 goto err_nyi;
507 /* Destination is a pointer. */
508 case CCX(P, P):
509 case CCX(P, A):
510 case CCX(P, S):
511 /* There are only 32 bit pointers/addresses on 32 bit machines.
512 ** Also ok on x64, since all 32 bit ops clear the upper part of the reg.
514 goto xstore;
515 case CCX(P, I):
516 if (st == IRT_CDATA) goto err_nyi;
517 if (!LJ_64 && ssize == 8) /* Truncate from 64 bit integer. */
518 sp = emitconv(sp, IRT_U32, st, 0);
519 goto xstore;
520 case CCX(P, F):
521 if (st == IRT_CDATA) goto err_nyi;
522 /* The signed conversion is cheaper. x64 really has 47 bit pointers. */
523 sp = emitconv(sp, (LJ_64 && dsize == 8) ? IRT_I64 : IRT_U32,
524 st, IRCONV_TRUNC|IRCONV_ANY);
525 goto xstore;
527 /* Destination is an array. */
528 case CCX(A, A):
529 /* Destination is a struct/union. */
530 case CCX(S, S):
531 if (dp == 0) goto err_conv;
532 crec_copy(J, dp, sp, lj_ir_kint(J, dsize), d);
533 break;
535 default:
536 err_conv:
537 err_nyi:
538 lj_trace_err(J, LJ_TRERR_NYICONV);
539 break;
541 return 0;
544 /* -- Convert C type to TValue (load) ------------------------------------- */
546 static TRef crec_tv_ct(jit_State *J, CType *s, CTypeID sid, TRef sp)
548 CTState *cts = ctype_ctsG(J2G(J));
549 IRType t = crec_ct2irt(cts, s);
550 CTInfo sinfo = s->info;
551 if (ctype_isnum(sinfo)) {
552 TRef tr;
553 if (t == IRT_CDATA)
554 goto err_nyi; /* NYI: copyval of >64 bit integers. */
555 tr = emitir(IRT(IR_XLOAD, t), sp, 0);
556 if (t == IRT_FLOAT || t == IRT_U32) { /* Keep uint32_t/float as numbers. */
557 return emitconv(tr, IRT_NUM, t, 0);
558 } else if (t == IRT_I64 || t == IRT_U64) { /* Box 64 bit integer. */
559 sp = tr;
560 lj_needsplit(J);
561 } else if ((sinfo & CTF_BOOL)) {
562 /* Assume not equal to zero. Fixup and emit pending guard later. */
563 lj_ir_set(J, IRTGI(IR_NE), tr, lj_ir_kint(J, 0));
564 J->postproc = LJ_POST_FIXGUARD;
565 return TREF_TRUE;
566 } else {
567 return tr;
569 } else if (ctype_isptr(sinfo) || ctype_isenum(sinfo)) {
570 sp = emitir(IRT(IR_XLOAD, t), sp, 0); /* Box pointers and enums. */
571 } else if (ctype_isrefarray(sinfo) || ctype_isstruct(sinfo)) {
572 cts->L = J->L;
573 sid = lj_ctype_intern(cts, CTINFO_REF(sid), CTSIZE_PTR); /* Create ref. */
574 } else if (ctype_iscomplex(sinfo)) { /* Unbox/box complex. */
575 ptrdiff_t esz = (ptrdiff_t)(s->size >> 1);
576 TRef ptr, tr1, tr2, dp;
577 dp = emitir(IRTG(IR_CNEW, IRT_CDATA), lj_ir_kint(J, sid), TREF_NIL);
578 tr1 = emitir(IRT(IR_XLOAD, t), sp, 0);
579 ptr = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, esz));
580 tr2 = emitir(IRT(IR_XLOAD, t), ptr, 0);
581 ptr = emitir(IRT(IR_ADD, IRT_PTR), dp, lj_ir_kintp(J, sizeof(GCcdata)));
582 emitir(IRT(IR_XSTORE, t), ptr, tr1);
583 ptr = emitir(IRT(IR_ADD, IRT_PTR), dp, lj_ir_kintp(J, sizeof(GCcdata)+esz));
584 emitir(IRT(IR_XSTORE, t), ptr, tr2);
585 return dp;
586 } else {
587 /* NYI: copyval of vectors. */
588 err_nyi:
589 lj_trace_err(J, LJ_TRERR_NYICONV);
591 /* Box pointer, ref, enum or 64 bit integer. */
592 return emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, sid), sp);
595 /* -- Convert TValue to C type (store) ------------------------------------ */
597 static TRef crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, cTValue *sval)
599 CTState *cts = ctype_ctsG(J2G(J));
600 CTypeID sid = CTID_P_VOID;
601 void *svisnz = 0;
602 CType *s;
603 if (LJ_LIKELY(tref_isinteger(sp))) {
604 sid = CTID_INT32;
605 svisnz = (void *)(intptr_t)(tvisint(sval)?(intV(sval)!=0):!tviszero(sval));
606 } else if (tref_isnum(sp)) {
607 sid = CTID_DOUBLE;
608 svisnz = (void *)(intptr_t)(tvisint(sval)?(intV(sval)!=0):!tviszero(sval));
609 } else if (tref_isbool(sp)) {
610 sp = lj_ir_kint(J, tref_istrue(sp) ? 1 : 0);
611 sid = CTID_BOOL;
612 } else if (tref_isnil(sp)) {
613 sp = lj_ir_kptr(J, NULL);
614 } else if (tref_isudata(sp)) {
615 GCudata *ud = udataV(sval);
616 if (ud->udtype == UDTYPE_IO_FILE) {
617 TRef tr = emitir(IRT(IR_FLOAD, IRT_U8), sp, IRFL_UDATA_UDTYPE);
618 emitir(IRTGI(IR_EQ), tr, lj_ir_kint(J, UDTYPE_IO_FILE));
619 sp = emitir(IRT(IR_FLOAD, IRT_PTR), sp, IRFL_UDATA_FILE);
620 } else {
621 sp = emitir(IRT(IR_ADD, IRT_P32), sp, lj_ir_kint(J, sizeof(GCudata)));
623 } else if (tref_isstr(sp)) {
624 if (ctype_isenum(d->info)) { /* Match string against enum constant. */
625 GCstr *str = strV(sval);
626 CTSize ofs;
627 CType *cct = lj_ctype_getfield(cts, d, str, &ofs);
628 /* Specialize to the name of the enum constant. */
629 emitir(IRTG(IR_EQ, IRT_STR), sp, lj_ir_kstr(J, str));
630 if (cct && ctype_isconstval(cct->info)) {
631 lua_assert(ctype_child(cts, cct)->size == 4);
632 svisnz = (void *)(intptr_t)(ofs != 0);
633 sp = lj_ir_kint(J, (int32_t)ofs);
634 sid = ctype_cid(cct->info);
635 } /* else: interpreter will throw. */
636 } else if (ctype_isrefarray(d->info)) { /* Copy string to array. */
637 lj_trace_err(J, LJ_TRERR_BADTYPE); /* NYI */
638 } else { /* Otherwise pass the string data as a const char[]. */
639 sp = emitir(IRT(IR_STRREF, IRT_P32), sp, lj_ir_kint(J, 0));
640 sid = CTID_A_CCHAR;
642 } else { /* NYI: tref_istab(sp), tref_islightud(sp). */
643 IRType t;
644 sid = argv2cdata(J, sp, sval)->ctypeid;
645 s = ctype_raw(cts, sid);
646 svisnz = cdataptr(cdataV(sval));
647 t = crec_ct2irt(cts, s);
648 if (ctype_isptr(s->info)) {
649 sp = emitir(IRT(IR_FLOAD, t), sp, IRFL_CDATA_PTR);
650 if (ctype_isref(s->info)) {
651 svisnz = *(void **)svisnz;
652 s = ctype_rawchild(cts, s);
653 if (ctype_isenum(s->info)) s = ctype_child(cts, s);
654 t = crec_ct2irt(cts, s);
655 } else {
656 goto doconv;
658 } else if (t == IRT_I64 || t == IRT_U64) {
659 sp = emitir(IRT(IR_FLOAD, t), sp, IRFL_CDATA_INT64);
660 lj_needsplit(J);
661 goto doconv;
662 } else if (t == IRT_INT || t == IRT_U32) {
663 if (ctype_isenum(s->info)) s = ctype_child(cts, s);
664 sp = emitir(IRT(IR_FLOAD, t), sp, IRFL_CDATA_INT);
665 goto doconv;
666 } else {
667 sp = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, sizeof(GCcdata)));
669 if (ctype_isnum(s->info) && t != IRT_CDATA)
670 sp = emitir(IRT(IR_XLOAD, t), sp, 0); /* Load number value. */
671 goto doconv;
673 s = ctype_get(cts, sid);
674 doconv:
675 if (ctype_isenum(d->info)) d = ctype_child(cts, d);
676 return crec_ct_ct(J, d, s, dp, sp, svisnz);
679 /* -- C data metamethods -------------------------------------------------- */
681 /* This would be rather difficult in FOLD, so do it here:
682 ** (base+k)+(idx*sz)+ofs ==> (base+idx*sz)+(ofs+k)
683 ** (base+(idx+k)*sz)+ofs ==> (base+idx*sz)+(ofs+k*sz)
685 static TRef crec_reassoc_ofs(jit_State *J, TRef tr, ptrdiff_t *ofsp, MSize sz)
687 IRIns *ir = IR(tref_ref(tr));
688 if (LJ_LIKELY(J->flags & JIT_F_OPT_FOLD) && irref_isk(ir->op2) &&
689 (ir->o == IR_ADD || ir->o == IR_ADDOV || ir->o == IR_SUBOV)) {
690 IRIns *irk = IR(ir->op2);
691 ptrdiff_t k;
692 if (LJ_64 && irk->o == IR_KINT64)
693 k = (ptrdiff_t)ir_kint64(irk)->u64 * sz;
694 else
695 k = (ptrdiff_t)irk->i * sz;
696 if (ir->o == IR_SUBOV) *ofsp -= k; else *ofsp += k;
697 tr = ir->op1; /* Not a TRef, but the caller doesn't care. */
699 return tr;
702 /* Record ctype __index/__newindex metamethods. */
703 static void crec_index_meta(jit_State *J, CTState *cts, CType *ct,
704 RecordFFData *rd)
706 CTypeID id = ctype_typeid(cts, ct);
707 cTValue *tv = lj_ctype_meta(cts, id, rd->data ? MM_newindex : MM_index);
708 if (!tv)
709 lj_trace_err(J, LJ_TRERR_BADTYPE);
710 if (tvisfunc(tv)) {
711 J->base[-1] = lj_ir_kfunc(J, funcV(tv)) | TREF_FRAME;
712 rd->nres = -1; /* Pending tailcall. */
713 } else if (rd->data == 0 && tvistab(tv) && tref_isstr(J->base[1])) {
714 /* Specialize to result of __index lookup. */
715 cTValue *o = lj_tab_get(J->L, tabV(tv), &rd->argv[1]);
716 J->base[0] = lj_record_constify(J, o);
717 if (!J->base[0])
718 lj_trace_err(J, LJ_TRERR_BADTYPE);
719 /* Always specialize to the key. */
720 emitir(IRTG(IR_EQ, IRT_STR), J->base[1], lj_ir_kstr(J, strV(&rd->argv[1])));
721 } else {
722 /* NYI: resolving of non-function metamethods. */
723 /* NYI: non-string keys for __index table. */
724 /* NYI: stores to __newindex table. */
725 lj_trace_err(J, LJ_TRERR_BADTYPE);
729 void LJ_FASTCALL recff_cdata_index(jit_State *J, RecordFFData *rd)
731 TRef idx, ptr = J->base[0];
732 ptrdiff_t ofs = sizeof(GCcdata);
733 GCcdata *cd = argv2cdata(J, ptr, &rd->argv[0]);
734 CTState *cts = ctype_ctsG(J2G(J));
735 CType *ct = ctype_raw(cts, cd->ctypeid);
736 CTypeID sid = 0;
738 /* Resolve pointer or reference for cdata object. */
739 if (ctype_isptr(ct->info)) {
740 IRType t = (LJ_64 && ct->size == 8) ? IRT_P64 : IRT_P32;
741 if (ctype_isref(ct->info)) ct = ctype_rawchild(cts, ct);
742 ptr = emitir(IRT(IR_FLOAD, t), ptr, IRFL_CDATA_PTR);
743 ofs = 0;
744 ptr = crec_reassoc_ofs(J, ptr, &ofs, 1);
747 again:
748 idx = J->base[1];
749 if (tref_isnumber(idx)) {
750 idx = lj_opt_narrow_cindex(J, idx);
751 if (ctype_ispointer(ct->info)) {
752 CTSize sz;
753 integer_key:
754 if ((ct->info & CTF_COMPLEX))
755 idx = emitir(IRT(IR_BAND, IRT_INTP), idx, lj_ir_kintp(J, 1));
756 sz = lj_ctype_size(cts, (sid = ctype_cid(ct->info)));
757 idx = crec_reassoc_ofs(J, idx, &ofs, sz);
758 #if LJ_TARGET_ARM || LJ_TARGET_PPC
759 /* Hoist base add to allow fusion of index/shift into operands. */
760 if (LJ_LIKELY(J->flags & JIT_F_OPT_LOOP) && ofs
761 #if LJ_TARGET_ARM
762 && (sz == 1 || sz == 4)
763 #endif
765 ptr = emitir(IRT(IR_ADD, IRT_PTR), ptr, lj_ir_kintp(J, ofs));
766 ofs = 0;
768 #endif
769 idx = emitir(IRT(IR_MUL, IRT_INTP), idx, lj_ir_kintp(J, sz));
770 ptr = emitir(IRT(IR_ADD, IRT_PTR), idx, ptr);
772 } else if (tref_iscdata(idx)) {
773 GCcdata *cdk = cdataV(&rd->argv[1]);
774 CType *ctk = ctype_raw(cts, cdk->ctypeid);
775 IRType t = crec_ct2irt(cts, ctk);
776 if (ctype_ispointer(ct->info) && t >= IRT_I8 && t <= IRT_U64) {
777 if (ctk->size == 8) {
778 idx = emitir(IRT(IR_FLOAD, t), idx, IRFL_CDATA_INT64);
779 } else if (ctk->size == 4) {
780 idx = emitir(IRT(IR_FLOAD, t), idx, IRFL_CDATA_INT);
781 } else {
782 idx = emitir(IRT(IR_ADD, IRT_PTR), idx,
783 lj_ir_kintp(J, sizeof(GCcdata)));
784 idx = emitir(IRT(IR_XLOAD, t), idx, 0);
786 if (LJ_64 && ctk->size < sizeof(intptr_t) && !(ctk->info & CTF_UNSIGNED))
787 idx = emitconv(idx, IRT_INTP, IRT_INT, IRCONV_SEXT);
788 if (!LJ_64 && ctk->size > sizeof(intptr_t)) {
789 idx = emitconv(idx, IRT_INTP, t, 0);
790 lj_needsplit(J);
792 goto integer_key;
794 } else if (tref_isstr(idx)) {
795 GCstr *name = strV(&rd->argv[1]);
796 if (cd->ctypeid == CTID_CTYPEID)
797 ct = ctype_raw(cts, crec_constructor(J, cd, ptr));
798 if (ctype_isstruct(ct->info)) {
799 CTSize fofs;
800 CType *fct;
801 fct = lj_ctype_getfield(cts, ct, name, &fofs);
802 if (fct) {
803 /* Always specialize to the field name. */
804 emitir(IRTG(IR_EQ, IRT_STR), idx, lj_ir_kstr(J, name));
805 if (ctype_isconstval(fct->info)) {
806 if (fct->size >= 0x80000000u &&
807 (ctype_child(cts, fct)->info & CTF_UNSIGNED)) {
808 J->base[0] = lj_ir_knum(J, (lua_Number)(uint32_t)fct->size);
809 return;
811 J->base[0] = lj_ir_kint(J, (int32_t)fct->size);
812 return; /* Interpreter will throw for newindex. */
813 } else if (ctype_isbitfield(fct->info)) {
814 lj_trace_err(J, LJ_TRERR_NYICONV);
815 } else {
816 lua_assert(ctype_isfield(fct->info));
817 sid = ctype_cid(fct->info);
819 ofs += (ptrdiff_t)fofs;
821 } else if (ctype_iscomplex(ct->info)) {
822 if (name->len == 2 &&
823 ((strdata(name)[0] == 'r' && strdata(name)[1] == 'e') ||
824 (strdata(name)[0] == 'i' && strdata(name)[1] == 'm'))) {
825 /* Always specialize to the field name. */
826 emitir(IRTG(IR_EQ, IRT_STR), idx, lj_ir_kstr(J, name));
827 if (strdata(name)[0] == 'i') ofs += (ct->size >> 1);
828 sid = ctype_cid(ct->info);
832 if (!sid) {
833 if (ctype_isptr(ct->info)) { /* Automatically perform '->'. */
834 CType *cct = ctype_rawchild(cts, ct);
835 if (ctype_isstruct(cct->info)) {
836 ct = cct;
837 if (tref_isstr(idx)) goto again;
840 crec_index_meta(J, cts, ct, rd);
841 return;
844 if (ofs)
845 ptr = emitir(IRT(IR_ADD, IRT_PTR), ptr, lj_ir_kintp(J, ofs));
847 /* Resolve reference for field. */
848 ct = ctype_get(cts, sid);
849 if (ctype_isref(ct->info))
850 ptr = emitir(IRT(IR_XLOAD, IRT_PTR), ptr, 0);
852 while (ctype_isattrib(ct->info))
853 ct = ctype_child(cts, ct); /* Skip attributes. */
855 if (rd->data == 0) { /* __index metamethod. */
856 J->base[0] = crec_tv_ct(J, ct, sid, ptr);
857 } else { /* __newindex metamethod. */
858 rd->nres = 0;
859 J->needsnap = 1;
860 crec_ct_tv(J, ct, ptr, J->base[2], &rd->argv[2]);
864 /* Record cdata allocation. */
865 static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id)
867 CTState *cts = ctype_ctsG(J2G(J));
868 CTSize sz;
869 CTInfo info = lj_ctype_info(cts, id, &sz);
870 CType *d = ctype_raw(cts, id);
871 TRef trid;
872 if (!sz || sz > 128 || (info & CTF_VLA) || ctype_align(info) > CT_MEMALIGN)
873 lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: large/special allocations. */
874 trid = lj_ir_kint(J, id);
875 /* Use special instruction to box pointer or 32/64 bit integer. */
876 if (ctype_isptr(info) || (ctype_isinteger(info) && (sz == 4 || sz == 8))) {
877 TRef sp = J->base[1] ? crec_ct_tv(J, d, 0, J->base[1], &rd->argv[1]) :
878 ctype_isptr(info) ? lj_ir_kptr(J, NULL) :
879 sz == 4 ? lj_ir_kint(J, 0) :
880 (lj_needsplit(J), lj_ir_kint64(J, 0));
881 J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), trid, sp);
882 } else {
883 TRef trcd = emitir(IRTG(IR_CNEW, IRT_CDATA), trid, TREF_NIL);
884 cTValue *fin;
885 J->base[0] = trcd;
886 if (J->base[1] && !J->base[2] &&
887 !lj_cconv_multi_init(cts, d, &rd->argv[1])) {
888 goto single_init;
889 } else if (ctype_isarray(d->info)) {
890 CType *dc = ctype_rawchild(cts, d); /* Array element type. */
891 CTSize ofs, esize = dc->size;
892 TRef sp = 0;
893 TValue tv;
894 TValue *sval = &tv;
895 MSize i;
896 tv.u64 = 0;
897 if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info)))
898 lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: init array of aggregates. */
899 for (i = 1, ofs = 0; ofs < sz; ofs += esize) {
900 TRef dp = emitir(IRT(IR_ADD, IRT_PTR), trcd,
901 lj_ir_kintp(J, ofs + sizeof(GCcdata)));
902 if (J->base[i]) {
903 sp = J->base[i];
904 sval = &rd->argv[i];
905 i++;
906 } else if (i != 2) {
907 sp = ctype_isnum(dc->info) ? lj_ir_kint(J, 0) : TREF_NIL;
909 crec_ct_tv(J, dc, dp, sp, sval);
911 } else if (ctype_isstruct(d->info)) {
912 CTypeID fid = d->sib;
913 MSize i = 1;
914 while (fid) {
915 CType *df = ctype_get(cts, fid);
916 fid = df->sib;
917 if (ctype_isfield(df->info)) {
918 CType *dc;
919 TRef sp, dp;
920 TValue tv;
921 TValue *sval = &tv;
922 setintV(&tv, 0);
923 if (!gcref(df->name)) continue; /* Ignore unnamed fields. */
924 dc = ctype_rawchild(cts, df); /* Field type. */
925 if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info) ||
926 ctype_isenum(dc->info)))
927 lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: init aggregates. */
928 if (J->base[i]) {
929 sp = J->base[i];
930 sval = &rd->argv[i];
931 i++;
932 } else {
933 sp = ctype_isptr(dc->info) ? TREF_NIL : lj_ir_kint(J, 0);
935 dp = emitir(IRT(IR_ADD, IRT_PTR), trcd,
936 lj_ir_kintp(J, df->size + sizeof(GCcdata)));
937 crec_ct_tv(J, dc, dp, sp, sval);
938 } else if (!ctype_isconstval(df->info)) {
939 /* NYI: init bitfields and sub-structures. */
940 lj_trace_err(J, LJ_TRERR_NYICONV);
943 } else {
944 TRef dp;
945 single_init:
946 dp = emitir(IRT(IR_ADD, IRT_PTR), trcd, lj_ir_kintp(J, sizeof(GCcdata)));
947 if (J->base[1]) {
948 crec_ct_tv(J, d, dp, J->base[1], &rd->argv[1]);
949 } else {
950 TValue tv;
951 tv.u64 = 0;
952 crec_ct_tv(J, d, dp, lj_ir_kint(J, 0), &tv);
955 /* Handle __gc metamethod. */
956 fin = lj_ctype_meta(cts, id, MM_gc);
957 if (fin) {
958 TRef trlo = lj_ir_call(J, IRCALL_lj_cdata_setfin, trcd);
959 TRef trhi = emitir(IRT(IR_ADD, IRT_P32), trlo, lj_ir_kint(J, 4));
960 if (LJ_BE) { TRef tmp = trlo; trlo = trhi; trhi = tmp; }
961 if (tvisfunc(fin)) {
962 emitir(IRT(IR_XSTORE, IRT_P32), trlo, lj_ir_kfunc(J, funcV(fin)));
963 emitir(IRTI(IR_XSTORE), trhi, lj_ir_kint(J, LJ_TFUNC));
964 } else if (tviscdata(fin)) {
965 emitir(IRT(IR_XSTORE, IRT_P32), trlo,
966 lj_ir_kgc(J, obj2gco(cdataV(fin)), IRT_CDATA));
967 emitir(IRTI(IR_XSTORE), trhi, lj_ir_kint(J, LJ_TCDATA));
968 } else {
969 lj_trace_err(J, LJ_TRERR_BADTYPE);
971 J->needsnap = 1;
976 /* Record argument conversions. */
977 static TRef crec_call_args(jit_State *J, RecordFFData *rd,
978 CTState *cts, CType *ct)
980 TRef args[CCI_NARGS_MAX];
981 CTypeID fid;
982 MSize i, n;
983 TRef tr, *base;
984 cTValue *o;
985 #if LJ_TARGET_X86
986 #if LJ_ABI_WIN
987 TRef *arg0 = NULL, *arg1 = NULL;
988 #endif
989 int ngpr = 0;
990 if (ctype_cconv(ct->info) == CTCC_THISCALL)
991 ngpr = 1;
992 else if (ctype_cconv(ct->info) == CTCC_FASTCALL)
993 ngpr = 2;
994 #endif
996 /* Skip initial attributes. */
997 fid = ct->sib;
998 while (fid) {
999 CType *ctf = ctype_get(cts, fid);
1000 if (!ctype_isattrib(ctf->info)) break;
1001 fid = ctf->sib;
1003 args[0] = TREF_NIL;
1004 for (n = 0, base = J->base+1, o = rd->argv+1; *base; n++, base++, o++) {
1005 CTypeID did;
1006 CType *d;
1008 if (n >= CCI_NARGS_MAX)
1009 lj_trace_err(J, LJ_TRERR_NYICALL);
1011 if (fid) { /* Get argument type from field. */
1012 CType *ctf = ctype_get(cts, fid);
1013 fid = ctf->sib;
1014 lua_assert(ctype_isfield(ctf->info));
1015 did = ctype_cid(ctf->info);
1016 } else {
1017 if (!(ct->info & CTF_VARARG))
1018 lj_trace_err(J, LJ_TRERR_NYICALL); /* Too many arguments. */
1019 did = lj_ccall_ctid_vararg(cts, o); /* Infer vararg type. */
1021 d = ctype_raw(cts, did);
1022 if (!(ctype_isnum(d->info) || ctype_isptr(d->info) ||
1023 ctype_isenum(d->info)))
1024 lj_trace_err(J, LJ_TRERR_NYICALL);
1025 tr = crec_ct_tv(J, d, 0, *base, o);
1026 if (ctype_isinteger_or_bool(d->info)) {
1027 if (d->size < 4) {
1028 if ((d->info & CTF_UNSIGNED))
1029 tr = emitconv(tr, IRT_INT, d->size==1 ? IRT_U8 : IRT_U16, 0);
1030 else
1031 tr = emitconv(tr, IRT_INT, d->size==1 ? IRT_I8 : IRT_I16,IRCONV_SEXT);
1033 } else if (LJ_SOFTFP && ctype_isfp(d->info) && d->size > 4) {
1034 lj_needsplit(J);
1036 #if LJ_TARGET_X86
1037 /* 64 bit args must not end up in registers for fastcall/thiscall. */
1038 #if LJ_ABI_WIN
1039 if (!ctype_isfp(d->info)) {
1040 /* Sigh, the Windows/x86 ABI allows reordering across 64 bit args. */
1041 if (tref_typerange(tr, IRT_I64, IRT_U64)) {
1042 if (ngpr) {
1043 arg0 = &args[n]; args[n++] = TREF_NIL; ngpr--;
1044 if (ngpr) {
1045 arg1 = &args[n]; args[n++] = TREF_NIL; ngpr--;
1048 } else {
1049 if (arg0) { *arg0 = tr; arg0 = NULL; n--; continue; }
1050 if (arg1) { *arg1 = tr; arg1 = NULL; n--; continue; }
1051 if (ngpr) ngpr--;
1054 #else
1055 if (!ctype_isfp(d->info) && ngpr) {
1056 if (tref_typerange(tr, IRT_I64, IRT_U64)) {
1057 /* No reordering for other x86 ABIs. Simply add alignment args. */
1058 do { args[n++] = TREF_NIL; } while (--ngpr);
1059 } else {
1060 ngpr--;
1063 #endif
1064 #endif
1065 args[n] = tr;
1067 tr = args[0];
1068 for (i = 1; i < n; i++)
1069 tr = emitir(IRT(IR_CARG, IRT_NIL), tr, args[i]);
1070 return tr;
1073 /* Create a snapshot for the caller, simulating a 'false' return value. */
1074 static void crec_snap_caller(jit_State *J)
1076 lua_State *L = J->L;
1077 TValue *base = L->base, *top = L->top;
1078 const BCIns *pc = J->pc;
1079 TRef ftr = J->base[-1];
1080 ptrdiff_t delta;
1081 if (!frame_islua(base-1))
1082 lj_trace_err(J, LJ_TRERR_NYICALL);
1083 J->pc = frame_pc(base-1); delta = 1+bc_a(J->pc[-1]);
1084 L->top = base; L->base = base - delta;
1085 J->base[-1] = TREF_FALSE;
1086 J->base -= delta; J->baseslot -= (BCReg)delta;
1087 J->maxslot = (BCReg)delta; J->framedepth--;
1088 lj_snap_add(J);
1089 L->base = base; L->top = top;
1090 J->framedepth++; J->maxslot = 1;
1091 J->base += delta; J->baseslot += (BCReg)delta;
1092 J->base[-1] = ftr; J->pc = pc;
1095 /* Record function call. */
1096 static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd)
1098 CTState *cts = ctype_ctsG(J2G(J));
1099 CType *ct = ctype_raw(cts, cd->ctypeid);
1100 IRType tp = IRT_PTR;
1101 if (ctype_isptr(ct->info)) {
1102 tp = (LJ_64 && ct->size == 8) ? IRT_P64 : IRT_P32;
1103 ct = ctype_rawchild(cts, ct);
1105 if (ctype_isfunc(ct->info)) {
1106 TRef func = emitir(IRT(IR_FLOAD, tp), J->base[0], IRFL_CDATA_PTR);
1107 CType *ctr = ctype_rawchild(cts, ct);
1108 IRType t = crec_ct2irt(cts, ctr);
1109 TRef tr;
1110 TValue tv;
1111 /* Check for blacklisted C functions that might call a callback. */
1112 setlightudV(&tv,
1113 cdata_getptr(cdataptr(cd), (LJ_64 && tp == IRT_P64) ? 8 : 4));
1114 if (tvistrue(lj_tab_get(J->L, cts->miscmap, &tv)))
1115 lj_trace_err(J, LJ_TRERR_BLACKL);
1116 if (ctype_isvoid(ctr->info)) {
1117 t = IRT_NIL;
1118 rd->nres = 0;
1119 } else if (!(ctype_isnum(ctr->info) || ctype_isptr(ctr->info) ||
1120 ctype_isenum(ctr->info)) || t == IRT_CDATA) {
1121 lj_trace_err(J, LJ_TRERR_NYICALL);
1123 if ((ct->info & CTF_VARARG)
1124 #if LJ_TARGET_X86
1125 || ctype_cconv(ct->info) != CTCC_CDECL
1126 #endif
1128 func = emitir(IRT(IR_CARG, IRT_NIL), func,
1129 lj_ir_kint(J, ctype_typeid(cts, ct)));
1130 tr = emitir(IRT(IR_CALLXS, t), crec_call_args(J, rd, cts, ct), func);
1131 if (ctype_isbool(ctr->info)) {
1132 if (frame_islua(J->L->base-1) && bc_b(frame_pc(J->L->base-1)[-1]) == 1) {
1133 /* Don't check result if ignored. */
1134 tr = TREF_NIL;
1135 } else {
1136 crec_snap_caller(J);
1137 lj_ir_set(J, IRTGI(IR_NE), tr, lj_ir_kint(J, 0));
1138 J->postproc = LJ_POST_FIXGUARDSNAP;
1139 tr = TREF_TRUE;
1141 } else if (t == IRT_PTR || (LJ_64 && t == IRT_P32) ||
1142 t == IRT_I64 || t == IRT_U64 || ctype_isenum(ctr->info)) {
1143 TRef trid = lj_ir_kint(J, ctype_cid(ct->info));
1144 tr = emitir(IRTG(IR_CNEWI, IRT_CDATA), trid, tr);
1145 if (t == IRT_I64 || t == IRT_U64) lj_needsplit(J);
1146 } else if (t == IRT_FLOAT || t == IRT_U32) {
1147 tr = emitconv(tr, IRT_NUM, t, 0);
1148 } else if (t == IRT_I8 || t == IRT_I16) {
1149 tr = emitconv(tr, IRT_INT, t, IRCONV_SEXT);
1150 } else if (t == IRT_U8 || t == IRT_U16) {
1151 tr = emitconv(tr, IRT_INT, t, 0);
1153 J->base[0] = tr;
1154 J->needsnap = 1;
1155 return 1;
1157 return 0;
1160 void LJ_FASTCALL recff_cdata_call(jit_State *J, RecordFFData *rd)
1162 CTState *cts = ctype_ctsG(J2G(J));
1163 GCcdata *cd = argv2cdata(J, J->base[0], &rd->argv[0]);
1164 CTypeID id = cd->ctypeid;
1165 CType *ct;
1166 cTValue *tv;
1167 MMS mm = MM_call;
1168 if (id == CTID_CTYPEID) {
1169 id = crec_constructor(J, cd, J->base[0]);
1170 mm = MM_new;
1171 } else if (crec_call(J, rd, cd)) {
1172 return;
1174 /* Record ctype __call/__new metamethod. */
1175 ct = ctype_raw(cts, id);
1176 tv = lj_ctype_meta(cts, ctype_isptr(ct->info) ? ctype_cid(ct->info) : id, mm);
1177 if (tv) {
1178 if (tvisfunc(tv)) {
1179 J->base[-1] = lj_ir_kfunc(J, funcV(tv)) | TREF_FRAME;
1180 rd->nres = -1; /* Pending tailcall. */
1181 return;
1183 } else if (mm == MM_new) {
1184 crec_alloc(J, rd, id);
1185 return;
1187 /* No metamethod or NYI: non-function metamethods. */
1188 lj_trace_err(J, LJ_TRERR_BADTYPE);
1191 static TRef crec_arith_int64(jit_State *J, TRef *sp, CType **s, MMS mm)
1193 if (ctype_isnum(s[0]->info) && ctype_isnum(s[1]->info)) {
1194 IRType dt;
1195 CTypeID id;
1196 TRef tr;
1197 MSize i;
1198 IROp op;
1199 lj_needsplit(J);
1200 if (((s[0]->info & CTF_UNSIGNED) && s[0]->size == 8) ||
1201 ((s[1]->info & CTF_UNSIGNED) && s[1]->size == 8)) {
1202 dt = IRT_U64; id = CTID_UINT64;
1203 } else {
1204 dt = IRT_I64; id = CTID_INT64;
1205 if (mm < MM_add &&
1206 !((s[0]->info | s[1]->info) & CTF_FP) &&
1207 s[0]->size == 4 && s[1]->size == 4) { /* Try to narrow comparison. */
1208 if (!((s[0]->info ^ s[1]->info) & CTF_UNSIGNED) ||
1209 (tref_isk(sp[1]) && IR(tref_ref(sp[1]))->i >= 0)) {
1210 dt = (s[0]->info & CTF_UNSIGNED) ? IRT_U32 : IRT_INT;
1211 goto comp;
1212 } else if (tref_isk(sp[0]) && IR(tref_ref(sp[0]))->i >= 0) {
1213 dt = (s[1]->info & CTF_UNSIGNED) ? IRT_U32 : IRT_INT;
1214 goto comp;
1218 for (i = 0; i < 2; i++) {
1219 IRType st = tref_type(sp[i]);
1220 if (st == IRT_NUM || st == IRT_FLOAT)
1221 sp[i] = emitconv(sp[i], dt, st, IRCONV_TRUNC|IRCONV_ANY);
1222 else if (!(st == IRT_I64 || st == IRT_U64))
1223 sp[i] = emitconv(sp[i], dt, IRT_INT,
1224 (s[i]->info & CTF_UNSIGNED) ? 0 : IRCONV_SEXT);
1226 if (mm < MM_add) {
1227 comp:
1228 /* Assume true comparison. Fixup and emit pending guard later. */
1229 if (mm == MM_eq) {
1230 op = IR_EQ;
1231 } else {
1232 op = mm == MM_lt ? IR_LT : IR_LE;
1233 if (dt == IRT_U32 || dt == IRT_U64)
1234 op += (IR_ULT-IR_LT);
1236 lj_ir_set(J, IRTG(op, dt), sp[0], sp[1]);
1237 J->postproc = LJ_POST_FIXGUARD;
1238 return TREF_TRUE;
1239 } else {
1240 tr = emitir(IRT(mm+(int)IR_ADD-(int)MM_add, dt), sp[0], sp[1]);
1242 return emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr);
1244 return 0;
1247 static TRef crec_arith_ptr(jit_State *J, TRef *sp, CType **s, MMS mm)
1249 CTState *cts = ctype_ctsG(J2G(J));
1250 CType *ctp = s[0];
1251 if (ctype_isptr(ctp->info) || ctype_isrefarray(ctp->info)) {
1252 if ((mm == MM_sub || mm == MM_eq || mm == MM_lt || mm == MM_le) &&
1253 (ctype_isptr(s[1]->info) || ctype_isrefarray(s[1]->info))) {
1254 if (mm == MM_sub) { /* Pointer difference. */
1255 TRef tr;
1256 CTSize sz = lj_ctype_size(cts, ctype_cid(ctp->info));
1257 if (sz == 0 || (sz & (sz-1)) != 0)
1258 return 0; /* NYI: integer division. */
1259 tr = emitir(IRT(IR_SUB, IRT_INTP), sp[0], sp[1]);
1260 tr = emitir(IRT(IR_BSAR, IRT_INTP), tr, lj_ir_kint(J, lj_fls(sz)));
1261 #if LJ_64
1262 tr = emitconv(tr, IRT_NUM, IRT_INTP, 0);
1263 #endif
1264 return tr;
1265 } else { /* Pointer comparison (unsigned). */
1266 /* Assume true comparison. Fixup and emit pending guard later. */
1267 IROp op = mm == MM_eq ? IR_EQ : mm == MM_lt ? IR_ULT : IR_ULE;
1268 lj_ir_set(J, IRTG(op, IRT_PTR), sp[0], sp[1]);
1269 J->postproc = LJ_POST_FIXGUARD;
1270 return TREF_TRUE;
1273 if (!((mm == MM_add || mm == MM_sub) && ctype_isnum(s[1]->info)))
1274 return 0;
1275 } else if (mm == MM_add && ctype_isnum(ctp->info) &&
1276 (ctype_isptr(s[1]->info) || ctype_isrefarray(s[1]->info))) {
1277 TRef tr = sp[0]; sp[0] = sp[1]; sp[1] = tr; /* Swap pointer and index. */
1278 ctp = s[1];
1279 } else {
1280 return 0;
1283 TRef tr = sp[1];
1284 IRType t = tref_type(tr);
1285 CTSize sz = lj_ctype_size(cts, ctype_cid(ctp->info));
1286 CTypeID id;
1287 #if LJ_64
1288 if (t == IRT_NUM || t == IRT_FLOAT)
1289 tr = emitconv(tr, IRT_INTP, t, IRCONV_TRUNC|IRCONV_ANY);
1290 else if (!(t == IRT_I64 || t == IRT_U64))
1291 tr = emitconv(tr, IRT_INTP, IRT_INT,
1292 ((t - IRT_I8) & 1) ? 0 : IRCONV_SEXT);
1293 #else
1294 if (!tref_typerange(sp[1], IRT_I8, IRT_U32)) {
1295 tr = emitconv(tr, IRT_INTP, t,
1296 (t == IRT_NUM || t == IRT_FLOAT) ?
1297 IRCONV_TRUNC|IRCONV_ANY : 0);
1299 #endif
1300 tr = emitir(IRT(IR_MUL, IRT_INTP), tr, lj_ir_kintp(J, sz));
1301 tr = emitir(IRT(mm+(int)IR_ADD-(int)MM_add, IRT_PTR), sp[0], tr);
1302 id = lj_ctype_intern(cts, CTINFO(CT_PTR, CTALIGN_PTR|ctype_cid(ctp->info)),
1303 CTSIZE_PTR);
1304 return emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr);
1308 /* Record ctype arithmetic metamethods. */
1309 static void crec_arith_meta(jit_State *J, CTState *cts, RecordFFData *rd)
1311 cTValue *tv = NULL;
1312 if (J->base[0]) {
1313 if (tviscdata(&rd->argv[0])) {
1314 CTypeID id = argv2cdata(J, J->base[0], &rd->argv[0])->ctypeid;
1315 CType *ct = ctype_raw(cts, id);
1316 if (ctype_isptr(ct->info)) id = ctype_cid(ct->info);
1317 tv = lj_ctype_meta(cts, id, (MMS)rd->data);
1319 if (!tv && J->base[1] && tviscdata(&rd->argv[1])) {
1320 CTypeID id = argv2cdata(J, J->base[1], &rd->argv[1])->ctypeid;
1321 CType *ct = ctype_raw(cts, id);
1322 if (ctype_isptr(ct->info)) id = ctype_cid(ct->info);
1323 tv = lj_ctype_meta(cts, id, (MMS)rd->data);
1326 if (tv) {
1327 if (tvisfunc(tv)) {
1328 J->base[-1] = lj_ir_kfunc(J, funcV(tv)) | TREF_FRAME;
1329 rd->nres = -1; /* Pending tailcall. */
1330 return;
1331 } /* NYI: non-function metamethods. */
1332 } else if ((MMS)rd->data == MM_eq) {
1333 J->base[0] = TREF_FALSE;
1334 return;
1336 lj_trace_err(J, LJ_TRERR_BADTYPE);
1339 void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
1341 CTState *cts = ctype_ctsG(J2G(J));
1342 TRef sp[2];
1343 CType *s[2];
1344 MSize i;
1345 for (i = 0; i < 2; i++) {
1346 TRef tr = J->base[i];
1347 CType *ct = ctype_get(cts, CTID_DOUBLE);
1348 if (!tr) {
1349 goto trymeta;
1350 } else if (tref_iscdata(tr)) {
1351 CTypeID id = argv2cdata(J, tr, &rd->argv[i])->ctypeid;
1352 IRType t;
1353 ct = ctype_raw(cts, id);
1354 t = crec_ct2irt(cts, ct);
1355 if (ctype_isptr(ct->info)) { /* Resolve pointer or reference. */
1356 tr = emitir(IRT(IR_FLOAD, t), tr, IRFL_CDATA_PTR);
1357 if (ctype_isref(ct->info)) {
1358 ct = ctype_rawchild(cts, ct);
1359 t = crec_ct2irt(cts, ct);
1361 } else if (t == IRT_I64 || t == IRT_U64) {
1362 tr = emitir(IRT(IR_FLOAD, t), tr, IRFL_CDATA_INT64);
1363 lj_needsplit(J);
1364 goto ok;
1365 } else if (t == IRT_INT || t == IRT_U32) {
1366 tr = emitir(IRT(IR_FLOAD, t), tr, IRFL_CDATA_INT);
1367 if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct);
1368 goto ok;
1369 } else if (ctype_isfunc(ct->info)) {
1370 tr = emitir(IRT(IR_FLOAD, IRT_PTR), tr, IRFL_CDATA_PTR);
1371 ct = ctype_get(cts,
1372 lj_ctype_intern(cts, CTINFO(CT_PTR, CTALIGN_PTR|id), CTSIZE_PTR));
1373 goto ok;
1374 } else {
1375 tr = emitir(IRT(IR_ADD, IRT_PTR), tr, lj_ir_kintp(J, sizeof(GCcdata)));
1377 if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct);
1378 if (ctype_isnum(ct->info)) {
1379 if (t == IRT_CDATA) goto trymeta;
1380 if (t == IRT_I64 || t == IRT_U64) lj_needsplit(J);
1381 tr = emitir(IRT(IR_XLOAD, t), tr, 0);
1382 } else if (!(ctype_isptr(ct->info) || ctype_isrefarray(ct->info))) {
1383 goto trymeta;
1385 } else if (tref_isnil(tr)) {
1386 tr = lj_ir_kptr(J, NULL);
1387 ct = ctype_get(cts, CTID_P_VOID);
1388 } else if (tref_isinteger(tr)) {
1389 ct = ctype_get(cts, CTID_INT32);
1390 } else if (tref_isstr(tr)) {
1391 TRef tr2 = J->base[1-i];
1392 CTypeID id = argv2cdata(J, tr2, &rd->argv[1-i])->ctypeid;
1393 ct = ctype_raw(cts, id);
1394 if (ctype_isenum(ct->info)) { /* Match string against enum constant. */
1395 GCstr *str = strV(&rd->argv[i]);
1396 CTSize ofs;
1397 CType *cct = lj_ctype_getfield(cts, ct, str, &ofs);
1398 if (cct && ctype_isconstval(cct->info)) {
1399 /* Specialize to the name of the enum constant. */
1400 emitir(IRTG(IR_EQ, IRT_STR), tr, lj_ir_kstr(J, str));
1401 ct = ctype_child(cts, cct);
1402 tr = lj_ir_kint(J, (int32_t)ofs);
1403 } /* else: interpreter will throw. */
1404 } /* else: interpreter will throw. */
1405 } else if (!tref_isnum(tr)) {
1406 goto trymeta;
1409 s[i] = ct;
1410 sp[i] = tr;
1413 TRef tr;
1414 if ((tr = crec_arith_int64(J, sp, s, (MMS)rd->data)) ||
1415 (tr = crec_arith_ptr(J, sp, s, (MMS)rd->data))) {
1416 J->base[0] = tr;
1417 /* Fixup cdata comparisons, too. Avoids some cdata escapes. */
1418 if (J->postproc == LJ_POST_FIXGUARD && frame_iscont(J->L->base-1) &&
1419 !irt_isguard(J->guardemit)) {
1420 const BCIns *pc = frame_contpc(J->L->base-1) - 1;
1421 if (bc_op(*pc) <= BC_ISNEP) {
1422 setframe_pc(&J2G(J)->tmptv, pc);
1423 J2G(J)->tmptv.u32.lo = ((tref_istrue(tr) ^ bc_op(*pc)) & 1);
1424 J->postproc = LJ_POST_FIXCOMP;
1427 } else {
1428 trymeta:
1429 crec_arith_meta(J, cts, rd);
1434 /* -- C library namespace metamethods ------------------------------------- */
1436 void LJ_FASTCALL recff_clib_index(jit_State *J, RecordFFData *rd)
1438 CTState *cts = ctype_ctsG(J2G(J));
1439 if (tref_isudata(J->base[0]) && tref_isstr(J->base[1]) &&
1440 udataV(&rd->argv[0])->udtype == UDTYPE_FFI_CLIB) {
1441 CLibrary *cl = (CLibrary *)uddata(udataV(&rd->argv[0]));
1442 GCstr *name = strV(&rd->argv[1]);
1443 CType *ct;
1444 CTypeID id = lj_ctype_getname(cts, &ct, name, CLNS_INDEX);
1445 cTValue *tv = lj_tab_getstr(cl->cache, name);
1446 rd->nres = rd->data;
1447 if (id && tv && !tvisnil(tv)) {
1448 /* Specialize to the symbol name and make the result a constant. */
1449 emitir(IRTG(IR_EQ, IRT_STR), J->base[1], lj_ir_kstr(J, name));
1450 if (ctype_isconstval(ct->info)) {
1451 if (ct->size >= 0x80000000u &&
1452 (ctype_child(cts, ct)->info & CTF_UNSIGNED))
1453 J->base[0] = lj_ir_knum(J, (lua_Number)(uint32_t)ct->size);
1454 else
1455 J->base[0] = lj_ir_kint(J, (int32_t)ct->size);
1456 } else if (ctype_isextern(ct->info)) {
1457 CTypeID sid = ctype_cid(ct->info);
1458 void *sp = *(void **)cdataptr(cdataV(tv));
1459 TRef ptr;
1460 ct = ctype_raw(cts, sid);
1461 if (LJ_64 && !checkptr32(sp))
1462 ptr = lj_ir_kintp(J, (uintptr_t)sp);
1463 else
1464 ptr = lj_ir_kptr(J, sp);
1465 if (rd->data) {
1466 J->base[0] = crec_tv_ct(J, ct, sid, ptr);
1467 } else {
1468 J->needsnap = 1;
1469 crec_ct_tv(J, ct, ptr, J->base[2], &rd->argv[2]);
1471 } else {
1472 J->base[0] = lj_ir_kgc(J, obj2gco(cdataV(tv)), IRT_CDATA);
1474 } else {
1475 lj_trace_err(J, LJ_TRERR_NOCACHE);
1477 } /* else: interpreter will throw. */
1480 /* -- FFI library functions ----------------------------------------------- */
1482 static TRef crec_toint(jit_State *J, CTState *cts, TRef sp, TValue *sval)
1484 return crec_ct_tv(J, ctype_get(cts, CTID_INT32), 0, sp, sval);
1487 void LJ_FASTCALL recff_ffi_new(jit_State *J, RecordFFData *rd)
1489 crec_alloc(J, rd, argv2ctype(J, J->base[0], &rd->argv[0]));
1492 void LJ_FASTCALL recff_ffi_errno(jit_State *J, RecordFFData *rd)
1494 UNUSED(rd);
1495 if (J->base[0])
1496 lj_trace_err(J, LJ_TRERR_NYICALL);
1497 J->base[0] = lj_ir_call(J, IRCALL_lj_vm_errno);
1500 void LJ_FASTCALL recff_ffi_string(jit_State *J, RecordFFData *rd)
1502 CTState *cts = ctype_ctsG(J2G(J));
1503 TRef tr = J->base[0];
1504 if (tr) {
1505 TRef trlen = J->base[1];
1506 if (trlen) {
1507 trlen = crec_toint(J, cts, trlen, &rd->argv[1]);
1508 tr = crec_ct_tv(J, ctype_get(cts, CTID_P_CVOID), 0, tr, &rd->argv[0]);
1509 } else {
1510 tr = crec_ct_tv(J, ctype_get(cts, CTID_P_CCHAR), 0, tr, &rd->argv[0]);
1511 trlen = lj_ir_call(J, IRCALL_strlen, tr);
1513 J->base[0] = emitir(IRT(IR_XSNEW, IRT_STR), tr, trlen);
1514 } /* else: interpreter will throw. */
1517 void LJ_FASTCALL recff_ffi_copy(jit_State *J, RecordFFData *rd)
1519 CTState *cts = ctype_ctsG(J2G(J));
1520 TRef trdst = J->base[0], trsrc = J->base[1], trlen = J->base[2];
1521 if (trdst && trsrc && (trlen || tref_isstr(trsrc))) {
1522 trdst = crec_ct_tv(J, ctype_get(cts, CTID_P_VOID), 0, trdst, &rd->argv[0]);
1523 trsrc = crec_ct_tv(J, ctype_get(cts, CTID_P_CVOID), 0, trsrc, &rd->argv[1]);
1524 if (trlen) {
1525 trlen = crec_toint(J, cts, trlen, &rd->argv[2]);
1526 } else {
1527 trlen = emitir(IRTI(IR_FLOAD), J->base[1], IRFL_STR_LEN);
1528 trlen = emitir(IRTI(IR_ADD), trlen, lj_ir_kint(J, 1));
1530 rd->nres = 0;
1531 crec_copy(J, trdst, trsrc, trlen, NULL);
1532 } /* else: interpreter will throw. */
1535 void LJ_FASTCALL recff_ffi_fill(jit_State *J, RecordFFData *rd)
1537 CTState *cts = ctype_ctsG(J2G(J));
1538 TRef trdst = J->base[0], trlen = J->base[1], trfill = J->base[2];
1539 if (trdst && trlen) {
1540 CTSize step = 1;
1541 if (tviscdata(&rd->argv[0])) { /* Get alignment of original destination. */
1542 CTSize sz;
1543 CType *ct = ctype_raw(cts, cdataV(&rd->argv[0])->ctypeid);
1544 if (ctype_isptr(ct->info))
1545 ct = ctype_rawchild(cts, ct);
1546 step = (1u<<ctype_align(lj_ctype_info(cts, ctype_typeid(cts, ct), &sz)));
1548 trdst = crec_ct_tv(J, ctype_get(cts, CTID_P_VOID), 0, trdst, &rd->argv[0]);
1549 trlen = crec_toint(J, cts, trlen, &rd->argv[1]);
1550 if (trfill)
1551 trfill = crec_toint(J, cts, trfill, &rd->argv[2]);
1552 else
1553 trfill = lj_ir_kint(J, 0);
1554 rd->nres = 0;
1555 crec_fill(J, trdst, trlen, trfill, step);
1556 } /* else: interpreter will throw. */
1559 void LJ_FASTCALL recff_ffi_typeof(jit_State *J, RecordFFData *rd)
1561 if (tref_iscdata(J->base[0])) {
1562 TRef trid = lj_ir_kint(J, argv2ctype(J, J->base[0], &rd->argv[0]));
1563 J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA),
1564 lj_ir_kint(J, CTID_CTYPEID), trid);
1565 } else {
1566 setfuncV(J->L, &J->errinfo, J->fn);
1567 lj_trace_err_info(J, LJ_TRERR_NYIFFU);
1571 void LJ_FASTCALL recff_ffi_istype(jit_State *J, RecordFFData *rd)
1573 argv2ctype(J, J->base[0], &rd->argv[0]);
1574 if (tref_iscdata(J->base[1])) {
1575 argv2ctype(J, J->base[1], &rd->argv[1]);
1576 J->postproc = LJ_POST_FIXBOOL;
1577 J->base[0] = TREF_TRUE;
1578 } else {
1579 J->base[0] = TREF_FALSE;
1583 void LJ_FASTCALL recff_ffi_abi(jit_State *J, RecordFFData *rd)
1585 if (tref_isstr(J->base[0])) {
1586 /* Specialize to the ABI string to make the boolean result a constant. */
1587 emitir(IRTG(IR_EQ, IRT_STR), J->base[0], lj_ir_kstr(J, strV(&rd->argv[0])));
1588 J->postproc = LJ_POST_FIXBOOL;
1589 J->base[0] = TREF_TRUE;
1590 } /* else: interpreter will throw. */
1593 /* -- Miscellaneous library functions ------------------------------------- */
1595 void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd)
1597 CTState *cts = ctype_ctsG(J2G(J));
1598 CType *d, *ct = lj_ctype_rawref(cts, cdataV(&rd->argv[0])->ctypeid);
1599 if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct);
1600 if (ctype_isnum(ct->info) || ctype_iscomplex(ct->info)) {
1601 if (ctype_isinteger_or_bool(ct->info) && ct->size <= 4 &&
1602 !(ct->size == 4 && (ct->info & CTF_UNSIGNED)))
1603 d = ctype_get(cts, CTID_INT32);
1604 else
1605 d = ctype_get(cts, CTID_DOUBLE);
1606 J->base[0] = crec_ct_tv(J, d, 0, J->base[0], &rd->argv[0]);
1607 } else {
1608 J->base[0] = TREF_NIL;
1612 #undef IR
1613 #undef emitir
1614 #undef emitconv
1616 #endif