emitbc.c 35.7 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
 * This file is part of the Micro Python project, http://micropython.org/
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2013, 2014 Damien P. George
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

xbe's avatar
xbe committed
27
#include <stdbool.h>
Damien's avatar
Damien committed
28
29
30
31
32
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>

33
#include "py/mpstate.h"
34
35
#include "py/emit.h"
#include "py/bc0.h"
Damien's avatar
Damien committed
36

37
38
39
#define BYTES_FOR_INT ((BYTES_PER_WORD * 8 + 6) / 7)
#define DUMMY_DATA_SIZE (BYTES_FOR_INT)

40
struct _emit_t {
41
    pass_kind_t pass : 8;
42
    mp_uint_t last_emit_was_return_value : 8;
43

Damien's avatar
Damien committed
44
45
46
47
    int stack_size;

    scope_t *scope;

48
49
    mp_uint_t last_source_line_offset;
    mp_uint_t last_source_line;
50

51
52
    mp_uint_t max_num_labels;
    mp_uint_t *label_offsets;
Damien's avatar
Damien committed
53

54
55
56
57
    mp_uint_t code_info_offset;
    mp_uint_t code_info_size;
    mp_uint_t bytecode_offset;
    mp_uint_t bytecode_size;
58
    byte *code_base; // stores both byte code and code info
59
60
61
62
63
64

    #if MICROPY_PERSISTENT_CODE
    uint16_t ct_cur_obj;
    uint16_t ct_num_obj;
    uint16_t ct_cur_raw_code;
    #endif
65
    mp_uint_t *const_table;
66

67
    // Accessed as mp_uint_t, so must be aligned as such
68
    byte dummy_data[DUMMY_DATA_SIZE];
Damien's avatar
Damien committed
69
70
};

71
emit_t *emit_bc_new(void) {
72
    emit_t *emit = m_new0(emit_t, 1);
73
74
75
    return emit;
}

76
void emit_bc_set_max_num_labels(emit_t *emit, mp_uint_t max_num_labels) {
77
    emit->max_num_labels = max_num_labels;
78
    emit->label_offsets = m_new(mp_uint_t, emit->max_num_labels);
79
}
80

81
void emit_bc_free(emit_t *emit) {
82
    m_del(mp_uint_t, emit->label_offsets, emit->max_num_labels);
83
84
85
    m_del_obj(emit_t, emit);
}

86
87
88
typedef byte *(*emit_allocator_t)(emit_t *emit, int nbytes);

STATIC void emit_write_uint(emit_t *emit, emit_allocator_t allocator, mp_uint_t val) {
89
90
91
92
93
94
95
96
    // We store each 7 bits in a separate byte, and that's how many bytes needed
    byte buf[BYTES_FOR_INT];
    byte *p = buf + sizeof(buf);
    // We encode in little-ending order, but store in big-endian, to help decoding
    do {
        *--p = val & 0x7f;
        val >>= 7;
    } while (val != 0);
97
    byte *c = allocator(emit, buf + sizeof(buf) - p);
98
99
100
101
102
103
    while (p != buf + sizeof(buf) - 1) {
        *c++ = *p++ | 0x80;
    }
    *c = *p;
}

104
// all functions must go through this one to emit code info
105
STATIC byte *emit_get_cur_to_write_code_info(emit_t *emit, int num_bytes_to_write) {
106
    //printf("emit %d\n", num_bytes_to_write);
107
    if (emit->pass < MP_PASS_EMIT) {
108
109
110
111
112
113
114
115
        emit->code_info_offset += num_bytes_to_write;
        return emit->dummy_data;
    } else {
        assert(emit->code_info_offset + num_bytes_to_write <= emit->code_info_size);
        byte *c = emit->code_base + emit->code_info_offset;
        emit->code_info_offset += num_bytes_to_write;
        return c;
    }
Damien's avatar
Damien committed
116
117
}

118
119
120
121
122
STATIC void emit_write_code_info_byte(emit_t* emit, byte val) {
    *emit_get_cur_to_write_code_info(emit, 1) = val;
}

STATIC void emit_write_code_info_uint(emit_t* emit, mp_uint_t val) {
123
124
125
    emit_write_uint(emit, emit_get_cur_to_write_code_info, val);
}

126
STATIC void emit_write_code_info_qstr(emit_t *emit, qstr qst) {
127
128
129
130
131
132
    #if MICROPY_PERSISTENT_CODE
    assert((qst >> 16) == 0);
    byte *c = emit_get_cur_to_write_code_info(emit, 2);
    c[0] = qst;
    c[1] = qst >> 8;
    #else
133
    emit_write_uint(emit, emit_get_cur_to_write_code_info, qst);
134
    #endif
Damien's avatar
Damien committed
135
136
}

137
#if MICROPY_ENABLE_SOURCE_LINE
138
STATIC void emit_write_code_info_bytes_lines(emit_t *emit, mp_uint_t bytes_to_skip, mp_uint_t lines_to_skip) {
139
    assert(bytes_to_skip > 0 || lines_to_skip > 0);
140
    //printf("  %d %d\n", bytes_to_skip, lines_to_skip);
141
    while (bytes_to_skip > 0 || lines_to_skip > 0) {
142
143
144
145
146
147
148
149
150
151
152
153
154
155
        mp_uint_t b, l;
        if (lines_to_skip <= 6) {
            // use 0b0LLBBBBB encoding
            b = MIN(bytes_to_skip, 0x1f);
            l = MIN(lines_to_skip, 0x3);
            *emit_get_cur_to_write_code_info(emit, 1) = b | (l << 5);
        } else {
            // use 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)
            b = MIN(bytes_to_skip, 0xf);
            l = MIN(lines_to_skip, 0x7ff);
            byte *ci = emit_get_cur_to_write_code_info(emit, 2);
            ci[0] = 0x80 | b | ((l >> 4) & 0x70);
            ci[1] = l;
        }
156
157
        bytes_to_skip -= b;
        lines_to_skip -= l;
158
    }
159
}
160
#endif
161
162

// all functions must go through this one to emit byte code
163
STATIC byte *emit_get_cur_to_write_bytecode(emit_t *emit, int num_bytes_to_write) {
Damien's avatar
Damien committed
164
    //printf("emit %d\n", num_bytes_to_write);
165
    if (emit->pass < MP_PASS_EMIT) {
166
        emit->bytecode_offset += num_bytes_to_write;
Damien's avatar
Damien committed
167
168
        return emit->dummy_data;
    } else {
169
170
171
        assert(emit->bytecode_offset + num_bytes_to_write <= emit->bytecode_size);
        byte *c = emit->code_base + emit->code_info_size + emit->bytecode_offset;
        emit->bytecode_offset += num_bytes_to_write;
Damien's avatar
Damien committed
172
173
174
175
        return c;
    }
}

176
177
STATIC void emit_write_bytecode_byte(emit_t *emit, byte b1) {
    byte *c = emit_get_cur_to_write_bytecode(emit, 1);
Damien's avatar
Damien committed
178
179
180
    c[0] = b1;
}

181
STATIC void emit_write_bytecode_byte_byte(emit_t* emit, byte b1, byte b2) {
Damien's avatar
Damien committed
182
    assert((b2 & (~0xff)) == 0);
183
    byte *c = emit_get_cur_to_write_bytecode(emit, 2);
Damien's avatar
Damien committed
184
185
186
187
    c[0] = b1;
    c[1] = b2;
}

188
// Similar to emit_write_bytecode_uint(), just some extra handling to encode sign
189
STATIC void emit_write_bytecode_byte_int(emit_t *emit, byte b1, mp_int_t num) {
190
    emit_write_bytecode_byte(emit, b1);
191
192

    // We store each 7 bits in a separate byte, and that's how many bytes needed
193
    byte buf[BYTES_FOR_INT];
194
195
196
197
198
199
200
201
202
203
204
205
206
207
    byte *p = buf + sizeof(buf);
    // We encode in little-ending order, but store in big-endian, to help decoding
    do {
        *--p = num & 0x7f;
        num >>= 7;
    } while (num != 0 && num != -1);
    // Make sure that highest bit we stored (mask 0x40) matches sign
    // of the number. If not, store extra byte just to encode sign
    if (num == -1 && (*p & 0x40) == 0) {
        *--p = 0x7f;
    } else if (num == 0 && (*p & 0x40) != 0) {
        *--p = 0;
    }

208
    byte *c = emit_get_cur_to_write_bytecode(emit, buf + sizeof(buf) - p);
209
210
211
212
    while (p != buf + sizeof(buf) - 1) {
        *c++ = *p++ | 0x80;
    }
    *c = *p;
Damien's avatar
Damien committed
213
214
}

215
STATIC void emit_write_bytecode_byte_uint(emit_t *emit, byte b, mp_uint_t val) {
216
    emit_write_bytecode_byte(emit, b);
217
    emit_write_uint(emit, emit_get_cur_to_write_bytecode, val);
Damien's avatar
Damien committed
218
219
}

220
221
222
223
224
225
226
227
#if MICROPY_PERSISTENT_CODE
STATIC void emit_write_bytecode_byte_const(emit_t *emit, byte b, mp_uint_t n, mp_uint_t c) {
    if (emit->pass == MP_PASS_EMIT) {
        emit->const_table[n] = c;
    }
    emit_write_bytecode_byte_uint(emit, b, n);
}
#else
228
STATIC void emit_write_bytecode_byte_ptr(emit_t *emit, byte b, void *ptr) {
229
    // aligns the pointer so it is friendly to GC
230
    emit_write_bytecode_byte(emit, b);
231
    emit->bytecode_offset = (mp_uint_t)MP_ALIGN(emit->bytecode_offset, sizeof(mp_uint_t));
232
    mp_uint_t *c = (mp_uint_t*)emit_get_cur_to_write_bytecode(emit, sizeof(mp_uint_t));
233
234
    // Verify thar c is already uint-aligned
    assert(c == MP_ALIGN(c, sizeof(mp_uint_t)));
235
    *c = (mp_uint_t)ptr;
236
}
237
#endif
238

239
STATIC void emit_write_bytecode_byte_qstr(emit_t* emit, byte b, qstr qst) {
240
241
242
243
244
245
246
    #if MICROPY_PERSISTENT_CODE
    assert((qst >> 16) == 0);
    byte *c = emit_get_cur_to_write_bytecode(emit, 3);
    c[0] = b;
    c[1] = qst;
    c[2] = qst >> 8;
    #else
247
    emit_write_bytecode_byte_uint(emit, b, qst);
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
    #endif
}

STATIC void emit_write_bytecode_byte_obj(emit_t *emit, byte b, void *ptr) {
    #if MICROPY_PERSISTENT_CODE
    emit_write_bytecode_byte_const(emit, b,
        emit->scope->num_pos_args + emit->scope->num_kwonly_args
        + emit->ct_cur_obj++, (mp_uint_t)ptr);
    #else
    emit_write_bytecode_byte_ptr(emit, b, ptr);
    #endif
}

STATIC void emit_write_bytecode_byte_raw_code(emit_t *emit, byte b, mp_raw_code_t *rc) {
    #if MICROPY_PERSISTENT_CODE
    emit_write_bytecode_byte_const(emit, b,
        emit->scope->num_pos_args + emit->scope->num_kwonly_args
        + emit->ct_num_obj + emit->ct_cur_raw_code++, (mp_uint_t)rc);
    #else
    emit_write_bytecode_byte_ptr(emit, b, rc);
    #endif
Damien's avatar
Damien committed
269
270
}

Damien's avatar
Damien committed
271
// unsigned labels are relative to ip following this instruction, stored as 16 bits
272
STATIC void emit_write_bytecode_byte_unsigned_label(emit_t *emit, byte b1, mp_uint_t label) {
273
    mp_uint_t bytecode_offset;
274
    if (emit->pass < MP_PASS_EMIT) {
275
        bytecode_offset = 0;
Damien's avatar
Damien committed
276
    } else {
277
        bytecode_offset = emit->label_offsets[label] - emit->bytecode_offset - 3;
Damien's avatar
Damien committed
278
    }
279
    byte *c = emit_get_cur_to_write_bytecode(emit, 3);
Damien's avatar
Damien committed
280
    c[0] = b1;
281
282
    c[1] = bytecode_offset;
    c[2] = bytecode_offset >> 8;
Damien's avatar
Damien committed
283
284
285
}

// signed labels are relative to ip following this instruction, stored as 16 bits, in excess
286
STATIC void emit_write_bytecode_byte_signed_label(emit_t *emit, byte b1, mp_uint_t label) {
287
    int bytecode_offset;
288
    if (emit->pass < MP_PASS_EMIT) {
289
        bytecode_offset = 0;
Damien's avatar
Damien committed
290
    } else {
291
        bytecode_offset = emit->label_offsets[label] - emit->bytecode_offset - 3 + 0x8000;
Damien's avatar
Damien committed
292
    }
293
    byte *c = emit_get_cur_to_write_bytecode(emit, 3);
Damien's avatar
Damien committed
294
    c[0] = b1;
295
296
    c[1] = bytecode_offset;
    c[2] = bytecode_offset >> 8;
Damien's avatar
Damien committed
297
298
}

299
300
#if MICROPY_EMIT_NATIVE
STATIC void mp_emit_bc_set_native_type(emit_t *emit, mp_uint_t op, mp_uint_t arg1, qstr arg2) {
301
302
303
304
    (void)emit;
    (void)op;
    (void)arg1;
    (void)arg2;
Damien George's avatar
Damien George committed
305
}
306
#endif
Damien George's avatar
Damien George committed
307

308
void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
Damien George's avatar
Damien George committed
309
310
311
312
    emit->pass = pass;
    emit->stack_size = 0;
    emit->last_emit_was_return_value = false;
    emit->scope = scope;
313
314
    emit->last_source_line_offset = 0;
    emit->last_source_line = 1;
315
    if (pass < MP_PASS_EMIT) {
316
        memset(emit->label_offsets, -1, emit->max_num_labels * sizeof(mp_uint_t));
Damien George's avatar
Damien George committed
317
    }
318
    emit->bytecode_offset = 0;
319
320
    emit->code_info_offset = 0;

321
322
323
324
325
326
327
328
329
330
331
    // Write local state size and exception stack size.
    {
        mp_uint_t n_state = scope->num_locals + scope->stack_size;
        if (n_state == 0) {
            // Need at least 1 entry in the state, in the case an exception is
            // propagated through this function, the exception is returned in
            // the highest slot in the state (fastn[0], see vm.c).
            n_state = 1;
        }
        emit_write_code_info_uint(emit, n_state);
        emit_write_code_info_uint(emit, scope->exc_stack_size);
332
333
    }

334
335
336
337
338
339
340
    // Write scope flags and number of arguments.
    // TODO check that num args all fit in a byte
    emit_write_code_info_byte(emit, emit->scope->scope_flags);
    emit_write_code_info_byte(emit, emit->scope->num_pos_args);
    emit_write_code_info_byte(emit, emit->scope->num_kwonly_args);
    emit_write_code_info_byte(emit, emit->scope->num_def_pos_args);

341
342
343
344
345
346
347
    // Write size of the rest of the code info.  We don't know how big this
    // variable uint will be on the MP_PASS_CODE_SIZE pass so we reserve 2 bytes
    // for it and hope that is enough!  TODO assert this or something.
    if (pass == MP_PASS_EMIT) {
        emit_write_code_info_uint(emit, emit->code_info_size - emit->code_info_offset);
    } else  {
        emit_get_cur_to_write_code_info(emit, 2);
348
349
    }

350
351
352
353
    // Write the name and source file of this function.
    emit_write_code_info_qstr(emit, scope->simple_name);
    emit_write_code_info_qstr(emit, scope->source_file);

354
    // bytecode prelude: initialise closed over variables
Damien George's avatar
Damien George committed
355
356
357
    for (int i = 0; i < scope->id_info_len; i++) {
        id_info_t *id = &scope->id_info[i];
        if (id->kind == ID_INFO_KIND_CELL) {
358
            assert(id->local_num < 255);
359
            emit_write_bytecode_byte(emit, id->local_num); // write the local which should be converted to a cell
Damien George's avatar
Damien George committed
360
361
        }
    }
362
    emit_write_bytecode_byte(emit, 255); // end of list sentinel
363

364
365
366
367
368
    #if MICROPY_PERSISTENT_CODE
    emit->ct_cur_obj = 0;
    emit->ct_cur_raw_code = 0;
    #endif

369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
    if (pass == MP_PASS_EMIT) {
        // Write argument names (needed to resolve positional args passed as
        // keywords).  We store them as full word-sized objects for efficient access
        // in mp_setup_code_state this is the start of the prelude and is guaranteed
        // to be aligned on a word boundary.

        // For a given argument position (indexed by i) we need to find the
        // corresponding id_info which is a parameter, as it has the correct
        // qstr name to use as the argument name.  Note that it's not a simple
        // 1-1 mapping (ie i!=j in general) because of possible closed-over
        // variables.  In the case that the argument i has no corresponding
        // parameter we use "*" as its name (since no argument can ever be named
        // "*").  We could use a blank qstr but "*" is better for debugging.
        // Note: there is some wasted RAM here for the case of storing a qstr
        // for each closed-over variable, and maybe there is a better way to do
        // it, but that would require changes to mp_setup_code_state.
        for (int i = 0; i < scope->num_pos_args + scope->num_kwonly_args; i++) {
            qstr qst = MP_QSTR__star_;
            for (int j = 0; j < scope->id_info_len; ++j) {
                id_info_t *id = &scope->id_info[j];
                if ((id->flags & ID_FLAG_IS_PARAM) && id->local_num == i) {
                    qst = id->qst;
                    break;
                }
            }
            emit->const_table[i] = (mp_uint_t)MP_OBJ_NEW_QSTR(qst);
        }
    }
Damien George's avatar
Damien George committed
397
398
}

399
void mp_emit_bc_end_pass(emit_t *emit) {
400
401
402
403
    if (emit->pass == MP_PASS_SCOPE) {
        return;
    }

Damien George's avatar
Damien George committed
404
405
    // check stack is back to zero size
    if (emit->stack_size != 0) {
406
        mp_printf(&mp_plat_print, "ERROR: stack size not back to zero; got %d\n", emit->stack_size);
Damien George's avatar
Damien George committed
407
408
    }

409
    emit_write_code_info_byte(emit, 0); // end of line number info
410

411
412
413
414
415
    #if MICROPY_PERSISTENT_CODE
    assert(emit->pass <= MP_PASS_STACK_SIZE || (emit->ct_num_obj == emit->ct_cur_obj));
    emit->ct_num_obj = emit->ct_cur_obj;
    #endif

416
    if (emit->pass == MP_PASS_CODE_SIZE) {
417
        #if !MICROPY_PERSISTENT_CODE
418
        // so bytecode is aligned
419
420
        emit->code_info_offset = (mp_uint_t)MP_ALIGN(emit->code_info_offset, sizeof(mp_uint_t));
        #endif
421
422

        // calculate size of total code-info + bytecode, in bytes
423
        emit->code_info_size = emit->code_info_offset;
424
425
        emit->bytecode_size = emit->bytecode_offset;
        emit->code_base = m_new0(byte, emit->code_info_size + emit->bytecode_size);
Damien George's avatar
Damien George committed
426

427
428
429
430
431
432
433
434
        #if MICROPY_PERSISTENT_CODE
        emit->const_table = m_new0(mp_uint_t,
            emit->scope->num_pos_args + emit->scope->num_kwonly_args
            + emit->ct_cur_obj + emit->ct_cur_raw_code);
        #else
        emit->const_table = m_new0(mp_uint_t,
            emit->scope->num_pos_args + emit->scope->num_kwonly_args);
        #endif
435

436
    } else if (emit->pass == MP_PASS_EMIT) {
437
        mp_emit_glue_assign_bytecode(emit->scope->raw_code, emit->code_base,
438
            emit->code_info_size + emit->bytecode_size,
439
440
441
442
443
            emit->const_table,
            #if MICROPY_PERSISTENT_CODE_SAVE
            emit->ct_cur_obj, emit->ct_cur_raw_code,
            #endif
            emit->scope->scope_flags);
Damien George's avatar
Damien George committed
444
445
446
    }
}

447
bool mp_emit_bc_last_emit_was_return_value(emit_t *emit) {
Damien's avatar
Damien committed
448
449
450
    return emit->last_emit_was_return_value;
}

451
void mp_emit_bc_adjust_stack_size(emit_t *emit, mp_int_t delta) {
452
    emit->stack_size += delta;
Damien's avatar
Damien committed
453
454
}

455
void mp_emit_bc_set_source_line(emit_t *emit, mp_uint_t source_line) {
456
    //printf("source: line %d -> %d  offset %d -> %d\n", emit->last_source_line, source_line, emit->last_source_line_offset, emit->bytecode_offset);
457
#if MICROPY_ENABLE_SOURCE_LINE
458
    if (MP_STATE_VM(mp_optimise_value) >= 3) {
459
460
461
        // If we compile with -O3, don't store line numbers.
        return;
    }
462
    if (source_line > emit->last_source_line) {
463
464
        mp_uint_t bytes_to_skip = emit->bytecode_offset - emit->last_source_line_offset;
        mp_uint_t lines_to_skip = source_line - emit->last_source_line;
465
        emit_write_code_info_bytes_lines(emit, bytes_to_skip, lines_to_skip);
466
        emit->last_source_line_offset = emit->bytecode_offset;
467
468
        emit->last_source_line = source_line;
    }
469
470
471
#else
    (void)emit;
    (void)source_line;
472
#endif
473
474
}

475
STATIC void emit_bc_pre(emit_t *emit, mp_int_t stack_size_delta) {
476
477
478
    if (emit->pass == MP_PASS_SCOPE) {
        return;
    }
479
    assert((mp_int_t)emit->stack_size + stack_size_delta >= 0);
480
481
482
    emit->stack_size += stack_size_delta;
    if (emit->stack_size > emit->scope->stack_size) {
        emit->scope->stack_size = emit->stack_size;
Damien's avatar
Damien committed
483
484
485
486
    }
    emit->last_emit_was_return_value = false;
}

487
void mp_emit_bc_label_assign(emit_t *emit, mp_uint_t l) {
488
    emit_bc_pre(emit, 0);
489
490
491
    if (emit->pass == MP_PASS_SCOPE) {
        return;
    }
492
    assert(l < emit->max_num_labels);
493
    if (emit->pass < MP_PASS_EMIT) {
494
        // assign label offset
495
        assert(emit->label_offsets[l] == (mp_uint_t)-1);
496
        emit->label_offsets[l] = emit->bytecode_offset;
497
498
    } else {
        // ensure label offset has not changed from MP_PASS_CODE_SIZE to MP_PASS_EMIT
499
500
        //printf("l%d: (at %d vs %d)\n", l, emit->bytecode_offset, emit->label_offsets[l]);
        assert(emit->label_offsets[l] == emit->bytecode_offset);
Damien's avatar
Damien committed
501
502
503
    }
}

504
void mp_emit_bc_import_name(emit_t *emit, qstr qst) {
505
    emit_bc_pre(emit, -1);
506
    emit_write_bytecode_byte_qstr(emit, MP_BC_IMPORT_NAME, qst);
Damien's avatar
Damien committed
507
508
}

509
void mp_emit_bc_import_from(emit_t *emit, qstr qst) {
510
    emit_bc_pre(emit, 1);
511
    emit_write_bytecode_byte_qstr(emit, MP_BC_IMPORT_FROM, qst);
Damien's avatar
Damien committed
512
513
}

514
void mp_emit_bc_import_star(emit_t *emit) {
515
    emit_bc_pre(emit, -1);
516
    emit_write_bytecode_byte(emit, MP_BC_IMPORT_STAR);
Damien's avatar
Damien committed
517
518
}

519
void mp_emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
520
    emit_bc_pre(emit, 1);
Damien's avatar
Damien committed
521
    switch (tok) {
522
523
524
        case MP_TOKEN_KW_FALSE: emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_FALSE); break;
        case MP_TOKEN_KW_NONE: emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_NONE); break;
        case MP_TOKEN_KW_TRUE: emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_TRUE); break;
525
        no_other_choice:
526
        case MP_TOKEN_ELLIPSIS: emit_write_bytecode_byte_obj(emit, MP_BC_LOAD_CONST_OBJ, (void*)&mp_const_ellipsis_obj); break;
527
        default: assert(0); goto no_other_choice; // to help flow control analysis
Damien's avatar
Damien committed
528
529
530
    }
}

531
void mp_emit_bc_load_const_small_int(emit_t *emit, mp_int_t arg) {
532
    emit_bc_pre(emit, 1);
533
534
535
536
537
    if (-16 <= arg && arg <= 47) {
        emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_SMALL_INT_MULTI + 16 + arg);
    } else {
        emit_write_bytecode_byte_int(emit, MP_BC_LOAD_CONST_SMALL_INT, arg);
    }
Damien's avatar
Damien committed
538
539
}

540
void mp_emit_bc_load_const_str(emit_t *emit, qstr qst) {
541
    emit_bc_pre(emit, 1);
542
    emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_CONST_STRING, qst);
Damien's avatar
Damien committed
543
544
}

545
void mp_emit_bc_load_const_obj(emit_t *emit, mp_obj_t obj) {
546
    emit_bc_pre(emit, 1);
547
    emit_write_bytecode_byte_obj(emit, MP_BC_LOAD_CONST_OBJ, obj);
548
549
}

550
void mp_emit_bc_load_null(emit_t *emit) {
551
    emit_bc_pre(emit, 1);
552
    emit_write_bytecode_byte(emit, MP_BC_LOAD_NULL);
553
554
};

555
void mp_emit_bc_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {
556
    (void)qst;
Damien's avatar
Damien committed
557
    assert(local_num >= 0);
558
    emit_bc_pre(emit, 1);
559
560
561
562
    if (local_num <= 15) {
        emit_write_bytecode_byte(emit, MP_BC_LOAD_FAST_MULTI + local_num);
    } else {
        emit_write_bytecode_byte_uint(emit, MP_BC_LOAD_FAST_N, local_num);
Damien's avatar
Damien committed
563
564
565
    }
}

566
void mp_emit_bc_load_deref(emit_t *emit, qstr qst, mp_uint_t local_num) {
567
    (void)qst;
568
    emit_bc_pre(emit, 1);
569
    emit_write_bytecode_byte_uint(emit, MP_BC_LOAD_DEREF, local_num);
Damien's avatar
Damien committed
570
571
}

572
void mp_emit_bc_load_name(emit_t *emit, qstr qst) {
573
    (void)qst;
574
    emit_bc_pre(emit, 1);
575
    emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_NAME, qst);
576
577
578
    if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) {
        emit_write_bytecode_byte(emit, 0);
    }
Damien's avatar
Damien committed
579
580
}

581
void mp_emit_bc_load_global(emit_t *emit, qstr qst) {
582
    (void)qst;
583
    emit_bc_pre(emit, 1);
584
    emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_GLOBAL, qst);
585
586
587
    if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) {
        emit_write_bytecode_byte(emit, 0);
    }
Damien's avatar
Damien committed
588
589
}

590
void mp_emit_bc_load_attr(emit_t *emit, qstr qst) {
591
    emit_bc_pre(emit, 0);
592
    emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_ATTR, qst);
593
594
595
    if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) {
        emit_write_bytecode_byte(emit, 0);
    }
Damien's avatar
Damien committed
596
597
}

598
void mp_emit_bc_load_method(emit_t *emit, qstr qst) {
599
    emit_bc_pre(emit, 1);
600
    emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_METHOD, qst);
Damien's avatar
Damien committed
601
602
}

603
void mp_emit_bc_load_build_class(emit_t *emit) {
604
    emit_bc_pre(emit, 1);
605
    emit_write_bytecode_byte(emit, MP_BC_LOAD_BUILD_CLASS);
Damien's avatar
Damien committed
606
607
}

608
void mp_emit_bc_load_subscr(emit_t *emit) {
609
    emit_bc_pre(emit, -1);
610
    emit_write_bytecode_byte(emit, MP_BC_LOAD_SUBSCR);
611
612
}

613
void mp_emit_bc_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {
614
    (void)qst;
Damien's avatar
Damien committed
615
    assert(local_num >= 0);
616
    emit_bc_pre(emit, -1);
617
618
619
620
    if (local_num <= 15) {
        emit_write_bytecode_byte(emit, MP_BC_STORE_FAST_MULTI + local_num);
    } else {
        emit_write_bytecode_byte_uint(emit, MP_BC_STORE_FAST_N, local_num);
Damien's avatar
Damien committed
621
622
623
    }
}

624
void mp_emit_bc_store_deref(emit_t *emit, qstr qst, mp_uint_t local_num) {
625
    (void)qst;
626
    emit_bc_pre(emit, -1);
627
    emit_write_bytecode_byte_uint(emit, MP_BC_STORE_DEREF, local_num);
Damien's avatar
Damien committed
628
629
}

630
void mp_emit_bc_store_name(emit_t *emit, qstr qst) {
631
    emit_bc_pre(emit, -1);
632
    emit_write_bytecode_byte_qstr(emit, MP_BC_STORE_NAME, qst);
Damien's avatar
Damien committed
633
634
}

635
void mp_emit_bc_store_global(emit_t *emit, qstr qst) {
636
    emit_bc_pre(emit, -1);
637
    emit_write_bytecode_byte_qstr(emit, MP_BC_STORE_GLOBAL, qst);
Damien's avatar
Damien committed
638
639
}

640
void mp_emit_bc_store_attr(emit_t *emit, qstr qst) {
641
    emit_bc_pre(emit, -2);
642
    emit_write_bytecode_byte_qstr(emit, MP_BC_STORE_ATTR, qst);
643
644
645
    if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) {
        emit_write_bytecode_byte(emit, 0);
    }
Damien's avatar
Damien committed
646
647
}

648
void mp_emit_bc_store_subscr(emit_t *emit) {
649
    emit_bc_pre(emit, -3);
650
    emit_write_bytecode_byte(emit, MP_BC_STORE_SUBSCR);
Damien's avatar
Damien committed
651
652
}

653
void mp_emit_bc_delete_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {
654
    (void)qst;
655
    emit_write_bytecode_byte_uint(emit, MP_BC_DELETE_FAST, local_num);
Damien's avatar
Damien committed
656
657
}

658
void mp_emit_bc_delete_deref(emit_t *emit, qstr qst, mp_uint_t local_num) {
659
    (void)qst;
660
    emit_write_bytecode_byte_uint(emit, MP_BC_DELETE_DEREF, local_num);
Damien's avatar
Damien committed
661
662
}

663
void mp_emit_bc_delete_name(emit_t *emit, qstr qst) {
664
    emit_bc_pre(emit, 0);
665
    emit_write_bytecode_byte_qstr(emit, MP_BC_DELETE_NAME, qst);
Damien's avatar
Damien committed
666
667
}

668
void mp_emit_bc_delete_global(emit_t *emit, qstr qst) {
669
    emit_bc_pre(emit, 0);
670
    emit_write_bytecode_byte_qstr(emit, MP_BC_DELETE_GLOBAL, qst);
Damien's avatar
Damien committed
671
672
}

673
674
675
676
void mp_emit_bc_delete_attr(emit_t *emit, qstr qst) {
    mp_emit_bc_load_null(emit);
    mp_emit_bc_rot_two(emit);
    mp_emit_bc_store_attr(emit, qst);
Damien's avatar
Damien committed
677
678
}

679
680
681
682
void mp_emit_bc_delete_subscr(emit_t *emit) {
    mp_emit_bc_load_null(emit);
    mp_emit_bc_rot_three(emit);
    mp_emit_bc_store_subscr(emit);
Damien's avatar
Damien committed
683
684
}

685
void mp_emit_bc_dup_top(emit_t *emit) {
686
    emit_bc_pre(emit, 1);
687
    emit_write_bytecode_byte(emit, MP_BC_DUP_TOP);
Damien's avatar
Damien committed
688
689
}

690
void mp_emit_bc_dup_top_two(emit_t *emit) {
691
    emit_bc_pre(emit, 2);
692
    emit_write_bytecode_byte(emit, MP_BC_DUP_TOP_TWO);
Damien's avatar
Damien committed
693
694
}

695
void mp_emit_bc_pop_top(emit_t *emit) {
696
    emit_bc_pre(emit, -1);
697
    emit_write_bytecode_byte(emit, MP_BC_POP_TOP);
Damien's avatar
Damien committed
698
699
}

700
void mp_emit_bc_rot_two(emit_t *emit) {
701
    emit_bc_pre(emit, 0);
702
    emit_write_bytecode_byte(emit, MP_BC_ROT_TWO);
Damien's avatar
Damien committed
703
704
}

705
void mp_emit_bc_rot_three(emit_t *emit) {
706
    emit_bc_pre(emit, 0);
707
    emit_write_bytecode_byte(emit, MP_BC_ROT_THREE);
Damien's avatar
Damien committed
708
709
}

710
void mp_emit_bc_jump(emit_t *emit, mp_uint_t label) {
711
    emit_bc_pre(emit, 0);
712
    emit_write_bytecode_byte_signed_label(emit, MP_BC_JUMP, label);
Damien's avatar
Damien committed
713
714
}

715
void mp_emit_bc_pop_jump_if(emit_t *emit, bool cond, mp_uint_t label) {
716
    emit_bc_pre(emit, -1);
717
718
719
720
721
    if (cond) {
        emit_write_bytecode_byte_signed_label(emit, MP_BC_POP_JUMP_IF_TRUE, label);
    } else {
        emit_write_bytecode_byte_signed_label(emit, MP_BC_POP_JUMP_IF_FALSE, label);
    }
Damien's avatar
Damien committed
722
723
}

724
void mp_emit_bc_jump_if_or_pop(emit_t *emit, bool cond, mp_uint_t label) {
725
    emit_bc_pre(emit, -1);
726
727
728
729
730
    if (cond) {
        emit_write_bytecode_byte_signed_label(emit, MP_BC_JUMP_IF_TRUE_OR_POP, label);
    } else {
        emit_write_bytecode_byte_signed_label(emit, MP_BC_JUMP_IF_FALSE_OR_POP, label);
    }
Damien's avatar
Damien committed
731
732
}

733
void mp_emit_bc_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_depth) {
734
    if (except_depth == 0) {
735
        emit_bc_pre(emit, 0);
736
737
738
739
740
741
742
743
        if (label & MP_EMIT_BREAK_FROM_FOR) {
            // need to pop the iterator if we are breaking out of a for loop
            emit_write_bytecode_byte(emit, MP_BC_POP_TOP);
        }
        emit_write_bytecode_byte_signed_label(emit, MP_BC_JUMP, label & ~MP_EMIT_BREAK_FROM_FOR);
    } else {
        emit_write_bytecode_byte_signed_label(emit, MP_BC_UNWIND_JUMP, label & ~MP_EMIT_BREAK_FROM_FOR);
        emit_write_bytecode_byte(emit, ((label & MP_EMIT_BREAK_FROM_FOR) ? 0x80 : 0) | except_depth);
744
    }
Damien's avatar
Damien committed
745
746
}

747
void mp_emit_bc_setup_with(emit_t *emit, mp_uint_t label) {
748
749
750
751
    // TODO We can probably optimise the amount of needed stack space, since
    // we don't actually need 4 slots during the entire with block, only in
    // the cleanup handler in certain cases.  It needs some thinking.
    emit_bc_pre(emit, 4);
752
    emit_write_bytecode_byte_unsigned_label(emit, MP_BC_SETUP_WITH, label);
Damien's avatar
Damien committed
753
754
}

755
void mp_emit_bc_with_cleanup(emit_t *emit) {
756
    emit_bc_pre(emit, -4);
757
    emit_write_bytecode_byte(emit, MP_BC_WITH_CLEANUP);
Damien's avatar
Damien committed
758
759
}

760
void mp_emit_bc_setup_except(emit_t *emit, mp_uint_t label) {
761
    emit_bc_pre(emit, 0);
762
    emit_write_bytecode_byte_unsigned_label(emit, MP_BC_SETUP_EXCEPT, label);
Damien's avatar
Damien committed
763
764
}

765
void mp_emit_bc_setup_finally(emit_t *emit, mp_uint_t label) {
766
    emit_bc_pre(emit, 0);
767
    emit_write_bytecode_byte_unsigned_label(emit, MP_BC_SETUP_FINALLY, label);
Damien's avatar
Damien committed
768
769
}

770
void mp_emit_bc_end_finally(emit_t *emit) {
771
    emit_bc_pre(emit, -1);
772
    emit_write_bytecode_byte(emit, MP_BC_END_FINALLY);
Damien's avatar
Damien committed
773
774
}

775
void mp_emit_bc_get_iter(emit_t *emit) {
776
    emit_bc_pre(emit, 0);
777
    emit_write_bytecode_byte(emit, MP_BC_GET_ITER);
Damien's avatar
Damien committed
778
779
}

780
void mp_emit_bc_for_iter(emit_t *emit, mp_uint_t label) {
781
    emit_bc_pre(emit, 1);
782
    emit_write_bytecode_byte_unsigned_label(emit, MP_BC_FOR_ITER, label);
Damien's avatar
Damien committed
783
784
}

785
void mp_emit_bc_for_iter_end(emit_t *emit) {
786
    emit_bc_pre(emit, -1);
Damien's avatar
Damien committed
787
788
}

789
void mp_emit_bc_pop_block(emit_t *emit) {
790
    emit_bc_pre(emit, 0);
791
    emit_write_bytecode_byte(emit, MP_BC_POP_BLOCK);
Damien's avatar
Damien committed
792
793
}

794
void mp_emit_bc_pop_except(emit_t *emit) {
795
    emit_bc_pre(emit, 0);
796
    emit_write_bytecode_byte(emit, MP_BC_POP_EXCEPT);
Damien's avatar
Damien committed
797
798
}

799
void mp_emit_bc_unary_op(emit_t *emit, mp_unary_op_t op) {
Damien George's avatar
Damien George committed
800
    if (op == MP_UNARY_OP_NOT) {
801
        emit_bc_pre(emit, 0);
802
        emit_write_bytecode_byte(emit, MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_BOOL);
803
        emit_bc_pre(emit, 0);
804
        emit_write_bytecode_byte(emit, MP_BC_NOT);
805
    } else {
806
        emit_bc_pre(emit, 0);
807
        emit_write_bytecode_byte(emit, MP_BC_UNARY_OP_MULTI + op);
808
    }
Damien's avatar
Damien committed
809
810
}

811
void mp_emit_bc_binary_op(emit_t *emit, mp_binary_op_t op) {
812
    bool invert = false;
Damien George's avatar
Damien George committed
813
    if (op == MP_BINARY_OP_NOT_IN) {
814
        invert = true;
Damien George's avatar
Damien George committed
815
816
        op = MP_BINARY_OP_IN;
    } else if (op == MP_BINARY_OP_IS_NOT) {
817
        invert = true;
Damien George's avatar
Damien George committed
818
        op = MP_BINARY_OP_IS;
819
    }
820
    emit_bc_pre(emit, -1);
821
    emit_write_bytecode_byte(emit, MP_BC_BINARY_OP_MULTI + op);
822
    if (invert) {
823
        emit_bc_pre(emit, 0);
824
        emit_write_bytecode_byte(emit, MP_BC_NOT);
825
    }
Damien's avatar
Damien committed
826
827
}

828
void mp_emit_bc_build_tuple(emit_t *emit, mp_uint_t n_args) {
829
    emit_bc_pre(emit, 1 - n_args);
830
    emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_TUPLE, n_args);
Damien's avatar
Damien committed
831
832
}

833
void mp_emit_bc_build_list(emit_t *emit, mp_uint_t n_args) {
834
    emit_bc_pre(emit, 1 - n_args);
835
    emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_LIST, n_args);
Damien's avatar
Damien committed
836
837
}

838
void mp_emit_bc_list_append(emit_t *emit, mp_uint_t list_stack_index) {
839
    emit_bc_pre(emit, -1);
840
    emit_write_bytecode_byte_uint(emit, MP_BC_LIST_APPEND, list_stack_index);
Damien's avatar
Damien committed
841
842
}

843
void mp_emit_bc_build_map(emit_t *emit, mp_uint_t n_args) {
844
    emit_bc_pre(emit, 1);
845
    emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_MAP, n_args);
Damien's avatar
Damien committed
846
847
}

848
void mp_emit_bc_store_map(emit_t *emit) {
849
    emit_bc_pre(emit, -2);