~ubuntu-branches/ubuntu/raring/luajit/raring-proposed

« back to all changes in this revision

Viewing changes to src/lj_crecord.c

  • Committer: Bazaar Package Importer
  • Author(s): Enrico Tassi
  • Date: 2011-02-13 13:22:20 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20110213132220-v7lgyan47fazf0js
Tags: 2.0.0~beta6+dfsg-1
* new upstream release
* watch file updated 
* updated standards-version to 3.9.1, no change needed
* updated copyright (extends to 2011)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
** Trace recorder for C data operations.
 
3
** Copyright (C) 2005-2011 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_str.h"
 
15
#include "lj_tab.h"
 
16
#include "lj_frame.h"
 
17
#include "lj_ctype.h"
 
18
#include "lj_cparse.h"
 
19
#include "lj_cconv.h"
 
20
#include "lj_clib.h"
 
21
#include "lj_ir.h"
 
22
#include "lj_jit.h"
 
23
#include "lj_iropt.h"
 
24
#include "lj_trace.h"
 
25
#include "lj_ffrecord.h"
 
26
#include "lj_crecord.h"
 
27
#include "lj_dispatch.h"
 
28
 
 
29
/* Some local macros to save typing. Undef'd at the end. */
 
30
#define IR(ref)                 (&J->cur.ir[(ref)])
 
31
 
 
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))
 
34
 
 
35
#define emitconv(a, dt, st, flags) \
 
36
  emitir(IRT(IR_CONV, (dt)), (a), (st)|((dt) << 5)|(flags))
 
37
 
 
38
/* -- C type checks ------------------------------------------------------- */
 
39
 
 
40
static GCcdata *argv2cdata(jit_State *J, TRef tr, cTValue *o)
 
41
{
 
42
  GCcdata *cd;
 
43
  TRef trtypeid;
 
44
  if (!tref_iscdata(tr))
 
45
    lj_trace_err(J, LJ_TRERR_BADTYPE);
 
46
  cd = cdataV(o);
 
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));
 
50
  return cd;
 
51
}
 
52
 
 
53
static CTypeID argv2ctype(jit_State *J, TRef tr, cTValue *o)
 
54
{
 
55
  if (tref_isstr(tr)) {
 
56
    GCstr *s = strV(o);
 
57
    CPState cp;
 
58
    CTypeID oldtop;
 
59
    /* Specialize to the string containing the C type declaration. */
 
60
    emitir(IRTG(IR_EQ, IRT_STR), tr, lj_ir_kstr(J, s));
 
61
    cp.L = J->L;
 
62
    cp.cts = ctype_ctsG(J2G(J));
 
63
    oldtop = cp.cts->top;
 
64
    cp.srcname = strdata(s);
 
65
    cp.p = 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);
 
69
    return cp.val.id;
 
70
  } else {
 
71
    GCcdata *cd = argv2cdata(J, tr, o);
 
72
    return cd->typeid == CTID_CTYPEID ? *(CTypeID *)cdataptr(cd) : cd->typeid;
 
73
  }
 
74
}
 
75
 
 
76
/* -- Convert C type to C type -------------------------------------------- */
 
77
 
 
78
/*
 
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.
 
81
**
 
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.
 
86
**
 
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
 
91
** trigger asserts.
 
92
*/
 
93
 
 
94
/* Convert CType to IRType. */
 
95
static IRType crec_ct2irt(CType *ct)
 
96
{
 
97
  if (LJ_LIKELY(ctype_isnum(ct->info))) {
 
98
    if ((ct->info & CTF_FP)) {
 
99
      if (ct->size == sizeof(double))
 
100
        return IRT_NUM;
 
101
      else if (ct->size == sizeof(float))
 
102
        return IRT_FLOAT;
 
103
    } else {
 
104
      uint32_t b = lj_fls(ct->size);
 
105
      if (b <= 3)
 
106
        return IRT_I8 + 2*b + ((ct->info & CTF_UNSIGNED) ? 1 : 0);
 
107
    }
 
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))
 
112
      return IRT_NUM;
 
113
    else if (ct->size == 2*sizeof(float))
 
114
      return IRT_FLOAT;
 
115
  }
 
116
  return IRT_CDATA;
 
117
}
 
118
 
 
119
/* Determine whether a passed number or cdata number is non-zero. */
 
120
static int crec_isnonzero(CType *s, void *p)
 
121
{
 
122
  if (p == (void *)0)
 
123
    return 0;
 
124
  if (p == (void *)1)
 
125
    return 1;
 
126
  if ((s->info & CTF_FP)) {
 
127
    if (s->size == sizeof(float))
 
128
      return (*(float *)p != 0);
 
129
    else
 
130
      return (*(double *)p != 0);
 
131
  } else {
 
132
    if (s->size == 1)
 
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);
 
138
    else
 
139
      return (*(uint64_t *)p != 0);
 
140
  }
 
141
}
 
142
 
 
143
static TRef crec_ct_ct(jit_State *J, CType *d, CType *s, TRef dp, TRef sp,
 
144
                       void *svisnz)
 
145
{
 
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);
 
150
 
 
151
  if (ctype_type(dinfo) > CT_MAYCONVERT || ctype_type(sinfo) > CT_MAYCONVERT)
 
152
    goto err_conv;
 
153
 
 
154
  /*
 
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.
 
157
  */
 
158
 
 
159
  switch (cconv_idx2(dinfo, sinfo)) {
 
160
  /* Destination is a bool. */
 
161
  case CCX(B, B):
 
162
    goto xstore;  /* Source operand is already normalized. */
 
163
  case CCX(B, I):
 
164
  case CCX(B, F):
 
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) :
 
169
                  lj_ir_kint(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);
 
173
      goto xstore;
 
174
    }
 
175
    goto err_nyi;
 
176
 
 
177
  /* Destination is an integer. */
 
178
  case CCX(I, B):
 
179
  case CCX(I, I):
 
180
  conv_I_I:
 
181
    if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi;
 
182
#if LJ_64
 
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. */
 
187
#else
 
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);
 
193
#endif
 
194
  xstore:
 
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);
 
198
    break;
 
199
  case CCX(I, C):
 
200
    sp = emitir(IRT(IR_XLOAD, st), sp, 0);  /* Load re. */
 
201
    /* fallthrough */
 
202
  case CCX(I, F):
 
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);
 
205
    goto xstore;
 
206
  case CCX(I, P):
 
207
  case CCX(I, A):
 
208
    sinfo = CTINFO(CT_NUM, CTF_UNSIGNED);
 
209
    ssize = CTSIZE_PTR;
 
210
    st = IRT_UINTP;
 
211
    goto conv_I_I;
 
212
 
 
213
  /* Destination is a floating-point number. */
 
214
  case CCX(F, B):
 
215
  case CCX(F, I):
 
216
  conv_F_I:
 
217
    if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi;
 
218
    sp = emitconv(sp, dt, ssize < 4 ? IRT_INT : st, 0);
 
219
    goto xstore;
 
220
  case CCX(F, C):
 
221
    sp = emitir(IRT(IR_XLOAD, st), sp, 0);  /* Load re. */
 
222
    /* fallthrough */
 
223
  case CCX(F, F):
 
224
  conv_F_F:
 
225
    if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi;
 
226
    if (dt != st) sp = emitconv(sp, dt, st, 0);
 
227
    goto xstore;
 
228
 
 
229
  /* Destination is a complex number. */
 
230
  case CCX(C, I):
 
231
  case CCX(C, F):
 
232
    {  /* Clear im. */
 
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));
 
235
    }
 
236
    /* Convert to re. */
 
237
    if ((sinfo & CTF_FP)) goto conv_F_F; else goto conv_F_I;
 
238
 
 
239
  case CCX(C, C):
 
240
    if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi;
 
241
    {
 
242
      TRef re, im, ptr;
 
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);
 
246
      if (dt != st) {
 
247
        re = emitconv(re, dt, st, 0);
 
248
        im = emitconv(im, dt, st, 0);
 
249
      }
 
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);
 
253
    }
 
254
    break;
 
255
 
 
256
  /* Destination is a vector. */
 
257
  case CCX(V, I):
 
258
  case CCX(V, F):
 
259
  case CCX(V, C):
 
260
  case CCX(V, V):
 
261
    goto err_nyi;
 
262
 
 
263
  /* Destination is a pointer. */
 
264
  case CCX(P, P):
 
265
  case CCX(P, A):
 
266
  case CCX(P, S):
 
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.
 
269
    */
 
270
    goto xstore;
 
271
  case CCX(P, I):
 
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);
 
275
    goto xstore;
 
276
  case CCX(P, F):
 
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);
 
281
    goto xstore;
 
282
 
 
283
  /* Destination is an array. */
 
284
  case CCX(A, A):
 
285
    goto err_nyi;
 
286
 
 
287
  /* Destination is a struct/union. */
 
288
  case CCX(S, S):
 
289
    goto err_nyi;
 
290
 
 
291
  default:
 
292
  err_conv:
 
293
  err_nyi:
 
294
    lj_trace_err(J, LJ_TRERR_NYICONV);
 
295
    break;
 
296
  }
 
297
  return 0;
 
298
}
 
299
 
 
300
/* -- Convert C type to TValue (load) ------------------------------------- */
 
301
 
 
302
static TRef crec_tv_ct(jit_State *J, CType *s, CTypeID sid, TRef sp)
 
303
{
 
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);
 
309
    TRef tr;
 
310
    if (t == IRT_CDATA)
 
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. */
 
316
      sp = tr;
 
317
      lj_needsplit(J);
 
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;
 
322
      return TREF_TRUE;
 
323
    } else {
 
324
      return tr;
 
325
    }
 
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)) {
 
330
    cts->L = J->L;
 
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);
 
344
    return dp;
 
345
  } else {
 
346
    /* NYI: copyval of vectors. */
 
347
  err_nyi:
 
348
    lj_trace_err(J, LJ_TRERR_NYICONV);
 
349
  }
 
350
  /* Box pointer, ref or 64 bit integer. */
 
351
  return emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, sid), sp);
 
352
}
 
353
 
 
354
/* -- Convert TValue to C type (store) ------------------------------------ */
 
355
 
 
356
static TRef crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, TValue *sval)
 
357
{
 
358
  CTState *cts = ctype_ctsG(J2G(J));
 
359
  CTypeID sid = CTID_P_VOID;
 
360
  void *svisnz = 0;
 
361
  CType *s;
 
362
  if (LJ_LIKELY(tref_isinteger(sp))) {
 
363
    sid = CTID_INT32;
 
364
    svisnz = (void *)(intptr_t)(numV(sval) != 0);
 
365
  } else if (tref_isnum(sp)) {
 
366
    sid = CTID_DOUBLE;
 
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);
 
370
    sid = CTID_BOOL;
 
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);
 
378
      CTSize ofs;
 
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));
 
392
      sid = CTID_A_CCHAR;
 
393
    }
 
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);
 
404
      } else {
 
405
        goto doconv;  /* The pointer value was loaded, don't load number. */
 
406
      }
 
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);
 
410
      lj_needsplit(J);
 
411
      goto doconv;
 
412
    } else {
 
413
      sp = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, sizeof(GCcdata)));
 
414
    }
 
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);
 
421
      }
 
422
    }
 
423
    goto doconv;
 
424
  }
 
425
  s = ctype_get(cts, sid);
 
426
doconv:
 
427
  if (ctype_isenum(d->info)) d = ctype_child(cts, d);
 
428
  return crec_ct_ct(J, d, s, dp, sp, svisnz);
 
429
}
 
430
 
 
431
/* -- C data metamethods -------------------------------------------------- */
 
432
 
 
433
/* Specialize to the CTypeID held by a cdata constructor. */
 
434
static CTypeID crec_constructor(jit_State *J, GCcdata *cd, TRef tr)
 
435
{
 
436
  CTypeID id;
 
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));
 
442
  return id;
 
443
}
 
444
 
 
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)
 
448
*/
 
449
static TRef crec_reassoc_ofs(jit_State *J, TRef tr, ptrdiff_t *ofsp, MSize sz)
 
450
{
 
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);
 
455
    tr = ir->op1;
 
456
#if LJ_64
 
457
    if (irk->o == IR_KINT64)
 
458
      *ofsp += (ptrdiff_t)ir_kint64(irk)->u64 * sz;
 
459
    else
 
460
#endif
 
461
      *ofsp += (ptrdiff_t)irk->i * sz;
 
462
  }
 
463
  return tr;
 
464
}
 
465
 
 
466
void LJ_FASTCALL recff_cdata_index(jit_State *J, RecordFFData *rd)
 
467
{
 
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);
 
473
  CTypeID sid = 0;
 
474
 
 
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);
 
480
    ofs = 0;
 
481
    ptr = crec_reassoc_ofs(J, ptr, &ofs, 1);
 
482
  }
 
483
 
 
484
  idx = J->base[1];
 
485
  if (tref_isnumber(idx)) {
 
486
    /* The size of a ptrdiff_t is target-specific. */
 
487
#if LJ_64
 
488
    if (tref_isnum(idx))
 
489
      idx = emitconv(idx, IRT_I64, IRT_NUM, IRCONV_TRUNC|IRCONV_ANY);
 
490
    else
 
491
      idx = emitconv(idx, IRT_I64, IRT_INT, IRCONV_SEXT);
 
492
#else
 
493
    if (tref_isnum(idx))
 
494
      idx = emitconv(idx, IRT_INT, IRT_NUM, IRCONV_TRUNC|IRCONV_ANY);
 
495
#endif
 
496
  integer_key:
 
497
    if (ctype_ispointer(ct->info)) {
 
498
      CTSize sz;
 
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);
 
505
    }
 
506
  } else if (tref_iscdata(idx)) {
 
507
    GCcdata *cdk = cdataV(&rd->argv[1]);
 
508
    CType *ctk = ctype_raw(cts, cdk->typeid);
 
509
    IRType t;
 
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);
 
516
        lj_needsplit(J);
 
517
      }
 
518
      goto integer_key;
 
519
    }
 
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)) {
 
529
        ct = cct;
 
530
        goto index_struct;
 
531
      }
 
532
    } else if (ctype_isstruct(ct->info)) {
 
533
      CTSize fofs;
 
534
      CType *fct;
 
535
index_struct:
 
536
      fct = lj_ctype_getfield(cts, ct, name, &fofs);
 
537
      if (fct) {
 
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);
 
542
            return;
 
543
          }
 
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);
 
548
        } else {
 
549
          lua_assert(ctype_isfield(fct->info));
 
550
          sid = ctype_cid(fct->info);
 
551
        }
 
552
        ofs += (ptrdiff_t)fofs;
 
553
      }
 
554
    } else if (ctype_iscomplex(ct->info)) {
 
555
      if (strdata(name)[0] == 'i') ofs += (ct->size >> 1);
 
556
      sid = ctype_cid(ct->info);
 
557
    }
 
558
  }
 
559
  if (!sid) lj_trace_err(J, LJ_TRERR_BADTYPE);
 
560
 
 
561
  if (ofs)
 
562
    ptr = emitir(IRT(IR_ADD, IRT_PTR), ptr, lj_ir_kintp(J, ofs));
 
563
 
 
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);
 
568
 
 
569
  while (ctype_isattrib(ct->info))
 
570
    ct = ctype_child(cts, ct);  /* Skip attributes. */
 
571
 
 
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. */
 
576
    rd->nres = 0;
 
577
    J->needsnap = 1;
 
578
    crec_ct_tv(J, ct, ptr, J->base[2], &rd->argv[2]);
 
579
  }
 
580
}
 
581
 
 
582
/* Record cdata allocation. */
 
583
static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id)
 
584
{
 
585
  CTState *cts = ctype_ctsG(J2G(J));
 
586
  CTSize sz;
 
587
  CTInfo info = lj_ctype_info(cts, id, &sz);
 
588
  CType *d = ctype_raw(cts, id);
 
589
  TRef trid;
 
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);
 
599
  } else {
 
600
    TRef trcd = emitir(IRTG(IR_CNEW, IRT_CDATA), trid, TREF_NIL);
 
601
    J->base[0] = trcd;
 
602
    if (J->base[1] && !J->base[2] && !lj_cconv_multi_init(d, &rd->argv[1])) {
 
603
      goto single_init;
 
604
    } else if (ctype_isarray(d->info)) {
 
605
      CType *dc = ctype_rawchild(cts, d);  /* Array element type. */
 
606
      CTSize ofs, esize = dc->size;
 
607
      TRef sp = 0;
 
608
      TValue tv;
 
609
      TValue *sval = &tv;
 
610
      MSize i;
 
611
      tv.u64 = 0;
 
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)));
 
617
        if (J->base[i]) {
 
618
          sp = J->base[i];
 
619
          sval = &rd->argv[i];
 
620
          i++;
 
621
        } else if (i != 2) {
 
622
          sp = ctype_isnum(dc->info) ? lj_ir_kint(J, 0) : TREF_NIL;
 
623
        }
 
624
        crec_ct_tv(J, dc, dp, sp, sval);
 
625
      }
 
626
    } else if (ctype_isstruct(d->info)) {
 
627
      CTypeID fid = d->sib;
 
628
      MSize i = 1;
 
629
      while (fid) {
 
630
        CType *df = ctype_get(cts, fid);
 
631
        fid = df->sib;
 
632
        if (ctype_isfield(df->info)) {
 
633
          CType *dc;
 
634
          TRef sp, dp;
 
635
          TValue tv;
 
636
          TValue *sval = &tv;
 
637
          setnumV(&tv, 0);
 
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. */
 
642
          if (J->base[i]) {
 
643
            sp = J->base[i];
 
644
            sval = &rd->argv[i];
 
645
            i++;
 
646
          } else {
 
647
            sp = ctype_isnum(dc->info) ? lj_ir_kint(J, 0) : TREF_NIL;
 
648
          }
 
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);
 
655
        }
 
656
      }
 
657
    } else {
 
658
      TRef dp;
 
659
    single_init:
 
660
      dp = emitir(IRT(IR_ADD, IRT_PTR), trcd, lj_ir_kintp(J, sizeof(GCcdata)));
 
661
      if (J->base[1]) {
 
662
        crec_ct_tv(J, d, dp, J->base[1], &rd->argv[1]);
 
663
      } else {
 
664
        TValue tv;
 
665
        tv.u64 = 0;
 
666
        crec_ct_tv(J, d, dp, lj_ir_kint(J, 0), &tv);
 
667
      }
 
668
    }
 
669
  }
 
670
}
 
671
 
 
672
/* Record argument conversions. */
 
673
static TRef crec_call_args(jit_State *J, RecordFFData *rd,
 
674
                           CTState *cts, CType *ct)
 
675
{
 
676
  TRef args[CCI_NARGS_MAX];
 
677
  MSize i, n;
 
678
  TRef tr;
 
679
  args[0] = TREF_NIL;
 
680
  for (n = 0; J->base[n+1]; n++) {
 
681
    CType *d;
 
682
    do {
 
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]);
 
694
  }
 
695
  tr = args[0];
 
696
  for (i = 1; i < n; i++)
 
697
    tr = emitir(IRT(IR_CARG, IRT_NIL), tr, args[i]);
 
698
  return tr;
 
699
}
 
700
 
 
701
/* Record function call. */
 
702
static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd)
 
703
{
 
704
  CTState *cts = ctype_ctsG(J2G(J));
 
705
  CType *ct = ctype_raw(cts, cd->typeid);
 
706
  IRType tp = IRT_PTR;
 
707
  if (ctype_isptr(ct->info)) {
 
708
    tp = (LJ_64 && ct->size == 8) ? IRT_P64 : IRT_P32;
 
709
    ct = ctype_rawchild(cts, ct);
 
710
  }
 
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);
 
715
    TRef tr;
 
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) ||
 
719
#if LJ_TARGET_X86
 
720
        ctype_cconv(ct->info) != CTCC_CDECL ||
 
721
#endif
 
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);
 
731
    }
 
732
    J->base[0] = tr;
 
733
    return 1;
 
734
  }
 
735
  return 0;
 
736
}
 
737
 
 
738
void LJ_FASTCALL recff_cdata_call(jit_State *J, RecordFFData *rd)
 
739
{
 
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);
 
745
}
 
746
 
 
747
static TRef crec_arith_int64(jit_State *J, TRef *sp, CType **s, MMS mm)
 
748
{
 
749
  if (ctype_isnum(s[0]->info) && ctype_isnum(s[1]->info)) {
 
750
    IRType dt;
 
751
    CTypeID id;
 
752
    TRef tr;
 
753
    MSize i;
 
754
    lj_needsplit(J);
 
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;
 
758
    } else {
 
759
      dt = IRT_I64; id = CTID_INT64;
 
760
    }
 
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);
 
768
    }
 
769
    if (mm < MM_add) {
 
770
      /* Assume true comparison. Fixup and emit pending guard later. */
 
771
      IROp op;
 
772
      if (mm == MM_eq) {
 
773
        op = IR_EQ;
 
774
      } else {
 
775
        op = mm == MM_lt ? IR_LT : IR_LE;
 
776
        if (dt == IRT_U64)
 
777
          op += (IR_ULT-IR_LT);
 
778
      }
 
779
      lj_ir_set(J, IRTG(op, dt), sp[0], sp[1]);
 
780
      J->postproc = LJ_POST_FIXGUARD;
 
781
      return TREF_TRUE;
 
782
    } else {
 
783
      tr = emitir(IRT(mm+(int)IR_ADD-(int)MM_add, dt), sp[0], sp[1]);
 
784
    }
 
785
    return emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr);
 
786
  }
 
787
  return 0;
 
788
}
 
789
 
 
790
static TRef crec_arith_ptr(jit_State *J, TRef *sp, CType **s, MMS mm)
 
791
{
 
792
  CTState *cts = ctype_ctsG(J2G(J));
 
793
  CType *ctp = s[0];
 
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. */
 
798
        TRef tr;
 
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)));
 
804
#if LJ_64
 
805
        tr = emitconv(tr, IRT_NUM, IRT_INTP, 0);
 
806
#endif
 
807
        return tr;
 
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;
 
813
        return TREF_TRUE;
 
814
      }
 
815
    }
 
816
    if (!((mm == MM_add || mm == MM_sub) && ctype_isnum(s[1]->info)))
 
817
      return 0;
 
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. */
 
821
    ctp = s[1];
 
822
  } else {
 
823
    return 0;
 
824
  }
 
825
  {
 
826
    TRef tr = sp[1];
 
827
    IRType t = tref_type(tr);
 
828
    CTSize sz = lj_ctype_size(cts, ctype_cid(ctp->info));
 
829
    CTypeID id;
 
830
#if LJ_64
 
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);
 
836
#else
 
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);
 
841
    }
 
842
#endif
 
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)),
 
846
                         CTSIZE_PTR);
 
847
    return emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr);
 
848
  }
 
849
}
 
850
 
 
851
void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
 
852
{
 
853
  CTState *cts = ctype_ctsG(J2G(J));
 
854
  TRef sp[2];
 
855
  CType *s[2];
 
856
  MSize i;
 
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);
 
870
        lj_needsplit(J);
 
871
        goto ok;
 
872
      } else {
 
873
        tr = emitir(IRT(IR_ADD, IRT_PTR), tr, lj_ir_kintp(J, sizeof(GCcdata)));
 
874
      }
 
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))) {
 
882
        goto err_type;
 
883
      }
 
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)) {
 
890
      goto err_type;
 
891
    }
 
892
  ok:
 
893
    s[i] = ct;
 
894
    sp[i] = tr;
 
895
  }
 
896
  {
 
897
    TRef tr;
 
898
    if (!(tr = crec_arith_int64(J, sp, s, (MMS)rd->data)) &&
 
899
        !(tr = crec_arith_ptr(J, sp, s, (MMS)rd->data))) {
 
900
    err_type:
 
901
      lj_trace_err(J, LJ_TRERR_BADTYPE);
 
902
    }
 
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;
 
910
      }
 
911
    }
 
912
    J->base[0] = tr;
 
913
  }
 
914
}
 
915
 
 
916
/* -- C library namespace metamethods ------------------------------------- */
 
917
 
 
918
void LJ_FASTCALL recff_clib_index(jit_State *J, RecordFFData *rd)
 
919
{
 
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]);
 
925
    CType *ct;
 
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);
 
935
        else
 
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. */
 
939
      } else {
 
940
        J->base[0] = lj_ir_kgc(J, obj2gco(cdataV(tv)), IRT_CDATA);
 
941
      }
 
942
    } else {
 
943
      lj_trace_err(J, LJ_TRERR_NOCACHE);
 
944
    }
 
945
  }  /* else: interpreter will throw. */
 
946
}
 
947
 
 
948
/* -- FFI library functions ----------------------------------------------- */
 
949
 
 
950
static TRef crec_toint(jit_State *J, CTState *cts, TRef sp, TValue *sval)
 
951
{
 
952
  return crec_ct_tv(J, ctype_get(cts, CTID_INT32), 0, sp, sval);
 
953
}
 
954
 
 
955
void LJ_FASTCALL recff_ffi_new(jit_State *J, RecordFFData *rd)
 
956
{
 
957
  crec_alloc(J, rd, argv2ctype(J, J->base[0], &rd->argv[0]));
 
958
}
 
959
 
 
960
void LJ_FASTCALL recff_ffi_string(jit_State *J, RecordFFData *rd)
 
961
{
 
962
  CTState *cts = ctype_ctsG(J2G(J));
 
963
  TRef tr = J->base[0];
 
964
  if (tr) {
 
965
    TRef trlen = J->base[1];
 
966
    if (trlen) {
 
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]);
 
969
    } else {
 
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);
 
972
    }
 
973
    J->base[0] = emitir(IRT(IR_SNEW, IRT_STR), tr, trlen);
 
974
  }  /* else: interpreter will throw. */
 
975
}
 
976
 
 
977
void LJ_FASTCALL recff_ffi_copy(jit_State *J, RecordFFData *rd)
 
978
{
 
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]);
 
984
    if (trlen) {
 
985
      trlen = crec_toint(J, cts, trlen, &rd->argv[2]);
 
986
    } else {
 
987
      trlen = emitir(IRTI(IR_FLOAD), trsrc, IRFL_STR_LEN);
 
988
      trlen = emitir(IRTI(IR_ADD), trlen, lj_ir_kint(J, 1));
 
989
    }
 
990
    lj_ir_call(J, IRCALL_memcpy, trdst, trsrc, trlen);
 
991
    emitir(IRT(IR_XBAR, IRT_NIL), 0, 0);
 
992
  }  /* else: interpreter will throw. */
 
993
}
 
994
 
 
995
void LJ_FASTCALL recff_ffi_fill(jit_State *J, RecordFFData *rd)
 
996
{
 
997
  CTState *cts = ctype_ctsG(J2G(J));
 
998
  TRef tr = J->base[0], trlen = J->base[1], trfill = J->base[2];
 
999
  if (tr && trlen) {
 
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]);
 
1002
    if (trfill)
 
1003
      trfill = crec_toint(J, cts, trfill, &rd->argv[2]);
 
1004
    else
 
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. */
 
1009
}
 
1010
 
 
1011
void LJ_FASTCALL recff_ffi_abi(jit_State *J, RecordFFData *rd)
 
1012
{
 
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. */
 
1019
}
 
1020
 
 
1021
/* -- Miscellaneous library functions ------------------------------------- */
 
1022
 
 
1023
void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd)
 
1024
{
 
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]);
 
1030
}
 
1031
 
 
1032
#undef IR
 
1033
#undef emitir
 
1034
#undef emitconv
 
1035
 
 
1036
#endif