diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-03-03 15:53:17 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-03-03 15:53:17 -0300 |
| commit | d1ea38580ae35a3a34e7122c41682af7f9901030 (patch) | |
| tree | ce7fa1568be9eb757805966b77ea1eac2bc604f6 /lcode.c | |
| parent | 3c9d999424520c809e05bee11d81788b488434f6 (diff) | |
| download | lua-d1ea38580ae35a3a34e7122c41682af7f9901030.tar.gz lua-d1ea38580ae35a3a34e7122c41682af7f9901030.tar.bz2 lua-d1ea38580ae35a3a34e7122c41682af7f9901030.zip | |
change of code generation design (independent functions for each opcode)
Diffstat (limited to 'lcode.c')
| -rw-r--r-- | lcode.c | 223 |
1 files changed, 100 insertions, 123 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lcode.c,v 1.2 2000/03/03 12:33:59 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 1.3 2000/03/03 14:58:26 roberto Exp roberto $ |
| 3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -20,12 +20,10 @@ void luaK_error (LexState *ls, const char *msg) { | |||
| 20 | } | 20 | } |
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | static Instruction *last_i (FuncState *fs) { | 23 | static Instruction *last_i (LexState *ls, expdesc *v) { |
| 24 | static Instruction dummy = SET_OPCODE(0, ENDCODE); | 24 | FuncState *fs = ls->fs; |
| 25 | if (fs->last_pc < 0) | 25 | int last_pc = (v->info != NOJUMPS) ? v->info : fs->pc-1; |
| 26 | return &dummy; | 26 | return &fs->f->code[last_pc]; |
| 27 | else | ||
| 28 | return &fs->f->code[fs->last_pc]; | ||
| 29 | } | 27 | } |
| 30 | 28 | ||
| 31 | 29 | ||
| @@ -37,58 +35,64 @@ int luaK_primitivecode (LexState *ls, Instruction i) { | |||
| 37 | } | 35 | } |
| 38 | 36 | ||
| 39 | 37 | ||
| 38 | static void luaK_minus (LexState *ls, expdesc *v) { | ||
| 39 | Instruction *last = last_i(ls, v); | ||
| 40 | switch(GET_OPCODE(*last)) { | ||
| 41 | case PUSHINT: *last = SETARG_S(*last, -GETARG_S(*last)); return; | ||
| 42 | case PUSHNUM: *last = SET_OPCODE(*last, PUSHNEGNUM); return; | ||
| 43 | case PUSHNEGNUM: *last = SET_OPCODE(*last, PUSHNUM); return; | ||
| 44 | default: luaK_primitivecode(ls, CREATE_0(MINUSOP)); | ||
| 45 | } | ||
| 46 | } | ||
| 40 | 47 | ||
| 41 | int luaK_code (LexState *ls, Instruction i) { | ||
| 42 | FuncState *fs = ls->fs; | ||
| 43 | Instruction *last = last_i(fs); | ||
| 44 | switch (GET_OPCODE(i)) { | ||
| 45 | |||
| 46 | case MINUSOP: | ||
| 47 | switch(GET_OPCODE(*last)) { | ||
| 48 | case PUSHINT: *last = SETARG_S(*last, -GETARG_S(*last)); break; | ||
| 49 | case PUSHNUM: *last = SET_OPCODE(*last, PUSHNEGNUM); break; | ||
| 50 | case PUSHNEGNUM: *last = SET_OPCODE(*last, PUSHNUM); break; | ||
| 51 | default: fs->last_pc = luaK_primitivecode(ls, i); | ||
| 52 | } | ||
| 53 | break; | ||
| 54 | 48 | ||
| 55 | case GETTABLE: | 49 | static void luaK_gettable (LexState *ls, expdesc *v) { |
| 56 | switch(GET_OPCODE(*last)) { | 50 | Instruction *last = last_i(ls, v); |
| 57 | case PUSHSTRING: *last = SET_OPCODE(*last, GETDOTTED); break; | 51 | luaK_deltastack(ls, -1); |
| 58 | default: fs->last_pc = luaK_primitivecode(ls, i); | 52 | switch(GET_OPCODE(*last)) { |
| 59 | } | 53 | case PUSHSTRING: *last = SET_OPCODE(*last, GETDOTTED); break; |
| 60 | break; | 54 | default: luaK_primitivecode(ls, CREATE_0(GETTABLE)); |
| 55 | } | ||
| 56 | } | ||
| 61 | 57 | ||
| 62 | case RETCODE: | ||
| 63 | switch(GET_OPCODE(*last)) { | ||
| 64 | case CALL: | ||
| 65 | *last = SET_OPCODE(*last, TAILCALL); | ||
| 66 | *last = SETARG_B(*last, GETARG_U(i)); | ||
| 67 | break; | ||
| 68 | default: fs->last_pc = luaK_primitivecode(ls, i); | ||
| 69 | } | ||
| 70 | break; | ||
| 71 | 58 | ||
| 72 | case ADDOP: | 59 | static void luaK_add (LexState *ls, expdesc *v) { |
| 73 | switch(GET_OPCODE(*last)) { | 60 | Instruction *last = last_i(ls, v); |
| 74 | case PUSHINT: *last = SET_OPCODE(*last, ADDI); break; | 61 | luaK_deltastack(ls, -1); |
| 75 | default: fs->last_pc = luaK_primitivecode(ls, i); | 62 | switch(GET_OPCODE(*last)) { |
| 76 | } | 63 | case PUSHINT: *last = SET_OPCODE(*last, ADDI); break; |
| 77 | break; | 64 | default: luaK_primitivecode(ls, CREATE_0(ADDOP)); |
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 78 | 68 | ||
| 79 | case SUBOP: | 69 | static void luaK_sub (LexState *ls, expdesc *v) { |
| 80 | switch(GET_OPCODE(*last)) { | 70 | Instruction *last = last_i(ls, v); |
| 81 | case PUSHINT: | 71 | luaK_deltastack(ls, -1); |
| 82 | *last = SET_OPCODE(*last, ADDI); | 72 | switch(GET_OPCODE(*last)) { |
| 83 | *last = SETARG_S(*last, -GETARG_S(*last)); | 73 | case PUSHINT: |
| 84 | break; | 74 | *last = SET_OPCODE(*last, ADDI); |
| 85 | default: fs->last_pc = luaK_primitivecode(ls, i); | 75 | *last = SETARG_S(*last, -GETARG_S(*last)); |
| 86 | } | ||
| 87 | break; | 76 | break; |
| 77 | default: luaK_primitivecode(ls, CREATE_0(SUBOP)); | ||
| 78 | } | ||
| 79 | } | ||
| 88 | 80 | ||
| 89 | default: fs->last_pc = luaK_primitivecode(ls, i); | 81 | |
| 82 | void luaK_retcode (LexState *ls, int nlocals, listdesc *e) { | ||
| 83 | if (e->n > 0 && luaK_iscall(ls, e->info)) { | ||
| 84 | Instruction *last = &ls->fs->f->code[ls->fs->pc-1]; | ||
| 85 | *last = SET_OPCODE(*last, TAILCALL); | ||
| 86 | *last = SETARG_B(*last, nlocals); | ||
| 90 | } | 87 | } |
| 91 | return fs->last_pc; | 88 | else |
| 89 | luaK_U(ls, RETCODE, nlocals, 0); | ||
| 90 | } | ||
| 91 | |||
| 92 | |||
| 93 | int luaK_code (LexState *ls, Instruction i, int delta) { | ||
| 94 | luaK_deltastack(ls, delta); | ||
| 95 | return luaK_primitivecode(ls, i); | ||
| 92 | } | 96 | } |
| 93 | 97 | ||
| 94 | 98 | ||
| @@ -97,7 +101,6 @@ void luaK_fixjump (LexState *ls, int pc, int dest) { | |||
| 97 | Instruction *jmp = &fs->f->code[pc]; | 101 | Instruction *jmp = &fs->f->code[pc]; |
| 98 | /* jump is relative to position following jump instruction */ | 102 | /* jump is relative to position following jump instruction */ |
| 99 | *jmp = SETARG_S(*jmp, dest-(pc+1)); | 103 | *jmp = SETARG_S(*jmp, dest-(pc+1)); |
| 100 | fs->last_pc = pc; | ||
| 101 | } | 104 | } |
| 102 | 105 | ||
| 103 | 106 | ||
| @@ -112,38 +115,8 @@ void luaK_deltastack (LexState *ls, int delta) { | |||
| 112 | } | 115 | } |
| 113 | 116 | ||
| 114 | 117 | ||
| 115 | static int aux_code (LexState *ls, OpCode op, Instruction i, int delta) { | 118 | void luaK_kstr (LexState *ls, int c) { |
| 116 | luaK_deltastack(ls, delta); | 119 | luaK_U(ls, PUSHSTRING, c, 1); |
| 117 | return luaK_code(ls, SET_OPCODE(i, op)); | ||
| 118 | } | ||
| 119 | |||
| 120 | |||
| 121 | int luaK_0 (LexState *ls, OpCode op, int delta) { | ||
| 122 | return aux_code(ls, op, 0, delta); | ||
| 123 | } | ||
| 124 | |||
| 125 | |||
| 126 | int luaK_U (LexState *ls, OpCode op, int u, int delta) { | ||
| 127 | Instruction i = SETARG_U(0, u); | ||
| 128 | return aux_code(ls, op, i, delta); | ||
| 129 | } | ||
| 130 | |||
| 131 | |||
| 132 | int luaK_S (LexState *ls, OpCode op, int s, int delta) { | ||
| 133 | Instruction i = SETARG_S(0, s); | ||
| 134 | return aux_code(ls, op, i, delta); | ||
| 135 | } | ||
| 136 | |||
| 137 | |||
| 138 | int luaK_AB (LexState *ls, OpCode op, int a, int b, int delta) { | ||
| 139 | Instruction i = SETARG_A(0, a); | ||
| 140 | i = SETARG_B(i, b); | ||
| 141 | return aux_code(ls, op, i, delta); | ||
| 142 | } | ||
| 143 | |||
| 144 | |||
| 145 | int luaK_kstr (LexState *ls, int c) { | ||
| 146 | return luaK_U(ls, PUSHSTRING, c, 1); | ||
| 147 | } | 120 | } |
| 148 | 121 | ||
| 149 | 122 | ||
| @@ -166,37 +139,40 @@ static int real_constant (LexState *ls, real r) { | |||
| 166 | } | 139 | } |
| 167 | 140 | ||
| 168 | 141 | ||
| 169 | int luaK_number (LexState *ls, real f) { | 142 | void luaK_number (LexState *ls, real f) { |
| 170 | if (f <= (real)MAXARG_S && (int)f == f) | 143 | if (f <= (real)MAXARG_S && (int)f == f) |
| 171 | return luaK_S(ls, PUSHINT, (int)f, 1); /* f has a short integer value */ | 144 | luaK_S(ls, PUSHINT, (int)f, 1); /* f has a short integer value */ |
| 172 | else | 145 | else |
| 173 | return luaK_U(ls, PUSHNUM, real_constant(ls, f), 1); | 146 | luaK_U(ls, PUSHNUM, real_constant(ls, f), 1); |
| 174 | } | 147 | } |
| 175 | 148 | ||
| 176 | 149 | ||
| 177 | int luaK_adjuststack (LexState *ls, int n) { | 150 | void luaK_adjuststack (LexState *ls, int n) { |
| 178 | if (n > 0) | 151 | if (n > 0) |
| 179 | return luaK_U(ls, POP, n, -n); | 152 | luaK_U(ls, POP, n, -n); |
| 180 | else if (n < 0) | 153 | else if (n < 0) |
| 181 | return luaK_U(ls, PUSHNIL, (-n)-1, -n); | 154 | luaK_U(ls, PUSHNIL, (-n)-1, -n); |
| 182 | else return 0; | ||
| 183 | } | 155 | } |
| 184 | 156 | ||
| 185 | 157 | ||
| 186 | int luaK_iscall (LexState *ls, int pc) { | 158 | int luaK_iscall (LexState *ls, int hasjumps) { |
| 187 | return (GET_OPCODE(ls->fs->f->code[pc]) == CALL); | 159 | if (hasjumps) return 0; /* a call cannot have internal jumps */ |
| 160 | else /* check whether last instruction is a function call */ | ||
| 161 | return (GET_OPCODE(ls->fs->f->code[ls->fs->pc-1]) == CALL); | ||
| 188 | } | 162 | } |
| 189 | 163 | ||
| 190 | 164 | ||
| 191 | void luaK_setcallreturns (LexState *ls, int pc, int nresults) { | 165 | void luaK_setcallreturns (LexState *ls, int hasjumps, int nresults) { |
| 192 | if (luaK_iscall(ls, pc)) { /* expression is a function call? */ | 166 | if (!hasjumps) { /* if `hasjumps' cannot be a function call */ |
| 193 | Instruction *i = &ls->fs->f->code[pc]; | 167 | Instruction *i = &ls->fs->f->code[ls->fs->pc-1]; |
| 194 | int old_nresults = GETARG_B(*i); | 168 | if (GET_OPCODE(*i) == CALL) { /* expression is a function call? */ |
| 195 | if (old_nresults != MULT_RET) | 169 | int old_nresults = GETARG_B(*i); |
| 196 | luaK_deltastack(ls, -old_nresults); /* pop old nresults */ | 170 | if (old_nresults != MULT_RET) |
| 197 | *i = SETARG_B(*i, nresults); /* set nresults */ | 171 | luaK_deltastack(ls, -old_nresults); /* pop old nresults */ |
| 198 | if (nresults != MULT_RET) | 172 | *i = SETARG_B(*i, nresults); /* set nresults */ |
| 199 | luaK_deltastack(ls, nresults); /* push results */ | 173 | if (nresults != MULT_RET) |
| 174 | luaK_deltastack(ls, nresults); /* push results */ | ||
| 175 | } | ||
| 200 | } | 176 | } |
| 201 | } | 177 | } |
| 202 | 178 | ||
| @@ -209,20 +185,21 @@ static void assertglobal (LexState *ls, int index) { | |||
| 209 | void luaK_2stack (LexState *ls, expdesc *var) { | 185 | void luaK_2stack (LexState *ls, expdesc *var) { |
| 210 | switch (var->k) { | 186 | switch (var->k) { |
| 211 | case VLOCAL: | 187 | case VLOCAL: |
| 212 | var->info = luaK_U(ls, PUSHLOCAL, var->info, 1); | 188 | luaK_U(ls, PUSHLOCAL, var->info, 1); |
| 213 | break; | 189 | break; |
| 214 | case VGLOBAL: | 190 | case VGLOBAL: |
| 191 | luaK_U(ls, GETGLOBAL, var->info, 1); | ||
| 215 | assertglobal(ls, var->info); /* make sure that there is a global */ | 192 | assertglobal(ls, var->info); /* make sure that there is a global */ |
| 216 | var->info = luaK_U(ls, GETGLOBAL, var->info, 1); | ||
| 217 | break; | 193 | break; |
| 218 | case VINDEXED: | 194 | case VINDEXED: |
| 219 | var->info = luaK_0(ls, GETTABLE, -1); | 195 | luaK_gettable(ls, var); |
| 220 | break; | 196 | break; |
| 221 | case VEXP: | 197 | case VEXP: |
| 222 | luaK_setcallreturns(ls, var->info, 1); /* call must return 1 value */ | 198 | luaK_setcallreturns(ls, var->info, 1); /* call must return 1 value */ |
| 223 | break; | 199 | return; /* does not change var->info */ |
| 224 | } | 200 | } |
| 225 | var->k = VEXP; | 201 | var->k = VEXP; |
| 202 | var->info = NOJUMPS; | ||
| 226 | } | 203 | } |
| 227 | 204 | ||
| 228 | 205 | ||
| @@ -246,10 +223,9 @@ void luaK_storevar (LexState *ls, const expdesc *var) { | |||
| 246 | 223 | ||
| 247 | void luaK_prefix (LexState *ls, int op, expdesc *v) { | 224 | void luaK_prefix (LexState *ls, int op, expdesc *v) { |
| 248 | luaK_2stack(ls, v); | 225 | luaK_2stack(ls, v); |
| 249 | if (op == '-') | 226 | if (op == '-') luaK_minus(ls, v); |
| 250 | v->info = luaK_0(ls, MINUSOP, 0); | 227 | else luaK_0(ls, NOTOP, 0); |
| 251 | else | 228 | v->info = NOJUMPS; |
| 252 | v->info = luaK_0(ls, NOTOP, 0); | ||
| 253 | } | 229 | } |
| 254 | 230 | ||
| 255 | 231 | ||
| @@ -267,19 +243,20 @@ void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2) { | |||
| 267 | switch (op) { | 243 | switch (op) { |
| 268 | case AND: case OR: | 244 | case AND: case OR: |
| 269 | luaK_fixjump(ls, v1->info, ls->fs->pc); | 245 | luaK_fixjump(ls, v1->info, ls->fs->pc); |
| 270 | break; | 246 | return; /* keep v1->info != NOJUMPS */ |
| 271 | case '+': v1->info = luaK_0(ls, ADDOP, -1); break; | 247 | case '+': luaK_add(ls, v2); break; |
| 272 | case '-': v1->info = luaK_0(ls, SUBOP, -1); break; | 248 | case '-': luaK_sub(ls, v2); break; |
| 273 | case '*': v1->info = luaK_0(ls, MULTOP, -1); break; | 249 | case '*': luaK_0(ls, MULTOP, -1); break; |
| 274 | case '/': v1->info = luaK_0(ls, DIVOP, -1); break; | 250 | case '/': luaK_0(ls, DIVOP, -1); break; |
| 275 | case '^': v1->info = luaK_0(ls, POWOP, -1); break; | 251 | case '^': luaK_0(ls, POWOP, -1); break; |
| 276 | case CONC: v1->info = luaK_0(ls, CONCOP, -1); break; | 252 | case CONC: luaK_0(ls, CONCOP, -1); break; |
| 277 | case EQ: v1->info = luaK_0(ls, EQOP, -1); break; | 253 | case EQ: luaK_0(ls, EQOP, -1); break; |
| 278 | case NE: v1->info = luaK_0(ls, NEQOP, -1); break; | 254 | case NE: luaK_0(ls, NEQOP, -1); break; |
| 279 | case '>': v1->info = luaK_0(ls, GTOP, -1); break; | 255 | case '>': luaK_0(ls, GTOP, -1); break; |
| 280 | case '<': v1->info = luaK_0(ls, LTOP, -1); break; | 256 | case '<': luaK_0(ls, LTOP, -1); break; |
| 281 | case GE: v1->info = luaK_0(ls, GEOP, -1); break; | 257 | case GE: luaK_0(ls, GEOP, -1); break; |
| 282 | case LE: v1->info = luaK_0(ls, LEOP, -1); break; | 258 | case LE: luaK_0(ls, LEOP, -1); break; |
| 283 | } | 259 | } |
| 260 | v1->info = NOJUMPS; | ||
| 284 | } | 261 | } |
| 285 | 262 | ||
