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"
25
#include "lj_ffrecord.h"
26
#include "lj_crecord.h"
27
#include "lj_dispatch.h"
29
/* Some local macros to save typing. Undef'd at the end. */
30
#define IR(ref) (&J->cur.ir[(ref)])
32
/* Pass IR on to next optimization in chain (FOLD). */
33
#define emitir(ot, a, b) (lj_ir_set(J, (ot), (a), (b)), lj_opt_fold(J))
35
#define emitconv(a, dt, st, flags) \
36
emitir(IRT(IR_CONV, (dt)), (a), (st)|((dt) << 5)|(flags))
38
/* -- C type checks ------------------------------------------------------- */
40
static GCcdata *argv2cdata(jit_State *J, TRef tr, cTValue *o)
44
if (!tref_iscdata(tr))
45
lj_trace_err(J, LJ_TRERR_BADTYPE);
47
/* Specialize to the CTypeID. */
48
trtypeid = emitir(IRT(IR_FLOAD, IRT_U16), tr, IRFL_CDATA_TYPEID);
49
emitir(IRTG(IR_EQ, IRT_INT), trtypeid, lj_ir_kint(J, (int32_t)cd->typeid));
53
static CTypeID argv2ctype(jit_State *J, TRef tr, cTValue *o)
59
/* Specialize to the string containing the C type declaration. */
60
emitir(IRTG(IR_EQ, IRT_STR), tr, lj_ir_kstr(J, s));
62
cp.cts = ctype_ctsG(J2G(J));
64
cp.srcname = strdata(s);
66
cp.mode = CPARSE_MODE_ABSTRACT|CPARSE_MODE_NOIMPLICIT;
67
if (lj_cparse(&cp) || cp.cts->top > oldtop) /* Avoid new struct defs. */
68
lj_trace_err(J, LJ_TRERR_BADTYPE);
71
GCcdata *cd = argv2cdata(J, tr, o);
72
return cd->typeid == CTID_CTYPEID ? *(CTypeID *)cdataptr(cd) : cd->typeid;
76
/* -- Convert C type to C type -------------------------------------------- */
79
** This code mirrors the code in lj_cconv.c. It performs the same steps
80
** for the trace recorder that lj_cconv.c does for the interpreter.
82
** One major difference is that we can get away with much fewer checks
83
** here. E.g. checks for casts, constness or correct types can often be
84
** omitted, even if they might fail. The interpreter subsequently throws
85
** an error, which aborts the trace.
87
** All operations are specialized to their C types, so the on-trace
88
** outcome must be the same as the outcome in the interpreter. If the
89
** interpreter doesn't throw an error, then the trace is correct, too.
90
** Care must be taken not to generate invalid (temporary) IR or to
94
/* Convert CType to IRType. */
95
static IRType crec_ct2irt(CType *ct)
97
if (LJ_LIKELY(ctype_isnum(ct->info))) {
98
if ((ct->info & CTF_FP)) {
99
if (ct->size == sizeof(double))
101
else if (ct->size == sizeof(float))
104
uint32_t b = lj_fls(ct->size);
106
return IRT_I8 + 2*b + ((ct->info & CTF_UNSIGNED) ? 1 : 0);
108
} else if (ctype_isptr(ct->info)) {
109
return (LJ_64 && ct->size == 8) ? IRT_P64 : IRT_P32;
110
} else if (ctype_iscomplex(ct->info)) {
111
if (ct->size == 2*sizeof(double))
113
else if (ct->size == 2*sizeof(float))
119
/* Determine whether a passed number or cdata number is non-zero. */
120
static int crec_isnonzero(CType *s, void *p)
126
if ((s->info & CTF_FP)) {
127
if (s->size == sizeof(float))
128
return (*(float *)p != 0);
130
return (*(double *)p != 0);
133
return (*(uint8_t *)p != 0);
134
else if (s->size == 2)
135
return (*(uint16_t *)p != 0);
136
else if (s->size == 4)
137
return (*(uint32_t *)p != 0);
139
return (*(uint64_t *)p != 0);
143
static TRef crec_ct_ct(jit_State *J, CType *d, CType *s, TRef dp, TRef sp,
146
CTSize dsize = d->size, ssize = s->size;
147
CTInfo dinfo = d->info, sinfo = s->info;
148
IRType dt = crec_ct2irt(d);
149
IRType st = crec_ct2irt(s);
151
if (ctype_type(dinfo) > CT_MAYCONVERT || ctype_type(sinfo) > CT_MAYCONVERT)
155
** Note: Unlike lj_cconv_ct_ct(), sp holds the _value_ of pointers and
156
** numbers up to 8 bytes. Otherwise sp holds a pointer.
159
switch (cconv_idx2(dinfo, sinfo)) {
160
/* Destination is a bool. */
162
goto xstore; /* Source operand is already normalized. */
165
if (st != IRT_CDATA) {
166
/* Specialize to the result of a comparison against 0. */
167
TRef zero = (st == IRT_NUM || st == IRT_FLOAT) ? lj_ir_knum(J, 0) :
168
(st == IRT_I64 || st == IRT_U64) ? lj_ir_kint64(J, 0) :
170
int isnz = crec_isnonzero(s, svisnz);
171
emitir(IRTG(isnz ? IR_NE : IR_EQ, st), sp, zero);
172
sp = lj_ir_kint(J, isnz);
177
/* Destination is an integer. */
181
if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi;
183
/* Sign-extend 32 to 64 bit integer. */
184
if (dsize == 8 && ssize < 8 && !(sinfo & CTF_UNSIGNED))
185
sp = emitconv(sp, dt, IRT_INT, IRCONV_SEXT);
186
/* All other conversions are no-ops on x64. */
188
if (dsize == 8 && ssize < 8) /* Extend to 64 bit integer. */
189
sp = emitconv(sp, dt, ssize < 4 ? IRT_INT : st,
190
(sinfo & CTF_UNSIGNED) ? 0 : IRCONV_SEXT);
191
else if (dsize < 8 && ssize == 8) /* Truncate from 64 bit integer. */
192
sp = emitconv(sp, dsize < 4 ? IRT_INT : dt, st, 0);
195
if (dt == IRT_I64 || dt == IRT_U64) lj_needsplit(J);
196
if (dp == 0) return sp;
197
emitir(IRT(IR_XSTORE, dt), dp, sp);
200
sp = emitir(IRT(IR_XLOAD, st), sp, 0); /* Load re. */
203
if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi;
204
sp = emitconv(sp, dsize < 4 ? IRT_INT : dt, st, IRCONV_TRUNC|IRCONV_ANY);
208
sinfo = CTINFO(CT_NUM, CTF_UNSIGNED);
213
/* Destination is a floating-point number. */
217
if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi;
218
sp = emitconv(sp, dt, ssize < 4 ? IRT_INT : st, 0);
221
sp = emitir(IRT(IR_XLOAD, st), sp, 0); /* Load re. */
225
if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi;
226
if (dt != st) sp = emitconv(sp, dt, st, 0);
229
/* Destination is a complex number. */
233
TRef ptr = emitir(IRT(IR_ADD, IRT_PTR), dp, lj_ir_kintp(J, (dsize >> 1)));
234
emitir(IRT(IR_XSTORE, dt), ptr, lj_ir_knum(J, 0));
237
if ((sinfo & CTF_FP)) goto conv_F_F; else goto conv_F_I;
240
if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi;
243
re = emitir(IRT(IR_XLOAD, st), sp, 0);
244
ptr = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, (ssize >> 1)));
245
im = emitir(IRT(IR_XLOAD, st), ptr, 0);
247
re = emitconv(re, dt, st, 0);
248
im = emitconv(im, dt, st, 0);
250
emitir(IRT(IR_XSTORE, dt), dp, re);
251
ptr = emitir(IRT(IR_ADD, IRT_PTR), dp, lj_ir_kintp(J, (dsize >> 1)));
252
emitir(IRT(IR_XSTORE, dt), ptr, im);
256
/* Destination is a vector. */
263
/* Destination is a pointer. */
267
/* There are only 32 bit pointers/addresses on 32 bit machines.
268
** Also ok on x64, since all 32 bit ops clear the upper part of the reg.
272
if (st == IRT_CDATA) goto err_nyi;
273
if (!LJ_64 && ssize == 8) /* Truncate from 64 bit integer. */
274
sp = emitconv(sp, IRT_U32, st, 0);
277
if (st == IRT_CDATA) goto err_nyi;
278
/* The signed conversion is cheaper. x64 really has 47 bit pointers. */
279
sp = emitconv(sp, (LJ_64 && dsize == 8) ? IRT_I64 : IRT_U32,
280
st, IRCONV_TRUNC|IRCONV_ANY);
283
/* Destination is an array. */
287
/* Destination is a struct/union. */
294
lj_trace_err(J, LJ_TRERR_NYICONV);
300
/* -- Convert C type to TValue (load) ------------------------------------- */
302
static TRef crec_tv_ct(jit_State *J, CType *s, CTypeID sid, TRef sp)
304
CTState *cts = ctype_ctsG(J2G(J));
305
CTInfo sinfo = s->info;
306
lua_assert(!ctype_isenum(sinfo));
307
if (ctype_isnum(sinfo)) {
308
IRType t = crec_ct2irt(s);
311
goto err_nyi; /* NYI: copyval of >64 bit integers. */
312
tr = emitir(IRT(IR_XLOAD, t), sp, 0);
313
if (t == IRT_FLOAT || t == IRT_U32) { /* Keep uint32_t/float as numbers. */
314
return emitconv(tr, IRT_NUM, t, 0);
315
} else if (t == IRT_I64 || t == IRT_U64) { /* Box 64 bit integer. */
318
} else if ((sinfo & CTF_BOOL)) {
319
/* Assume not equal to zero. Fixup and emit pending guard later. */
320
lj_ir_set(J, IRTGI(IR_NE), tr, lj_ir_kint(J, 0));
321
J->postproc = LJ_POST_FIXGUARD;
326
} else if (ctype_isptr(sinfo)) {
327
IRType t = (LJ_64 && s->size == 8) ? IRT_P64 : IRT_P32;
328
sp = emitir(IRT(IR_XLOAD, t), sp, 0);
329
} else if (ctype_isrefarray(sinfo) || ctype_isstruct(sinfo)) {
331
sid = lj_ctype_intern(cts, CTINFO_REF(sid), CTSIZE_PTR); /* Create ref. */
332
} else if (ctype_iscomplex(sinfo)) { /* Unbox/box complex. */
333
IRType t = s->size == 2*sizeof(double) ? IRT_NUM : IRT_FLOAT;
334
ptrdiff_t esz = (ptrdiff_t)(s->size >> 1);
335
TRef ptr, tr1, tr2, dp;
336
dp = emitir(IRTG(IR_CNEW, IRT_CDATA), lj_ir_kint(J, sid), TREF_NIL);
337
tr1 = emitir(IRT(IR_XLOAD, t), sp, 0);
338
ptr = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, esz));
339
tr2 = emitir(IRT(IR_XLOAD, t), ptr, 0);
340
ptr = emitir(IRT(IR_ADD, IRT_PTR), dp, lj_ir_kintp(J, sizeof(GCcdata)));
341
emitir(IRT(IR_XSTORE, t), ptr, tr1);
342
ptr = emitir(IRT(IR_ADD, IRT_PTR), dp, lj_ir_kintp(J, sizeof(GCcdata)+esz));
343
emitir(IRT(IR_XSTORE, t), ptr, tr2);
346
/* NYI: copyval of vectors. */
348
lj_trace_err(J, LJ_TRERR_NYICONV);
350
/* Box pointer, ref or 64 bit integer. */
351
return emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, sid), sp);
354
/* -- Convert TValue to C type (store) ------------------------------------ */
356
static TRef crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, TValue *sval)
358
CTState *cts = ctype_ctsG(J2G(J));
359
CTypeID sid = CTID_P_VOID;
362
if (LJ_LIKELY(tref_isinteger(sp))) {
364
svisnz = (void *)(intptr_t)(numV(sval) != 0);
365
} else if (tref_isnum(sp)) {
367
svisnz = (void *)(intptr_t)(numV(sval) != 0);
368
} else if (tref_isbool(sp)) {
369
sp = lj_ir_kint(J, tref_istrue(sp) ? 1 : 0);
371
} else if (tref_isnil(sp)) {
372
sp = lj_ir_kptr(J, NULL);
373
} else if (tref_isudata(sp)) {
374
sp = emitir(IRT(IR_ADD, IRT_P32), sp, lj_ir_kint(J, sizeof(GCcdata)));
375
} else if (tref_isstr(sp)) {
376
if (ctype_isenum(d->info)) { /* Match string against enum constant. */
377
GCstr *str = strV(sval);
379
CType *cct = lj_ctype_getfield(cts, d, str, &ofs);
380
/* Specialize to the name of the enum constant. */
381
emitir(IRTG(IR_EQ, IRT_STR), sp, lj_ir_kstr(J, str));
382
if (cct && ctype_isconstval(cct->info)) {
383
lua_assert(ctype_child(cts, cct)->size == 4);
384
svisnz = (void *)(intptr_t)(cct->size != 0);
385
sp = lj_ir_kint(J, (int32_t)cct->size);
386
sid = ctype_cid(cct->info);
387
} /* else: interpreter will throw. */
388
} else if (ctype_isrefarray(d->info)) { /* Copy string to array. */
389
lj_trace_err(J, LJ_TRERR_BADTYPE); /* NYI */
390
} else { /* Otherwise pass the string data as a const char[]. */
391
sp = emitir(IRT(IR_STRREF, IRT_P32), sp, lj_ir_kint(J, 0));
394
} else { /* NYI: tref_istab(sp), tref_islightud(sp). */
395
sid = argv2cdata(J, sp, sval)->typeid;
396
s = ctype_raw(cts, sid);
397
svisnz = cdataptr(cdataV(sval));
398
if (ctype_isptr(s->info)) {
399
IRType t = (LJ_64 && s->size == 8) ? IRT_P64 : IRT_P32;
400
sp = emitir(IRT(IR_FLOAD, t), sp, IRFL_CDATA_PTR);
401
if (ctype_isref(s->info)) {
402
svisnz = *(void **)svisnz;
403
s = ctype_rawchild(cts, s);
405
goto doconv; /* The pointer value was loaded, don't load number. */
407
} else if (ctype_isinteger(s->info) && s->size == 8) {
408
IRType t = (s->info & CTF_UNSIGNED) ? IRT_U64 : IRT_I64;
409
sp = emitir(IRT(IR_FLOAD, t), sp, IRFL_CDATA_INT64);
413
sp = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, sizeof(GCcdata)));
415
if (ctype_isenum(s->info)) s = ctype_child(cts, s);
416
if (ctype_isnum(s->info)) { /* Load number value. */
417
IRType t = crec_ct2irt(s);
418
if (t != IRT_CDATA) {
419
sp = emitir(IRT(IR_XLOAD, t), sp, 0);
420
if (t == IRT_I64 || t == IRT_U64) lj_needsplit(J);
425
s = ctype_get(cts, sid);
427
if (ctype_isenum(d->info)) d = ctype_child(cts, d);
428
return crec_ct_ct(J, d, s, dp, sp, svisnz);
431
/* -- C data metamethods -------------------------------------------------- */
433
/* Specialize to the CTypeID held by a cdata constructor. */
434
static CTypeID crec_constructor(jit_State *J, GCcdata *cd, TRef tr)
437
lua_assert(tref_iscdata(tr) && cd->typeid == CTID_CTYPEID);
438
id = *(CTypeID *)cdataptr(cd);
439
tr = emitir(IRT(IR_ADD, IRT_PTR), tr, lj_ir_kintp(J, sizeof(GCcdata)));
440
tr = emitir(IRT(IR_XLOAD, IRT_INT), tr, 0);
441
emitir(IRTG(IR_EQ, IRT_INT), tr, lj_ir_kint(J, (int32_t)id));
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) &&
453
ir->o == IR_ADD && irref_isk(ir->op2)) {
454
IRIns *irk = IR(ir->op2);
457
if (irk->o == IR_KINT64)
458
*ofsp += (ptrdiff_t)ir_kint64(irk)->u64 * sz;
461
*ofsp += (ptrdiff_t)irk->i * sz;
466
void LJ_FASTCALL recff_cdata_index(jit_State *J, RecordFFData *rd)
468
TRef idx, ptr = J->base[0];
469
ptrdiff_t ofs = sizeof(GCcdata);
470
GCcdata *cd = argv2cdata(J, ptr, &rd->argv[0]);
471
CTState *cts = ctype_ctsG(J2G(J));
472
CType *ct = ctype_raw(cts, cd->typeid);
475
/* Resolve pointer or reference for cdata object. */
476
if (ctype_isptr(ct->info)) {
477
IRType t = (LJ_64 && ct->size == 8) ? IRT_P64 : IRT_P32;
478
if (ctype_isref(ct->info)) ct = ctype_rawchild(cts, ct);
479
ptr = emitir(IRT(IR_FLOAD, t), ptr, IRFL_CDATA_PTR);
481
ptr = crec_reassoc_ofs(J, ptr, &ofs, 1);
485
if (tref_isnumber(idx)) {
486
/* The size of a ptrdiff_t is target-specific. */
489
idx = emitconv(idx, IRT_I64, IRT_NUM, IRCONV_TRUNC|IRCONV_ANY);
491
idx = emitconv(idx, IRT_I64, IRT_INT, IRCONV_SEXT);
494
idx = emitconv(idx, IRT_INT, IRT_NUM, IRCONV_TRUNC|IRCONV_ANY);
497
if (ctype_ispointer(ct->info)) {
499
if ((ct->info & CTF_COMPLEX))
500
idx = emitir(IRT(IR_BAND, IRT_INTP), idx, lj_ir_kintp(J, 1));
501
sz = lj_ctype_size(cts, (sid = ctype_cid(ct->info)));
502
idx = crec_reassoc_ofs(J, idx, &ofs, sz);
503
idx = emitir(IRT(IR_MUL, IRT_INTP), idx, lj_ir_kintp(J, sz));
504
ptr = emitir(IRT(IR_ADD, IRT_PTR), idx, ptr);
506
} else if (tref_iscdata(idx)) {
507
GCcdata *cdk = cdataV(&rd->argv[1]);
508
CType *ctk = ctype_raw(cts, cdk->typeid);
510
if (ctype_isenum(ctk->info)) ctk = ctype_child(cts, ctk);
511
if (ctype_isinteger(ctk->info) && (t = crec_ct2irt(ctk)) != IRT_CDATA) {
512
idx = emitir(IRT(IR_ADD, IRT_PTR), idx, lj_ir_kintp(J, sizeof(GCcdata)));
513
idx = emitir(IRT(IR_XLOAD, t), idx, 0);
514
if (!LJ_64 && (t == IRT_I64 || t == IRT_U64)) {
515
idx = emitconv(idx, IRT_INT, t, 0);
520
} else if (tref_isstr(idx)) {
521
GCstr *name = strV(&rd->argv[1]);
522
/* Always specialize to the field name. */
523
emitir(IRTG(IR_EQ, IRT_STR), idx, lj_ir_kstr(J, name));
524
if (cd->typeid == CTID_CTYPEID)
525
ct = ctype_raw(cts, crec_constructor(J, cd, ptr));
526
if (ctype_isptr(ct->info)) { /* Automatically perform '->'. */
527
CType *cct = ctype_rawchild(cts, ct);
528
if (ctype_isstruct(cct->info)) {
532
} else if (ctype_isstruct(ct->info)) {
536
fct = lj_ctype_getfield(cts, ct, name, &fofs);
538
if (ctype_isconstval(fct->info)) {
539
if (fct->size >= 0x80000000u &&
540
(ctype_child(cts, fct)->info & CTF_UNSIGNED)) {
541
J->base[0] = lj_ir_knum(J, (lua_Number)(uint32_t)fct->size);
544
J->base[0] = lj_ir_kint(J, (int32_t)fct->size);
545
return; /* Interpreter will throw for newindex. */
546
} else if (ctype_isbitfield(fct->info)) {
547
lj_trace_err(J, LJ_TRERR_NYICONV);
549
lua_assert(ctype_isfield(fct->info));
550
sid = ctype_cid(fct->info);
552
ofs += (ptrdiff_t)fofs;
554
} else if (ctype_iscomplex(ct->info)) {
555
if (strdata(name)[0] == 'i') ofs += (ct->size >> 1);
556
sid = ctype_cid(ct->info);
559
if (!sid) lj_trace_err(J, LJ_TRERR_BADTYPE);
562
ptr = emitir(IRT(IR_ADD, IRT_PTR), ptr, lj_ir_kintp(J, ofs));
564
/* Resolve reference for field. */
565
ct = ctype_get(cts, sid);
566
if (ctype_isref(ct->info))
567
ptr = emitir(IRT(IR_XLOAD, IRT_PTR), ptr, 0);
569
while (ctype_isattrib(ct->info))
570
ct = ctype_child(cts, ct); /* Skip attributes. */
572
if (rd->data == 0) { /* __index metamethod. */
573
if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct); /* Skip enums. */
574
J->base[0] = crec_tv_ct(J, ct, sid, ptr);
575
} else { /* __newindex metamethod. */
578
crec_ct_tv(J, ct, ptr, J->base[2], &rd->argv[2]);
582
/* Record cdata allocation. */
583
static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id)
585
CTState *cts = ctype_ctsG(J2G(J));
587
CTInfo info = lj_ctype_info(cts, id, &sz);
588
CType *d = ctype_raw(cts, id);
590
if (sz == 0 || sz > 64 || (info & CTF_VLA) || ctype_align(info) > CT_MEMALIGN)
591
lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: large/special allocations. */
592
trid = lj_ir_kint(J, id);
593
/* Use special instruction to box pointer or 64 bit integer. */
594
if (ctype_isptr(info) || (ctype_isinteger(info) && sz == 8)) {
595
TRef sp = J->base[1] ? crec_ct_tv(J, d, 0, J->base[1], &rd->argv[1]) :
596
ctype_isptr(info) ? lj_ir_kptr(J, NULL) :
597
(lj_needsplit(J), lj_ir_kint64(J, 0));
598
J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), trid, sp);
600
TRef trcd = emitir(IRTG(IR_CNEW, IRT_CDATA), trid, TREF_NIL);
602
if (J->base[1] && !J->base[2] && !lj_cconv_multi_init(d, &rd->argv[1])) {
604
} else if (ctype_isarray(d->info)) {
605
CType *dc = ctype_rawchild(cts, d); /* Array element type. */
606
CTSize ofs, esize = dc->size;
612
if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info)))
613
lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: init array of aggregates. */
614
for (i = 1, ofs = 0; ofs < sz; ofs += esize) {
615
TRef dp = emitir(IRT(IR_ADD, IRT_PTR), trcd,
616
lj_ir_kintp(J, ofs + sizeof(GCcdata)));
622
sp = ctype_isnum(dc->info) ? lj_ir_kint(J, 0) : TREF_NIL;
624
crec_ct_tv(J, dc, dp, sp, sval);
626
} else if (ctype_isstruct(d->info)) {
627
CTypeID fid = d->sib;
630
CType *df = ctype_get(cts, fid);
632
if (ctype_isfield(df->info)) {
638
if (!gcref(df->name)) continue; /* Ignore unnamed fields. */
639
dc = ctype_rawchild(cts, df); /* Field type. */
640
if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info)))
641
lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: init aggregates. */
647
sp = ctype_isnum(dc->info) ? lj_ir_kint(J, 0) : TREF_NIL;
649
dp = emitir(IRT(IR_ADD, IRT_PTR), trcd,
650
lj_ir_kintp(J, df->size + sizeof(GCcdata)));
651
crec_ct_tv(J, dc, dp, sp, sval);
652
} else if (!ctype_isconstval(df->info)) {
653
/* NYI: init bitfields and sub-structures. */
654
lj_trace_err(J, LJ_TRERR_NYICONV);
660
dp = emitir(IRT(IR_ADD, IRT_PTR), trcd, lj_ir_kintp(J, sizeof(GCcdata)));
662
crec_ct_tv(J, d, dp, J->base[1], &rd->argv[1]);
666
crec_ct_tv(J, d, dp, lj_ir_kint(J, 0), &tv);
672
/* Record argument conversions. */
673
static TRef crec_call_args(jit_State *J, RecordFFData *rd,
674
CTState *cts, CType *ct)
676
TRef args[CCI_NARGS_MAX];
680
for (n = 0; J->base[n+1]; n++) {
683
if (!ct->sib || n >= CCI_NARGS_MAX)
684
lj_trace_err(J, LJ_TRERR_NYICALL);
685
ct = ctype_get(cts, ct->sib);
686
} while (ctype_isattrib(ct->info));
687
if (!ctype_isfield(ct->info))
688
lj_trace_err(J, LJ_TRERR_NYICALL);
689
d = ctype_rawchild(cts, ct);
690
if (!(ctype_isnum(d->info) || ctype_isptr(d->info) ||
691
ctype_isenum(d->info)))
692
lj_trace_err(J, LJ_TRERR_NYICALL);
693
args[n] = crec_ct_tv(J, d, 0, J->base[n+1], &rd->argv[n+1]);
696
for (i = 1; i < n; i++)
697
tr = emitir(IRT(IR_CARG, IRT_NIL), tr, args[i]);
701
/* Record function call. */
702
static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd)
704
CTState *cts = ctype_ctsG(J2G(J));
705
CType *ct = ctype_raw(cts, cd->typeid);
707
if (ctype_isptr(ct->info)) {
708
tp = (LJ_64 && ct->size == 8) ? IRT_P64 : IRT_P32;
709
ct = ctype_rawchild(cts, ct);
711
if (ctype_isfunc(ct->info)) {
712
TRef func = emitir(IRT(IR_FLOAD, tp), J->base[0], IRFL_CDATA_PTR);
713
CType *ctr = ctype_rawchild(cts, ct);
714
IRType t = crec_ct2irt(ctr);
716
if (ctype_isenum(ctr->info)) ctr = ctype_child(cts, ctr);
717
if (!(ctype_isnum(ctr->info) || ctype_isptr(ctr->info)) ||
718
ctype_isbool(ctr->info) || (ct->info & CTF_VARARG) ||
720
ctype_cconv(ct->info) != CTCC_CDECL ||
722
t == IRT_CDATA || (LJ_32 && (t == IRT_I64 || t == IRT_U64)))
723
lj_trace_err(J, LJ_TRERR_NYICALL);
724
tr = emitir(IRT(IR_CALLXS, t), crec_call_args(J, rd, cts, ct), func);
725
if (t == IRT_FLOAT || t == IRT_U32) {
726
tr = emitconv(tr, IRT_NUM, t, 0);
727
} else if (t == IRT_PTR || (LJ_64 && t == IRT_P32) ||
728
(LJ_64 && (t == IRT_I64 || t == IRT_U64))) {
729
TRef trid = lj_ir_kint(J, ctype_cid(ct->info));
730
tr = emitir(IRTG(IR_CNEWI, IRT_CDATA), trid, tr);
738
void LJ_FASTCALL recff_cdata_call(jit_State *J, RecordFFData *rd)
740
GCcdata *cd = argv2cdata(J, J->base[0], &rd->argv[0]);
741
if (cd->typeid == CTID_CTYPEID)
742
crec_alloc(J, rd, crec_constructor(J, cd, J->base[0]));
743
else if (!crec_call(J, rd, cd))
744
lj_trace_err(J, LJ_TRERR_BADTYPE);
747
static TRef crec_arith_int64(jit_State *J, TRef *sp, CType **s, MMS mm)
749
if (ctype_isnum(s[0]->info) && ctype_isnum(s[1]->info)) {
755
if (((s[0]->info & CTF_UNSIGNED) && s[0]->size == 8) ||
756
((s[1]->info & CTF_UNSIGNED) && s[1]->size == 8)) {
757
dt = IRT_U64; id = CTID_UINT64;
759
dt = IRT_I64; id = CTID_INT64;
761
for (i = 0; i < 2; i++) {
762
IRType st = tref_type(sp[i]);
763
if (st == IRT_NUM || st == IRT_FLOAT)
764
sp[i] = emitconv(sp[i], dt, st, IRCONV_TRUNC|IRCONV_ANY);
765
else if (!(st == IRT_I64 || st == IRT_U64))
766
sp[i] = emitconv(sp[i], dt, IRT_INT,
767
((st - IRT_I8) & 1) ? 0 : IRCONV_SEXT);
770
/* Assume true comparison. Fixup and emit pending guard later. */
775
op = mm == MM_lt ? IR_LT : IR_LE;
777
op += (IR_ULT-IR_LT);
779
lj_ir_set(J, IRTG(op, dt), sp[0], sp[1]);
780
J->postproc = LJ_POST_FIXGUARD;
783
tr = emitir(IRT(mm+(int)IR_ADD-(int)MM_add, dt), sp[0], sp[1]);
785
return emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr);
790
static TRef crec_arith_ptr(jit_State *J, TRef *sp, CType **s, MMS mm)
792
CTState *cts = ctype_ctsG(J2G(J));
794
if (ctype_isptr(ctp->info) || ctype_isrefarray(ctp->info)) {
795
if ((mm == MM_sub || mm == MM_eq || mm == MM_lt || mm == MM_le) &&
796
(ctype_isptr(s[1]->info) || ctype_isrefarray(s[1]->info))) {
797
if (mm == MM_sub) { /* Pointer difference. */
799
CTSize sz = lj_ctype_size(cts, ctype_cid(ctp->info));
800
if (sz == 0 || (sz & (sz-1)) != 0)
801
return 0; /* NYI: integer division. */
802
tr = emitir(IRT(IR_SUB, IRT_PTR), sp[0], sp[1]);
803
tr = emitir(IRT(IR_BSAR, IRT_INTP), tr, lj_ir_kint(J, lj_fls(sz)));
805
tr = emitconv(tr, IRT_NUM, IRT_INTP, 0);
808
} else { /* Pointer comparison (unsigned). */
809
/* Assume true comparison. Fixup and emit pending guard later. */
810
IROp op = mm == MM_eq ? IR_EQ : mm == MM_lt ? IR_ULT : IR_ULE;
811
lj_ir_set(J, IRTG(op, IRT_PTR), sp[0], sp[1]);
812
J->postproc = LJ_POST_FIXGUARD;
816
if (!((mm == MM_add || mm == MM_sub) && ctype_isnum(s[1]->info)))
818
} else if (mm == MM_add && ctype_isnum(ctp->info) &&
819
(ctype_isptr(s[1]->info) || ctype_isrefarray(s[1]->info))) {
820
TRef tr = sp[0]; sp[0] = sp[1]; sp[1] = tr; /* Swap pointer and index. */
827
IRType t = tref_type(tr);
828
CTSize sz = lj_ctype_size(cts, ctype_cid(ctp->info));
831
if (t == IRT_NUM || t == IRT_FLOAT)
832
tr = emitconv(tr, IRT_INTP, t, IRCONV_TRUNC|IRCONV_ANY);
833
else if (!(t == IRT_I64 || t == IRT_U64))
834
tr = emitconv(tr, IRT_INTP, IRT_INT,
835
((t - IRT_I8) & 1) ? 0 : IRCONV_SEXT);
837
if (!tref_typerange(sp[1], IRT_I8, IRT_U32)) {
838
tr = emitconv(tr, IRT_INTP, t,
839
(t == IRT_NUM || t == IRT_FLOAT) ?
840
IRCONV_TRUNC|IRCONV_ANY : 0);
843
tr = emitir(IRT(IR_MUL, IRT_INTP), tr, lj_ir_kintp(J, sz));
844
tr = emitir(IRT(mm+(int)IR_ADD-(int)MM_add, IRT_PTR), sp[0], tr);
845
id = lj_ctype_intern(cts, CTINFO(CT_PTR, CTALIGN_PTR|ctype_cid(ctp->info)),
847
return emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr);
851
void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
853
CTState *cts = ctype_ctsG(J2G(J));
857
for (i = 0; i < 2; i++) {
858
TRef tr = J->base[i];
859
CType *ct = ctype_get(cts, CTID_DOUBLE);
860
if (tref_iscdata(tr)) {
861
CTypeID id = argv2cdata(J, tr, &rd->argv[i])->typeid;
862
ct = ctype_raw(cts, id);
863
if (ctype_isptr(ct->info)) { /* Resolve pointer or reference. */
864
IRType t = (LJ_64 && ct->size == 8) ? IRT_P64 : IRT_P32;
865
if (ctype_isref(ct->info)) ct = ctype_rawchild(cts, ct);
866
tr = emitir(IRT(IR_FLOAD, t), tr, IRFL_CDATA_PTR);
867
} else if (ctype_isinteger(ct->info) && ct->size == 8) {
868
IRType t = (ct->info & CTF_UNSIGNED) ? IRT_U64 : IRT_I64;
869
tr = emitir(IRT(IR_FLOAD, t), tr, IRFL_CDATA_INT64);
873
tr = emitir(IRT(IR_ADD, IRT_PTR), tr, lj_ir_kintp(J, sizeof(GCcdata)));
875
if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct);
876
if (ctype_isnum(ct->info)) {
877
IRType t = crec_ct2irt(ct);
878
if (t == IRT_CDATA) goto err_type;
879
if (t == IRT_I64 || t == IRT_U64) lj_needsplit(J);
880
tr = emitir(IRT(IR_XLOAD, t), tr, 0);
881
} else if (!(ctype_isptr(ct->info) || ctype_isrefarray(ct->info))) {
884
} else if (tref_isnil(tr)) {
885
tr = lj_ir_kptr(J, NULL);
886
ct = ctype_get(cts, CTID_P_VOID);
887
} else if (tref_isinteger(tr)) {
888
ct = ctype_get(cts, CTID_INT32);
889
} else if (!tref_isnum(tr)) {
898
if (!(tr = crec_arith_int64(J, sp, s, (MMS)rd->data)) &&
899
!(tr = crec_arith_ptr(J, sp, s, (MMS)rd->data))) {
901
lj_trace_err(J, LJ_TRERR_BADTYPE);
903
/* Fixup cdata comparisons, too. Avoids some cdata escapes. */
904
if (J->postproc == LJ_POST_FIXGUARD && frame_iscont(J->L->base-1)) {
905
const BCIns *pc = frame_contpc(J->L->base-1) - 1;
906
if (bc_op(*pc) <= BC_ISNEP) {
907
setframe_pc(&J2G(J)->tmptv, pc);
908
J2G(J)->tmptv.u32.lo = ((tref_istrue(tr) ^ bc_op(*pc)) & 1);
909
J->postproc = LJ_POST_FIXCOMP;
916
/* -- C library namespace metamethods ------------------------------------- */
918
void LJ_FASTCALL recff_clib_index(jit_State *J, RecordFFData *rd)
920
CTState *cts = ctype_ctsG(J2G(J));
921
if (tref_isudata(J->base[0]) && tref_isstr(J->base[1]) &&
922
udataV(&rd->argv[0])->udtype == UDTYPE_FFI_CLIB) {
923
CLibrary *cl = (CLibrary *)uddata(udataV(&rd->argv[0]));
924
GCstr *name = strV(&rd->argv[1]);
926
CTypeID id = lj_ctype_getname(cts, &ct, name, CLNS_INDEX);
927
cTValue *tv = lj_tab_getstr(cl->cache, name);
928
if (id && tv && tviscdata(tv)) {
929
/* Specialize to the symbol name and make the result a constant. */
930
emitir(IRTG(IR_EQ, IRT_STR), J->base[1], lj_ir_kstr(J, name));
931
if (ctype_isconstval(ct->info)) {
932
if (ct->size >= 0x80000000u &&
933
(ctype_child(cts, ct)->info & CTF_UNSIGNED))
934
J->base[0] = lj_ir_knum(J, (lua_Number)(uint32_t)ct->size);
936
J->base[0] = lj_ir_kint(J, (int32_t)ct->size);
937
} else if (ctype_isextern(ct->info)) {
938
lj_trace_err(J, LJ_TRERR_BADTYPE); /* NYI: access extern variables. */
940
J->base[0] = lj_ir_kgc(J, obj2gco(cdataV(tv)), IRT_CDATA);
943
lj_trace_err(J, LJ_TRERR_NOCACHE);
945
} /* else: interpreter will throw. */
948
/* -- FFI library functions ----------------------------------------------- */
950
static TRef crec_toint(jit_State *J, CTState *cts, TRef sp, TValue *sval)
952
return crec_ct_tv(J, ctype_get(cts, CTID_INT32), 0, sp, sval);
955
void LJ_FASTCALL recff_ffi_new(jit_State *J, RecordFFData *rd)
957
crec_alloc(J, rd, argv2ctype(J, J->base[0], &rd->argv[0]));
960
void LJ_FASTCALL recff_ffi_string(jit_State *J, RecordFFData *rd)
962
CTState *cts = ctype_ctsG(J2G(J));
963
TRef tr = J->base[0];
965
TRef trlen = J->base[1];
967
trlen = crec_toint(J, cts, trlen, &rd->argv[1]);
968
tr = crec_ct_tv(J, ctype_get(cts, CTID_P_CVOID), 0, tr, &rd->argv[0]);
970
tr = crec_ct_tv(J, ctype_get(cts, CTID_P_CCHAR), 0, tr, &rd->argv[0]);
971
trlen = lj_ir_call(J, IRCALL_strlen, tr);
973
J->base[0] = emitir(IRT(IR_SNEW, IRT_STR), tr, trlen);
974
} /* else: interpreter will throw. */
977
void LJ_FASTCALL recff_ffi_copy(jit_State *J, RecordFFData *rd)
979
CTState *cts = ctype_ctsG(J2G(J));
980
TRef trdst = J->base[0], trsrc = J->base[1], trlen = J->base[2];
981
if (trdst && trsrc && (trlen || tref_isstr(trsrc))) {
982
trdst = crec_ct_tv(J, ctype_get(cts, CTID_P_VOID), 0, trdst, &rd->argv[0]);
983
trsrc = crec_ct_tv(J, ctype_get(cts, CTID_P_CVOID), 0, trsrc, &rd->argv[1]);
985
trlen = crec_toint(J, cts, trlen, &rd->argv[2]);
987
trlen = emitir(IRTI(IR_FLOAD), trsrc, IRFL_STR_LEN);
988
trlen = emitir(IRTI(IR_ADD), trlen, lj_ir_kint(J, 1));
990
lj_ir_call(J, IRCALL_memcpy, trdst, trsrc, trlen);
991
emitir(IRT(IR_XBAR, IRT_NIL), 0, 0);
992
} /* else: interpreter will throw. */
995
void LJ_FASTCALL recff_ffi_fill(jit_State *J, RecordFFData *rd)
997
CTState *cts = ctype_ctsG(J2G(J));
998
TRef tr = J->base[0], trlen = J->base[1], trfill = J->base[2];
1000
tr = crec_ct_tv(J, ctype_get(cts, CTID_P_VOID), 0, tr, &rd->argv[0]);
1001
trlen = crec_toint(J, cts, trlen, &rd->argv[1]);
1003
trfill = crec_toint(J, cts, trfill, &rd->argv[2]);
1005
trfill = lj_ir_kint(J, 0);
1006
lj_ir_call(J, IRCALL_memset, tr, trfill, trlen);
1007
emitir(IRT(IR_XBAR, IRT_NIL), 0, 0);
1008
} /* else: interpreter will throw. */
1011
void LJ_FASTCALL recff_ffi_abi(jit_State *J, RecordFFData *rd)
1013
if (tref_isstr(J->base[0])) {
1014
/* Specialize to the ABI string to make the boolean result a constant. */
1015
emitir(IRTG(IR_EQ, IRT_STR), J->base[0], lj_ir_kstr(J, strV(&rd->argv[0])));
1016
J->postproc = LJ_POST_FIXBOOL;
1017
J->base[0] = TREF_TRUE;
1018
} /* else: interpreter will throw. */
1021
/* -- Miscellaneous library functions ------------------------------------- */
1023
void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd)
1025
CTState *cts = ctype_ctsG(J2G(J));
1026
IRType st = crec_ct2irt(ctype_raw(cts, cdataV(&rd->argv[0])->typeid));
1027
CTypeID did = (st >= IRT_I8 && st <= IRT_INT) ? CTID_INT32 : CTID_DOUBLE;
1028
CType *d = ctype_get(cts, did);
1029
J->base[0] = crec_ct_tv(J, d, 0, J->base[0], &rd->argv[0]);