blob: adf84c0e0228a133d8eccb7d1ed00f1547e028b0 [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
13#define DECODE_UINT do { unum = *ip++; if (unum > 127) { unum = ((unum & 0x3f) << 8) | (*ip++); } } while (0)
14#define DECODE_QSTR do { qstr = *ip++; if (qstr > 127) { qstr = ((qstr & 0x3f) << 8) | (*ip++); } } while (0)
15#define PUSH(val) *--sp = (val)
16#define POP() (*sp++)
17
Damiena3977762013-10-09 23:10:10 +010018// args are in reverse order in array
19py_obj_t py_execute_byte_code(const byte *code, uint len, const py_obj_t *args, uint n_args) {
Damienc9f91972013-10-15 23:46:01 +010020 // careful: be sure to declare volatile any variables read in the exception handler (written is ok, I think)
21
Damiena3977762013-10-09 23:10:10 +010022 const byte *ip = code;
Damien429d7192013-10-04 19:53:11 +010023 py_obj_t stack[10];
24 py_obj_t *sp = &stack[10]; // stack grows down, sp points to top of stack
25 machine_uint_t unum;
26 machine_int_t snum;
27 qstr qstr;
28 py_obj_t obj1, obj2;
29 py_obj_t fast0 = NULL, fast1 = NULL, fast2 = NULL, fastn[4] = {NULL, NULL, NULL, NULL};
Damience89a212013-10-15 22:25:17 +010030 nlr_buf_t nlr;
Damien429d7192013-10-04 19:53:11 +010031
Damienc9f91972013-10-15 23:46:01 +010032 // on the exception stack we store (ip, sp) for each block
33 machine_uint_t exc_stack[8];
34 machine_uint_t *volatile exc_sp = &exc_stack[-1]; // stack grows up, exc_sp points to top of stack
35
Damien429d7192013-10-04 19:53:11 +010036 // init args
37 for (int i = 0; i < n_args; i++) {
38 if (i == 0) {
Damiena3977762013-10-09 23:10:10 +010039 fast0 = args[n_args - 1];
Damien429d7192013-10-04 19:53:11 +010040 } else if (i == 1) {
Damiena3977762013-10-09 23:10:10 +010041 fast1 = args[n_args - 2];
Damien429d7192013-10-04 19:53:11 +010042 } else if (i == 2) {
Damiena3977762013-10-09 23:10:10 +010043 fast2 = args[n_args - 3];
Damien429d7192013-10-04 19:53:11 +010044 } else {
45 assert(i - 3 < 4);
Damiena3977762013-10-09 23:10:10 +010046 fastn[i - 3] = args[n_args - 1 - i];
Damien429d7192013-10-04 19:53:11 +010047 }
48 }
49
Damience89a212013-10-15 22:25:17 +010050 // outer exception handling loop
Damien429d7192013-10-04 19:53:11 +010051 for (;;) {
Damience89a212013-10-15 22:25:17 +010052 if (nlr_push(&nlr) == 0) {
53 // loop to execute byte code
54 for (;;) {
55 int op = *ip++;
56 switch (op) {
57 case PYBC_LOAD_CONST_FALSE:
58 PUSH(py_const_false);
59 break;
Damien429d7192013-10-04 19:53:11 +010060
Damience89a212013-10-15 22:25:17 +010061 case PYBC_LOAD_CONST_NONE:
62 PUSH(py_const_none);
63 break;
Damien429d7192013-10-04 19:53:11 +010064
Damience89a212013-10-15 22:25:17 +010065 case PYBC_LOAD_CONST_TRUE:
66 PUSH(py_const_true);
67 break;
Damien429d7192013-10-04 19:53:11 +010068
Damience89a212013-10-15 22:25:17 +010069 case PYBC_LOAD_CONST_SMALL_INT:
70 snum = ip[0] | (ip[1] << 8);
71 if (snum & 0x8000) {
72 snum |= ~0xffff;
73 }
74 ip += 2;
75 PUSH((py_obj_t)(snum << 1 | 1));
76 break;
77
78 case PYBC_LOAD_CONST_ID:
79 DECODE_QSTR;
80 PUSH(rt_load_const_str(qstr)); // TODO
81 break;
82
83 case PYBC_LOAD_CONST_STRING:
84 DECODE_QSTR;
85 PUSH(rt_load_const_str(qstr));
86 break;
87
88 case PYBC_LOAD_FAST_0:
89 PUSH(fast0);
90 break;
91
92 case PYBC_LOAD_FAST_1:
93 PUSH(fast1);
94 break;
95
96 case PYBC_LOAD_FAST_2:
97 PUSH(fast2);
98 break;
99
100 case PYBC_LOAD_FAST_N:
101 DECODE_UINT;
102 PUSH(fastn[unum - 3]);
103 break;
104
105 case PYBC_LOAD_NAME:
106 DECODE_QSTR;
107 PUSH(rt_load_name(qstr));
108 break;
109
110 case PYBC_LOAD_GLOBAL:
111 DECODE_QSTR;
112 PUSH(rt_load_global(qstr));
113 break;
114
115 case PYBC_LOAD_ATTR:
116 DECODE_QSTR;
117 *sp = rt_load_attr(*sp, qstr);
118 break;
119
120 case PYBC_LOAD_METHOD:
121 DECODE_QSTR;
122 sp -= 1;
123 rt_load_method(sp[1], qstr, sp);
124 break;
125
126 case PYBC_LOAD_BUILD_CLASS:
127 PUSH(rt_load_build_class());
128 break;
129
130 case PYBC_STORE_FAST_0:
131 fast0 = POP();
132 break;
133
134 case PYBC_STORE_FAST_1:
135 fast1 = POP();
136 break;
137
138 case PYBC_STORE_FAST_2:
139 fast2 = POP();
140 break;
141
142 case PYBC_STORE_FAST_N:
143 DECODE_UINT;
144 fastn[unum - 3] = POP();
145 break;
146
147 case PYBC_STORE_NAME:
148 DECODE_QSTR;
149 rt_store_name(qstr, POP());
150 break;
151
152 case PYBC_STORE_ATTR:
153 DECODE_QSTR;
154 rt_store_attr(sp[0], qstr, sp[1]);
155 sp += 2;
156 break;
157
158 case PYBC_STORE_SUBSCR:
159 rt_store_subscr(sp[1], sp[0], sp[2]);
160 sp += 3;
161 break;
162
163 case PYBC_DUP_TOP:
164 obj1 = *sp;
165 PUSH(obj1);
166 break;
167
168 case PYBC_DUP_TOP_TWO:
169 sp -= 2;
170 sp[0] = sp[2];
171 sp[1] = sp[3];
172 break;
173
174 case PYBC_POP_TOP:
175 ++sp;
176 break;
177
178 case PYBC_ROT_THREE:
179 obj1 = sp[0];
180 sp[0] = sp[1];
181 sp[1] = sp[2];
182 sp[2] = obj1;
183 break;
184
185 case PYBC_JUMP:
186 DECODE_UINT;
187 ip = code + unum;
188 break;
189
190 case PYBC_POP_JUMP_IF_TRUE:
191 DECODE_UINT;
192 if (rt_is_true(POP())) {
193 ip = code + unum;
194 }
195 break;
196
197 case PYBC_POP_JUMP_IF_FALSE:
198 DECODE_UINT;
199 if (!rt_is_true(POP())) {
200 ip = code + unum;
201 }
202 break;
203
204 /* we are trying to get away without using this opcode
205 case PYBC_SETUP_LOOP:
206 DECODE_UINT;
207 // push_block(PYBC_SETUP_LOOP, code + unum, sp)
208 break;
209 */
210
211 case PYBC_SETUP_EXCEPT:
Damienc9f91972013-10-15 23:46:01 +0100212 DECODE_UINT;
213 *++exc_sp = (machine_uint_t)code + unum;
214 *++exc_sp = (machine_uint_t)sp;
Damience89a212013-10-15 22:25:17 +0100215 break;
216
217 case PYBC_END_FINALLY:
218 // not implemented
219 // if TOS is an exception, reraises the exception (3 values on TOS)
220 // if TOS is an integer, does something else
221 // if TOS is None, just pops it and continues
222 // else error
223 assert(0);
224 break;
225
226 case PYBC_GET_ITER:
227 *sp = rt_getiter(*sp);
228 break;
229
230 case PYBC_FOR_ITER:
231 DECODE_UINT; // the jump offset if iteration finishes
232 obj1 = rt_iternext(*sp);
233 if (obj1 == py_const_stop_iteration) {
234 ++sp; // pop the exhausted iterator
235 ip = code + unum; // jump to after for-block
236 } else {
237 PUSH(obj1); // push the next iteration value
238 }
239 break;
240
241 case PYBC_POP_BLOCK:
242 // pops block and restores the stack
243 assert(0);
244 break;
245
246 case PYBC_POP_EXCEPT:
Damienc9f91972013-10-15 23:46:01 +0100247 // TODO need to work out how blocks work etc
Damience89a212013-10-15 22:25:17 +0100248 // 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 +0100249 assert(exc_sp >= &exc_stack[0]);
250 //sp = (py_obj_t*)(*exc_sp--);
251 //exc_sp--; // discard ip
252 exc_sp -= 2;
253 //sp += 3; // pop 3 exception values
254 assert(sp <= &stack[10]);
Damience89a212013-10-15 22:25:17 +0100255 break;
256
257 case PYBC_BINARY_OP:
258 unum = *ip++;
259 obj2 = POP();
260 obj1 = *sp;
261 *sp = rt_binary_op(unum, obj1, obj2);
262 break;
263
264 case PYBC_COMPARE_OP:
265 unum = *ip++;
266 obj2 = POP();
267 obj1 = *sp;
268 *sp = rt_compare_op(unum, obj1, obj2);
269 break;
270
271 case PYBC_BUILD_LIST:
272 DECODE_UINT;
273 obj1 = rt_build_list(unum, sp);
274 sp += unum - 1;
275 *sp = obj1;
276 break;
277
278 case PYBC_BUILD_MAP:
279 DECODE_UINT;
280 PUSH(rt_build_map(unum));
281 break;
282
283 case PYBC_STORE_MAP:
284 sp += 2;
285 rt_store_map(sp[0], sp[-2], sp[-1]);
286 break;
287
288 case PYBC_BUILD_SET:
289 DECODE_UINT;
290 obj1 = rt_build_set(unum, sp);
291 sp += unum - 1;
292 *sp = obj1;
293 break;
294
295 case PYBC_MAKE_FUNCTION:
296 DECODE_UINT;
297 PUSH(rt_make_function_from_id(unum));
298 break;
299
300 case PYBC_CALL_FUNCTION:
301 DECODE_UINT;
302 assert((unum & 0xff00) == 0); // n_keyword
303 unum &= 0xff; // n_positional
304 sp += unum;
305 *sp = rt_call_function_n(*sp, unum, sp - unum);
306 break;
307
308 case PYBC_CALL_METHOD:
309 DECODE_UINT;
310 assert((unum & 0xff00) == 0); // n_keyword
311 unum &= 0xff;
312 obj1 = rt_call_method_n(unum, sp);
313 sp += unum + 1;
314 *sp = obj1;
315 break;
316
317 case PYBC_RETURN_VALUE:
318 nlr_pop();
Damienc9f91972013-10-15 23:46:01 +0100319 assert(sp == &stack[9]);
320 assert(exc_sp == &exc_stack[-1]);
Damience89a212013-10-15 22:25:17 +0100321 return *sp;
322
323 default:
324 printf("code %p, offset %u, byte code 0x%02x not implemented\n", code, (uint)(ip - code), op);
325 assert(0);
326 nlr_pop();
327 return py_const_none;
Damien429d7192013-10-04 19:53:11 +0100328 }
Damience89a212013-10-15 22:25:17 +0100329 }
Damien429d7192013-10-04 19:53:11 +0100330
Damience89a212013-10-15 22:25:17 +0100331 } else {
332 // exception occurred
Damien429d7192013-10-04 19:53:11 +0100333
Damienc9f91972013-10-15 23:46:01 +0100334 if (exc_sp >= &exc_stack[0]) {
Damience89a212013-10-15 22:25:17 +0100335 // catch exception and pass to byte code
Damienc9f91972013-10-15 23:46:01 +0100336 sp = (py_obj_t*)(exc_sp[0]);
337 ip = (const byte*)(exc_sp[-1]);
338 // push(traceback, exc-val, exc-type)
339 PUSH(py_const_none);
340 PUSH(nlr.ret_val);
341 PUSH(py_const_none);
Damience89a212013-10-15 22:25:17 +0100342 } else {
343 // re-raise exception
344 nlr_jump(nlr.ret_val);
345 }
Damien429d7192013-10-04 19:53:11 +0100346 }
347 }
348}