Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/openzfs/module/lua/lcode.c
48383 views
1
// SPDX-License-Identifier: MIT
2
/*
3
** $Id: lcode.c,v 2.62.1.1 2013/04/12 18:48:47 roberto Exp $
4
** Code generator for Lua
5
** See Copyright Notice in lua.h
6
*/
7
8
#define lcode_c
9
#define LUA_CORE
10
11
#if defined(HAVE_IMPLICIT_FALLTHROUGH)
12
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
13
#endif
14
15
#include <sys/lua/lua.h>
16
17
#include "lcode.h"
18
#include "ldebug.h"
19
#include "ldo.h"
20
#include "lgc.h"
21
#include "llex.h"
22
#include "lmem.h"
23
#include "lobject.h"
24
#include "lopcodes.h"
25
#include "lparser.h"
26
#include "lstring.h"
27
#include "ltable.h"
28
#include "lvm.h"
29
30
31
#define hasjumps(e) ((e)->t != (e)->f)
32
33
34
static int isnumeral(expdesc *e) {
35
return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);
36
}
37
38
39
void luaK_nil (FuncState *fs, int from, int n) {
40
Instruction *previous;
41
int l = from + n - 1; /* last register to set nil */
42
if (fs->pc > fs->lasttarget) { /* no jumps to current position? */
43
previous = &fs->f->code[fs->pc-1];
44
if (GET_OPCODE(*previous) == OP_LOADNIL) {
45
int pfrom = GETARG_A(*previous);
46
int pl = pfrom + GETARG_B(*previous);
47
if ((pfrom <= from && from <= pl + 1) ||
48
(from <= pfrom && pfrom <= l + 1)) { /* can connect both? */
49
if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */
50
if (pl > l) l = pl; /* l = max(l, pl) */
51
SETARG_A(*previous, from);
52
SETARG_B(*previous, l - from);
53
return;
54
}
55
} /* else go through */
56
}
57
luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */
58
}
59
60
61
int luaK_jump (FuncState *fs) {
62
int jpc = fs->jpc; /* save list of jumps to here */
63
int j;
64
fs->jpc = NO_JUMP;
65
j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP);
66
luaK_concat(fs, &j, jpc); /* keep them on hold */
67
return j;
68
}
69
70
71
void luaK_ret (FuncState *fs, int first, int nret) {
72
luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);
73
}
74
75
76
static int condjump (FuncState *fs, OpCode op, int A, int B, int C) {
77
luaK_codeABC(fs, op, A, B, C);
78
return luaK_jump(fs);
79
}
80
81
82
static void fixjump (FuncState *fs, int pc, int dest) {
83
Instruction *jmp = &fs->f->code[pc];
84
int offset = dest-(pc+1);
85
lua_assert(dest != NO_JUMP);
86
if (abs(offset) > MAXARG_sBx)
87
luaX_syntaxerror(fs->ls, "control structure too long");
88
SETARG_sBx(*jmp, offset);
89
}
90
91
92
/*
93
** returns current `pc' and marks it as a jump target (to avoid wrong
94
** optimizations with consecutive instructions not in the same basic block).
95
*/
96
int luaK_getlabel (FuncState *fs) {
97
fs->lasttarget = fs->pc;
98
return fs->pc;
99
}
100
101
102
static int getjump (FuncState *fs, int pc) {
103
int offset = GETARG_sBx(fs->f->code[pc]);
104
if (offset == NO_JUMP) /* point to itself represents end of list */
105
return NO_JUMP; /* end of list */
106
else
107
return (pc+1)+offset; /* turn offset into absolute position */
108
}
109
110
111
static Instruction *getjumpcontrol (FuncState *fs, int pc) {
112
Instruction *pi = &fs->f->code[pc];
113
if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1))))
114
return pi-1;
115
else
116
return pi;
117
}
118
119
120
/*
121
** check whether list has any jump that do not produce a value
122
** (or produce an inverted value)
123
*/
124
static int need_value (FuncState *fs, int list) {
125
for (; list != NO_JUMP; list = getjump(fs, list)) {
126
Instruction i = *getjumpcontrol(fs, list);
127
if (GET_OPCODE(i) != OP_TESTSET) return 1;
128
}
129
return 0; /* not found */
130
}
131
132
133
static int patchtestreg (FuncState *fs, int node, int reg) {
134
Instruction *i = getjumpcontrol(fs, node);
135
if (GET_OPCODE(*i) != OP_TESTSET)
136
return 0; /* cannot patch other instructions */
137
if (reg != NO_REG && reg != GETARG_B(*i))
138
SETARG_A(*i, reg);
139
else /* no register to put value or register already has the value */
140
*i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i));
141
142
return 1;
143
}
144
145
146
static void removevalues (FuncState *fs, int list) {
147
for (; list != NO_JUMP; list = getjump(fs, list))
148
patchtestreg(fs, list, NO_REG);
149
}
150
151
152
static void patchlistaux (FuncState *fs, int list, int vtarget, int reg,
153
int dtarget) {
154
while (list != NO_JUMP) {
155
int next = getjump(fs, list);
156
if (patchtestreg(fs, list, reg))
157
fixjump(fs, list, vtarget);
158
else
159
fixjump(fs, list, dtarget); /* jump to default target */
160
list = next;
161
}
162
}
163
164
165
static void dischargejpc (FuncState *fs) {
166
patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc);
167
fs->jpc = NO_JUMP;
168
}
169
170
171
void luaK_patchlist (FuncState *fs, int list, int target) {
172
if (target == fs->pc)
173
luaK_patchtohere(fs, list);
174
else {
175
lua_assert(target < fs->pc);
176
patchlistaux(fs, list, target, NO_REG, target);
177
}
178
}
179
180
181
LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level) {
182
level++; /* argument is +1 to reserve 0 as non-op */
183
while (list != NO_JUMP) {
184
int next = getjump(fs, list);
185
lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP &&
186
(GETARG_A(fs->f->code[list]) == 0 ||
187
GETARG_A(fs->f->code[list]) >= level));
188
SETARG_A(fs->f->code[list], level);
189
list = next;
190
}
191
}
192
193
194
void luaK_patchtohere (FuncState *fs, int list) {
195
luaK_getlabel(fs);
196
luaK_concat(fs, &fs->jpc, list);
197
}
198
199
200
void luaK_concat (FuncState *fs, int *l1, int l2) {
201
if (l2 == NO_JUMP) return;
202
else if (*l1 == NO_JUMP)
203
*l1 = l2;
204
else {
205
int list = *l1;
206
int next;
207
while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */
208
list = next;
209
fixjump(fs, list, l2);
210
}
211
}
212
213
214
static int luaK_code (FuncState *fs, Instruction i) {
215
Proto *f = fs->f;
216
dischargejpc(fs); /* `pc' will change */
217
/* put new instruction in code array */
218
luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction,
219
MAX_INT, "opcodes");
220
f->code[fs->pc] = i;
221
/* save corresponding line information */
222
luaM_growvector(fs->ls->L, f->lineinfo, fs->pc, f->sizelineinfo, int,
223
MAX_INT, "opcodes");
224
f->lineinfo[fs->pc] = fs->ls->lastline;
225
return fs->pc++;
226
}
227
228
229
int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) {
230
lua_assert(getOpMode(o) == iABC);
231
lua_assert(getBMode(o) != OpArgN || b == 0);
232
lua_assert(getCMode(o) != OpArgN || c == 0);
233
lua_assert(a <= MAXARG_A && b <= MAXARG_B && c <= MAXARG_C);
234
return luaK_code(fs, CREATE_ABC(o, a, b, c));
235
}
236
237
238
int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {
239
lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);
240
lua_assert(getCMode(o) == OpArgN);
241
lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx);
242
return luaK_code(fs, CREATE_ABx(o, a, bc));
243
}
244
245
246
static int codeextraarg (FuncState *fs, int a) {
247
lua_assert(a <= MAXARG_Ax);
248
return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a));
249
}
250
251
252
int luaK_codek (FuncState *fs, int reg, int k) {
253
if (k <= MAXARG_Bx)
254
return luaK_codeABx(fs, OP_LOADK, reg, k);
255
else {
256
int p = luaK_codeABx(fs, OP_LOADKX, reg, 0);
257
codeextraarg(fs, k);
258
return p;
259
}
260
}
261
262
263
void luaK_checkstack (FuncState *fs, int n) {
264
int newstack = fs->freereg + n;
265
if (newstack > fs->f->maxstacksize) {
266
if (newstack >= MAXSTACK)
267
luaX_syntaxerror(fs->ls, "function or expression too complex");
268
fs->f->maxstacksize = cast_byte(newstack);
269
}
270
}
271
272
273
void luaK_reserveregs (FuncState *fs, int n) {
274
luaK_checkstack(fs, n);
275
fs->freereg += n;
276
}
277
278
279
static void freereg (FuncState *fs, int reg) {
280
if (!ISK(reg) && reg >= fs->nactvar) {
281
fs->freereg--;
282
lua_assert(reg == fs->freereg);
283
}
284
}
285
286
287
static void freeexp (FuncState *fs, expdesc *e) {
288
if (e->k == VNONRELOC)
289
freereg(fs, e->u.info);
290
}
291
292
293
static int addk (FuncState *fs, TValue *key, TValue *v) {
294
lua_State *L = fs->ls->L;
295
TValue *idx = luaH_set(L, fs->h, key);
296
Proto *f = fs->f;
297
int k, oldsize;
298
if (ttisnumber(idx)) {
299
lua_Number n = nvalue(idx);
300
lua_number2int(k, n);
301
if (luaV_rawequalobj(&f->k[k], v))
302
return k;
303
/* else may be a collision (e.g., between 0.0 and "\0\0\0\0\0\0\0\0");
304
go through and create a new entry for this value */
305
}
306
/* constant not found; create a new entry */
307
oldsize = f->sizek;
308
k = fs->nk;
309
/* numerical value does not need GC barrier;
310
table has no metatable, so it does not need to invalidate cache */
311
setnvalue(idx, cast_num(k));
312
luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants");
313
while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
314
setobj(L, &f->k[k], v);
315
fs->nk++;
316
luaC_barrier(L, f, v);
317
return k;
318
}
319
320
321
int luaK_stringK (FuncState *fs, TString *s) {
322
TValue o;
323
setsvalue(fs->ls->L, &o, s);
324
return addk(fs, &o, &o);
325
}
326
327
328
int luaK_numberK (FuncState *fs, lua_Number r) {
329
int n;
330
lua_State *L = fs->ls->L;
331
TValue o;
332
setnvalue(&o, r);
333
if (r == 0 || luai_numisnan(NULL, r)) { /* handle -0 and NaN */
334
/* use raw representation as key to avoid numeric problems */
335
setsvalue(L, L->top++, luaS_newlstr(L, (char *)&r, sizeof(r)));
336
n = addk(fs, L->top - 1, &o);
337
L->top--;
338
}
339
else
340
n = addk(fs, &o, &o); /* regular case */
341
return n;
342
}
343
344
345
static int boolK (FuncState *fs, int b) {
346
TValue o;
347
setbvalue(&o, b);
348
return addk(fs, &o, &o);
349
}
350
351
352
static int nilK (FuncState *fs) {
353
TValue k, v;
354
setnilvalue(&v);
355
/* cannot use nil as key; instead use table itself to represent nil */
356
sethvalue(fs->ls->L, &k, fs->h);
357
return addk(fs, &k, &v);
358
}
359
360
361
void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
362
if (e->k == VCALL) { /* expression is an open function call? */
363
SETARG_C(getcode(fs, e), nresults+1);
364
}
365
else if (e->k == VVARARG) {
366
SETARG_B(getcode(fs, e), nresults+1);
367
SETARG_A(getcode(fs, e), fs->freereg);
368
luaK_reserveregs(fs, 1);
369
}
370
}
371
372
373
void luaK_setoneret (FuncState *fs, expdesc *e) {
374
if (e->k == VCALL) { /* expression is an open function call? */
375
e->k = VNONRELOC;
376
e->u.info = GETARG_A(getcode(fs, e));
377
}
378
else if (e->k == VVARARG) {
379
SETARG_B(getcode(fs, e), 2);
380
e->k = VRELOCABLE; /* can relocate its simple result */
381
}
382
}
383
384
385
void luaK_dischargevars (FuncState *fs, expdesc *e) {
386
switch (e->k) {
387
case VLOCAL: {
388
e->k = VNONRELOC;
389
break;
390
}
391
case VUPVAL: {
392
e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0);
393
e->k = VRELOCABLE;
394
break;
395
}
396
case VINDEXED: {
397
OpCode op = OP_GETTABUP; /* assume 't' is in an upvalue */
398
freereg(fs, e->u.ind.idx);
399
if (e->u.ind.vt == VLOCAL) { /* 't' is in a register? */
400
freereg(fs, e->u.ind.t);
401
op = OP_GETTABLE;
402
}
403
e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx);
404
e->k = VRELOCABLE;
405
break;
406
}
407
case VVARARG:
408
case VCALL: {
409
luaK_setoneret(fs, e);
410
break;
411
}
412
default: break; /* there is one value available (somewhere) */
413
}
414
}
415
416
417
static int code_label (FuncState *fs, int A, int b, int jump) {
418
luaK_getlabel(fs); /* those instructions may be jump targets */
419
return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump);
420
}
421
422
423
static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
424
luaK_dischargevars(fs, e);
425
switch (e->k) {
426
case VNIL: {
427
luaK_nil(fs, reg, 1);
428
break;
429
}
430
case VFALSE: case VTRUE: {
431
luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0);
432
break;
433
}
434
case VK: {
435
luaK_codek(fs, reg, e->u.info);
436
break;
437
}
438
case VKNUM: {
439
luaK_codek(fs, reg, luaK_numberK(fs, e->u.nval));
440
break;
441
}
442
case VRELOCABLE: {
443
Instruction *pc = &getcode(fs, e);
444
SETARG_A(*pc, reg);
445
break;
446
}
447
case VNONRELOC: {
448
if (reg != e->u.info)
449
luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0);
450
break;
451
}
452
default: {
453
lua_assert(e->k == VVOID || e->k == VJMP);
454
return; /* nothing to do... */
455
}
456
}
457
e->u.info = reg;
458
e->k = VNONRELOC;
459
}
460
461
462
static void discharge2anyreg (FuncState *fs, expdesc *e) {
463
if (e->k != VNONRELOC) {
464
luaK_reserveregs(fs, 1);
465
discharge2reg(fs, e, fs->freereg-1);
466
}
467
}
468
469
470
static void exp2reg (FuncState *fs, expdesc *e, int reg) {
471
discharge2reg(fs, e, reg);
472
if (e->k == VJMP)
473
luaK_concat(fs, &e->t, e->u.info); /* put this jump in `t' list */
474
if (hasjumps(e)) {
475
int final; /* position after whole expression */
476
int p_f = NO_JUMP; /* position of an eventual LOAD false */
477
int p_t = NO_JUMP; /* position of an eventual LOAD true */
478
if (need_value(fs, e->t) || need_value(fs, e->f)) {
479
int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs);
480
p_f = code_label(fs, reg, 0, 1);
481
p_t = code_label(fs, reg, 1, 0);
482
luaK_patchtohere(fs, fj);
483
}
484
final = luaK_getlabel(fs);
485
patchlistaux(fs, e->f, final, reg, p_f);
486
patchlistaux(fs, e->t, final, reg, p_t);
487
}
488
e->f = e->t = NO_JUMP;
489
e->u.info = reg;
490
e->k = VNONRELOC;
491
}
492
493
494
void luaK_exp2nextreg (FuncState *fs, expdesc *e) {
495
luaK_dischargevars(fs, e);
496
freeexp(fs, e);
497
luaK_reserveregs(fs, 1);
498
exp2reg(fs, e, fs->freereg - 1);
499
}
500
501
502
int luaK_exp2anyreg (FuncState *fs, expdesc *e) {
503
luaK_dischargevars(fs, e);
504
if (e->k == VNONRELOC) {
505
if (!hasjumps(e)) return e->u.info; /* exp is already in a register */
506
if (e->u.info >= fs->nactvar) { /* reg. is not a local? */
507
exp2reg(fs, e, e->u.info); /* put value on it */
508
return e->u.info;
509
}
510
}
511
luaK_exp2nextreg(fs, e); /* default */
512
return e->u.info;
513
}
514
515
516
void luaK_exp2anyregup (FuncState *fs, expdesc *e) {
517
if (e->k != VUPVAL || hasjumps(e))
518
luaK_exp2anyreg(fs, e);
519
}
520
521
522
void luaK_exp2val (FuncState *fs, expdesc *e) {
523
if (hasjumps(e))
524
luaK_exp2anyreg(fs, e);
525
else
526
luaK_dischargevars(fs, e);
527
}
528
529
530
int luaK_exp2RK (FuncState *fs, expdesc *e) {
531
luaK_exp2val(fs, e);
532
switch (e->k) {
533
case VTRUE:
534
case VFALSE:
535
case VNIL: {
536
if (fs->nk <= MAXINDEXRK) { /* constant fits in RK operand? */
537
e->u.info = (e->k == VNIL) ? nilK(fs) : boolK(fs, (e->k == VTRUE));
538
e->k = VK;
539
return RKASK(e->u.info);
540
}
541
else break;
542
}
543
case VKNUM: {
544
e->u.info = luaK_numberK(fs, e->u.nval);
545
e->k = VK;
546
/* go through */
547
}
548
case VK: {
549
if (e->u.info <= MAXINDEXRK) /* constant fits in argC? */
550
return RKASK(e->u.info);
551
else break;
552
}
553
default: break;
554
}
555
/* not a constant in the right range: put it in a register */
556
return luaK_exp2anyreg(fs, e);
557
}
558
559
560
void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
561
switch (var->k) {
562
case VLOCAL: {
563
freeexp(fs, ex);
564
exp2reg(fs, ex, var->u.info);
565
return;
566
}
567
case VUPVAL: {
568
int e = luaK_exp2anyreg(fs, ex);
569
luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0);
570
break;
571
}
572
case VINDEXED: {
573
OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP;
574
int e = luaK_exp2RK(fs, ex);
575
luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e);
576
break;
577
}
578
default: {
579
lua_assert(0); /* invalid var kind to store */
580
break;
581
}
582
}
583
freeexp(fs, ex);
584
}
585
586
587
void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
588
int ereg;
589
luaK_exp2anyreg(fs, e);
590
ereg = e->u.info; /* register where 'e' was placed */
591
freeexp(fs, e);
592
e->u.info = fs->freereg; /* base register for op_self */
593
e->k = VNONRELOC;
594
luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */
595
luaK_codeABC(fs, OP_SELF, e->u.info, ereg, luaK_exp2RK(fs, key));
596
freeexp(fs, key);
597
}
598
599
600
static void invertjump (FuncState *fs, expdesc *e) {
601
Instruction *pc = getjumpcontrol(fs, e->u.info);
602
lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&
603
GET_OPCODE(*pc) != OP_TEST);
604
SETARG_A(*pc, !(GETARG_A(*pc)));
605
}
606
607
608
static int jumponcond (FuncState *fs, expdesc *e, int cond) {
609
if (e->k == VRELOCABLE) {
610
Instruction ie = getcode(fs, e);
611
if (GET_OPCODE(ie) == OP_NOT) {
612
fs->pc--; /* remove previous OP_NOT */
613
return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond);
614
}
615
/* else go through */
616
}
617
discharge2anyreg(fs, e);
618
freeexp(fs, e);
619
return condjump(fs, OP_TESTSET, NO_REG, e->u.info, cond);
620
}
621
622
623
void luaK_goiftrue (FuncState *fs, expdesc *e) {
624
int pc; /* pc of last jump */
625
luaK_dischargevars(fs, e);
626
switch (e->k) {
627
case VJMP: {
628
invertjump(fs, e);
629
pc = e->u.info;
630
break;
631
}
632
case VK: case VKNUM: case VTRUE: {
633
pc = NO_JUMP; /* always true; do nothing */
634
break;
635
}
636
default: {
637
pc = jumponcond(fs, e, 0);
638
break;
639
}
640
}
641
luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */
642
luaK_patchtohere(fs, e->t);
643
e->t = NO_JUMP;
644
}
645
646
647
void luaK_goiffalse (FuncState *fs, expdesc *e) {
648
int pc; /* pc of last jump */
649
luaK_dischargevars(fs, e);
650
switch (e->k) {
651
case VJMP: {
652
pc = e->u.info;
653
break;
654
}
655
case VNIL: case VFALSE: {
656
pc = NO_JUMP; /* always false; do nothing */
657
break;
658
}
659
default: {
660
pc = jumponcond(fs, e, 1);
661
break;
662
}
663
}
664
luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */
665
luaK_patchtohere(fs, e->f);
666
e->f = NO_JUMP;
667
}
668
669
670
static void codenot (FuncState *fs, expdesc *e) {
671
luaK_dischargevars(fs, e);
672
switch (e->k) {
673
case VNIL: case VFALSE: {
674
e->k = VTRUE;
675
break;
676
}
677
case VK: case VKNUM: case VTRUE: {
678
e->k = VFALSE;
679
break;
680
}
681
case VJMP: {
682
invertjump(fs, e);
683
break;
684
}
685
case VRELOCABLE:
686
case VNONRELOC: {
687
discharge2anyreg(fs, e);
688
freeexp(fs, e);
689
e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0);
690
e->k = VRELOCABLE;
691
break;
692
}
693
default: {
694
lua_assert(0); /* cannot happen */
695
break;
696
}
697
}
698
/* interchange true and false lists */
699
{ int temp = e->f; e->f = e->t; e->t = temp; }
700
removevalues(fs, e->f);
701
removevalues(fs, e->t);
702
}
703
704
705
void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
706
lua_assert(!hasjumps(t));
707
t->u.ind.t = t->u.info;
708
t->u.ind.idx = luaK_exp2RK(fs, k);
709
t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL
710
: check_exp(vkisinreg(t->k), VLOCAL);
711
t->k = VINDEXED;
712
}
713
714
715
static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
716
lua_Number r;
717
if (!isnumeral(e1) || !isnumeral(e2)) return 0;
718
if ((op == OP_DIV || op == OP_MOD) && e2->u.nval == 0)
719
return 0; /* do not attempt to divide by 0 */
720
/*
721
* Patched: check for MIN_INT / -1
722
*/
723
if (op == OP_DIV && e1->u.nval == INT64_MIN && e2->u.nval == -1)
724
return 0;
725
r = luaO_arith(op - OP_ADD + LUA_OPADD, e1->u.nval, e2->u.nval);
726
e1->u.nval = r;
727
return 1;
728
}
729
730
731
static void codearith (FuncState *fs, OpCode op,
732
expdesc *e1, expdesc *e2, int line) {
733
if (constfolding(op, e1, e2))
734
return;
735
else {
736
int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;
737
int o1 = luaK_exp2RK(fs, e1);
738
if (o1 > o2) {
739
freeexp(fs, e1);
740
freeexp(fs, e2);
741
}
742
else {
743
freeexp(fs, e2);
744
freeexp(fs, e1);
745
}
746
e1->u.info = luaK_codeABC(fs, op, 0, o1, o2);
747
e1->k = VRELOCABLE;
748
luaK_fixline(fs, line);
749
}
750
}
751
752
753
static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,
754
expdesc *e2) {
755
int o1 = luaK_exp2RK(fs, e1);
756
int o2 = luaK_exp2RK(fs, e2);
757
freeexp(fs, e2);
758
freeexp(fs, e1);
759
if (cond == 0 && op != OP_EQ) {
760
int temp; /* exchange args to replace by `<' or `<=' */
761
temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */
762
cond = 1;
763
}
764
e1->u.info = condjump(fs, op, cond, o1, o2);
765
e1->k = VJMP;
766
}
767
768
769
void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) {
770
expdesc e2;
771
e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
772
switch (op) {
773
case OPR_MINUS: {
774
if (isnumeral(e)) /* minus constant? */
775
e->u.nval = luai_numunm(NULL, e->u.nval); /* fold it */
776
else {
777
luaK_exp2anyreg(fs, e);
778
codearith(fs, OP_UNM, e, &e2, line);
779
}
780
break;
781
}
782
case OPR_NOT: codenot(fs, e); break;
783
case OPR_LEN: {
784
luaK_exp2anyreg(fs, e); /* cannot operate on constants */
785
codearith(fs, OP_LEN, e, &e2, line);
786
break;
787
}
788
default: lua_assert(0);
789
}
790
}
791
792
793
void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
794
switch (op) {
795
case OPR_AND: {
796
luaK_goiftrue(fs, v);
797
break;
798
}
799
case OPR_OR: {
800
luaK_goiffalse(fs, v);
801
break;
802
}
803
case OPR_CONCAT: {
804
luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */
805
break;
806
}
807
case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
808
case OPR_MOD: case OPR_POW: {
809
if (!isnumeral(v)) luaK_exp2RK(fs, v);
810
break;
811
}
812
default: {
813
luaK_exp2RK(fs, v);
814
break;
815
}
816
}
817
}
818
819
820
void luaK_posfix (FuncState *fs, BinOpr op,
821
expdesc *e1, expdesc *e2, int line) {
822
switch (op) {
823
case OPR_AND: {
824
lua_assert(e1->t == NO_JUMP); /* list must be closed */
825
luaK_dischargevars(fs, e2);
826
luaK_concat(fs, &e2->f, e1->f);
827
*e1 = *e2;
828
break;
829
}
830
case OPR_OR: {
831
lua_assert(e1->f == NO_JUMP); /* list must be closed */
832
luaK_dischargevars(fs, e2);
833
luaK_concat(fs, &e2->t, e1->t);
834
*e1 = *e2;
835
break;
836
}
837
case OPR_CONCAT: {
838
luaK_exp2val(fs, e2);
839
if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {
840
lua_assert(e1->u.info == GETARG_B(getcode(fs, e2))-1);
841
freeexp(fs, e1);
842
SETARG_B(getcode(fs, e2), e1->u.info);
843
e1->k = VRELOCABLE; e1->u.info = e2->u.info;
844
}
845
else {
846
luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */
847
codearith(fs, OP_CONCAT, e1, e2, line);
848
}
849
break;
850
}
851
case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
852
case OPR_MOD: case OPR_POW: {
853
codearith(fs, cast(OpCode, op - OPR_ADD + OP_ADD), e1, e2, line);
854
break;
855
}
856
case OPR_EQ: case OPR_LT: case OPR_LE: {
857
codecomp(fs, cast(OpCode, op - OPR_EQ + OP_EQ), 1, e1, e2);
858
break;
859
}
860
case OPR_NE: case OPR_GT: case OPR_GE: {
861
codecomp(fs, cast(OpCode, op - OPR_NE + OP_EQ), 0, e1, e2);
862
break;
863
}
864
default: lua_assert(0);
865
}
866
}
867
868
869
void luaK_fixline (FuncState *fs, int line) {
870
fs->f->lineinfo[fs->pc - 1] = line;
871
}
872
873
874
void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) {
875
int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1;
876
int b = (tostore == LUA_MULTRET) ? 0 : tostore;
877
lua_assert(tostore != 0);
878
if (c <= MAXARG_C)
879
luaK_codeABC(fs, OP_SETLIST, base, b, c);
880
else if (c <= MAXARG_Ax) {
881
luaK_codeABC(fs, OP_SETLIST, base, b, 0);
882
codeextraarg(fs, c);
883
}
884
else
885
luaX_syntaxerror(fs->ls, "constructor too long");
886
fs->freereg = base + 1; /* free registers with list values */
887
}
888
889