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