emitbc.c 35.9 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
#if MICROPY_ENABLE_COMPILER

39
40
41
#define BYTES_FOR_INT ((BYTES_PER_WORD * 8 + 6) / 7)
#define DUMMY_DATA_SIZE (BYTES_FOR_INT)

42
struct _emit_t {
43
44
45
46
47
    // 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];

48
    pass_kind_t pass : 8;
49
    mp_uint_t last_emit_was_return_value : 8;
50

Damien's avatar
Damien committed
51
52
53
54
    int stack_size;

    scope_t *scope;

55
56
    mp_uint_t last_source_line_offset;
    mp_uint_t last_source_line;
57

58
59
    mp_uint_t max_num_labels;
    mp_uint_t *label_offsets;
Damien's avatar
Damien committed
60

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

224
225
226
227
228
229
230
231
#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
232

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

245
STATIC void emit_write_bytecode_byte_obj(emit_t *emit, byte b, mp_obj_t obj) {
246
247
248
    #if MICROPY_PERSISTENT_CODE
    emit_write_bytecode_byte_const(emit, b,
        emit->scope->num_pos_args + emit->scope->num_kwonly_args
249
        + emit->ct_cur_obj++, (mp_uint_t)obj);
250
    #else
251
252
253
254
255
256
257
    // 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;
258
259
260
261
262
263
264
    #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
265
        + emit->ct_num_obj + emit->ct_cur_raw_code++, (mp_uint_t)(uintptr_t)rc);
266
    #else
267
268
269
270
271
272
273
    // 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;
274
    #endif
Damien's avatar
Damien committed
275
276
}

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

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

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

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

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

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

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

356
357
358
359
    // 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);

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

370
371
372
373
374
    #if MICROPY_PERSISTENT_CODE
    emit->ct_cur_obj = 0;
    emit->ct_cur_raw_code = 0;
    #endif

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
401
402
    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
403
404
}

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

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

415
    emit_write_code_info_byte(emit, 0); // end of line number info
416

417
418
419
420
421
    #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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

587
void mp_emit_bc_load_global(emit_t *emit, qstr qst) {
588
    (void)qst;
589
    emit_bc_pre(emit, 1);
590
    emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_GLOBAL, qst);
591
592
593
    if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) {
        emit_write_bytecode_byte(emit, 0);
    }
Damien's avatar
Damien committed
594
595
}

596
void mp_emit_bc_load_attr(emit_t *emit, qstr qst) {
597
    emit_bc_pre(emit, 0);
598
    emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_ATTR, qst);
599
600
601
    if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) {
        emit_write_bytecode_byte(emit, 0);
    }
Damien's avatar
Damien committed
602
603
}

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

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

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

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

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

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

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

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

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

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

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

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

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

679
680
681
682
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
683
684
}

685
686
687
688
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
689
690
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

805
void mp_emit_bc_unary_op(emit_t *emit, mp_unary_op_t op) {
806
807
    emit_bc_pre(emit, 0);
    emit_write_bytecode_byte(emit, MP_BC_UNARY_OP_MULTI + op);
Damien's avatar
Damien committed
808
809
}

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

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

832
void mp_emit_bc_build_list(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_LIST, n_args);
Damien's avatar
Damien committed
835
836
}

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

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

847
void mp_emit_bc_store_map(emit_t *emit) {
848
    emit_bc_pre(emit, -2);
849
    emit_write_bytecode_byte(emit, MP_BC_STORE_MAP);
Damien's avatar
Damien committed
850
851
}

852
void mp_emit_bc_map_add(emit_t *emit, mp_uint_t map_stack_index) {
853
    emit_bc_pre(emit, -2);
854
    emit_write_bytecode_byte_uint(emit, MP_BC_MAP_ADD, map_stack_index);
Damien's avatar
Damien committed
855