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"
24 #include "lj_ircall.h"
27 #include "lj_record.h"
28 #include "lj_ffrecord.h"
29 #include "lj_crecord.h"
30 #include "lj_dispatch.h"
32 /* Some local macros to save typing. Undef'd at the end. */
33 #define IR(ref) (&J->cur.ir[(ref)])
35 /* Pass IR on to next optimization in chain (FOLD). */
36 #define emitir(ot, a, b) (lj_ir_set(J, (ot), (a), (b)), lj_opt_fold(J))
38 #define emitconv(a, dt, st, flags) \
39 emitir(IRT(IR_CONV, (dt)), (a), (st)|((dt) << 5)|(flags))
41 /* -- C type checks ------------------------------------------------------- */
43 static GCcdata
*argv2cdata(jit_State
*J
, TRef tr
, cTValue
*o
)
47 if (!tref_iscdata(tr
))
48 lj_trace_err(J
, LJ_TRERR_BADTYPE
);
50 /* Specialize to the CTypeID. */
51 trtypeid
= emitir(IRT(IR_FLOAD
, IRT_U16
), tr
, IRFL_CDATA_TYPEID
);
52 emitir(IRTG(IR_EQ
, IRT_INT
), trtypeid
, lj_ir_kint(J
, (int32_t)cd
->typeid));
56 /* Specialize to the CTypeID held by a cdata constructor. */
57 static CTypeID
crec_constructor(jit_State
*J
, GCcdata
*cd
, TRef tr
)
60 lua_assert(tref_iscdata(tr
) && cd
->typeid == CTID_CTYPEID
);
61 id
= *(CTypeID
*)cdataptr(cd
);
62 tr
= emitir(IRT(IR_ADD
, IRT_PTR
), tr
, lj_ir_kintp(J
, sizeof(GCcdata
)));
63 tr
= emitir(IRT(IR_XLOAD
, IRT_INT
), tr
, 0);
64 emitir(IRTG(IR_EQ
, IRT_INT
), tr
, lj_ir_kint(J
, (int32_t)id
));
68 static CTypeID
argv2ctype(jit_State
*J
, TRef tr
, cTValue
*o
)
74 /* Specialize to the string containing the C type declaration. */
75 emitir(IRTG(IR_EQ
, IRT_STR
), tr
, lj_ir_kstr(J
, s
));
77 cp
.cts
= ctype_ctsG(J2G(J
));
79 cp
.srcname
= strdata(s
);
81 cp
.mode
= CPARSE_MODE_ABSTRACT
|CPARSE_MODE_NOIMPLICIT
;
82 if (lj_cparse(&cp
) || cp
.cts
->top
> oldtop
) /* Avoid new struct defs. */
83 lj_trace_err(J
, LJ_TRERR_BADTYPE
);
86 GCcdata
*cd
= argv2cdata(J
, tr
, o
);
87 return cd
->typeid == CTID_CTYPEID
? crec_constructor(J
, cd
, tr
) :
92 /* -- Convert C type to C type -------------------------------------------- */
95 ** This code mirrors the code in lj_cconv.c. It performs the same steps
96 ** for the trace recorder that lj_cconv.c does for the interpreter.
98 ** One major difference is that we can get away with much fewer checks
99 ** here. E.g. checks for casts, constness or correct types can often be
100 ** omitted, even if they might fail. The interpreter subsequently throws
101 ** an error, which aborts the trace.
103 ** All operations are specialized to their C types, so the on-trace
104 ** outcome must be the same as the outcome in the interpreter. If the
105 ** interpreter doesn't throw an error, then the trace is correct, too.
106 ** Care must be taken not to generate invalid (temporary) IR or to
110 /* Convert CType to IRType. */
111 static IRType
crec_ct2irt(CType
*ct
)
113 if (LJ_LIKELY(ctype_isnum(ct
->info
))) {
114 if ((ct
->info
& CTF_FP
)) {
115 if (ct
->size
== sizeof(double))
117 else if (ct
->size
== sizeof(float))
120 uint32_t b
= lj_fls(ct
->size
);
122 return IRT_I8
+ 2*b
+ ((ct
->info
& CTF_UNSIGNED
) ? 1 : 0);
124 } else if (ctype_isptr(ct
->info
)) {
125 return (LJ_64
&& ct
->size
== 8) ? IRT_P64
: IRT_P32
;
126 } else if (ctype_iscomplex(ct
->info
)) {
127 if (ct
->size
== 2*sizeof(double))
129 else if (ct
->size
== 2*sizeof(float))
135 /* Determine whether a passed number or cdata number is non-zero. */
136 static int crec_isnonzero(CType
*s
, void *p
)
142 if ((s
->info
& CTF_FP
)) {
143 if (s
->size
== sizeof(float))
144 return (*(float *)p
!= 0);
146 return (*(double *)p
!= 0);
149 return (*(uint8_t *)p
!= 0);
150 else if (s
->size
== 2)
151 return (*(uint16_t *)p
!= 0);
152 else if (s
->size
== 4)
153 return (*(uint32_t *)p
!= 0);
155 return (*(uint64_t *)p
!= 0);
159 static TRef
crec_ct_ct(jit_State
*J
, CType
*d
, CType
*s
, TRef dp
, TRef sp
,
162 CTSize dsize
= d
->size
, ssize
= s
->size
;
163 CTInfo dinfo
= d
->info
, sinfo
= s
->info
;
164 IRType dt
= crec_ct2irt(d
);
165 IRType st
= crec_ct2irt(s
);
167 if (ctype_type(dinfo
) > CT_MAYCONVERT
|| ctype_type(sinfo
) > CT_MAYCONVERT
)
171 ** Note: Unlike lj_cconv_ct_ct(), sp holds the _value_ of pointers and
172 ** numbers up to 8 bytes. Otherwise sp holds a pointer.
175 switch (cconv_idx2(dinfo
, sinfo
)) {
176 /* Destination is a bool. */
178 goto xstore
; /* Source operand is already normalized. */
181 if (st
!= IRT_CDATA
) {
182 /* Specialize to the result of a comparison against 0. */
183 TRef zero
= (st
== IRT_NUM
|| st
== IRT_FLOAT
) ? lj_ir_knum(J
, 0) :
184 (st
== IRT_I64
|| st
== IRT_U64
) ? lj_ir_kint64(J
, 0) :
186 int isnz
= crec_isnonzero(s
, svisnz
);
187 emitir(IRTG(isnz
? IR_NE
: IR_EQ
, st
), sp
, zero
);
188 sp
= lj_ir_kint(J
, isnz
);
193 /* Destination is an integer. */
197 if (dt
== IRT_CDATA
|| st
== IRT_CDATA
) goto err_nyi
;
198 /* Extend 32 to 64 bit integer. */
199 if (dsize
== 8 && ssize
< 8 && !(LJ_64
&& (sinfo
& CTF_UNSIGNED
)))
200 sp
= emitconv(sp
, dt
, ssize
< 4 ? IRT_INT
: st
,
201 (sinfo
& CTF_UNSIGNED
) ? 0 : IRCONV_SEXT
);
202 else if (dsize
< 8 && ssize
== 8) /* Truncate from 64 bit integer. */
203 sp
= emitconv(sp
, dsize
< 4 ? IRT_INT
: dt
, st
, 0);
204 else if (st
== IRT_INT
)
205 sp
= lj_opt_narrow_toint(J
, sp
);
207 if (dt
== IRT_I64
|| dt
== IRT_U64
) lj_needsplit(J
);
208 if (dp
== 0) return sp
;
209 emitir(IRT(IR_XSTORE
, dt
), dp
, sp
);
212 sp
= emitir(IRT(IR_XLOAD
, st
), sp
, 0); /* Load re. */
215 if (dt
== IRT_CDATA
|| st
== IRT_CDATA
) goto err_nyi
;
216 sp
= emitconv(sp
, dsize
< 4 ? IRT_INT
: dt
, st
, IRCONV_TRUNC
|IRCONV_ANY
);
220 sinfo
= CTINFO(CT_NUM
, CTF_UNSIGNED
);
225 /* Destination is a floating-point number. */
229 if (dt
== IRT_CDATA
|| st
== IRT_CDATA
) goto err_nyi
;
230 sp
= emitconv(sp
, dt
, ssize
< 4 ? IRT_INT
: st
, 0);
233 sp
= emitir(IRT(IR_XLOAD
, st
), sp
, 0); /* Load re. */
237 if (dt
== IRT_CDATA
|| st
== IRT_CDATA
) goto err_nyi
;
238 if (dt
!= st
) sp
= emitconv(sp
, dt
, st
, 0);
241 /* Destination is a complex number. */
245 TRef ptr
= emitir(IRT(IR_ADD
, IRT_PTR
), dp
, lj_ir_kintp(J
, (dsize
>> 1)));
246 emitir(IRT(IR_XSTORE
, dt
), ptr
, lj_ir_knum(J
, 0));
249 if ((sinfo
& CTF_FP
)) goto conv_F_F
; else goto conv_F_I
;
252 if (dt
== IRT_CDATA
|| st
== IRT_CDATA
) goto err_nyi
;
255 re
= emitir(IRT(IR_XLOAD
, st
), sp
, 0);
256 ptr
= emitir(IRT(IR_ADD
, IRT_PTR
), sp
, lj_ir_kintp(J
, (ssize
>> 1)));
257 im
= emitir(IRT(IR_XLOAD
, st
), ptr
, 0);
259 re
= emitconv(re
, dt
, st
, 0);
260 im
= emitconv(im
, dt
, st
, 0);
262 emitir(IRT(IR_XSTORE
, dt
), dp
, re
);
263 ptr
= emitir(IRT(IR_ADD
, IRT_PTR
), dp
, lj_ir_kintp(J
, (dsize
>> 1)));
264 emitir(IRT(IR_XSTORE
, dt
), ptr
, im
);
268 /* Destination is a vector. */
275 /* Destination is a pointer. */
279 /* There are only 32 bit pointers/addresses on 32 bit machines.
280 ** Also ok on x64, since all 32 bit ops clear the upper part of the reg.
284 if (st
== IRT_CDATA
) goto err_nyi
;
285 if (!LJ_64
&& ssize
== 8) /* Truncate from 64 bit integer. */
286 sp
= emitconv(sp
, IRT_U32
, st
, 0);
289 if (st
== IRT_CDATA
) goto err_nyi
;
290 /* The signed conversion is cheaper. x64 really has 47 bit pointers. */
291 sp
= emitconv(sp
, (LJ_64
&& dsize
== 8) ? IRT_I64
: IRT_U32
,
292 st
, IRCONV_TRUNC
|IRCONV_ANY
);
295 /* Destination is an array. */
299 /* Destination is a struct/union. */
306 lj_trace_err(J
, LJ_TRERR_NYICONV
);
312 /* -- Convert C type to TValue (load) ------------------------------------- */
314 static TRef
crec_tv_ct(jit_State
*J
, CType
*s
, CTypeID sid
, TRef sp
)
316 CTState
*cts
= ctype_ctsG(J2G(J
));
317 CTInfo sinfo
= s
->info
;
318 lua_assert(!ctype_isenum(sinfo
));
319 if (ctype_isnum(sinfo
)) {
320 IRType t
= crec_ct2irt(s
);
323 goto err_nyi
; /* NYI: copyval of >64 bit integers. */
324 tr
= emitir(IRT(IR_XLOAD
, t
), sp
, 0);
325 if (t
== IRT_FLOAT
|| t
== IRT_U32
) { /* Keep uint32_t/float as numbers. */
326 return emitconv(tr
, IRT_NUM
, t
, 0);
327 } else if (t
== IRT_I64
|| t
== IRT_U64
) { /* Box 64 bit integer. */
330 } else if ((sinfo
& CTF_BOOL
)) {
331 /* Assume not equal to zero. Fixup and emit pending guard later. */
332 lj_ir_set(J
, IRTGI(IR_NE
), tr
, lj_ir_kint(J
, 0));
333 J
->postproc
= LJ_POST_FIXGUARD
;
338 } else if (ctype_isptr(sinfo
)) {
339 IRType t
= (LJ_64
&& s
->size
== 8) ? IRT_P64
: IRT_P32
;
340 sp
= emitir(IRT(IR_XLOAD
, t
), sp
, 0);
341 } else if (ctype_isrefarray(sinfo
) || ctype_isstruct(sinfo
)) {
343 sid
= lj_ctype_intern(cts
, CTINFO_REF(sid
), CTSIZE_PTR
); /* Create ref. */
344 } else if (ctype_iscomplex(sinfo
)) { /* Unbox/box complex. */
345 IRType t
= s
->size
== 2*sizeof(double) ? IRT_NUM
: IRT_FLOAT
;
346 ptrdiff_t esz
= (ptrdiff_t)(s
->size
>> 1);
347 TRef ptr
, tr1
, tr2
, dp
;
348 dp
= emitir(IRTG(IR_CNEW
, IRT_CDATA
), lj_ir_kint(J
, sid
), TREF_NIL
);
349 tr1
= emitir(IRT(IR_XLOAD
, t
), sp
, 0);
350 ptr
= emitir(IRT(IR_ADD
, IRT_PTR
), sp
, lj_ir_kintp(J
, esz
));
351 tr2
= emitir(IRT(IR_XLOAD
, t
), ptr
, 0);
352 ptr
= emitir(IRT(IR_ADD
, IRT_PTR
), dp
, lj_ir_kintp(J
, sizeof(GCcdata
)));
353 emitir(IRT(IR_XSTORE
, t
), ptr
, tr1
);
354 ptr
= emitir(IRT(IR_ADD
, IRT_PTR
), dp
, lj_ir_kintp(J
, sizeof(GCcdata
)+esz
));
355 emitir(IRT(IR_XSTORE
, t
), ptr
, tr2
);
358 /* NYI: copyval of vectors. */
360 lj_trace_err(J
, LJ_TRERR_NYICONV
);
362 /* Box pointer, ref or 64 bit integer. */
363 return emitir(IRTG(IR_CNEWI
, IRT_CDATA
), lj_ir_kint(J
, sid
), sp
);
366 /* -- Convert TValue to C type (store) ------------------------------------ */
368 static TRef
crec_ct_tv(jit_State
*J
, CType
*d
, TRef dp
, TRef sp
, cTValue
*sval
)
370 CTState
*cts
= ctype_ctsG(J2G(J
));
371 CTypeID sid
= CTID_P_VOID
;
374 if (LJ_LIKELY(tref_isinteger(sp
))) {
376 svisnz
= (void *)(intptr_t)(tvisint(sval
)?(intV(sval
)!=0):!tviszero(sval
));
377 } else if (tref_isnum(sp
)) {
379 svisnz
= (void *)(intptr_t)(tvisint(sval
)?(intV(sval
)!=0):!tviszero(sval
));
380 } else if (tref_isbool(sp
)) {
381 sp
= lj_ir_kint(J
, tref_istrue(sp
) ? 1 : 0);
383 } else if (tref_isnil(sp
)) {
384 sp
= lj_ir_kptr(J
, NULL
);
385 } else if (tref_isudata(sp
)) {
386 sp
= emitir(IRT(IR_ADD
, IRT_P32
), sp
, lj_ir_kint(J
, sizeof(GCudata
)));
387 } else if (tref_isstr(sp
)) {
388 if (ctype_isenum(d
->info
)) { /* Match string against enum constant. */
389 GCstr
*str
= strV(sval
);
391 CType
*cct
= lj_ctype_getfield(cts
, d
, str
, &ofs
);
392 /* Specialize to the name of the enum constant. */
393 emitir(IRTG(IR_EQ
, IRT_STR
), sp
, lj_ir_kstr(J
, str
));
394 if (cct
&& ctype_isconstval(cct
->info
)) {
395 lua_assert(ctype_child(cts
, cct
)->size
== 4);
396 svisnz
= (void *)(intptr_t)(cct
->size
!= 0);
397 sp
= lj_ir_kint(J
, (int32_t)cct
->size
);
398 sid
= ctype_cid(cct
->info
);
399 } /* else: interpreter will throw. */
400 } else if (ctype_isrefarray(d
->info
)) { /* Copy string to array. */
401 lj_trace_err(J
, LJ_TRERR_BADTYPE
); /* NYI */
402 } else { /* Otherwise pass the string data as a const char[]. */
403 sp
= emitir(IRT(IR_STRREF
, IRT_P32
), sp
, lj_ir_kint(J
, 0));
406 } else { /* NYI: tref_istab(sp), tref_islightud(sp). */
407 sid
= argv2cdata(J
, sp
, sval
)->typeid;
408 s
= ctype_raw(cts
, sid
);
409 svisnz
= cdataptr(cdataV(sval
));
410 if (ctype_isptr(s
->info
)) {
411 IRType t
= (LJ_64
&& s
->size
== 8) ? IRT_P64
: IRT_P32
;
412 sp
= emitir(IRT(IR_FLOAD
, t
), sp
, IRFL_CDATA_PTR
);
413 if (ctype_isref(s
->info
)) {
414 svisnz
= *(void **)svisnz
;
415 s
= ctype_rawchild(cts
, s
);
417 goto doconv
; /* The pointer value was loaded, don't load number. */
419 } else if (ctype_isinteger(s
->info
) && s
->size
== 8) {
420 IRType t
= (s
->info
& CTF_UNSIGNED
) ? IRT_U64
: IRT_I64
;
421 sp
= emitir(IRT(IR_FLOAD
, t
), sp
, IRFL_CDATA_INT64
);
425 sp
= emitir(IRT(IR_ADD
, IRT_PTR
), sp
, lj_ir_kintp(J
, sizeof(GCcdata
)));
427 if (ctype_isenum(s
->info
)) s
= ctype_child(cts
, s
);
428 if (ctype_isnum(s
->info
)) { /* Load number value. */
429 IRType t
= crec_ct2irt(s
);
430 if (t
!= IRT_CDATA
) {
431 sp
= emitir(IRT(IR_XLOAD
, t
), sp
, 0);
432 if (t
== IRT_I64
|| t
== IRT_U64
) lj_needsplit(J
);
437 s
= ctype_get(cts
, sid
);
439 if (ctype_isenum(d
->info
)) d
= ctype_child(cts
, d
);
440 return crec_ct_ct(J
, d
, s
, dp
, sp
, svisnz
);
443 /* -- C data metamethods -------------------------------------------------- */
445 /* This would be rather difficult in FOLD, so do it here:
446 ** (base+k)+(idx*sz)+ofs ==> (base+idx*sz)+(ofs+k)
447 ** (base+(idx+k)*sz)+ofs ==> (base+idx*sz)+(ofs+k*sz)
449 static TRef
crec_reassoc_ofs(jit_State
*J
, TRef tr
, ptrdiff_t *ofsp
, MSize sz
)
451 IRIns
*ir
= IR(tref_ref(tr
));
452 if (LJ_LIKELY(J
->flags
& JIT_F_OPT_FOLD
) && irref_isk(ir
->op2
) &&
453 (ir
->o
== IR_ADD
|| ir
->o
== IR_ADDOV
|| ir
->o
== IR_SUBOV
)) {
454 IRIns
*irk
= IR(ir
->op2
);
456 if (LJ_64
&& irk
->o
== IR_KINT64
)
457 k
= (ptrdiff_t)ir_kint64(irk
)->u64
* sz
;
459 k
= (ptrdiff_t)irk
->i
* sz
;
460 if (ir
->o
== IR_SUBOV
) *ofsp
-= k
; else *ofsp
+= k
;
461 tr
= ir
->op1
; /* Not a TRef, but the caller doesn't care. */
466 /* Record ctype __index/__newindex metamethods. */
467 static void crec_index_meta(jit_State
*J
, CTState
*cts
, CType
*ct
,
470 CTypeID id
= ctype_typeid(cts
, ct
);
471 cTValue
*tv
= lj_ctype_meta(cts
, id
, rd
->data
? MM_newindex
: MM_index
);
473 lj_trace_err(J
, LJ_TRERR_BADTYPE
);
475 J
->base
[-1] = lj_ir_kfunc(J
, funcV(tv
)) | TREF_FRAME
;
476 rd
->nres
= -1; /* Pending tailcall. */
477 } else if (rd
->data
== 0 && tvistab(tv
) && tref_isstr(J
->base
[1])) {
478 /* Specialize to result of __index lookup. */
479 cTValue
*o
= lj_tab_get(J
->L
, tabV(tv
), &rd
->argv
[1]);
480 IRType t
= itype2irt(o
);
482 J
->base
[0] = lj_ir_kgc(J
, gcV(o
), t
);
484 J
->base
[0] = lj_ir_kint(J
, intV(o
));
486 J
->base
[0] = lj_ir_knumint(J
, numV(o
));
487 else if (tvisbool(o
))
488 J
->base
[0] = TREF_PRI(t
);
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
->typeid);
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
->typeid);
548 if (ctype_isenum(ctk
->info
)) ctk
= ctype_child(cts
, ctk
);
549 if (ctype_ispointer(ct
->info
) &&
550 ctype_isinteger(ctk
->info
) && (t
= crec_ct2irt(ctk
)) != IRT_CDATA
) {
551 if (ctk
->size
== 8) {
552 idx
= emitir(IRT(IR_FLOAD
, t
), idx
, IRFL_CDATA_INT64
);
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
->typeid == 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 if (ctype_isenum(ct
->info
)) ct
= ctype_child(cts
, ct
); /* Skip enums. */
629 J
->base
[0] = crec_tv_ct(J
, ct
, sid
, ptr
);
630 } else { /* __newindex metamethod. */
633 crec_ct_tv(J
, ct
, ptr
, J
->base
[2], &rd
->argv
[2]);
637 /* Record cdata allocation. */
638 static void crec_alloc(jit_State
*J
, RecordFFData
*rd
, CTypeID id
)
640 CTState
*cts
= ctype_ctsG(J2G(J
));
642 CTInfo info
= lj_ctype_info(cts
, id
, &sz
);
643 CType
*d
= ctype_raw(cts
, id
);
645 if (sz
== 0 || sz
> 64 || (info
& CTF_VLA
) || ctype_align(info
) > CT_MEMALIGN
)
646 lj_trace_err(J
, LJ_TRERR_NYICONV
); /* NYI: large/special allocations. */
647 trid
= lj_ir_kint(J
, id
);
648 /* Use special instruction to box pointer or 64 bit integer. */
649 if (ctype_isptr(info
) || (ctype_isinteger(info
) && sz
== 8)) {
650 TRef sp
= J
->base
[1] ? crec_ct_tv(J
, d
, 0, J
->base
[1], &rd
->argv
[1]) :
651 ctype_isptr(info
) ? lj_ir_kptr(J
, NULL
) :
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 lj_trace_err(J
, LJ_TRERR_NYICONV
); /* NYI: init aggregates. */
703 sp
= ctype_isnum(dc
->info
) ? lj_ir_kint(J
, 0) : TREF_NIL
;
705 dp
= emitir(IRT(IR_ADD
, IRT_PTR
), trcd
,
706 lj_ir_kintp(J
, df
->size
+ sizeof(GCcdata
)));
707 crec_ct_tv(J
, dc
, dp
, sp
, sval
);
708 } else if (!ctype_isconstval(df
->info
)) {
709 /* NYI: init bitfields and sub-structures. */
710 lj_trace_err(J
, LJ_TRERR_NYICONV
);
716 dp
= emitir(IRT(IR_ADD
, IRT_PTR
), trcd
, lj_ir_kintp(J
, sizeof(GCcdata
)));
718 crec_ct_tv(J
, d
, dp
, J
->base
[1], &rd
->argv
[1]);
722 crec_ct_tv(J
, d
, dp
, lj_ir_kint(J
, 0), &tv
);
725 /* Handle __gc metamethod. */
726 fin
= lj_ctype_meta(cts
, id
, MM_gc
);
728 TRef trlo
= lj_ir_call(J
, IRCALL_lj_cdata_setfin
, trcd
);
729 TRef trhi
= emitir(IRT(IR_ADD
, IRT_P32
), trlo
, lj_ir_kint(J
, 4));
730 if (LJ_BE
) { TRef tmp
= trlo
; trlo
= trhi
; trhi
= tmp
; }
732 emitir(IRT(IR_XSTORE
, IRT_P32
), trlo
, lj_ir_kfunc(J
, funcV(fin
)));
733 emitir(IRTI(IR_XSTORE
), trhi
, lj_ir_kint(J
, LJ_TFUNC
));
734 } else if (tviscdata(fin
)) {
735 emitir(IRT(IR_XSTORE
, IRT_P32
), trlo
,
736 lj_ir_kgc(J
, obj2gco(cdataV(fin
)), IRT_CDATA
));
737 emitir(IRTI(IR_XSTORE
), trhi
, lj_ir_kint(J
, LJ_TCDATA
));
739 lj_trace_err(J
, LJ_TRERR_BADTYPE
);
746 /* Record argument conversions. */
747 static TRef
crec_call_args(jit_State
*J
, RecordFFData
*rd
,
748 CTState
*cts
, CType
*ct
)
750 TRef args
[CCI_NARGS_MAX
];
757 TRef
*arg0
= NULL
, *arg1
= NULL
;
760 if (ctype_cconv(ct
->info
) == CTCC_THISCALL
)
762 else if (ctype_cconv(ct
->info
) == CTCC_FASTCALL
)
766 /* Skip initial attributes. */
769 CType
*ctf
= ctype_get(cts
, fid
);
770 if (!ctype_isattrib(ctf
->info
)) break;
774 for (n
= 0, base
= J
->base
+1, o
= rd
->argv
+1; *base
; n
++, base
++, o
++) {
778 if (n
>= CCI_NARGS_MAX
)
779 lj_trace_err(J
, LJ_TRERR_NYICALL
);
781 if (fid
) { /* Get argument type from field. */
782 CType
*ctf
= ctype_get(cts
, fid
);
784 lua_assert(ctype_isfield(ctf
->info
));
785 did
= ctype_cid(ctf
->info
);
787 if (!(ct
->info
& CTF_VARARG
))
788 lj_trace_err(J
, LJ_TRERR_NYICALL
); /* Too many arguments. */
789 did
= lj_ccall_ctid_vararg(cts
, o
); /* Infer vararg type. */
791 d
= ctype_raw(cts
, did
);
792 if (!(ctype_isnum(d
->info
) || ctype_isptr(d
->info
) ||
793 ctype_isenum(d
->info
)))
794 lj_trace_err(J
, LJ_TRERR_NYICALL
);
795 tr
= crec_ct_tv(J
, d
, 0, *base
, o
);
796 if (ctype_isinteger_or_bool(d
->info
)) {
798 if ((d
->info
& CTF_UNSIGNED
))
799 tr
= emitconv(tr
, IRT_INT
, d
->size
==1 ? IRT_U8
: IRT_U16
, 0);
801 tr
= emitconv(tr
, IRT_INT
, d
->size
==1 ? IRT_I8
: IRT_I16
,IRCONV_SEXT
);
805 /* 64 bit args must not end up in registers for fastcall/thiscall. */
807 if (!ctype_isfp(d
->info
)) {
808 /* Sigh, the Windows/x86 ABI allows reordering across 64 bit args. */
809 if (tref_typerange(tr
, IRT_I64
, IRT_U64
)) {
811 arg0
= &args
[n
]; args
[n
++] = TREF_NIL
; ngpr
--;
813 arg1
= &args
[n
]; args
[n
++] = TREF_NIL
; ngpr
--;
817 if (arg0
) { *arg0
= tr
; arg0
= NULL
; n
--; continue; }
818 if (arg1
) { *arg1
= tr
; arg1
= NULL
; n
--; continue; }
823 if (!ctype_isfp(d
->info
) && ngpr
) {
824 if (tref_typerange(tr
, IRT_I64
, IRT_U64
)) {
825 /* No reordering for other x86 ABIs. Simply add alignment args. */
826 do { args
[n
++] = TREF_NIL
; } while (--ngpr
);
836 for (i
= 1; i
< n
; i
++)
837 tr
= emitir(IRT(IR_CARG
, IRT_NIL
), tr
, args
[i
]);
841 /* Record function call. */
842 static int crec_call(jit_State
*J
, RecordFFData
*rd
, GCcdata
*cd
)
844 CTState
*cts
= ctype_ctsG(J2G(J
));
845 CType
*ct
= ctype_raw(cts
, cd
->typeid);
847 if (ctype_isptr(ct
->info
)) {
848 tp
= (LJ_64
&& ct
->size
== 8) ? IRT_P64
: IRT_P32
;
849 ct
= ctype_rawchild(cts
, ct
);
851 if (ctype_isfunc(ct
->info
)) {
852 TRef func
= emitir(IRT(IR_FLOAD
, tp
), J
->base
[0], IRFL_CDATA_PTR
);
853 CType
*ctr
= ctype_rawchild(cts
, ct
);
854 IRType t
= crec_ct2irt(ctr
);
856 if (ctype_isvoid(ctr
->info
)) {
859 } else if (ctype_isenum(ctr
->info
)) {
860 ctr
= ctype_child(cts
, ctr
);
862 if (!(ctype_isnum(ctr
->info
) || ctype_isptr(ctr
->info
) ||
863 ctype_isvoid(ctr
->info
)) ||
864 ctype_isbool(ctr
->info
) || t
== IRT_CDATA
)
865 lj_trace_err(J
, LJ_TRERR_NYICALL
);
866 if ((ct
->info
& CTF_VARARG
)
868 || ctype_cconv(ct
->info
) != CTCC_CDECL
871 func
= emitir(IRT(IR_CARG
, IRT_NIL
), func
,
872 lj_ir_kint(J
, ctype_typeid(cts
, ct
)));
873 tr
= emitir(IRT(IR_CALLXS
, t
), crec_call_args(J
, rd
, cts
, ct
), func
);
874 if (t
== IRT_FLOAT
|| t
== IRT_U32
) {
875 tr
= emitconv(tr
, IRT_NUM
, t
, 0);
876 } else if (t
== IRT_I8
|| t
== IRT_I16
) {
877 tr
= emitconv(tr
, IRT_INT
, t
, IRCONV_SEXT
);
878 } else if (t
== IRT_U8
|| t
== IRT_U16
) {
879 tr
= emitconv(tr
, IRT_INT
, t
, 0);
880 } else if (t
== IRT_PTR
|| (LJ_64
&& t
== IRT_P32
) ||
881 (t
== IRT_I64
|| t
== IRT_U64
)) {
882 TRef trid
= lj_ir_kint(J
, ctype_cid(ct
->info
));
883 tr
= emitir(IRTG(IR_CNEWI
, IRT_CDATA
), trid
, tr
);
884 if (t
== IRT_I64
|| t
== IRT_U64
) lj_needsplit(J
);
893 void LJ_FASTCALL
recff_cdata_call(jit_State
*J
, RecordFFData
*rd
)
895 GCcdata
*cd
= argv2cdata(J
, J
->base
[0], &rd
->argv
[0]);
896 if (cd
->typeid == CTID_CTYPEID
)
897 crec_alloc(J
, rd
, crec_constructor(J
, cd
, J
->base
[0]));
898 else if (!crec_call(J
, rd
, cd
))
899 lj_trace_err(J
, LJ_TRERR_BADTYPE
);
902 static TRef
crec_arith_int64(jit_State
*J
, TRef
*sp
, CType
**s
, MMS mm
)
904 if (ctype_isnum(s
[0]->info
) && ctype_isnum(s
[1]->info
)) {
910 if (((s
[0]->info
& CTF_UNSIGNED
) && s
[0]->size
== 8) ||
911 ((s
[1]->info
& CTF_UNSIGNED
) && s
[1]->size
== 8)) {
912 dt
= IRT_U64
; id
= CTID_UINT64
;
914 dt
= IRT_I64
; id
= CTID_INT64
;
916 for (i
= 0; i
< 2; i
++) {
917 IRType st
= tref_type(sp
[i
]);
918 if (st
== IRT_NUM
|| st
== IRT_FLOAT
)
919 sp
[i
] = emitconv(sp
[i
], dt
, st
, IRCONV_TRUNC
|IRCONV_ANY
);
920 else if (!(st
== IRT_I64
|| st
== IRT_U64
))
921 sp
[i
] = emitconv(sp
[i
], dt
, IRT_INT
,
922 ((st
- IRT_I8
) & 1) ? 0 : IRCONV_SEXT
);
925 /* Assume true comparison. Fixup and emit pending guard later. */
930 op
= mm
== MM_lt
? IR_LT
: IR_LE
;
932 op
+= (IR_ULT
-IR_LT
);
934 lj_ir_set(J
, IRTG(op
, dt
), sp
[0], sp
[1]);
935 J
->postproc
= LJ_POST_FIXGUARD
;
938 tr
= emitir(IRT(mm
+(int)IR_ADD
-(int)MM_add
, dt
), sp
[0], sp
[1]);
940 return emitir(IRTG(IR_CNEWI
, IRT_CDATA
), lj_ir_kint(J
, id
), tr
);
945 static TRef
crec_arith_ptr(jit_State
*J
, TRef
*sp
, CType
**s
, MMS mm
)
947 CTState
*cts
= ctype_ctsG(J2G(J
));
949 if (ctype_isptr(ctp
->info
) || ctype_isrefarray(ctp
->info
)) {
950 if ((mm
== MM_sub
|| mm
== MM_eq
|| mm
== MM_lt
|| mm
== MM_le
) &&
951 (ctype_isptr(s
[1]->info
) || ctype_isrefarray(s
[1]->info
))) {
952 if (mm
== MM_sub
) { /* Pointer difference. */
954 CTSize sz
= lj_ctype_size(cts
, ctype_cid(ctp
->info
));
955 if (sz
== 0 || (sz
& (sz
-1)) != 0)
956 return 0; /* NYI: integer division. */
957 tr
= emitir(IRT(IR_SUB
, IRT_PTR
), sp
[0], sp
[1]);
958 tr
= emitir(IRT(IR_BSAR
, IRT_INTP
), tr
, lj_ir_kint(J
, lj_fls(sz
)));
960 tr
= emitconv(tr
, IRT_NUM
, IRT_INTP
, 0);
963 } else { /* Pointer comparison (unsigned). */
964 /* Assume true comparison. Fixup and emit pending guard later. */
965 IROp op
= mm
== MM_eq
? IR_EQ
: mm
== MM_lt
? IR_ULT
: IR_ULE
;
966 lj_ir_set(J
, IRTG(op
, IRT_PTR
), sp
[0], sp
[1]);
967 J
->postproc
= LJ_POST_FIXGUARD
;
971 if (!((mm
== MM_add
|| mm
== MM_sub
) && ctype_isnum(s
[1]->info
)))
973 } else if (mm
== MM_add
&& ctype_isnum(ctp
->info
) &&
974 (ctype_isptr(s
[1]->info
) || ctype_isrefarray(s
[1]->info
))) {
975 TRef tr
= sp
[0]; sp
[0] = sp
[1]; sp
[1] = tr
; /* Swap pointer and index. */
982 IRType t
= tref_type(tr
);
983 CTSize sz
= lj_ctype_size(cts
, ctype_cid(ctp
->info
));
986 if (t
== IRT_NUM
|| t
== IRT_FLOAT
)
987 tr
= emitconv(tr
, IRT_INTP
, t
, IRCONV_TRUNC
|IRCONV_ANY
);
988 else if (!(t
== IRT_I64
|| t
== IRT_U64
))
989 tr
= emitconv(tr
, IRT_INTP
, IRT_INT
,
990 ((t
- IRT_I8
) & 1) ? 0 : IRCONV_SEXT
);
992 if (!tref_typerange(sp
[1], IRT_I8
, IRT_U32
)) {
993 tr
= emitconv(tr
, IRT_INTP
, t
,
994 (t
== IRT_NUM
|| t
== IRT_FLOAT
) ?
995 IRCONV_TRUNC
|IRCONV_ANY
: 0);
998 tr
= emitir(IRT(IR_MUL
, IRT_INTP
), tr
, lj_ir_kintp(J
, sz
));
999 tr
= emitir(IRT(mm
+(int)IR_ADD
-(int)MM_add
, IRT_PTR
), sp
[0], tr
);
1000 id
= lj_ctype_intern(cts
, CTINFO(CT_PTR
, CTALIGN_PTR
|ctype_cid(ctp
->info
)),
1002 return emitir(IRTG(IR_CNEWI
, IRT_CDATA
), lj_ir_kint(J
, id
), tr
);
1006 /* Record ctype arithmetic metamethods. */
1007 static void crec_arith_meta(jit_State
*J
, CTState
*cts
, RecordFFData
*rd
)
1011 if (tviscdata(&rd
->argv
[0]))
1012 tv
= lj_ctype_meta(cts
, argv2cdata(J
, J
->base
[0], &rd
->argv
[0])->typeid,
1014 if (!tv
&& J
->base
[1] && tviscdata(&rd
->argv
[1]))
1015 tv
= lj_ctype_meta(cts
, argv2cdata(J
, J
->base
[1], &rd
->argv
[1])->typeid,
1018 if (tv
&& tvisfunc(tv
)) {
1019 J
->base
[-1] = lj_ir_kfunc(J
, funcV(tv
)) | TREF_FRAME
;
1020 rd
->nres
= -1; /* Pending tailcall. */
1022 /* NYI: non-function metamethods. */
1023 lj_trace_err(J
, LJ_TRERR_BADTYPE
);
1027 void LJ_FASTCALL
recff_cdata_arith(jit_State
*J
, RecordFFData
*rd
)
1029 CTState
*cts
= ctype_ctsG(J2G(J
));
1033 for (i
= 0; i
< 2; i
++) {
1034 TRef tr
= J
->base
[i
];
1035 CType
*ct
= ctype_get(cts
, CTID_DOUBLE
);
1038 } else if (tref_iscdata(tr
)) {
1039 CTypeID id
= argv2cdata(J
, tr
, &rd
->argv
[i
])->typeid;
1040 ct
= ctype_raw(cts
, id
);
1041 if (ctype_isptr(ct
->info
)) { /* Resolve pointer or reference. */
1042 IRType t
= (LJ_64
&& ct
->size
== 8) ? IRT_P64
: IRT_P32
;
1043 if (ctype_isref(ct
->info
)) ct
= ctype_rawchild(cts
, ct
);
1044 tr
= emitir(IRT(IR_FLOAD
, t
), tr
, IRFL_CDATA_PTR
);
1045 } else if (ctype_isinteger(ct
->info
) && ct
->size
== 8) {
1046 IRType t
= (ct
->info
& CTF_UNSIGNED
) ? IRT_U64
: IRT_I64
;
1047 tr
= emitir(IRT(IR_FLOAD
, t
), tr
, IRFL_CDATA_INT64
);
1050 } else if (ctype_isfunc(ct
->info
)) {
1051 tr
= emitir(IRT(IR_FLOAD
, IRT_PTR
), tr
, IRFL_CDATA_PTR
);
1053 lj_ctype_intern(cts
, CTINFO(CT_PTR
, CTALIGN_PTR
|id
), CTSIZE_PTR
));
1055 tr
= emitir(IRT(IR_ADD
, IRT_PTR
), tr
, lj_ir_kintp(J
, sizeof(GCcdata
)));
1057 if (ctype_isenum(ct
->info
)) ct
= ctype_child(cts
, ct
);
1058 if (ctype_isnum(ct
->info
)) {
1059 IRType t
= crec_ct2irt(ct
);
1060 if (t
== IRT_CDATA
) goto trymeta
;
1061 if (t
== IRT_I64
|| t
== IRT_U64
) lj_needsplit(J
);
1062 tr
= emitir(IRT(IR_XLOAD
, t
), tr
, 0);
1063 } else if (!(ctype_isptr(ct
->info
) || ctype_isrefarray(ct
->info
))) {
1066 } else if (tref_isnil(tr
)) {
1067 tr
= lj_ir_kptr(J
, NULL
);
1068 ct
= ctype_get(cts
, CTID_P_VOID
);
1069 } else if (tref_isinteger(tr
)) {
1070 ct
= ctype_get(cts
, CTID_INT32
);
1071 } else if (!tref_isnum(tr
)) {
1080 if ((tr
= crec_arith_int64(J
, sp
, s
, (MMS
)rd
->data
)) ||
1081 (tr
= crec_arith_ptr(J
, sp
, s
, (MMS
)rd
->data
))) {
1083 /* Fixup cdata comparisons, too. Avoids some cdata escapes. */
1084 if (J
->postproc
== LJ_POST_FIXGUARD
&& frame_iscont(J
->L
->base
-1) &&
1085 !irt_isguard(J
->guardemit
)) {
1086 const BCIns
*pc
= frame_contpc(J
->L
->base
-1) - 1;
1087 if (bc_op(*pc
) <= BC_ISNEP
) {
1088 setframe_pc(&J2G(J
)->tmptv
, pc
);
1089 J2G(J
)->tmptv
.u32
.lo
= ((tref_istrue(tr
) ^ bc_op(*pc
)) & 1);
1090 J
->postproc
= LJ_POST_FIXCOMP
;
1095 crec_arith_meta(J
, cts
, rd
);
1100 /* -- C library namespace metamethods ------------------------------------- */
1102 void LJ_FASTCALL
recff_clib_index(jit_State
*J
, RecordFFData
*rd
)
1104 CTState
*cts
= ctype_ctsG(J2G(J
));
1105 if (tref_isudata(J
->base
[0]) && tref_isstr(J
->base
[1]) &&
1106 udataV(&rd
->argv
[0])->udtype
== UDTYPE_FFI_CLIB
) {
1107 CLibrary
*cl
= (CLibrary
*)uddata(udataV(&rd
->argv
[0]));
1108 GCstr
*name
= strV(&rd
->argv
[1]);
1110 CTypeID id
= lj_ctype_getname(cts
, &ct
, name
, CLNS_INDEX
);
1111 cTValue
*tv
= lj_tab_getstr(cl
->cache
, name
);
1112 rd
->nres
= rd
->data
;
1113 if (id
&& tv
&& !tvisnil(tv
)) {
1114 /* Specialize to the symbol name and make the result a constant. */
1115 emitir(IRTG(IR_EQ
, IRT_STR
), J
->base
[1], lj_ir_kstr(J
, name
));
1116 if (ctype_isconstval(ct
->info
)) {
1117 if (ct
->size
>= 0x80000000u
&&
1118 (ctype_child(cts
, ct
)->info
& CTF_UNSIGNED
))
1119 J
->base
[0] = lj_ir_knum(J
, (lua_Number
)(uint32_t)ct
->size
);
1121 J
->base
[0] = lj_ir_kint(J
, (int32_t)ct
->size
);
1122 } else if (ctype_isextern(ct
->info
)) {
1123 CTypeID sid
= ctype_cid(ct
->info
);
1124 void *sp
= *(void **)cdataptr(cdataV(tv
));
1126 ct
= ctype_raw(cts
, sid
);
1127 if (rd
->data
&& ctype_isenum(ct
->info
)) ct
= ctype_child(cts
, ct
);
1128 if (LJ_64
&& !checkptr32(sp
))
1129 ptr
= lj_ir_kintp(J
, (uintptr_t)sp
);
1131 ptr
= lj_ir_kptr(J
, sp
);
1133 J
->base
[0] = crec_tv_ct(J
, ct
, sid
, ptr
);
1136 crec_ct_tv(J
, ct
, ptr
, J
->base
[2], &rd
->argv
[2]);
1139 J
->base
[0] = lj_ir_kgc(J
, obj2gco(cdataV(tv
)), IRT_CDATA
);
1142 lj_trace_err(J
, LJ_TRERR_NOCACHE
);
1144 } /* else: interpreter will throw. */
1147 /* -- FFI library functions ----------------------------------------------- */
1149 static TRef
crec_toint(jit_State
*J
, CTState
*cts
, TRef sp
, TValue
*sval
)
1151 return crec_ct_tv(J
, ctype_get(cts
, CTID_INT32
), 0, sp
, sval
);
1154 void LJ_FASTCALL
recff_ffi_new(jit_State
*J
, RecordFFData
*rd
)
1156 crec_alloc(J
, rd
, argv2ctype(J
, J
->base
[0], &rd
->argv
[0]));
1159 void LJ_FASTCALL
recff_ffi_string(jit_State
*J
, RecordFFData
*rd
)
1161 CTState
*cts
= ctype_ctsG(J2G(J
));
1162 TRef tr
= J
->base
[0];
1164 TRef trlen
= J
->base
[1];
1166 trlen
= crec_toint(J
, cts
, trlen
, &rd
->argv
[1]);
1167 tr
= crec_ct_tv(J
, ctype_get(cts
, CTID_P_CVOID
), 0, tr
, &rd
->argv
[0]);
1169 tr
= crec_ct_tv(J
, ctype_get(cts
, CTID_P_CCHAR
), 0, tr
, &rd
->argv
[0]);
1170 trlen
= lj_ir_call(J
, IRCALL_strlen
, tr
);
1172 J
->base
[0] = emitir(IRT(IR_XSNEW
, IRT_STR
), tr
, trlen
);
1173 } /* else: interpreter will throw. */
1176 void LJ_FASTCALL
recff_ffi_copy(jit_State
*J
, RecordFFData
*rd
)
1178 CTState
*cts
= ctype_ctsG(J2G(J
));
1179 TRef trdst
= J
->base
[0], trsrc
= J
->base
[1], trlen
= J
->base
[2];
1180 if (trdst
&& trsrc
&& (trlen
|| tref_isstr(trsrc
))) {
1181 trdst
= crec_ct_tv(J
, ctype_get(cts
, CTID_P_VOID
), 0, trdst
, &rd
->argv
[0]);
1182 trsrc
= crec_ct_tv(J
, ctype_get(cts
, CTID_P_CVOID
), 0, trsrc
, &rd
->argv
[1]);
1184 trlen
= crec_toint(J
, cts
, trlen
, &rd
->argv
[2]);
1186 trlen
= emitir(IRTI(IR_FLOAD
), J
->base
[1], IRFL_STR_LEN
);
1187 trlen
= emitir(IRTI(IR_ADD
), trlen
, lj_ir_kint(J
, 1));
1189 lj_ir_call(J
, IRCALL_memcpy
, trdst
, trsrc
, trlen
);
1190 emitir(IRT(IR_XBAR
, IRT_NIL
), 0, 0);
1192 } /* else: interpreter will throw. */
1195 void LJ_FASTCALL
recff_ffi_fill(jit_State
*J
, RecordFFData
*rd
)
1197 CTState
*cts
= ctype_ctsG(J2G(J
));
1198 TRef tr
= J
->base
[0], trlen
= J
->base
[1], trfill
= J
->base
[2];
1200 tr
= crec_ct_tv(J
, ctype_get(cts
, CTID_P_VOID
), 0, tr
, &rd
->argv
[0]);
1201 trlen
= crec_toint(J
, cts
, trlen
, &rd
->argv
[1]);
1203 trfill
= crec_toint(J
, cts
, trfill
, &rd
->argv
[2]);
1205 trfill
= lj_ir_kint(J
, 0);
1206 lj_ir_call(J
, IRCALL_memset
, tr
, trfill
, trlen
);
1207 emitir(IRT(IR_XBAR
, IRT_NIL
), 0, 0);
1209 } /* else: interpreter will throw. */
1212 void LJ_FASTCALL
recff_ffi_istype(jit_State
*J
, RecordFFData
*rd
)
1214 argv2ctype(J
, J
->base
[0], &rd
->argv
[0]);
1215 if (tref_iscdata(J
->base
[1])) {
1216 argv2ctype(J
, J
->base
[1], &rd
->argv
[1]);
1217 J
->postproc
= LJ_POST_FIXBOOL
;
1218 J
->base
[0] = TREF_TRUE
;
1220 J
->base
[0] = TREF_FALSE
;
1224 void LJ_FASTCALL
recff_ffi_abi(jit_State
*J
, RecordFFData
*rd
)
1226 if (tref_isstr(J
->base
[0])) {
1227 /* Specialize to the ABI string to make the boolean result a constant. */
1228 emitir(IRTG(IR_EQ
, IRT_STR
), J
->base
[0], lj_ir_kstr(J
, strV(&rd
->argv
[0])));
1229 J
->postproc
= LJ_POST_FIXBOOL
;
1230 J
->base
[0] = TREF_TRUE
;
1231 } /* else: interpreter will throw. */
1234 /* -- Miscellaneous library functions ------------------------------------- */
1236 void LJ_FASTCALL
lj_crecord_tonumber(jit_State
*J
, RecordFFData
*rd
)
1238 CTState
*cts
= ctype_ctsG(J2G(J
));
1239 CType
*d
, *ct
= lj_ctype_rawref(cts
, cdataV(&rd
->argv
[0])->typeid);
1240 if (ctype_isenum(ct
->info
)) ct
= ctype_child(cts
, ct
);
1241 if (ctype_isnum(ct
->info
) || ctype_iscomplex(ct
->info
)) {
1242 if (ctype_isinteger_or_bool(ct
->info
) && ct
->size
<= 4 &&
1243 !(ct
->size
== 4 && (ct
->info
& CTF_UNSIGNED
)))
1244 d
= ctype_get(cts
, CTID_INT32
);
1246 d
= ctype_get(cts
, CTID_DOUBLE
);
1247 J
->base
[0] = crec_ct_tv(J
, d
, 0, J
->base
[0], &rd
->argv
[0]);
1249 J
->base
[0] = TREF_NIL
;