2 ** Trace recorder for C data operations.
3 ** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h
11 #if LJ_HASJIT && LJ_HASFFI
18 #include "lj_cparse.h"
23 #include "lj_ircall.h"
26 #include "lj_record.h"
27 #include "lj_ffrecord.h"
28 #include "lj_crecord.h"
29 #include "lj_dispatch.h"
31 /* Some local macros to save typing. Undef'd at the end. */
32 #define IR(ref) (&J->cur.ir[(ref)])
34 /* Pass IR on to next optimization in chain (FOLD). */
35 #define emitir(ot, a, b) (lj_ir_set(J, (ot), (a), (b)), lj_opt_fold(J))
37 #define emitconv(a, dt, st, flags) \
38 emitir(IRT(IR_CONV, (dt)), (a), (st)|((dt) << 5)|(flags))
40 /* -- C type checks ------------------------------------------------------- */
42 static GCcdata
*argv2cdata(jit_State
*J
, TRef tr
, cTValue
*o
)
46 if (!tref_iscdata(tr
))
47 lj_trace_err(J
, LJ_TRERR_BADTYPE
);
49 /* Specialize to the CTypeID. */
50 trtypeid
= emitir(IRT(IR_FLOAD
, IRT_U16
), tr
, IRFL_CDATA_TYPEID
);
51 emitir(IRTG(IR_EQ
, IRT_INT
), trtypeid
, lj_ir_kint(J
, (int32_t)cd
->typeid));
55 /* Specialize to the CTypeID held by a cdata constructor. */
56 static CTypeID
crec_constructor(jit_State
*J
, GCcdata
*cd
, TRef tr
)
59 lua_assert(tref_iscdata(tr
) && cd
->typeid == CTID_CTYPEID
);
60 id
= *(CTypeID
*)cdataptr(cd
);
61 tr
= emitir(IRT(IR_ADD
, IRT_PTR
), tr
, lj_ir_kintp(J
, sizeof(GCcdata
)));
62 tr
= emitir(IRT(IR_XLOAD
, IRT_INT
), tr
, 0);
63 emitir(IRTG(IR_EQ
, IRT_INT
), tr
, lj_ir_kint(J
, (int32_t)id
));
67 static CTypeID
argv2ctype(jit_State
*J
, TRef tr
, cTValue
*o
)
73 /* Specialize to the string containing the C type declaration. */
74 emitir(IRTG(IR_EQ
, IRT_STR
), tr
, lj_ir_kstr(J
, s
));
76 cp
.cts
= ctype_ctsG(J2G(J
));
78 cp
.srcname
= strdata(s
);
80 cp
.mode
= CPARSE_MODE_ABSTRACT
|CPARSE_MODE_NOIMPLICIT
;
81 if (lj_cparse(&cp
) || cp
.cts
->top
> oldtop
) /* Avoid new struct defs. */
82 lj_trace_err(J
, LJ_TRERR_BADTYPE
);
85 GCcdata
*cd
= argv2cdata(J
, tr
, o
);
86 return cd
->typeid == CTID_CTYPEID
? crec_constructor(J
, cd
, tr
) :
91 /* -- Convert C type to C type -------------------------------------------- */
94 ** This code mirrors the code in lj_cconv.c. It performs the same steps
95 ** for the trace recorder that lj_cconv.c does for the interpreter.
97 ** One major difference is that we can get away with much fewer checks
98 ** here. E.g. checks for casts, constness or correct types can often be
99 ** omitted, even if they might fail. The interpreter subsequently throws
100 ** an error, which aborts the trace.
102 ** All operations are specialized to their C types, so the on-trace
103 ** outcome must be the same as the outcome in the interpreter. If the
104 ** interpreter doesn't throw an error, then the trace is correct, too.
105 ** Care must be taken not to generate invalid (temporary) IR or to
109 /* Convert CType to IRType. */
110 static IRType
crec_ct2irt(CType
*ct
)
112 if (LJ_LIKELY(ctype_isnum(ct
->info
))) {
113 if ((ct
->info
& CTF_FP
)) {
114 if (ct
->size
== sizeof(double))
116 else if (ct
->size
== sizeof(float))
119 uint32_t b
= lj_fls(ct
->size
);
121 return IRT_I8
+ 2*b
+ ((ct
->info
& CTF_UNSIGNED
) ? 1 : 0);
123 } else if (ctype_isptr(ct
->info
)) {
124 return (LJ_64
&& ct
->size
== 8) ? IRT_P64
: IRT_P32
;
125 } else if (ctype_iscomplex(ct
->info
)) {
126 if (ct
->size
== 2*sizeof(double))
128 else if (ct
->size
== 2*sizeof(float))
134 /* Determine whether a passed number or cdata number is non-zero. */
135 static int crec_isnonzero(CType
*s
, void *p
)
141 if ((s
->info
& CTF_FP
)) {
142 if (s
->size
== sizeof(float))
143 return (*(float *)p
!= 0);
145 return (*(double *)p
!= 0);
148 return (*(uint8_t *)p
!= 0);
149 else if (s
->size
== 2)
150 return (*(uint16_t *)p
!= 0);
151 else if (s
->size
== 4)
152 return (*(uint32_t *)p
!= 0);
154 return (*(uint64_t *)p
!= 0);
158 static TRef
crec_ct_ct(jit_State
*J
, CType
*d
, CType
*s
, TRef dp
, TRef sp
,
161 CTSize dsize
= d
->size
, ssize
= s
->size
;
162 CTInfo dinfo
= d
->info
, sinfo
= s
->info
;
163 IRType dt
= crec_ct2irt(d
);
164 IRType st
= crec_ct2irt(s
);
166 if (ctype_type(dinfo
) > CT_MAYCONVERT
|| ctype_type(sinfo
) > CT_MAYCONVERT
)
170 ** Note: Unlike lj_cconv_ct_ct(), sp holds the _value_ of pointers and
171 ** numbers up to 8 bytes. Otherwise sp holds a pointer.
174 switch (cconv_idx2(dinfo
, sinfo
)) {
175 /* Destination is a bool. */
177 goto xstore
; /* Source operand is already normalized. */
180 if (st
!= IRT_CDATA
) {
181 /* Specialize to the result of a comparison against 0. */
182 TRef zero
= (st
== IRT_NUM
|| st
== IRT_FLOAT
) ? lj_ir_knum(J
, 0) :
183 (st
== IRT_I64
|| st
== IRT_U64
) ? lj_ir_kint64(J
, 0) :
185 int isnz
= crec_isnonzero(s
, svisnz
);
186 emitir(IRTG(isnz
? IR_NE
: IR_EQ
, st
), sp
, zero
);
187 sp
= lj_ir_kint(J
, isnz
);
192 /* Destination is an integer. */
196 if (dt
== IRT_CDATA
|| st
== IRT_CDATA
) goto err_nyi
;
197 /* Extend 32 to 64 bit integer. */
198 if (dsize
== 8 && ssize
< 8 && !(LJ_64
&& (sinfo
& CTF_UNSIGNED
)))
199 sp
= emitconv(sp
, dt
, ssize
< 4 ? IRT_INT
: st
,
200 (sinfo
& CTF_UNSIGNED
) ? 0 : IRCONV_SEXT
);
201 else if (dsize
< 8 && ssize
== 8) /* Truncate from 64 bit integer. */
202 sp
= emitconv(sp
, dsize
< 4 ? IRT_INT
: dt
, st
, 0);
203 else if (st
== IRT_INT
)
204 sp
= lj_opt_narrow_toint(J
, sp
);
206 if (dt
== IRT_I64
|| dt
== IRT_U64
) lj_needsplit(J
);
207 if (dp
== 0) return sp
;
208 emitir(IRT(IR_XSTORE
, dt
), dp
, sp
);
211 sp
= emitir(IRT(IR_XLOAD
, st
), sp
, 0); /* Load re. */
214 if (dt
== IRT_CDATA
|| st
== IRT_CDATA
) goto err_nyi
;
215 sp
= emitconv(sp
, dsize
< 4 ? IRT_INT
: dt
, st
, IRCONV_TRUNC
|IRCONV_ANY
);
219 sinfo
= CTINFO(CT_NUM
, CTF_UNSIGNED
);
224 /* Destination is a floating-point number. */
228 if (dt
== IRT_CDATA
|| st
== IRT_CDATA
) goto err_nyi
;
229 sp
= emitconv(sp
, dt
, ssize
< 4 ? IRT_INT
: st
, 0);
232 sp
= emitir(IRT(IR_XLOAD
, st
), sp
, 0); /* Load re. */
236 if (dt
== IRT_CDATA
|| st
== IRT_CDATA
) goto err_nyi
;
237 if (dt
!= st
) sp
= emitconv(sp
, dt
, st
, 0);
240 /* Destination is a complex number. */
244 TRef ptr
= emitir(IRT(IR_ADD
, IRT_PTR
), dp
, lj_ir_kintp(J
, (dsize
>> 1)));
245 emitir(IRT(IR_XSTORE
, dt
), ptr
, lj_ir_knum(J
, 0));
248 if ((sinfo
& CTF_FP
)) goto conv_F_F
; else goto conv_F_I
;
251 if (dt
== IRT_CDATA
|| st
== IRT_CDATA
) goto err_nyi
;
254 re
= emitir(IRT(IR_XLOAD
, st
), sp
, 0);
255 ptr
= emitir(IRT(IR_ADD
, IRT_PTR
), sp
, lj_ir_kintp(J
, (ssize
>> 1)));
256 im
= emitir(IRT(IR_XLOAD
, st
), ptr
, 0);
258 re
= emitconv(re
, dt
, st
, 0);
259 im
= emitconv(im
, dt
, st
, 0);
261 emitir(IRT(IR_XSTORE
, dt
), dp
, re
);
262 ptr
= emitir(IRT(IR_ADD
, IRT_PTR
), dp
, lj_ir_kintp(J
, (dsize
>> 1)));
263 emitir(IRT(IR_XSTORE
, dt
), ptr
, im
);
267 /* Destination is a vector. */
274 /* Destination is a pointer. */
278 /* There are only 32 bit pointers/addresses on 32 bit machines.
279 ** Also ok on x64, since all 32 bit ops clear the upper part of the reg.
283 if (st
== IRT_CDATA
) goto err_nyi
;
284 if (!LJ_64
&& ssize
== 8) /* Truncate from 64 bit integer. */
285 sp
= emitconv(sp
, IRT_U32
, st
, 0);
288 if (st
== IRT_CDATA
) goto err_nyi
;
289 /* The signed conversion is cheaper. x64 really has 47 bit pointers. */
290 sp
= emitconv(sp
, (LJ_64
&& dsize
== 8) ? IRT_I64
: IRT_U32
,
291 st
, IRCONV_TRUNC
|IRCONV_ANY
);
294 /* Destination is an array. */
298 /* Destination is a struct/union. */
305 lj_trace_err(J
, LJ_TRERR_NYICONV
);
311 /* -- Convert C type to TValue (load) ------------------------------------- */
313 static TRef
crec_tv_ct(jit_State
*J
, CType
*s
, CTypeID sid
, TRef sp
)
315 CTState
*cts
= ctype_ctsG(J2G(J
));
316 CTInfo sinfo
= s
->info
;
317 lua_assert(!ctype_isenum(sinfo
));
318 if (ctype_isnum(sinfo
)) {
319 IRType t
= crec_ct2irt(s
);
322 goto err_nyi
; /* NYI: copyval of >64 bit integers. */
323 tr
= emitir(IRT(IR_XLOAD
, t
), sp
, 0);
324 if (t
== IRT_FLOAT
|| t
== IRT_U32
) { /* Keep uint32_t/float as numbers. */
325 return emitconv(tr
, IRT_NUM
, t
, 0);
326 } else if (t
== IRT_I64
|| t
== IRT_U64
) { /* Box 64 bit integer. */
329 } else if ((sinfo
& CTF_BOOL
)) {
330 /* Assume not equal to zero. Fixup and emit pending guard later. */
331 lj_ir_set(J
, IRTGI(IR_NE
), tr
, lj_ir_kint(J
, 0));
332 J
->postproc
= LJ_POST_FIXGUARD
;
337 } else if (ctype_isptr(sinfo
)) {
338 IRType t
= (LJ_64
&& s
->size
== 8) ? IRT_P64
: IRT_P32
;
339 sp
= emitir(IRT(IR_XLOAD
, t
), sp
, 0);
340 } else if (ctype_isrefarray(sinfo
) || ctype_isstruct(sinfo
)) {
342 sid
= lj_ctype_intern(cts
, CTINFO_REF(sid
), CTSIZE_PTR
); /* Create ref. */
343 } else if (ctype_iscomplex(sinfo
)) { /* Unbox/box complex. */
344 IRType t
= s
->size
== 2*sizeof(double) ? IRT_NUM
: IRT_FLOAT
;
345 ptrdiff_t esz
= (ptrdiff_t)(s
->size
>> 1);
346 TRef ptr
, tr1
, tr2
, dp
;
347 dp
= emitir(IRTG(IR_CNEW
, IRT_CDATA
), lj_ir_kint(J
, sid
), TREF_NIL
);
348 tr1
= emitir(IRT(IR_XLOAD
, t
), sp
, 0);
349 ptr
= emitir(IRT(IR_ADD
, IRT_PTR
), sp
, lj_ir_kintp(J
, esz
));
350 tr2
= emitir(IRT(IR_XLOAD
, t
), ptr
, 0);
351 ptr
= emitir(IRT(IR_ADD
, IRT_PTR
), dp
, lj_ir_kintp(J
, sizeof(GCcdata
)));
352 emitir(IRT(IR_XSTORE
, t
), ptr
, tr1
);
353 ptr
= emitir(IRT(IR_ADD
, IRT_PTR
), dp
, lj_ir_kintp(J
, sizeof(GCcdata
)+esz
));
354 emitir(IRT(IR_XSTORE
, t
), ptr
, tr2
);
357 /* NYI: copyval of vectors. */
359 lj_trace_err(J
, LJ_TRERR_NYICONV
);
361 /* Box pointer, ref or 64 bit integer. */
362 return emitir(IRTG(IR_CNEWI
, IRT_CDATA
), lj_ir_kint(J
, sid
), sp
);
365 /* -- Convert TValue to C type (store) ------------------------------------ */
367 static TRef
crec_ct_tv(jit_State
*J
, CType
*d
, TRef dp
, TRef sp
, TValue
*sval
)
369 CTState
*cts
= ctype_ctsG(J2G(J
));
370 CTypeID sid
= CTID_P_VOID
;
373 if (LJ_LIKELY(tref_isinteger(sp
))) {
375 svisnz
= (void *)(intptr_t)(tvisint(sval
)?(intV(sval
)!=0):!tviszero(sval
));
376 } else if (tref_isnum(sp
)) {
378 svisnz
= (void *)(intptr_t)(tvisint(sval
)?(intV(sval
)!=0):!tviszero(sval
));
379 } else if (tref_isbool(sp
)) {
380 sp
= lj_ir_kint(J
, tref_istrue(sp
) ? 1 : 0);
382 } else if (tref_isnil(sp
)) {
383 sp
= lj_ir_kptr(J
, NULL
);
384 } else if (tref_isudata(sp
)) {
385 sp
= emitir(IRT(IR_ADD
, IRT_P32
), sp
, lj_ir_kint(J
, sizeof(GCudata
)));
386 } else if (tref_isstr(sp
)) {
387 if (ctype_isenum(d
->info
)) { /* Match string against enum constant. */
388 GCstr
*str
= strV(sval
);
390 CType
*cct
= lj_ctype_getfield(cts
, d
, str
, &ofs
);
391 /* Specialize to the name of the enum constant. */
392 emitir(IRTG(IR_EQ
, IRT_STR
), sp
, lj_ir_kstr(J
, str
));
393 if (cct
&& ctype_isconstval(cct
->info
)) {
394 lua_assert(ctype_child(cts
, cct
)->size
== 4);
395 svisnz
= (void *)(intptr_t)(cct
->size
!= 0);
396 sp
= lj_ir_kint(J
, (int32_t)cct
->size
);
397 sid
= ctype_cid(cct
->info
);
398 } /* else: interpreter will throw. */
399 } else if (ctype_isrefarray(d
->info
)) { /* Copy string to array. */
400 lj_trace_err(J
, LJ_TRERR_BADTYPE
); /* NYI */
401 } else { /* Otherwise pass the string data as a const char[]. */
402 sp
= emitir(IRT(IR_STRREF
, IRT_P32
), sp
, lj_ir_kint(J
, 0));
405 } else { /* NYI: tref_istab(sp), tref_islightud(sp). */
406 sid
= argv2cdata(J
, sp
, sval
)->typeid;
407 s
= ctype_raw(cts
, sid
);
408 svisnz
= cdataptr(cdataV(sval
));
409 if (ctype_isptr(s
->info
)) {
410 IRType t
= (LJ_64
&& s
->size
== 8) ? IRT_P64
: IRT_P32
;
411 sp
= emitir(IRT(IR_FLOAD
, t
), sp
, IRFL_CDATA_PTR
);
412 if (ctype_isref(s
->info
)) {
413 svisnz
= *(void **)svisnz
;
414 s
= ctype_rawchild(cts
, s
);
416 goto doconv
; /* The pointer value was loaded, don't load number. */
418 } else if (ctype_isinteger(s
->info
) && s
->size
== 8) {
419 IRType t
= (s
->info
& CTF_UNSIGNED
) ? IRT_U64
: IRT_I64
;
420 sp
= emitir(IRT(IR_FLOAD
, t
), sp
, IRFL_CDATA_INT64
);
424 sp
= emitir(IRT(IR_ADD
, IRT_PTR
), sp
, lj_ir_kintp(J
, sizeof(GCcdata
)));
426 if (ctype_isenum(s
->info
)) s
= ctype_child(cts
, s
);
427 if (ctype_isnum(s
->info
)) { /* Load number value. */
428 IRType t
= crec_ct2irt(s
);
429 if (t
!= IRT_CDATA
) {
430 sp
= emitir(IRT(IR_XLOAD
, t
), sp
, 0);
431 if (t
== IRT_I64
|| t
== IRT_U64
) lj_needsplit(J
);
436 s
= ctype_get(cts
, sid
);
438 if (ctype_isenum(d
->info
)) d
= ctype_child(cts
, d
);
439 return crec_ct_ct(J
, d
, s
, dp
, sp
, svisnz
);
442 /* -- C data metamethods -------------------------------------------------- */
444 /* This would be rather difficult in FOLD, so do it here:
445 ** (base+k)+(idx*sz)+ofs ==> (base+idx*sz)+(ofs+k)
446 ** (base+(idx+k)*sz)+ofs ==> (base+idx*sz)+(ofs+k*sz)
448 static TRef
crec_reassoc_ofs(jit_State
*J
, TRef tr
, ptrdiff_t *ofsp
, MSize sz
)
450 IRIns
*ir
= IR(tref_ref(tr
));
451 if (LJ_LIKELY(J
->flags
& JIT_F_OPT_FOLD
) && irref_isk(ir
->op2
) &&
452 (ir
->o
== IR_ADD
|| ir
->o
== IR_ADDOV
|| ir
->o
== IR_SUBOV
)) {
453 IRIns
*irk
= IR(ir
->op2
);
455 if (LJ_64
&& irk
->o
== IR_KINT64
)
456 k
= (ptrdiff_t)ir_kint64(irk
)->u64
* sz
;
458 k
= (ptrdiff_t)irk
->i
* sz
;
459 if (ir
->o
== IR_SUBOV
) *ofsp
-= k
; else *ofsp
+= k
;
460 tr
= ir
->op1
; /* Not a TRef, but the caller doesn't care. */
465 /* Record ctype __index/__newindex metamethods. */
466 static void crec_index_meta(jit_State
*J
, CTState
*cts
, CType
*ct
,
469 CTypeID id
= ctype_typeid(cts
, ct
);
470 cTValue
*tv
= lj_ctype_meta(cts
, id
, rd
->data
? MM_newindex
: MM_index
);
472 lj_trace_err(J
, LJ_TRERR_BADTYPE
);
474 J
->base
[-1] = lj_ir_kfunc(J
, funcV(tv
)) | TREF_FRAME
;
475 rd
->nres
= -1; /* Pending tailcall. */
476 } else if (rd
->data
== 0 && tvistab(tv
) && tref_isstr(J
->base
[1])) {
477 /* Specialize to result of __index lookup. */
478 cTValue
*o
= lj_tab_get(J
->L
, tabV(tv
), &rd
->argv
[1]);
479 IRType t
= itype2irt(o
);
481 J
->base
[0] = lj_ir_kgc(J
, gcV(o
), t
);
483 J
->base
[0] = lj_ir_kint(J
, intV(o
));
485 J
->base
[0] = lj_ir_knumint(J
, numV(o
));
486 else if (tvisbool(o
))
487 J
->base
[0] = TREF_PRI(t
);
489 lj_trace_err(J
, LJ_TRERR_BADTYPE
);
490 /* Always specialize to the key. */
491 emitir(IRTG(IR_EQ
, IRT_STR
), J
->base
[1], lj_ir_kstr(J
, strV(&rd
->argv
[1])));
493 /* NYI: resolving of non-function metamethods. */
494 /* NYI: non-string keys for __index table. */
495 /* NYI: stores to __newindex table. */
496 lj_trace_err(J
, LJ_TRERR_BADTYPE
);
500 void LJ_FASTCALL
recff_cdata_index(jit_State
*J
, RecordFFData
*rd
)
502 TRef idx
, ptr
= J
->base
[0];
503 ptrdiff_t ofs
= sizeof(GCcdata
);
504 GCcdata
*cd
= argv2cdata(J
, ptr
, &rd
->argv
[0]);
505 CTState
*cts
= ctype_ctsG(J2G(J
));
506 CType
*ct
= ctype_raw(cts
, cd
->typeid);
509 /* Resolve pointer or reference for cdata object. */
510 if (ctype_isptr(ct
->info
)) {
511 IRType t
= (LJ_64
&& ct
->size
== 8) ? IRT_P64
: IRT_P32
;
512 if (ctype_isref(ct
->info
)) ct
= ctype_rawchild(cts
, ct
);
513 ptr
= emitir(IRT(IR_FLOAD
, t
), ptr
, IRFL_CDATA_PTR
);
515 ptr
= crec_reassoc_ofs(J
, ptr
, &ofs
, 1);
520 if (tref_isnumber(idx
)) {
521 idx
= lj_opt_narrow_cindex(J
, idx
);
522 if (ctype_ispointer(ct
->info
)) {
525 if ((ct
->info
& CTF_COMPLEX
))
526 idx
= emitir(IRT(IR_BAND
, IRT_INTP
), idx
, lj_ir_kintp(J
, 1));
527 sz
= lj_ctype_size(cts
, (sid
= ctype_cid(ct
->info
)));
528 idx
= crec_reassoc_ofs(J
, idx
, &ofs
, sz
);
530 /* Hoist base add to allow fusion of shifts into operands. */
531 if (LJ_LIKELY(J
->flags
& JIT_F_OPT_LOOP
) && ofs
&& (sz
== 1 || sz
== 4)) {
532 ptr
= emitir(IRT(IR_ADD
, IRT_PTR
), ptr
, lj_ir_kintp(J
, ofs
));
536 idx
= emitir(IRT(IR_MUL
, IRT_INTP
), idx
, lj_ir_kintp(J
, sz
));
537 ptr
= emitir(IRT(IR_ADD
, IRT_PTR
), idx
, ptr
);
539 } else if (tref_iscdata(idx
)) {
540 GCcdata
*cdk
= cdataV(&rd
->argv
[1]);
541 CType
*ctk
= ctype_raw(cts
, cdk
->typeid);
543 if (ctype_isenum(ctk
->info
)) ctk
= ctype_child(cts
, ctk
);
544 if (ctype_ispointer(ct
->info
) &&
545 ctype_isinteger(ctk
->info
) && (t
= crec_ct2irt(ctk
)) != IRT_CDATA
) {
546 if (ctk
->size
== 8) {
547 idx
= emitir(IRT(IR_FLOAD
, t
), idx
, IRFL_CDATA_INT64
);
549 idx
= emitir(IRT(IR_ADD
, IRT_PTR
), idx
,
550 lj_ir_kintp(J
, sizeof(GCcdata
)));
551 idx
= emitir(IRT(IR_XLOAD
, t
), idx
, 0);
553 if (LJ_64
&& ctk
->size
< sizeof(intptr_t) && !(ctk
->info
& CTF_UNSIGNED
))
554 idx
= emitconv(idx
, IRT_INTP
, IRT_INT
, IRCONV_SEXT
);
555 if (!LJ_64
&& ctk
->size
> sizeof(intptr_t)) {
556 idx
= emitconv(idx
, IRT_INTP
, t
, 0);
561 } else if (tref_isstr(idx
)) {
562 GCstr
*name
= strV(&rd
->argv
[1]);
563 if (cd
->typeid == CTID_CTYPEID
)
564 ct
= ctype_raw(cts
, crec_constructor(J
, cd
, ptr
));
565 if (ctype_isstruct(ct
->info
)) {
568 fct
= lj_ctype_getfield(cts
, ct
, name
, &fofs
);
570 /* Always specialize to the field name. */
571 emitir(IRTG(IR_EQ
, IRT_STR
), idx
, lj_ir_kstr(J
, name
));
572 if (ctype_isconstval(fct
->info
)) {
573 if (fct
->size
>= 0x80000000u
&&
574 (ctype_child(cts
, fct
)->info
& CTF_UNSIGNED
)) {
575 J
->base
[0] = lj_ir_knum(J
, (lua_Number
)(uint32_t)fct
->size
);
578 J
->base
[0] = lj_ir_kint(J
, (int32_t)fct
->size
);
579 return; /* Interpreter will throw for newindex. */
580 } else if (ctype_isbitfield(fct
->info
)) {
581 lj_trace_err(J
, LJ_TRERR_NYICONV
);
583 lua_assert(ctype_isfield(fct
->info
));
584 sid
= ctype_cid(fct
->info
);
586 ofs
+= (ptrdiff_t)fofs
;
588 } else if (ctype_iscomplex(ct
->info
)) {
589 if (name
->len
== 2 &&
590 ((strdata(name
)[0] == 'r' && strdata(name
)[1] == 'e') ||
591 (strdata(name
)[0] == 'i' && strdata(name
)[1] == 'm'))) {
592 /* Always specialize to the field name. */
593 emitir(IRTG(IR_EQ
, IRT_STR
), idx
, lj_ir_kstr(J
, name
));
594 if (strdata(name
)[0] == 'i') ofs
+= (ct
->size
>> 1);
595 sid
= ctype_cid(ct
->info
);
600 if (ctype_isptr(ct
->info
)) { /* Automatically perform '->'. */
601 CType
*cct
= ctype_rawchild(cts
, ct
);
602 if (ctype_isstruct(cct
->info
)) {
604 if (tref_isstr(idx
)) goto again
;
607 crec_index_meta(J
, cts
, ct
, rd
);
612 ptr
= emitir(IRT(IR_ADD
, IRT_PTR
), ptr
, lj_ir_kintp(J
, ofs
));
614 /* Resolve reference for field. */
615 ct
= ctype_get(cts
, sid
);
616 if (ctype_isref(ct
->info
))
617 ptr
= emitir(IRT(IR_XLOAD
, IRT_PTR
), ptr
, 0);
619 while (ctype_isattrib(ct
->info
))
620 ct
= ctype_child(cts
, ct
); /* Skip attributes. */
622 if (rd
->data
== 0) { /* __index metamethod. */
623 if (ctype_isenum(ct
->info
)) ct
= ctype_child(cts
, ct
); /* Skip enums. */
624 J
->base
[0] = crec_tv_ct(J
, ct
, sid
, ptr
);
625 } else { /* __newindex metamethod. */
628 crec_ct_tv(J
, ct
, ptr
, J
->base
[2], &rd
->argv
[2]);
632 /* Record cdata allocation. */
633 static void crec_alloc(jit_State
*J
, RecordFFData
*rd
, CTypeID id
)
635 CTState
*cts
= ctype_ctsG(J2G(J
));
637 CTInfo info
= lj_ctype_info(cts
, id
, &sz
);
638 CType
*d
= ctype_raw(cts
, id
);
640 if (sz
== 0 || sz
> 64 || (info
& CTF_VLA
) || ctype_align(info
) > CT_MEMALIGN
)
641 lj_trace_err(J
, LJ_TRERR_NYICONV
); /* NYI: large/special allocations. */
642 trid
= lj_ir_kint(J
, id
);
643 /* Use special instruction to box pointer or 64 bit integer. */
644 if (ctype_isptr(info
) || (ctype_isinteger(info
) && sz
== 8)) {
645 TRef sp
= J
->base
[1] ? crec_ct_tv(J
, d
, 0, J
->base
[1], &rd
->argv
[1]) :
646 ctype_isptr(info
) ? lj_ir_kptr(J
, NULL
) :
647 (lj_needsplit(J
), lj_ir_kint64(J
, 0));
648 J
->base
[0] = emitir(IRTG(IR_CNEWI
, IRT_CDATA
), trid
, sp
);
650 TRef trcd
= emitir(IRTG(IR_CNEW
, IRT_CDATA
), trid
, TREF_NIL
);
653 if (J
->base
[1] && !J
->base
[2] && !lj_cconv_multi_init(d
, &rd
->argv
[1])) {
655 } else if (ctype_isarray(d
->info
)) {
656 CType
*dc
= ctype_rawchild(cts
, d
); /* Array element type. */
657 CTSize ofs
, esize
= dc
->size
;
663 if (!(ctype_isnum(dc
->info
) || ctype_isptr(dc
->info
)))
664 lj_trace_err(J
, LJ_TRERR_NYICONV
); /* NYI: init array of aggregates. */
665 for (i
= 1, ofs
= 0; ofs
< sz
; ofs
+= esize
) {
666 TRef dp
= emitir(IRT(IR_ADD
, IRT_PTR
), trcd
,
667 lj_ir_kintp(J
, ofs
+ sizeof(GCcdata
)));
673 sp
= ctype_isnum(dc
->info
) ? lj_ir_kint(J
, 0) : TREF_NIL
;
675 crec_ct_tv(J
, dc
, dp
, sp
, sval
);
677 } else if (ctype_isstruct(d
->info
)) {
678 CTypeID fid
= d
->sib
;
681 CType
*df
= ctype_get(cts
, fid
);
683 if (ctype_isfield(df
->info
)) {
689 if (!gcref(df
->name
)) continue; /* Ignore unnamed fields. */
690 dc
= ctype_rawchild(cts
, df
); /* Field type. */
691 if (!(ctype_isnum(dc
->info
) || ctype_isptr(dc
->info
)))
692 lj_trace_err(J
, LJ_TRERR_NYICONV
); /* NYI: init aggregates. */
698 sp
= ctype_isnum(dc
->info
) ? lj_ir_kint(J
, 0) : TREF_NIL
;
700 dp
= emitir(IRT(IR_ADD
, IRT_PTR
), trcd
,
701 lj_ir_kintp(J
, df
->size
+ sizeof(GCcdata
)));
702 crec_ct_tv(J
, dc
, dp
, sp
, sval
);
703 } else if (!ctype_isconstval(df
->info
)) {
704 /* NYI: init bitfields and sub-structures. */
705 lj_trace_err(J
, LJ_TRERR_NYICONV
);
711 dp
= emitir(IRT(IR_ADD
, IRT_PTR
), trcd
, lj_ir_kintp(J
, sizeof(GCcdata
)));
713 crec_ct_tv(J
, d
, dp
, J
->base
[1], &rd
->argv
[1]);
717 crec_ct_tv(J
, d
, dp
, lj_ir_kint(J
, 0), &tv
);
720 /* Handle __gc metamethod. */
721 fin
= lj_ctype_meta(cts
, id
, MM_gc
);
723 TRef trlo
= lj_ir_call(J
, IRCALL_lj_cdata_setfin
, trcd
);
724 TRef trhi
= emitir(IRT(IR_ADD
, IRT_P32
), trlo
, lj_ir_kint(J
, 4));
725 if (LJ_BE
) { TRef tmp
= trlo
; trlo
= trhi
; trhi
= tmp
; }
727 emitir(IRT(IR_XSTORE
, IRT_P32
), trlo
, lj_ir_kfunc(J
, funcV(fin
)));
728 emitir(IRTI(IR_XSTORE
), trhi
, lj_ir_kint(J
, LJ_TFUNC
));
729 } else if (tviscdata(fin
)) {
730 emitir(IRT(IR_XSTORE
, IRT_P32
), trlo
,
731 lj_ir_kgc(J
, obj2gco(cdataV(fin
)), IRT_CDATA
));
732 emitir(IRTI(IR_XSTORE
), trhi
, lj_ir_kint(J
, LJ_TCDATA
));
734 lj_trace_err(J
, LJ_TRERR_BADTYPE
);
741 /* Record argument conversions. */
742 static TRef
crec_call_args(jit_State
*J
, RecordFFData
*rd
,
743 CTState
*cts
, CType
*ct
)
745 TRef args
[CCI_NARGS_MAX
];
749 for (n
= 0; J
->base
[n
+1]; n
++) {
752 if (!ct
->sib
|| n
>= CCI_NARGS_MAX
)
753 lj_trace_err(J
, LJ_TRERR_NYICALL
);
754 ct
= ctype_get(cts
, ct
->sib
);
755 } while (ctype_isattrib(ct
->info
));
756 if (!ctype_isfield(ct
->info
))
757 lj_trace_err(J
, LJ_TRERR_NYICALL
);
758 d
= ctype_rawchild(cts
, ct
);
759 if (!(ctype_isnum(d
->info
) || ctype_isptr(d
->info
) ||
760 ctype_isenum(d
->info
)))
761 lj_trace_err(J
, LJ_TRERR_NYICALL
);
762 tr
= crec_ct_tv(J
, d
, 0, J
->base
[n
+1], &rd
->argv
[n
+1]);
763 if (ctype_isinteger_or_bool(d
->info
) && d
->size
< 4) {
764 if ((d
->info
& CTF_UNSIGNED
))
765 tr
= emitconv(tr
, IRT_INT
, d
->size
==1 ? IRT_U8
: IRT_U16
, 0);
767 tr
= emitconv(tr
, IRT_INT
, d
->size
==1 ? IRT_I8
: IRT_I16
, IRCONV_SEXT
);
772 for (i
= 1; i
< n
; i
++)
773 tr
= emitir(IRT(IR_CARG
, IRT_NIL
), tr
, args
[i
]);
777 /* Record function call. */
778 static int crec_call(jit_State
*J
, RecordFFData
*rd
, GCcdata
*cd
)
780 CTState
*cts
= ctype_ctsG(J2G(J
));
781 CType
*ct
= ctype_raw(cts
, cd
->typeid);
783 if (ctype_isptr(ct
->info
)) {
784 tp
= (LJ_64
&& ct
->size
== 8) ? IRT_P64
: IRT_P32
;
785 ct
= ctype_rawchild(cts
, ct
);
787 if (ctype_isfunc(ct
->info
)) {
788 TRef func
= emitir(IRT(IR_FLOAD
, tp
), J
->base
[0], IRFL_CDATA_PTR
);
789 CType
*ctr
= ctype_rawchild(cts
, ct
);
790 IRType t
= crec_ct2irt(ctr
);
792 if (ctype_isvoid(ctr
->info
)) {
795 } else if (ctype_isenum(ctr
->info
)) {
796 ctr
= ctype_child(cts
, ctr
);
798 if (!(ctype_isnum(ctr
->info
) || ctype_isptr(ctr
->info
) ||
799 ctype_isvoid(ctr
->info
)) ||
800 ctype_isbool(ctr
->info
) || (ct
->info
& CTF_VARARG
) ||
802 ctype_cconv(ct
->info
) != CTCC_CDECL
||
805 lj_trace_err(J
, LJ_TRERR_NYICALL
);
806 tr
= emitir(IRT(IR_CALLXS
, t
), crec_call_args(J
, rd
, cts
, ct
), func
);
807 if (t
== IRT_FLOAT
|| t
== IRT_U32
) {
808 tr
= emitconv(tr
, IRT_NUM
, t
, 0);
809 } else if (t
== IRT_I8
|| t
== IRT_I16
) {
810 tr
= emitconv(tr
, IRT_INT
, t
, IRCONV_SEXT
);
811 } else if (t
== IRT_U8
|| t
== IRT_U16
) {
812 tr
= emitconv(tr
, IRT_INT
, t
, 0);
813 } else if (t
== IRT_PTR
|| (LJ_64
&& t
== IRT_P32
) ||
814 (t
== IRT_I64
|| t
== IRT_U64
)) {
815 TRef trid
= lj_ir_kint(J
, ctype_cid(ct
->info
));
816 tr
= emitir(IRTG(IR_CNEWI
, IRT_CDATA
), trid
, tr
);
817 if (t
== IRT_I64
|| t
== IRT_U64
) lj_needsplit(J
);
826 void LJ_FASTCALL
recff_cdata_call(jit_State
*J
, RecordFFData
*rd
)
828 GCcdata
*cd
= argv2cdata(J
, J
->base
[0], &rd
->argv
[0]);
829 if (cd
->typeid == CTID_CTYPEID
)
830 crec_alloc(J
, rd
, crec_constructor(J
, cd
, J
->base
[0]));
831 else if (!crec_call(J
, rd
, cd
))
832 lj_trace_err(J
, LJ_TRERR_BADTYPE
);
835 static TRef
crec_arith_int64(jit_State
*J
, TRef
*sp
, CType
**s
, MMS mm
)
837 if (ctype_isnum(s
[0]->info
) && ctype_isnum(s
[1]->info
)) {
843 if (((s
[0]->info
& CTF_UNSIGNED
) && s
[0]->size
== 8) ||
844 ((s
[1]->info
& CTF_UNSIGNED
) && s
[1]->size
== 8)) {
845 dt
= IRT_U64
; id
= CTID_UINT64
;
847 dt
= IRT_I64
; id
= CTID_INT64
;
849 for (i
= 0; i
< 2; i
++) {
850 IRType st
= tref_type(sp
[i
]);
851 if (st
== IRT_NUM
|| st
== IRT_FLOAT
)
852 sp
[i
] = emitconv(sp
[i
], dt
, st
, IRCONV_TRUNC
|IRCONV_ANY
);
853 else if (!(st
== IRT_I64
|| st
== IRT_U64
))
854 sp
[i
] = emitconv(sp
[i
], dt
, IRT_INT
,
855 ((st
- IRT_I8
) & 1) ? 0 : IRCONV_SEXT
);
858 /* Assume true comparison. Fixup and emit pending guard later. */
863 op
= mm
== MM_lt
? IR_LT
: IR_LE
;
865 op
+= (IR_ULT
-IR_LT
);
867 lj_ir_set(J
, IRTG(op
, dt
), sp
[0], sp
[1]);
868 J
->postproc
= LJ_POST_FIXGUARD
;
871 tr
= emitir(IRT(mm
+(int)IR_ADD
-(int)MM_add
, dt
), sp
[0], sp
[1]);
873 return emitir(IRTG(IR_CNEWI
, IRT_CDATA
), lj_ir_kint(J
, id
), tr
);
878 static TRef
crec_arith_ptr(jit_State
*J
, TRef
*sp
, CType
**s
, MMS mm
)
880 CTState
*cts
= ctype_ctsG(J2G(J
));
882 if (ctype_isptr(ctp
->info
) || ctype_isrefarray(ctp
->info
)) {
883 if ((mm
== MM_sub
|| mm
== MM_eq
|| mm
== MM_lt
|| mm
== MM_le
) &&
884 (ctype_isptr(s
[1]->info
) || ctype_isrefarray(s
[1]->info
))) {
885 if (mm
== MM_sub
) { /* Pointer difference. */
887 CTSize sz
= lj_ctype_size(cts
, ctype_cid(ctp
->info
));
888 if (sz
== 0 || (sz
& (sz
-1)) != 0)
889 return 0; /* NYI: integer division. */
890 tr
= emitir(IRT(IR_SUB
, IRT_PTR
), sp
[0], sp
[1]);
891 tr
= emitir(IRT(IR_BSAR
, IRT_INTP
), tr
, lj_ir_kint(J
, lj_fls(sz
)));
893 tr
= emitconv(tr
, IRT_NUM
, IRT_INTP
, 0);
896 } else { /* Pointer comparison (unsigned). */
897 /* Assume true comparison. Fixup and emit pending guard later. */
898 IROp op
= mm
== MM_eq
? IR_EQ
: mm
== MM_lt
? IR_ULT
: IR_ULE
;
899 lj_ir_set(J
, IRTG(op
, IRT_PTR
), sp
[0], sp
[1]);
900 J
->postproc
= LJ_POST_FIXGUARD
;
904 if (!((mm
== MM_add
|| mm
== MM_sub
) && ctype_isnum(s
[1]->info
)))
906 } else if (mm
== MM_add
&& ctype_isnum(ctp
->info
) &&
907 (ctype_isptr(s
[1]->info
) || ctype_isrefarray(s
[1]->info
))) {
908 TRef tr
= sp
[0]; sp
[0] = sp
[1]; sp
[1] = tr
; /* Swap pointer and index. */
915 IRType t
= tref_type(tr
);
916 CTSize sz
= lj_ctype_size(cts
, ctype_cid(ctp
->info
));
919 if (t
== IRT_NUM
|| t
== IRT_FLOAT
)
920 tr
= emitconv(tr
, IRT_INTP
, t
, IRCONV_TRUNC
|IRCONV_ANY
);
921 else if (!(t
== IRT_I64
|| t
== IRT_U64
))
922 tr
= emitconv(tr
, IRT_INTP
, IRT_INT
,
923 ((t
- IRT_I8
) & 1) ? 0 : IRCONV_SEXT
);
925 if (!tref_typerange(sp
[1], IRT_I8
, IRT_U32
)) {
926 tr
= emitconv(tr
, IRT_INTP
, t
,
927 (t
== IRT_NUM
|| t
== IRT_FLOAT
) ?
928 IRCONV_TRUNC
|IRCONV_ANY
: 0);
931 tr
= emitir(IRT(IR_MUL
, IRT_INTP
), tr
, lj_ir_kintp(J
, sz
));
932 tr
= emitir(IRT(mm
+(int)IR_ADD
-(int)MM_add
, IRT_PTR
), sp
[0], tr
);
933 id
= lj_ctype_intern(cts
, CTINFO(CT_PTR
, CTALIGN_PTR
|ctype_cid(ctp
->info
)),
935 return emitir(IRTG(IR_CNEWI
, IRT_CDATA
), lj_ir_kint(J
, id
), tr
);
939 /* Record ctype arithmetic metamethods. */
940 static void crec_arith_meta(jit_State
*J
, CTState
*cts
, RecordFFData
*rd
)
944 if (tviscdata(&rd
->argv
[0]))
945 tv
= lj_ctype_meta(cts
, argv2cdata(J
, J
->base
[0], &rd
->argv
[0])->typeid,
947 if (!tv
&& J
->base
[1] && tviscdata(&rd
->argv
[1]))
948 tv
= lj_ctype_meta(cts
, argv2cdata(J
, J
->base
[1], &rd
->argv
[1])->typeid,
951 if (tv
&& tvisfunc(tv
)) {
952 J
->base
[-1] = lj_ir_kfunc(J
, funcV(tv
)) | TREF_FRAME
;
953 rd
->nres
= -1; /* Pending tailcall. */
955 /* NYI: non-function metamethods. */
956 lj_trace_err(J
, LJ_TRERR_BADTYPE
);
960 void LJ_FASTCALL
recff_cdata_arith(jit_State
*J
, RecordFFData
*rd
)
962 CTState
*cts
= ctype_ctsG(J2G(J
));
966 for (i
= 0; i
< 2; i
++) {
967 TRef tr
= J
->base
[i
];
968 CType
*ct
= ctype_get(cts
, CTID_DOUBLE
);
971 } else if (tref_iscdata(tr
)) {
972 CTypeID id
= argv2cdata(J
, tr
, &rd
->argv
[i
])->typeid;
973 ct
= ctype_raw(cts
, id
);
974 if (ctype_isptr(ct
->info
)) { /* Resolve pointer or reference. */
975 IRType t
= (LJ_64
&& ct
->size
== 8) ? IRT_P64
: IRT_P32
;
976 if (ctype_isref(ct
->info
)) ct
= ctype_rawchild(cts
, ct
);
977 tr
= emitir(IRT(IR_FLOAD
, t
), tr
, IRFL_CDATA_PTR
);
978 } else if (ctype_isinteger(ct
->info
) && ct
->size
== 8) {
979 IRType t
= (ct
->info
& CTF_UNSIGNED
) ? IRT_U64
: IRT_I64
;
980 tr
= emitir(IRT(IR_FLOAD
, t
), tr
, IRFL_CDATA_INT64
);
983 } else if (ctype_isfunc(ct
->info
)) {
984 tr
= emitir(IRT(IR_FLOAD
, IRT_PTR
), tr
, IRFL_CDATA_PTR
);
986 lj_ctype_intern(cts
, CTINFO(CT_PTR
, CTALIGN_PTR
|id
), CTSIZE_PTR
));
988 tr
= emitir(IRT(IR_ADD
, IRT_PTR
), tr
, lj_ir_kintp(J
, sizeof(GCcdata
)));
990 if (ctype_isenum(ct
->info
)) ct
= ctype_child(cts
, ct
);
991 if (ctype_isnum(ct
->info
)) {
992 IRType t
= crec_ct2irt(ct
);
993 if (t
== IRT_CDATA
) goto trymeta
;
994 if (t
== IRT_I64
|| t
== IRT_U64
) lj_needsplit(J
);
995 tr
= emitir(IRT(IR_XLOAD
, t
), tr
, 0);
996 } else if (!(ctype_isptr(ct
->info
) || ctype_isrefarray(ct
->info
))) {
999 } else if (tref_isnil(tr
)) {
1000 tr
= lj_ir_kptr(J
, NULL
);
1001 ct
= ctype_get(cts
, CTID_P_VOID
);
1002 } else if (tref_isinteger(tr
)) {
1003 ct
= ctype_get(cts
, CTID_INT32
);
1004 } else if (!tref_isnum(tr
)) {
1013 if ((tr
= crec_arith_int64(J
, sp
, s
, (MMS
)rd
->data
)) ||
1014 (tr
= crec_arith_ptr(J
, sp
, s
, (MMS
)rd
->data
))) {
1016 /* Fixup cdata comparisons, too. Avoids some cdata escapes. */
1017 if (J
->postproc
== LJ_POST_FIXGUARD
&& frame_iscont(J
->L
->base
-1) &&
1018 !irt_isguard(J
->guardemit
)) {
1019 const BCIns
*pc
= frame_contpc(J
->L
->base
-1) - 1;
1020 if (bc_op(*pc
) <= BC_ISNEP
) {
1021 setframe_pc(&J2G(J
)->tmptv
, pc
);
1022 J2G(J
)->tmptv
.u32
.lo
= ((tref_istrue(tr
) ^ bc_op(*pc
)) & 1);
1023 J
->postproc
= LJ_POST_FIXCOMP
;
1028 crec_arith_meta(J
, cts
, rd
);
1033 /* -- C library namespace metamethods ------------------------------------- */
1035 void LJ_FASTCALL
recff_clib_index(jit_State
*J
, RecordFFData
*rd
)
1037 CTState
*cts
= ctype_ctsG(J2G(J
));
1038 if (tref_isudata(J
->base
[0]) && tref_isstr(J
->base
[1]) &&
1039 udataV(&rd
->argv
[0])->udtype
== UDTYPE_FFI_CLIB
) {
1040 CLibrary
*cl
= (CLibrary
*)uddata(udataV(&rd
->argv
[0]));
1041 GCstr
*name
= strV(&rd
->argv
[1]);
1043 CTypeID id
= lj_ctype_getname(cts
, &ct
, name
, CLNS_INDEX
);
1044 cTValue
*tv
= lj_tab_getstr(cl
->cache
, name
);
1045 rd
->nres
= rd
->data
;
1046 if (id
&& tv
&& !tvisnil(tv
)) {
1047 /* Specialize to the symbol name and make the result a constant. */
1048 emitir(IRTG(IR_EQ
, IRT_STR
), J
->base
[1], lj_ir_kstr(J
, name
));
1049 if (ctype_isconstval(ct
->info
)) {
1050 if (ct
->size
>= 0x80000000u
&&
1051 (ctype_child(cts
, ct
)->info
& CTF_UNSIGNED
))
1052 J
->base
[0] = lj_ir_knum(J
, (lua_Number
)(uint32_t)ct
->size
);
1054 J
->base
[0] = lj_ir_kint(J
, (int32_t)ct
->size
);
1055 } else if (ctype_isextern(ct
->info
)) {
1056 CTypeID sid
= ctype_cid(ct
->info
);
1057 void *sp
= *(void **)cdataptr(cdataV(tv
));
1059 ct
= ctype_raw(cts
, sid
);
1060 if (rd
->data
&& ctype_isenum(ct
->info
)) ct
= ctype_child(cts
, ct
);
1061 if (LJ_64
&& !checkptr32(sp
))
1062 ptr
= lj_ir_kintp(J
, (uintptr_t)sp
);
1064 ptr
= lj_ir_kptr(J
, sp
);
1066 J
->base
[0] = crec_tv_ct(J
, ct
, sid
, ptr
);
1069 crec_ct_tv(J
, ct
, ptr
, J
->base
[2], &rd
->argv
[2]);
1072 J
->base
[0] = lj_ir_kgc(J
, obj2gco(cdataV(tv
)), IRT_CDATA
);
1075 lj_trace_err(J
, LJ_TRERR_NOCACHE
);
1077 } /* else: interpreter will throw. */
1080 /* -- FFI library functions ----------------------------------------------- */
1082 static TRef
crec_toint(jit_State
*J
, CTState
*cts
, TRef sp
, TValue
*sval
)
1084 return crec_ct_tv(J
, ctype_get(cts
, CTID_INT32
), 0, sp
, sval
);
1087 void LJ_FASTCALL
recff_ffi_new(jit_State
*J
, RecordFFData
*rd
)
1089 crec_alloc(J
, rd
, argv2ctype(J
, J
->base
[0], &rd
->argv
[0]));
1092 void LJ_FASTCALL
recff_ffi_string(jit_State
*J
, RecordFFData
*rd
)
1094 CTState
*cts
= ctype_ctsG(J2G(J
));
1095 TRef tr
= J
->base
[0];
1097 TRef trlen
= J
->base
[1];
1099 trlen
= crec_toint(J
, cts
, trlen
, &rd
->argv
[1]);
1100 tr
= crec_ct_tv(J
, ctype_get(cts
, CTID_P_CVOID
), 0, tr
, &rd
->argv
[0]);
1102 tr
= crec_ct_tv(J
, ctype_get(cts
, CTID_P_CCHAR
), 0, tr
, &rd
->argv
[0]);
1103 trlen
= lj_ir_call(J
, IRCALL_strlen
, tr
);
1105 J
->base
[0] = emitir(IRT(IR_XSNEW
, IRT_STR
), tr
, trlen
);
1106 } /* else: interpreter will throw. */
1109 void LJ_FASTCALL
recff_ffi_copy(jit_State
*J
, RecordFFData
*rd
)
1111 CTState
*cts
= ctype_ctsG(J2G(J
));
1112 TRef trdst
= J
->base
[0], trsrc
= J
->base
[1], trlen
= J
->base
[2];
1113 if (trdst
&& trsrc
&& (trlen
|| tref_isstr(trsrc
))) {
1114 trdst
= crec_ct_tv(J
, ctype_get(cts
, CTID_P_VOID
), 0, trdst
, &rd
->argv
[0]);
1115 trsrc
= crec_ct_tv(J
, ctype_get(cts
, CTID_P_CVOID
), 0, trsrc
, &rd
->argv
[1]);
1117 trlen
= crec_toint(J
, cts
, trlen
, &rd
->argv
[2]);
1119 trlen
= emitir(IRTI(IR_FLOAD
), J
->base
[1], IRFL_STR_LEN
);
1120 trlen
= emitir(IRTI(IR_ADD
), trlen
, lj_ir_kint(J
, 1));
1122 lj_ir_call(J
, IRCALL_memcpy
, trdst
, trsrc
, trlen
);
1123 emitir(IRT(IR_XBAR
, IRT_NIL
), 0, 0);
1125 } /* else: interpreter will throw. */
1128 void LJ_FASTCALL
recff_ffi_fill(jit_State
*J
, RecordFFData
*rd
)
1130 CTState
*cts
= ctype_ctsG(J2G(J
));
1131 TRef tr
= J
->base
[0], trlen
= J
->base
[1], trfill
= J
->base
[2];
1133 tr
= crec_ct_tv(J
, ctype_get(cts
, CTID_P_VOID
), 0, tr
, &rd
->argv
[0]);
1134 trlen
= crec_toint(J
, cts
, trlen
, &rd
->argv
[1]);
1136 trfill
= crec_toint(J
, cts
, trfill
, &rd
->argv
[2]);
1138 trfill
= lj_ir_kint(J
, 0);
1139 lj_ir_call(J
, IRCALL_memset
, tr
, trfill
, trlen
);
1140 emitir(IRT(IR_XBAR
, IRT_NIL
), 0, 0);
1142 } /* else: interpreter will throw. */
1145 void LJ_FASTCALL
recff_ffi_istype(jit_State
*J
, RecordFFData
*rd
)
1147 argv2ctype(J
, J
->base
[0], &rd
->argv
[0]);
1148 if (tref_iscdata(J
->base
[1])) {
1149 argv2ctype(J
, J
->base
[1], &rd
->argv
[1]);
1150 J
->postproc
= LJ_POST_FIXBOOL
;
1151 J
->base
[0] = TREF_TRUE
;
1153 J
->base
[0] = TREF_FALSE
;
1157 void LJ_FASTCALL
recff_ffi_abi(jit_State
*J
, RecordFFData
*rd
)
1159 if (tref_isstr(J
->base
[0])) {
1160 /* Specialize to the ABI string to make the boolean result a constant. */
1161 emitir(IRTG(IR_EQ
, IRT_STR
), J
->base
[0], lj_ir_kstr(J
, strV(&rd
->argv
[0])));
1162 J
->postproc
= LJ_POST_FIXBOOL
;
1163 J
->base
[0] = TREF_TRUE
;
1164 } /* else: interpreter will throw. */
1167 /* -- Miscellaneous library functions ------------------------------------- */
1169 void LJ_FASTCALL
lj_crecord_tonumber(jit_State
*J
, RecordFFData
*rd
)
1171 CTState
*cts
= ctype_ctsG(J2G(J
));
1172 CType
*d
, *ct
= lj_ctype_rawref(cts
, cdataV(&rd
->argv
[0])->typeid);
1173 if (ctype_isenum(ct
->info
)) ct
= ctype_child(cts
, ct
);
1174 if (ctype_isnum(ct
->info
) || ctype_iscomplex(ct
->info
)) {
1175 if (ctype_isinteger_or_bool(ct
->info
) && ct
->size
<= 4 &&
1176 !(ct
->size
== 4 && (ct
->info
& CTF_UNSIGNED
)))
1177 d
= ctype_get(cts
, CTID_INT32
);
1179 d
= ctype_get(cts
, CTID_DOUBLE
);
1180 J
->base
[0] = crec_ct_tv(J
, d
, 0, J
->base
[0], &rd
->argv
[0]);
1182 J
->base
[0] = TREF_NIL
;