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

tarantool / luajit / 10940225480

19 Sep 2024 11:22AM UTC coverage: 92.845% (-0.06%) from 92.909%
10940225480

push

github

Buristan
FFI: Workaround for platform dlerror() returning NULL.

Contributed by mcclure.

(cherry picked from commit 478bcfe52)

The `ffi.load()` implementation assumes the string returned from
`dlerror()` is non-NULL and immediately dereferences it. This may lead
to a crash on POSIX platforms [1] where it is possible.

This patch adds the corresponding check and the default "dlopen failed"
error message.

Sergey Kaplun:
* added the description and the test for the problem

[1]: https://pubs.opengroup.org/onlinepubs/009695399/functions/dlerror.html

Part of tarantool/tarantool#10199

Reviewed-by: Sergey Bronnikov <sergeyb@tarantool.org>
Reviewed-by: Maxim Kokryashkin <m.kokryashkin@tarantool.org>
Signed-off-by: Sergey Kaplun <skaplun@tarantool.org>

5684 of 6027 branches covered (94.31%)

Branch coverage included in aggregate %.

2 of 2 new or added lines in 1 file covered. (100.0%)

26 existing lines in 5 files now uncovered.

21670 of 23435 relevant lines covered (92.47%)

2912061.21 hits per line

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

94.08
/src/lj_ir.c
1
/*
2
** SSA IR (Intermediate Representation) emitter.
3
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
4
*/
5

6
#define lj_ir_c
7
#define LUA_CORE
8

9
/* For pointers to libc/libm functions. */
10
#include <stdio.h>
11
#include <math.h>
12

13
#include "lj_obj.h"
14

15
#if LJ_HASJIT
16

17
#include "lj_gc.h"
18
#include "lj_buf.h"
19
#include "lj_str.h"
20
#include "lj_tab.h"
21
#include "lj_ir.h"
22
#include "lj_jit.h"
23
#include "lj_ircall.h"
24
#include "lj_iropt.h"
25
#include "lj_trace.h"
26
#if LJ_HASFFI
27
#include "lj_ctype.h"
28
#include "lj_cdata.h"
29
#include "lj_carith.h"
30
#endif
31
#include "lj_vm.h"
32
#include "lj_strscan.h"
33
#include "lj_strfmt.h"
34
#include "lj_lib.h"
35

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

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

43
/* -- IR tables ----------------------------------------------------------- */
44

45
/* IR instruction modes. */
46
LJ_DATADEF const uint8_t lj_ir_mode[IR__MAX+1] = {
47
IRDEF(IRMODE)
48
  0
49
};
50

51
/* IR type sizes. */
52
LJ_DATADEF const uint8_t lj_ir_type_size[IRT__MAX+1] = {
53
#define IRTSIZE(name, size)        size,
54
IRTDEF(IRTSIZE)
55
#undef IRTSIZE
56
  0
57
};
58

59
/* C call info for CALL* instructions. */
60
LJ_DATADEF const CCallInfo lj_ir_callinfo[] = {
61
#define IRCALLCI(cond, name, nargs, kind, type, flags) \
62
  { (ASMFunction)IRCALLCOND_##cond(name), \
63
    (nargs)|(CCI_CALL_##kind)|(IRT_##type<<CCI_OTSHIFT)|(flags) },
64
IRCALLDEF(IRCALLCI)
65
#undef IRCALLCI
66
  { NULL, 0 }
67
};
68

69
/* -- IR emitter ---------------------------------------------------------- */
70

71
/* Grow IR buffer at the top. */
72
void LJ_FASTCALL lj_ir_growtop(jit_State *J)
214✔
73
{
74
  IRIns *baseir = J->irbuf + J->irbotlim;
214✔
75
  MSize szins = J->irtoplim - J->irbotlim;
214✔
76
  if (szins) {
214✔
77
    baseir = (IRIns *)lj_mem_realloc(J->L, baseir, szins*sizeof(IRIns),
163✔
78
                                     2*szins*sizeof(IRIns));
82✔
79
    J->irtoplim = J->irbotlim + 2*szins;
81✔
80
  } else {
81
    baseir = (IRIns *)lj_mem_realloc(J->L, NULL, 0, LJ_MIN_IRSZ*sizeof(IRIns));
132✔
82
    J->irbotlim = REF_BASE - LJ_MIN_IRSZ/4;
132✔
83
    J->irtoplim = J->irbotlim + LJ_MIN_IRSZ;
132✔
84
  }
85
  J->cur.ir = J->irbuf = baseir - J->irbotlim;
213✔
86
}
213✔
87

88
/* Grow IR buffer at the bottom or shift it up. */
89
static void lj_ir_growbot(jit_State *J)
322✔
90
{
91
  IRIns *baseir = J->irbuf + J->irbotlim;
322✔
92
  MSize szins = J->irtoplim - J->irbotlim;
322✔
93
  lj_assertJ(szins != 0, "zero IR size");
322✔
94
  lj_assertJ(J->cur.nk == J->irbotlim || J->cur.nk-1 == J->irbotlim,
322✔
95
             "unexpected IR growth");
96
  if (J->cur.nins + (szins >> 1) < J->irtoplim) {
322✔
97
    /* More than half of the buffer is free on top: shift up by a quarter. */
98
    MSize ofs = szins >> 2;
84✔
99
    memmove(baseir + ofs, baseir, (J->cur.nins - J->irbotlim)*sizeof(IRIns));
84✔
100
    J->irbotlim -= ofs;
84✔
101
    J->irtoplim -= ofs;
84✔
102
    J->cur.ir = J->irbuf = baseir - J->irbotlim;
84✔
103
  } else {
104
    /* Double the buffer size, but split the growth amongst top/bottom. */
105
    IRIns *newbase = lj_mem_newt(J->L, 2*szins*sizeof(IRIns), IRIns);
238✔
106
    MSize ofs = szins >= 256 ? 128 : (szins >> 1);  /* Limit bottom growth. */
238✔
107
    memcpy(newbase + ofs, baseir, (J->cur.nins - J->irbotlim)*sizeof(IRIns));
238✔
108
    lj_mem_free(G(J->L), baseir, szins*sizeof(IRIns));
238✔
109
    J->irbotlim -= ofs;
238✔
110
    J->irtoplim = J->irbotlim + 2*szins;
238✔
111
    J->cur.ir = J->irbuf = newbase - J->irbotlim;
238✔
112
  }
113
}
322✔
114

115
/* Emit IR without any optimizations. */
116
TRef LJ_FASTCALL lj_ir_emit(jit_State *J)
1,567,453✔
117
{
118
  IRRef ref = lj_ir_nextins(J);
1,567,453✔
119
  IRIns *ir = IR(ref);
1,567,453✔
120
  IROp op = fins->o;
1,567,453✔
121
  ir->prev = J->chain[op];
1,567,453✔
122
  J->chain[op] = (IRRef1)ref;
1,567,453✔
123
  ir->o = op;
1,567,453✔
124
  ir->op1 = fins->op1;
1,567,453✔
125
  ir->op2 = fins->op2;
1,567,453✔
126
  J->guardemit.irt |= fins->t.irt;
1,567,453✔
127
  return TREF(ref, irt_t((ir->t = fins->t)));
1,567,453✔
128
}
129

130
/* Emit call to a C function. */
131
TRef lj_ir_call(jit_State *J, IRCallID id, ...)
587✔
132
{
133
  const CCallInfo *ci = &lj_ir_callinfo[id];
587✔
134
  uint32_t n = CCI_NARGS(ci);
587✔
135
  TRef tr = TREF_NIL;
587✔
136
  va_list argp;
587✔
137
  va_start(argp, id);
587✔
138
  if ((ci->flags & CCI_L)) n--;
587✔
139
  if (n > 0)
587✔
140
    tr = va_arg(argp, IRRef);
586✔
141
  while (n-- > 1)
1,680✔
142
    tr = emitir(IRT(IR_CARG, IRT_NIL), tr, va_arg(argp, IRRef));
1,093✔
143
  va_end(argp);
587✔
144
  if (CCI_OP(ci) == IR_CALLS)
587✔
145
    J->needsnap = 1;  /* Need snapshot after call with side effect. */
159✔
146
  return emitir(CCI_OPTYPE(ci), tr, id);
587✔
147
}
148

149
/* Load field of type t from GG_State + offset. Must be 32 bit aligned. */
150
LJ_FUNC TRef lj_ir_ggfload(jit_State *J, IRType t, uintptr_t ofs)
474✔
151
{
152
  lj_assertJ((ofs & 3) == 0, "unaligned GG_State field offset");
474✔
153
  ofs >>= 2;
474✔
154
  lj_assertJ(ofs >= IRFL__MAX && ofs <= 0x3ff,
474✔
155
             "GG_State field offset breaks 10 bit FOLD key limit");
156
  lj_ir_set(J, IRT(IR_FLOAD, t), REF_NIL, ofs);
474✔
157
  return lj_opt_fold(J);
474✔
158
}
159

160
/* -- Interning of constants ---------------------------------------------- */
161

162
/*
163
** IR instructions for constants are kept between J->cur.nk >= ref < REF_BIAS.
164
** They are chained like all other instructions, but grow downwards.
165
** The are interned (like strings in the VM) to facilitate reference
166
** comparisons. The same constant must get the same reference.
167
*/
168

169
/* Get ref of next IR constant and optionally grow IR.
170
** Note: this may invalidate all IRIns *!
171
*/
172
static LJ_AINLINE IRRef ir_nextk(jit_State *J)
305,226✔
173
{
174
  IRRef ref = J->cur.nk;
305,226✔
175
  if (LJ_UNLIKELY(ref <= J->irbotlim)) lj_ir_growbot(J);
86✔
176
  J->cur.nk = --ref;
305,226✔
177
  return ref;
305,226✔
178
}
179

180
/* Get ref of next 64 bit IR constant and optionally grow IR.
181
** Note: this may invalidate all IRIns *!
182
*/
183
static LJ_AINLINE IRRef ir_nextk64(jit_State *J)
684,450✔
184
{
185
  IRRef ref = J->cur.nk - 2;
684,450✔
186
  lj_assertJ(J->state != LJ_TRACE_ASM, "bad JIT state");
684,450✔
187
  if (LJ_UNLIKELY(ref < J->irbotlim)) lj_ir_growbot(J);
236✔
188
  J->cur.nk = ref;
684,450✔
189
  return ref;
684,450✔
190
}
191

192
#if LJ_GC64
193
#define ir_nextkgc ir_nextk64
194
#else
195
#define ir_nextkgc ir_nextk
196
#endif
197

198
/* Intern int32_t constant. */
199
TRef LJ_FASTCALL lj_ir_kint(jit_State *J, int32_t k)
1,633,891✔
200
{
201
  IRIns *ir, *cir = J->cur.ir;
1,633,891✔
202
  IRRef ref;
1,633,891✔
203
  for (ref = J->chain[IR_KINT]; ref; ref = cir[ref].prev)
7,324,397✔
204
    if (cir[ref].i == k)
7,192,192✔
205
      goto found;
1,501,686✔
206
  ref = ir_nextk(J);
132,205✔
207
  ir = IR(ref);
132,205✔
208
  ir->i = k;
132,205✔
209
  ir->t.irt = IRT_INT;
132,205✔
210
  ir->o = IR_KINT;
132,205✔
211
  ir->prev = J->chain[IR_KINT];
132,205✔
212
  J->chain[IR_KINT] = (IRRef1)ref;
132,205✔
213
found:
1,633,891✔
214
  return TREF(ref, IRT_INT);
1,633,891✔
215
}
216

217
/* Intern 64 bit constant, given by its 64 bit pattern. */
218
TRef lj_ir_k64(jit_State *J, IROp op, uint64_t u64)
968,541✔
219
{
220
  IRIns *ir, *cir = J->cur.ir;
968,541✔
221
  IRRef ref;
968,541✔
222
  IRType t = op == IR_KNUM ? IRT_NUM : IRT_I64;
968,541✔
223
  for (ref = J->chain[op]; ref; ref = cir[ref].prev)
7,448,124✔
224
    if (ir_k64(&cir[ref])->u64 == u64)
7,209,243✔
225
      goto found;
729,660✔
226
  ref = ir_nextk64(J);
238,881✔
227
  ir = IR(ref);
238,881✔
228
  ir[1].tv.u64 = u64;
238,881✔
229
  ir->t.irt = t;
238,881✔
230
  ir->o = op;
238,881✔
231
  ir->op12 = 0;
238,881✔
232
  ir->prev = J->chain[op];
238,881✔
233
  J->chain[op] = (IRRef1)ref;
238,881✔
234
found:
968,541✔
235
  return TREF(ref, t);
968,541✔
236
}
237

238
/* Intern FP constant, given by its 64 bit pattern. */
239
TRef lj_ir_knum_u64(jit_State *J, uint64_t u64)
285,924✔
240
{
241
  return lj_ir_k64(J, IR_KNUM, u64);
285,924✔
242
}
243

244
/* Intern 64 bit integer constant. */
245
TRef lj_ir_kint64(jit_State *J, uint64_t u64)
102,253✔
246
{
247
  return lj_ir_k64(J, IR_KINT64, u64);
102,253✔
248
}
249

250
/* Check whether a number is int and return it. -0 is NOT considered an int. */
251
static int numistrueint(lua_Number n, int32_t *kp)
189,862✔
252
{
253
  int32_t k = lj_num2int(n);
189,862✔
254
  if (n == (lua_Number)k) {
189,862✔
255
    if (kp) *kp = k;
187,796✔
256
    if (k == 0) {  /* Special check for -0. */
187,796✔
257
      TValue tv;
26,378✔
258
      setnumV(&tv, n);
26,378✔
259
      if (tv.u32.hi != 0)
26,378✔
260
        return 0;
261
    }
262
    return 1;
187,796✔
263
  }
264
  return 0;
265
}
266

267
/* Intern number as int32_t constant if possible, otherwise as FP constant. */
268
TRef lj_ir_knumint(jit_State *J, lua_Number n)
189,862✔
269
{
270
  int32_t k;
189,862✔
271
  if (numistrueint(n, &k))
189,862✔
272
    return lj_ir_kint(J, k);
187,796✔
273
  else
274
    return lj_ir_knum(J, n);
2,066✔
275
}
276

277
/* Intern GC object "constant". */
278
TRef lj_ir_kgc(jit_State *J, GCobj *o, IRType t)
2,868,704✔
279
{
280
  IRIns *ir, *cir = J->cur.ir;
2,868,704✔
281
  IRRef ref;
2,868,704✔
282
  lj_assertJ(!isdead(J2G(J), o), "interning of dead GC object");
2,868,704✔
283
  for (ref = J->chain[IR_KGC]; ref; ref = cir[ref].prev)
25,447,718✔
284
    if (ir_kgc(&cir[ref]) == o)
25,055,746✔
285
      goto found;
2,476,732✔
286
  ref = ir_nextkgc(J);
391,972✔
287
  ir = IR(ref);
391,972✔
288
  /* NOBARRIER: Current trace is a GC root. */
289
  ir->op12 = 0;
391,972✔
290
  setgcref(ir[LJ_GC64].gcr, o);
391,972✔
291
  ir->t.irt = (uint8_t)t;
391,972✔
292
  ir->o = IR_KGC;
391,972✔
293
  ir->prev = J->chain[IR_KGC];
391,972✔
294
  J->chain[IR_KGC] = (IRRef1)ref;
391,972✔
295
found:
2,868,704✔
296
  return TREF(ref, t);
2,868,704✔
297
}
298

299
/* Allocate GCtrace constant placeholder (no interning). */
300
TRef lj_ir_ktrace(jit_State *J)
268✔
301
{
302
  IRRef ref = ir_nextkgc(J);
268✔
303
  IRIns *ir = IR(ref);
268✔
304
  lj_assertJ(irt_toitype_(IRT_P64) == LJ_TTRACE, "mismatched type mapping");
268✔
305
  ir->t.irt = IRT_P64;
268✔
306
  ir->o = LJ_GC64 ? IR_KNUM : IR_KNULL;  /* Not IR_KGC yet, but same size. */
268✔
307
  ir->op12 = 0;
268✔
308
  ir->prev = 0;
268✔
309
  return TREF(ref, IRT_P64);
268✔
310
}
311

312
/* Intern pointer constant. */
313
TRef lj_ir_kptr_(jit_State *J, IROp op, void *ptr)
136,415✔
314
{
315
  IRIns *ir, *cir = J->cur.ir;
136,415✔
316
  IRRef ref;
136,415✔
317
#if LJ_64 && !LJ_GC64
318
  lj_assertJ((void *)(uintptr_t)u32ptr(ptr) == ptr, "out-of-range GC pointer");
319
#endif
320
  for (ref = J->chain[op]; ref; ref = cir[ref].prev)
249,459✔
321
    if (ir_kptr(&cir[ref]) == ptr)
196,130✔
322
      goto found;
83,086✔
323
#if LJ_GC64
324
  ref = ir_nextk64(J);
53,329✔
325
#else
326
  ref = ir_nextk(J);
327
#endif
328
  ir = IR(ref);
53,329✔
329
  ir->op12 = 0;
53,329✔
330
  setmref(ir[LJ_GC64].ptr, ptr);
53,329✔
331
  ir->t.irt = IRT_PGC;
53,329✔
332
  ir->o = op;
53,329✔
333
  ir->prev = J->chain[op];
53,329✔
334
  J->chain[op] = (IRRef1)ref;
53,329✔
335
found:
136,415✔
336
  return TREF(ref, IRT_PGC);
136,415✔
337
}
338

339
/* Intern typed NULL constant. */
340
TRef lj_ir_knull(jit_State *J, IRType t)
235,013✔
341
{
342
  IRIns *ir, *cir = J->cur.ir;
235,013✔
343
  IRRef ref;
235,013✔
344
  for (ref = J->chain[IR_KNULL]; ref; ref = cir[ref].prev)
235,101✔
345
    if (irt_t(cir[ref].t) == t)
223,065✔
346
      goto found;
222,977✔
347
  ref = ir_nextk(J);
12,036✔
348
  ir = IR(ref);
12,036✔
349
  ir->i = 0;
12,036✔
350
  ir->t.irt = (uint8_t)t;
12,036✔
351
  ir->o = IR_KNULL;
12,036✔
352
  ir->prev = J->chain[IR_KNULL];
12,036✔
353
  J->chain[IR_KNULL] = (IRRef1)ref;
12,036✔
354
found:
235,013✔
355
  return TREF(ref, t);
235,013✔
356
}
357

358
/* Intern key slot. */
359
TRef lj_ir_kslot(jit_State *J, TRef key, IRRef slot)
1,031,307✔
360
{
361
  IRIns *ir, *cir = J->cur.ir;
1,031,307✔
362
  IRRef2 op12 = IRREF2((IRRef1)key, (IRRef1)slot);
1,031,307✔
363
  IRRef ref;
1,031,307✔
364
  /* Const part is not touched by CSE/DCE, so 0-65535 is ok for IRMlit here. */
365
  lj_assertJ(tref_isk(key) && slot == (IRRef)(IRRef1)slot,
1,031,307✔
366
             "out-of-range key/slot");
367
  for (ref = J->chain[IR_KSLOT]; ref; ref = cir[ref].prev)
4,760,926✔
368
    if (cir[ref].op12 == op12)
4,599,941✔
369
      goto found;
870,322✔
370
  ref = ir_nextk(J);
160,985✔
371
  ir = IR(ref);
160,985✔
372
  ir->op12 = op12;
160,985✔
373
  ir->t.irt = IRT_P32;
160,985✔
374
  ir->o = IR_KSLOT;
160,985✔
375
  ir->prev = J->chain[IR_KSLOT];
160,985✔
376
  J->chain[IR_KSLOT] = (IRRef1)ref;
160,985✔
377
found:
1,031,307✔
378
  return TREF(ref, IRT_P32);
1,031,307✔
379
}
380

381
/* -- Access to IR constants ---------------------------------------------- */
382

383
/* Copy value of IR constant. */
384
void lj_ir_kvalue(lua_State *L, TValue *tv, const IRIns *ir)
390,588✔
385
{
386
  UNUSED(L);
390,588✔
387
  lj_assertL(ir->o != IR_KSLOT, "unexpected KSLOT");  /* Common mistake. */
390,588✔
388
  switch (ir->o) {
390,588✔
389
  case IR_KPRI: setpriV(tv, irt_toitype(ir->t)); break;
11,046✔
390
  case IR_KINT: setintV(tv, ir->i); break;
6,385✔
391
  case IR_KGC: setgcV(L, tv, ir_kgc(ir), irt_toitype(ir->t)); break;
268,573✔
392
  case IR_KPTR: case IR_KKPTR:
×
393
    setnumV(tv, (lua_Number)(uintptr_t)ir_kptr(ir));
×
394
    break;
×
395
  case IR_KNULL: setintV(tv, 0); break;
1✔
396
  case IR_KNUM: setnumV(tv, ir_knum(ir)->n); break;
104,583✔
397
#if LJ_HASFFI
398
  case IR_KINT64: {
399
    GCcdata *cd = lj_cdata_new_(L, CTID_INT64, 8);
×
400
    *(uint64_t *)cdataptr(cd) = ir_kint64(ir)->u64;
×
401
    setcdataV(L, tv, cd);
×
402
    break;
403
    }
404
#endif
405
  default: lj_assertL(0, "bad IR constant op %d", ir->o); break;
406
  }
407
}
390,588✔
408

409
/* -- Convert IR operand types -------------------------------------------- */
410

411
/* Convert from string to number. */
412
TRef LJ_FASTCALL lj_ir_tonumber(jit_State *J, TRef tr)
151,346✔
413
{
414
  if (!tref_isnumber(tr)) {
151,346✔
415
    if (tref_isstr(tr))
×
416
      tr = emitir(IRTG(IR_STRTO, IRT_NUM), tr, 0);
×
417
    else
418
      lj_trace_err(J, LJ_TRERR_BADTYPE);
×
419
  }
420
  return tr;
151,346✔
421
}
422

423
/* Convert from integer or string to number. */
424
TRef LJ_FASTCALL lj_ir_tonum(jit_State *J, TRef tr)
808✔
425
{
426
  if (!tref_isnum(tr)) {
808✔
427
    if (tref_isinteger(tr))
175✔
428
      tr = emitir(IRTN(IR_CONV), tr, IRCONV_NUM_INT);
175✔
UNCOV
429
    else if (tref_isstr(tr))
×
UNCOV
430
      tr = emitir(IRTG(IR_STRTO, IRT_NUM), tr, 0);
×
431
    else
432
      lj_trace_err(J, LJ_TRERR_BADTYPE);
×
433
  }
434
  return tr;
808✔
435
}
436

437
/* Convert from integer or number to string. */
438
TRef LJ_FASTCALL lj_ir_tostr(jit_State *J, TRef tr)
659✔
439
{
440
  if (!tref_isstr(tr)) {
659✔
441
    if (!tref_isnumber(tr))
4✔
442
      lj_trace_err(J, LJ_TRERR_BADTYPE);
×
443
    tr = emitir(IRT(IR_TOSTR, IRT_STR), tr,
4✔
444
                tref_isnum(tr) ? IRTOSTR_NUM : IRTOSTR_INT);
445
  }
446
  return tr;
659✔
447
}
448

449
/* -- Miscellaneous IR ops ------------------------------------------------ */
450

451
/* Evaluate numeric comparison. */
452
int lj_ir_numcmp(lua_Number a, lua_Number b, IROp op)
146,891✔
453
{
454
  switch (op) {
146,891✔
455
  case IR_EQ: return (a == b);
4✔
UNCOV
456
  case IR_NE: return (a != b);
×
457
  case IR_LT: return (a < b);
34✔
458
  case IR_GE: return (a >= b);
40✔
459
  case IR_LE: return (a <= b);
235✔
460
  case IR_GT: return (a > b);
11✔
461
  case IR_ULT: return !(a >= b);
×
462
  case IR_UGE: return !(a < b);
10,396✔
463
  case IR_ULE: return !(a > b);
×
464
  case IR_UGT: return !(a <= b);
136,171✔
465
  default: lj_assertX(0, "bad IR op %d", op); return 0;
466
  }
467
}
468

469
/* Evaluate string comparison. */
470
int lj_ir_strcmp(GCstr *a, GCstr *b, IROp op)
10✔
471
{
472
  int res = lj_str_cmp(a, b);
10✔
473
  switch (op) {
10✔
474
  case IR_LT: return (res < 0);
3✔
475
  case IR_GE: return (res >= 0);
2✔
476
  case IR_LE: return (res <= 0);
3✔
477
  case IR_GT: return (res > 0);
2✔
478
  default: lj_assertX(0, "bad IR op %d", op); return 0;
479
  }
480
}
481

482
/* Rollback IR to previous state. */
483
void lj_ir_rollback(jit_State *J, IRRef ref)
416,439✔
484
{
485
  IRRef nins = J->cur.nins;
416,439✔
486
  while (nins > ref) {
420,673✔
487
    IRIns *ir;
4,234✔
488
    nins--;
4,234✔
489
    ir = IR(nins);
4,234✔
490
    J->chain[ir->o] = ir->prev;
4,234✔
491
  }
492
  J->cur.nins = nins;
416,439✔
493
}
416,439✔
494

495
#undef IR
496
#undef fins
497
#undef emitir
498

499
#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