2 ** Trace recorder for C data operations.
3 ** Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h
11 #if LJ_HASJIT && LJ_HASFFI
19 #include "lj_cparse.h"
25 #include "lj_ircall.h"
28 #include "lj_record.h"
29 #include "lj_ffrecord.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
)
49 if (!tref_iscdata(tr
))
50 lj_trace_err(J
, LJ_TRERR_BADTYPE
);
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
));
58 /* Specialize to the CTypeID held by a cdata constructor. */
59 static CTypeID
crec_constructor(jit_State
*J
, GCcdata
*cd
, TRef tr
)
62 lua_assert(tref_iscdata(tr
) && cd
->ctypeid
== CTID_CTYPEID
);
63 id
= *(CTypeID
*)cdataptr(cd
);
64 tr
= emitir(IRT(IR_ADD
, IRT_PTR
), tr
, lj_ir_kintp(J
, sizeof(GCcdata
)));
65 tr
= emitir(IRT(IR_XLOAD
, IRT_INT
), tr
, 0);
66 emitir(IRTG(IR_EQ
, IRT_INT
), tr
, lj_ir_kint(J
, (int32_t)id
));
70 static CTypeID
argv2ctype(jit_State
*J
, TRef tr
, cTValue
*o
)
76 /* Specialize to the string containing the C type declaration. */
77 emitir(IRTG(IR_EQ
, IRT_STR
), tr
, lj_ir_kstr(J
, s
));
79 cp
.cts
= ctype_ctsG(J2G(J
));
81 cp
.srcname
= strdata(s
);
84 cp
.mode
= CPARSE_MODE_ABSTRACT
|CPARSE_MODE_NOIMPLICIT
;
85 if (lj_cparse(&cp
) || cp
.cts
->top
> oldtop
) /* Avoid new struct defs. */
86 lj_trace_err(J
, LJ_TRERR_BADTYPE
);
89 GCcdata
*cd
= argv2cdata(J
, tr
, o
);
90 return cd
->ctypeid
== CTID_CTYPEID
? crec_constructor(J
, cd
, tr
) :
95 /* -- Convert C type to C type -------------------------------------------- */
98 ** This code mirrors the code in lj_cconv.c. It performs the same steps
99 ** for the trace recorder that lj_cconv.c does for the interpreter.
101 ** One major difference is that we can get away with much fewer checks
102 ** here. E.g. checks for casts, constness or correct types can often be
103 ** omitted, even if they might fail. The interpreter subsequently throws
104 ** an error, which aborts the trace.
106 ** All operations are specialized to their C types, so the on-trace
107 ** outcome must be the same as the outcome in the interpreter. If the
108 ** interpreter doesn't throw an error, then the trace is correct, too.
109 ** Care must be taken not to generate invalid (temporary) IR or to
113 /* Convert CType to IRType. */
114 static IRType
crec_ct2irt(CTState
*cts
, CType
*ct
)
116 if (ctype_isenum(ct
->info
)) ct
= ctype_child(cts
, ct
);
117 if (LJ_LIKELY(ctype_isnum(ct
->info
))) {
118 if ((ct
->info
& CTF_FP
)) {
119 if (ct
->size
== sizeof(double))
121 else if (ct
->size
== sizeof(float))
124 uint32_t b
= lj_fls(ct
->size
);
126 return IRT_I8
+ 2*b
+ ((ct
->info
& CTF_UNSIGNED
) ? 1 : 0);
128 } else if (ctype_isptr(ct
->info
)) {
129 return (LJ_64
&& ct
->size
== 8) ? IRT_P64
: IRT_P32
;
130 } else if (ctype_iscomplex(ct
->info
)) {
131 if (ct
->size
== 2*sizeof(double))
133 else if (ct
->size
== 2*sizeof(float))
139 /* Determine whether a passed number or cdata number is non-zero. */
140 static int crec_isnonzero(CType
*s
, void *p
)
146 if ((s
->info
& CTF_FP
)) {
147 if (s
->size
== sizeof(float))
148 return (*(float *)p
!= 0);
150 return (*(double *)p
!= 0);
153 return (*(uint8_t *)p
!= 0);
154 else if (s
->size
== 2)
155 return (*(uint16_t *)p
!= 0);
156 else if (s
->size
== 4)
157 return (*(uint32_t *)p
!= 0);
159 return (*(uint64_t *)p
!= 0);
163 static TRef
crec_ct_ct(jit_State
*J
, CType
*d
, CType
*s
, TRef dp
, TRef sp
,
166 IRType dt
= crec_ct2irt(ctype_ctsG(J2G(J
)), d
);
167 IRType st
= crec_ct2irt(ctype_ctsG(J2G(J
)), s
);
168 CTSize dsize
= d
->size
, ssize
= s
->size
;
169 CTInfo dinfo
= d
->info
, sinfo
= s
->info
;
171 if (ctype_type(dinfo
) > CT_MAYCONVERT
|| ctype_type(sinfo
) > CT_MAYCONVERT
)
175 ** Note: Unlike lj_cconv_ct_ct(), sp holds the _value_ of pointers and
176 ** numbers up to 8 bytes. Otherwise sp holds a pointer.
179 switch (cconv_idx2(dinfo
, sinfo
)) {
180 /* Destination is a bool. */
182 goto xstore
; /* Source operand is already normalized. */
185 if (st
!= IRT_CDATA
) {
186 /* Specialize to the result of a comparison against 0. */
187 TRef zero
= (st
== IRT_NUM
|| st
== IRT_FLOAT
) ? lj_ir_knum(J
, 0) :
188 (st
== IRT_I64
|| st
== IRT_U64
) ? lj_ir_kint64(J
, 0) :
190 int isnz
= crec_isnonzero(s
, svisnz
);
191 emitir(IRTG(isnz
? IR_NE
: IR_EQ
, st
), sp
, zero
);
192 sp
= lj_ir_kint(J
, isnz
);
197 /* Destination is an integer. */
201 if (dt
== IRT_CDATA
|| st
== IRT_CDATA
) goto err_nyi
;
202 /* Extend 32 to 64 bit integer. */
203 if (dsize
== 8 && ssize
< 8 && !(LJ_64
&& (sinfo
& CTF_UNSIGNED
)))
204 sp
= emitconv(sp
, dt
, ssize
< 4 ? IRT_INT
: st
,
205 (sinfo
& CTF_UNSIGNED
) ? 0 : IRCONV_SEXT
);
206 else if (dsize
< 8 && ssize
== 8) /* Truncate from 64 bit integer. */
207 sp
= emitconv(sp
, dsize
< 4 ? IRT_INT
: dt
, st
, 0);
208 else if (st
== IRT_INT
)
209 sp
= lj_opt_narrow_toint(J
, sp
);
211 if (dt
== IRT_I64
|| dt
== IRT_U64
) lj_needsplit(J
);
212 if (dp
== 0) return sp
;
213 emitir(IRT(IR_XSTORE
, dt
), dp
, sp
);
216 sp
= emitir(IRT(IR_XLOAD
, st
), sp
, 0); /* Load re. */
219 if (dt
== IRT_CDATA
|| st
== IRT_CDATA
) goto err_nyi
;
220 sp
= emitconv(sp
, dsize
< 4 ? IRT_INT
: dt
, st
, IRCONV_TRUNC
|IRCONV_ANY
);
224 sinfo
= CTINFO(CT_NUM
, CTF_UNSIGNED
);
229 /* Destination is a floating-point number. */
233 if (dt
== IRT_CDATA
|| st
== IRT_CDATA
) goto err_nyi
;
234 sp
= emitconv(sp
, dt
, ssize
< 4 ? IRT_INT
: st
, 0);
237 sp
= emitir(IRT(IR_XLOAD
, st
), sp
, 0); /* Load re. */
241 if (dt
== IRT_CDATA
|| st
== IRT_CDATA
) goto err_nyi
;
242 if (dt
!= st
) sp
= emitconv(sp
, dt
, st
, 0);
245 /* Destination is a complex number. */
249 TRef ptr
= emitir(IRT(IR_ADD
, IRT_PTR
), dp
, lj_ir_kintp(J
, (dsize
>> 1)));
250 emitir(IRT(IR_XSTORE
, dt
), ptr
, lj_ir_knum(J
, 0));
253 if ((sinfo
& CTF_FP
)) goto conv_F_F
; else goto conv_F_I
;
256 if (dt
== IRT_CDATA
|| st
== IRT_CDATA
) goto err_nyi
;
259 re
= emitir(IRT(IR_XLOAD
, st
), sp
, 0);
260 ptr
= emitir(IRT(IR_ADD
, IRT_PTR
), sp
, lj_ir_kintp(J
, (ssize
>> 1)));
261 im
= emitir(IRT(IR_XLOAD
, st
), ptr
, 0);
263 re
= emitconv(re
, dt
, st
, 0);
264 im
= emitconv(im
, dt
, st
, 0);
266 emitir(IRT(IR_XSTORE
, dt
), dp
, re
);
267 ptr
= emitir(IRT(IR_ADD
, IRT_PTR
), dp
, lj_ir_kintp(J
, (dsize
>> 1)));
268 emitir(IRT(IR_XSTORE
, dt
), ptr
, im
);
272 /* Destination is a vector. */
279 /* Destination is a pointer. */
283 /* There are only 32 bit pointers/addresses on 32 bit machines.
284 ** Also ok on x64, since all 32 bit ops clear the upper part of the reg.
288 if (st
== IRT_CDATA
) goto err_nyi
;
289 if (!LJ_64
&& ssize
== 8) /* Truncate from 64 bit integer. */
290 sp
= emitconv(sp
, IRT_U32
, st
, 0);
293 if (st
== IRT_CDATA
) goto err_nyi
;
294 /* The signed conversion is cheaper. x64 really has 47 bit pointers. */
295 sp
= emitconv(sp
, (LJ_64
&& dsize
== 8) ? IRT_I64
: IRT_U32
,
296 st
, IRCONV_TRUNC
|IRCONV_ANY
);
299 /* Destination is an array. */
303 /* Destination is a struct/union. */
310 lj_trace_err(J
, LJ_TRERR_NYICONV
);
316 /* -- Convert C type to TValue (load) ------------------------------------- */
318 static TRef
crec_tv_ct(jit_State
*J
, CType
*s
, CTypeID sid
, TRef sp
)
320 CTState
*cts
= ctype_ctsG(J2G(J
));
321 IRType t
= crec_ct2irt(cts
, s
);
322 CTInfo sinfo
= s
->info
;
323 if (ctype_isnum(sinfo
)) {
326 goto err_nyi
; /* NYI: copyval of >64 bit integers. */
327 tr
= emitir(IRT(IR_XLOAD
, t
), sp
, 0);
328 if (t
== IRT_FLOAT
|| t
== IRT_U32
) { /* Keep uint32_t/float as numbers. */
329 return emitconv(tr
, IRT_NUM
, t
, 0);
330 } else if (t
== IRT_I64
|| t
== IRT_U64
) { /* Box 64 bit integer. */
333 } else if ((sinfo
& CTF_BOOL
)) {
334 /* Assume not equal to zero. Fixup and emit pending guard later. */
335 lj_ir_set(J
, IRTGI(IR_NE
), tr
, lj_ir_kint(J
, 0));
336 J
->postproc
= LJ_POST_FIXGUARD
;
341 } else if (ctype_isptr(sinfo
) || ctype_isenum(sinfo
)) {
342 sp
= emitir(IRT(IR_XLOAD
, t
), sp
, 0); /* Box pointers and enums. */
343 } else if (ctype_isrefarray(sinfo
) || ctype_isstruct(sinfo
)) {
345 sid
= lj_ctype_intern(cts
, CTINFO_REF(sid
), CTSIZE_PTR
); /* Create ref. */
346 } else if (ctype_iscomplex(sinfo
)) { /* Unbox/box complex. */
347 ptrdiff_t esz
= (ptrdiff_t)(s
->size
>> 1);
348 TRef ptr
, tr1
, tr2
, dp
;
349 dp
= emitir(IRTG(IR_CNEW
, IRT_CDATA
), lj_ir_kint(J
, sid
), TREF_NIL
);
350 tr1
= emitir(IRT(IR_XLOAD
, t
), sp
, 0);
351 ptr
= emitir(IRT(IR_ADD
, IRT_PTR
), sp
, lj_ir_kintp(J
, esz
));
352 tr2
= emitir(IRT(IR_XLOAD
, t
), ptr
, 0);
353 ptr
= emitir(IRT(IR_ADD
, IRT_PTR
), dp
, lj_ir_kintp(J
, sizeof(GCcdata
)));
354 emitir(IRT(IR_XSTORE
, t
), ptr
, tr1
);
355 ptr
= emitir(IRT(IR_ADD
, IRT_PTR
), dp
, lj_ir_kintp(J
, sizeof(GCcdata
)+esz
));
356 emitir(IRT(IR_XSTORE
, t
), ptr
, tr2
);
359 /* NYI: copyval of vectors. */
361 lj_trace_err(J
, LJ_TRERR_NYICONV
);
363 /* Box pointer, ref, enum or 64 bit integer. */
364 return emitir(IRTG(IR_CNEWI
, IRT_CDATA
), lj_ir_kint(J
, sid
), sp
);
367 /* -- Convert TValue to C type (store) ------------------------------------ */
369 static TRef
crec_ct_tv(jit_State
*J
, CType
*d
, TRef dp
, TRef sp
, cTValue
*sval
)
371 CTState
*cts
= ctype_ctsG(J2G(J
));
372 CTypeID sid
= CTID_P_VOID
;
375 if (LJ_LIKELY(tref_isinteger(sp
))) {
377 svisnz
= (void *)(intptr_t)(tvisint(sval
)?(intV(sval
)!=0):!tviszero(sval
));
378 } else if (tref_isnum(sp
)) {
380 svisnz
= (void *)(intptr_t)(tvisint(sval
)?(intV(sval
)!=0):!tviszero(sval
));
381 } else if (tref_isbool(sp
)) {
382 sp
= lj_ir_kint(J
, tref_istrue(sp
) ? 1 : 0);
384 } else if (tref_isnil(sp
)) {
385 sp
= lj_ir_kptr(J
, NULL
);
386 } else if (tref_isudata(sp
)) {
387 GCudata
*ud
= udataV(sval
);
388 if (ud
->udtype
== UDTYPE_IO_FILE
) {
389 TRef tr
= emitir(IRT(IR_FLOAD
, IRT_U8
), sp
, IRFL_UDATA_UDTYPE
);
390 emitir(IRTGI(IR_EQ
), tr
, lj_ir_kint(J
, UDTYPE_IO_FILE
));
391 sp
= emitir(IRT(IR_FLOAD
, IRT_PTR
), sp
, IRFL_UDATA_FILE
);
393 sp
= emitir(IRT(IR_ADD
, IRT_P32
), sp
, lj_ir_kint(J
, sizeof(GCudata
)));
395 } else if (tref_isstr(sp
)) {
396 if (ctype_isenum(d
->info
)) { /* Match string against enum constant. */
397 GCstr
*str
= strV(sval
);
399 CType
*cct
= lj_ctype_getfield(cts
, d
, str
, &ofs
);
400 /* Specialize to the name of the enum constant. */
401 emitir(IRTG(IR_EQ
, IRT_STR
), sp
, lj_ir_kstr(J
, str
));
402 if (cct
&& ctype_isconstval(cct
->info
)) {
403 lua_assert(ctype_child(cts
, cct
)->size
== 4);
404 svisnz
= (void *)(intptr_t)(ofs
!= 0);
405 sp
= lj_ir_kint(J
, (int32_t)ofs
);
406 sid
= ctype_cid(cct
->info
);
407 } /* else: interpreter will throw. */
408 } else if (ctype_isrefarray(d
->info
)) { /* Copy string to array. */
409 lj_trace_err(J
, LJ_TRERR_BADTYPE
); /* NYI */
410 } else { /* Otherwise pass the string data as a const char[]. */
411 sp
= emitir(IRT(IR_STRREF
, IRT_P32
), sp
, lj_ir_kint(J
, 0));
414 } else { /* NYI: tref_istab(sp), tref_islightud(sp). */
416 sid
= argv2cdata(J
, sp
, sval
)->ctypeid
;
417 s
= ctype_raw(cts
, sid
);
418 svisnz
= cdataptr(cdataV(sval
));
419 t
= crec_ct2irt(cts
, s
);
420 if (ctype_isptr(s
->info
)) {
421 sp
= emitir(IRT(IR_FLOAD
, t
), sp
, IRFL_CDATA_PTR
);
422 if (ctype_isref(s
->info
)) {
423 svisnz
= *(void **)svisnz
;
424 s
= ctype_rawchild(cts
, s
);
425 if (ctype_isenum(s
->info
)) s
= ctype_child(cts
, s
);
426 t
= crec_ct2irt(cts
, s
);
430 } else if (t
== IRT_I64
|| t
== IRT_U64
) {
431 sp
= emitir(IRT(IR_FLOAD
, t
), sp
, IRFL_CDATA_INT64
);
434 } else if (t
== IRT_INT
|| t
== IRT_U32
) {
435 if (ctype_isenum(s
->info
)) s
= ctype_child(cts
, s
);
436 sp
= emitir(IRT(IR_FLOAD
, t
), sp
, IRFL_CDATA_INT
);
439 sp
= emitir(IRT(IR_ADD
, IRT_PTR
), sp
, lj_ir_kintp(J
, sizeof(GCcdata
)));
441 if (ctype_isnum(s
->info
) && t
!= IRT_CDATA
)
442 sp
= emitir(IRT(IR_XLOAD
, t
), sp
, 0); /* Load number value. */
445 s
= ctype_get(cts
, sid
);
447 if (ctype_isenum(d
->info
)) d
= ctype_child(cts
, d
);
448 return crec_ct_ct(J
, d
, s
, dp
, sp
, svisnz
);
451 /* -- C data metamethods -------------------------------------------------- */
453 /* This would be rather difficult in FOLD, so do it here:
454 ** (base+k)+(idx*sz)+ofs ==> (base+idx*sz)+(ofs+k)
455 ** (base+(idx+k)*sz)+ofs ==> (base+idx*sz)+(ofs+k*sz)
457 static TRef
crec_reassoc_ofs(jit_State
*J
, TRef tr
, ptrdiff_t *ofsp
, MSize sz
)
459 IRIns
*ir
= IR(tref_ref(tr
));
460 if (LJ_LIKELY(J
->flags
& JIT_F_OPT_FOLD
) && irref_isk(ir
->op2
) &&
461 (ir
->o
== IR_ADD
|| ir
->o
== IR_ADDOV
|| ir
->o
== IR_SUBOV
)) {
462 IRIns
*irk
= IR(ir
->op2
);
464 if (LJ_64
&& irk
->o
== IR_KINT64
)
465 k
= (ptrdiff_t)ir_kint64(irk
)->u64
* sz
;
467 k
= (ptrdiff_t)irk
->i
* sz
;
468 if (ir
->o
== IR_SUBOV
) *ofsp
-= k
; else *ofsp
+= k
;
469 tr
= ir
->op1
; /* Not a TRef, but the caller doesn't care. */
474 /* Record ctype __index/__newindex metamethods. */
475 static void crec_index_meta(jit_State
*J
, CTState
*cts
, CType
*ct
,
478 CTypeID id
= ctype_typeid(cts
, ct
);
479 cTValue
*tv
= lj_ctype_meta(cts
, id
, rd
->data
? MM_newindex
: MM_index
);
481 lj_trace_err(J
, LJ_TRERR_BADTYPE
);
483 J
->base
[-1] = lj_ir_kfunc(J
, funcV(tv
)) | TREF_FRAME
;
484 rd
->nres
= -1; /* Pending tailcall. */
485 } else if (rd
->data
== 0 && tvistab(tv
) && tref_isstr(J
->base
[1])) {
486 /* Specialize to result of __index lookup. */
487 cTValue
*o
= lj_tab_get(J
->L
, tabV(tv
), &rd
->argv
[1]);
488 J
->base
[0] = lj_record_constify(J
, o
);
490 lj_trace_err(J
, LJ_TRERR_BADTYPE
);
491 /* Always specialize to the key. */
492 emitir(IRTG(IR_EQ
, IRT_STR
), J
->base
[1], lj_ir_kstr(J
, strV(&rd
->argv
[1])));
494 /* NYI: resolving of non-function metamethods. */
495 /* NYI: non-string keys for __index table. */
496 /* NYI: stores to __newindex table. */
497 lj_trace_err(J
, LJ_TRERR_BADTYPE
);
501 void LJ_FASTCALL
recff_cdata_index(jit_State
*J
, RecordFFData
*rd
)
503 TRef idx
, ptr
= J
->base
[0];
504 ptrdiff_t ofs
= sizeof(GCcdata
);
505 GCcdata
*cd
= argv2cdata(J
, ptr
, &rd
->argv
[0]);
506 CTState
*cts
= ctype_ctsG(J2G(J
));
507 CType
*ct
= ctype_raw(cts
, cd
->ctypeid
);
510 /* Resolve pointer or reference for cdata object. */
511 if (ctype_isptr(ct
->info
)) {
512 IRType t
= (LJ_64
&& ct
->size
== 8) ? IRT_P64
: IRT_P32
;
513 if (ctype_isref(ct
->info
)) ct
= ctype_rawchild(cts
, ct
);
514 ptr
= emitir(IRT(IR_FLOAD
, t
), ptr
, IRFL_CDATA_PTR
);
516 ptr
= crec_reassoc_ofs(J
, ptr
, &ofs
, 1);
521 if (tref_isnumber(idx
)) {
522 idx
= lj_opt_narrow_cindex(J
, idx
);
523 if (ctype_ispointer(ct
->info
)) {
526 if ((ct
->info
& CTF_COMPLEX
))
527 idx
= emitir(IRT(IR_BAND
, IRT_INTP
), idx
, lj_ir_kintp(J
, 1));
528 sz
= lj_ctype_size(cts
, (sid
= ctype_cid(ct
->info
)));
529 idx
= crec_reassoc_ofs(J
, idx
, &ofs
, sz
);
530 #if LJ_TARGET_ARM || LJ_TARGET_PPC
531 /* Hoist base add to allow fusion of index/shift into operands. */
532 if (LJ_LIKELY(J
->flags
& JIT_F_OPT_LOOP
) && ofs
534 && (sz
== 1 || sz
== 4)
537 ptr
= emitir(IRT(IR_ADD
, IRT_PTR
), ptr
, lj_ir_kintp(J
, ofs
));
541 idx
= emitir(IRT(IR_MUL
, IRT_INTP
), idx
, lj_ir_kintp(J
, sz
));
542 ptr
= emitir(IRT(IR_ADD
, IRT_PTR
), idx
, ptr
);
544 } else if (tref_iscdata(idx
)) {
545 GCcdata
*cdk
= cdataV(&rd
->argv
[1]);
546 CType
*ctk
= ctype_raw(cts
, cdk
->ctypeid
);
547 IRType t
= crec_ct2irt(cts
, ctk
);
548 if (ctype_ispointer(ct
->info
) && t
>= IRT_I8
&& t
<= IRT_U64
) {
549 if (ctk
->size
== 8) {
550 idx
= emitir(IRT(IR_FLOAD
, t
), idx
, IRFL_CDATA_INT64
);
551 } else if (ctk
->size
== 4) {
552 idx
= emitir(IRT(IR_FLOAD
, t
), idx
, IRFL_CDATA_INT
);
554 idx
= emitir(IRT(IR_ADD
, IRT_PTR
), idx
,
555 lj_ir_kintp(J
, sizeof(GCcdata
)));
556 idx
= emitir(IRT(IR_XLOAD
, t
), idx
, 0);
558 if (LJ_64
&& ctk
->size
< sizeof(intptr_t) && !(ctk
->info
& CTF_UNSIGNED
))
559 idx
= emitconv(idx
, IRT_INTP
, IRT_INT
, IRCONV_SEXT
);
560 if (!LJ_64
&& ctk
->size
> sizeof(intptr_t)) {
561 idx
= emitconv(idx
, IRT_INTP
, t
, 0);
566 } else if (tref_isstr(idx
)) {
567 GCstr
*name
= strV(&rd
->argv
[1]);
568 if (cd
->ctypeid
== CTID_CTYPEID
)
569 ct
= ctype_raw(cts
, crec_constructor(J
, cd
, ptr
));
570 if (ctype_isstruct(ct
->info
)) {
573 fct
= lj_ctype_getfield(cts
, ct
, name
, &fofs
);
575 /* Always specialize to the field name. */
576 emitir(IRTG(IR_EQ
, IRT_STR
), idx
, lj_ir_kstr(J
, name
));
577 if (ctype_isconstval(fct
->info
)) {
578 if (fct
->size
>= 0x80000000u
&&
579 (ctype_child(cts
, fct
)->info
& CTF_UNSIGNED
)) {
580 J
->base
[0] = lj_ir_knum(J
, (lua_Number
)(uint32_t)fct
->size
);
583 J
->base
[0] = lj_ir_kint(J
, (int32_t)fct
->size
);
584 return; /* Interpreter will throw for newindex. */
585 } else if (ctype_isbitfield(fct
->info
)) {
586 lj_trace_err(J
, LJ_TRERR_NYICONV
);
588 lua_assert(ctype_isfield(fct
->info
));
589 sid
= ctype_cid(fct
->info
);
591 ofs
+= (ptrdiff_t)fofs
;
593 } else if (ctype_iscomplex(ct
->info
)) {
594 if (name
->len
== 2 &&
595 ((strdata(name
)[0] == 'r' && strdata(name
)[1] == 'e') ||
596 (strdata(name
)[0] == 'i' && strdata(name
)[1] == 'm'))) {
597 /* Always specialize to the field name. */
598 emitir(IRTG(IR_EQ
, IRT_STR
), idx
, lj_ir_kstr(J
, name
));
599 if (strdata(name
)[0] == 'i') ofs
+= (ct
->size
>> 1);
600 sid
= ctype_cid(ct
->info
);
605 if (ctype_isptr(ct
->info
)) { /* Automatically perform '->'. */
606 CType
*cct
= ctype_rawchild(cts
, ct
);
607 if (ctype_isstruct(cct
->info
)) {
609 if (tref_isstr(idx
)) goto again
;
612 crec_index_meta(J
, cts
, ct
, rd
);
617 ptr
= emitir(IRT(IR_ADD
, IRT_PTR
), ptr
, lj_ir_kintp(J
, ofs
));
619 /* Resolve reference for field. */
620 ct
= ctype_get(cts
, sid
);
621 if (ctype_isref(ct
->info
))
622 ptr
= emitir(IRT(IR_XLOAD
, IRT_PTR
), ptr
, 0);
624 while (ctype_isattrib(ct
->info
))
625 ct
= ctype_child(cts
, ct
); /* Skip attributes. */
627 if (rd
->data
== 0) { /* __index metamethod. */
628 J
->base
[0] = crec_tv_ct(J
, ct
, sid
, ptr
);
629 } else { /* __newindex metamethod. */
632 crec_ct_tv(J
, ct
, ptr
, J
->base
[2], &rd
->argv
[2]);
636 /* Record cdata allocation. */
637 static void crec_alloc(jit_State
*J
, RecordFFData
*rd
, CTypeID id
)
639 CTState
*cts
= ctype_ctsG(J2G(J
));
641 CTInfo info
= lj_ctype_info(cts
, id
, &sz
);
642 CType
*d
= ctype_raw(cts
, id
);
644 if (!sz
|| sz
> 128 || (info
& CTF_VLA
) || ctype_align(info
) > CT_MEMALIGN
)
645 lj_trace_err(J
, LJ_TRERR_NYICONV
); /* NYI: large/special allocations. */
646 trid
= lj_ir_kint(J
, id
);
647 /* Use special instruction to box pointer or 32/64 bit integer. */
648 if (ctype_isptr(info
) || (ctype_isinteger(info
) && (sz
== 4 || sz
== 8))) {
649 TRef sp
= J
->base
[1] ? crec_ct_tv(J
, d
, 0, J
->base
[1], &rd
->argv
[1]) :
650 ctype_isptr(info
) ? lj_ir_kptr(J
, NULL
) :
651 sz
== 4 ? lj_ir_kint(J
, 0) :
652 (lj_needsplit(J
), lj_ir_kint64(J
, 0));
653 J
->base
[0] = emitir(IRTG(IR_CNEWI
, IRT_CDATA
), trid
, sp
);
655 TRef trcd
= emitir(IRTG(IR_CNEW
, IRT_CDATA
), trid
, TREF_NIL
);
658 if (J
->base
[1] && !J
->base
[2] && !lj_cconv_multi_init(d
, &rd
->argv
[1])) {
660 } else if (ctype_isarray(d
->info
)) {
661 CType
*dc
= ctype_rawchild(cts
, d
); /* Array element type. */
662 CTSize ofs
, esize
= dc
->size
;
668 if (!(ctype_isnum(dc
->info
) || ctype_isptr(dc
->info
)))
669 lj_trace_err(J
, LJ_TRERR_NYICONV
); /* NYI: init array of aggregates. */
670 for (i
= 1, ofs
= 0; ofs
< sz
; ofs
+= esize
) {
671 TRef dp
= emitir(IRT(IR_ADD
, IRT_PTR
), trcd
,
672 lj_ir_kintp(J
, ofs
+ sizeof(GCcdata
)));
678 sp
= ctype_isnum(dc
->info
) ? lj_ir_kint(J
, 0) : TREF_NIL
;
680 crec_ct_tv(J
, dc
, dp
, sp
, sval
);
682 } else if (ctype_isstruct(d
->info
)) {
683 CTypeID fid
= d
->sib
;
686 CType
*df
= ctype_get(cts
, fid
);
688 if (ctype_isfield(df
->info
)) {
694 if (!gcref(df
->name
)) continue; /* Ignore unnamed fields. */
695 dc
= ctype_rawchild(cts
, df
); /* Field type. */
696 if (!(ctype_isnum(dc
->info
) || ctype_isptr(dc
->info
) ||
697 ctype_isenum(dc
->info
)))
698 lj_trace_err(J
, LJ_TRERR_NYICONV
); /* NYI: init aggregates. */
704 sp
= ctype_isptr(dc
->info
) ? TREF_NIL
: lj_ir_kint(J
, 0);
706 dp
= emitir(IRT(IR_ADD
, IRT_PTR
), trcd
,
707 lj_ir_kintp(J
, df
->size
+ sizeof(GCcdata
)));
708 crec_ct_tv(J
, dc
, dp
, sp
, sval
);
709 } else if (!ctype_isconstval(df
->info
)) {
710 /* NYI: init bitfields and sub-structures. */
711 lj_trace_err(J
, LJ_TRERR_NYICONV
);
717 dp
= emitir(IRT(IR_ADD
, IRT_PTR
), trcd
, lj_ir_kintp(J
, sizeof(GCcdata
)));
719 crec_ct_tv(J
, d
, dp
, J
->base
[1], &rd
->argv
[1]);
723 crec_ct_tv(J
, d
, dp
, lj_ir_kint(J
, 0), &tv
);
726 /* Handle __gc metamethod. */
727 fin
= lj_ctype_meta(cts
, id
, MM_gc
);
729 TRef trlo
= lj_ir_call(J
, IRCALL_lj_cdata_setfin
, trcd
);
730 TRef trhi
= emitir(IRT(IR_ADD
, IRT_P32
), trlo
, lj_ir_kint(J
, 4));
731 if (LJ_BE
) { TRef tmp
= trlo
; trlo
= trhi
; trhi
= tmp
; }
733 emitir(IRT(IR_XSTORE
, IRT_P32
), trlo
, lj_ir_kfunc(J
, funcV(fin
)));
734 emitir(IRTI(IR_XSTORE
), trhi
, lj_ir_kint(J
, LJ_TFUNC
));
735 } else if (tviscdata(fin
)) {
736 emitir(IRT(IR_XSTORE
, IRT_P32
), trlo
,
737 lj_ir_kgc(J
, obj2gco(cdataV(fin
)), IRT_CDATA
));
738 emitir(IRTI(IR_XSTORE
), trhi
, lj_ir_kint(J
, LJ_TCDATA
));
740 lj_trace_err(J
, LJ_TRERR_BADTYPE
);
747 /* Record argument conversions. */
748 static TRef
crec_call_args(jit_State
*J
, RecordFFData
*rd
,
749 CTState
*cts
, CType
*ct
)
751 TRef args
[CCI_NARGS_MAX
];
758 TRef
*arg0
= NULL
, *arg1
= NULL
;
761 if (ctype_cconv(ct
->info
) == CTCC_THISCALL
)
763 else if (ctype_cconv(ct
->info
) == CTCC_FASTCALL
)
767 /* Skip initial attributes. */
770 CType
*ctf
= ctype_get(cts
, fid
);
771 if (!ctype_isattrib(ctf
->info
)) break;
775 for (n
= 0, base
= J
->base
+1, o
= rd
->argv
+1; *base
; n
++, base
++, o
++) {
779 if (n
>= CCI_NARGS_MAX
)
780 lj_trace_err(J
, LJ_TRERR_NYICALL
);
782 if (fid
) { /* Get argument type from field. */
783 CType
*ctf
= ctype_get(cts
, fid
);
785 lua_assert(ctype_isfield(ctf
->info
));
786 did
= ctype_cid(ctf
->info
);
788 if (!(ct
->info
& CTF_VARARG
))
789 lj_trace_err(J
, LJ_TRERR_NYICALL
); /* Too many arguments. */
790 did
= lj_ccall_ctid_vararg(cts
, o
); /* Infer vararg type. */
792 d
= ctype_raw(cts
, did
);
793 if (!(ctype_isnum(d
->info
) || ctype_isptr(d
->info
) ||
794 ctype_isenum(d
->info
)))
795 lj_trace_err(J
, LJ_TRERR_NYICALL
);
796 tr
= crec_ct_tv(J
, d
, 0, *base
, o
);
797 if (ctype_isinteger_or_bool(d
->info
)) {
799 if ((d
->info
& CTF_UNSIGNED
))
800 tr
= emitconv(tr
, IRT_INT
, d
->size
==1 ? IRT_U8
: IRT_U16
, 0);
802 tr
= emitconv(tr
, IRT_INT
, d
->size
==1 ? IRT_I8
: IRT_I16
,IRCONV_SEXT
);
804 } else if (LJ_SOFTFP
&& ctype_isfp(d
->info
) && d
->size
> 4) {
808 /* 64 bit args must not end up in registers for fastcall/thiscall. */
810 if (!ctype_isfp(d
->info
)) {
811 /* Sigh, the Windows/x86 ABI allows reordering across 64 bit args. */
812 if (tref_typerange(tr
, IRT_I64
, IRT_U64
)) {
814 arg0
= &args
[n
]; args
[n
++] = TREF_NIL
; ngpr
--;
816 arg1
= &args
[n
]; args
[n
++] = TREF_NIL
; ngpr
--;
820 if (arg0
) { *arg0
= tr
; arg0
= NULL
; n
--; continue; }
821 if (arg1
) { *arg1
= tr
; arg1
= NULL
; n
--; continue; }
826 if (!ctype_isfp(d
->info
) && ngpr
) {
827 if (tref_typerange(tr
, IRT_I64
, IRT_U64
)) {
828 /* No reordering for other x86 ABIs. Simply add alignment args. */
829 do { args
[n
++] = TREF_NIL
; } while (--ngpr
);
839 for (i
= 1; i
< n
; i
++)
840 tr
= emitir(IRT(IR_CARG
, IRT_NIL
), tr
, args
[i
]);
844 /* Create a snapshot for the caller, simulating a 'false' return value. */
845 static void crec_snap_caller(jit_State
*J
)
848 TValue
*base
= L
->base
, *top
= L
->top
;
849 const BCIns
*pc
= J
->pc
;
850 TRef ftr
= J
->base
[-1];
852 if (!frame_islua(base
-1))
853 lj_trace_err(J
, LJ_TRERR_NYICALL
);
854 J
->pc
= frame_pc(base
-1); delta
= 1+bc_a(J
->pc
[-1]);
855 L
->top
= base
; L
->base
= base
- delta
;
856 J
->base
[-1] = TREF_FALSE
;
857 J
->base
-= delta
; J
->baseslot
-= (BCReg
)delta
;
858 J
->maxslot
= (BCReg
)delta
; J
->framedepth
--;
860 L
->base
= base
; L
->top
= top
;
861 J
->framedepth
++; J
->maxslot
= 1;
862 J
->base
+= delta
; J
->baseslot
+= (BCReg
)delta
;
863 J
->base
[-1] = ftr
; J
->pc
= pc
;
866 /* Record function call. */
867 static int crec_call(jit_State
*J
, RecordFFData
*rd
, GCcdata
*cd
)
869 CTState
*cts
= ctype_ctsG(J2G(J
));
870 CType
*ct
= ctype_raw(cts
, cd
->ctypeid
);
872 if (ctype_isptr(ct
->info
)) {
873 tp
= (LJ_64
&& ct
->size
== 8) ? IRT_P64
: IRT_P32
;
874 ct
= ctype_rawchild(cts
, ct
);
876 if (ctype_isfunc(ct
->info
)) {
877 TRef func
= emitir(IRT(IR_FLOAD
, tp
), J
->base
[0], IRFL_CDATA_PTR
);
878 CType
*ctr
= ctype_rawchild(cts
, ct
);
879 IRType t
= crec_ct2irt(cts
, ctr
);
882 /* Check for blacklisted C functions that might call a callback. */
884 cdata_getptr(cdataptr(cd
), (LJ_64
&& tp
== IRT_P64
) ? 8 : 4));
885 if (tvistrue(lj_tab_get(J
->L
, cts
->miscmap
, &tv
)))
886 lj_trace_err(J
, LJ_TRERR_BLACKL
);
887 if (ctype_isvoid(ctr
->info
)) {
890 } else if (!(ctype_isnum(ctr
->info
) || ctype_isptr(ctr
->info
) ||
891 ctype_isenum(ctr
->info
)) || t
== IRT_CDATA
) {
892 lj_trace_err(J
, LJ_TRERR_NYICALL
);
894 if ((ct
->info
& CTF_VARARG
)
896 || ctype_cconv(ct
->info
) != CTCC_CDECL
899 func
= emitir(IRT(IR_CARG
, IRT_NIL
), func
,
900 lj_ir_kint(J
, ctype_typeid(cts
, ct
)));
901 tr
= emitir(IRT(IR_CALLXS
, t
), crec_call_args(J
, rd
, cts
, ct
), func
);
902 if (ctype_isbool(ctr
->info
)) {
903 if (frame_islua(J
->L
->base
-1) && bc_b(frame_pc(J
->L
->base
-1)[-1]) == 1) {
904 /* Don't check result if ignored. */
908 lj_ir_set(J
, IRTGI(IR_NE
), tr
, lj_ir_kint(J
, 0));
909 J
->postproc
= LJ_POST_FIXGUARDSNAP
;
912 } else if (t
== IRT_PTR
|| (LJ_64
&& t
== IRT_P32
) ||
913 t
== IRT_I64
|| t
== IRT_U64
|| ctype_isenum(ctr
->info
)) {
914 TRef trid
= lj_ir_kint(J
, ctype_cid(ct
->info
));
915 tr
= emitir(IRTG(IR_CNEWI
, IRT_CDATA
), trid
, tr
);
916 if (t
== IRT_I64
|| t
== IRT_U64
) lj_needsplit(J
);
917 } else if (t
== IRT_FLOAT
|| t
== IRT_U32
) {
918 tr
= emitconv(tr
, IRT_NUM
, t
, 0);
919 } else if (t
== IRT_I8
|| t
== IRT_I16
) {
920 tr
= emitconv(tr
, IRT_INT
, t
, IRCONV_SEXT
);
921 } else if (t
== IRT_U8
|| t
== IRT_U16
) {
922 tr
= emitconv(tr
, IRT_INT
, t
, 0);
931 void LJ_FASTCALL
recff_cdata_call(jit_State
*J
, RecordFFData
*rd
)
933 CTState
*cts
= ctype_ctsG(J2G(J
));
934 GCcdata
*cd
= argv2cdata(J
, J
->base
[0], &rd
->argv
[0]);
935 CTypeID id
= cd
->ctypeid
;
939 if (id
== CTID_CTYPEID
) {
940 id
= crec_constructor(J
, cd
, J
->base
[0]);
942 } else if (crec_call(J
, rd
, cd
)) {
945 /* Record ctype __call/__new metamethod. */
946 ct
= ctype_raw(cts
, id
);
947 if (ctype_isptr(ct
->info
)) id
= ctype_cid(ct
->info
);
948 tv
= lj_ctype_meta(cts
, id
, mm
);
951 J
->base
[-1] = lj_ir_kfunc(J
, funcV(tv
)) | TREF_FRAME
;
952 rd
->nres
= -1; /* Pending tailcall. */
955 } else if (mm
== MM_new
) {
956 crec_alloc(J
, rd
, id
);
959 /* No metamethod or NYI: non-function metamethods. */
960 lj_trace_err(J
, LJ_TRERR_BADTYPE
);
963 static TRef
crec_arith_int64(jit_State
*J
, TRef
*sp
, CType
**s
, MMS mm
)
965 if (ctype_isnum(s
[0]->info
) && ctype_isnum(s
[1]->info
)) {
972 if (((s
[0]->info
& CTF_UNSIGNED
) && s
[0]->size
== 8) ||
973 ((s
[1]->info
& CTF_UNSIGNED
) && s
[1]->size
== 8)) {
974 dt
= IRT_U64
; id
= CTID_UINT64
;
976 dt
= IRT_I64
; id
= CTID_INT64
;
978 !((s
[0]->info
| s
[1]->info
) & CTF_FP
) &&
979 s
[0]->size
== 4 && s
[1]->size
== 4) { /* Try to narrow comparison. */
980 if (!((s
[0]->info
^ s
[1]->info
) & CTF_UNSIGNED
) ||
981 (tref_isk(sp
[1]) && IR(tref_ref(sp
[1]))->i
>= 0)) {
982 dt
= (s
[0]->info
& CTF_UNSIGNED
) ? IRT_U32
: IRT_INT
;
984 } else if (tref_isk(sp
[0]) && IR(tref_ref(sp
[0]))->i
>= 0) {
985 dt
= (s
[1]->info
& CTF_UNSIGNED
) ? IRT_U32
: IRT_INT
;
990 for (i
= 0; i
< 2; i
++) {
991 IRType st
= tref_type(sp
[i
]);
992 if (st
== IRT_NUM
|| st
== IRT_FLOAT
)
993 sp
[i
] = emitconv(sp
[i
], dt
, st
, IRCONV_TRUNC
|IRCONV_ANY
);
994 else if (!(st
== IRT_I64
|| st
== IRT_U64
))
995 sp
[i
] = emitconv(sp
[i
], dt
, IRT_INT
,
996 (s
[i
]->info
& CTF_UNSIGNED
) ? 0 : IRCONV_SEXT
);
1000 /* Assume true comparison. Fixup and emit pending guard later. */
1004 op
= mm
== MM_lt
? IR_LT
: IR_LE
;
1005 if (dt
== IRT_U32
|| dt
== IRT_U64
)
1006 op
+= (IR_ULT
-IR_LT
);
1008 lj_ir_set(J
, IRTG(op
, dt
), sp
[0], sp
[1]);
1009 J
->postproc
= LJ_POST_FIXGUARD
;
1012 tr
= emitir(IRT(mm
+(int)IR_ADD
-(int)MM_add
, dt
), sp
[0], sp
[1]);
1014 return emitir(IRTG(IR_CNEWI
, IRT_CDATA
), lj_ir_kint(J
, id
), tr
);
1019 static TRef
crec_arith_ptr(jit_State
*J
, TRef
*sp
, CType
**s
, MMS mm
)
1021 CTState
*cts
= ctype_ctsG(J2G(J
));
1023 if (ctype_isptr(ctp
->info
) || ctype_isrefarray(ctp
->info
)) {
1024 if ((mm
== MM_sub
|| mm
== MM_eq
|| mm
== MM_lt
|| mm
== MM_le
) &&
1025 (ctype_isptr(s
[1]->info
) || ctype_isrefarray(s
[1]->info
))) {
1026 if (mm
== MM_sub
) { /* Pointer difference. */
1028 CTSize sz
= lj_ctype_size(cts
, ctype_cid(ctp
->info
));
1029 if (sz
== 0 || (sz
& (sz
-1)) != 0)
1030 return 0; /* NYI: integer division. */
1031 tr
= emitir(IRT(IR_SUB
, IRT_INTP
), sp
[0], sp
[1]);
1032 tr
= emitir(IRT(IR_BSAR
, IRT_INTP
), tr
, lj_ir_kint(J
, lj_fls(sz
)));
1034 tr
= emitconv(tr
, IRT_NUM
, IRT_INTP
, 0);
1037 } else { /* Pointer comparison (unsigned). */
1038 /* Assume true comparison. Fixup and emit pending guard later. */
1039 IROp op
= mm
== MM_eq
? IR_EQ
: mm
== MM_lt
? IR_ULT
: IR_ULE
;
1040 lj_ir_set(J
, IRTG(op
, IRT_PTR
), sp
[0], sp
[1]);
1041 J
->postproc
= LJ_POST_FIXGUARD
;
1045 if (!((mm
== MM_add
|| mm
== MM_sub
) && ctype_isnum(s
[1]->info
)))
1047 } else if (mm
== MM_add
&& ctype_isnum(ctp
->info
) &&
1048 (ctype_isptr(s
[1]->info
) || ctype_isrefarray(s
[1]->info
))) {
1049 TRef tr
= sp
[0]; sp
[0] = sp
[1]; sp
[1] = tr
; /* Swap pointer and index. */
1056 IRType t
= tref_type(tr
);
1057 CTSize sz
= lj_ctype_size(cts
, ctype_cid(ctp
->info
));
1060 if (t
== IRT_NUM
|| t
== IRT_FLOAT
)
1061 tr
= emitconv(tr
, IRT_INTP
, t
, IRCONV_TRUNC
|IRCONV_ANY
);
1062 else if (!(t
== IRT_I64
|| t
== IRT_U64
))
1063 tr
= emitconv(tr
, IRT_INTP
, IRT_INT
,
1064 ((t
- IRT_I8
) & 1) ? 0 : IRCONV_SEXT
);
1066 if (!tref_typerange(sp
[1], IRT_I8
, IRT_U32
)) {
1067 tr
= emitconv(tr
, IRT_INTP
, t
,
1068 (t
== IRT_NUM
|| t
== IRT_FLOAT
) ?
1069 IRCONV_TRUNC
|IRCONV_ANY
: 0);
1072 tr
= emitir(IRT(IR_MUL
, IRT_INTP
), tr
, lj_ir_kintp(J
, sz
));
1073 tr
= emitir(IRT(mm
+(int)IR_ADD
-(int)MM_add
, IRT_PTR
), sp
[0], tr
);
1074 id
= lj_ctype_intern(cts
, CTINFO(CT_PTR
, CTALIGN_PTR
|ctype_cid(ctp
->info
)),
1076 return emitir(IRTG(IR_CNEWI
, IRT_CDATA
), lj_ir_kint(J
, id
), tr
);
1080 /* Record ctype arithmetic metamethods. */
1081 static void crec_arith_meta(jit_State
*J
, CTState
*cts
, RecordFFData
*rd
)
1085 if (tviscdata(&rd
->argv
[0]))
1086 tv
= lj_ctype_meta(cts
, argv2cdata(J
, J
->base
[0], &rd
->argv
[0])->ctypeid
,
1088 if (!tv
&& J
->base
[1] && tviscdata(&rd
->argv
[1]))
1089 tv
= lj_ctype_meta(cts
, argv2cdata(J
, J
->base
[1], &rd
->argv
[1])->ctypeid
,
1094 J
->base
[-1] = lj_ir_kfunc(J
, funcV(tv
)) | TREF_FRAME
;
1095 rd
->nres
= -1; /* Pending tailcall. */
1097 } /* NYI: non-function metamethods. */
1098 } else if ((MMS
)rd
->data
== MM_eq
) {
1099 J
->base
[0] = TREF_FALSE
;
1102 lj_trace_err(J
, LJ_TRERR_BADTYPE
);
1105 void LJ_FASTCALL
recff_cdata_arith(jit_State
*J
, RecordFFData
*rd
)
1107 CTState
*cts
= ctype_ctsG(J2G(J
));
1111 for (i
= 0; i
< 2; i
++) {
1112 TRef tr
= J
->base
[i
];
1113 CType
*ct
= ctype_get(cts
, CTID_DOUBLE
);
1116 } else if (tref_iscdata(tr
)) {
1117 CTypeID id
= argv2cdata(J
, tr
, &rd
->argv
[i
])->ctypeid
;
1119 ct
= ctype_raw(cts
, id
);
1120 t
= crec_ct2irt(cts
, ct
);
1121 if (ctype_isptr(ct
->info
)) { /* Resolve pointer or reference. */
1122 tr
= emitir(IRT(IR_FLOAD
, t
), tr
, IRFL_CDATA_PTR
);
1123 if (ctype_isref(ct
->info
)) {
1124 ct
= ctype_rawchild(cts
, ct
);
1125 t
= crec_ct2irt(cts
, ct
);
1127 } else if (t
== IRT_I64
|| t
== IRT_U64
) {
1128 tr
= emitir(IRT(IR_FLOAD
, t
), tr
, IRFL_CDATA_INT64
);
1131 } else if (t
== IRT_INT
|| t
== IRT_U32
) {
1132 tr
= emitir(IRT(IR_FLOAD
, t
), tr
, IRFL_CDATA_INT
);
1133 if (ctype_isenum(ct
->info
)) ct
= ctype_child(cts
, ct
);
1135 } else if (ctype_isfunc(ct
->info
)) {
1136 tr
= emitir(IRT(IR_FLOAD
, IRT_PTR
), tr
, IRFL_CDATA_PTR
);
1138 lj_ctype_intern(cts
, CTINFO(CT_PTR
, CTALIGN_PTR
|id
), CTSIZE_PTR
));
1141 tr
= emitir(IRT(IR_ADD
, IRT_PTR
), tr
, lj_ir_kintp(J
, sizeof(GCcdata
)));
1143 if (ctype_isenum(ct
->info
)) ct
= ctype_child(cts
, ct
);
1144 if (ctype_isnum(ct
->info
)) {
1145 if (t
== IRT_CDATA
) goto trymeta
;
1146 if (t
== IRT_I64
|| t
== IRT_U64
) lj_needsplit(J
);
1147 tr
= emitir(IRT(IR_XLOAD
, t
), tr
, 0);
1148 } else if (!(ctype_isptr(ct
->info
) || ctype_isrefarray(ct
->info
))) {
1151 } else if (tref_isnil(tr
)) {
1152 tr
= lj_ir_kptr(J
, NULL
);
1153 ct
= ctype_get(cts
, CTID_P_VOID
);
1154 } else if (tref_isinteger(tr
)) {
1155 ct
= ctype_get(cts
, CTID_INT32
);
1156 } else if (tref_isstr(tr
)) {
1157 TRef tr2
= J
->base
[1-i
];
1158 CTypeID id
= argv2cdata(J
, tr2
, &rd
->argv
[1-i
])->ctypeid
;
1159 ct
= ctype_raw(cts
, id
);
1160 if (ctype_isenum(ct
->info
)) { /* Match string against enum constant. */
1161 GCstr
*str
= strV(&rd
->argv
[i
]);
1163 CType
*cct
= lj_ctype_getfield(cts
, ct
, str
, &ofs
);
1164 if (cct
&& ctype_isconstval(cct
->info
)) {
1165 /* Specialize to the name of the enum constant. */
1166 emitir(IRTG(IR_EQ
, IRT_STR
), tr
, lj_ir_kstr(J
, str
));
1167 ct
= ctype_child(cts
, cct
);
1168 tr
= lj_ir_kint(J
, (int32_t)ofs
);
1169 } /* else: interpreter will throw. */
1170 } /* else: interpreter will throw. */
1171 } else if (!tref_isnum(tr
)) {
1180 if ((tr
= crec_arith_int64(J
, sp
, s
, (MMS
)rd
->data
)) ||
1181 (tr
= crec_arith_ptr(J
, sp
, s
, (MMS
)rd
->data
))) {
1183 /* Fixup cdata comparisons, too. Avoids some cdata escapes. */
1184 if (J
->postproc
== LJ_POST_FIXGUARD
&& frame_iscont(J
->L
->base
-1) &&
1185 !irt_isguard(J
->guardemit
)) {
1186 const BCIns
*pc
= frame_contpc(J
->L
->base
-1) - 1;
1187 if (bc_op(*pc
) <= BC_ISNEP
) {
1188 setframe_pc(&J2G(J
)->tmptv
, pc
);
1189 J2G(J
)->tmptv
.u32
.lo
= ((tref_istrue(tr
) ^ bc_op(*pc
)) & 1);
1190 J
->postproc
= LJ_POST_FIXCOMP
;
1195 crec_arith_meta(J
, cts
, rd
);
1200 /* -- C library namespace metamethods ------------------------------------- */
1202 void LJ_FASTCALL
recff_clib_index(jit_State
*J
, RecordFFData
*rd
)
1204 CTState
*cts
= ctype_ctsG(J2G(J
));
1205 if (tref_isudata(J
->base
[0]) && tref_isstr(J
->base
[1]) &&
1206 udataV(&rd
->argv
[0])->udtype
== UDTYPE_FFI_CLIB
) {
1207 CLibrary
*cl
= (CLibrary
*)uddata(udataV(&rd
->argv
[0]));
1208 GCstr
*name
= strV(&rd
->argv
[1]);
1210 CTypeID id
= lj_ctype_getname(cts
, &ct
, name
, CLNS_INDEX
);
1211 cTValue
*tv
= lj_tab_getstr(cl
->cache
, name
);
1212 rd
->nres
= rd
->data
;
1213 if (id
&& tv
&& !tvisnil(tv
)) {
1214 /* Specialize to the symbol name and make the result a constant. */
1215 emitir(IRTG(IR_EQ
, IRT_STR
), J
->base
[1], lj_ir_kstr(J
, name
));
1216 if (ctype_isconstval(ct
->info
)) {
1217 if (ct
->size
>= 0x80000000u
&&
1218 (ctype_child(cts
, ct
)->info
& CTF_UNSIGNED
))
1219 J
->base
[0] = lj_ir_knum(J
, (lua_Number
)(uint32_t)ct
->size
);
1221 J
->base
[0] = lj_ir_kint(J
, (int32_t)ct
->size
);
1222 } else if (ctype_isextern(ct
->info
)) {
1223 CTypeID sid
= ctype_cid(ct
->info
);
1224 void *sp
= *(void **)cdataptr(cdataV(tv
));
1226 ct
= ctype_raw(cts
, sid
);
1227 if (LJ_64
&& !checkptr32(sp
))
1228 ptr
= lj_ir_kintp(J
, (uintptr_t)sp
);
1230 ptr
= lj_ir_kptr(J
, sp
);
1232 J
->base
[0] = crec_tv_ct(J
, ct
, sid
, ptr
);
1235 crec_ct_tv(J
, ct
, ptr
, J
->base
[2], &rd
->argv
[2]);
1238 J
->base
[0] = lj_ir_kgc(J
, obj2gco(cdataV(tv
)), IRT_CDATA
);
1241 lj_trace_err(J
, LJ_TRERR_NOCACHE
);
1243 } /* else: interpreter will throw. */
1246 /* -- FFI library functions ----------------------------------------------- */
1248 static TRef
crec_toint(jit_State
*J
, CTState
*cts
, TRef sp
, TValue
*sval
)
1250 return crec_ct_tv(J
, ctype_get(cts
, CTID_INT32
), 0, sp
, sval
);
1253 void LJ_FASTCALL
recff_ffi_new(jit_State
*J
, RecordFFData
*rd
)
1255 crec_alloc(J
, rd
, argv2ctype(J
, J
->base
[0], &rd
->argv
[0]));
1258 void LJ_FASTCALL
recff_ffi_errno(jit_State
*J
, RecordFFData
*rd
)
1262 lj_trace_err(J
, LJ_TRERR_NYICALL
);
1263 J
->base
[0] = lj_ir_call(J
, IRCALL_lj_vm_errno
);
1266 void LJ_FASTCALL
recff_ffi_string(jit_State
*J
, RecordFFData
*rd
)
1268 CTState
*cts
= ctype_ctsG(J2G(J
));
1269 TRef tr
= J
->base
[0];
1271 TRef trlen
= J
->base
[1];
1273 trlen
= crec_toint(J
, cts
, trlen
, &rd
->argv
[1]);
1274 tr
= crec_ct_tv(J
, ctype_get(cts
, CTID_P_CVOID
), 0, tr
, &rd
->argv
[0]);
1276 tr
= crec_ct_tv(J
, ctype_get(cts
, CTID_P_CCHAR
), 0, tr
, &rd
->argv
[0]);
1277 trlen
= lj_ir_call(J
, IRCALL_strlen
, tr
);
1279 J
->base
[0] = emitir(IRT(IR_XSNEW
, IRT_STR
), tr
, trlen
);
1280 } /* else: interpreter will throw. */
1283 void LJ_FASTCALL
recff_ffi_copy(jit_State
*J
, RecordFFData
*rd
)
1285 CTState
*cts
= ctype_ctsG(J2G(J
));
1286 TRef trdst
= J
->base
[0], trsrc
= J
->base
[1], trlen
= J
->base
[2];
1287 if (trdst
&& trsrc
&& (trlen
|| tref_isstr(trsrc
))) {
1288 trdst
= crec_ct_tv(J
, ctype_get(cts
, CTID_P_VOID
), 0, trdst
, &rd
->argv
[0]);
1289 trsrc
= crec_ct_tv(J
, ctype_get(cts
, CTID_P_CVOID
), 0, trsrc
, &rd
->argv
[1]);
1291 trlen
= crec_toint(J
, cts
, trlen
, &rd
->argv
[2]);
1293 trlen
= emitir(IRTI(IR_FLOAD
), J
->base
[1], IRFL_STR_LEN
);
1294 trlen
= emitir(IRTI(IR_ADD
), trlen
, lj_ir_kint(J
, 1));
1296 lj_ir_call(J
, IRCALL_memcpy
, trdst
, trsrc
, trlen
);
1297 emitir(IRT(IR_XBAR
, IRT_NIL
), 0, 0);
1299 } /* else: interpreter will throw. */
1302 void LJ_FASTCALL
recff_ffi_fill(jit_State
*J
, RecordFFData
*rd
)
1304 CTState
*cts
= ctype_ctsG(J2G(J
));
1305 TRef tr
= J
->base
[0], trlen
= J
->base
[1], trfill
= J
->base
[2];
1307 tr
= crec_ct_tv(J
, ctype_get(cts
, CTID_P_VOID
), 0, tr
, &rd
->argv
[0]);
1308 trlen
= crec_toint(J
, cts
, trlen
, &rd
->argv
[1]);
1310 trfill
= crec_toint(J
, cts
, trfill
, &rd
->argv
[2]);
1312 trfill
= lj_ir_kint(J
, 0);
1313 lj_ir_call(J
, IRCALL_memset
, tr
, trfill
, trlen
);
1314 emitir(IRT(IR_XBAR
, IRT_NIL
), 0, 0);
1316 } /* else: interpreter will throw. */
1319 void LJ_FASTCALL
recff_ffi_typeof(jit_State
*J
, RecordFFData
*rd
)
1321 if (tref_iscdata(J
->base
[0])) {
1322 TRef trid
= lj_ir_kint(J
, argv2ctype(J
, J
->base
[0], &rd
->argv
[0]));
1323 J
->base
[0] = emitir(IRTG(IR_CNEWI
, IRT_CDATA
),
1324 lj_ir_kint(J
, CTID_CTYPEID
), trid
);
1326 setfuncV(J
->L
, &J
->errinfo
, J
->fn
);
1327 lj_trace_err_info(J
, LJ_TRERR_NYIFFU
);
1331 void LJ_FASTCALL
recff_ffi_istype(jit_State
*J
, RecordFFData
*rd
)
1333 argv2ctype(J
, J
->base
[0], &rd
->argv
[0]);
1334 if (tref_iscdata(J
->base
[1])) {
1335 argv2ctype(J
, J
->base
[1], &rd
->argv
[1]);
1336 J
->postproc
= LJ_POST_FIXBOOL
;
1337 J
->base
[0] = TREF_TRUE
;
1339 J
->base
[0] = TREF_FALSE
;
1343 void LJ_FASTCALL
recff_ffi_abi(jit_State
*J
, RecordFFData
*rd
)
1345 if (tref_isstr(J
->base
[0])) {
1346 /* Specialize to the ABI string to make the boolean result a constant. */
1347 emitir(IRTG(IR_EQ
, IRT_STR
), J
->base
[0], lj_ir_kstr(J
, strV(&rd
->argv
[0])));
1348 J
->postproc
= LJ_POST_FIXBOOL
;
1349 J
->base
[0] = TREF_TRUE
;
1350 } /* else: interpreter will throw. */
1353 /* -- Miscellaneous library functions ------------------------------------- */
1355 void LJ_FASTCALL
lj_crecord_tonumber(jit_State
*J
, RecordFFData
*rd
)
1357 CTState
*cts
= ctype_ctsG(J2G(J
));
1358 CType
*d
, *ct
= lj_ctype_rawref(cts
, cdataV(&rd
->argv
[0])->ctypeid
);
1359 if (ctype_isenum(ct
->info
)) ct
= ctype_child(cts
, ct
);
1360 if (ctype_isnum(ct
->info
) || ctype_iscomplex(ct
->info
)) {
1361 if (ctype_isinteger_or_bool(ct
->info
) && ct
->size
<= 4 &&
1362 !(ct
->size
== 4 && (ct
->info
& CTF_UNSIGNED
)))
1363 d
= ctype_get(cts
, CTID_INT32
);
1365 d
= ctype_get(cts
, CTID_DOUBLE
);
1366 J
->base
[0] = crec_ct_tv(J
, d
, 0, J
->base
[0], &rd
->argv
[0]);
1368 J
->base
[0] = TREF_NIL
;