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