emitbc.c 36 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
42
43
44
45
    // Accessed as mp_obj_t, so must be aligned as such, and we rely on the
    // memory allocator returning a suitably aligned pointer.
    // Should work for cases when mp_obj_t is 64-bit on a 32-bit machine.
    byte dummy_data[DUMMY_DATA_SIZE];

46
    pass_kind_t pass : 8;
47
    mp_uint_t last_emit_was_return_value : 8;
48

Damien's avatar
Damien committed
49
50
51
52
    int stack_size;

    scope_t *scope;

53
54
    mp_uint_t last_source_line_offset;
    mp_uint_t last_source_line;
55

56
57
    mp_uint_t max_num_labels;
    mp_uint_t *label_offsets;
Damien's avatar
Damien committed
58

59
60
61
62
    size_t code_info_offset;
    size_t code_info_size;
    size_t bytecode_offset;
    size_t bytecode_size;
63
    byte *code_base; // stores both byte code and code info
64
65
66
67
68
69

    #if MICROPY_PERSISTENT_CODE
    uint16_t ct_cur_obj;
    uint16_t ct_num_obj;
    uint16_t ct_cur_raw_code;
    #endif
70
    mp_uint_t *const_table;
Damien's avatar
Damien committed
71
72
};

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

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

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

88
89
90
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) {
91
92
93
94
95
96
97
98
    // 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);
99
    byte *c = allocator(emit, buf + sizeof(buf) - p);
100
101
102
103
104
105
    while (p != buf + sizeof(buf) - 1) {
        *c++ = *p++ | 0x80;
    }
    *c = *p;
}

106
// all functions must go through this one to emit code info
107
STATIC byte *emit_get_cur_to_write_code_info(emit_t *emit, int num_bytes_to_write) {
108
    //printf("emit %d\n", num_bytes_to_write);
109
    if (emit->pass < MP_PASS_EMIT) {
110
111
112
113
114
115
116
117
        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
118
119
}

120
121
122
123
124
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) {
125
126
127
    emit_write_uint(emit, emit_get_cur_to_write_code_info, val);
}

128
STATIC void emit_write_code_info_qstr(emit_t *emit, qstr qst) {
129
130
131
132
133
134
    #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
135
    emit_write_uint(emit, emit_get_cur_to_write_code_info, qst);
136
    #endif
Damien's avatar
Damien committed
137
138
}

139
#if MICROPY_ENABLE_SOURCE_LINE
140
STATIC void emit_write_code_info_bytes_lines(emit_t *emit, mp_uint_t bytes_to_skip, mp_uint_t lines_to_skip) {
141
    assert(bytes_to_skip > 0 || lines_to_skip > 0);
142
    //printf("  %d %d\n", bytes_to_skip, lines_to_skip);
143
    while (bytes_to_skip > 0 || lines_to_skip > 0) {
144
145
146
147
148
149
150
151
152
153
154
155
156
157
        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;
        }
158
159
        bytes_to_skip -= b;
        lines_to_skip -= l;
160
    }
161
}
162
#endif
163
164

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

178
179
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
180
181
182
    c[0] = b1;
}

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

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

    // We store each 7 bits in a separate byte, and that's how many bytes needed
195
    byte buf[BYTES_FOR_INT];
196
197
198
199
200
201
202
203
204
205
206
207
208
209
    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;
    }

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

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

222
223
224
225
226
227
228
229
#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);
}
#endif
230

231
STATIC void emit_write_bytecode_byte_qstr(emit_t* emit, byte b, qstr qst) {
232
233
234
235
236
237
238
    #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
239
    emit_write_bytecode_byte_uint(emit, b, qst);
240
241
242
    #endif
}

243
STATIC void emit_write_bytecode_byte_obj(emit_t *emit, byte b, mp_obj_t obj) {
244
245
246
    #if MICROPY_PERSISTENT_CODE
    emit_write_bytecode_byte_const(emit, b,
        emit->scope->num_pos_args + emit->scope->num_kwonly_args
247
        + emit->ct_cur_obj++, (mp_uint_t)obj);
248
    #else
249
250
251
252
253
254
255
    // aligns the pointer so it is friendly to GC
    emit_write_bytecode_byte(emit, b);
    emit->bytecode_offset = (size_t)MP_ALIGN(emit->bytecode_offset, sizeof(mp_obj_t));
    mp_obj_t *c = (mp_obj_t*)emit_get_cur_to_write_bytecode(emit, sizeof(mp_obj_t));
    // Verify thar c is already uint-aligned
    assert(c == MP_ALIGN(c, sizeof(mp_obj_t)));
    *c = obj;
256
257
258
259
260
261
262
    #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
263
        + emit->ct_num_obj + emit->ct_cur_raw_code++, (mp_uint_t)(uintptr_t)rc);
264
    #else
265
266
267
268
269
270
271
    // aligns the pointer so it is friendly to GC
    emit_write_bytecode_byte(emit, b);
    emit->bytecode_offset = (size_t)MP_ALIGN(emit->bytecode_offset, sizeof(void*));
    void **c = (void**)emit_get_cur_to_write_bytecode(emit, sizeof(void*));
    // Verify thar c is already uint-aligned
    assert(c == MP_ALIGN(c, sizeof(void*)));
    *c = rc;
272
    #endif
Damien's avatar
Damien committed
273
274
}

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

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

303
304
#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) {
305
306
307
308
    (void)emit;
    (void)op;
    (void)arg1;
    (void)arg2;
Damien George's avatar
Damien George committed
309
}
310
#endif
Damien George's avatar
Damien George committed
311

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

325
326
327
328
329
330
331
332
333
334
335
    // 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);
336
337
    }

338
339
340
341
342
343
344
    // 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);

345
346
347
348
349
350
351
    // 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);
352
353
    }

354
355
356
357
    // 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);

358
    // bytecode prelude: initialise closed over variables
Damien George's avatar
Damien George committed
359
360
361
    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) {
362
            assert(id->local_num < 255);
363
            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
364
365
        }
    }
366
    emit_write_bytecode_byte(emit, 255); // end of list sentinel
367

368
369
370
371
372
    #if MICROPY_PERSISTENT_CODE
    emit->ct_cur_obj = 0;
    emit->ct_cur_raw_code = 0;
    #endif

373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
    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
401
402
}

403
void mp_emit_bc_end_pass(emit_t *emit) {
404
405
406
407
    if (emit->pass == MP_PASS_SCOPE) {
        return;
    }

Damien George's avatar
Damien George committed
408
409
    // check stack is back to zero size
    if (emit->stack_size != 0) {
410
        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
411
412
    }

413
    emit_write_code_info_byte(emit, 0); // end of line number info
414

415
416
417
418
419
    #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

420
    if (emit->pass == MP_PASS_CODE_SIZE) {
421
        #if !MICROPY_PERSISTENT_CODE
422
        // so bytecode is aligned
423
        emit->code_info_offset = (size_t)MP_ALIGN(emit->code_info_offset, sizeof(mp_uint_t));
424
        #endif
425
426

        // calculate size of total code-info + bytecode, in bytes
427
        emit->code_info_size = emit->code_info_offset;
428
429
        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
430

431
432
433
434
435
436
437
438
        #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
439

440
    } else if (emit->pass == MP_PASS_EMIT) {
441
        mp_emit_glue_assign_bytecode(emit->scope->raw_code, emit->code_base,
442
            emit->code_info_size + emit->bytecode_size,
443
444
445
446
447
            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
448
449
450
    }
}

451
bool mp_emit_bc_last_emit_was_return_value(emit_t *emit) {
Damien's avatar
Damien committed
452
453
454
    return emit->last_emit_was_return_value;
}

455
void mp_emit_bc_adjust_stack_size(emit_t *emit, mp_int_t delta) {
456
    emit->stack_size += delta;
Damien's avatar
Damien committed
457
458
}

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

479
STATIC void emit_bc_pre(emit_t *emit, mp_int_t stack_size_delta) {
480
481
482
    if (emit->pass == MP_PASS_SCOPE) {
        return;
    }
483
    assert((mp_int_t)emit->stack_size + stack_size_delta >= 0);
484
485
486
    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
487
488
489
490
    }
    emit->last_emit_was_return_value = false;
}

491
void mp_emit_bc_label_assign(emit_t *emit, mp_uint_t l) {
492
    emit_bc_pre(emit, 0);
493
494
495
    if (emit->pass == MP_PASS_SCOPE) {
        return;
    }
496
    assert(l < emit->max_num_labels);
497
    if (emit->pass < MP_PASS_EMIT) {
498
        // assign label offset
499
        assert(emit->label_offsets[l] == (mp_uint_t)-1);
500
        emit->label_offsets[l] = emit->bytecode_offset;
501
502
    } else {
        // ensure label offset has not changed from MP_PASS_CODE_SIZE to MP_PASS_EMIT
503
504
        //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
505
506
507
    }
}

508
void mp_emit_bc_import_name(emit_t *emit, qstr qst) {
509
    emit_bc_pre(emit, -1);
510
    emit_write_bytecode_byte_qstr(emit, MP_BC_IMPORT_NAME, qst);
Damien's avatar
Damien committed
511
512
}

513
void mp_emit_bc_import_from(emit_t *emit, qstr qst) {
514
    emit_bc_pre(emit, 1);
515
    emit_write_bytecode_byte_qstr(emit, MP_BC_IMPORT_FROM, qst);
Damien's avatar
Damien committed
516
517
}

518
void mp_emit_bc_import_star(emit_t *emit) {
519
    emit_bc_pre(emit, -1);
520
    emit_write_bytecode_byte(emit, MP_BC_IMPORT_STAR);
Damien's avatar
Damien committed
521
522
}

523
void mp_emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
524
    emit_bc_pre(emit, 1);
Damien's avatar
Damien committed
525
    switch (tok) {
526
527
528
        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;
529
        no_other_choice:
530
        case MP_TOKEN_ELLIPSIS: emit_write_bytecode_byte_obj(emit, MP_BC_LOAD_CONST_OBJ, MP_OBJ_FROM_PTR(&mp_const_ellipsis_obj)); break;
531
        default: assert(0); goto no_other_choice; // to help flow control analysis
Damien's avatar
Damien committed
532
533
534
    }
}

535
void mp_emit_bc_load_const_small_int(emit_t *emit, mp_int_t arg) {
536
    emit_bc_pre(emit, 1);
537
538
539
540
541
    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
542
543
}

544
void mp_emit_bc_load_const_str(emit_t *emit, qstr qst) {
545
    emit_bc_pre(emit, 1);
546
    emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_CONST_STRING, qst);
Damien's avatar
Damien committed
547
548
}

549
void mp_emit_bc_load_const_obj(emit_t *emit, mp_obj_t obj) {
550
    emit_bc_pre(emit, 1);
551
    emit_write_bytecode_byte_obj(emit, MP_BC_LOAD_CONST_OBJ, obj);
552
553
}

554
void mp_emit_bc_load_null(emit_t *emit) {
555
    emit_bc_pre(emit, 1);
556
    emit_write_bytecode_byte(emit, MP_BC_LOAD_NULL);
557
558
};

559
void mp_emit_bc_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {
560
    (void)qst;
Damien's avatar
Damien committed
561
    assert(local_num >= 0);
562
    emit_bc_pre(emit, 1);
563
564
565
566
    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
567
568
569
    }
}

570
void mp_emit_bc_load_deref(emit_t *emit, qstr qst, mp_uint_t local_num) {
571
    (void)qst;
572
    emit_bc_pre(emit, 1);
573
    emit_write_bytecode_byte_uint(emit, MP_BC_LOAD_DEREF, local_num);
Damien's avatar
Damien committed
574
575
}

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

585
void mp_emit_bc_load_global(emit_t *emit, qstr qst) {
586
    (void)qst;
587
    emit_bc_pre(emit, 1);
588
    emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_GLOBAL, 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_attr(emit_t *emit, qstr qst) {
595
    emit_bc_pre(emit, 0);
596
    emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_ATTR, qst);
597
598
599
    if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) {
        emit_write_bytecode_byte(emit, 0);
    }
Damien's avatar
Damien committed
600
601
}

602
void mp_emit_bc_load_method(emit_t *emit, qstr qst) {
603
    emit_bc_pre(emit, 1);
604
    emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_METHOD, qst);
Damien's avatar
Damien committed
605
606
}

607
void mp_emit_bc_load_build_class(emit_t *emit) {
608
    emit_bc_pre(emit, 1);
609
    emit_write_bytecode_byte(emit, MP_BC_LOAD_BUILD_CLASS);
Damien's avatar
Damien committed
610
611
}

612
void mp_emit_bc_load_subscr(emit_t *emit) {
613
    emit_bc_pre(emit, -1);
614
    emit_write_bytecode_byte(emit, MP_BC_LOAD_SUBSCR);
615
616
}

617
void mp_emit_bc_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {
618
    (void)qst;
Damien's avatar
Damien committed
619
    assert(local_num >= 0);
620
    emit_bc_pre(emit, -1);
621
622
623
624
    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
625
626
627
    }
}

628
void mp_emit_bc_store_deref(emit_t *emit, qstr qst, mp_uint_t local_num) {
629
    (void)qst;
630
    emit_bc_pre(emit, -1);
631
    emit_write_bytecode_byte_uint(emit, MP_BC_STORE_DEREF, local_num);
Damien's avatar
Damien committed
632
633
}

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

639
void mp_emit_bc_store_global(emit_t *emit, qstr qst) {
640
    emit_bc_pre(emit, -1);
641
    emit_write_bytecode_byte_qstr(emit, MP_BC_STORE_GLOBAL, qst);
Damien's avatar
Damien committed
642
643
}

644
void mp_emit_bc_store_attr(emit_t *emit, qstr qst) {
645
    emit_bc_pre(emit, -2);
646
    emit_write_bytecode_byte_qstr(emit, MP_BC_STORE_ATTR, qst);
647
648
649
    if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) {
        emit_write_bytecode_byte(emit, 0);
    }
Damien's avatar
Damien committed
650
651
}

652
void mp_emit_bc_store_subscr(emit_t *emit) {
653
    emit_bc_pre(emit, -3);
654
    emit_write_bytecode_byte(emit, MP_BC_STORE_SUBSCR);
Damien's avatar
Damien committed
655
656
}

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

662
void mp_emit_bc_delete_deref(emit_t *emit, qstr qst, mp_uint_t local_num) {
663
    (void)qst;
664
    emit_write_bytecode_byte_uint(emit, MP_BC_DELETE_DEREF, local_num);
Damien's avatar
Damien committed
665
666
}

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

672
void mp_emit_bc_delete_global(emit_t *emit, qstr qst) {
673
    emit_bc_pre(emit, 0);
674
    emit_write_bytecode_byte_qstr(emit, MP_BC_DELETE_GLOBAL, qst);
Damien's avatar
Damien committed
675
676
}

677
678
679
680
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
681
682
}

683
684
685
686
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
687
688
}

689
void mp_emit_bc_dup_top(emit_t *emit) {
690
    emit_bc_pre(emit, 1);
691
    emit_write_bytecode_byte(emit, MP_BC_DUP_TOP);
Damien's avatar
Damien committed
692
693
}

694
void mp_emit_bc_dup_top_two(emit_t *emit) {
695
    emit_bc_pre(emit, 2);
696
    emit_write_bytecode_byte(emit, MP_BC_DUP_TOP_TWO);
Damien's avatar
Damien committed
697
698
}

699
void mp_emit_bc_pop_top(emit_t *emit) {
700
    emit_bc_pre(emit, -1);
701
    emit_write_bytecode_byte(emit, MP_BC_POP_TOP);
Damien's avatar
Damien committed
702
703
}

704
void mp_emit_bc_rot_two(emit_t *emit) {
705
    emit_bc_pre(emit, 0);
706
    emit_write_bytecode_byte(emit, MP_BC_ROT_TWO);
Damien's avatar
Damien committed
707
708
}

709
void mp_emit_bc_rot_three(emit_t *emit) {
710
    emit_bc_pre(emit, 0);
711
    emit_write_bytecode_byte(emit, MP_BC_ROT_THREE);
Damien's avatar
Damien committed
712
713
}

714
void mp_emit_bc_jump(emit_t *emit, mp_uint_t label) {
715
    emit_bc_pre(emit, 0);
716
    emit_write_bytecode_byte_signed_label(emit, MP_BC_JUMP, label);
Damien's avatar
Damien committed
717
718
}

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

728
void mp_emit_bc_jump_if_or_pop(emit_t *emit, bool cond, mp_uint_t label) {
729
    emit_bc_pre(emit, -1);
730
731
732
733
734
    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
735
736
}

737
void mp_emit_bc_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_depth) {
738
    if (except_depth == 0) {
739
        emit_bc_pre(emit, 0);
740
741
742
743
744
745
746
747
        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);
748
    }
Damien's avatar
Damien committed
749
750
}

751
void mp_emit_bc_setup_with(emit_t *emit, mp_uint_t label) {
752
753
754
755
    // 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);
756
    emit_write_bytecode_byte_unsigned_label(emit, MP_BC_SETUP_WITH, label);
Damien's avatar
Damien committed
757
758
}

759
void mp_emit_bc_with_cleanup(emit_t *emit) {
760
    emit_bc_pre(emit, -4);
761
    emit_write_bytecode_byte(emit, MP_BC_WITH_CLEANUP);
Damien's avatar
Damien committed
762
763
}

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

769
void mp_emit_bc_setup_finally(emit_t *emit, mp_uint_t label) {
770
    emit_bc_pre(emit, 0);
771
    emit_write_bytecode_byte_unsigned_label(emit, MP_BC_SETUP_FINALLY, label);
Damien's avatar
Damien committed
772
773
}

774
void mp_emit_bc_end_finally(emit_t *emit) {
775
    emit_bc_pre(emit, -1);
776
    emit_write_bytecode_byte(emit, MP_BC_END_FINALLY);
Damien's avatar
Damien committed
777
778
}

779
void mp_emit_bc_get_iter(emit_t *emit) {
780
    emit_bc_pre(emit, 0);
781
    emit_write_bytecode_byte(emit, MP_BC_GET_ITER);
Damien's avatar
Damien committed
782
783
}

784
void mp_emit_bc_for_iter(emit_t *emit, mp_uint_t label) {
785
    emit_bc_pre(emit, 1);
786
    emit_write_bytecode_byte_unsigned_label(emit, MP_BC_FOR_ITER, label);
Damien's avatar
Damien committed
787
788
}

789
void mp_emit_bc_for_iter_end(emit_t *emit) {
790
    emit_bc_pre(emit, -1);
Damien's avatar
Damien committed
791
792
}

793
void mp_emit_bc_pop_block(emit_t *emit) {
794
    emit_bc_pre(emit, 0);
795
    emit_write_bytecode_byte(emit, MP_BC_POP_BLOCK);
Damien's avatar
Damien committed
796
797
}

798
void mp_emit_bc_pop_except(emit_t *emit) {
799
    emit_bc_pre(emit, 0);
800
    emit_write_bytecode_byte(emit, MP_BC_POP_EXCEPT);
Damien's avatar
Damien committed
801
802
}

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

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

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

837
void mp_emit_bc_build_list(emit_t *emit, mp_uint_t n_args) {
838
    emit_bc_pre(emit, 1 - n_args);
839
    emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_LIST, n_args);
Damien's avatar
Damien committed
840
841
}

842
void mp_emit_bc_list_append(emit_t *emit, mp_uint_t list_stack_index) {
843
    emit_bc_pre(emit, -1);
844
    emit_write_bytecode_byte_uint(emit, MP_BC_LIST_APPEND, list_stack_index);
Damien's avatar
Damien committed
845
846
}

847
void mp_emit_bc_build_map(emit_t *emit, mp_uint_t n_args) {
848
    emit_bc_pre(emit, 1);
849
    emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_MAP, n_args);
Damien's avatar
Damien committed
850
851
}

852
void mp_emit_bc_store_map(emit_t *emit) {