blob: 05754cfabf65d6b93e992c630414becbc81e72e9 [file] [log] [blame]
Damien George04b91472014-05-03 23:27:38 +01001/*
Alexander Steffen55f33242017-06-30 09:22:17 +02002 * This file is part of the MicroPython project, http://micropython.org/
Damien George04b91472014-05-03 23:27:38 +01003 *
4 * The MIT License (MIT)
5 *
Damien George8e7745e2019-08-22 14:55:16 +10006 * Copyright (c) 2013-2019 Damien P. George
Damien George04b91472014-05-03 23:27:38 +01007 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 */
26
xbeefe34222014-03-16 00:14:26 -070027#include <stdbool.h>
Damien429d7192013-10-04 19:53:11 +010028#include <stdint.h>
29#include <stdio.h>
30#include <string.h>
Damien George538c3c02022-03-16 09:37:58 +110031#include <unistd.h>
Damien429d7192013-10-04 19:53:11 +010032#include <assert.h>
33
Damien Georgeb4b10fd2015-01-01 23:30:53 +000034#include "py/mpstate.h"
Damien Georgee3de7232022-03-31 23:59:10 +110035#include "py/smallint.h"
Damien George51dfcb42015-01-01 20:27:54 +000036#include "py/emit.h"
37#include "py/bc0.h"
Damien429d7192013-10-04 19:53:11 +010038
Damien Georgedd5353a2015-12-18 12:35:44 +000039#if MICROPY_ENABLE_COMPILER
40
Damien Georgef2040bf2021-10-22 22:22:47 +110041#define DUMMY_DATA_SIZE (MP_ENCODE_UINT_MAX_BYTES)
Damien George95977712014-05-10 18:07:08 +010042
Damien415eb6f2013-10-05 12:19:06 +010043struct _emit_t {
Damien George999cedb2015-11-27 17:01:44 +000044 // Accessed as mp_obj_t, so must be aligned as such, and we rely on the
45 // memory allocator returning a suitably aligned pointer.
46 // Should work for cases when mp_obj_t is 64-bit on a 32-bit machine.
47 byte dummy_data[DUMMY_DATA_SIZE];
48
Damien George0fb80c32014-05-10 18:16:21 +010049 pass_kind_t pass : 8;
Damien George0fb80c32014-05-10 18:16:21 +010050
Damien Georgea5063352022-06-17 23:14:32 +100051 // Set to true if the code generator should suppress emitted code due to it
52 // being dead code. This can happen when opcodes immediately follow an
53 // unconditional flow control (eg jump or raise).
54 bool suppress;
55
Damien429d7192013-10-04 19:53:11 +010056 int stack_size;
Damien429d7192013-10-04 19:53:11 +010057
Damien Georgef2040bf2021-10-22 22:22:47 +110058 mp_emit_common_t *emit_common;
Damien429d7192013-10-04 19:53:11 +010059 scope_t *scope;
60
Damien George7ff996c2014-09-08 23:05:16 +010061 mp_uint_t last_source_line_offset;
62 mp_uint_t last_source_line;
Damien George08335002014-01-18 23:24:36 +000063
Damien George538c3c02022-03-16 09:37:58 +110064 size_t max_num_labels;
65 size_t *label_offsets;
Damien429d7192013-10-04 19:53:11 +010066
Damien George999cedb2015-11-27 17:01:44 +000067 size_t code_info_offset;
68 size_t code_info_size;
69 size_t bytecode_offset;
70 size_t bytecode_size;
Damien George08335002014-01-18 23:24:36 +000071 byte *code_base; // stores both byte code and code info
Damien Georgeacd2c5c2022-03-18 13:18:59 +110072 bool overflow;
Damien Georgec8e9c0d2015-11-02 17:27:18 +000073
Damien Georgec8c0fd42019-09-25 15:45:47 +100074 size_t n_info;
75 size_t n_cell;
Damien429d7192013-10-04 19:53:11 +010076};
77
Damien Georgef2040bf2021-10-22 22:22:47 +110078emit_t *emit_bc_new(mp_emit_common_t *emit_common) {
Damien George08335002014-01-18 23:24:36 +000079 emit_t *emit = m_new0(emit_t, 1);
Damien Georgef2040bf2021-10-22 22:22:47 +110080 emit->emit_common = emit_common;
Damien Georgea210c772015-03-26 15:49:53 +000081 return emit;
82}
83
Damien George4dea9222015-04-09 15:29:54 +000084void emit_bc_set_max_num_labels(emit_t *emit, mp_uint_t max_num_labels) {
Damien6cdd3af2013-10-05 18:08:26 +010085 emit->max_num_labels = max_num_labels;
Damien George538c3c02022-03-16 09:37:58 +110086 emit->label_offsets = m_new(size_t, emit->max_num_labels);
Damien6cdd3af2013-10-05 18:08:26 +010087}
Damien4b03e772013-10-05 14:17:09 +010088
Damien George41d02b62014-01-24 22:42:28 +000089void emit_bc_free(emit_t *emit) {
Damien George538c3c02022-03-16 09:37:58 +110090 m_del(size_t, emit->label_offsets, emit->max_num_labels);
Paul Sokolovskyf46d87a2014-01-24 16:20:11 +020091 m_del_obj(emit_t, emit);
92}
93
Damien George08335002014-01-18 23:24:36 +000094// all functions must go through this one to emit code info
Angus Grattondecf8e62024-02-27 15:32:29 +110095static uint8_t *emit_get_cur_to_write_code_info(void *emit_in, size_t num_bytes_to_write) {
Damien Georgef2040bf2021-10-22 22:22:47 +110096 emit_t *emit = emit_in;
Damien George36db6bc2014-05-07 17:24:22 +010097 if (emit->pass < MP_PASS_EMIT) {
Damien George08335002014-01-18 23:24:36 +000098 emit->code_info_offset += num_bytes_to_write;
Damien429d7192013-10-04 19:53:11 +010099 return emit->dummy_data;
100 } else {
Damien George08335002014-01-18 23:24:36 +0000101 assert(emit->code_info_offset + num_bytes_to_write <= emit->code_info_size);
102 byte *c = emit->code_base + emit->code_info_offset;
103 emit->code_info_offset += num_bytes_to_write;
Damien429d7192013-10-04 19:53:11 +0100104 return c;
105 }
106}
107
Angus Grattondecf8e62024-02-27 15:32:29 +1100108static void emit_write_code_info_byte(emit_t *emit, byte val) {
Damien George9b7f5832015-03-18 17:47:47 +0000109 *emit_get_cur_to_write_code_info(emit, 1) = val;
110}
111
Angus Grattondecf8e62024-02-27 15:32:29 +1100112static void emit_write_code_info_qstr(emit_t *emit, qstr qst) {
Damien Georgef2040bf2021-10-22 22:22:47 +1100113 mp_encode_uint(emit, emit_get_cur_to_write_code_info, mp_emit_common_use_qstr(emit->emit_common, qst));
Damien George08335002014-01-18 23:24:36 +0000114}
115
Damien George73496fb2014-04-13 14:51:56 +0100116#if MICROPY_ENABLE_SOURCE_LINE
Angus Grattondecf8e62024-02-27 15:32:29 +1100117static void emit_write_code_info_bytes_lines(emit_t *emit, mp_uint_t bytes_to_skip, mp_uint_t lines_to_skip) {
Damien George73496fb2014-04-13 14:51:56 +0100118 assert(bytes_to_skip > 0 || lines_to_skip > 0);
119 while (bytes_to_skip > 0 || lines_to_skip > 0) {
Damien George4747bec2014-07-31 16:12:01 +0000120 mp_uint_t b, l;
Damien Georgecc2dbdd2017-02-10 11:58:10 +1100121 if (lines_to_skip <= 6 || bytes_to_skip > 0xf) {
Damien George4747bec2014-07-31 16:12:01 +0000122 // use 0b0LLBBBBB encoding
123 b = MIN(bytes_to_skip, 0x1f);
Damien Georgecc2dbdd2017-02-10 11:58:10 +1100124 if (b < bytes_to_skip) {
125 // we can't skip any lines until we skip all the bytes
126 l = 0;
127 } else {
128 l = MIN(lines_to_skip, 0x3);
129 }
Damien George4747bec2014-07-31 16:12:01 +0000130 *emit_get_cur_to_write_code_info(emit, 1) = b | (l << 5);
131 } else {
132 // use 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)
133 b = MIN(bytes_to_skip, 0xf);
134 l = MIN(lines_to_skip, 0x7ff);
135 byte *ci = emit_get_cur_to_write_code_info(emit, 2);
136 ci[0] = 0x80 | b | ((l >> 4) & 0x70);
137 ci[1] = l;
138 }
Damien George73496fb2014-04-13 14:51:56 +0100139 bytes_to_skip -= b;
140 lines_to_skip -= l;
Damien George28eb5772014-01-25 11:43:20 +0000141 }
Damien George08335002014-01-18 23:24:36 +0000142}
Damien George73496fb2014-04-13 14:51:56 +0100143#endif
Damien George08335002014-01-18 23:24:36 +0000144
145// all functions must go through this one to emit byte code
Angus Grattondecf8e62024-02-27 15:32:29 +1100146static uint8_t *emit_get_cur_to_write_bytecode(void *emit_in, size_t num_bytes_to_write) {
Damien Georgef2040bf2021-10-22 22:22:47 +1100147 emit_t *emit = emit_in;
Damien Georgea5063352022-06-17 23:14:32 +1000148 if (emit->suppress) {
149 return emit->dummy_data;
150 }
Damien George36db6bc2014-05-07 17:24:22 +0100151 if (emit->pass < MP_PASS_EMIT) {
Damien George3417bc22014-05-10 10:36:38 +0100152 emit->bytecode_offset += num_bytes_to_write;
Damien George08335002014-01-18 23:24:36 +0000153 return emit->dummy_data;
154 } else {
Damien George3417bc22014-05-10 10:36:38 +0100155 assert(emit->bytecode_offset + num_bytes_to_write <= emit->bytecode_size);
156 byte *c = emit->code_base + emit->code_info_size + emit->bytecode_offset;
157 emit->bytecode_offset += num_bytes_to_write;
Damien George08335002014-01-18 23:24:36 +0000158 return c;
159 }
160}
161
Angus Grattondecf8e62024-02-27 15:32:29 +1100162static void emit_write_bytecode_raw_byte(emit_t *emit, byte b1) {
Damien George4dea9222015-04-09 15:29:54 +0000163 byte *c = emit_get_cur_to_write_bytecode(emit, 1);
Damien429d7192013-10-04 19:53:11 +0100164 c[0] = b1;
165}
166
Angus Grattondecf8e62024-02-27 15:32:29 +1100167static void emit_write_bytecode_byte(emit_t *emit, int stack_adj, byte b1) {
Damien George8e7745e2019-08-22 14:55:16 +1000168 mp_emit_bc_adjust_stack_size(emit, stack_adj);
169 byte *c = emit_get_cur_to_write_bytecode(emit, 1);
170 c[0] = b1;
171}
172
Damien Georgef2040bf2021-10-22 22:22:47 +1100173// Similar to mp_encode_uint(), just some extra handling to encode sign
Angus Grattondecf8e62024-02-27 15:32:29 +1100174static void emit_write_bytecode_byte_int(emit_t *emit, int stack_adj, byte b1, mp_int_t num) {
Damien George8e7745e2019-08-22 14:55:16 +1000175 emit_write_bytecode_byte(emit, stack_adj, b1);
Paul Sokolovsky047cd402014-02-19 15:47:59 +0200176
177 // We store each 7 bits in a separate byte, and that's how many bytes needed
Damien Georgef2040bf2021-10-22 22:22:47 +1100178 byte buf[MP_ENCODE_UINT_MAX_BYTES];
Paul Sokolovsky047cd402014-02-19 15:47:59 +0200179 byte *p = buf + sizeof(buf);
180 // We encode in little-ending order, but store in big-endian, to help decoding
181 do {
182 *--p = num & 0x7f;
183 num >>= 7;
184 } while (num != 0 && num != -1);
185 // Make sure that highest bit we stored (mask 0x40) matches sign
186 // of the number. If not, store extra byte just to encode sign
187 if (num == -1 && (*p & 0x40) == 0) {
188 *--p = 0x7f;
189 } else if (num == 0 && (*p & 0x40) != 0) {
190 *--p = 0;
191 }
192
Damien George4dea9222015-04-09 15:29:54 +0000193 byte *c = emit_get_cur_to_write_bytecode(emit, buf + sizeof(buf) - p);
Paul Sokolovsky047cd402014-02-19 15:47:59 +0200194 while (p != buf + sizeof(buf) - 1) {
195 *c++ = *p++ | 0x80;
196 }
197 *c = *p;
Damien429d7192013-10-04 19:53:11 +0100198}
199
Angus Grattondecf8e62024-02-27 15:32:29 +1100200static void emit_write_bytecode_byte_uint(emit_t *emit, int stack_adj, byte b, mp_uint_t val) {
Damien George8e7745e2019-08-22 14:55:16 +1000201 emit_write_bytecode_byte(emit, stack_adj, b);
Damien Georgef2040bf2021-10-22 22:22:47 +1100202 mp_encode_uint(emit, emit_get_cur_to_write_bytecode, val);
Damien429d7192013-10-04 19:53:11 +0100203}
204
Angus Grattondecf8e62024-02-27 15:32:29 +1100205static void emit_write_bytecode_byte_const(emit_t *emit, int stack_adj, byte b, mp_uint_t n) {
Damien George8e7745e2019-08-22 14:55:16 +1000206 emit_write_bytecode_byte_uint(emit, stack_adj, b, n);
Damien Georgec8e9c0d2015-11-02 17:27:18 +0000207}
Damien Georgedf8127a2014-04-13 11:04:33 +0100208
Angus Grattondecf8e62024-02-27 15:32:29 +1100209static void emit_write_bytecode_byte_qstr(emit_t *emit, int stack_adj, byte b, qstr qst) {
Damien Georgef2040bf2021-10-22 22:22:47 +1100210 emit_write_bytecode_byte_uint(emit, stack_adj, b, mp_emit_common_use_qstr(emit->emit_common, qst));
Damien Georgec8e9c0d2015-11-02 17:27:18 +0000211}
212
Angus Grattondecf8e62024-02-27 15:32:29 +1100213static void emit_write_bytecode_byte_obj(emit_t *emit, int stack_adj, byte b, mp_obj_t obj) {
Damien George85885252022-05-07 15:51:41 +1000214 emit_write_bytecode_byte_const(emit, stack_adj, b, mp_emit_common_use_const_obj(emit->emit_common, obj));
Damien Georgec8e9c0d2015-11-02 17:27:18 +0000215}
216
Angus Grattondecf8e62024-02-27 15:32:29 +1100217static void emit_write_bytecode_byte_child(emit_t *emit, int stack_adj, byte b, mp_raw_code_t *rc) {
Damien George8e7745e2019-08-22 14:55:16 +1000218 emit_write_bytecode_byte_const(emit, stack_adj, b,
Damien Georgef2040bf2021-10-22 22:22:47 +1100219 mp_emit_common_alloc_const_child(emit->emit_common, rc));
Milan Rossa310b3d12019-08-14 16:09:36 +0200220 #if MICROPY_PY_SYS_SETTRACE
221 rc->line_of_definition = emit->last_source_line;
222 #endif
Damien429d7192013-10-04 19:53:11 +0100223}
224
Damien George538c3c02022-03-16 09:37:58 +1100225// Emit a jump opcode to a destination label.
226// The offset to the label is relative to the ip following this instruction.
227// The offset is encoded as either 1 or 2 bytes, depending on how big it is.
228// The encoding of this jump opcode can change size from one pass to the next,
229// but it must only ever decrease in size on successive passes.
Angus Grattondecf8e62024-02-27 15:32:29 +1100230static void emit_write_bytecode_byte_label(emit_t *emit, int stack_adj, byte b1, mp_uint_t label) {
Damien George8e7745e2019-08-22 14:55:16 +1000231 mp_emit_bc_adjust_stack_size(emit, stack_adj);
Damien03c9cfb2013-11-05 22:06:08 +0000232
Damien Georgea5063352022-06-17 23:14:32 +1000233 if (emit->suppress) {
234 return;
235 }
236
Damien George538c3c02022-03-16 09:37:58 +1100237 // Determine if the jump offset is signed or unsigned, based on the opcode.
Damien George6d11c692022-03-21 16:36:13 +1100238 const bool is_signed = b1 <= MP_BC_POP_JUMP_IF_FALSE;
Damien George538c3c02022-03-16 09:37:58 +1100239
240 // Default to a 2-byte encoding (the largest) with an unknown jump offset.
241 unsigned int jump_encoding_size = 1;
242 ssize_t bytecode_offset = 0;
243
244 // Compute the jump size and offset only when code size is known.
245 if (emit->pass >= MP_PASS_CODE_SIZE) {
246 // The -2 accounts for this jump opcode taking 2 bytes (at least).
247 bytecode_offset = emit->label_offsets[label] - emit->bytecode_offset - 2;
248
249 // Check if the bytecode_offset is small enough to use a 1-byte encoding.
250 if ((is_signed && -64 <= bytecode_offset && bytecode_offset <= 63)
251 || (!is_signed && (size_t)bytecode_offset <= 127)) {
252 // Use a 1-byte jump offset.
253 jump_encoding_size = 0;
254 }
255
256 // Adjust the offset depending on the size of the encoding of the offset.
257 bytecode_offset -= jump_encoding_size;
258
259 assert(is_signed || bytecode_offset >= 0);
Damien03c9cfb2013-11-05 22:06:08 +0000260 }
Damien George538c3c02022-03-16 09:37:58 +1100261
262 // Emit the opcode.
263 byte *c = emit_get_cur_to_write_bytecode(emit, 2 + jump_encoding_size);
Damien03c9cfb2013-11-05 22:06:08 +0000264 c[0] = b1;
Damien George538c3c02022-03-16 09:37:58 +1100265 if (jump_encoding_size == 0) {
266 if (is_signed) {
267 bytecode_offset += 0x40;
268 }
269 assert(0 <= bytecode_offset && bytecode_offset <= 0x7f);
270 c[1] = bytecode_offset;
271 } else {
272 if (is_signed) {
273 bytecode_offset += 0x4000;
274 }
Damien Georgeacd2c5c2022-03-18 13:18:59 +1100275 if (emit->pass == MP_PASS_EMIT && !(0 <= bytecode_offset && bytecode_offset <= 0x7fff)) {
276 emit->overflow = true;
277 }
Damien George538c3c02022-03-16 09:37:58 +1100278 c[1] = 0x80 | (bytecode_offset & 0x7f);
279 c[2] = bytecode_offset >> 7;
280 }
Damien429d7192013-10-04 19:53:11 +0100281}
282
Damien George41125902015-03-26 16:44:14 +0000283void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
Damien George6baf76e2013-12-30 22:32:17 +0000284 emit->pass = pass;
285 emit->stack_size = 0;
Damien Georgea5063352022-06-17 23:14:32 +1000286 emit->suppress = false;
Damien George6baf76e2013-12-30 22:32:17 +0000287 emit->scope = scope;
Damien George08335002014-01-18 23:24:36 +0000288 emit->last_source_line_offset = 0;
289 emit->last_source_line = 1;
Damien George3417bc22014-05-10 10:36:38 +0100290 emit->bytecode_offset = 0;
Damien George08335002014-01-18 23:24:36 +0000291 emit->code_info_offset = 0;
Damien Georgeacd2c5c2022-03-18 13:18:59 +1100292 emit->overflow = false;
Damien George08335002014-01-18 23:24:36 +0000293
Damien Georgeb5ebfad2019-09-16 22:12:59 +1000294 // Write local state size, exception stack size, scope flags and number of arguments
Damien George9b7f5832015-03-18 17:47:47 +0000295 {
296 mp_uint_t n_state = scope->num_locals + scope->stack_size;
297 if (n_state == 0) {
298 // Need at least 1 entry in the state, in the case an exception is
299 // propagated through this function, the exception is returned in
300 // the highest slot in the state (fastn[0], see vm.c).
301 n_state = 1;
302 }
Damien George6d199342019-01-04 17:09:41 +1100303 #if MICROPY_DEBUG_VM_STACK_OVERFLOW
304 // An extra slot in the stack is needed to detect VM stack overflow
305 n_state += 1;
306 #endif
Damien George08335002014-01-18 23:24:36 +0000307
Damien Georgeb5ebfad2019-09-16 22:12:59 +1000308 size_t n_exc_stack = scope->exc_stack_size;
309 MP_BC_PRELUDE_SIG_ENCODE(n_state, n_exc_stack, scope, emit_write_code_info_byte, emit);
310 }
Damien George3a3db4d2015-10-22 23:45:37 +0100311
Damien Georgec8c0fd42019-09-25 15:45:47 +1000312 // Write number of cells and size of the source code info
Damien Georgef2040bf2021-10-22 22:22:47 +1100313 if (emit->pass >= MP_PASS_CODE_SIZE) {
314 size_t n_info = emit->n_info;
315 size_t n_cell = emit->n_cell;
316 MP_BC_PRELUDE_SIZE_ENCODE(n_info, n_cell, emit_write_code_info_byte, emit);
Damien George8dcc0c72014-03-27 10:55:21 +0000317 }
318
Damien Georgec8c0fd42019-09-25 15:45:47 +1000319 emit->n_info = emit->code_info_offset;
320
Damien Georgef2040bf2021-10-22 22:22:47 +1100321 // Write the name of this function.
Damien George9b7f5832015-03-18 17:47:47 +0000322 emit_write_code_info_qstr(emit, scope->simple_name);
Damien George9b7f5832015-03-18 17:47:47 +0000323
Damien Georgef2040bf2021-10-22 22:22:47 +1100324 // Write argument names, needed to resolve positional args passed as keywords.
325 {
Damien George713ea182015-10-23 01:23:11 +0100326 // For a given argument position (indexed by i) we need to find the
327 // corresponding id_info which is a parameter, as it has the correct
328 // qstr name to use as the argument name. Note that it's not a simple
329 // 1-1 mapping (ie i!=j in general) because of possible closed-over
330 // variables. In the case that the argument i has no corresponding
331 // parameter we use "*" as its name (since no argument can ever be named
332 // "*"). We could use a blank qstr but "*" is better for debugging.
333 // Note: there is some wasted RAM here for the case of storing a qstr
334 // for each closed-over variable, and maybe there is a better way to do
335 // it, but that would require changes to mp_setup_code_state.
336 for (int i = 0; i < scope->num_pos_args + scope->num_kwonly_args; i++) {
337 qstr qst = MP_QSTR__star_;
338 for (int j = 0; j < scope->id_info_len; ++j) {
339 id_info_t *id = &scope->id_info[j];
340 if ((id->flags & ID_FLAG_IS_PARAM) && id->local_num == i) {
341 qst = id->qst;
342 break;
343 }
344 }
Damien Georgef2040bf2021-10-22 22:22:47 +1100345 emit_write_code_info_qstr(emit, qst);
Damien George713ea182015-10-23 01:23:11 +0100346 }
347 }
Damien George6baf76e2013-12-30 22:32:17 +0000348}
349
Damien George538c3c02022-03-16 09:37:58 +1100350bool mp_emit_bc_end_pass(emit_t *emit) {
Damien Georgea210c772015-03-26 15:49:53 +0000351 if (emit->pass == MP_PASS_SCOPE) {
Damien George538c3c02022-03-16 09:37:58 +1100352 return true;
Damien Georgea210c772015-03-26 15:49:53 +0000353 }
354
Damien George6baf76e2013-12-30 22:32:17 +0000355 // check stack is back to zero size
Damien George7385b012016-09-27 15:46:50 +1000356 assert(emit->stack_size == 0);
Damien George6baf76e2013-12-30 22:32:17 +0000357
Damien Georgec8c0fd42019-09-25 15:45:47 +1000358 // Calculate size of source code info section
359 emit->n_info = emit->code_info_offset - emit->n_info;
360
361 // Emit closure section of prelude
362 emit->n_cell = 0;
363 for (size_t i = 0; i < emit->scope->id_info_len; ++i) {
364 id_info_t *id = &emit->scope->id_info[i];
365 if (id->kind == ID_INFO_KIND_CELL) {
366 assert(id->local_num <= 255);
367 emit_write_code_info_byte(emit, id->local_num); // write the local which should be converted to a cell
368 ++emit->n_cell;
369 }
370 }
371
Damien George36db6bc2014-05-07 17:24:22 +0100372 if (emit->pass == MP_PASS_CODE_SIZE) {
Damien Georgeb534e1b2014-09-04 14:44:01 +0100373 // calculate size of total code-info + bytecode, in bytes
Damien George08335002014-01-18 23:24:36 +0000374 emit->code_info_size = emit->code_info_offset;
Damien George3417bc22014-05-10 10:36:38 +0100375 emit->bytecode_size = emit->bytecode_offset;
376 emit->code_base = m_new0(byte, emit->code_info_size + emit->bytecode_size);
Damien George6baf76e2013-12-30 22:32:17 +0000377
Damien George36db6bc2014-05-07 17:24:22 +0100378 } else if (emit->pass == MP_PASS_EMIT) {
Damien George538c3c02022-03-16 09:37:58 +1100379 // Code info and/or bytecode can shrink during this pass.
380 assert(emit->code_info_offset <= emit->code_info_size);
381 assert(emit->bytecode_offset <= emit->bytecode_size);
382
383 if (emit->code_info_offset != emit->code_info_size
384 || emit->bytecode_offset != emit->bytecode_size) {
385 // Code info and/or bytecode changed size in this pass, so request the
386 // compiler to do another pass with these updated sizes.
387 emit->code_info_size = emit->code_info_offset;
388 emit->bytecode_size = emit->bytecode_offset;
389 return false;
390 }
391
Damien Georgeacd2c5c2022-03-18 13:18:59 +1100392 if (emit->overflow) {
393 mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("bytecode overflow"));
394 }
395
Damien Georgedef6ad42024-02-13 10:46:11 +1100396 #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS
397 size_t bytecode_len = emit->code_info_size + emit->bytecode_size;
398 #if MICROPY_DEBUG_PRINTERS
399 emit->scope->raw_code_data_len = bytecode_len;
400 #endif
401 #endif
402
Damien George538c3c02022-03-16 09:37:58 +1100403 // Bytecode is finalised, assign it to the raw code object.
Damien George3417bc22014-05-10 10:36:38 +0100404 mp_emit_glue_assign_bytecode(emit->scope->raw_code, emit->code_base,
Damien Georgef2040bf2021-10-22 22:22:47 +1100405 emit->emit_common->children,
Damien Georged8c834c2015-11-02 21:55:42 +0000406 #if MICROPY_PERSISTENT_CODE_SAVE
Damien Georgedef6ad42024-02-13 10:46:11 +1100407 bytecode_len,
Damien Georgef2040bf2021-10-22 22:22:47 +1100408 emit->emit_common->ct_cur_child,
Damien Georged8c834c2015-11-02 21:55:42 +0000409 #endif
410 emit->scope->scope_flags);
Damien George6baf76e2013-12-30 22:32:17 +0000411 }
Damien George538c3c02022-03-16 09:37:58 +1100412
413 return true;
Damien George6baf76e2013-12-30 22:32:17 +0000414}
415
Damien George41125902015-03-26 16:44:14 +0000416void mp_emit_bc_adjust_stack_size(emit_t *emit, mp_int_t delta) {
Damien George8f064e42017-05-25 20:42:30 +1000417 if (emit->pass == MP_PASS_SCOPE) {
418 return;
419 }
420 assert((mp_int_t)emit->stack_size + delta >= 0);
Damien Georged66ae182014-04-10 17:28:54 +0000421 emit->stack_size += delta;
Damien George8f064e42017-05-25 20:42:30 +1000422 if (emit->stack_size > emit->scope->stack_size) {
423 emit->scope->stack_size = emit->stack_size;
424 }
Damien George8f064e42017-05-25 20:42:30 +1000425}
426
Damien George41125902015-03-26 16:44:14 +0000427void mp_emit_bc_set_source_line(emit_t *emit, mp_uint_t source_line) {
Damien George69661f32020-02-27 15:36:53 +1100428 #if MICROPY_ENABLE_SOURCE_LINE
Damien Georgeb4b10fd2015-01-01 23:30:53 +0000429 if (MP_STATE_VM(mp_optimise_value) >= 3) {
Paul Sokolovskyb8f117d2014-06-02 19:39:15 +0300430 // If we compile with -O3, don't store line numbers.
431 return;
432 }
Damien George08335002014-01-18 23:24:36 +0000433 if (source_line > emit->last_source_line) {
Damien George7ff996c2014-09-08 23:05:16 +0100434 mp_uint_t bytes_to_skip = emit->bytecode_offset - emit->last_source_line_offset;
435 mp_uint_t lines_to_skip = source_line - emit->last_source_line;
Damien George28eb5772014-01-25 11:43:20 +0000436 emit_write_code_info_bytes_lines(emit, bytes_to_skip, lines_to_skip);
Damien George3417bc22014-05-10 10:36:38 +0100437 emit->last_source_line_offset = emit->bytecode_offset;
Damien George08335002014-01-18 23:24:36 +0000438 emit->last_source_line = source_line;
439 }
Damien George69661f32020-02-27 15:36:53 +1100440 #else
Damien George3a2171e2015-09-04 16:53:46 +0100441 (void)emit;
442 (void)source_line;
Damien George69661f32020-02-27 15:36:53 +1100443 #endif
Damien George08335002014-01-18 23:24:36 +0000444}
445
Damien George41125902015-03-26 16:44:14 +0000446void mp_emit_bc_label_assign(emit_t *emit, mp_uint_t l) {
Damien Georgeb1229ef2023-03-08 14:10:02 +1100447 // Assigning a label ends any dead-code region, and all following opcodes
Damien Georgea5063352022-06-17 23:14:32 +1000448 // should be emitted (until another unconditional flow control).
449 emit->suppress = false;
450
Damien Georgea210c772015-03-26 15:49:53 +0000451 if (emit->pass == MP_PASS_SCOPE) {
452 return;
453 }
Damien George538c3c02022-03-16 09:37:58 +1100454
455 // Label offsets can change from one pass to the next, but they must only
456 // decrease (ie code can only shrink). There will be multiple MP_PASS_EMIT
457 // stages until the labels no longer change, which is when the code size
458 // stays constant after a MP_PASS_EMIT.
Damienb05d7072013-10-05 13:37:10 +0100459 assert(l < emit->max_num_labels);
Damien George538c3c02022-03-16 09:37:58 +1100460 assert(emit->pass == MP_PASS_STACK_SIZE || emit->bytecode_offset <= emit->label_offsets[l]);
461
462 // Assign label offset.
463 emit->label_offsets[l] = emit->bytecode_offset;
Damien429d7192013-10-04 19:53:11 +0100464}
465
Damien Georged97906c2018-05-22 21:58:25 +1000466void mp_emit_bc_import(emit_t *emit, qstr qst, int kind) {
467 MP_STATIC_ASSERT(MP_BC_IMPORT_NAME + MP_EMIT_IMPORT_NAME == MP_BC_IMPORT_NAME);
468 MP_STATIC_ASSERT(MP_BC_IMPORT_NAME + MP_EMIT_IMPORT_FROM == MP_BC_IMPORT_FROM);
Damien George8e7745e2019-08-22 14:55:16 +1000469 int stack_adj = kind == MP_EMIT_IMPORT_FROM ? 1 : -1;
Damien Georged97906c2018-05-22 21:58:25 +1000470 if (kind == MP_EMIT_IMPORT_STAR) {
Damien George8e7745e2019-08-22 14:55:16 +1000471 emit_write_bytecode_byte(emit, stack_adj, MP_BC_IMPORT_STAR);
Damien Georged97906c2018-05-22 21:58:25 +1000472 } else {
Damien George8e7745e2019-08-22 14:55:16 +1000473 emit_write_bytecode_byte_qstr(emit, stack_adj, MP_BC_IMPORT_NAME + kind, qst);
Damien Georged97906c2018-05-22 21:58:25 +1000474 }
Damien429d7192013-10-04 19:53:11 +0100475}
476
Damien George41125902015-03-26 16:44:14 +0000477void mp_emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
Damien George3d9bd802019-08-22 14:36:27 +1000478 MP_STATIC_ASSERT(MP_BC_LOAD_CONST_FALSE + (MP_TOKEN_KW_NONE - MP_TOKEN_KW_FALSE) == MP_BC_LOAD_CONST_NONE);
479 MP_STATIC_ASSERT(MP_BC_LOAD_CONST_FALSE + (MP_TOKEN_KW_TRUE - MP_TOKEN_KW_FALSE) == MP_BC_LOAD_CONST_TRUE);
Damien George3d9bd802019-08-22 14:36:27 +1000480 if (tok == MP_TOKEN_ELLIPSIS) {
Damien George8e7745e2019-08-22 14:55:16 +1000481 emit_write_bytecode_byte_obj(emit, 1, MP_BC_LOAD_CONST_OBJ, MP_OBJ_FROM_PTR(&mp_const_ellipsis_obj));
Damien George3d9bd802019-08-22 14:36:27 +1000482 } else {
Damien George8e7745e2019-08-22 14:55:16 +1000483 emit_write_bytecode_byte(emit, 1, MP_BC_LOAD_CONST_FALSE + (tok - MP_TOKEN_KW_FALSE));
Damien429d7192013-10-04 19:53:11 +0100484 }
485}
486
Damien George41125902015-03-26 16:44:14 +0000487void mp_emit_bc_load_const_small_int(emit_t *emit, mp_int_t arg) {
Damien Georgee3de7232022-03-31 23:59:10 +1100488 assert(MP_SMALL_INT_FITS(arg));
Damien George870e9002019-09-12 12:19:49 +1000489 if (-MP_BC_LOAD_CONST_SMALL_INT_MULTI_EXCESS <= arg
490 && arg < MP_BC_LOAD_CONST_SMALL_INT_MULTI_NUM - MP_BC_LOAD_CONST_SMALL_INT_MULTI_EXCESS) {
491 emit_write_bytecode_byte(emit, 1,
492 MP_BC_LOAD_CONST_SMALL_INT_MULTI + MP_BC_LOAD_CONST_SMALL_INT_MULTI_EXCESS + arg);
Damien George8456cc02014-10-25 16:43:46 +0100493 } else {
Damien George8e7745e2019-08-22 14:55:16 +1000494 emit_write_bytecode_byte_int(emit, 1, MP_BC_LOAD_CONST_SMALL_INT, arg);
Damien George8456cc02014-10-25 16:43:46 +0100495 }
Damien429d7192013-10-04 19:53:11 +0100496}
497
Damien George59fba2d2015-06-25 14:42:13 +0000498void mp_emit_bc_load_const_str(emit_t *emit, qstr qst) {
Damien George8e7745e2019-08-22 14:55:16 +1000499 emit_write_bytecode_byte_qstr(emit, 1, MP_BC_LOAD_CONST_STRING, qst);
Damien429d7192013-10-04 19:53:11 +0100500}
501
Damien George5d66b422015-11-27 12:41:25 +0000502void mp_emit_bc_load_const_obj(emit_t *emit, mp_obj_t obj) {
Damien George8e7745e2019-08-22 14:55:16 +1000503 emit_write_bytecode_byte_obj(emit, 1, MP_BC_LOAD_CONST_OBJ, obj);
Damien Georgedab13852015-01-13 15:55:54 +0000504}
505
Damien George41125902015-03-26 16:44:14 +0000506void mp_emit_bc_load_null(emit_t *emit) {
Damien George8e7745e2019-08-22 14:55:16 +1000507 emit_write_bytecode_byte(emit, 1, MP_BC_LOAD_NULL);
Damien George280fb4d2017-09-13 20:36:06 +1000508}
Damien George523b5752014-03-31 11:59:23 +0100509
Damien George0a25fff2018-05-19 00:11:04 +1000510void mp_emit_bc_load_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind) {
511 MP_STATIC_ASSERT(MP_BC_LOAD_FAST_N + MP_EMIT_IDOP_LOCAL_FAST == MP_BC_LOAD_FAST_N);
512 MP_STATIC_ASSERT(MP_BC_LOAD_FAST_N + MP_EMIT_IDOP_LOCAL_DEREF == MP_BC_LOAD_DEREF);
Damien Georgeff8dd3f2015-01-20 12:47:20 +0000513 (void)qst;
Damien George0a25fff2018-05-19 00:11:04 +1000514 if (kind == MP_EMIT_IDOP_LOCAL_FAST && local_num <= 15) {
Damien George8e7745e2019-08-22 14:55:16 +1000515 emit_write_bytecode_byte(emit, 1, MP_BC_LOAD_FAST_MULTI + local_num);
Damien George8456cc02014-10-25 16:43:46 +0100516 } else {
Damien George8e7745e2019-08-22 14:55:16 +1000517 emit_write_bytecode_byte_uint(emit, 1, MP_BC_LOAD_FAST_N + kind, local_num);
Damien429d7192013-10-04 19:53:11 +0100518 }
519}
520
Damien Georged2980132018-05-22 21:16:30 +1000521void mp_emit_bc_load_global(emit_t *emit, qstr qst, int kind) {
522 MP_STATIC_ASSERT(MP_BC_LOAD_NAME + MP_EMIT_IDOP_GLOBAL_NAME == MP_BC_LOAD_NAME);
523 MP_STATIC_ASSERT(MP_BC_LOAD_NAME + MP_EMIT_IDOP_GLOBAL_GLOBAL == MP_BC_LOAD_GLOBAL);
Damien Georgeff8dd3f2015-01-20 12:47:20 +0000524 (void)qst;
Damien George8e7745e2019-08-22 14:55:16 +1000525 emit_write_bytecode_byte_qstr(emit, 1, MP_BC_LOAD_NAME + kind, qst);
Damien429d7192013-10-04 19:53:11 +0100526}
527
Damien Georgedd11af22017-04-19 09:45:59 +1000528void mp_emit_bc_load_method(emit_t *emit, qstr qst, bool is_super) {
Damien George8e7745e2019-08-22 14:55:16 +1000529 int stack_adj = 1 - 2 * is_super;
530 emit_write_bytecode_byte_qstr(emit, stack_adj, is_super ? MP_BC_LOAD_SUPER_METHOD : MP_BC_LOAD_METHOD, qst);
Damien429d7192013-10-04 19:53:11 +0100531}
532
Damien George41125902015-03-26 16:44:14 +0000533void mp_emit_bc_load_build_class(emit_t *emit) {
Damien George8e7745e2019-08-22 14:55:16 +1000534 emit_write_bytecode_byte(emit, 1, MP_BC_LOAD_BUILD_CLASS);
Damien429d7192013-10-04 19:53:11 +0100535}
536
Damien Georgea4941a82018-05-22 21:31:56 +1000537void mp_emit_bc_subscr(emit_t *emit, int kind) {
538 if (kind == MP_EMIT_SUBSCR_LOAD) {
Damien George8e7745e2019-08-22 14:55:16 +1000539 emit_write_bytecode_byte(emit, -1, MP_BC_LOAD_SUBSCR);
Damien Georgea4941a82018-05-22 21:31:56 +1000540 } else {
541 if (kind == MP_EMIT_SUBSCR_DELETE) {
542 mp_emit_bc_load_null(emit);
543 mp_emit_bc_rot_three(emit);
544 }
Damien George8e7745e2019-08-22 14:55:16 +1000545 emit_write_bytecode_byte(emit, -3, MP_BC_STORE_SUBSCR);
Damien Georgea4941a82018-05-22 21:31:56 +1000546 }
Damien George729f7b42014-04-17 22:10:53 +0100547}
548
Damien George6211d972018-05-22 21:43:41 +1000549void mp_emit_bc_attr(emit_t *emit, qstr qst, int kind) {
550 if (kind == MP_EMIT_ATTR_LOAD) {
Damien George8e7745e2019-08-22 14:55:16 +1000551 emit_write_bytecode_byte_qstr(emit, 0, MP_BC_LOAD_ATTR, qst);
Damien George6211d972018-05-22 21:43:41 +1000552 } else {
553 if (kind == MP_EMIT_ATTR_DELETE) {
554 mp_emit_bc_load_null(emit);
555 mp_emit_bc_rot_two(emit);
556 }
Damien George8e7745e2019-08-22 14:55:16 +1000557 emit_write_bytecode_byte_qstr(emit, -2, MP_BC_STORE_ATTR, qst);
Damien George6211d972018-05-22 21:43:41 +1000558 }
Damien George6211d972018-05-22 21:43:41 +1000559}
560
Damien George0a25fff2018-05-19 00:11:04 +1000561void mp_emit_bc_store_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind) {
562 MP_STATIC_ASSERT(MP_BC_STORE_FAST_N + MP_EMIT_IDOP_LOCAL_FAST == MP_BC_STORE_FAST_N);
563 MP_STATIC_ASSERT(MP_BC_STORE_FAST_N + MP_EMIT_IDOP_LOCAL_DEREF == MP_BC_STORE_DEREF);
Damien Georgeff8dd3f2015-01-20 12:47:20 +0000564 (void)qst;
Damien George0a25fff2018-05-19 00:11:04 +1000565 if (kind == MP_EMIT_IDOP_LOCAL_FAST && local_num <= 15) {
Damien George8e7745e2019-08-22 14:55:16 +1000566 emit_write_bytecode_byte(emit, -1, MP_BC_STORE_FAST_MULTI + local_num);
Damien George8456cc02014-10-25 16:43:46 +0100567 } else {
Damien George8e7745e2019-08-22 14:55:16 +1000568 emit_write_bytecode_byte_uint(emit, -1, MP_BC_STORE_FAST_N + kind, local_num);
Damien429d7192013-10-04 19:53:11 +0100569 }
570}
571
Damien Georged2980132018-05-22 21:16:30 +1000572void mp_emit_bc_store_global(emit_t *emit, qstr qst, int kind) {
573 MP_STATIC_ASSERT(MP_BC_STORE_NAME + MP_EMIT_IDOP_GLOBAL_NAME == MP_BC_STORE_NAME);
574 MP_STATIC_ASSERT(MP_BC_STORE_NAME + MP_EMIT_IDOP_GLOBAL_GLOBAL == MP_BC_STORE_GLOBAL);
Damien George8e7745e2019-08-22 14:55:16 +1000575 emit_write_bytecode_byte_qstr(emit, -1, MP_BC_STORE_NAME + kind, qst);
Damien429d7192013-10-04 19:53:11 +0100576}
577
Damien George0a25fff2018-05-19 00:11:04 +1000578void mp_emit_bc_delete_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind) {
579 MP_STATIC_ASSERT(MP_BC_DELETE_FAST + MP_EMIT_IDOP_LOCAL_FAST == MP_BC_DELETE_FAST);
580 MP_STATIC_ASSERT(MP_BC_DELETE_FAST + MP_EMIT_IDOP_LOCAL_DEREF == MP_BC_DELETE_DEREF);
Damien Georgeff8dd3f2015-01-20 12:47:20 +0000581 (void)qst;
Damien George8e7745e2019-08-22 14:55:16 +1000582 emit_write_bytecode_byte_uint(emit, 0, MP_BC_DELETE_FAST + kind, local_num);
Damien9ecbcff2013-12-11 00:41:43 +0000583}
584
Damien Georged2980132018-05-22 21:16:30 +1000585void mp_emit_bc_delete_global(emit_t *emit, qstr qst, int kind) {
586 MP_STATIC_ASSERT(MP_BC_DELETE_NAME + MP_EMIT_IDOP_GLOBAL_NAME == MP_BC_DELETE_NAME);
587 MP_STATIC_ASSERT(MP_BC_DELETE_NAME + MP_EMIT_IDOP_GLOBAL_GLOBAL == MP_BC_DELETE_GLOBAL);
Damien George8e7745e2019-08-22 14:55:16 +1000588 emit_write_bytecode_byte_qstr(emit, 0, MP_BC_DELETE_NAME + kind, qst);
Damien429d7192013-10-04 19:53:11 +0100589}
590
Damien George41125902015-03-26 16:44:14 +0000591void mp_emit_bc_dup_top(emit_t *emit) {
Damien George8e7745e2019-08-22 14:55:16 +1000592 emit_write_bytecode_byte(emit, 1, MP_BC_DUP_TOP);
Damien429d7192013-10-04 19:53:11 +0100593}
594
Damien George41125902015-03-26 16:44:14 +0000595void mp_emit_bc_dup_top_two(emit_t *emit) {
Damien George8e7745e2019-08-22 14:55:16 +1000596 emit_write_bytecode_byte(emit, 2, MP_BC_DUP_TOP_TWO);
Damien429d7192013-10-04 19:53:11 +0100597}
598
Damien George41125902015-03-26 16:44:14 +0000599void mp_emit_bc_pop_top(emit_t *emit) {
Damien George8e7745e2019-08-22 14:55:16 +1000600 emit_write_bytecode_byte(emit, -1, MP_BC_POP_TOP);
Damien429d7192013-10-04 19:53:11 +0100601}
602
Damien George41125902015-03-26 16:44:14 +0000603void mp_emit_bc_rot_two(emit_t *emit) {
Damien George8e7745e2019-08-22 14:55:16 +1000604 emit_write_bytecode_byte(emit, 0, MP_BC_ROT_TWO);
Damien429d7192013-10-04 19:53:11 +0100605}
606
Damien George41125902015-03-26 16:44:14 +0000607void mp_emit_bc_rot_three(emit_t *emit) {
Damien George8e7745e2019-08-22 14:55:16 +1000608 emit_write_bytecode_byte(emit, 0, MP_BC_ROT_THREE);
Damien429d7192013-10-04 19:53:11 +0100609}
610
Damien George41125902015-03-26 16:44:14 +0000611void mp_emit_bc_jump(emit_t *emit, mp_uint_t label) {
Damien George538c3c02022-03-16 09:37:58 +1100612 emit_write_bytecode_byte_label(emit, 0, MP_BC_JUMP, label);
Damien Georgea5063352022-06-17 23:14:32 +1000613 emit->suppress = true;
Damien429d7192013-10-04 19:53:11 +0100614}
615
Damien George41125902015-03-26 16:44:14 +0000616void mp_emit_bc_pop_jump_if(emit_t *emit, bool cond, mp_uint_t label) {
Damien George63f38322015-02-28 15:04:06 +0000617 if (cond) {
Damien George538c3c02022-03-16 09:37:58 +1100618 emit_write_bytecode_byte_label(emit, -1, MP_BC_POP_JUMP_IF_TRUE, label);
Damien George63f38322015-02-28 15:04:06 +0000619 } else {
Damien George538c3c02022-03-16 09:37:58 +1100620 emit_write_bytecode_byte_label(emit, -1, MP_BC_POP_JUMP_IF_FALSE, label);
Damien George63f38322015-02-28 15:04:06 +0000621 }
Damien429d7192013-10-04 19:53:11 +0100622}
623
Damien George41125902015-03-26 16:44:14 +0000624void mp_emit_bc_jump_if_or_pop(emit_t *emit, bool cond, mp_uint_t label) {
Damien George63f38322015-02-28 15:04:06 +0000625 if (cond) {
Damien George538c3c02022-03-16 09:37:58 +1100626 emit_write_bytecode_byte_label(emit, -1, MP_BC_JUMP_IF_TRUE_OR_POP, label);
Damien George63f38322015-02-28 15:04:06 +0000627 } else {
Damien George538c3c02022-03-16 09:37:58 +1100628 emit_write_bytecode_byte_label(emit, -1, MP_BC_JUMP_IF_FALSE_OR_POP, label);
Damien George63f38322015-02-28 15:04:06 +0000629 }
Damien429d7192013-10-04 19:53:11 +0100630}
631
Damien George41125902015-03-26 16:44:14 +0000632void mp_emit_bc_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_depth) {
Damien Georgecbddb272014-02-01 20:08:18 +0000633 if (except_depth == 0) {
Damien George25c84642014-05-30 15:20:41 +0100634 if (label & MP_EMIT_BREAK_FROM_FOR) {
635 // need to pop the iterator if we are breaking out of a for loop
Damien George8e7745e2019-08-22 14:55:16 +1000636 emit_write_bytecode_raw_byte(emit, MP_BC_POP_TOP);
Damien Georgef4df3aa2016-01-09 23:59:52 +0000637 // also pop the iter_buf
Damien George60656ea2017-03-23 16:36:08 +1100638 for (size_t i = 0; i < MP_OBJ_ITER_BUF_NSLOTS - 1; ++i) {
Damien George8e7745e2019-08-22 14:55:16 +1000639 emit_write_bytecode_raw_byte(emit, MP_BC_POP_TOP);
Damien Georgef4df3aa2016-01-09 23:59:52 +0000640 }
Damien George25c84642014-05-30 15:20:41 +0100641 }
Damien George538c3c02022-03-16 09:37:58 +1100642 emit_write_bytecode_byte_label(emit, 0, MP_BC_JUMP, label & ~MP_EMIT_BREAK_FROM_FOR);
Damien George25c84642014-05-30 15:20:41 +0100643 } else {
Damien George538c3c02022-03-16 09:37:58 +1100644 emit_write_bytecode_byte_label(emit, 0, MP_BC_UNWIND_JUMP, label & ~MP_EMIT_BREAK_FROM_FOR);
Damien George8e7745e2019-08-22 14:55:16 +1000645 emit_write_bytecode_raw_byte(emit, ((label & MP_EMIT_BREAK_FROM_FOR) ? 0x80 : 0) | except_depth);
Damien Georgecbddb272014-02-01 20:08:18 +0000646 }
Damien Georgea5063352022-06-17 23:14:32 +1000647 emit->suppress = true;
Damien429d7192013-10-04 19:53:11 +0100648}
649
Damien George18e63582018-05-22 22:33:26 +1000650void mp_emit_bc_setup_block(emit_t *emit, mp_uint_t label, int kind) {
651 MP_STATIC_ASSERT(MP_BC_SETUP_WITH + MP_EMIT_SETUP_BLOCK_WITH == MP_BC_SETUP_WITH);
652 MP_STATIC_ASSERT(MP_BC_SETUP_WITH + MP_EMIT_SETUP_BLOCK_EXCEPT == MP_BC_SETUP_EXCEPT);
653 MP_STATIC_ASSERT(MP_BC_SETUP_WITH + MP_EMIT_SETUP_BLOCK_FINALLY == MP_BC_SETUP_FINALLY);
Damien Georgef0406852016-09-27 12:37:21 +1000654 // The SETUP_WITH opcode pops ctx_mgr from the top of the stack
655 // and then pushes 3 entries: __exit__, ctx_mgr, as_value.
Damien George8e7745e2019-08-22 14:55:16 +1000656 int stack_adj = kind == MP_EMIT_SETUP_BLOCK_WITH ? 2 : 0;
Damien George538c3c02022-03-16 09:37:58 +1100657 emit_write_bytecode_byte_label(emit, stack_adj, MP_BC_SETUP_WITH + kind, label);
Damien429d7192013-10-04 19:53:11 +0100658}
659
Damien Georgece8b4e82016-04-07 08:50:38 +0100660void mp_emit_bc_with_cleanup(emit_t *emit, mp_uint_t label) {
Damien Georgece8b4e82016-04-07 08:50:38 +0100661 mp_emit_bc_load_const_tok(emit, MP_TOKEN_KW_NONE);
662 mp_emit_bc_label_assign(emit, label);
Damien George8e7745e2019-08-22 14:55:16 +1000663 // The +2 is to ensure we have enough stack space to call the __exit__ method
664 emit_write_bytecode_byte(emit, 2, MP_BC_WITH_CLEANUP);
665 // Cancel the +2 above, plus the +2 from mp_emit_bc_setup_block(MP_EMIT_SETUP_BLOCK_WITH)
666 mp_emit_bc_adjust_stack_size(emit, -4);
Damien429d7192013-10-04 19:53:11 +0100667}
668
Damien George41125902015-03-26 16:44:14 +0000669void mp_emit_bc_end_finally(emit_t *emit) {
Damien George8e7745e2019-08-22 14:55:16 +1000670 emit_write_bytecode_byte(emit, -1, MP_BC_END_FINALLY);
Damien429d7192013-10-04 19:53:11 +0100671}
672
Damien Georgef4df3aa2016-01-09 23:59:52 +0000673void mp_emit_bc_get_iter(emit_t *emit, bool use_stack) {
Damien George8e7745e2019-08-22 14:55:16 +1000674 int stack_adj = use_stack ? MP_OBJ_ITER_BUF_NSLOTS - 1 : 0;
675 emit_write_bytecode_byte(emit, stack_adj, use_stack ? MP_BC_GET_ITER_STACK : MP_BC_GET_ITER);
Damien429d7192013-10-04 19:53:11 +0100676}
677
Damien George41125902015-03-26 16:44:14 +0000678void mp_emit_bc_for_iter(emit_t *emit, mp_uint_t label) {
Damien George538c3c02022-03-16 09:37:58 +1100679 emit_write_bytecode_byte_label(emit, 1, MP_BC_FOR_ITER, label);
Damien429d7192013-10-04 19:53:11 +0100680}
681
Damien George30b42dd2017-01-17 15:30:18 +1100682void mp_emit_bc_for_iter_end(emit_t *emit) {
Damien George8e7745e2019-08-22 14:55:16 +1000683 mp_emit_bc_adjust_stack_size(emit, -MP_OBJ_ITER_BUF_NSLOTS);
Damien429d7192013-10-04 19:53:11 +0100684}
685
Damien George5a2599d2019-02-15 12:18:59 +1100686void mp_emit_bc_pop_except_jump(emit_t *emit, mp_uint_t label, bool within_exc_handler) {
687 (void)within_exc_handler;
Damien George538c3c02022-03-16 09:37:58 +1100688 emit_write_bytecode_byte_label(emit, 0, MP_BC_POP_EXCEPT_JUMP, label);
Damien Georgea5063352022-06-17 23:14:32 +1000689 emit->suppress = true;
Damien429d7192013-10-04 19:53:11 +0100690}
691
Damien George41125902015-03-26 16:44:14 +0000692void mp_emit_bc_unary_op(emit_t *emit, mp_unary_op_t op) {
Damien George8e7745e2019-08-22 14:55:16 +1000693 emit_write_bytecode_byte(emit, 0, MP_BC_UNARY_OP_MULTI + op);
Damien429d7192013-10-04 19:53:11 +0100694}
695
Damien George41125902015-03-26 16:44:14 +0000696void mp_emit_bc_binary_op(emit_t *emit, mp_binary_op_t op) {
Damien George9aa2a522014-02-01 23:04:09 +0000697 bool invert = false;
Damien Georged17926d2014-03-30 13:35:08 +0100698 if (op == MP_BINARY_OP_NOT_IN) {
Damien George9aa2a522014-02-01 23:04:09 +0000699 invert = true;
Damien Georged17926d2014-03-30 13:35:08 +0100700 op = MP_BINARY_OP_IN;
701 } else if (op == MP_BINARY_OP_IS_NOT) {
Damien George9aa2a522014-02-01 23:04:09 +0000702 invert = true;
Damien Georged17926d2014-03-30 13:35:08 +0100703 op = MP_BINARY_OP_IS;
Damien George9aa2a522014-02-01 23:04:09 +0000704 }
Damien George8e7745e2019-08-22 14:55:16 +1000705 emit_write_bytecode_byte(emit, -1, MP_BC_BINARY_OP_MULTI + op);
Damien George9aa2a522014-02-01 23:04:09 +0000706 if (invert) {
Damien George8e7745e2019-08-22 14:55:16 +1000707 emit_write_bytecode_byte(emit, 0, MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_NOT);
Damien George9aa2a522014-02-01 23:04:09 +0000708 }
Damien429d7192013-10-04 19:53:11 +0100709}
710
Damien George26b57542018-05-19 00:41:40 +1000711void mp_emit_bc_build(emit_t *emit, mp_uint_t n_args, int kind) {
712 MP_STATIC_ASSERT(MP_BC_BUILD_TUPLE + MP_EMIT_BUILD_TUPLE == MP_BC_BUILD_TUPLE);
713 MP_STATIC_ASSERT(MP_BC_BUILD_TUPLE + MP_EMIT_BUILD_LIST == MP_BC_BUILD_LIST);
714 MP_STATIC_ASSERT(MP_BC_BUILD_TUPLE + MP_EMIT_BUILD_MAP == MP_BC_BUILD_MAP);
Damien George436e0d42018-05-22 22:18:42 +1000715 MP_STATIC_ASSERT(MP_BC_BUILD_TUPLE + MP_EMIT_BUILD_SET == MP_BC_BUILD_SET);
716 MP_STATIC_ASSERT(MP_BC_BUILD_TUPLE + MP_EMIT_BUILD_SLICE == MP_BC_BUILD_SLICE);
Damien George8e7745e2019-08-22 14:55:16 +1000717 int stack_adj = kind == MP_EMIT_BUILD_MAP ? 1 : 1 - n_args;
718 emit_write_bytecode_byte_uint(emit, stack_adj, MP_BC_BUILD_TUPLE + kind, n_args);
Damien429d7192013-10-04 19:53:11 +0100719}
720
Damien George41125902015-03-26 16:44:14 +0000721void mp_emit_bc_store_map(emit_t *emit) {
Damien George8e7745e2019-08-22 14:55:16 +1000722 emit_write_bytecode_byte(emit, -2, MP_BC_STORE_MAP);
Damien429d7192013-10-04 19:53:11 +0100723}
724
Damien Georgea5624bf2016-09-18 23:59:47 +1000725void mp_emit_bc_store_comp(emit_t *emit, scope_kind_t kind, mp_uint_t collection_stack_index) {
Damien Georgeadaf0d82016-09-19 08:46:01 +1000726 int t;
Damien Georgea5624bf2016-09-18 23:59:47 +1000727 int n;
Damien Georgea5624bf2016-09-18 23:59:47 +1000728 if (kind == SCOPE_LIST_COMP) {
Damien Georgeadaf0d82016-09-19 08:46:01 +1000729 n = 0;
730 t = 0;
731 } else if (!MICROPY_PY_BUILTINS_SET || kind == SCOPE_DICT_COMP) {
732 n = 1;
733 t = 1;
734 } else if (MICROPY_PY_BUILTINS_SET) {
735 n = 0;
736 t = 2;
Damien Georgea5624bf2016-09-18 23:59:47 +1000737 }
Damien Georgeadaf0d82016-09-19 08:46:01 +1000738 // the lower 2 bits of the opcode argument indicate the collection type
Damien George8e7745e2019-08-22 14:55:16 +1000739 emit_write_bytecode_byte_uint(emit, -1 - n, MP_BC_STORE_COMP, ((collection_stack_index + n) << 2) | t);
Damien Georgea5624bf2016-09-18 23:59:47 +1000740}
741
Damien George41125902015-03-26 16:44:14 +0000742void mp_emit_bc_unpack_sequence(emit_t *emit, mp_uint_t n_args) {
Damien George8e7745e2019-08-22 14:55:16 +1000743 emit_write_bytecode_byte_uint(emit, -1 + n_args, MP_BC_UNPACK_SEQUENCE, n_args);
Damien429d7192013-10-04 19:53:11 +0100744}
745
Damien George41125902015-03-26 16:44:14 +0000746void mp_emit_bc_unpack_ex(emit_t *emit, mp_uint_t n_left, mp_uint_t n_right) {
Damien George8e7745e2019-08-22 14:55:16 +1000747 emit_write_bytecode_byte_uint(emit, -1 + n_left + n_right + 1, MP_BC_UNPACK_EX, n_left | (n_right << 8));
Damien429d7192013-10-04 19:53:11 +0100748}
749
Damien George41125902015-03-26 16:44:14 +0000750void mp_emit_bc_make_function(emit_t *emit, scope_t *scope, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults) {
Damien Georgee337f1e2014-03-31 15:18:37 +0100751 if (n_pos_defaults == 0 && n_kw_defaults == 0) {
Damien Georgef2040bf2021-10-22 22:22:47 +1100752 emit_write_bytecode_byte_child(emit, 1, MP_BC_MAKE_FUNCTION, scope->raw_code);
Damien Georgefb083ea2014-02-01 18:29:40 +0000753 } else {
Damien Georgef2040bf2021-10-22 22:22:47 +1100754 emit_write_bytecode_byte_child(emit, -1, MP_BC_MAKE_FUNCTION_DEFARGS, scope->raw_code);
Paul Sokolovsky90750022014-02-01 15:05:04 +0200755 }
Damien429d7192013-10-04 19:53:11 +0100756}
757
Damien George41125902015-03-26 16:44:14 +0000758void mp_emit_bc_make_closure(emit_t *emit, scope_t *scope, mp_uint_t n_closed_over, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults) {
Damien Georgee337f1e2014-03-31 15:18:37 +0100759 if (n_pos_defaults == 0 && n_kw_defaults == 0) {
Damien George8e7745e2019-08-22 14:55:16 +1000760 int stack_adj = -n_closed_over + 1;
Damien Georgef2040bf2021-10-22 22:22:47 +1100761 emit_write_bytecode_byte_child(emit, stack_adj, MP_BC_MAKE_CLOSURE, scope->raw_code);
Damien George8e7745e2019-08-22 14:55:16 +1000762 emit_write_bytecode_raw_byte(emit, n_closed_over);
Paul Sokolovsky2447a5b2014-03-26 23:14:59 +0200763 } else {
Damien George3558f622014-04-20 17:50:40 +0100764 assert(n_closed_over <= 255);
Damien George8e7745e2019-08-22 14:55:16 +1000765 int stack_adj = -2 - (mp_int_t)n_closed_over + 1;
Damien Georgef2040bf2021-10-22 22:22:47 +1100766 emit_write_bytecode_byte_child(emit, stack_adj, MP_BC_MAKE_CLOSURE_DEFARGS, scope->raw_code);
Damien George8e7745e2019-08-22 14:55:16 +1000767 emit_write_bytecode_raw_byte(emit, n_closed_over);
Paul Sokolovsky2447a5b2014-03-26 23:14:59 +0200768 }
Damien429d7192013-10-04 19:53:11 +0100769}
770
Angus Grattondecf8e62024-02-27 15:32:29 +1100771static void emit_bc_call_function_method_helper(emit_t *emit, int stack_adj, mp_uint_t bytecode_base, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) {
Damien George922ddd62014-04-09 12:43:17 +0100772 if (star_flags) {
David Lechner1e99d292020-03-24 21:39:46 -0500773 // each positional arg is one object, each kwarg is two objects, the key
774 // and the value and one extra object for the star args bitmap.
775 stack_adj -= (int)n_positional + 2 * (int)n_keyword + 1;
Damien George8e7745e2019-08-22 14:55:16 +1000776 emit_write_bytecode_byte_uint(emit, stack_adj, bytecode_base + 1, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints?
Damien429d7192013-10-04 19:53:11 +0100777 } else {
Damien George8e7745e2019-08-22 14:55:16 +1000778 stack_adj -= (int)n_positional + 2 * (int)n_keyword;
779 emit_write_bytecode_byte_uint(emit, stack_adj, bytecode_base, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints?
Damien429d7192013-10-04 19:53:11 +0100780 }
Damien George523b5752014-03-31 11:59:23 +0100781}
782
Damien George41125902015-03-26 16:44:14 +0000783void mp_emit_bc_call_function(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) {
Damien George922ddd62014-04-09 12:43:17 +0100784 emit_bc_call_function_method_helper(emit, 0, MP_BC_CALL_FUNCTION, n_positional, n_keyword, star_flags);
Damien429d7192013-10-04 19:53:11 +0100785}
786
Damien George41125902015-03-26 16:44:14 +0000787void mp_emit_bc_call_method(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) {
Damien George922ddd62014-04-09 12:43:17 +0100788 emit_bc_call_function_method_helper(emit, -1, MP_BC_CALL_METHOD, n_positional, n_keyword, star_flags);
Damien429d7192013-10-04 19:53:11 +0100789}
790
Damien George41125902015-03-26 16:44:14 +0000791void mp_emit_bc_return_value(emit_t *emit) {
Damien George8e7745e2019-08-22 14:55:16 +1000792 emit_write_bytecode_byte(emit, -1, MP_BC_RETURN_VALUE);
Damien Georgea5063352022-06-17 23:14:32 +1000793 emit->suppress = true;
Damien429d7192013-10-04 19:53:11 +0100794}
795
Damien George41125902015-03-26 16:44:14 +0000796void mp_emit_bc_raise_varargs(emit_t *emit, mp_uint_t n_args) {
Damien George02db91a2019-08-22 12:39:07 +1000797 MP_STATIC_ASSERT(MP_BC_RAISE_LAST + 1 == MP_BC_RAISE_OBJ);
798 MP_STATIC_ASSERT(MP_BC_RAISE_LAST + 2 == MP_BC_RAISE_FROM);
Pavol Rusnak7ffc9592016-10-25 11:05:33 +0200799 assert(n_args <= 2);
Damien George02db91a2019-08-22 12:39:07 +1000800 emit_write_bytecode_byte(emit, -n_args, MP_BC_RAISE_LAST + n_args);
Damien Georgea5063352022-06-17 23:14:32 +1000801 emit->suppress = true;
Damien429d7192013-10-04 19:53:11 +0100802}
803
Damien Georgee686c942018-05-19 00:30:42 +1000804void mp_emit_bc_yield(emit_t *emit, int kind) {
805 MP_STATIC_ASSERT(MP_BC_YIELD_VALUE + 1 == MP_BC_YIELD_FROM);
Damien George8e7745e2019-08-22 14:55:16 +1000806 emit_write_bytecode_byte(emit, -kind, MP_BC_YIELD_VALUE + kind);
Damien George36db6bc2014-05-07 17:24:22 +0100807 emit->scope->scope_flags |= MP_SCOPE_FLAG_GENERATOR;
Damien429d7192013-10-04 19:53:11 +0100808}
809
Damien George41125902015-03-26 16:44:14 +0000810void mp_emit_bc_start_except_handler(emit_t *emit) {
Damien Georgef0406852016-09-27 12:37:21 +1000811 mp_emit_bc_adjust_stack_size(emit, 4); // stack adjust for the exception instance, +3 for possible UNWIND_JUMP state
Damien Georgeb601d952014-06-30 05:17:25 +0100812}
813
Damien George41125902015-03-26 16:44:14 +0000814void mp_emit_bc_end_except_handler(emit_t *emit) {
Damien Georgef0406852016-09-27 12:37:21 +1000815 mp_emit_bc_adjust_stack_size(emit, -3); // stack adjust
Damien Georgeb601d952014-06-30 05:17:25 +0100816}
817
Damien George41125902015-03-26 16:44:14 +0000818#if MICROPY_EMIT_NATIVE
Damien6cdd3af2013-10-05 18:08:26 +0100819const emit_method_table_t emit_bc_method_table = {
Damien Georged9d92f22019-03-09 10:59:25 +1100820 #if MICROPY_DYNAMIC_COMPILER
821 NULL,
822 NULL,
823 #endif
824
Damien George41125902015-03-26 16:44:14 +0000825 mp_emit_bc_start_pass,
826 mp_emit_bc_end_pass,
Damien George41125902015-03-26 16:44:14 +0000827 mp_emit_bc_adjust_stack_size,
828 mp_emit_bc_set_source_line,
Damien415eb6f2013-10-05 12:19:06 +0100829
Damien George542bd6b2015-03-26 14:42:40 +0000830 {
Damien George0a25fff2018-05-19 00:11:04 +1000831 mp_emit_bc_load_local,
Damien George41125902015-03-26 16:44:14 +0000832 mp_emit_bc_load_global,
Damien George542bd6b2015-03-26 14:42:40 +0000833 },
834 {
Damien George0a25fff2018-05-19 00:11:04 +1000835 mp_emit_bc_store_local,
Damien George41125902015-03-26 16:44:14 +0000836 mp_emit_bc_store_global,
Damien George542bd6b2015-03-26 14:42:40 +0000837 },
838 {
Damien George0a25fff2018-05-19 00:11:04 +1000839 mp_emit_bc_delete_local,
Damien George41125902015-03-26 16:44:14 +0000840 mp_emit_bc_delete_global,
Damien George542bd6b2015-03-26 14:42:40 +0000841 },
Damien4b03e772013-10-05 14:17:09 +0100842
Damien George41125902015-03-26 16:44:14 +0000843 mp_emit_bc_label_assign,
Damien Georged97906c2018-05-22 21:58:25 +1000844 mp_emit_bc_import,
Damien George41125902015-03-26 16:44:14 +0000845 mp_emit_bc_load_const_tok,
846 mp_emit_bc_load_const_small_int,
847 mp_emit_bc_load_const_str,
848 mp_emit_bc_load_const_obj,
849 mp_emit_bc_load_null,
Damien George41125902015-03-26 16:44:14 +0000850 mp_emit_bc_load_method,
851 mp_emit_bc_load_build_class,
Damien Georgea4941a82018-05-22 21:31:56 +1000852 mp_emit_bc_subscr,
Damien George6211d972018-05-22 21:43:41 +1000853 mp_emit_bc_attr,
Damien George41125902015-03-26 16:44:14 +0000854 mp_emit_bc_dup_top,
855 mp_emit_bc_dup_top_two,
856 mp_emit_bc_pop_top,
857 mp_emit_bc_rot_two,
858 mp_emit_bc_rot_three,
859 mp_emit_bc_jump,
860 mp_emit_bc_pop_jump_if,
861 mp_emit_bc_jump_if_or_pop,
862 mp_emit_bc_unwind_jump,
Damien George18e63582018-05-22 22:33:26 +1000863 mp_emit_bc_setup_block,
Damien George41125902015-03-26 16:44:14 +0000864 mp_emit_bc_with_cleanup,
Damien George41125902015-03-26 16:44:14 +0000865 mp_emit_bc_end_finally,
866 mp_emit_bc_get_iter,
867 mp_emit_bc_for_iter,
868 mp_emit_bc_for_iter_end,
Damien George5a2599d2019-02-15 12:18:59 +1100869 mp_emit_bc_pop_except_jump,
Damien George41125902015-03-26 16:44:14 +0000870 mp_emit_bc_unary_op,
871 mp_emit_bc_binary_op,
Damien George26b57542018-05-19 00:41:40 +1000872 mp_emit_bc_build,
Damien George41125902015-03-26 16:44:14 +0000873 mp_emit_bc_store_map,
Damien Georgea5624bf2016-09-18 23:59:47 +1000874 mp_emit_bc_store_comp,
Damien George41125902015-03-26 16:44:14 +0000875 mp_emit_bc_unpack_sequence,
876 mp_emit_bc_unpack_ex,
877 mp_emit_bc_make_function,
878 mp_emit_bc_make_closure,
879 mp_emit_bc_call_function,
880 mp_emit_bc_call_method,
881 mp_emit_bc_return_value,
882 mp_emit_bc_raise_varargs,
Damien Georgee686c942018-05-19 00:30:42 +1000883 mp_emit_bc_yield,
Damien Georgeb601d952014-06-30 05:17:25 +0100884
Damien George41125902015-03-26 16:44:14 +0000885 mp_emit_bc_start_except_handler,
886 mp_emit_bc_end_except_handler,
Damien415eb6f2013-10-05 12:19:06 +0100887};
Damien George41125902015-03-26 16:44:14 +0000888#else
889const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_load_id_ops = {
Damien George0a25fff2018-05-19 00:11:04 +1000890 mp_emit_bc_load_local,
Damien George41125902015-03-26 16:44:14 +0000891 mp_emit_bc_load_global,
892};
893
894const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_store_id_ops = {
Damien George0a25fff2018-05-19 00:11:04 +1000895 mp_emit_bc_store_local,
Damien George41125902015-03-26 16:44:14 +0000896 mp_emit_bc_store_global,
897};
898
899const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_delete_id_ops = {
Damien George0a25fff2018-05-19 00:11:04 +1000900 mp_emit_bc_delete_local,
Damien George41125902015-03-26 16:44:14 +0000901 mp_emit_bc_delete_global,
902};
903#endif
Damien Georgedd5353a2015-12-18 12:35:44 +0000904
stijn84fa3312020-04-16 09:13:57 +0200905#endif // MICROPY_ENABLE_COMPILER