blob: a4fbf2f16c610b75f452b9acb51e9e31423deabe [file] [log] [blame]
Damien429d7192013-10-04 19:53:11 +01001#include <stdint.h>
2#include <stdlib.h>
3#include <stdio.h>
4#include <string.h>
5#include <assert.h>
6
Damience89a212013-10-15 22:25:17 +01007#include "nlr.h"
Damien429d7192013-10-04 19:53:11 +01008#include "misc.h"
Damienc025ebb2013-10-12 14:30:21 +01009#include "mpyconfig.h"
Damien429d7192013-10-04 19:53:11 +010010#include "runtime.h"
Damieneb19efb2013-10-10 22:06:54 +010011#include "bc.h"
Damien429d7192013-10-04 19:53:11 +010012
Damienbd254452013-10-16 20:39:12 +010013// (value) stack grows down (to be compatible with native code when passing pointers to the stack), top element is pointed to
14// exception stack grows up, top element is pointed to
15
Damien429d7192013-10-04 19:53:11 +010016#define DECODE_UINT do { unum = *ip++; if (unum > 127) { unum = ((unum & 0x3f) << 8) | (*ip++); } } while (0)
17#define DECODE_QSTR do { qstr = *ip++; if (qstr > 127) { qstr = ((qstr & 0x3f) << 8) | (*ip++); } } while (0)
18#define PUSH(val) *--sp = (val)
19#define POP() (*sp++)
20
Damiena3977762013-10-09 23:10:10 +010021// args are in reverse order in array
Damienbd254452013-10-16 20:39:12 +010022py_obj_t py_execute_byte_code(const byte *code, const py_obj_t *args, uint n_args) {
23 py_obj_t state[18]; // TODO allocate properly
24 // init args
25 for (int i = 0; i < n_args; i++) {
26 assert(i < 8);
27 state[i] = args[n_args - 1 - i];
28 }
29 py_obj_t *sp = &state[18];
30 const byte *ip = code;
31 if (py_execute_byte_code_2(code, &ip, &state[0], &sp)) {
32 // it shouldn't yield
33 assert(0);
34 }
35 assert(sp == &state[17]);
36 return *sp;
37}
38
39// fastn has items in normal order
40// sp points to top of stack which grows down
41bool py_execute_byte_code_2(const byte *code, const byte **ip_in_out, py_obj_t *fastn, py_obj_t **sp_in_out) {
Damienc9f91972013-10-15 23:46:01 +010042 // careful: be sure to declare volatile any variables read in the exception handler (written is ok, I think)
43
Damienbd254452013-10-16 20:39:12 +010044 const byte *ip = *ip_in_out;
45 py_obj_t *sp = *sp_in_out;
Damien429d7192013-10-04 19:53:11 +010046 machine_uint_t unum;
47 machine_int_t snum;
48 qstr qstr;
49 py_obj_t obj1, obj2;
Damienbd254452013-10-16 20:39:12 +010050 py_obj_t fast0 = fastn[0], fast1 = fastn[1], fast2 = fastn[2];
Damience89a212013-10-15 22:25:17 +010051 nlr_buf_t nlr;
Damien429d7192013-10-04 19:53:11 +010052
Damienc9f91972013-10-15 23:46:01 +010053 // on the exception stack we store (ip, sp) for each block
54 machine_uint_t exc_stack[8];
55 machine_uint_t *volatile exc_sp = &exc_stack[-1]; // stack grows up, exc_sp points to top of stack
56
Damience89a212013-10-15 22:25:17 +010057 // outer exception handling loop
Damien429d7192013-10-04 19:53:11 +010058 for (;;) {
Damience89a212013-10-15 22:25:17 +010059 if (nlr_push(&nlr) == 0) {
60 // loop to execute byte code
61 for (;;) {
62 int op = *ip++;
63 switch (op) {
64 case PYBC_LOAD_CONST_FALSE:
65 PUSH(py_const_false);
66 break;
Damien429d7192013-10-04 19:53:11 +010067
Damience89a212013-10-15 22:25:17 +010068 case PYBC_LOAD_CONST_NONE:
69 PUSH(py_const_none);
70 break;
Damien429d7192013-10-04 19:53:11 +010071
Damience89a212013-10-15 22:25:17 +010072 case PYBC_LOAD_CONST_TRUE:
73 PUSH(py_const_true);
74 break;
Damien429d7192013-10-04 19:53:11 +010075
Damience89a212013-10-15 22:25:17 +010076 case PYBC_LOAD_CONST_SMALL_INT:
77 snum = ip[0] | (ip[1] << 8);
78 if (snum & 0x8000) {
79 snum |= ~0xffff;
80 }
81 ip += 2;
82 PUSH((py_obj_t)(snum << 1 | 1));
83 break;
84
85 case PYBC_LOAD_CONST_ID:
86 DECODE_QSTR;
87 PUSH(rt_load_const_str(qstr)); // TODO
88 break;
89
90 case PYBC_LOAD_CONST_STRING:
91 DECODE_QSTR;
92 PUSH(rt_load_const_str(qstr));
93 break;
94
95 case PYBC_LOAD_FAST_0:
96 PUSH(fast0);
97 break;
98
99 case PYBC_LOAD_FAST_1:
100 PUSH(fast1);
101 break;
102
103 case PYBC_LOAD_FAST_2:
104 PUSH(fast2);
105 break;
106
107 case PYBC_LOAD_FAST_N:
108 DECODE_UINT;
Damienbd254452013-10-16 20:39:12 +0100109 PUSH(fastn[unum]);
Damience89a212013-10-15 22:25:17 +0100110 break;
111
112 case PYBC_LOAD_NAME:
113 DECODE_QSTR;
114 PUSH(rt_load_name(qstr));
115 break;
116
117 case PYBC_LOAD_GLOBAL:
118 DECODE_QSTR;
119 PUSH(rt_load_global(qstr));
120 break;
121
122 case PYBC_LOAD_ATTR:
123 DECODE_QSTR;
124 *sp = rt_load_attr(*sp, qstr);
125 break;
126
127 case PYBC_LOAD_METHOD:
128 DECODE_QSTR;
129 sp -= 1;
130 rt_load_method(sp[1], qstr, sp);
131 break;
132
133 case PYBC_LOAD_BUILD_CLASS:
134 PUSH(rt_load_build_class());
135 break;
136
137 case PYBC_STORE_FAST_0:
138 fast0 = POP();
139 break;
140
141 case PYBC_STORE_FAST_1:
142 fast1 = POP();
143 break;
144
145 case PYBC_STORE_FAST_2:
146 fast2 = POP();
147 break;
148
149 case PYBC_STORE_FAST_N:
150 DECODE_UINT;
Damienbd254452013-10-16 20:39:12 +0100151 fastn[unum] = POP();
Damience89a212013-10-15 22:25:17 +0100152 break;
153
154 case PYBC_STORE_NAME:
155 DECODE_QSTR;
156 rt_store_name(qstr, POP());
157 break;
158
159 case PYBC_STORE_ATTR:
160 DECODE_QSTR;
161 rt_store_attr(sp[0], qstr, sp[1]);
162 sp += 2;
163 break;
164
165 case PYBC_STORE_SUBSCR:
166 rt_store_subscr(sp[1], sp[0], sp[2]);
167 sp += 3;
168 break;
169
170 case PYBC_DUP_TOP:
171 obj1 = *sp;
172 PUSH(obj1);
173 break;
174
175 case PYBC_DUP_TOP_TWO:
176 sp -= 2;
177 sp[0] = sp[2];
178 sp[1] = sp[3];
179 break;
180
181 case PYBC_POP_TOP:
182 ++sp;
183 break;
184
185 case PYBC_ROT_THREE:
186 obj1 = sp[0];
187 sp[0] = sp[1];
188 sp[1] = sp[2];
189 sp[2] = obj1;
190 break;
191
192 case PYBC_JUMP:
193 DECODE_UINT;
194 ip = code + unum;
195 break;
196
197 case PYBC_POP_JUMP_IF_TRUE:
198 DECODE_UINT;
199 if (rt_is_true(POP())) {
200 ip = code + unum;
201 }
202 break;
203
204 case PYBC_POP_JUMP_IF_FALSE:
205 DECODE_UINT;
206 if (!rt_is_true(POP())) {
207 ip = code + unum;
208 }
209 break;
210
211 /* we are trying to get away without using this opcode
212 case PYBC_SETUP_LOOP:
213 DECODE_UINT;
214 // push_block(PYBC_SETUP_LOOP, code + unum, sp)
215 break;
216 */
217
218 case PYBC_SETUP_EXCEPT:
Damienc9f91972013-10-15 23:46:01 +0100219 DECODE_UINT;
220 *++exc_sp = (machine_uint_t)code + unum;
221 *++exc_sp = (machine_uint_t)sp;
Damience89a212013-10-15 22:25:17 +0100222 break;
223
224 case PYBC_END_FINALLY:
225 // not implemented
226 // if TOS is an exception, reraises the exception (3 values on TOS)
227 // if TOS is an integer, does something else
228 // if TOS is None, just pops it and continues
229 // else error
230 assert(0);
231 break;
232
233 case PYBC_GET_ITER:
234 *sp = rt_getiter(*sp);
235 break;
236
237 case PYBC_FOR_ITER:
238 DECODE_UINT; // the jump offset if iteration finishes
239 obj1 = rt_iternext(*sp);
240 if (obj1 == py_const_stop_iteration) {
241 ++sp; // pop the exhausted iterator
242 ip = code + unum; // jump to after for-block
243 } else {
244 PUSH(obj1); // push the next iteration value
245 }
246 break;
247
248 case PYBC_POP_BLOCK:
249 // pops block and restores the stack
250 assert(0);
251 break;
252
253 case PYBC_POP_EXCEPT:
Damienc9f91972013-10-15 23:46:01 +0100254 // TODO need to work out how blocks work etc
Damience89a212013-10-15 22:25:17 +0100255 // pops block, checks it's an exception block, and restores the stack, saving the 3 exception values to local threadstate
Damienc9f91972013-10-15 23:46:01 +0100256 assert(exc_sp >= &exc_stack[0]);
257 //sp = (py_obj_t*)(*exc_sp--);
258 //exc_sp--; // discard ip
259 exc_sp -= 2;
260 //sp += 3; // pop 3 exception values
Damience89a212013-10-15 22:25:17 +0100261 break;
262
263 case PYBC_BINARY_OP:
264 unum = *ip++;
265 obj2 = POP();
266 obj1 = *sp;
267 *sp = rt_binary_op(unum, obj1, obj2);
268 break;
269
270 case PYBC_COMPARE_OP:
271 unum = *ip++;
272 obj2 = POP();
273 obj1 = *sp;
274 *sp = rt_compare_op(unum, obj1, obj2);
275 break;
276
Damienc226dca2013-10-16 16:12:52 +0100277 case PYBC_BUILD_TUPLE:
278 DECODE_UINT;
279 obj1 = rt_build_tuple(unum, sp);
280 sp += unum - 1;
281 *sp = obj1;
282 break;
283
Damience89a212013-10-15 22:25:17 +0100284 case PYBC_BUILD_LIST:
285 DECODE_UINT;
286 obj1 = rt_build_list(unum, sp);
287 sp += unum - 1;
288 *sp = obj1;
289 break;
290
Damienc226dca2013-10-16 16:12:52 +0100291 case PYBC_LIST_APPEND:
292 DECODE_UINT;
293 // I think it's guaranteed by the compiler that sp[unum] is a list
294 rt_list_append(sp[unum], sp[0]);
295 sp++;
296 break;
297
Damience89a212013-10-15 22:25:17 +0100298 case PYBC_BUILD_MAP:
299 DECODE_UINT;
300 PUSH(rt_build_map(unum));
301 break;
302
303 case PYBC_STORE_MAP:
304 sp += 2;
305 rt_store_map(sp[0], sp[-2], sp[-1]);
306 break;
307
308 case PYBC_BUILD_SET:
309 DECODE_UINT;
310 obj1 = rt_build_set(unum, sp);
311 sp += unum - 1;
312 *sp = obj1;
313 break;
314
315 case PYBC_MAKE_FUNCTION:
316 DECODE_UINT;
317 PUSH(rt_make_function_from_id(unum));
318 break;
319
320 case PYBC_CALL_FUNCTION:
321 DECODE_UINT;
322 assert((unum & 0xff00) == 0); // n_keyword
323 unum &= 0xff; // n_positional
324 sp += unum;
325 *sp = rt_call_function_n(*sp, unum, sp - unum);
326 break;
327
328 case PYBC_CALL_METHOD:
329 DECODE_UINT;
330 assert((unum & 0xff00) == 0); // n_keyword
331 unum &= 0xff;
332 obj1 = rt_call_method_n(unum, sp);
333 sp += unum + 1;
334 *sp = obj1;
335 break;
336
337 case PYBC_RETURN_VALUE:
338 nlr_pop();
Damienbd254452013-10-16 20:39:12 +0100339 *sp_in_out = sp;
Damienc9f91972013-10-15 23:46:01 +0100340 assert(exc_sp == &exc_stack[-1]);
Damienbd254452013-10-16 20:39:12 +0100341 return false;
342
343 case PYBC_YIELD_VALUE:
344 nlr_pop();
345 *ip_in_out = ip;
346 fastn[0] = fast0;
347 fastn[1] = fast1;
348 fastn[2] = fast2;
349 *sp_in_out = sp;
350 return true;
Damience89a212013-10-15 22:25:17 +0100351
352 default:
353 printf("code %p, offset %u, byte code 0x%02x not implemented\n", code, (uint)(ip - code), op);
354 assert(0);
355 nlr_pop();
Damienbd254452013-10-16 20:39:12 +0100356 return false;
Damien429d7192013-10-04 19:53:11 +0100357 }
Damience89a212013-10-15 22:25:17 +0100358 }
Damien429d7192013-10-04 19:53:11 +0100359
Damience89a212013-10-15 22:25:17 +0100360 } else {
361 // exception occurred
Damien429d7192013-10-04 19:53:11 +0100362
Damienc9f91972013-10-15 23:46:01 +0100363 if (exc_sp >= &exc_stack[0]) {
Damience89a212013-10-15 22:25:17 +0100364 // catch exception and pass to byte code
Damienc9f91972013-10-15 23:46:01 +0100365 sp = (py_obj_t*)(exc_sp[0]);
366 ip = (const byte*)(exc_sp[-1]);
367 // push(traceback, exc-val, exc-type)
368 PUSH(py_const_none);
369 PUSH(nlr.ret_val);
370 PUSH(py_const_none);
Damience89a212013-10-15 22:25:17 +0100371 } else {
372 // re-raise exception
Damienbd254452013-10-16 20:39:12 +0100373 // TODO what to do if this is a generator??
Damience89a212013-10-15 22:25:17 +0100374 nlr_jump(nlr.ret_val);
375 }
Damien429d7192013-10-04 19:53:11 +0100376 }
377 }
378}