diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-03-17 10:09:46 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-03-17 10:09:46 -0300 |
commit | 2c8e28d75a09fb6de3c3b16a64561a0103866cea (patch) | |
tree | f7adc9c14f45e3602390f74cc432be2fc6efb37d | |
parent | 4fb8e93c36f3a38bd5041650361d820898122532 (diff) | |
download | lua-2c8e28d75a09fb6de3c3b16a64561a0103866cea.tar.gz lua-2c8e28d75a09fb6de3c3b16a64561a0103866cea.tar.bz2 lua-2c8e28d75a09fb6de3c3b16a64561a0103866cea.zip |
small changes
-rw-r--r-- | lcode.c | 182 | ||||
-rw-r--r-- | lcode.h | 12 |
2 files changed, 101 insertions, 93 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 1.12 2000/03/15 20:50:33 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 1.13 2000/03/16 18:03:09 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 | */ |
@@ -22,130 +22,147 @@ void luaK_error (LexState *ls, const char *msg) { | |||
22 | } | 22 | } |
23 | 23 | ||
24 | 24 | ||
25 | int luaK_code (FuncState *fs, Instruction i, int delta) { | ||
26 | luaK_deltastack(fs, delta); | ||
27 | luaM_growvector(fs->L, fs->f->code, fs->pc, 1, Instruction, codeEM, MAX_INT); | ||
28 | fs->f->code[fs->pc] = i; | ||
29 | return fs->pc++; | ||
30 | } | ||
31 | |||
32 | int luaK_0(FuncState *fs, OpCode o, int d) { | ||
33 | return luaK_code(fs, CREATE_0(o), d); | ||
34 | } | ||
35 | |||
36 | int luaK_U(FuncState *fs, OpCode o, int u, int d) { | ||
37 | return luaK_code(fs, CREATE_U(o,u), d); | ||
38 | } | ||
39 | |||
40 | int luaK_S(FuncState *fs, OpCode o, int s, int d) { | ||
41 | return luaK_code(fs, CREATE_S(o,s), d); | ||
42 | } | ||
43 | |||
44 | int luaK_AB(FuncState *fs, OpCode o, int a, int b, int d) { | ||
45 | return luaK_code(fs, CREATE_AB(o,a,b), d); | ||
46 | } | ||
47 | |||
48 | |||
25 | /* | 49 | /* |
26 | ** Returns the address of the previous instruction, for optimizations. | 50 | ** Returns the the previous instruction, for optimizations. |
27 | ** If there is a jump target between this and the current instruction, | 51 | ** If there is a jump target between this and the current instruction, |
28 | ** returns the address of a dummy instruction to avoid wrong optimizations. | 52 | ** returns a dummy instruction to avoid wrong optimizations. |
29 | */ | 53 | */ |
30 | static Instruction *previous_instruction (FuncState *fs) { | 54 | static Instruction previous_instruction (FuncState *fs) { |
31 | if (fs->pc > fs->lasttarget) /* no jumps to current position? */ | 55 | if (fs->pc > fs->lasttarget) /* no jumps to current position? */ |
32 | return &fs->f->code[fs->pc-1]; /* returns previous instruction */ | 56 | return fs->f->code[fs->pc-1]; /* returns previous instruction */ |
33 | else { | 57 | else |
34 | static Instruction dummy = CREATE_0(OP_END); | 58 | return CREATE_0(OP_END); /* no optimizations after an `END' */ |
35 | return &dummy; /* no optimizations after an `END' */ | ||
36 | } | ||
37 | } | 59 | } |
38 | 60 | ||
39 | 61 | ||
40 | static int luaK_primitivecode (FuncState *fs, Instruction i) { | 62 | static Instruction prepare (FuncState *fs, Instruction i, int delta) { |
41 | luaM_growvector(fs->L, fs->f->code, fs->pc, 1, Instruction, codeEM, MAX_INT); | 63 | Instruction previous = previous_instruction(fs); |
42 | fs->f->code[fs->pc] = i; | 64 | luaK_code(fs, i, delta); |
43 | return fs->pc++; | 65 | return previous; |
66 | } | ||
67 | |||
68 | |||
69 | static void setprevious (FuncState *fs, Instruction i) { | ||
70 | fs->pc--; /* remove last instruction */ | ||
71 | fs->f->code[fs->pc-1] = i; /* change previous instruction */ | ||
44 | } | 72 | } |
45 | 73 | ||
46 | 74 | ||
47 | static void luaK_minus (FuncState *fs) { | 75 | static void luaK_minus (FuncState *fs) { |
48 | Instruction *previous = previous_instruction(fs); | 76 | Instruction previous = prepare(fs, CREATE_0(OP_MINUS), 0); |
49 | switch(GET_OPCODE(*previous)) { | 77 | switch(GET_OPCODE(previous)) { |
50 | case OP_PUSHINT: SETARG_S(*previous, -GETARG_S(*previous)); return; | 78 | case OP_PUSHINT: SETARG_S(previous, -GETARG_S(previous)); break; |
51 | case OP_PUSHNUM: SET_OPCODE(*previous, OP_PUSHNEGNUM); return; | 79 | case OP_PUSHNUM: SET_OPCODE(previous, OP_PUSHNEGNUM); break; |
52 | case OP_PUSHNEGNUM: SET_OPCODE(*previous, OP_PUSHNUM); return; | 80 | case OP_PUSHNEGNUM: SET_OPCODE(previous, OP_PUSHNUM); break; |
53 | default: luaK_primitivecode(fs, CREATE_0(OP_MINUS)); | 81 | default: return; |
54 | } | 82 | } |
83 | setprevious(fs, previous); | ||
55 | } | 84 | } |
56 | 85 | ||
57 | 86 | ||
58 | static void luaK_gettable (FuncState *fs) { | 87 | static void luaK_gettable (FuncState *fs) { |
59 | Instruction *previous = previous_instruction(fs); | 88 | Instruction previous = prepare(fs, CREATE_0(OP_GETTABLE), -1); |
60 | luaK_deltastack(fs, -1); | 89 | switch(GET_OPCODE(previous)) { |
61 | switch(GET_OPCODE(*previous)) { | 90 | case OP_PUSHSTRING: SET_OPCODE(previous, OP_GETDOTTED); break; |
62 | case OP_PUSHSTRING: SET_OPCODE(*previous, OP_GETDOTTED); break; | 91 | default: return; |
63 | default: luaK_primitivecode(fs, CREATE_0(OP_GETTABLE)); | ||
64 | } | 92 | } |
93 | setprevious(fs, previous); | ||
65 | } | 94 | } |
66 | 95 | ||
67 | 96 | ||
68 | static void luaK_add (FuncState *fs) { | 97 | static void luaK_add (FuncState *fs) { |
69 | Instruction *previous = previous_instruction(fs); | 98 | Instruction previous = prepare(fs, CREATE_0(OP_ADD), -1); |
70 | luaK_deltastack(fs, -1); | 99 | switch(GET_OPCODE(previous)) { |
71 | switch(GET_OPCODE(*previous)) { | 100 | case OP_PUSHINT: SET_OPCODE(previous, OP_ADDI); break; |
72 | case OP_PUSHINT: SET_OPCODE(*previous, OP_ADDI); break; | 101 | default: return; |
73 | default: luaK_primitivecode(fs, CREATE_0(OP_ADD)); | ||
74 | } | 102 | } |
103 | setprevious(fs, previous); | ||
75 | } | 104 | } |
76 | 105 | ||
77 | 106 | ||
78 | static void luaK_sub (FuncState *fs) { | 107 | static void luaK_sub (FuncState *fs) { |
79 | Instruction *previous = previous_instruction(fs); | 108 | Instruction previous = prepare(fs, CREATE_0(OP_SUB), -1); |
80 | luaK_deltastack(fs, -1); | 109 | switch(GET_OPCODE(previous)) { |
81 | switch(GET_OPCODE(*previous)) { | ||
82 | case OP_PUSHINT: | 110 | case OP_PUSHINT: |
83 | SET_OPCODE(*previous, OP_ADDI); | 111 | SET_OPCODE(previous, OP_ADDI); |
84 | SETARG_S(*previous, -GETARG_S(*previous)); | 112 | SETARG_S(previous, -GETARG_S(previous)); |
85 | break; | 113 | break; |
86 | default: luaK_primitivecode(fs, CREATE_0(OP_SUB)); | 114 | default: return; |
87 | } | 115 | } |
116 | setprevious(fs, previous); | ||
88 | } | 117 | } |
89 | 118 | ||
90 | 119 | ||
91 | static void luaK_conc (FuncState *fs) { | 120 | static void luaK_conc (FuncState *fs) { |
92 | Instruction *previous = previous_instruction(fs); | 121 | Instruction previous = prepare(fs, CREATE_U(OP_CONC, 2), -1); |
93 | luaK_deltastack(fs, -1); | 122 | switch(GET_OPCODE(previous)) { |
94 | switch(GET_OPCODE(*previous)) { | 123 | case OP_CONC: SETARG_U(previous, GETARG_U(previous)+1); break; |
95 | case OP_CONC: SETARG_U(*previous, GETARG_U(*previous)+1); break; | 124 | default: return; |
96 | default: luaK_primitivecode(fs, CREATE_U(OP_CONC, 2)); | ||
97 | } | 125 | } |
126 | setprevious(fs, previous); | ||
98 | } | 127 | } |
99 | 128 | ||
100 | 129 | ||
101 | static void luaK_eq (FuncState *fs) { | 130 | static void luaK_eq (FuncState *fs) { |
102 | Instruction *previous = previous_instruction(fs); | 131 | Instruction previous = prepare(fs, CREATE_S(OP_IFEQJMP, 0), -2); |
103 | if (*previous == CREATE_U(OP_PUSHNIL, 1)) { | 132 | if (previous == CREATE_U(OP_PUSHNIL, 1)) { |
104 | *previous = CREATE_0(OP_NOT); | 133 | setprevious(fs, CREATE_0(OP_NOT)); |
105 | luaK_deltastack(fs, -1); /* undo effect of PUSHNIL */ | 134 | luaK_deltastack(fs, 1); /* undo delta from `prepare' */ |
106 | } | 135 | } |
107 | else | ||
108 | luaK_S(fs, OP_IFEQJMP, 0, -2); | ||
109 | } | 136 | } |
110 | 137 | ||
111 | 138 | ||
112 | static void luaK_neq (FuncState *fs) { | 139 | static void luaK_neq (FuncState *fs) { |
113 | Instruction *previous = previous_instruction(fs); | 140 | Instruction previous = prepare(fs, CREATE_S(OP_IFNEQJMP, 0), -2); |
114 | if (*previous == CREATE_U(OP_PUSHNIL, 1)) { | 141 | if (previous == CREATE_U(OP_PUSHNIL, 1)) { |
115 | fs->pc--; /* remove PUSHNIL */ | 142 | fs->pc -= 2; /* remove PUSHNIL and IFNEQJMP */ |
116 | luaK_deltastack(fs, -1); /* undo effect of PUSHNIL */ | 143 | luaK_deltastack(fs, 1); /* undo delta from `prepare' */ |
117 | luaK_getlabel(fs); /* previous instruction could be a (closed) call */ | ||
118 | } | 144 | } |
119 | else | ||
120 | luaK_S(fs, OP_IFNEQJMP, 0, -2); | ||
121 | } | 145 | } |
122 | 146 | ||
123 | 147 | ||
124 | void luaK_retcode (FuncState *fs, int nlocals, int nexps) { | 148 | void luaK_retcode (FuncState *fs, int nlocals, int nexps) { |
125 | Instruction *previous = previous_instruction(fs); | 149 | Instruction previous = prepare(fs, CREATE_U(OP_RETURN, nlocals), 0); |
126 | if (nexps > 0 && GET_OPCODE(*previous) == OP_CALL) { | 150 | if (nexps > 0 && GET_OPCODE(previous) == OP_CALL) { |
127 | LUA_ASSERT(fs->L, GETARG_B(*previous) == MULT_RET, "call should be open"); | 151 | LUA_ASSERT(fs->L, GETARG_B(previous) == MULT_RET, "call should be open"); |
128 | SET_OPCODE(*previous, OP_TAILCALL); | 152 | SET_OPCODE(previous, OP_TAILCALL); |
129 | SETARG_B(*previous, nlocals); | 153 | SETARG_B(previous, nlocals); |
154 | setprevious(fs, previous); | ||
130 | } | 155 | } |
131 | else | ||
132 | luaK_primitivecode(fs, CREATE_U(OP_RETURN, nlocals)); | ||
133 | } | 156 | } |
134 | 157 | ||
135 | 158 | ||
136 | static void luaK_pushnil (FuncState *fs, int n) { | 159 | static void luaK_pushnil (FuncState *fs, int n) { |
137 | Instruction *previous = previous_instruction(fs); | 160 | Instruction previous = prepare(fs, CREATE_U(OP_PUSHNIL, n), n); |
138 | luaK_deltastack(fs, n); | 161 | switch(GET_OPCODE(previous)) { |
139 | switch(GET_OPCODE(*previous)) { | 162 | case OP_PUSHNIL: SETARG_U(previous, GETARG_U(previous)+n); break; |
140 | case OP_PUSHNIL: SETARG_U(*previous, GETARG_U(*previous)+n); break; | 163 | default: return; |
141 | default: luaK_primitivecode(fs, CREATE_U(OP_PUSHNIL, n)); | ||
142 | } | 164 | } |
143 | } | 165 | setprevious(fs, previous); |
144 | |||
145 | |||
146 | int luaK_code (FuncState *fs, Instruction i, int delta) { | ||
147 | luaK_deltastack(fs, delta); | ||
148 | return luaK_primitivecode(fs, i); | ||
149 | } | 166 | } |
150 | 167 | ||
151 | 168 | ||
@@ -232,21 +249,17 @@ void luaK_adjuststack (FuncState *fs, int n) { | |||
232 | 249 | ||
233 | 250 | ||
234 | int luaK_lastisopen (FuncState *fs) { | 251 | int luaK_lastisopen (FuncState *fs) { |
235 | /* check whether last instruction is an (open) function call */ | 252 | /* check whether last instruction is an open function call */ |
236 | Instruction *i = previous_instruction(fs); | 253 | Instruction i = previous_instruction(fs); |
237 | if (GET_OPCODE(*i) == OP_CALL) { | 254 | if (GET_OPCODE(i) == OP_CALL && GETARG_B(i) == MULT_RET) |
238 | LUA_ASSERT(fs->L, GETARG_B(*i) == MULT_RET, "call should be open"); | ||
239 | return 1; | 255 | return 1; |
240 | } | ||
241 | else return 0; | 256 | else return 0; |
242 | } | 257 | } |
243 | 258 | ||
244 | 259 | ||
245 | void luaK_setcallreturns (FuncState *fs, int nresults) { | 260 | void luaK_setcallreturns (FuncState *fs, int nresults) { |
246 | Instruction *i = previous_instruction(fs); | 261 | if (luaK_lastisopen(fs)) { /* expression is an open function call? */ |
247 | if (GET_OPCODE(*i) == OP_CALL) { /* expression is a function call? */ | 262 | SETARG_B(fs->f->code[fs->pc-1], nresults); /* set number of results */ |
248 | LUA_ASSERT(fs->L, GETARG_B(*i) == MULT_RET, "call should be open"); | ||
249 | SETARG_B(*i, nresults); /* set nresults */ | ||
250 | luaK_deltastack(fs, nresults); /* push results */ | 263 | luaK_deltastack(fs, nresults); /* push results */ |
251 | } | 264 | } |
252 | } | 265 | } |
@@ -323,12 +336,9 @@ static OpCode invertjump (OpCode op) { | |||
323 | 336 | ||
324 | 337 | ||
325 | static void luaK_jump (FuncState *fs, OpCode jump) { | 338 | static void luaK_jump (FuncState *fs, OpCode jump) { |
326 | Instruction *previous = previous_instruction(fs); | 339 | Instruction previous = prepare(fs, CREATE_S(jump, 0), -1); |
327 | luaK_deltastack(fs, -1); | 340 | if (previous == CREATE_0(OP_NOT)) |
328 | if (*previous == CREATE_0(OP_NOT)) | 341 | setprevious(fs, CREATE_S(invertjump(jump), 0)); |
329 | *previous = CREATE_S(invertjump(jump), 0); | ||
330 | else | ||
331 | luaK_primitivecode(fs, CREATE_S(jump, 0)); | ||
332 | } | 342 | } |
333 | 343 | ||
334 | 344 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.h,v 1.7 2000/03/13 20:37:16 roberto Exp roberto $ | 2 | ** $Id: lcode.h,v 1.8 2000/03/15 20:50:33 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 | */ |
@@ -13,13 +13,11 @@ | |||
13 | #include "lparser.h" | 13 | #include "lparser.h" |
14 | 14 | ||
15 | 15 | ||
16 | #define luaK_0(ls,o,d) luaK_code(ls, CREATE_0(o), d) | ||
17 | #define luaK_U(ls,o,u,d) luaK_code(ls, CREATE_U(o,u), d) | ||
18 | #define luaK_S(ls,o,s,d) luaK_code(ls, CREATE_S(o,s), d) | ||
19 | #define luaK_AB(ls,o,a,b,d) luaK_code(ls, CREATE_AB(o,a,b), d) | ||
20 | |||
21 | |||
22 | void luaK_error (LexState *ls, const char *msg); | 16 | void luaK_error (LexState *ls, const char *msg); |
17 | int luaK_0(FuncState *fs, OpCode o, int d); | ||
18 | int luaK_U(FuncState *fs, OpCode o, int u, int d); | ||
19 | int luaK_S(FuncState *fs, OpCode o, int s, int d); | ||
20 | int luaK_AB(FuncState *fs, OpCode o, int a, int b, int d); | ||
23 | int luaK_code (FuncState *fs, Instruction i, int delta); | 21 | int luaK_code (FuncState *fs, Instruction i, int delta); |
24 | void luaK_retcode (FuncState *fs, int nlocals, int nexps); | 22 | void luaK_retcode (FuncState *fs, int nlocals, int nexps); |
25 | void luaK_fixjump (FuncState *fs, int pc, int dest); | 23 | void luaK_fixjump (FuncState *fs, int pc, int dest); |