emitbc.c 35.6 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
439
            emit->code_info_size + emit->bytecode_size,
            emit->const_table, emit->scope->scope_flags);
Damien George's avatar
Damien George committed
440
441
442
    }
}

443
bool mp_emit_bc_last_emit_was_return_value(emit_t *emit) {
Damien's avatar
Damien committed
444
445
446
    return emit->last_emit_was_return_value;
}

447
void mp_emit_bc_adjust_stack_size(emit_t *emit, mp_int_t delta) {
448
    emit->stack_size += delta;
Damien's avatar
Damien committed
449
450
}

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

471
STATIC void emit_bc_pre(emit_t *emit, mp_int_t stack_size_delta) {
472
473
474
    if (emit->pass == MP_PASS_SCOPE) {
        return;
    }
475
    assert((mp_int_t)emit->stack_size + stack_size_delta >= 0);
476
477
478
    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
479
480
481
482
    }
    emit->last_emit_was_return_value = false;
}

483
void mp_emit_bc_label_assign(emit_t *emit, mp_uint_t l) {
484
    emit_bc_pre(emit, 0);
485
486
487
    if (emit->pass == MP_PASS_SCOPE) {
        return;
    }
488
    assert(l < emit->max_num_labels);
489
    if (emit->pass < MP_PASS_EMIT) {
490
        // assign label offset
491
        assert(emit->label_offsets[l] == (mp_uint_t)-1);
492
        emit->label_offsets[l] = emit->bytecode_offset;
493
494
    } else {
        // ensure label offset has not changed from MP_PASS_CODE_SIZE to MP_PASS_EMIT
495
496
        //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
497
498
499
    }
}

500
void mp_emit_bc_import_name(emit_t *emit, qstr qst) {
501
    emit_bc_pre(emit, -1);
502
    emit_write_bytecode_byte_qstr(emit, MP_BC_IMPORT_NAME, qst);
Damien's avatar
Damien committed
503
504
}

505
void mp_emit_bc_import_from(emit_t *emit, qstr qst) {
506
    emit_bc_pre(emit, 1);
507
    emit_write_bytecode_byte_qstr(emit, MP_BC_IMPORT_FROM, qst);
Damien's avatar
Damien committed
508
509
}

510
void mp_emit_bc_import_star(emit_t *emit) {
511
    emit_bc_pre(emit, -1);
512
    emit_write_bytecode_byte(emit, MP_BC_IMPORT_STAR);
Damien's avatar
Damien committed
513
514
}

515
void mp_emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
516
    emit_bc_pre(emit, 1);
Damien's avatar
Damien committed
517
    switch (tok) {
518
519
520
        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;
521
        no_other_choice:
522
        case MP_TOKEN_ELLIPSIS: emit_write_bytecode_byte_obj(emit, MP_BC_LOAD_CONST_OBJ, (void*)&mp_const_ellipsis_obj); break;
523
        default: assert(0); goto no_other_choice; // to help flow control analysis
Damien's avatar
Damien committed
524
525
526
    }
}

527
void mp_emit_bc_load_const_small_int(emit_t *emit, mp_int_t arg) {
528
    emit_bc_pre(emit, 1);
529
530
531
532
533
    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
534
535
}

536
void mp_emit_bc_load_const_str(emit_t *emit, qstr qst) {
537
    emit_bc_pre(emit, 1);
538
    emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_CONST_STRING, qst);
Damien's avatar
Damien committed
539
540
}

541
void mp_emit_bc_load_const_obj(emit_t *emit, void *obj) {
542
    emit_bc_pre(emit, 1);
543
    emit_write_bytecode_byte_obj(emit, MP_BC_LOAD_CONST_OBJ, obj);
544
545
}

546
void mp_emit_bc_load_null(emit_t *emit) {
547
    emit_bc_pre(emit, 1);
548
    emit_write_bytecode_byte(emit, MP_BC_LOAD_NULL);
549
550
};

551
void mp_emit_bc_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {
552
    (void)qst;
Damien's avatar
Damien committed
553
    assert(local_num >= 0);
554
    emit_bc_pre(emit, 1);
555
556
557
558
    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
559
560
561
    }
}

562
void mp_emit_bc_load_deref(emit_t *emit, qstr qst, mp_uint_t local_num) {
563
    (void)qst;
564
    emit_bc_pre(emit, 1);
565
    emit_write_bytecode_byte_uint(emit, MP_BC_LOAD_DEREF, local_num);
Damien's avatar
Damien committed
566
567
}

568
void mp_emit_bc_load_name(emit_t *emit, qstr qst) {
569
    (void)qst;
570
    emit_bc_pre(emit, 1);
571
    emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_NAME, qst);
572
573
574
    if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) {
        emit_write_bytecode_byte(emit, 0);
    }
Damien's avatar
Damien committed
575
576
}

577
void mp_emit_bc_load_global(emit_t *emit, qstr qst) {
578
    (void)qst;
579
    emit_bc_pre(emit, 1);
580
    emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_GLOBAL, qst);
581
582
583
    if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) {
        emit_write_bytecode_byte(emit, 0);
    }
Damien's avatar
Damien committed
584
585
}

586
void mp_emit_bc_load_attr(emit_t *emit, qstr qst) {
587
    emit_bc_pre(emit, 0);
588
    emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_ATTR, qst);
589
590
591
    if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) {
        emit_write_bytecode_byte(emit, 0);
    }
Damien's avatar
Damien committed
592
593
}

594
void mp_emit_bc_load_method(emit_t *emit, qstr qst) {
595
    emit_bc_pre(emit, 1);
596
    emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_METHOD, qst);
Damien's avatar
Damien committed
597
598
}

599
void mp_emit_bc_load_build_class(emit_t *emit) {
600
    emit_bc_pre(emit, 1);
601
    emit_write_bytecode_byte(emit, MP_BC_LOAD_BUILD_CLASS);
Damien's avatar
Damien committed
602
603
}

604
void mp_emit_bc_load_subscr(emit_t *emit) {
605
    emit_bc_pre(emit, -1);
606
    emit_write_bytecode_byte(emit, MP_BC_LOAD_SUBSCR);
607
608
}

609
void mp_emit_bc_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {
610
    (void)qst;
Damien's avatar
Damien committed
611
    assert(local_num >= 0);
612
    emit_bc_pre(emit, -1);
613
614
615
616
    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
617
618
619
    }
}

620
void mp_emit_bc_store_deref(emit_t *emit, qstr qst, mp_uint_t local_num) {
621
    (void)qst;
622
    emit_bc_pre(emit, -1);
623
    emit_write_bytecode_byte_uint(emit, MP_BC_STORE_DEREF, local_num);
Damien's avatar
Damien committed
624
625
}

626
void mp_emit_bc_store_name(emit_t *emit, qstr qst) {
627
    emit_bc_pre(emit, -1);
628
    emit_write_bytecode_byte_qstr(emit, MP_BC_STORE_NAME, qst);
Damien's avatar
Damien committed
629
630
}

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

636
void mp_emit_bc_store_attr(emit_t *emit, qstr qst) {
637
    emit_bc_pre(emit, -2);
638
    emit_write_bytecode_byte_qstr(emit, MP_BC_STORE_ATTR, qst);
639
640
641
    if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) {
        emit_write_bytecode_byte(emit, 0);
    }
Damien's avatar
Damien committed
642
643
}

644
void mp_emit_bc_store_subscr(emit_t *emit) {
645
    emit_bc_pre(emit, -3);
646
    emit_write_bytecode_byte(emit, MP_BC_STORE_SUBSCR);
Damien's avatar
Damien committed
647
648
}

649
void mp_emit_bc_delete_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {
650
    (void)qst;
651
    emit_write_bytecode_byte_uint(emit, MP_BC_DELETE_FAST, local_num);
Damien's avatar
Damien committed
652
653
}

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

659
void mp_emit_bc_delete_name(emit_t *emit, qstr qst) {
660
    emit_bc_pre(emit, 0);
661
    emit_write_bytecode_byte_qstr(emit, MP_BC_DELETE_NAME, qst);
Damien's avatar
Damien committed
662
663
}

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

669
670
671
672
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
673
674
}

675
676
677
678
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
679
680
}

681
void mp_emit_bc_dup_top(emit_t *emit) {
682
    emit_bc_pre(emit, 1);
683
    emit_write_bytecode_byte(emit, MP_BC_DUP_TOP);
Damien's avatar
Damien committed
684
685
}

686
void mp_emit_bc_dup_top_two(emit_t *emit) {
687
    emit_bc_pre(emit, 2);
688
    emit_write_bytecode_byte(emit, MP_BC_DUP_TOP_TWO);
Damien's avatar
Damien committed
689
690
}

691
void mp_emit_bc_pop_top(emit_t *emit) {
692
    emit_bc_pre(emit, -1);
693
    emit_write_bytecode_byte(emit, MP_BC_POP_TOP);
Damien's avatar
Damien committed
694
695
}

696
void mp_emit_bc_rot_two(emit_t *emit) {
697
    emit_bc_pre(emit, 0);
698
    emit_write_bytecode_byte(emit, MP_BC_ROT_TWO);
Damien's avatar
Damien committed
699
700
}

701
void mp_emit_bc_rot_three(emit_t *emit) {
702
    emit_bc_pre(emit, 0);
703
    emit_write_bytecode_byte(emit, MP_BC_ROT_THREE);
Damien's avatar
Damien committed
704
705
}

706
void mp_emit_bc_jump(emit_t *emit, mp_uint_t label) {
707
    emit_bc_pre(emit, 0);
708
    emit_write_bytecode_byte_signed_label(emit, MP_BC_JUMP, label);
Damien's avatar
Damien committed
709
710
}

711
void mp_emit_bc_pop_jump_if(emit_t *emit, bool cond, mp_uint_t label) {
712
    emit_bc_pre(emit, -1);
713
714
715
716
717
    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
718
719
}

720
void mp_emit_bc_jump_if_or_pop(emit_t *emit, bool cond, mp_uint_t label) {
721
    emit_bc_pre(emit, -1);
722
723
724
725
726
    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
727
728
}

729
void mp_emit_bc_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_depth) {
730
    if (except_depth == 0) {
731
        emit_bc_pre(emit, 0);
732
733
734
735
736
737
738
739
        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);
740
    }
Damien's avatar
Damien committed
741
742
}

743
void mp_emit_bc_setup_with(emit_t *emit, mp_uint_t label) {
744
745
746
747
    // 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);
748
    emit_write_bytecode_byte_unsigned_label(emit, MP_BC_SETUP_WITH, label);
Damien's avatar
Damien committed
749
750
}

751
void mp_emit_bc_with_cleanup(emit_t *emit) {
752
    emit_bc_pre(emit, -4);
753
    emit_write_bytecode_byte(emit, MP_BC_WITH_CLEANUP);
Damien's avatar
Damien committed
754
755
}

756
void mp_emit_bc_setup_except(emit_t *emit, mp_uint_t label) {
757
    emit_bc_pre(emit, 0);
758
    emit_write_bytecode_byte_unsigned_label(emit, MP_BC_SETUP_EXCEPT, label);
Damien's avatar
Damien committed
759
760
}

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

766
void mp_emit_bc_end_finally(emit_t *emit) {
767
    emit_bc_pre(emit, -1);
768
    emit_write_bytecode_byte(emit, MP_BC_END_FINALLY);
Damien's avatar
Damien committed
769
770
}

771
void mp_emit_bc_get_iter(emit_t *emit) {
772
    emit_bc_pre(emit, 0);
773
    emit_write_bytecode_byte(emit, MP_BC_GET_ITER);
Damien's avatar
Damien committed
774
775
}

776
void mp_emit_bc_for_iter(emit_t *emit, mp_uint_t label) {
777
    emit_bc_pre(emit, 1);
778
    emit_write_bytecode_byte_unsigned_label(emit, MP_BC_FOR_ITER, label);
Damien's avatar
Damien committed
779
780
}

781
void mp_emit_bc_for_iter_end(emit_t *emit) {
782
    emit_bc_pre(emit, -1);
Damien's avatar
Damien committed
783
784
}

785
void mp_emit_bc_pop_block(emit_t *emit) {
786
    emit_bc_pre(emit, 0);
787
    emit_write_bytecode_byte(emit, MP_BC_POP_BLOCK);
Damien's avatar
Damien committed
788
789
}

790
void mp_emit_bc_pop_except(emit_t *emit) {
791
    emit_bc_pre(emit, 0);
792
    emit_write_bytecode_byte(emit, MP_BC_POP_EXCEPT);
Damien's avatar
Damien committed
793
794
}

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

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

824
void mp_emit_bc_build_tuple(emit_t *emit, mp_uint_t n_args) {
825
    emit_bc_pre(emit, 1 - n_args);
826
    emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_TUPLE, n_args);
Damien's avatar
Damien committed
827
828
}

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

834
void mp_emit_bc_list_append(emit_t *emit, mp_uint_t list_stack_index) {
835
    emit_bc_pre(emit, -1);
836
    emit_write_bytecode_byte_uint(emit, MP_BC_LIST_APPEND, list_stack_index);
Damien's avatar
Damien committed
837
838
}

839
void mp_emit_bc_build_map(emit_t *emit, mp_uint_t n_args) {
840
    emit_bc_pre(emit, 1);
841
    emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_MAP, n_args);
Damien's avatar
Damien committed
842
843
}

844
void mp_emit_bc_store_map(emit_t *emit) {
845
    emit_bc_pre(emit, -2);
846
    emit_write_bytecode_byte(emit, MP_BC_STORE_MAP);
Damien's avatar
Damien committed
847