/*** $Id: lcode.c,v 2.99 2014/12/29 16:49:25 roberto Exp $** Code generator for Lua** See Copyright Notice in lua.h*/ #define lcode_c#define LUA_CORE #include "lprefix.h" #include <math.h>#include <stdlib.h> #include "lua.h" #include "lcode.h"#include "ldebug.h"#include "ldo.h"#include "lgc.h"#include "llex.h"#include "lmem.h"#include "lobject.h"#include "lopcodes.h"#include "lparser.h"#include "lstring.h"#include "ltable.h"#include "lvm.h" /* Maximum number of registers in a Lua function */#define MAXREGS 250 #define hasjumps(e) ((e)->t != (e)->f) static int tonumeral(expdesc *e, TValue *v) { if (e->t != NO_JUMP || e->f != NO_JUMP) return 0; /* not a numeral */ switch (e->k) { case VKINT: if (v) setivalue(v, e->u.ival); return 1; case VKFLT: if (v) setfltvalue(v, e->u.nval); return 1; default: return 0; }} void luaK_nil (FuncState *fs, int from, int n) { Instruction *previous; int l = from + n - 1; /* last register to set nil */ if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ previous = &fs->f->code[fs->pc-1]; if (GET_OPCODE(*previous) == OP_LOADNIL) { int pfrom = GETARG_A(*previous); int pl = pfrom + GETARG_B(*previous); if ((pfrom <= from && from <= pl + 1) || (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */ if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */ if (pl > l) l = pl; /* l = max(l, pl) */ SETARG_A(*previous, from); SETARG_B(*previous, l - from); return; } } /* else go through */ } luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */} int luaK_jump (FuncState *fs) { int jpc = fs->jpc; /* save list of jumps to here */ int j; fs->jpc = NO_JUMP; j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); luaK_concat(fs, &j, jpc); /* keep them on hold */ return j;} void luaK_ret (FuncState *fs, int first, int nret) { luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);} static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { luaK_codeABC(fs, op, A, B, C); return luaK_jump(fs);} static void fixjump (FuncState *fs, int pc, int dest) { Instruction *jmp = &fs->f->code[pc]; int offset = dest-(pc+1); lua_assert(dest != NO_JUMP); if (abs(offset) > MAXARG_sBx) luaX_syntaxerror(fs->ls, "control structure too long"); SETARG_sBx(*jmp, offset);} /*** returns current 'pc' and marks it as a jump target (to avoid wrong** optimizations with consecutive instructions not in the same basic block).*/int luaK_getlabel (FuncState *fs) { fs->lasttarget = fs->pc; return fs->pc;} static int getjump (FuncState *fs, int pc) { int offset = GETARG_sBx(fs->f->code[pc]); if (offset == NO_JUMP) /* point to itself represents end of list */ return NO_JUMP; /* end of list */ else return (pc+1)+offset; /* turn offset into absolute position */} static Instruction *getjumpcontrol (FuncState *fs, int pc) { Instruction *pi = &fs->f->code[pc]; if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) return pi-1; else return pi;} /*** check whether list has any jump that do not produce a value** (or produce an inverted value)*/static int need_value (FuncState *fs, int list) { for (; list != NO_JUMP; list = getjump(fs, list)) { Instruction i = *getjumpcontrol(fs, list); if (GET_OPCODE(i) != OP_TESTSET) return 1; } return 0; /* not found */} static int patchtestreg (FuncState *fs, int node, int reg) { Instruction *i = getjumpcontrol(fs, node); if (GET_OPCODE(*i) != OP_TESTSET) return 0; /* cannot patch other instructions */ if (reg != NO_REG && reg != GETARG_B(*i)) SETARG_A(*i, reg); else /* no register to put value or register already has the value */ *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); return 1;} static void removevalues (FuncState *fs, int list) { for (; list != NO_JUMP; list = getjump(fs, list)) patchtestreg(fs, list, NO_REG);} static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, int dtarget) { while (list != NO_JUMP) { int next = getjump(fs, list); if (patchtestreg(fs, list, reg)) fixjump(fs, list, vtarget); else fixjump(fs, list, dtarget); /* jump to default target */ list = next; }} static void dischargejpc (FuncState *fs) { patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); fs->jpc = NO_JUMP;} void luaK_patchlist (FuncState *fs, int list, int target) { if (target == fs->pc) luaK_patchtohere(fs, list); else { lua_assert(target < fs->pc); patchlistaux(fs, list, target, NO_REG, target); }} void luaK_patchclose (FuncState *fs, int list, int level) { level++; /* argument is +1 to reserve 0 as non-op */ while (list != NO_JUMP) { int next = getjump(fs, list); lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP && (GETARG_A(fs->f->code[list]) == 0 || GETARG_A(fs->f->code[list]) >= level)); SETARG_A(fs->f->code[list], level); list = next; }} void luaK_patchtohere (FuncState *fs, int list) { luaK_getlabel(fs); luaK_concat(fs, &fs->jpc, list);} void luaK_concat (FuncState *fs, int *l1, int l2) { if (l2 == NO_JUMP) return; else if (*l1 == NO_JUMP) *l1 = l2; else { int list = *l1; int next; while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ list = next; fixjump(fs, list, l2); }} static int luaK_code (FuncState *fs, Instruction i) { Proto *f = fs->f; dischargejpc(fs); /* 'pc' will change */ /* put new instruction in code array */ luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, MAX_INT, "opcodes"); f->code[fs->pc] = i; /* save corresponding line information */ luaM_growvector(fs->ls->L, f->lineinfo, fs->pc, f->sizelineinfo, int, MAX_INT, "opcodes"); f->lineinfo[fs->pc] = fs->ls->lastline; return fs->pc++;} int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { lua_assert(getOpMode(o) == iABC); lua_assert(getBMode(o) != OpArgN || b == 0); lua_assert(getCMode(o) != OpArgN || c == 0); lua_assert(a <= MAXARG_A && b <= MAXARG_B && c <= MAXARG_C); return luaK_code(fs, CREATE_ABC(o, a, b, c));} int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); lua_assert(getCMode(o) == OpArgN); lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx); return luaK_code(fs, CREATE_ABx(o, a, bc));} static int codeextraarg (FuncState *fs, int a) { lua_assert(a <= MAXARG_Ax); return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a));} int luaK_codek (FuncState *fs, int reg, int k) { if (k <= MAXARG_Bx) return luaK_codeABx(fs, OP_LOADK, reg, k); else { int p = luaK_codeABx(fs, OP_LOADKX, reg, 0); codeextraarg(fs, k); return p; }} void luaK_checkstack (FuncState *fs, int n) { int newstack = fs->freereg + n; if (newstack > fs->f->maxstacksize) { if (newstack >= MAXREGS) luaX_syntaxerror(fs->ls, "function or expression too complex"); fs->f->maxstacksize = cast_byte(newstack); }} void luaK_reserveregs (FuncState *fs, int n) { luaK_checkstack(fs, n); fs->freereg += n;} static void freereg (FuncState *fs, int reg) { if (!ISK(reg) && reg >= fs->nactvar) { fs->freereg--; lua_assert(reg == fs->freereg); }} static void freeexp (FuncState *fs, expdesc *e) { if (e->k == VNONRELOC) freereg(fs, e->u.info);} /*** Use scanner's table to cache position of constants in constant list** and try to reuse constants*/static int addk (FuncState *fs, TValue *key, TValue *v) { lua_State *L = fs->ls->L; Proto *f = fs->f; TValue *idx = luaH_set(L, fs->ls->h, key); /* index scanner table */ int k, oldsize; if (ttisinteger(idx)) { /* is there an index there? */ k = cast_int(ivalue(idx)); /* correct value? (warning: must distinguish floats from integers!) */ if (k < fs->nk && ttype(&f->k[k]) == ttype(v) && luaV_rawequalobj(&f->k[k], v)) return k; /* reuse index */ } /* constant not found; create a new entry */ oldsize = f->sizek; k = fs->nk; /* numerical value does not need GC barrier; table has no metatable, so it does not need to invalidate cache */ setivalue(idx, k); luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); setobj(L, &f->k[k], v); fs->nk++; luaC_barrier(L, f, v); return k;} int luaK_stringK (FuncState *fs, TString *s) { TValue o; setsvalue(fs->ls->L, &o, s); return addk(fs, &o, &o);} /*** Integers use userdata as keys to avoid collision with floats with same** value; conversion to 'void*' used only for hashing, no "precision"** problems*/int luaK_intK (FuncState *fs, lua_Integer n) { TValue k, o; setpvalue(&k, cast(void*, cast(size_t, n))); setivalue(&o, n); return addk(fs, &k, &o);} static int luaK_numberK (FuncState *fs, lua_Number r) { TValue o; setfltvalue(&o, r); return addk(fs, &o, &o);} static int boolK (FuncState *fs, int b) { TValue o; setbvalue(&o, b); return addk(fs, &o, &o);} static int nilK (FuncState *fs) { TValue k, v; setnilvalue(&v); /* cannot use nil as key; instead use table itself to represent nil */ sethvalue(fs->ls->L, &k, fs->ls->h); return addk(fs, &k, &v);} void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { if (e->k == VCALL) { /* expression is an open function call? */ SETARG_C(getcode(fs, e), nresults+1); } else if (e->k == VVARARG) { SETARG_B(getcode(fs, e), nresults+1); SETARG_A(getcode(fs, e), fs->freereg); luaK_reserveregs(fs, 1); }} void luaK_setoneret (FuncState *fs, expdesc *e) { if (e->k == VCALL) { /* expression is an open function call? */ e->k = VNONRELOC; e->u.info = GETARG_A(getcode(fs, e)); } else if (e->k == VVARARG) { SETARG_B(getcode(fs, e), 2); e->k = VRELOCABLE; /* can relocate its simple result */ }} void luaK_dischargevars (FuncState *fs, expdesc *e) { switch (e->k) { case VLOCAL: { e->k = VNONRELOC; break; } case VUPVAL: { e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); e->k = VRELOCABLE; break; } case VINDEXED: { OpCode op = OP_GETTABUP; /* assume 't' is in an upvalue */ freereg(fs, e->u.ind.idx); if (e->u.ind.vt == VLOCAL) { /* 't' is in a register? */ freereg(fs, e->u.ind.t); op = OP_GETTABLE; } e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx); e->k = VRELOCABLE; break; } case VVARARG: case VCALL: { luaK_setoneret(fs, e); break; } default: break; /* there is one value available (somewhere) */ }} static int code_label (FuncState *fs, int A, int b, int jump) { luaK_getlabel(fs); /* those instructions may be jump targets */ return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump);} static void discharge2reg (FuncState *fs, expdesc *e, int reg) { luaK_dischargevars(fs, e); switch (e->k) { case VNIL: { luaK_nil(fs, reg, 1); break; } case VFALSE: case VTRUE: { luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); break; } case VK: { luaK_codek(fs, reg, e->u.info); break; } case VKFLT: { luaK_codek(fs, reg, luaK_numberK(fs, e->u.nval)); break; } case VKINT: { luaK_codek(fs, reg, luaK_intK(fs, e->u.ival)); break; } case VRELOCABLE: { Instruction *pc = &getcode(fs, e); SETARG_A(*pc, reg); break; } case VNONRELOC: { if (reg != e->u.info) luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0); break; } default: { lua_assert(e->k == VVOID || e->k == VJMP); return; /* nothing to do... */ } } e->u.info = reg; e->k = VNONRELOC;} static void discharge2anyreg (FuncState *fs, expdesc *e) { if (e->k != VNONRELOC) { luaK_reserveregs(fs, 1); discharge2reg(fs, e, fs->freereg-1); }} static void exp2reg (FuncState *fs, expdesc *e, int reg) { discharge2reg(fs, e, reg); if (e->k == VJMP) luaK_concat(fs, &e->t, e->u.info); /* put this jump in 't' list */ if (hasjumps(e)) { int final; /* position after whole expression */Lines 1–500 of 954. Load more
/* ** $Id: lcode.c,v 2.99 2014/12/29 16:49:25 roberto Exp $ ** Code generator for Lua ** See Copyright Notice in lua.h */ #define lcode_c #define LUA_CORE #include "lprefix.h" #include <math.h> #include <stdlib.h> #include "lua.h" #include "lcode.h" #include "ldebug.h" #include "ldo.h" #include "lgc.h" #include "llex.h" #include "lmem.h" #include "lobject.h" #include "lopcodes.h" #include "lparser.h" #include "lstring.h" #include "ltable.h" #include "lvm.h" /* Maximum number of registers in a Lua function */ #define MAXREGS 250 #define hasjumps(e) ((e)->t != (e)->f) static int tonumeral(expdesc *e, TValue *v) { if (e->t != NO_JUMP || e->f != NO_JUMP) return 0; /* not a numeral */ switch (e->k) { case VKINT: if (v) setivalue(v, e->u.ival); return 1; case VKFLT: if (v) setfltvalue(v, e->u.nval); return 1; default: return 0; } } void luaK_nil (FuncState *fs, int from, int n) { Instruction *previous; int l = from + n - 1; /* last register to set nil */ if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ previous = &fs->f->code[fs->pc-1]; if (GET_OPCODE(*previous) == OP_LOADNIL) { int pfrom = GETARG_A(*previous); int pl = pfrom + GETARG_B(*previous); if ((pfrom <= from && from <= pl + 1) || (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */ if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */ if (pl > l) l = pl; /* l = max(l, pl) */ SETARG_A(*previous, from); SETARG_B(*previous, l - from); return; } } /* else go through */ } luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */ } int luaK_jump (FuncState *fs) { int jpc = fs->jpc; /* save list of jumps to here */ int j; fs->jpc = NO_JUMP; j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); luaK_concat(fs, &j, jpc); /* keep them on hold */ return j; } void luaK_ret (FuncState *fs, int first, int nret) { luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); } static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { luaK_codeABC(fs, op, A, B, C); return luaK_jump(fs); } static void fixjump (FuncState *fs, int pc, int dest) { Instruction *jmp = &fs->f->code[pc]; int offset = dest-(pc+1); lua_assert(dest != NO_JUMP); if (abs(offset) > MAXARG_sBx) luaX_syntaxerror(fs->ls, "control structure too long"); SETARG_sBx(*jmp, offset); } /* ** returns current 'pc' and marks it as a jump target (to avoid wrong ** optimizations with consecutive instructions not in the same basic block). */ int luaK_getlabel (FuncState *fs) { fs->lasttarget = fs->pc; return fs->pc; } static int getjump (FuncState *fs, int pc) { int offset = GETARG_sBx(fs->f->code[pc]); if (offset == NO_JUMP) /* point to itself represents end of list */ return NO_JUMP; /* end of list */ else return (pc+1)+offset; /* turn offset into absolute position */ } static Instruction *getjumpcontrol (FuncState *fs, int pc) { Instruction *pi = &fs->f->code[pc]; if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) return pi-1; else return pi; } /* ** check whether list has any jump that do not produce a value ** (or produce an inverted value) */ static int need_value (FuncState *fs, int list) { for (; list != NO_JUMP; list = getjump(fs, list)) { Instruction i = *getjumpcontrol(fs, list); if (GET_OPCODE(i) != OP_TESTSET) return 1; } return 0; /* not found */ } static int patchtestreg (FuncState *fs, int node, int reg) { Instruction *i = getjumpcontrol(fs, node); if (GET_OPCODE(*i) != OP_TESTSET) return 0; /* cannot patch other instructions */ if (reg != NO_REG && reg != GETARG_B(*i)) SETARG_A(*i, reg); else /* no register to put value or register already has the value */ *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); return 1; } static void removevalues (FuncState *fs, int list) { for (; list != NO_JUMP; list = getjump(fs, list)) patchtestreg(fs, list, NO_REG); } static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, int dtarget) { while (list != NO_JUMP) { int next = getjump(fs, list); if (patchtestreg(fs, list, reg)) fixjump(fs, list, vtarget); else fixjump(fs, list, dtarget); /* jump to default target */ list = next; } } static void dischargejpc (FuncState *fs) { patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); fs->jpc = NO_JUMP; } void luaK_patchlist (FuncState *fs, int list, int target) { if (target == fs->pc) luaK_patchtohere(fs, list); else { lua_assert(target < fs->pc); patchlistaux(fs, list, target, NO_REG, target); } } void luaK_patchclose (FuncState *fs, int list, int level) { level++; /* argument is +1 to reserve 0 as non-op */ while (list != NO_JUMP) { int next = getjump(fs, list); lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP && (GETARG_A(fs->f->code[list]) == 0 || GETARG_A(fs->f->code[list]) >= level)); SETARG_A(fs->f->code[list], level); list = next; } } void luaK_patchtohere (FuncState *fs, int list) { luaK_getlabel(fs); luaK_concat(fs, &fs->jpc, list); } void luaK_concat (FuncState *fs, int *l1, int l2) { if (l2 == NO_JUMP) return; else if (*l1 == NO_JUMP) *l1 = l2; else { int list = *l1; int next; while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ list = next; fixjump(fs, list, l2); } } static int luaK_code (FuncState *fs, Instruction i) { Proto *f = fs->f; dischargejpc(fs); /* 'pc' will change */ /* put new instruction in code array */ luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, MAX_INT, "opcodes"); f->code[fs->pc] = i; /* save corresponding line information */ luaM_growvector(fs->ls->L, f->lineinfo, fs->pc, f->sizelineinfo, int, MAX_INT, "opcodes"); f->lineinfo[fs->pc] = fs->ls->lastline; return fs->pc++; } int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { lua_assert(getOpMode(o) == iABC); lua_assert(getBMode(o) != OpArgN || b == 0); lua_assert(getCMode(o) != OpArgN || c == 0); lua_assert(a <= MAXARG_A && b <= MAXARG_B && c <= MAXARG_C); return luaK_code(fs, CREATE_ABC(o, a, b, c)); } int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); lua_assert(getCMode(o) == OpArgN); lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx); return luaK_code(fs, CREATE_ABx(o, a, bc)); } static int codeextraarg (FuncState *fs, int a) { lua_assert(a <= MAXARG_Ax); return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a)); } int luaK_codek (FuncState *fs, int reg, int k) { if (k <= MAXARG_Bx) return luaK_codeABx(fs, OP_LOADK, reg, k); else { int p = luaK_codeABx(fs, OP_LOADKX, reg, 0); codeextraarg(fs, k); return p; } } void luaK_checkstack (FuncState *fs, int n) { int newstack = fs->freereg + n; if (newstack > fs->f->maxstacksize) { if (newstack >= MAXREGS) luaX_syntaxerror(fs->ls, "function or expression too complex"); fs->f->maxstacksize = cast_byte(newstack); } } void luaK_reserveregs (FuncState *fs, int n) { luaK_checkstack(fs, n); fs->freereg += n; } static void freereg (FuncState *fs, int reg) { if (!ISK(reg) && reg >= fs->nactvar) { fs->freereg--; lua_assert(reg == fs->freereg); } } static void freeexp (FuncState *fs, expdesc *e) { if (e->k == VNONRELOC) freereg(fs, e->u.info); } /* ** Use scanner's table to cache position of constants in constant list ** and try to reuse constants */ static int addk (FuncState *fs, TValue *key, TValue *v) { lua_State *L = fs->ls->L; Proto *f = fs->f; TValue *idx = luaH_set(L, fs->ls->h, key); /* index scanner table */ int k, oldsize; if (ttisinteger(idx)) { /* is there an index there? */ k = cast_int(ivalue(idx)); /* correct value? (warning: must distinguish floats from integers!) */ if (k < fs->nk && ttype(&f->k[k]) == ttype(v) && luaV_rawequalobj(&f->k[k], v)) return k; /* reuse index */ } /* constant not found; create a new entry */ oldsize = f->sizek; k = fs->nk; /* numerical value does not need GC barrier; table has no metatable, so it does not need to invalidate cache */ setivalue(idx, k); luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); setobj(L, &f->k[k], v); fs->nk++; luaC_barrier(L, f, v); return k; } int luaK_stringK (FuncState *fs, TString *s) { TValue o; setsvalue(fs->ls->L, &o, s); return addk(fs, &o, &o); } /* ** Integers use userdata as keys to avoid collision with floats with same ** value; conversion to 'void*' used only for hashing, no "precision" ** problems */ int luaK_intK (FuncState *fs, lua_Integer n) { TValue k, o; setpvalue(&k, cast(void*, cast(size_t, n))); setivalue(&o, n); return addk(fs, &k, &o); } static int luaK_numberK (FuncState *fs, lua_Number r) { TValue o; setfltvalue(&o, r); return addk(fs, &o, &o); } static int boolK (FuncState *fs, int b) { TValue o; setbvalue(&o, b); return addk(fs, &o, &o); } static int nilK (FuncState *fs) { TValue k, v; setnilvalue(&v); /* cannot use nil as key; instead use table itself to represent nil */ sethvalue(fs->ls->L, &k, fs->ls->h); return addk(fs, &k, &v); } void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { if (e->k == VCALL) { /* expression is an open function call? */ SETARG_C(getcode(fs, e), nresults+1); } else if (e->k == VVARARG) { SETARG_B(getcode(fs, e), nresults+1); SETARG_A(getcode(fs, e), fs->freereg); luaK_reserveregs(fs, 1); } } void luaK_setoneret (FuncState *fs, expdesc *e) { if (e->k == VCALL) { /* expression is an open function call? */ e->k = VNONRELOC; e->u.info = GETARG_A(getcode(fs, e)); } else if (e->k == VVARARG) { SETARG_B(getcode(fs, e), 2); e->k = VRELOCABLE; /* can relocate its simple result */ } } void luaK_dischargevars (FuncState *fs, expdesc *e) { switch (e->k) { case VLOCAL: { e->k = VNONRELOC; break; } case VUPVAL: { e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); e->k = VRELOCABLE; break; } case VINDEXED: { OpCode op = OP_GETTABUP; /* assume 't' is in an upvalue */ freereg(fs, e->u.ind.idx); if (e->u.ind.vt == VLOCAL) { /* 't' is in a register? */ freereg(fs, e->u.ind.t); op = OP_GETTABLE; } e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx); e->k = VRELOCABLE; break; } case VVARARG: case VCALL: { luaK_setoneret(fs, e); break; } default: break; /* there is one value available (somewhere) */ } } static int code_label (FuncState *fs, int A, int b, int jump) { luaK_getlabel(fs); /* those instructions may be jump targets */ return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); } static void discharge2reg (FuncState *fs, expdesc *e, int reg) { luaK_dischargevars(fs, e); switch (e->k) { case VNIL: { luaK_nil(fs, reg, 1); break; } case VFALSE: case VTRUE: { luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); break; } case VK: { luaK_codek(fs, reg, e->u.info); break; } case VKFLT: { luaK_codek(fs, reg, luaK_numberK(fs, e->u.nval)); break; } case VKINT: { luaK_codek(fs, reg, luaK_intK(fs, e->u.ival)); break; } case VRELOCABLE: { Instruction *pc = &getcode(fs, e); SETARG_A(*pc, reg); break; } case VNONRELOC: { if (reg != e->u.info) luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0); break; } default: { lua_assert(e->k == VVOID || e->k == VJMP); return; /* nothing to do... */ } } e->u.info = reg; e->k = VNONRELOC; } static void discharge2anyreg (FuncState *fs, expdesc *e) { if (e->k != VNONRELOC) { luaK_reserveregs(fs, 1); discharge2reg(fs, e, fs->freereg-1); } } static void exp2reg (FuncState *fs, expdesc *e, int reg) { discharge2reg(fs, e, reg); if (e->k == VJMP) luaK_concat(fs, &e->t, e->u.info); /* put this jump in 't' list */ if (hasjumps(e)) { int final; /* position after whole expression */