From 3afe85b2ce9ffdc8eca819ddc1c05414701606fd Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 14 Feb 2000 14:51:08 -0200 Subject: new version for INSTRUCTION formats --- lparser.c | 332 +++++++++++++++++++++++--------------------------------------- 1 file changed, 122 insertions(+), 210 deletions(-) (limited to 'lparser.c') diff --git a/lparser.c b/lparser.c index 09e7dd53..c185b506 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 1.57 2000/01/28 16:53:00 roberto Exp roberto $ +** $Id: lparser.c,v 1.58 2000/02/11 16:52:54 roberto Exp roberto $ ** LL(1) Parser and code generator for Lua ** See Copyright Notice in lua.h */ @@ -20,30 +20,27 @@ -/* size of a "normal" jump instruction: OpCode + 1 byte */ -#define JMPSIZE 2 - /* maximum number of local variables */ #ifndef MAXLOCALS -#define MAXLOCALS 200 /* arbitrary limit (<256) */ +#define MAXLOCALS 200 /* arbitrary limit (locvars (-1 if no debug information) */ @@ -131,89 +127,63 @@ static void checklimit (LexState *ls, int val, int limit, const char *msg) { } -static void check_pc (LexState *ls, int n) { - luaM_growvector(ls->L, ls->fs->f->code, ls->fs->pc, n, - Byte, codeEM, MAX_INT); +static int code_instruction (LexState *ls, Instruction i) { + FuncState *fs = ls->fs; + luaM_growvector(ls->L, fs->f->code, fs->pc, 1, Instruction, codeEM, MAXARG_S); + fs->f->code[fs->pc] = i; + return fs->pc++; } -static void code_byte (LexState *ls, Byte c) { - check_pc(ls, 1); - ls->fs->f->code[ls->fs->pc++] = c; +static void fix_jump (LexState *ls, int pc, int dest) { + Instruction *jmp = &ls->fs->f->code[pc]; + /* jump is relative to position following jump instruction */ + *jmp = SETARG_S(*jmp, dest-(pc+1)); } static void deltastack (LexState *ls, int delta) { FuncState *fs = ls->fs; fs->stacksize += delta; - if (fs->stacksize > fs->maxstacksize) { - if (fs->stacksize > MAX_BYTE) - luaY_error(ls, "function or expression too complex"); - fs->maxstacksize = fs->stacksize; + if (delta > 0 && fs->stacksize > fs->f->maxstacksize) { + fs->f->maxstacksize = fs->stacksize; } } -static void code_oparg_at (LexState *ls, int pc, OpCode op, - int arg, int delta) { - Byte *code = ls->fs->f->code; +static int aux_code (LexState *ls, OpCode op, Instruction i, int delta) { deltastack(ls, delta); - if (arg <= MAX_BYTE) { - code[pc] = (Byte)op; - code[pc+1] = (Byte)arg; - } - else if (arg > MAX_ARG) - luaY_error(ls, "code too long"); - else { /* MAX_BYTE < arg < MAX_ARG */ - if (arg > MAX_WORD) { - code[pc] = (Byte)LONGARG; - code[pc+1] = (Byte)(arg>>16); - pc += 2; - } - code[pc] = (Byte)(op-1); /* opcode for word argument */ - code[pc+1] = (Byte)((arg&0xFFFF)>>8); - code[pc+2] = (Byte)(arg&0xFF); - } + return code_instruction(ls, SET_OPCODE(i, op)); } -static int codesize (int arg) { - if (arg <= MAX_BYTE) return 2; /* opcode + 1 byte */ - else if (arg <= MAX_WORD) return 3; /* opcode + 1 word (2 bytes) */ - else return 5; /* LONGARG + 1 byte + opcode + 1 word (2 bytes) */ +static int code_0 (LexState *ls, OpCode op, int delta) { + return aux_code(ls, op, 0, delta); } -static int fix_opcode (LexState *ls, int pc, OpCode op, int arg) { - int tomove = codesize(arg)-2; - if (tomove > 0) { /* need to open space? */ - FuncState *fs = ls->fs; - TProtoFunc *f = fs->f; - check_pc(ls, tomove); - luaO_memup(f->code+pc+tomove, f->code+pc, fs->pc-pc); - fs->pc += tomove; - } - code_oparg_at(ls, pc, op, arg, 0); - return tomove; + +static int code_U (LexState *ls, OpCode op, int u, int delta) { + Instruction i = SETARG_U(0, u); + return aux_code(ls, op, i, delta); } -static void code_oparg (LexState *ls, OpCode op, int arg, int delta) { - int size = codesize(arg); - check_pc(ls, size); - code_oparg_at(ls, ls->fs->pc, op, arg, delta); - ls->fs->pc += size; +static int code_S (LexState *ls, OpCode op, int s, int delta) { + Instruction i = SETARG_S(0, s); + return aux_code(ls, op, i, delta); } -static void code_opcode (LexState *ls, OpCode op, int delta) { - deltastack(ls, delta); - code_byte(ls, (Byte)op); +static int code_AB (LexState *ls, OpCode op, int a, int b, int delta) { + Instruction i = SETARG_A(0, a); + i = SETARG_B(i, b); + return aux_code(ls, op, i, delta); } static void code_kstr (LexState *ls, int c) { - code_oparg(ls, PUSHSTRING, c, 1); + code_U(ls, PUSHSTRING, c, 1); } @@ -226,8 +196,8 @@ static int string_constant (LexState *ls, FuncState *fs, TaggedString *s) { TProtoFunc *f = fs->f; int c = s->constindex; if (c >= f->nkstr || f->kstr[c] != s) { - luaM_growvector(ls->L, f->kstr, f->nkstr, 1, - TaggedString *, constantEM, MAX_ARG); + luaM_growvector(ls->L, f->kstr, f->nkstr, 1, TaggedString *, + constantEM, MAXARG_U); c = f->nkstr++; f->kstr[c] = s; s->constindex = c; /* hint for next time */ @@ -250,8 +220,7 @@ static int real_constant (LexState *ls, real r) { while (--c >= lim) if (f->knum[c] == r) return c; /* not found; create a new entry */ - luaM_growvector(ls->L, f->knum, f->nknum, 1, - real, constantEM, MAX_ARG); + luaM_growvector(ls->L, f->knum, f->nknum, 1, real, constantEM, MAXARG_U); c = f->nknum++; f->knum[c] = r; return c; @@ -259,27 +228,10 @@ static int real_constant (LexState *ls, real r) { static void code_number (LexState *ls, real f) { - real af = (f<0) ? -f : f; - if (0 <= af && af <= (real)MAX_WORD && (int)af == af) { - /* abs(f) has a short integer value */ - code_oparg(ls, (f<0) ? PUSHINTNEG : PUSHINT, (int)af, 1); - } + if ((real)(-MAXARG_S) <= f && f <= (real)MAXARG_S && (int)f == f) + code_S(ls, PUSHINT, (int)f, 1); /* f has a short integer value */ else - code_oparg(ls, PUSHNUMBER, real_constant(ls, f), 1); -} - - -static void flush_record (LexState *ls, int n) { - if (n > 0) - code_oparg(ls, SETMAP, n-1, -2*n); -} - - -static void flush_list (LexState *ls, int m, int n) { - if (n > 0) { - code_oparg(ls, SETLIST, m, -n); - code_byte(ls, (Byte)n); - } + code_U(ls, PUSHNUMBER, real_constant(ls, f), 1); } @@ -371,14 +323,14 @@ static void pushupvalue (LexState *ls, TaggedString *n) { luaX_syntaxerror(ls, "cannot access upvalue in main", n->str); if (aux_localname(ls->fs, n) >= 0) luaX_syntaxerror(ls, "cannot access an upvalue in current scope", n->str); - code_oparg(ls, PUSHUPVALUE, indexupvalue(ls, n), 1); + code_U(ls, PUSHUPVALUE, indexupvalue(ls, n), 1); } static void check_debugline (LexState *ls) { if (ls->L->debug && ls->linenumber != ls->fs->lastsetline) { - code_oparg(ls, SETLINE, ls->linenumber, 0); + code_U(ls, SETLINE, ls->linenumber, 0); ls->fs->lastsetline = ls->linenumber; } } @@ -386,16 +338,16 @@ static void check_debugline (LexState *ls) { static void adjuststack (LexState *ls, int n) { if (n > 0) - code_oparg(ls, POP, n, -n); + code_U(ls, POP, n, -n); else if (n < 0) - code_oparg(ls, PUSHNIL, (-n)-1, -n); + code_U(ls, PUSHNIL, (-n)-1, -n); } static void close_exp (LexState *ls, int pc, int nresults) { if (pc > 0) { /* expression is an open function call? */ - Byte *code = ls->fs->f->code; - code[pc-1] = (Byte)nresults; /* set nresults */ + Instruction *i = &ls->fs->f->code[pc]; + *i = SETARG_B(*i, nresults); /* set nresults */ if (nresults != MULT_RET) deltastack(ls, nresults); /* push results */ } @@ -426,13 +378,12 @@ static void code_args (LexState *ls, int nparams, int dots) { FuncState *fs = ls->fs; adjustlocalvars(ls, nparams, 0); checklimit(ls, fs->nlocalvar, MAXPARAMS, "parameters"); - nparams = fs->nlocalvar; - if (!dots) { - fs->f->code[1] = (Byte)nparams; /* fill-in arg information */ + nparams = fs->nlocalvar; /* `self' could be there already */ + fs->f->numparams = nparams; + fs->f->is_vararg = dots; + if (!dots) deltastack(ls, nparams); - } else { - fs->f->code[1] = (Byte)(nparams+ZEROVARARG); deltastack(ls, nparams+1); add_localvar(ls, luaS_newfixed(ls->L, "arg")); } @@ -451,17 +402,17 @@ static void unloaddot (LexState *ls, vardesc *v) { static void lua_pushvar (LexState *ls, vardesc *var) { switch (var->k) { case VLOCAL: - code_oparg(ls, PUSHLOCAL, var->info, 1); + code_U(ls, PUSHLOCAL, var->info, 1); break; case VGLOBAL: - code_oparg(ls, GETGLOBAL, var->info, 1); + code_U(ls, GETGLOBAL, var->info, 1); assertglobal(ls, var->info); /* make sure that there is a global */ break; case VDOT: - code_oparg(ls, GETDOTTED, var->info, 0); + code_U(ls, GETDOTTED, var->info, 0); break; case VINDEXED: - code_opcode(ls, GETTABLE, -1); + code_0(ls, GETTABLE, -1); break; case VEXP: close_exp(ls, var->info, 1); /* function must return 1 value */ @@ -475,14 +426,14 @@ static void lua_pushvar (LexState *ls, vardesc *var) { static void storevar (LexState *ls, const vardesc *var) { switch (var->k) { case VLOCAL: - code_oparg(ls, SETLOCAL, var->info, -1); + code_U(ls, SETLOCAL, var->info, -1); break; case VGLOBAL: - code_oparg(ls, SETGLOBAL, var->info, -1); + code_U(ls, SETGLOBAL, var->info, -1); assertglobal(ls, var->info); /* make sure that there is a global */ break; case VINDEXED: - code_opcode(ls, SETTABLEPOP, -3); + code_0(ls, SETTABLEPOP, -3); break; default: LUA_INTERNALERROR(ls->L, "invalid var kind to store"); @@ -490,43 +441,16 @@ static void storevar (LexState *ls, const vardesc *var) { } -static int fix_jump (LexState *ls, int pc, OpCode op, int n) { - /* jump is relative to position following jump instruction */ - return fix_opcode(ls, pc, op, n-(pc+JMPSIZE)); -} - - -static void fix_upjmp (LexState *ls, OpCode op, int pos) { - int delta = ls->fs->pc+JMPSIZE - pos; /* jump is relative */ - code_oparg(ls, op, delta+(codesize(delta)-2), 0); -} - - -static void codeIf (LexState *ls, int thenAdd, int elseAdd) { - FuncState *fs = ls->fs; - int elseinit = elseAdd+JMPSIZE; - if (fs->pc == elseinit) { /* no else part? */ - fs->pc -= JMPSIZE; - elseinit = fs->pc; - } - else - elseinit += fix_jump(ls, elseAdd, JMP, fs->pc); - fix_jump(ls, thenAdd, IFFJMP, elseinit); -} - - static void func_onstack (LexState *ls, FuncState *func) { - FuncState *fs = ls->fs; - TProtoFunc *f = fs->f; + TProtoFunc *f = ls->fs->f; int i; - luaM_growvector(ls->L, f->kproto, f->nkproto, 1, - TProtoFunc *, constantEM, MAX_ARG); - f->kproto[f->nkproto] = func->f; for (i=0; inupvalues; i++) lua_pushvar(ls, &func->upvalues[i]); + luaM_growvector(ls->L, f->kproto, f->nkproto, 1, TProtoFunc *, + constantEM, MAXARG_A); + f->kproto[f->nkproto++] = func->f; deltastack(ls, 1); /* CLOSURE puts one extra element (before popping) */ - code_oparg(ls, CLOSURE, f->nkproto++, -func->nupvalues); - code_byte(ls, (Byte)func->nupvalues); + code_AB(ls, CLOSURE, f->nkproto-1, func->nupvalues, -func->nupvalues); } @@ -536,7 +460,6 @@ static void init_state (LexState *ls, FuncState *fs, TaggedString *source) { fs->prev = ls->fs; /* linked list of funcstates */ ls->fs = fs; fs->stacksize = 0; - fs->maxstacksize = 0; fs->nlocalvar = 0; fs->nupvalues = 0; fs->lastsetline = 0; @@ -544,9 +467,10 @@ static void init_state (LexState *ls, FuncState *fs, TaggedString *source) { f->source = source; fs->pc = 0; f->code = NULL; + f->maxstacksize = 0; + f->numparams = 0; /* default for main chunk */ + f->is_vararg = 0; /* default for main chunk */ fs->nvars = (L->debug) ? 0 : -1; /* flag no debug information? */ - code_byte(ls, 0); /* to be filled with maxstacksize */ - code_byte(ls, 0); /* to be filled with arg information */ /* push function (to avoid GC) */ tfvalue(L->top) = f; ttype(L->top) = LUA_T_LPROTO; @@ -557,9 +481,8 @@ static void init_state (LexState *ls, FuncState *fs, TaggedString *source) { static void close_func (LexState *ls) { FuncState *fs = ls->fs; TProtoFunc *f = fs->f; - code_opcode(ls, ENDCODE, 0); - f->code[0] = (Byte)fs->maxstacksize; - luaM_reallocvector(ls->L, f->code, fs->pc, Byte); + code_0(ls, ENDCODE, 0); + luaM_reallocvector(ls->L, f->code, fs->pc, Instruction); luaM_reallocvector(ls->L, f->kstr, f->nkstr, TaggedString *); luaM_reallocvector(ls->L, f->knum, f->nknum, real); luaM_reallocvector(ls->L, f->kproto, f->nkproto, TProtoFunc *); @@ -662,28 +585,6 @@ TProtoFunc *luaY_parser (lua_State *L, ZIO *z) { /*============================================================*/ - -static int SaveWord (LexState *ls) { - int res = ls->fs->pc; - check_pc(ls, JMPSIZE); - ls->fs->pc += JMPSIZE; /* open space */ - return res; -} - - -static int SaveWordPop (LexState *ls) { - deltastack(ls, -1); /* pop condition */ - return SaveWord(ls); -} - - -static int cond (LexState *ls) { - /* cond -> exp1 */ - exp1(ls); - return SaveWordPop(ls); -} - - static void explist1 (LexState *ls, listdesc *d) { vardesc v; expr(ls, &v); @@ -744,11 +645,8 @@ static int funcparams (LexState *ls, int slf) { luaY_error(ls, "function arguments expected"); break; } - code_byte(ls, CALL); - code_byte(ls, 0); /* save space for nresult */ - code_byte(ls, (Byte)slevel); fs->stacksize = slevel; /* call will remove func and params */ - return fs->pc-1; + return code_AB(ls, CALL, slevel, 0, 0); } @@ -775,7 +673,7 @@ static void var_or_func_tail (LexState *ls, vardesc *v) { next(ls); name = checkname(ls); lua_pushvar(ls, v); /* `v' must be on stack */ - code_oparg(ls, PUSHSELF, name, 1); + code_U(ls, PUSHSELF, name, 1); v->k = VEXP; v->info = funcparams(ls, 1); break; @@ -836,16 +734,20 @@ static void recfield (LexState *ls) { static int recfields (LexState *ls) { /* recfields -> { ',' recfield } [','] */ int n = 1; /* one has been read before */ + int mod_n = 1; /* mod_n == n%RFIELDS_PER_FLUSH */ while (ls->token == ',') { next(ls); if (ls->token == ';' || ls->token == '}') break; recfield(ls); n++; - if (n%RFIELDS_PER_FLUSH == 0) - flush_record(ls, RFIELDS_PER_FLUSH); + if (++mod_n == RFIELDS_PER_FLUSH) { + code_U(ls, SETMAP, RFIELDS_PER_FLUSH-1, -2*RFIELDS_PER_FLUSH); + mod_n = 0; + } } - flush_record(ls, n%RFIELDS_PER_FLUSH); + if (mod_n) + code_U(ls, SETMAP, mod_n-1, -2*mod_n); return n; } @@ -853,16 +755,23 @@ static int recfields (LexState *ls) { static int listfields (LexState *ls) { /* listfields -> { ',' exp1 } [','] */ int n = 1; /* one has been read before */ + int mod_n = 1; /* mod_n == n%LFIELDS_PER_FLUSH */ while (ls->token == ',') { next(ls); if (ls->token == ';' || ls->token == '}') break; exp1(ls); n++; - if (n%LFIELDS_PER_FLUSH == 0) - flush_list(ls, n/LFIELDS_PER_FLUSH - 1, LFIELDS_PER_FLUSH); + checklimit(ls, n, MAXARG_A*LFIELDS_PER_FLUSH, + "items in a list initializer"); + if (++mod_n == LFIELDS_PER_FLUSH) { + code_AB(ls, SETLIST, n/LFIELDS_PER_FLUSH - 1, LFIELDS_PER_FLUSH-1, + -LFIELDS_PER_FLUSH); + mod_n = 0; + } } - flush_list(ls, n/LFIELDS_PER_FLUSH, n%LFIELDS_PER_FLUSH); + if (mod_n > 0) + code_AB(ls, SETLIST, n/LFIELDS_PER_FLUSH, mod_n-1, -mod_n); return n; } @@ -920,10 +829,9 @@ static void constructor_part (LexState *ls, constdesc *cd) { static void constructor (LexState *ls) { /* constructor -> '{' constructor_part [';' constructor_part] '}' */ int line = ls->linenumber; - int pc = SaveWord(ls); + int pc = code_U(ls, CREATETABLE, 0, 1); int nelems; constdesc cd; - deltastack(ls, 1); check(ls, '{'); constructor_part(ls, &cd); nelems = cd.n; @@ -936,7 +844,8 @@ static void constructor (LexState *ls) { nelems += other_cd.n; } check_match(ls, '}', '{', line); - fix_opcode(ls, pc, CREATEARRAY, nelems); + /* set initial table size */ + ls->fs->f->code[pc] = SETARG_U(ls->fs->f->code[pc], nelems); } /* }====================================================================== */ @@ -1009,7 +918,7 @@ static void push (LexState *ls, stack_op *s, int op) { static void pop_to (LexState *ls, stack_op *s, int prio) { int op; while (s->top > 0 && priority[(op=s->ops[s->top-1])] >= prio) { - code_opcode(ls, opcodes[op], optop--; } } @@ -1113,10 +1022,10 @@ static void expr (LexState *ls, vardesc *v) { int pc; lua_pushvar(ls, v); next(ls); - pc = SaveWordPop(ls); + pc = code_S(ls, op, 0, -1); arith_exp(ls, v); lua_pushvar(ls, v); - fix_jump(ls, pc, op, ls->fs->pc); + fix_jump(ls, pc, ls->fs->pc); } } @@ -1167,7 +1076,7 @@ static int assignment (LexState *ls, vardesc *v, int nvars) { storevar(ls, v); } else { /* indexed var with values in between*/ - code_oparg(ls, SETTABLE, left+(nvars-1), -1); + code_U(ls, SETTABLE, left+(nvars-1), -1); left += 2; /* table&index are not popped, because they aren't on top */ } return left; @@ -1175,22 +1084,18 @@ static int assignment (LexState *ls, vardesc *v, int nvars) { static void whilestat (LexState *ls, int line) { - /* whilestat -> WHILE cond DO block END */ + /* whilestat -> WHILE exp1 DO block END */ FuncState *fs = ls->fs; - TProtoFunc *f = fs->f; int while_init = fs->pc; - int cond_end, cond_size; + int j1; next(ls); - cond_end = cond(ls); + exp1(ls); + j1 = code_U(ls, IFFJMP, 0, -1); /* jump to exit loop */ check(ls, DO); block(ls); check_match(ls, END, WHILE, line); - cond_size = cond_end-while_init; - check_pc(ls, cond_size); - memcpy(f->code+fs->pc, f->code+while_init, cond_size); - luaO_memdown(f->code+while_init, f->code+cond_end, fs->pc-while_init); - while_init += JMPSIZE + fix_jump(ls, while_init, JMP, fs->pc-cond_size); - fix_upjmp(ls, IFTUPJMP, while_init); + fix_jump(ls, code_U(ls, JMP, 0, 0), while_init); /* jump to keep loop */ + fix_jump(ls, j1, fs->pc); } @@ -1202,8 +1107,7 @@ static void repeatstat (LexState *ls, int line) { block(ls); check_match(ls, UNTIL, REPEAT, line); exp1(ls); - fix_upjmp(ls, IFFUPJMP, repeat_init); - deltastack(ls, -1); /* pops condition */ + fix_jump(ls, code_U(ls, IFFJMP, 0, -1), repeat_init); } @@ -1295,21 +1199,29 @@ static void namestat (LexState *ls) { static void ifpart (LexState *ls, int line) { /* ifpart -> cond THEN block [ELSE block | ELSEIF ifpart] */ + FuncState *fs = ls->fs; int c; - int e; + int je; next(ls); /* skip IF or ELSEIF */ - c = cond(ls); + exp1(ls); /* cond */ + c = code_U(ls, IFFJMP, 0, -1); /* jump `then' if `cond' is false */ check(ls, THEN); - block(ls); - e = SaveWord(ls); + block(ls); /* `then' part */ + je = code_U(ls, JMP, 0, 0); /* jump `else' part after `then' */ if (ls->token == ELSEIF) ifpart(ls, line); else { if (optional(ls, ELSE)) - block(ls); + block(ls); /* `else' part */ check_match(ls, END, IF, line); } - codeIf(ls, c, e); + if (fs->pc == je+1) { /* `else' part empty? */ + fs->pc--; /* remove last jump */ + je--; /* first jump will be smaller */ + } + else + fix_jump(ls, je, fs->pc); /* fix last jump */ + fix_jump(ls, c, je+1); /* fix first jump to beginning of `else' part */ } @@ -1395,9 +1307,9 @@ static void parlist (LexState *ls) { static void body (LexState *ls, int needself, int line) { /* body -> '(' parlist ')' chunk END */ - FuncState newfs; - init_state(ls, &newfs, ls->fs->f->source); - newfs.f->lineDefined = line; + FuncState new_fs; + init_state(ls, &new_fs, ls->fs->f->source); + new_fs.f->lineDefined = line; check(ls, '('); if (needself) add_localvar(ls, luaS_newfixed(ls->L, "self")); @@ -1406,7 +1318,7 @@ static void body (LexState *ls, int needself, int line) { chunk(ls); check_match(ls, END, FUNCTION, line); close_func(ls); - func_onstack(ls, &newfs); + func_onstack(ls, &new_fs); } @@ -1418,12 +1330,12 @@ static void ret (LexState *ls) { next(ls); explist(ls, &e); if (e.pc > 0) { /* expression is an open function call? */ - Byte *code = ls->fs->f->code; - code[e.pc-2] = TAILCALL; /* instead of a conventional CALL */ - code[e.pc-1] = (Byte)ls->fs->nlocalvar; + Instruction *i = &ls->fs->f->code[e.pc]; + *i = SET_OPCODE(*i, TAILCALL); /* instead of a conventional CALL */ + *i = SETARG_B(*i, ls->fs->nlocalvar); } else - code_oparg(ls, RETCODE, ls->fs->nlocalvar, 0); + code_U(ls, RETCODE, ls->fs->nlocalvar, 0); ls->fs->stacksize = ls->fs->nlocalvar; /* removes all temp values */ optional(ls, ';'); } -- cgit v1.2.3-55-g6feb