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