• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tarantool / luajit / 5926974017

21 Aug 2023 01:32PM UTC coverage: 87.828% (+0.03%) from 87.797%
5926974017

push

github

fckxorg
sysprof: improve parser's memory footprint

This patch reduces sysprof's parser memory footprint,
by avoiding reading all callchains before collapsing them.
Instead of it, parser merges stacks immediately after
reading them and stores counts in a Lua table.

The `collapse.lua` module is purged as a result of the
patch, but it is left as a stub to keep the integrational
testing intact. This stub should be removed in the next
series.

Resolves tarantool/tarantool#8700

5339 of 6002 branches covered (88.95%)

Branch coverage included in aggregate %.

20493 of 23410 relevant lines covered (87.54%)

869698.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.22
/src/lj_crecord.c
1
/*
2
** Trace recorder for C data operations.
3
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
4
*/
5

6
#define lj_ffrecord_c
7
#define LUA_CORE
8

9
#include "lj_obj.h"
10

11
#if LJ_HASJIT && LJ_HASFFI
12

13
#include "lj_err.h"
14
#include "lj_tab.h"
15
#include "lj_frame.h"
16
#include "lj_ctype.h"
17
#include "lj_cdata.h"
18
#include "lj_cparse.h"
19
#include "lj_cconv.h"
20
#include "lj_carith.h"
21
#include "lj_clib.h"
22
#include "lj_ccall.h"
23
#include "lj_ff.h"
24
#include "lj_ir.h"
25
#include "lj_jit.h"
26
#include "lj_ircall.h"
27
#include "lj_iropt.h"
28
#include "lj_trace.h"
29
#include "lj_record.h"
30
#include "lj_ffrecord.h"
31
#include "lj_snap.h"
32
#include "lj_crecord.h"
33
#include "lj_dispatch.h"
34
#include "lj_strfmt.h"
35

36
/* Some local macros to save typing. Undef'd at the end. */
37
#define IR(ref)                        (&J->cur.ir[(ref)])
38

39
/* Pass IR on to next optimization in chain (FOLD). */
40
#define emitir(ot, a, b)        (lj_ir_set(J, (ot), (a), (b)), lj_opt_fold(J))
41

42
#define emitconv(a, dt, st, flags) \
43
  emitir(IRT(IR_CONV, (dt)), (a), (st)|((dt) << 5)|(flags))
44

45
/* -- C type checks ------------------------------------------------------- */
46

47
static GCcdata *argv2cdata(jit_State *J, TRef tr, cTValue *o)
48
{
49
  GCcdata *cd;
50
  TRef trtypeid;
51
  if (!tref_iscdata(tr))
52
    lj_trace_err(J, LJ_TRERR_BADTYPE);
53
  cd = cdataV(o);
54
  /* Specialize to the CTypeID. */
55
  trtypeid = emitir(IRT(IR_FLOAD, IRT_U16), tr, IRFL_CDATA_CTYPEID);
56
  emitir(IRTG(IR_EQ, IRT_INT), trtypeid, lj_ir_kint(J, (int32_t)cd->ctypeid));
57
  return cd;
58
}
59

60
/* Specialize to the CTypeID held by a cdata constructor. */
61
static CTypeID crec_constructor(jit_State *J, GCcdata *cd, TRef tr)
28✔
62
{
63
  CTypeID id;
28✔
64
  lua_assert(tref_iscdata(tr) && cd->ctypeid == CTID_CTYPEID);
28✔
65
  id = *(CTypeID *)cdataptr(cd);
28✔
66
  tr = emitir(IRT(IR_FLOAD, IRT_INT), tr, IRFL_CDATA_INT);
28✔
67
  emitir(IRTG(IR_EQ, IRT_INT), tr, lj_ir_kint(J, (int32_t)id));
28✔
68
  return id;
28✔
69
}
70

71
static CTypeID argv2ctype(jit_State *J, TRef tr, cTValue *o)
156✔
72
{
73
  if (tref_isstr(tr)) {
156✔
74
    GCstr *s = strV(o);
145✔
75
    CPState cp;
145✔
76
    CTypeID oldtop;
145✔
77
    /* Specialize to the string containing the C type declaration. */
78
    emitir(IRTG(IR_EQ, IRT_STR), tr, lj_ir_kstr(J, s));
145✔
79
    cp.L = J->L;
145✔
80
    cp.cts = ctype_ctsG(J2G(J));
145✔
81
    oldtop = cp.cts->top;
145✔
82
    cp.srcname = strdata(s);
145✔
83
    cp.p = strdata(s);
145✔
84
    cp.param = NULL;
145✔
85
    cp.mode = CPARSE_MODE_ABSTRACT|CPARSE_MODE_NOIMPLICIT;
145✔
86
    if (lj_cparse(&cp) || cp.cts->top > oldtop)  /* Avoid new struct defs. */
145✔
87
      lj_trace_err(J, LJ_TRERR_BADTYPE);
×
88
    return cp.val.id;
145✔
89
  } else {
90
    GCcdata *cd = argv2cdata(J, tr, o);
11✔
91
    return cd->ctypeid == CTID_CTYPEID ? crec_constructor(J, cd, tr) :
11✔
92
                                        cd->ctypeid;
93
  }
94
}
95

96
/* Convert CType to IRType (if possible). */
97
static IRType crec_ct2irt(CTState *cts, CType *ct)
98
{
99
  if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct);
100
  if (LJ_LIKELY(ctype_isnum(ct->info))) {
101
    if ((ct->info & CTF_FP)) {
102
      if (ct->size == sizeof(double))
103
        return IRT_NUM;
104
      else if (ct->size == sizeof(float))
105
        return IRT_FLOAT;
106
    } else {
107
      uint32_t b = lj_fls(ct->size);
108
      if (b <= 3)
109
        return IRT_I8 + 2*b + ((ct->info & CTF_UNSIGNED) ? 1 : 0);
110
    }
111
  } else if (ctype_isptr(ct->info)) {
112
    return (LJ_64 && ct->size == 8) ? IRT_P64 : IRT_P32;
113
  } else if (ctype_iscomplex(ct->info)) {
114
    if (ct->size == 2*sizeof(double))
115
      return IRT_NUM;
116
    else if (ct->size == 2*sizeof(float))
117
      return IRT_FLOAT;
118
  }
119
  return IRT_CDATA;
120
}
121

122
/* -- Optimized memory fill and copy -------------------------------------- */
123

124
/* Maximum length and unroll of inlined copy/fill. */
125
#define CREC_COPY_MAXUNROLL                16
126
#define CREC_COPY_MAXLEN                128
127

128
#define CREC_FILL_MAXUNROLL                16
129

130
/* Number of windowed registers used for optimized memory copy. */
131
#if LJ_TARGET_X86
132
#define CREC_COPY_REGWIN                2
133
#elif LJ_TARGET_PPC || LJ_TARGET_MIPS
134
#define CREC_COPY_REGWIN                8
135
#else
136
#define CREC_COPY_REGWIN                4
137
#endif
138

139
/* List of memory offsets for copy/fill. */
140
typedef struct CRecMemList {
141
  CTSize ofs;                /* Offset in bytes. */
142
  IRType tp;                /* Type of load/store. */
143
  TRef trofs;                /* TRef of interned offset. */
144
  TRef trval;                /* TRef of load value. */
145
} CRecMemList;
146

147
/* Generate copy list for element-wise struct copy. */
148
static MSize crec_copy_struct(CRecMemList *ml, CTState *cts, CType *ct)
149
{
150
  CTypeID fid = ct->sib;
151
  MSize mlp = 0;
152
  while (fid) {
153
    CType *df = ctype_get(cts, fid);
154
    fid = df->sib;
155
    if (ctype_isfield(df->info)) {
156
      CType *cct;
157
      IRType tp;
158
      if (!gcref(df->name)) continue;  /* Ignore unnamed fields. */
159
      cct = ctype_rawchild(cts, df);  /* Field type. */
160
      tp = crec_ct2irt(cts, cct);
161
      if (tp == IRT_CDATA) return 0;  /* NYI: aggregates. */
162
      if (mlp >= CREC_COPY_MAXUNROLL) return 0;
163
      ml[mlp].ofs = df->size;
164
      ml[mlp].tp = tp;
165
      mlp++;
166
      if (ctype_iscomplex(cct->info)) {
167
        if (mlp >= CREC_COPY_MAXUNROLL) return 0;
168
        ml[mlp].ofs = df->size + (cct->size >> 1);
169
        ml[mlp].tp = tp;
170
        mlp++;
171
      }
172
    } else if (!ctype_isconstval(df->info)) {
173
      /* NYI: bitfields and sub-structures. */
174
      return 0;
175
    }
176
  }
177
  return mlp;
178
}
179

180
/* Generate unrolled copy list, from highest to lowest step size/alignment. */
181
static MSize crec_copy_unroll(CRecMemList *ml, CTSize len, CTSize step,
7✔
182
                              IRType tp)
183
{
184
  CTSize ofs = 0;
7✔
185
  MSize mlp = 0;
7✔
186
  if (tp == IRT_CDATA) tp = IRT_U8 + 2*lj_fls(step);
5✔
187
  do {
188
    while (ofs + step <= len) {
38✔
189
      if (mlp >= CREC_COPY_MAXUNROLL) return 0;
25✔
190
      ml[mlp].ofs = ofs;
25✔
191
      ml[mlp].tp = tp;
25✔
192
      mlp++;
25✔
193
      ofs += step;
25✔
194
    }
195
    step >>= 1;
13✔
196
    tp -= 2;
13✔
197
  } while (ofs < len);
13✔
198
  return mlp;
199
}
200

201
/*
202
** Emit copy list with windowed loads/stores.
203
** LJ_TARGET_UNALIGNED: may emit unaligned loads/stores (not marked as such).
204
*/
205
static void crec_copy_emit(jit_State *J, CRecMemList *ml, MSize mlp,
9✔
206
                           TRef trdst, TRef trsrc)
207
{
208
  MSize i, j, rwin = 0;
9✔
209
  for (i = 0, j = 0; i < mlp; ) {
40✔
210
    TRef trofs = lj_ir_kintp(J, ml[i].ofs);
31✔
211
    TRef trsptr = emitir(IRT(IR_ADD, IRT_PTR), trsrc, trofs);
31✔
212
    ml[i].trval = emitir(IRT(IR_XLOAD, ml[i].tp), trsptr, 0);
31✔
213
    ml[i].trofs = trofs;
31✔
214
    i++;
31✔
215
    rwin += (LJ_SOFTFP && ml[i].tp == IRT_NUM) ? 2 : 1;
31✔
216
    if (rwin >= CREC_COPY_REGWIN || i >= mlp) {  /* Flush buffered stores. */
31✔
217
      rwin = 0;
44✔
218
      for ( ; j < i; j++) {
44✔
219
        TRef trdptr = emitir(IRT(IR_ADD, IRT_PTR), trdst, ml[j].trofs);
31✔
220
        emitir(IRT(IR_XSTORE, ml[j].tp), trdptr, ml[j].trval);
31✔
221
      }
222
    }
223
  }
224
}
9✔
225

226
/* Optimized memory copy. */
227
static void crec_copy(jit_State *J, TRef trdst, TRef trsrc, TRef trlen,
9✔
228
                      CType *ct)
229
{
230
  if (tref_isk(trlen)) {  /* Length must be constant. */
9✔
231
    CRecMemList ml[CREC_COPY_MAXUNROLL];
9✔
232
    MSize mlp = 0;
9✔
233
    CTSize step = 1, len = (CTSize)IR(tref_ref(trlen))->i;
9✔
234
    IRType tp = IRT_CDATA;
9✔
235
    int needxbar = 0;
9✔
236
    if (len == 0) return;  /* Shortcut. */
18✔
237
    if (len > CREC_COPY_MAXLEN) goto fallback;
9✔
238
    if (ct) {
9✔
239
      CTState *cts = ctype_ctsG(J2G(J));
4✔
240
      lua_assert(ctype_isarray(ct->info) || ctype_isstruct(ct->info));
4✔
241
      if (ctype_isarray(ct->info)) {
4✔
242
        CType *cct = ctype_rawchild(cts, ct);
2✔
243
        tp = crec_ct2irt(cts, cct);
2✔
244
        if (tp == IRT_CDATA) goto rawcopy;
2✔
245
        step = lj_ir_type_size[tp];
2✔
246
        lua_assert((len & (step-1)) == 0);
2✔
247
      } else if ((ct->info & CTF_UNION)) {
2✔
248
        step = (1u << ctype_align(ct->info));
×
249
        goto rawcopy;
×
250
      } else {
251
        mlp = crec_copy_struct(ml, cts, ct);
2✔
252
        goto emitcopy;
2✔
253
      }
254
    } else {
255
    rawcopy:
5✔
256
      needxbar = 1;
257
      if (LJ_TARGET_UNALIGNED || step >= CTSIZE_PTR)
258
        step = CTSIZE_PTR;
259
    }
260
    mlp = crec_copy_unroll(ml, len, step, tp);
7✔
261
  emitcopy:
9✔
262
    if (mlp) {
9✔
263
      crec_copy_emit(J, ml, mlp, trdst, trsrc);
9✔
264
      if (needxbar)
9✔
265
        emitir(IRT(IR_XBAR, IRT_NIL), 0, 0);
5✔
266
      return;
9✔
267
    }
268
  }
269
fallback:
×
270
  /* Call memcpy. Always needs a barrier to disable alias analysis. */
271
  lj_ir_call(J, IRCALL_memcpy, trdst, trsrc, trlen);
×
272
  emitir(IRT(IR_XBAR, IRT_NIL), 0, 0);
×
273
}
274

275
/* Generate unrolled fill list, from highest to lowest step size/alignment. */
276
static MSize crec_fill_unroll(CRecMemList *ml, CTSize len, CTSize step)
277
{
278
  CTSize ofs = 0;
279
  MSize mlp = 0;
280
  IRType tp = IRT_U8 + 2*lj_fls(step);
281
  do {
282
    while (ofs + step <= len) {
283
      if (mlp >= CREC_COPY_MAXUNROLL) return 0;
284
      ml[mlp].ofs = ofs;
285
      ml[mlp].tp = tp;
286
      mlp++;
287
      ofs += step;
288
    }
289
    step >>= 1;
290
    tp -= 2;
291
  } while (ofs < len);
292
  return mlp;
293
}
294

295
/*
296
** Emit stores for fill list.
297
** LJ_TARGET_UNALIGNED: may emit unaligned stores (not marked as such).
298
*/
299
static void crec_fill_emit(jit_State *J, CRecMemList *ml, MSize mlp,
4✔
300
                           TRef trdst, TRef trfill)
301
{
302
  MSize i;
4✔
303
  for (i = 0; i < mlp; i++) {
16✔
304
    TRef trofs = lj_ir_kintp(J, ml[i].ofs);
12✔
305
    TRef trdptr = emitir(IRT(IR_ADD, IRT_PTR), trdst, trofs);
12✔
306
    emitir(IRT(IR_XSTORE, ml[i].tp), trdptr, trfill);
12✔
307
  }
308
}
4✔
309

310
/* Optimized memory fill. */
311
static void crec_fill(jit_State *J, TRef trdst, TRef trlen, TRef trfill,
312
                      CTSize step)
313
{
314
  if (tref_isk(trlen)) {  /* Length must be constant. */
315
    CRecMemList ml[CREC_FILL_MAXUNROLL];
316
    MSize mlp;
317
    CTSize len = (CTSize)IR(tref_ref(trlen))->i;
318
    if (len == 0) return;  /* Shortcut. */
319
    if (LJ_TARGET_UNALIGNED || step >= CTSIZE_PTR)
320
      step = CTSIZE_PTR;
321
    if (step * CREC_FILL_MAXUNROLL < len) goto fallback;
322
    mlp = crec_fill_unroll(ml, len, step);
323
    if (!mlp) goto fallback;
324
    if (tref_isk(trfill) || ml[0].tp != IRT_U8)
325
      trfill = emitconv(trfill, IRT_INT, IRT_U8, 0);
326
    if (ml[0].tp != IRT_U8) {  /* Scatter U8 to U16/U32/U64. */
327
      if (CTSIZE_PTR == 8 && ml[0].tp == IRT_U64) {
328
        if (tref_isk(trfill))  /* Pointless on x64 with zero-extended regs. */
329
          trfill = emitconv(trfill, IRT_U64, IRT_U32, 0);
330
        trfill = emitir(IRT(IR_MUL, IRT_U64), trfill,
331
                        lj_ir_kint64(J, U64x(01010101,01010101)));
332
      } else {
333
        trfill = emitir(IRTI(IR_MUL), trfill,
334
                   lj_ir_kint(J, ml[0].tp == IRT_U16 ? 0x0101 : 0x01010101));
335
      }
336
    }
337
    crec_fill_emit(J, ml, mlp, trdst, trfill);
338
  } else {
339
fallback:
340
    /* Call memset. Always needs a barrier to disable alias analysis. */
341
    lj_ir_call(J, IRCALL_memset, trdst, trfill, trlen);  /* Note: arg order! */
342
  }
343
  emitir(IRT(IR_XBAR, IRT_NIL), 0, 0);
344
}
345

346
/* -- Convert C type to C type -------------------------------------------- */
347

348
/*
349
** This code mirrors the code in lj_cconv.c. It performs the same steps
350
** for the trace recorder that lj_cconv.c does for the interpreter.
351
**
352
** One major difference is that we can get away with much fewer checks
353
** here. E.g. checks for casts, constness or correct types can often be
354
** omitted, even if they might fail. The interpreter subsequently throws
355
** an error, which aborts the trace.
356
**
357
** All operations are specialized to their C types, so the on-trace
358
** outcome must be the same as the outcome in the interpreter. If the
359
** interpreter doesn't throw an error, then the trace is correct, too.
360
** Care must be taken not to generate invalid (temporary) IR or to
361
** trigger asserts.
362
*/
363

364
/* Determine whether a passed number or cdata number is non-zero. */
365
static int crec_isnonzero(CType *s, void *p)
366
{
367
  if (p == (void *)0)
368
    return 0;
369
  if (p == (void *)1)
370
    return 1;
371
  if ((s->info & CTF_FP)) {
372
    if (s->size == sizeof(float))
373
      return (*(float *)p != 0);
374
    else
375
      return (*(double *)p != 0);
376
  } else {
377
    if (s->size == 1)
378
      return (*(uint8_t *)p != 0);
379
    else if (s->size == 2)
380
      return (*(uint16_t *)p != 0);
381
    else if (s->size == 4)
382
      return (*(uint32_t *)p != 0);
383
    else
384
      return (*(uint64_t *)p != 0);
385
  }
386
}
387

388
static TRef crec_ct_ct(jit_State *J, CType *d, CType *s, TRef dp, TRef sp,
437✔
389
                       void *svisnz)
390
{
391
  IRType dt = crec_ct2irt(ctype_ctsG(J2G(J)), d);
437✔
392
  IRType st = crec_ct2irt(ctype_ctsG(J2G(J)), s);
437✔
393
  CTSize dsize = d->size, ssize = s->size;
437✔
394
  CTInfo dinfo = d->info, sinfo = s->info;
437✔
395

396
  if (ctype_type(dinfo) > CT_MAYCONVERT || ctype_type(sinfo) > CT_MAYCONVERT)
437✔
397
    goto err_conv;
×
398

399
  /*
400
  ** Note: Unlike lj_cconv_ct_ct(), sp holds the _value_ of pointers and
401
  ** numbers up to 8 bytes. Otherwise sp holds a pointer.
402
  */
403

404
  switch (cconv_idx2(dinfo, sinfo)) {
437✔
405
  /* Destination is a bool. */
406
  case CCX(B, B):
×
407
    goto xstore;  /* Source operand is already normalized. */
×
408
  case CCX(B, I):
×
409
  case CCX(B, F):
410
    if (st != IRT_CDATA) {
×
411
      /* Specialize to the result of a comparison against 0. */
412
      TRef zero = (st == IRT_NUM  || st == IRT_FLOAT) ? lj_ir_knum(J, 0) :
×
413
                  (st == IRT_I64 || st == IRT_U64) ? lj_ir_kint64(J, 0) :
×
414
                  lj_ir_kint(J, 0);
×
415
      int isnz = crec_isnonzero(s, svisnz);
×
416
      emitir(IRTG(isnz ? IR_NE : IR_EQ, st), sp, zero);
×
417
      sp = lj_ir_kint(J, isnz);
×
418
      goto xstore;
×
419
    }
420
    goto err_nyi;
×
421

422
  /* Destination is an integer. */
423
  case CCX(I, B):
424
  case CCX(I, I):
425
  conv_I_I:
318✔
426
    if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi;
318✔
427
    /* Extend 32 to 64 bit integer. */
428
    if (dsize == 8 && ssize < 8 && !(LJ_64 && (sinfo & CTF_UNSIGNED)))
318✔
429
      sp = emitconv(sp, dt, ssize < 4 ? IRT_INT : st,
66✔
430
                    (sinfo & CTF_UNSIGNED) ? 0 : IRCONV_SEXT);
431
    else if (dsize < 8 && ssize == 8)  /* Truncate from 64 bit integer. */
285✔
432
      sp = emitconv(sp, dsize < 4 ? IRT_INT : dt, st, 0);
1✔
433
    else if (st == IRT_INT)
284✔
434
      sp = lj_opt_narrow_toint(J, sp);
207✔
435
  xstore:
77✔
436
    if (dt == IRT_I64 || dt == IRT_U64) lj_needsplit(J);
428✔
437
    if (dp == 0) return sp;
428✔
438
    emitir(IRT(IR_XSTORE, dt), dp, sp);
131✔
439
    break;
131✔
440
  case CCX(I, C):
×
441
    sp = emitir(IRT(IR_XLOAD, st), sp, 0);  /* Load re. */
×
442
    /* fallthrough */
443
  case CCX(I, F):
8✔
444
    if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi;
8✔
445
    sp = emitconv(sp, dsize < 4 ? IRT_INT : dt, st, IRCONV_ANY);
8✔
446
    goto xstore;
8✔
447
  case CCX(I, P):
×
448
  case CCX(I, A):
449
    sinfo = CTINFO(CT_NUM, CTF_UNSIGNED);
×
450
    ssize = CTSIZE_PTR;
×
451
    st = IRT_UINTP;
×
452
    if (((dsize ^ ssize) & 8) == 0) {  /* Must insert no-op type conversion. */
×
453
      sp = emitconv(sp, dsize < 4 ? IRT_INT : dt, IRT_PTR, 0);
×
454
      goto xstore;
×
455
    }
456
    goto conv_I_I;
×
457

458
  /* Destination is a floating-point number. */
459
  case CCX(F, B):
460
  case CCX(F, I):
461
  conv_F_I:
36✔
462
    if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi;
36✔
463
    sp = emitconv(sp, dt, ssize < 4 ? IRT_INT : st, 0);
72✔
464
    goto xstore;
36✔
465
  case CCX(F, C):
×
466
    sp = emitir(IRT(IR_XLOAD, st), sp, 0);  /* Load re. */
×
467
    /* fallthrough */
468
  case CCX(F, F):
469
  conv_F_F:
11✔
470
    if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi;
11✔
471
    if (dt != st) sp = emitconv(sp, dt, st, 0);
11✔
472
    goto xstore;
11✔
473

474
  /* Destination is a complex number. */
475
  case CCX(C, I):
2✔
476
  case CCX(C, F):
477
    {  /* Clear im. */
478
      TRef ptr = emitir(IRT(IR_ADD, IRT_PTR), dp, lj_ir_kintp(J, (dsize >> 1)));
2✔
479
      emitir(IRT(IR_XSTORE, dt), ptr, lj_ir_knum(J, 0));
2✔
480
    }
481
    /* Convert to re. */
482
    if ((sinfo & CTF_FP)) goto conv_F_F; else goto conv_F_I;
2✔
483

484
  case CCX(C, C):
5✔
485
    if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi;
5✔
486
    {
487
      TRef re, im, ptr;
5✔
488
      re = emitir(IRT(IR_XLOAD, st), sp, 0);
5✔
489
      ptr = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, (ssize >> 1)));
5✔
490
      im = emitir(IRT(IR_XLOAD, st), ptr, 0);
5✔
491
      if (dt != st) {
5✔
492
        re = emitconv(re, dt, st, 0);
2✔
493
        im = emitconv(im, dt, st, 0);
2✔
494
      }
495
      emitir(IRT(IR_XSTORE, dt), dp, re);
5✔
496
      ptr = emitir(IRT(IR_ADD, IRT_PTR), dp, lj_ir_kintp(J, (dsize >> 1)));
5✔
497
      emitir(IRT(IR_XSTORE, dt), ptr, im);
5✔
498
    }
499
    break;
5✔
500

501
  /* Destination is a vector. */
502
  case CCX(V, I):
×
503
  case CCX(V, F):
504
  case CCX(V, C):
505
  case CCX(V, V):
506
    goto err_nyi;
×
507

508
  /* Destination is a pointer. */
509
  case CCX(P, P):
53✔
510
  case CCX(P, A):
511
  case CCX(P, S):
512
    /* There are only 32 bit pointers/addresses on 32 bit machines.
513
    ** Also ok on x64, since all 32 bit ops clear the upper part of the reg.
514
    */
515
    goto xstore;
53✔
516
  case CCX(P, I):
1✔
517
    if (st == IRT_CDATA) goto err_nyi;
1✔
518
    if (!LJ_64 && ssize == 8)  /* Truncate from 64 bit integer. */
1✔
519
      sp = emitconv(sp, IRT_U32, st, 0);
520
    goto xstore;
1✔
521
  case CCX(P, F):
1✔
522
    if (st == IRT_CDATA) goto err_nyi;
1✔
523
    /* The signed conversion is cheaper. x64 really has 47 bit pointers. */
524
    sp = emitconv(sp, (LJ_64 && dsize == 8) ? IRT_I64 : IRT_U32,
1✔
525
                  st, IRCONV_ANY);
526
    goto xstore;
1✔
527

528
  /* Destination is an array. */
529
  case CCX(A, A):
4✔
530
  /* Destination is a struct/union. */
531
  case CCX(S, S):
532
    if (dp == 0) goto err_conv;
4✔
533
    crec_copy(J, dp, sp, lj_ir_kint(J, dsize), d);
4✔
534
    break;
4✔
535

536
  default:
537
  err_conv:
×
538
  err_nyi:
×
539
    lj_trace_err(J, LJ_TRERR_NYICONV);
×
540
    break;
541
  }
542
  return 0;
543
}
544

545
/* -- Convert C type to TValue (load) ------------------------------------- */
546

547
static TRef crec_tv_ct(jit_State *J, CType *s, CTypeID sid, TRef sp)
217✔
548
{
549
  CTState *cts = ctype_ctsG(J2G(J));
217✔
550
  IRType t = crec_ct2irt(cts, s);
217✔
551
  CTInfo sinfo = s->info;
217✔
552
  if (ctype_isnum(sinfo)) {
217✔
553
    TRef tr;
171✔
554
    if (t == IRT_CDATA)
171✔
555
      goto err_nyi;  /* NYI: copyval of >64 bit integers. */
×
556
    tr = emitir(IRT(IR_XLOAD, t), sp, 0);
171✔
557
    if (t == IRT_FLOAT || t == IRT_U32) {  /* Keep uint32_t/float as numbers. */
171✔
558
      return emitconv(tr, IRT_NUM, t, 0);
14✔
559
    } else if (t == IRT_I64 || t == IRT_U64) {  /* Box 64 bit integer. */
157✔
560
      sp = tr;
561
      lj_needsplit(J);
562
    } else if ((sinfo & CTF_BOOL)) {
136✔
563
      /* Assume not equal to zero. Fixup and emit pending guard later. */
564
      lj_ir_set(J, IRTGI(IR_NE), tr, lj_ir_kint(J, 0));
×
565
      J->postproc = LJ_POST_FIXGUARD;
×
566
      return TREF_TRUE;
×
567
    } else {
568
      return tr;
569
    }
570
  } else if (ctype_isptr(sinfo) || ctype_isenum(sinfo)) {
46✔
571
    sp = emitir(IRT(IR_XLOAD, t), sp, 0);  /* Box pointers and enums. */
3✔
572
  } else if (ctype_isrefarray(sinfo) || ctype_isstruct(sinfo)) {
43✔
573
    cts->L = J->L;
30✔
574
    sid = lj_ctype_intern(cts, CTINFO_REF(sid), CTSIZE_PTR);  /* Create ref. */
30✔
575
  } else if (ctype_iscomplex(sinfo)) {  /* Unbox/box complex. */
13✔
576
    ptrdiff_t esz = (ptrdiff_t)(s->size >> 1);
13✔
577
    TRef ptr, tr1, tr2, dp;
13✔
578
    dp = emitir(IRTG(IR_CNEW, IRT_CDATA), lj_ir_kint(J, sid), TREF_NIL);
13✔
579
    tr1 = emitir(IRT(IR_XLOAD, t), sp, 0);
13✔
580
    ptr = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, esz));
13✔
581
    tr2 = emitir(IRT(IR_XLOAD, t), ptr, 0);
13✔
582
    ptr = emitir(IRT(IR_ADD, IRT_PTR), dp, lj_ir_kintp(J, sizeof(GCcdata)));
13✔
583
    emitir(IRT(IR_XSTORE, t), ptr, tr1);
13✔
584
    ptr = emitir(IRT(IR_ADD, IRT_PTR), dp, lj_ir_kintp(J, sizeof(GCcdata)+esz));
13✔
585
    emitir(IRT(IR_XSTORE, t), ptr, tr2);
13✔
586
    return dp;
13✔
587
  } else {
588
    /* NYI: copyval of vectors. */
589
  err_nyi:
×
590
    lj_trace_err(J, LJ_TRERR_NYICONV);
×
591
  }
592
  /* Box pointer, ref, enum or 64 bit integer. */
593
  return emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, sid), sp);
54✔
594
}
595

596
/* -- Convert TValue to C type (store) ------------------------------------ */
597

598
static TRef crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, cTValue *sval)
437✔
599
{
600
  CTState *cts = ctype_ctsG(J2G(J));
437✔
601
  CTypeID sid = CTID_P_VOID;
437✔
602
  void *svisnz = 0;
437✔
603
  CType *s;
437✔
604
  if (LJ_LIKELY(tref_isinteger(sp))) {
437✔
605
    sid = CTID_INT32;
262✔
606
    svisnz = (void *)(intptr_t)(tvisint(sval)?(intV(sval)!=0):!tviszero(sval));
262✔
607
  } else if (tref_isnum(sp)) {
175✔
608
    sid = CTID_DOUBLE;
20✔
609
    svisnz = (void *)(intptr_t)(tvisint(sval)?(intV(sval)!=0):!tviszero(sval));
20✔
610
  } else if (tref_isbool(sp)) {
155✔
611
    sp = lj_ir_kint(J, tref_istrue(sp) ? 1 : 0);
×
612
    sid = CTID_BOOL;
×
613
  } else if (tref_isnil(sp)) {
155✔
614
    sp = lj_ir_kptr(J, NULL);
4✔
615
  } else if (tref_isudata(sp)) {
151✔
616
    GCudata *ud = udataV(sval);
4✔
617
    if (ud->udtype == UDTYPE_IO_FILE) {
4✔
618
      TRef tr = emitir(IRT(IR_FLOAD, IRT_U8), sp, IRFL_UDATA_UDTYPE);
×
619
      emitir(IRTGI(IR_EQ), tr, lj_ir_kint(J, UDTYPE_IO_FILE));
×
620
      sp = emitir(IRT(IR_FLOAD, IRT_PTR), sp, IRFL_UDATA_FILE);
×
621
    } else {
622
      sp = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, sizeof(GCudata)));
4✔
623
    }
624
  } else if (tref_isstr(sp)) {
147✔
625
    if (ctype_isenum(d->info)) {  /* Match string against enum constant. */
4✔
626
      GCstr *str = strV(sval);
×
627
      CTSize ofs;
×
628
      CType *cct = lj_ctype_getfield(cts, d, str, &ofs);
×
629
      /* Specialize to the name of the enum constant. */
630
      emitir(IRTG(IR_EQ, IRT_STR), sp, lj_ir_kstr(J, str));
×
631
      if (cct && ctype_isconstval(cct->info)) {
×
632
        lua_assert(ctype_child(cts, cct)->size == 4);
×
633
        svisnz = (void *)(intptr_t)(ofs != 0);
×
634
        sp = lj_ir_kint(J, (int32_t)ofs);
×
635
        sid = ctype_cid(cct->info);
×
636
      }  /* else: interpreter will throw. */
637
    } else if (ctype_isrefarray(d->info)) {  /* Copy string to array. */
4✔
638
      lj_trace_err(J, LJ_TRERR_BADTYPE);  /* NYI */
×
639
    } else {  /* Otherwise pass the string data as a const char[]. */
640
      /* Don't use STRREF. It folds with SNEW, which loses the trailing NUL. */
641
      sp = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, sizeof(GCstr)));
4✔
642
      sid = CTID_A_CCHAR;
4✔
643
    }
644
  } else if (tref_islightud(sp)) {
143✔
645
#if LJ_64
646
    lj_trace_err(J, LJ_TRERR_NYICONV);
×
647
#endif
648
  } else {  /* NYI: tref_istab(sp). */
649
    IRType t;
143✔
650
    sid = argv2cdata(J, sp, sval)->ctypeid;
143✔
651
    s = ctype_raw(cts, sid);
143✔
652
    svisnz = cdataptr(cdataV(sval));
143✔
653
    if (ctype_isfunc(s->info)) {
143✔
654
      sid = lj_ctype_intern(cts, CTINFO(CT_PTR, CTALIGN_PTR|sid), CTSIZE_PTR);
×
655
      s = ctype_get(cts, sid);
×
656
      t = IRT_PTR;
×
657
    } else {
658
      t = crec_ct2irt(cts, s);
143✔
659
    }
660
    if (ctype_isptr(s->info)) {
143✔
661
      sp = emitir(IRT(IR_FLOAD, t), sp, IRFL_CDATA_PTR);
31✔
662
      if (ctype_isref(s->info)) {
31✔
663
        svisnz = *(void **)svisnz;
1✔
664
        s = ctype_rawchild(cts, s);
1✔
665
        if (ctype_isenum(s->info)) s = ctype_child(cts, s);
1✔
666
        t = crec_ct2irt(cts, s);
1✔
667
      } else {
668
        goto doconv;
30✔
669
      }
670
    } else if (t == IRT_I64 || t == IRT_U64) {
112✔
671
      sp = emitir(IRT(IR_FLOAD, t), sp, IRFL_CDATA_INT64);
93✔
672
      lj_needsplit(J);
93✔
673
      goto doconv;
93✔
674
    } else if (t == IRT_INT || t == IRT_U32) {
19✔
675
      if (ctype_isenum(s->info)) s = ctype_child(cts, s);
×
676
      sp = emitir(IRT(IR_FLOAD, t), sp, IRFL_CDATA_INT);
×
677
      goto doconv;
×
678
    } else {
679
      sp = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, sizeof(GCcdata)));
19✔
680
    }
681
    if (ctype_isnum(s->info) && t != IRT_CDATA)
20✔
682
      sp = emitir(IRT(IR_XLOAD, t), sp, 0);  /* Load number value. */
×
683
    goto doconv;
20✔
684
  }
685
  s = ctype_get(cts, sid);
294✔
686
doconv:
437✔
687
  if (ctype_isenum(d->info)) d = ctype_child(cts, d);
437✔
688
  return crec_ct_ct(J, d, s, dp, sp, svisnz);
437✔
689
}
690

691
/* -- C data metamethods -------------------------------------------------- */
692

693
/* This would be rather difficult in FOLD, so do it here:
694
** (base+k)+(idx*sz)+ofs ==> (base+idx*sz)+(ofs+k)
695
** (base+(idx+k)*sz)+ofs ==> (base+idx*sz)+(ofs+k*sz)
696
*/
697
static TRef crec_reassoc_ofs(jit_State *J, TRef tr, ptrdiff_t *ofsp, MSize sz)
698
{
699
  IRIns *ir = IR(tref_ref(tr));
700
  if (LJ_LIKELY(J->flags & JIT_F_OPT_FOLD) && irref_isk(ir->op2) &&
701
      (ir->o == IR_ADD || ir->o == IR_ADDOV || ir->o == IR_SUBOV)) {
702
    IRIns *irk = IR(ir->op2);
703
    ptrdiff_t k;
704
    if (LJ_64 && irk->o == IR_KINT64)
705
      k = (ptrdiff_t)ir_kint64(irk)->u64 * sz;
706
    else
707
      k = (ptrdiff_t)irk->i * sz;
708
    if (ir->o == IR_SUBOV) *ofsp -= k; else *ofsp += k;
709
    tr = ir->op1;  /* Not a TRef, but the caller doesn't care. */
710
  }
711
  return tr;
712
}
713

714
/* Tailcall to function. */
715
static void crec_tailcall(jit_State *J, RecordFFData *rd, cTValue *tv)
×
716
{
717
  TRef kfunc = lj_ir_kfunc(J, funcV(tv));
×
718
#if LJ_FR2
719
  J->base[-2] = kfunc;
×
720
  J->base[-1] = TREF_FRAME;
×
721
#else
722
  J->base[-1] = kfunc | TREF_FRAME;
723
#endif
724
  rd->nres = -1;  /* Pending tailcall. */
×
725
}
×
726

727
/* Record ctype __index/__newindex metamethods. */
728
static void crec_index_meta(jit_State *J, CTState *cts, CType *ct,
×
729
                            RecordFFData *rd)
730
{
731
  CTypeID id = ctype_typeid(cts, ct);
×
732
  cTValue *tv = lj_ctype_meta(cts, id, rd->data ? MM_newindex : MM_index);
×
733
  if (!tv)
×
734
    lj_trace_err(J, LJ_TRERR_BADTYPE);
×
735
  if (tvisfunc(tv)) {
×
736
    crec_tailcall(J, rd, tv);
×
737
  } else if (rd->data == 0 && tvistab(tv) && tref_isstr(J->base[1])) {
×
738
    /* Specialize to result of __index lookup. */
739
    cTValue *o = lj_tab_get(J->L, tabV(tv), &rd->argv[1]);
×
740
    J->base[0] = lj_record_constify(J, o);
×
741
    if (!J->base[0])
×
742
      lj_trace_err(J, LJ_TRERR_BADTYPE);
×
743
    /* Always specialize to the key. */
744
    emitir(IRTG(IR_EQ, IRT_STR), J->base[1], lj_ir_kstr(J, strV(&rd->argv[1])));
×
745
  } else {
746
    /* NYI: resolving of non-function metamethods. */
747
    /* NYI: non-string keys for __index table. */
748
    /* NYI: stores to __newindex table. */
749
    lj_trace_err(J, LJ_TRERR_BADTYPE);
×
750
  }
751
}
×
752

753
/* Record bitfield load/store. */
754
static void crec_index_bf(jit_State *J, RecordFFData *rd, TRef ptr, CTInfo info)
×
755
{
756
  IRType t = IRT_I8 + 2*lj_fls(ctype_bitcsz(info)) + ((info&CTF_UNSIGNED)?1:0);
×
757
  TRef tr = emitir(IRT(IR_XLOAD, t), ptr, 0);
×
758
  CTSize pos = ctype_bitpos(info), bsz = ctype_bitbsz(info), shift = 32 - bsz;
×
759
  lua_assert(t <= IRT_U32);  /* NYI: 64 bit bitfields. */
×
760
  if (rd->data == 0) {  /* __index metamethod. */
×
761
    if ((info & CTF_BOOL)) {
×
762
      tr = emitir(IRTI(IR_BAND), tr, lj_ir_kint(J, (int32_t)((1u << pos))));
×
763
      /* Assume not equal to zero. Fixup and emit pending guard later. */
764
      lj_ir_set(J, IRTGI(IR_NE), tr, lj_ir_kint(J, 0));
×
765
      J->postproc = LJ_POST_FIXGUARD;
×
766
      tr = TREF_TRUE;
×
767
    } else if (!(info & CTF_UNSIGNED)) {
×
768
      tr = emitir(IRTI(IR_BSHL), tr, lj_ir_kint(J, shift - pos));
×
769
      tr = emitir(IRTI(IR_BSAR), tr, lj_ir_kint(J, shift));
×
770
    } else {
771
      lua_assert(bsz < 32);  /* Full-size fields cannot end up here. */
×
772
      tr = emitir(IRTI(IR_BSHR), tr, lj_ir_kint(J, pos));
×
773
      tr = emitir(IRTI(IR_BAND), tr, lj_ir_kint(J, (int32_t)((1u << bsz)-1)));
×
774
      /* We can omit the U32 to NUM conversion, since bsz < 32. */
775
    }
776
    J->base[0] = tr;
×
777
  } else {  /* __newindex metamethod. */
778
    CTState *cts = ctype_ctsG(J2G(J));
×
779
    CType *ct = ctype_get(cts,
×
780
                          (info & CTF_BOOL) ? CTID_BOOL :
×
781
                          (info & CTF_UNSIGNED) ? CTID_UINT32 : CTID_INT32);
×
782
    int32_t mask = (int32_t)(((1u << bsz)-1) << pos);
×
783
    TRef sp = crec_ct_tv(J, ct, 0, J->base[2], &rd->argv[2]);
×
784
    sp = emitir(IRTI(IR_BSHL), sp, lj_ir_kint(J, pos));
×
785
    /* Use of the target type avoids forwarding conversions. */
786
    sp = emitir(IRT(IR_BAND, t), sp, lj_ir_kint(J, mask));
×
787
    tr = emitir(IRT(IR_BAND, t), tr, lj_ir_kint(J, (int32_t)~mask));
×
788
    tr = emitir(IRT(IR_BOR, t), tr, sp);
×
789
    emitir(IRT(IR_XSTORE, t), ptr, tr);
×
790
    rd->nres = 0;
×
791
    J->needsnap = 1;
×
792
  }
793
}
×
794

795
void LJ_FASTCALL recff_cdata_index(jit_State *J, RecordFFData *rd)
311✔
796
{
797
  TRef idx, ptr = J->base[0];
311✔
798
  ptrdiff_t ofs = sizeof(GCcdata);
311✔
799
  GCcdata *cd = argv2cdata(J, ptr, &rd->argv[0]);
311✔
800
  CTState *cts = ctype_ctsG(J2G(J));
311✔
801
  CType *ct = ctype_raw(cts, cd->ctypeid);
311✔
802
  CTypeID sid = 0;
311✔
803

804
  /* Resolve pointer or reference for cdata object. */
805
  if (ctype_isptr(ct->info)) {
311✔
806
    IRType t = (LJ_64 && ct->size == 8) ? IRT_P64 : IRT_P32;
51✔
807
    if (ctype_isref(ct->info)) ct = ctype_rawchild(cts, ct);
51✔
808
    ptr = emitir(IRT(IR_FLOAD, t), ptr, IRFL_CDATA_PTR);
51✔
809
    ofs = 0;
51✔
810
    ptr = crec_reassoc_ofs(J, ptr, &ofs, 1);
51✔
811
  }
812

813
again:
260✔
814
  idx = J->base[1];
320✔
815
  if (tref_isnumber(idx)) {
320✔
816
    idx = lj_opt_narrow_cindex(J, idx);
169✔
817
    if (ctype_ispointer(ct->info)) {
169✔
818
      CTSize sz;
172✔
819
  integer_key:
169✔
820
      if ((ct->info & CTF_COMPLEX))
172✔
821
        idx = emitir(IRT(IR_BAND, IRT_INTP), idx, lj_ir_kintp(J, 1));
3✔
822
      sz = lj_ctype_size(cts, (sid = ctype_cid(ct->info)));
172✔
823
      idx = crec_reassoc_ofs(J, idx, &ofs, sz);
172✔
824
#if LJ_TARGET_ARM || LJ_TARGET_PPC
825
      /* Hoist base add to allow fusion of index/shift into operands. */
826
      if (LJ_LIKELY(J->flags & JIT_F_OPT_LOOP) && ofs
827
#if LJ_TARGET_ARM
828
          && (sz == 1 || sz == 4)
829
#endif
830
          ) {
831
        ptr = emitir(IRT(IR_ADD, IRT_PTR), ptr, lj_ir_kintp(J, ofs));
832
        ofs = 0;
833
      }
834
#endif
835
      idx = emitir(IRT(IR_MUL, IRT_INTP), idx, lj_ir_kintp(J, sz));
172✔
836
      ptr = emitir(IRT(IR_ADD, IRT_PTR), idx, ptr);
172✔
837
    }
838
  } else if (tref_iscdata(idx)) {
151✔
839
    GCcdata *cdk = cdataV(&rd->argv[1]);
3✔
840
    CType *ctk = ctype_raw(cts, cdk->ctypeid);
3✔
841
    IRType t = crec_ct2irt(cts, ctk);
3✔
842
    if (ctype_ispointer(ct->info) && t >= IRT_I8 && t <= IRT_U64) {
3✔
843
      if (ctk->size == 8) {
3✔
844
        idx = emitir(IRT(IR_FLOAD, t), idx, IRFL_CDATA_INT64);
2✔
845
      } else if (ctk->size == 4) {
1✔
846
        idx = emitir(IRT(IR_FLOAD, t), idx, IRFL_CDATA_INT);
1✔
847
      } else {
848
        idx = emitir(IRT(IR_ADD, IRT_PTR), idx,
×
849
                     lj_ir_kintp(J, sizeof(GCcdata)));
850
        idx = emitir(IRT(IR_XLOAD, t), idx, 0);
×
851
      }
852
      if (LJ_64 && ctk->size < sizeof(intptr_t) && !(ctk->info & CTF_UNSIGNED))
3✔
853
        idx = emitconv(idx, IRT_INTP, IRT_INT, IRCONV_SEXT);
1✔
854
      if (!LJ_64 && ctk->size > sizeof(intptr_t)) {
3✔
855
        idx = emitconv(idx, IRT_INTP, t, 0);
856
        lj_needsplit(J);
3✔
857
      }
858
      goto integer_key;
3✔
859
    }
860
  } else if (tref_isstr(idx)) {
148✔
861
    GCstr *name = strV(&rd->argv[1]);
148✔
862
    if (cd && cd->ctypeid == CTID_CTYPEID)
148✔
863
      ct = ctype_raw(cts, crec_constructor(J, cd, ptr));
×
864
    if (ctype_isstruct(ct->info)) {
148✔
865
      CTSize fofs;
122✔
866
      CType *fct;
122✔
867
      fct = lj_ctype_getfield(cts, ct, name, &fofs);
122✔
868
      if (fct) {
122✔
869
        ofs += (ptrdiff_t)fofs;
122✔
870
        /* Always specialize to the field name. */
871
        emitir(IRTG(IR_EQ, IRT_STR), idx, lj_ir_kstr(J, name));
122✔
872
        if (ctype_isconstval(fct->info)) {
122✔
873
          if (fct->size >= 0x80000000u &&
×
874
              (ctype_child(cts, fct)->info & CTF_UNSIGNED)) {
×
875
            J->base[0] = lj_ir_knum(J, (lua_Number)(uint32_t)fct->size);
×
876
            return;
×
877
          }
878
          J->base[0] = lj_ir_kint(J, (int32_t)fct->size);
×
879
          return;  /* Interpreter will throw for newindex. */
×
880
        } else if (ctype_isbitfield(fct->info)) {
122✔
881
          if (ofs)
×
882
            ptr = emitir(IRT(IR_ADD, IRT_PTR), ptr, lj_ir_kintp(J, ofs));
×
883
          crec_index_bf(J, rd, ptr, fct->info);
×
884
          return;
×
885
        } else {
886
          lua_assert(ctype_isfield(fct->info));
122✔
887
          sid = ctype_cid(fct->info);
122✔
888
        }
889
      }
890
    } else if (ctype_iscomplex(ct->info)) {
26✔
891
      if (name->len == 2 &&
17✔
892
          ((strdata(name)[0] == 'r' && strdata(name)[1] == 'e') ||
17✔
893
           (strdata(name)[0] == 'i' && strdata(name)[1] == 'm'))) {
8✔
894
        /* Always specialize to the field name. */
895
        emitir(IRTG(IR_EQ, IRT_STR), idx, lj_ir_kstr(J, name));
17✔
896
        if (strdata(name)[0] == 'i') ofs += (ct->size >> 1);
17✔
897
        sid = ctype_cid(ct->info);
17✔
898
      }
899
    }
900
  }
901
  if (!sid) {
320✔
902
    if (ctype_isptr(ct->info)) {  /* Automatically perform '->'. */
9✔
903
      CType *cct = ctype_rawchild(cts, ct);
9✔
904
      if (ctype_isstruct(cct->info)) {
9✔
905
        ct = cct;
9✔
906
        cd = NULL;
9✔
907
        if (tref_isstr(idx)) goto again;
9✔
908
      }
909
    }
910
    crec_index_meta(J, cts, ct, rd);
×
911
    return;
×
912
  }
913

914
  if (ofs)
311✔
915
    ptr = emitir(IRT(IR_ADD, IRT_PTR), ptr, lj_ir_kintp(J, ofs));
277✔
916

917
  /* Resolve reference for field. */
918
  ct = ctype_get(cts, sid);
311✔
919
  if (ctype_isref(ct->info)) {
311✔
920
    ptr = emitir(IRT(IR_XLOAD, IRT_PTR), ptr, 0);
×
921
    sid = ctype_cid(ct->info);
×
922
    ct = ctype_get(cts, sid);
×
923
  }
924

925
  while (ctype_isattrib(ct->info))
311✔
926
    ct = ctype_child(cts, ct);  /* Skip attributes. */
×
927

928
  if (rd->data == 0) {  /* __index metamethod. */
311✔
929
    J->base[0] = crec_tv_ct(J, ct, sid, ptr);
217✔
930
  } else {  /* __newindex metamethod. */
931
    rd->nres = 0;
94✔
932
    J->needsnap = 1;
94✔
933
    crec_ct_tv(J, ct, ptr, J->base[2], &rd->argv[2]);
94✔
934
  }
935
}
936

937
/* Record setting a finalizer. */
938
static void crec_finalizer(jit_State *J, TRef trcd, TRef trfin, cTValue *fin)
939
{
940
  if (tvisgcv(fin)) {
941
    if (!trfin) trfin = lj_ir_kptr(J, gcval(fin));
942
  } else if (tvisnil(fin)) {
943
    trfin = lj_ir_kptr(J, NULL);
944
  } else {
945
    lj_trace_err(J, LJ_TRERR_BADTYPE);
946
  }
947
  lj_ir_call(J, IRCALL_lj_cdata_setfin, trcd,
948
             trfin, lj_ir_kint(J, (int32_t)itype(fin)));
949
  J->needsnap = 1;
950
}
951

952
/* Record cdata allocation. */
953
static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id)
954
{
955
  CTState *cts = ctype_ctsG(J2G(J));
956
  CTSize sz;
957
  CTInfo info = lj_ctype_info(cts, id, &sz);
958
  CType *d = ctype_raw(cts, id);
959
  TRef trcd, trid = lj_ir_kint(J, id);
960
  cTValue *fin;
961
  /* Use special instruction to box pointer or 32/64 bit integer. */
962
  if (ctype_isptr(info) || (ctype_isinteger(info) && (sz == 4 || sz == 8))) {
963
    TRef sp = J->base[1] ? crec_ct_tv(J, d, 0, J->base[1], &rd->argv[1]) :
964
              ctype_isptr(info) ? lj_ir_kptr(J, NULL) :
965
              sz == 4 ? lj_ir_kint(J, 0) :
966
              (lj_needsplit(J), lj_ir_kint64(J, 0));
967
    J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), trid, sp);
968
    return;
969
  } else {
970
    TRef trsz = TREF_NIL;
971
    if ((info & CTF_VLA)) {  /* Calculate VLA/VLS size at runtime. */
972
      CTSize sz0, sz1;
973
      if (!J->base[1] || J->base[2])
974
        lj_trace_err(J, LJ_TRERR_NYICONV);  /* NYI: init VLA/VLS. */
975
      trsz = crec_ct_tv(J, ctype_get(cts, CTID_INT32), 0,
976
                        J->base[1], &rd->argv[1]);
977
      sz0 = lj_ctype_vlsize(cts, d, 0);
978
      sz1 = lj_ctype_vlsize(cts, d, 1);
979
      trsz = emitir(IRTGI(IR_MULOV), trsz, lj_ir_kint(J, (int32_t)(sz1-sz0)));
980
      trsz = emitir(IRTGI(IR_ADDOV), trsz, lj_ir_kint(J, (int32_t)sz0));
981
      J->base[1] = 0;  /* Simplify logic below. */
982
    } else if (ctype_align(info) > CT_MEMALIGN) {
983
      trsz = lj_ir_kint(J, sz);
984
    }
985
    trcd = emitir(IRTG(IR_CNEW, IRT_CDATA), trid, trsz);
986
    if (sz > 128 || (info & CTF_VLA)) {
987
      TRef dp;
988
      CTSize align;
989
    special:  /* Only handle bulk zero-fill for large/VLA/VLS types. */
990
      if (J->base[1])
991
        lj_trace_err(J, LJ_TRERR_NYICONV);  /* NYI: init large/VLA/VLS types. */
992
      dp = emitir(IRT(IR_ADD, IRT_PTR), trcd, lj_ir_kintp(J, sizeof(GCcdata)));
993
      if (trsz == TREF_NIL) trsz = lj_ir_kint(J, sz);
994
      align = ctype_align(info);
995
      if (align < CT_MEMALIGN) align = CT_MEMALIGN;
996
      crec_fill(J, dp, trsz, lj_ir_kint(J, 0), (1u << align));
997
    } else if (J->base[1] && !J->base[2] &&
998
        !lj_cconv_multi_init(cts, d, &rd->argv[1])) {
999
      goto single_init;
1000
    } else if (ctype_isarray(d->info)) {
1001
      CType *dc = ctype_rawchild(cts, d);  /* Array element type. */
1002
      CTSize ofs, esize = dc->size;
1003
      TRef sp = 0;
1004
      TValue tv;
1005
      TValue *sval = &tv;
1006
      MSize i;
1007
      tv.u64 = 0;
1008
      if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info)) ||
1009
          esize * CREC_FILL_MAXUNROLL < sz)
1010
        goto special;
1011
      for (i = 1, ofs = 0; ofs < sz; ofs += esize) {
1012
        TRef dp = emitir(IRT(IR_ADD, IRT_PTR), trcd,
1013
                         lj_ir_kintp(J, ofs + sizeof(GCcdata)));
1014
        if (J->base[i]) {
1015
          sp = J->base[i];
1016
          sval = &rd->argv[i];
1017
          i++;
1018
        } else if (i != 2) {
1019
          sp = ctype_isnum(dc->info) ? lj_ir_kint(J, 0) : TREF_NIL;
1020
        }
1021
        crec_ct_tv(J, dc, dp, sp, sval);
1022
      }
1023
    } else if (ctype_isstruct(d->info)) {
1024
      CTypeID fid;
1025
      MSize i = 1;
1026
      if (!J->base[1]) {  /* Handle zero-fill of struct-of-NYI. */
1027
        fid = d->sib;
1028
        while (fid) {
1029
          CType *df = ctype_get(cts, fid);
1030
          fid = df->sib;
1031
          if (ctype_isfield(df->info)) {
1032
            CType *dc;
1033
            if (!gcref(df->name)) continue;  /* Ignore unnamed fields. */
1034
            dc = ctype_rawchild(cts, df);  /* Field type. */
1035
            if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info) ||
1036
                  ctype_isenum(dc->info)))
1037
              goto special;
1038
          } else if (!ctype_isconstval(df->info)) {
1039
            goto special;
1040
          }
1041
        }
1042
      }
1043
      fid = d->sib;
1044
      while (fid) {
1045
        CType *df = ctype_get(cts, fid);
1046
        fid = df->sib;
1047
        if (ctype_isfield(df->info)) {
1048
          CType *dc;
1049
          TRef sp, dp;
1050
          TValue tv;
1051
          TValue *sval = &tv;
1052
          setintV(&tv, 0);
1053
          if (!gcref(df->name)) continue;  /* Ignore unnamed fields. */
1054
          dc = ctype_rawchild(cts, df);  /* Field type. */
1055
          if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info) ||
1056
                ctype_isenum(dc->info)))
1057
            lj_trace_err(J, LJ_TRERR_NYICONV);  /* NYI: init aggregates. */
1058
          if (J->base[i]) {
1059
            sp = J->base[i];
1060
            sval = &rd->argv[i];
1061
            i++;
1062
          } else {
1063
            sp = ctype_isptr(dc->info) ? TREF_NIL : lj_ir_kint(J, 0);
1064
          }
1065
          dp = emitir(IRT(IR_ADD, IRT_PTR), trcd,
1066
                      lj_ir_kintp(J, df->size + sizeof(GCcdata)));
1067
          crec_ct_tv(J, dc, dp, sp, sval);
1068
          if ((d->info & CTF_UNION)) {
1069
            if (d->size != dc->size)  /* NYI: partial init of union. */
1070
              lj_trace_err(J, LJ_TRERR_NYICONV);
1071
            break;
1072
          }
1073
        } else if (!ctype_isconstval(df->info)) {
1074
          /* NYI: init bitfields and sub-structures. */
1075
          lj_trace_err(J, LJ_TRERR_NYICONV);
1076
        }
1077
      }
1078
    } else {
1079
      TRef dp;
1080
    single_init:
1081
      dp = emitir(IRT(IR_ADD, IRT_PTR), trcd, lj_ir_kintp(J, sizeof(GCcdata)));
1082
      if (J->base[1]) {
1083
        crec_ct_tv(J, d, dp, J->base[1], &rd->argv[1]);
1084
      } else {
1085
        TValue tv;
1086
        tv.u64 = 0;
1087
        crec_ct_tv(J, d, dp, lj_ir_kint(J, 0), &tv);
1088
      }
1089
    }
1090
  }
1091
  J->base[0] = trcd;
1092
  /* Handle __gc metamethod. */
1093
  fin = lj_ctype_meta(cts, id, MM_gc);
1094
  if (fin)
1095
    crec_finalizer(J, trcd, 0, fin);
1096
}
1097

1098
/* Record argument conversions. */
1099
static TRef crec_call_args(jit_State *J, RecordFFData *rd,
1100
                           CTState *cts, CType *ct)
1101
{
1102
  TRef args[CCI_NARGS_MAX];
1103
  CTypeID fid;
1104
  MSize i, n;
1105
  TRef tr, *base;
1106
  cTValue *o;
1107
#if LJ_TARGET_X86
1108
#if LJ_ABI_WIN
1109
  TRef *arg0 = NULL, *arg1 = NULL;
1110
#endif
1111
  int ngpr = 0;
1112
  if (ctype_cconv(ct->info) == CTCC_THISCALL)
1113
    ngpr = 1;
1114
  else if (ctype_cconv(ct->info) == CTCC_FASTCALL)
1115
    ngpr = 2;
1116
#endif
1117

1118
  /* Skip initial attributes. */
1119
  fid = ct->sib;
1120
  while (fid) {
1121
    CType *ctf = ctype_get(cts, fid);
1122
    if (!ctype_isattrib(ctf->info)) break;
1123
    fid = ctf->sib;
1124
  }
1125
  args[0] = TREF_NIL;
1126
  for (n = 0, base = J->base+1, o = rd->argv+1; *base; n++, base++, o++) {
1127
    CTypeID did;
1128
    CType *d;
1129

1130
    if (n >= CCI_NARGS_MAX)
1131
      lj_trace_err(J, LJ_TRERR_NYICALL);
1132

1133
    if (fid) {  /* Get argument type from field. */
1134
      CType *ctf = ctype_get(cts, fid);
1135
      fid = ctf->sib;
1136
      lua_assert(ctype_isfield(ctf->info));
1137
      did = ctype_cid(ctf->info);
1138
    } else {
1139
      if (!(ct->info & CTF_VARARG))
1140
        lj_trace_err(J, LJ_TRERR_NYICALL);  /* Too many arguments. */
1141
      did = lj_ccall_ctid_vararg(cts, o);  /* Infer vararg type. */
1142
    }
1143
    d = ctype_raw(cts, did);
1144
    if (!(ctype_isnum(d->info) || ctype_isptr(d->info) ||
1145
          ctype_isenum(d->info)))
1146
      lj_trace_err(J, LJ_TRERR_NYICALL);
1147
    tr = crec_ct_tv(J, d, 0, *base, o);
1148
    if (ctype_isinteger_or_bool(d->info)) {
1149
      if (d->size < 4) {
1150
        if ((d->info & CTF_UNSIGNED))
1151
          tr = emitconv(tr, IRT_INT, d->size==1 ? IRT_U8 : IRT_U16, 0);
1152
        else
1153
          tr = emitconv(tr, IRT_INT, d->size==1 ? IRT_I8 : IRT_I16,IRCONV_SEXT);
1154
      }
1155
    } else if (LJ_SOFTFP && ctype_isfp(d->info) && d->size > 4) {
1156
      lj_needsplit(J);
1157
    }
1158
#if LJ_TARGET_X86
1159
    /* 64 bit args must not end up in registers for fastcall/thiscall. */
1160
#if LJ_ABI_WIN
1161
    if (!ctype_isfp(d->info)) {
1162
      /* Sigh, the Windows/x86 ABI allows reordering across 64 bit args. */
1163
      if (tref_typerange(tr, IRT_I64, IRT_U64)) {
1164
        if (ngpr) {
1165
          arg0 = &args[n]; args[n++] = TREF_NIL; ngpr--;
1166
          if (ngpr) {
1167
            arg1 = &args[n]; args[n++] = TREF_NIL; ngpr--;
1168
          }
1169
        }
1170
      } else {
1171
        if (arg0) { *arg0 = tr; arg0 = NULL; n--; continue; }
1172
        if (arg1) { *arg1 = tr; arg1 = NULL; n--; continue; }
1173
        if (ngpr) ngpr--;
1174
      }
1175
    }
1176
#else
1177
    if (!ctype_isfp(d->info) && ngpr) {
1178
      if (tref_typerange(tr, IRT_I64, IRT_U64)) {
1179
        /* No reordering for other x86 ABIs. Simply add alignment args. */
1180
        do { args[n++] = TREF_NIL; } while (--ngpr);
1181
      } else {
1182
        ngpr--;
1183
      }
1184
    }
1185
#endif
1186
#endif
1187
    args[n] = tr;
1188
  }
1189
  tr = args[0];
1190
  for (i = 1; i < n; i++)
1191
    tr = emitir(IRT(IR_CARG, IRT_NIL), tr, args[i]);
1192
  return tr;
1193
}
1194

1195
/* Create a snapshot for the caller, simulating a 'false' return value. */
1196
static void crec_snap_caller(jit_State *J)
×
1197
{
1198
  lua_State *L = J->L;
×
1199
  TValue *base = L->base, *top = L->top;
×
1200
  const BCIns *pc = J->pc;
×
1201
  TRef ftr = J->base[-1-LJ_FR2];
×
1202
  ptrdiff_t delta;
×
1203
  if (!frame_islua(base-1) || J->framedepth <= 0)
×
1204
    lj_trace_err(J, LJ_TRERR_NYICALL);
×
1205
  J->pc = frame_pc(base-1); delta = 1+LJ_FR2+bc_a(J->pc[-1]);
×
1206
  L->top = base; L->base = base - delta;
×
1207
  J->base[-1-LJ_FR2] = TREF_FALSE;
×
1208
  J->base -= delta; J->baseslot -= (BCReg)delta;
×
1209
  J->maxslot = (BCReg)delta-LJ_FR2; J->framedepth--;
×
1210
  lj_snap_add(J);
×
1211
  L->base = base; L->top = top;
×
1212
  J->framedepth++; J->maxslot = 1;
×
1213
  J->base += delta; J->baseslot += (BCReg)delta;
×
1214
  J->base[-1-LJ_FR2] = ftr; J->pc = pc;
×
1215
}
×
1216

1217
/* Record function call. */
1218
static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd)
25✔
1219
{
1220
  CTState *cts = ctype_ctsG(J2G(J));
25✔
1221
  CType *ct = ctype_raw(cts, cd->ctypeid);
25✔
1222
  IRType tp = IRT_PTR;
25✔
1223
  if (ctype_isptr(ct->info)) {
25✔
1224
    tp = (LJ_64 && ct->size == 8) ? IRT_P64 : IRT_P32;
×
1225
    ct = ctype_rawchild(cts, ct);
×
1226
  }
1227
  if (ctype_isfunc(ct->info)) {
25✔
1228
    TRef func = emitir(IRT(IR_FLOAD, tp), J->base[0], IRFL_CDATA_PTR);
25✔
1229
    CType *ctr = ctype_rawchild(cts, ct);
25✔
1230
    IRType t = crec_ct2irt(cts, ctr);
25✔
1231
    TRef tr;
25✔
1232
    TValue tv;
25✔
1233
    /* Check for blacklisted C functions that might call a callback. */
1234
    tv.u64 = ((uintptr_t)cdata_getptr(cdataptr(cd), (LJ_64 && tp == IRT_P64) ? 8 : 4) >> 2) | U64x(800000000, 00000000);
25✔
1235
    if (tvistrue(lj_tab_get(J->L, cts->miscmap, &tv)))
25✔
1236
      lj_trace_err(J, LJ_TRERR_BLACKL);
×
1237
    if (ctype_isvoid(ctr->info)) {
25✔
1238
      t = IRT_NIL;
2✔
1239
      rd->nres = 0;
2✔
1240
    } else if (!(ctype_isnum(ctr->info) || ctype_isptr(ctr->info) ||
23✔
1241
                 ctype_isenum(ctr->info)) || t == IRT_CDATA) {
23✔
1242
      lj_trace_err(J, LJ_TRERR_NYICALL);
×
1243
    }
1244
    if ((ct->info & CTF_VARARG)
25✔
1245
#if LJ_TARGET_X86
1246
        || ctype_cconv(ct->info) != CTCC_CDECL
1247
#endif
1248
        )
1249
      func = emitir(IRT(IR_CARG, IRT_NIL), func,
×
1250
                    lj_ir_kint(J, ctype_typeid(cts, ct)));
1251
    tr = emitir(IRT(IR_CALLXS, t), crec_call_args(J, rd, cts, ct), func);
25✔
1252
    if (ctype_isbool(ctr->info)) {
25✔
1253
      if (frame_islua(J->L->base-1) && bc_b(frame_pc(J->L->base-1)[-1]) == 1) {
×
1254
        /* Don't check result if ignored. */
1255
        tr = TREF_NIL;
1256
      } else {
1257
        crec_snap_caller(J);
×
1258
#if LJ_TARGET_X86ORX64
1259
        /* Note: only the x86/x64 backend supports U8 and only for EQ(tr, 0). */
1260
        lj_ir_set(J, IRTG(IR_NE, IRT_U8), tr, lj_ir_kint(J, 0));
×
1261
#else
1262
        lj_ir_set(J, IRTGI(IR_NE), tr, lj_ir_kint(J, 0));
1263
#endif
1264
        J->postproc = LJ_POST_FIXGUARDSNAP;
×
1265
        tr = TREF_TRUE;
×
1266
      }
1267
    } else if (t == IRT_PTR || (LJ_64 && t == IRT_P32) ||
25✔
1268
               t == IRT_I64 || t == IRT_U64 || ctype_isenum(ctr->info)) {
26✔
1269
      TRef trid = lj_ir_kint(J, ctype_cid(ct->info));
3✔
1270
      tr = emitir(IRTG(IR_CNEWI, IRT_CDATA), trid, tr);
3✔
1271
      if (t == IRT_I64 || t == IRT_U64) lj_needsplit(J);
3✔
1272
    } else if (t == IRT_FLOAT || t == IRT_U32) {
22✔
1273
      tr = emitconv(tr, IRT_NUM, t, 0);
×
1274
    } else if (t == IRT_I8 || t == IRT_I16) {
22✔
1275
      tr = emitconv(tr, IRT_INT, t, IRCONV_SEXT);
×
1276
    } else if (t == IRT_U8 || t == IRT_U16) {
22✔
1277
      tr = emitconv(tr, IRT_INT, t, 0);
×
1278
    }
1279
    J->base[0] = tr;
25✔
1280
    J->needsnap = 1;
25✔
1281
    return 1;
25✔
1282
  }
1283
  return 0;
1284
}
1285

1286
void LJ_FASTCALL recff_cdata_call(jit_State *J, RecordFFData *rd)
46✔
1287
{
1288
  CTState *cts = ctype_ctsG(J2G(J));
46✔
1289
  GCcdata *cd = argv2cdata(J, J->base[0], &rd->argv[0]);
46✔
1290
  CTypeID id = cd->ctypeid;
46✔
1291
  CType *ct;
46✔
1292
  cTValue *tv;
46✔
1293
  MMS mm = MM_call;
46✔
1294
  if (id == CTID_CTYPEID) {
46✔
1295
    id = crec_constructor(J, cd, J->base[0]);
21✔
1296
    mm = MM_new;
21✔
1297
  } else if (crec_call(J, rd, cd)) {
25✔
1298
    return;
1299
  }
1300
  /* Record ctype __call/__new metamethod. */
1301
  ct = ctype_raw(cts, id);
21✔
1302
  tv = lj_ctype_meta(cts, ctype_isptr(ct->info) ? ctype_cid(ct->info) : id, mm);
21✔
1303
  if (tv) {
21✔
1304
    if (tvisfunc(tv)) {
×
1305
      crec_tailcall(J, rd, tv);
×
1306
      return;
×
1307
    }
1308
  } else if (mm == MM_new) {
21✔
1309
    crec_alloc(J, rd, id);
21✔
1310
    return;
21✔
1311
  }
1312
  /* No metamethod or NYI: non-function metamethods. */
1313
  lj_trace_err(J, LJ_TRERR_BADTYPE);
×
1314
}
1315

1316
static TRef crec_arith_int64(jit_State *J, TRef *sp, CType **s, MMS mm)
122✔
1317
{
1318
  if (sp[0] && sp[1] && ctype_isnum(s[0]->info) && ctype_isnum(s[1]->info)) {
122✔
1319
    IRType dt;
93✔
1320
    CTypeID id;
93✔
1321
    TRef tr;
93✔
1322
    MSize i;
93✔
1323
    IROp op;
93✔
1324
    lj_needsplit(J);
93✔
1325
    if (((s[0]->info & CTF_UNSIGNED) && s[0]->size == 8) ||
93✔
1326
        ((s[1]->info & CTF_UNSIGNED) && s[1]->size == 8)) {
67✔
1327
      dt = IRT_U64; id = CTID_UINT64;
1328
    } else {
1329
      dt = IRT_I64; id = CTID_INT64;
33✔
1330
      if (mm < MM_add &&
33✔
1331
          !((s[0]->info | s[1]->info) & CTF_FP) &&
3✔
1332
          s[0]->size == 4 && s[1]->size == 4) {  /* Try to narrow comparison. */
3✔
1333
        if (!((s[0]->info ^ s[1]->info) & CTF_UNSIGNED) ||
1✔
1334
            (tref_isk(sp[1]) && IR(tref_ref(sp[1]))->i >= 0)) {
×
1335
          dt = (s[0]->info & CTF_UNSIGNED) ? IRT_U32 : IRT_INT;
1✔
1336
          goto comp;
1✔
1337
        } else if (tref_isk(sp[0]) && IR(tref_ref(sp[0]))->i >= 0) {
×
1338
          dt = (s[1]->info & CTF_UNSIGNED) ? IRT_U32 : IRT_INT;
×
1339
          goto comp;
×
1340
        }
1341
      }
1342
    }
1343
    for (i = 0; i < 2; i++) {
276✔
1344
      IRType st = tref_type(sp[i]);
184✔
1345
      if (st == IRT_NUM || st == IRT_FLOAT)
184✔
1346
        sp[i] = emitconv(sp[i], dt, st, IRCONV_ANY);
39✔
1347
      else if (!(st == IRT_I64 || st == IRT_U64))
145✔
1348
        sp[i] = emitconv(sp[i], dt, IRT_INT,
62✔
1349
                         (s[i]->info & CTF_UNSIGNED) ? 0 : IRCONV_SEXT);
1350
    }
1351
    if (mm < MM_add) {
92✔
1352
    comp:
39✔
1353
      /* Assume true comparison. Fixup and emit pending guard later. */
1354
      if (mm == MM_eq) {
40✔
1355
        op = IR_EQ;
1356
      } else {
1357
        op = mm == MM_lt ? IR_LT : IR_LE;
17✔
1358
        if (dt == IRT_U32 || dt == IRT_U64)
17✔
1359
          op += (IR_ULT-IR_LT);
17✔
1360
      }
1361
      lj_ir_set(J, IRTG(op, dt), sp[0], sp[1]);
40✔
1362
      J->postproc = LJ_POST_FIXGUARD;
40✔
1363
      return TREF_TRUE;
40✔
1364
    } else {
1365
      tr = emitir(IRT(mm+(int)IR_ADD-(int)MM_add, dt), sp[0], sp[1]);
53✔
1366
    }
1367
    return emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr);
53✔
1368
  }
1369
  return 0;
1370
}
1371

1372
static TRef crec_arith_ptr(jit_State *J, TRef *sp, CType **s, MMS mm)
29✔
1373
{
1374
  CTState *cts = ctype_ctsG(J2G(J));
29✔
1375
  CType *ctp = s[0];
29✔
1376
  if (!(sp[0] && sp[1])) return 0;
29✔
1377
  if (ctype_isptr(ctp->info) || ctype_isrefarray(ctp->info)) {
29✔
1378
    if ((mm == MM_sub || mm == MM_eq || mm == MM_lt || mm == MM_le) &&
28✔
1379
        (ctype_isptr(s[1]->info) || ctype_isrefarray(s[1]->info))) {
9✔
1380
      if (mm == MM_sub) {  /* Pointer difference. */
7✔
1381
        TRef tr;
1✔
1382
        CTSize sz = lj_ctype_size(cts, ctype_cid(ctp->info));
1✔
1383
        if (sz == 0 || (sz & (sz-1)) != 0)
1✔
1384
          return 0;  /* NYI: integer division. */
1385
        tr = emitir(IRT(IR_SUB, IRT_INTP), sp[0], sp[1]);
1✔
1386
        tr = emitir(IRT(IR_BSAR, IRT_INTP), tr, lj_ir_kint(J, lj_fls(sz)));
1✔
1387
#if LJ_64
1388
        tr = emitconv(tr, IRT_NUM, IRT_INTP, 0);
1✔
1389
#endif
1390
        return tr;
1✔
1391
      } else {  /* Pointer comparison (unsigned). */
1392
        /* Assume true comparison. Fixup and emit pending guard later. */
1393
        IROp op = mm == MM_eq ? IR_EQ : mm == MM_lt ? IR_ULT : IR_ULE;
6✔
1394
        lj_ir_set(J, IRTG(op, IRT_PTR), sp[0], sp[1]);
6✔
1395
        J->postproc = LJ_POST_FIXGUARD;
6✔
1396
        return TREF_TRUE;
6✔
1397
      }
1398
    }
1399
    if (!((mm == MM_add || mm == MM_sub) && ctype_isnum(s[1]->info)))
21✔
1400
      return 0;
1401
  } else if (mm == MM_add && ctype_isnum(ctp->info) &&
1✔
1402
             (ctype_isptr(s[1]->info) || ctype_isrefarray(s[1]->info))) {
1✔
1403
    TRef tr = sp[0]; sp[0] = sp[1]; sp[1] = tr;  /* Swap pointer and index. */
1✔
1404
    ctp = s[1];
1✔
1405
  } else {
1406
    return 0;
1407
  }
1408
  {
1409
    TRef tr = sp[1];
22✔
1410
    IRType t = tref_type(tr);
22✔
1411
    CTSize sz = lj_ctype_size(cts, ctype_cid(ctp->info));
22✔
1412
    CTypeID id;
22✔
1413
#if LJ_64
1414
    if (t == IRT_NUM || t == IRT_FLOAT)
22✔
1415
      tr = emitconv(tr, IRT_INTP, t, IRCONV_ANY);
2✔
1416
    else if (!(t == IRT_I64 || t == IRT_U64))
20✔
1417
      tr = emitconv(tr, IRT_INTP, IRT_INT,
40✔
1418
                    ((t - IRT_I8) & 1) ? 0 : IRCONV_SEXT);
1419
#else
1420
    if (!tref_typerange(sp[1], IRT_I8, IRT_U32)) {
1421
      tr = emitconv(tr, IRT_INTP, t,
1422
                    (t == IRT_NUM || t == IRT_FLOAT) ? IRCONV_ANY : 0);
1423
    }
1424
#endif
1425
    tr = emitir(IRT(IR_MUL, IRT_INTP), tr, lj_ir_kintp(J, sz));
22✔
1426
    tr = emitir(IRT(mm+(int)IR_ADD-(int)MM_add, IRT_PTR), sp[0], tr);
22✔
1427
    id = lj_ctype_intern(cts, CTINFO(CT_PTR, CTALIGN_PTR|ctype_cid(ctp->info)),
22✔
1428
                         CTSIZE_PTR);
1429
    return emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr);
22✔
1430
  }
1431
}
1432

1433
/* Record ctype arithmetic metamethods. */
1434
static TRef crec_arith_meta(jit_State *J, TRef *sp, CType **s, CTState *cts,
×
1435
                            RecordFFData *rd)
1436
{
1437
  cTValue *tv = NULL;
×
1438
  if (J->base[0]) {
×
1439
    if (tviscdata(&rd->argv[0])) {
×
1440
      CTypeID id = argv2cdata(J, J->base[0], &rd->argv[0])->ctypeid;
×
1441
      CType *ct = ctype_raw(cts, id);
×
1442
      if (ctype_isptr(ct->info)) id = ctype_cid(ct->info);
×
1443
      tv = lj_ctype_meta(cts, id, (MMS)rd->data);
×
1444
    }
1445
    if (!tv && J->base[1] && tviscdata(&rd->argv[1])) {
×
1446
      CTypeID id = argv2cdata(J, J->base[1], &rd->argv[1])->ctypeid;
×
1447
      CType *ct = ctype_raw(cts, id);
×
1448
      if (ctype_isptr(ct->info)) id = ctype_cid(ct->info);
×
1449
      tv = lj_ctype_meta(cts, id, (MMS)rd->data);
×
1450
    }
1451
  }
1452
  if (tv) {
×
1453
    if (tvisfunc(tv)) {
×
1454
      crec_tailcall(J, rd, tv);
×
1455
      return 0;
×
1456
    }  /* NYI: non-function metamethods. */
1457
  } else if ((MMS)rd->data == MM_eq) {  /* Fallback cdata pointer comparison. */
×
1458
    if (sp[0] && sp[1] && ctype_isnum(s[0]->info) == ctype_isnum(s[1]->info)) {
×
1459
      /* Assume true comparison. Fixup and emit pending guard later. */
1460
      lj_ir_set(J, IRTG(IR_EQ, IRT_PTR), sp[0], sp[1]);
×
1461
      J->postproc = LJ_POST_FIXGUARD;
×
1462
      return TREF_TRUE;
×
1463
    } else {
1464
      return TREF_FALSE;
1465
    }
1466
  }
1467
  lj_trace_err(J, LJ_TRERR_BADTYPE);
×
1468
  return 0;
1469
}
1470

1471
void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
122✔
1472
{
1473
  CTState *cts = ctype_ctsG(J2G(J));
122✔
1474
  TRef sp[2];
122✔
1475
  CType *s[2];
122✔
1476
  MSize i;
122✔
1477
  for (i = 0; i < 2; i++) {
366✔
1478
    TRef tr = J->base[i];
244✔
1479
    CType *ct = ctype_get(cts, CTID_DOUBLE);
244✔
1480
    if (!tr) {
244✔
1481
      lj_trace_err(J, LJ_TRERR_BADTYPE);
×
1482
    } else if (tref_iscdata(tr)) {
244✔
1483
      CTypeID id = argv2cdata(J, tr, &rd->argv[i])->ctypeid;
153✔
1484
      IRType t;
153✔
1485
      ct = ctype_raw(cts, id);
153✔
1486
      t = crec_ct2irt(cts, ct);
153✔
1487
      if (ctype_isptr(ct->info)) {  /* Resolve pointer or reference. */
153✔
1488
        tr = emitir(IRT(IR_FLOAD, t), tr, IRFL_CDATA_PTR);
18✔
1489
        if (ctype_isref(ct->info)) {
18✔
1490
          ct = ctype_rawchild(cts, ct);
×
1491
          t = crec_ct2irt(cts, ct);
×
1492
        }
1493
      } else if (t == IRT_I64 || t == IRT_U64) {
135✔
1494
        tr = emitir(IRT(IR_FLOAD, t), tr, IRFL_CDATA_INT64);
113✔
1495
        lj_needsplit(J);
113✔
1496
        goto ok;
113✔
1497
      } else if (t == IRT_INT || t == IRT_U32) {
22✔
1498
        tr = emitir(IRT(IR_FLOAD, t), tr, IRFL_CDATA_INT);
4✔
1499
        if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct);
4✔
1500
        goto ok;
4✔
1501
      } else if (ctype_isfunc(ct->info)) {
18✔
1502
        tr = emitir(IRT(IR_FLOAD, IRT_PTR), tr, IRFL_CDATA_PTR);
×
1503
        ct = ctype_get(cts,
×
1504
          lj_ctype_intern(cts, CTINFO(CT_PTR, CTALIGN_PTR|id), CTSIZE_PTR));
×
1505
        goto ok;
×
1506
      } else {
1507
        tr = emitir(IRT(IR_ADD, IRT_PTR), tr, lj_ir_kintp(J, sizeof(GCcdata)));
18✔
1508
      }
1509
      if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct);
36✔
1510
      if (ctype_isnum(ct->info)) {
36✔
1511
        if (t == IRT_CDATA) {
×
1512
          tr = 0;
1513
        } else {
1514
          if (t == IRT_I64 || t == IRT_U64) lj_needsplit(J);
×
1515
          tr = emitir(IRT(IR_XLOAD, t), tr, 0);
×
1516
        }
1517
      }
1518
    } else if (tref_isnil(tr)) {
91✔
1519
      tr = lj_ir_kptr(J, NULL);
×
1520
      ct = ctype_get(cts, CTID_P_VOID);
×
1521
    } else if (tref_isinteger(tr)) {
91✔
1522
      ct = ctype_get(cts, CTID_INT32);
50✔
1523
    } else if (tref_isstr(tr)) {
41✔
1524
      TRef tr2 = J->base[1-i];
×
1525
      CTypeID id = argv2cdata(J, tr2, &rd->argv[1-i])->ctypeid;
×
1526
      ct = ctype_raw(cts, id);
×
1527
      if (ctype_isenum(ct->info)) {  /* Match string against enum constant. */
×
1528
        GCstr *str = strV(&rd->argv[i]);
×
1529
        CTSize ofs;
×
1530
        CType *cct = lj_ctype_getfield(cts, ct, str, &ofs);
×
1531
        if (cct && ctype_isconstval(cct->info)) {
×
1532
          /* Specialize to the name of the enum constant. */
1533
          emitir(IRTG(IR_EQ, IRT_STR), tr, lj_ir_kstr(J, str));
×
1534
          ct = ctype_child(cts, cct);
×
1535
          tr = lj_ir_kint(J, (int32_t)ofs);
×
1536
        } else {  /* Interpreter will throw or return false. */
1537
          ct = ctype_get(cts, CTID_P_VOID);
×
1538
        }
1539
      } else if (ctype_isptr(ct->info)) {
×
1540
        tr = emitir(IRT(IR_ADD, IRT_PTR), tr, lj_ir_kintp(J, sizeof(GCstr)));
×
1541
      } else {
1542
        ct = ctype_get(cts, CTID_P_VOID);
×
1543
      }
1544
    } else if (!tref_isnum(tr)) {
41✔
1545
      tr = 0;
×
1546
      ct = ctype_get(cts, CTID_P_VOID);
×
1547
    }
1548
  ok:
41✔
1549
    s[i] = ct;
244✔
1550
    sp[i] = tr;
244✔
1551
  }
1552
  {
1553
    TRef tr;
122✔
1554
    MMS mm = (MMS)rd->data;
122✔
1555
    if ((mm == MM_len || mm == MM_concat ||
122✔
1556
         (!(tr = crec_arith_int64(J, sp, s, mm)) &&
122✔
1557
          !(tr = crec_arith_ptr(J, sp, s, mm)))) &&
29✔
1558
        !(tr = crec_arith_meta(J, sp, s, cts, rd)))
×
1559
      return;
×
1560
    J->base[0] = tr;
122✔
1561
    /* Fixup cdata comparisons, too. Avoids some cdata escapes. */
1562
    if (J->postproc == LJ_POST_FIXGUARD && frame_iscont(J->L->base-1) &&
122✔
1563
        !irt_isguard(J->guardemit)) {
46✔
1564
      const BCIns *pc = frame_contpc(J->L->base-1) - 1;
21✔
1565
      if (bc_op(*pc) <= BC_ISNEP) {
21✔
1566
        J2G(J)->tmptv.u64 = (uint64_t)(uintptr_t)pc;
21✔
1567
        J->postproc = LJ_POST_FIXCOMP;
21✔
1568
      }
1569
    }
1570
  }
1571
}
1572

1573
/* -- C library namespace metamethods ------------------------------------- */
1574

1575
void LJ_FASTCALL recff_clib_index(jit_State *J, RecordFFData *rd)
25✔
1576
{
1577
  CTState *cts = ctype_ctsG(J2G(J));
25✔
1578
  if (tref_isudata(J->base[0]) && tref_isstr(J->base[1]) &&
25✔
1579
      udataV(&rd->argv[0])->udtype == UDTYPE_FFI_CLIB) {
25✔
1580
    CLibrary *cl = (CLibrary *)uddata(udataV(&rd->argv[0]));
25✔
1581
    GCstr *name = strV(&rd->argv[1]);
25✔
1582
    CType *ct;
25✔
1583
    CTypeID id = lj_ctype_getname(cts, &ct, name, CLNS_INDEX);
25✔
1584
    cTValue *tv = lj_tab_getstr(cl->cache, name);
25✔
1585
    rd->nres = rd->data;
25✔
1586
    if (id && tv && !tvisnil(tv)) {
25✔
1587
      /* Specialize to the symbol name and make the result a constant. */
1588
      emitir(IRTG(IR_EQ, IRT_STR), J->base[1], lj_ir_kstr(J, name));
24✔
1589
      if (ctype_isconstval(ct->info)) {
24✔
1590
        if (ct->size >= 0x80000000u &&
×
1591
            (ctype_child(cts, ct)->info & CTF_UNSIGNED))
×
1592
          J->base[0] = lj_ir_knum(J, (lua_Number)(uint32_t)ct->size);
×
1593
        else
1594
          J->base[0] = lj_ir_kint(J, (int32_t)ct->size);
×
1595
      } else if (ctype_isextern(ct->info)) {
24✔
1596
        CTypeID sid = ctype_cid(ct->info);
×
1597
        void *sp = *(void **)cdataptr(cdataV(tv));
×
1598
        TRef ptr;
×
1599
        ct = ctype_raw(cts, sid);
×
1600
        if (LJ_64 && !checkptr32(sp))
×
1601
          ptr = lj_ir_kintp(J, (uintptr_t)sp);
×
1602
        else
1603
          ptr = lj_ir_kptr(J, sp);
×
1604
        if (rd->data) {
×
1605
          J->base[0] = crec_tv_ct(J, ct, sid, ptr);
×
1606
        } else {
1607
          J->needsnap = 1;
×
1608
          crec_ct_tv(J, ct, ptr, J->base[2], &rd->argv[2]);
×
1609
        }
1610
      } else {
1611
        J->base[0] = lj_ir_kgc(J, obj2gco(cdataV(tv)), IRT_CDATA);
24✔
1612
      }
1613
    } else {
1614
      lj_trace_err(J, LJ_TRERR_NOCACHE);
1✔
1615
    }
1616
  }  /* else: interpreter will throw. */
1617
}
24✔
1618

1619
/* -- FFI library functions ----------------------------------------------- */
1620

1621
static TRef crec_toint(jit_State *J, CTState *cts, TRef sp, TValue *sval)
16✔
1622
{
1623
  return crec_ct_tv(J, ctype_get(cts, CTID_INT32), 0, sp, sval);
16✔
1624
}
1625

1626
void LJ_FASTCALL recff_ffi_new(jit_State *J, RecordFFData *rd)
144✔
1627
{
1628
  crec_alloc(J, rd, argv2ctype(J, J->base[0], &rd->argv[0]));
144✔
1629
}
144✔
1630

1631
void LJ_FASTCALL recff_ffi_errno(jit_State *J, RecordFFData *rd)
1✔
1632
{
1633
  UNUSED(rd);
1✔
1634
  if (J->base[0])
1✔
1635
    lj_trace_err(J, LJ_TRERR_NYICALL);
×
1636
  J->base[0] = lj_ir_call(J, IRCALL_lj_vm_errno);
1✔
1637
}
1✔
1638

1639
void LJ_FASTCALL recff_ffi_string(jit_State *J, RecordFFData *rd)
7✔
1640
{
1641
  CTState *cts = ctype_ctsG(J2G(J));
7✔
1642
  TRef tr = J->base[0];
7✔
1643
  if (tr) {
7✔
1644
    TRef trlen = J->base[1];
7✔
1645
    if (!tref_isnil(trlen)) {
7✔
1646
      trlen = crec_toint(J, cts, trlen, &rd->argv[1]);
6✔
1647
      tr = crec_ct_tv(J, ctype_get(cts, CTID_P_CVOID), 0, tr, &rd->argv[0]);
6✔
1648
    } else {
1649
      tr = crec_ct_tv(J, ctype_get(cts, CTID_P_CCHAR), 0, tr, &rd->argv[0]);
1✔
1650
      trlen = lj_ir_call(J, IRCALL_strlen, tr);
1✔
1651
    }
1652
    J->base[0] = emitir(IRT(IR_XSNEW, IRT_STR), tr, trlen);
7✔
1653
  }  /* else: interpreter will throw. */
1654
}
7✔
1655

1656
void LJ_FASTCALL recff_ffi_copy(jit_State *J, RecordFFData *rd)
5✔
1657
{
1658
  CTState *cts = ctype_ctsG(J2G(J));
5✔
1659
  TRef trdst = J->base[0], trsrc = J->base[1], trlen = J->base[2];
5✔
1660
  if (trdst && trsrc && (trlen || tref_isstr(trsrc))) {
5✔
1661
    trdst = crec_ct_tv(J, ctype_get(cts, CTID_P_VOID), 0, trdst, &rd->argv[0]);
5✔
1662
    trsrc = crec_ct_tv(J, ctype_get(cts, CTID_P_CVOID), 0, trsrc, &rd->argv[1]);
5✔
1663
    if (trlen) {
5✔
1664
      trlen = crec_toint(J, cts, trlen, &rd->argv[2]);
4✔
1665
    } else {
1666
      trlen = emitir(IRTI(IR_FLOAD), J->base[1], IRFL_STR_LEN);
1✔
1667
      trlen = emitir(IRTI(IR_ADD), trlen, lj_ir_kint(J, 1));
1✔
1668
    }
1669
    rd->nres = 0;
5✔
1670
    crec_copy(J, trdst, trsrc, trlen, NULL);
5✔
1671
  }  /* else: interpreter will throw. */
1672
}
5✔
1673

1674
void LJ_FASTCALL recff_ffi_fill(jit_State *J, RecordFFData *rd)
3✔
1675
{
1676
  CTState *cts = ctype_ctsG(J2G(J));
3✔
1677
  TRef trdst = J->base[0], trlen = J->base[1], trfill = J->base[2];
3✔
1678
  if (trdst && trlen) {
3✔
1679
    CTSize step = 1;
3✔
1680
    if (tviscdata(&rd->argv[0])) {  /* Get alignment of original destination. */
3✔
1681
      CTSize sz;
3✔
1682
      CType *ct = ctype_raw(cts, cdataV(&rd->argv[0])->ctypeid);
3✔
1683
      if (ctype_isptr(ct->info))
3✔
1684
        ct = ctype_rawchild(cts, ct);
2✔
1685
      step = (1u<<ctype_align(lj_ctype_info(cts, ctype_typeid(cts, ct), &sz)));
3✔
1686
    }
1687
    trdst = crec_ct_tv(J, ctype_get(cts, CTID_P_VOID), 0, trdst, &rd->argv[0]);
3✔
1688
    trlen = crec_toint(J, cts, trlen, &rd->argv[1]);
3✔
1689
    if (trfill)
3✔
1690
      trfill = crec_toint(J, cts, trfill, &rd->argv[2]);
3✔
1691
    else
1692
      trfill = lj_ir_kint(J, 0);
×
1693
    rd->nres = 0;
3✔
1694
    crec_fill(J, trdst, trlen, trfill, step);
3✔
1695
  }  /* else: interpreter will throw. */
1696
}
3✔
1697

1698
void LJ_FASTCALL recff_ffi_typeof(jit_State *J, RecordFFData *rd)
1✔
1699
{
1700
  if (tref_iscdata(J->base[0])) {
1✔
1701
    TRef trid = lj_ir_kint(J, argv2ctype(J, J->base[0], &rd->argv[0]));
1✔
1702
    J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA),
1✔
1703
                        lj_ir_kint(J, CTID_CTYPEID), trid);
1704
  } else {
1705
    setfuncV(J->L, &J->errinfo, J->fn);
×
1706
    lj_trace_err_info(J, LJ_TRERR_NYIFFU);
×
1707
  }
1708
}
1✔
1709

1710
void LJ_FASTCALL recff_ffi_istype(jit_State *J, RecordFFData *rd)
3✔
1711
{
1712
  argv2ctype(J, J->base[0], &rd->argv[0]);
3✔
1713
  if (tref_iscdata(J->base[1])) {
3✔
1714
    argv2ctype(J, J->base[1], &rd->argv[1]);
3✔
1715
    J->postproc = LJ_POST_FIXBOOL;
3✔
1716
    J->base[0] = TREF_TRUE;
3✔
1717
  } else {
1718
    J->base[0] = TREF_FALSE;
×
1719
  }
1720
}
3✔
1721

1722
void LJ_FASTCALL recff_ffi_abi(jit_State *J, RecordFFData *rd)
11✔
1723
{
1724
  if (tref_isstr(J->base[0])) {
11✔
1725
    /* Specialize to the ABI string to make the boolean result a constant. */
1726
    emitir(IRTG(IR_EQ, IRT_STR), J->base[0], lj_ir_kstr(J, strV(&rd->argv[0])));
11✔
1727
    J->postproc = LJ_POST_FIXBOOL;
11✔
1728
    J->base[0] = TREF_TRUE;
11✔
1729
  } else {
1730
    lj_trace_err(J, LJ_TRERR_BADTYPE);
×
1731
  }
1732
}
11✔
1733

1734
/* Record ffi.sizeof(), ffi.alignof(), ffi.offsetof(). */
1735
void LJ_FASTCALL recff_ffi_xof(jit_State *J, RecordFFData *rd)
5✔
1736
{
1737
  CTypeID id = argv2ctype(J, J->base[0], &rd->argv[0]);
5✔
1738
  if (rd->data == FF_ffi_sizeof) {
5✔
1739
    CType *ct = lj_ctype_rawref(ctype_ctsG(J2G(J)), id);
5✔
1740
    if (ctype_isvltype(ct->info))
5✔
1741
      lj_trace_err(J, LJ_TRERR_BADTYPE);
4✔
1742
  } else if (rd->data == FF_ffi_offsetof) {  /* Specialize to the field name. */
×
1743
    if (!tref_isstr(J->base[1]))
×
1744
      lj_trace_err(J, LJ_TRERR_BADTYPE);
×
1745
    emitir(IRTG(IR_EQ, IRT_STR), J->base[1], lj_ir_kstr(J, strV(&rd->argv[1])));
×
1746
    rd->nres = 3;  /* Just in case. */
×
1747
  }
1748
  J->postproc = LJ_POST_FIXCONST;
1✔
1749
  J->base[0] = J->base[1] = J->base[2] = TREF_NIL;
1✔
1750
}
1✔
1751

1752
void LJ_FASTCALL recff_ffi_gc(jit_State *J, RecordFFData *rd)
×
1753
{
1754
  argv2cdata(J, J->base[0], &rd->argv[0]);
×
1755
  if (!J->base[1])
×
1756
    lj_trace_err(J, LJ_TRERR_BADTYPE);
×
1757
  crec_finalizer(J, J->base[0], J->base[1], &rd->argv[1]);
×
1758
}
×
1759

1760
/* -- 64 bit bit.* library functions -------------------------------------- */
1761

1762
/* Determine bit operation type from argument type. */
1763
static CTypeID crec_bit64_type(CTState *cts, cTValue *tv)
1764
{
1765
  if (tviscdata(tv)) {
1766
    CType *ct = lj_ctype_rawref(cts, cdataV(tv)->ctypeid);
1767
    if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct);
1768
    if ((ct->info & (CTMASK_NUM|CTF_BOOL|CTF_FP|CTF_UNSIGNED)) ==
1769
        CTINFO(CT_NUM, CTF_UNSIGNED) && ct->size == 8)
1770
      return CTID_UINT64;  /* Use uint64_t, since it has the highest rank. */
1771
    return CTID_INT64;  /* Otherwise use int64_t. */
1772
  }
1773
  return 0;  /* Use regular 32 bit ops. */
1774
}
1775

1776
void LJ_FASTCALL recff_bit64_tobit(jit_State *J, RecordFFData *rd)
×
1777
{
1778
  CTState *cts = ctype_ctsG(J2G(J));
×
1779
  TRef tr = crec_ct_tv(J, ctype_get(cts, CTID_INT64), 0,
×
1780
                       J->base[0], &rd->argv[0]);
×
1781
  if (!tref_isinteger(tr))
×
1782
    tr = emitconv(tr, IRT_INT, tref_type(tr), 0);
×
1783
  J->base[0] = tr;
×
1784
}
×
1785

1786
int LJ_FASTCALL recff_bit64_unary(jit_State *J, RecordFFData *rd)
4✔
1787
{
1788
  CTState *cts = ctype_ctsG(J2G(J));
4✔
1789
  CTypeID id = crec_bit64_type(cts, &rd->argv[0]);
4✔
1790
  if (id) {
4✔
1791
    TRef tr = crec_ct_tv(J, ctype_get(cts, id), 0, J->base[0], &rd->argv[0]);
2✔
1792
    tr = emitir(IRT(rd->data, id-CTID_INT64+IRT_I64), tr, 0);
2✔
1793
    J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr);
2✔
1794
    return 1;
2✔
1795
  }
1796
  return 0;
1797
}
1798

1799
int LJ_FASTCALL recff_bit64_nary(jit_State *J, RecordFFData *rd)
199✔
1800
{
1801
  CTState *cts = ctype_ctsG(J2G(J));
199✔
1802
  CTypeID id = 0;
199✔
1803
  MSize i;
199✔
1804
  for (i = 0; J->base[i] != 0; i++) {
597✔
1805
    CTypeID aid = crec_bit64_type(cts, &rd->argv[i]);
398✔
1806
    if (id < aid) id = aid;  /* Determine highest type rank of all arguments. */
398✔
1807
  }
1808
  if (id) {
199✔
1809
    CType *ct = ctype_get(cts, id);
24✔
1810
    uint32_t ot = IRT(rd->data, id-CTID_INT64+IRT_I64);
24✔
1811
    TRef tr = crec_ct_tv(J, ct, 0, J->base[0], &rd->argv[0]);
24✔
1812
    for (i = 1; J->base[i] != 0; i++) {
72✔
1813
      TRef tr2 = crec_ct_tv(J, ct, 0, J->base[i], &rd->argv[i]);
24✔
1814
      tr = emitir(ot, tr, tr2);
24✔
1815
    }
1816
    J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr);
24✔
1817
    return 1;
24✔
1818
  }
1819
  return 0;
1820
}
1821

1822
int LJ_FASTCALL recff_bit64_shift(jit_State *J, RecordFFData *rd)
48✔
1823
{
1824
  CTState *cts = ctype_ctsG(J2G(J));
48✔
1825
  CTypeID id;
48✔
1826
  TRef tsh = 0;
48✔
1827
  if (J->base[0] && tref_iscdata(J->base[1])) {
48✔
1828
    tsh = crec_ct_tv(J, ctype_get(cts, CTID_INT64), 0,
6✔
1829
                     J->base[1], &rd->argv[1]);
3✔
1830
    if (!tref_isinteger(tsh))
3✔
1831
      tsh = emitconv(tsh, IRT_INT, tref_type(tsh), 0);
3✔
1832
    J->base[1] = tsh;
3✔
1833
  }
1834
  id = crec_bit64_type(cts, &rd->argv[0]);
48✔
1835
  if (id) {
48✔
1836
    TRef tr = crec_ct_tv(J, ctype_get(cts, id), 0, J->base[0], &rd->argv[0]);
14✔
1837
    uint32_t op = rd->data;
14✔
1838
    if (!tsh) tsh = lj_opt_narrow_tobit(J, J->base[1]);
14✔
1839
    if (!(op < IR_BROL ? LJ_TARGET_MASKSHIFT : LJ_TARGET_MASKROT) &&
14✔
1840
        !tref_isk(tsh))
1841
      tsh = emitir(IRTI(IR_BAND), tsh, lj_ir_kint(J, 63));
1842
#ifdef LJ_TARGET_UNIFYROT
1843
      if (op == (LJ_TARGET_UNIFYROT == 1 ? IR_BROR : IR_BROL)) {
1844
        op = LJ_TARGET_UNIFYROT == 1 ? IR_BROL : IR_BROR;
1845
        tsh = emitir(IRTI(IR_NEG), tsh, tsh);
1846
      }
1847
#endif
1848
    tr = emitir(IRT(op, id-CTID_INT64+IRT_I64), tr, tsh);
14✔
1849
    J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr);
14✔
1850
    return 1;
14✔
1851
  }
1852
  return 0;
1853
}
1854

1855
TRef recff_bit64_tohex(jit_State *J, RecordFFData *rd, TRef hdr)
14✔
1856
{
1857
  CTState *cts = ctype_ctsG(J2G(J));
14✔
1858
  CTypeID id = crec_bit64_type(cts, &rd->argv[0]);
14✔
1859
  TRef tr, trsf = J->base[1];
14✔
1860
  SFormat sf = (STRFMT_UINT|STRFMT_T_HEX);
14✔
1861
  int32_t n;
14✔
1862
  if (trsf) {
14✔
1863
    CTypeID id2 = 0;
13✔
1864
    n = (int32_t)lj_carith_check64(J->L, 2, &id2);
13✔
1865
    if (id2)
13✔
1866
      trsf = crec_ct_tv(J, ctype_get(cts, CTID_INT32), 0, trsf, &rd->argv[1]);
×
1867
    else
1868
      trsf = lj_opt_narrow_tobit(J, trsf);
13✔
1869
    emitir(IRTGI(IR_EQ), trsf, lj_ir_kint(J, n));  /* Specialize to n. */
13✔
1870
  } else {
1871
    n = id ? 16 : 8;
1✔
1872
  }
1873
  if (n < 0) { n = -n; sf |= STRFMT_F_UPPER; }
14✔
1874
  sf |= ((SFormat)((n+1)&255) << STRFMT_SH_PREC);
14✔
1875
  if (id) {
14✔
1876
    tr = crec_ct_tv(J, ctype_get(cts, id), 0, J->base[0], &rd->argv[0]);
×
1877
    if (n < 16)
×
1878
      tr = emitir(IRT(IR_BAND, IRT_U64), tr,
×
1879
                  lj_ir_kint64(J, ((uint64_t)1 << 4*n)-1));
1880
  } else {
1881
    tr = lj_opt_narrow_tobit(J, J->base[0]);
14✔
1882
    if (n < 8)
13✔
1883
      tr = emitir(IRTI(IR_BAND), tr, lj_ir_kint(J, (int32_t)((1u << 4*n)-1)));
12✔
1884
    tr = emitconv(tr, IRT_U64, IRT_INT, 0);  /* No sign-extension. */
13✔
1885
    lj_needsplit(J);
13✔
1886
  }
1887
  return lj_ir_call(J, IRCALL_lj_strfmt_putfxint, hdr, lj_ir_kint(J, sf), tr);
13✔
1888
}
1889

1890
/* -- Miscellaneous library functions ------------------------------------- */
1891

1892
void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd)
15✔
1893
{
1894
  CTState *cts = ctype_ctsG(J2G(J));
15✔
1895
  CType *d, *ct = lj_ctype_rawref(cts, cdataV(&rd->argv[0])->ctypeid);
15✔
1896
  if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct);
15✔
1897
  if (ctype_isnum(ct->info) || ctype_iscomplex(ct->info)) {
15✔
1898
    if (ctype_isinteger_or_bool(ct->info) && ct->size <= 4 &&
14✔
1899
        !(ct->size == 4 && (ct->info & CTF_UNSIGNED)))
×
1900
      d = ctype_get(cts, CTID_INT32);
×
1901
    else
1902
      d = ctype_get(cts, CTID_DOUBLE);
14✔
1903
    J->base[0] = crec_ct_tv(J, d, 0, J->base[0], &rd->argv[0]);
14✔
1904
  } else {
1905
    /* Specialize to the ctype that couldn't be converted. */
1906
    argv2cdata(J, J->base[0], &rd->argv[0]);
1✔
1907
    J->base[0] = TREF_NIL;
1✔
1908
  }
1909
}
15✔
1910

1911
#undef IR
1912
#undef emitir
1913
#undef emitconv
1914

1915
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc