emitbc.c 28.2 KB
Newer Older
Damien's avatar
Damien committed
1
2
3
4
5
6
7
8
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>

#include "misc.h"
9
#include "mpconfig.h"
10
#include "qstr.h"
Damien's avatar
Damien committed
11
12
13
#include "lexer.h"
#include "parse.h"
#include "scope.h"
14
#include "runtime0.h"
Damien's avatar
Damien committed
15
#include "emit.h"
16
#include "bc0.h"
Damien's avatar
Damien committed
17

18
19
struct _emit_t {
    pass_kind_t pass;
Damien's avatar
Damien committed
20
21
22
23
24
    int stack_size;
    bool last_emit_was_return_value;

    scope_t *scope;

25
26
27
    uint last_source_line_offset;
    uint last_source_line;

28
    uint max_num_labels;
Damien's avatar
Damien committed
29
30
    uint *label_offsets;

31
32
33
34
35
    uint code_info_offset;
    uint code_info_size;
    uint byte_code_offset;
    uint byte_code_size;
    byte *code_base; // stores both byte code and code info
Damien's avatar
Damien committed
36
37
38
    byte dummy_data[8];
};

39
emit_t *emit_bc_new(uint max_num_labels) {
40
    emit_t *emit = m_new0(emit_t, 1);
41
42
43
44
    emit->max_num_labels = max_num_labels;
    emit->label_offsets = m_new(uint, emit->max_num_labels);
    return emit;
}
45

46
void emit_bc_free(emit_t *emit) {
47
48
49
50
    m_del(uint, emit->label_offsets, emit->max_num_labels);
    m_del_obj(emit_t, emit);
}

51
// all functions must go through this one to emit code info
52
STATIC byte* emit_get_cur_to_write_code_info(emit_t* emit, int num_bytes_to_write) {
53
54
55
56
57
58
59
60
61
62
    //printf("emit %d\n", num_bytes_to_write);
    if (emit->pass < PASS_3) {
        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
63
64
}

65
STATIC void emit_write_code_info_qstr(emit_t* emit, qstr qstr) {
66
67
68
69
70
71
    byte* c = emit_get_cur_to_write_code_info(emit, 4);
    // TODO variable length encoding for qstr
    c[0] = qstr & 0xff;
    c[1] = (qstr >> 8) & 0xff;
    c[2] = (qstr >> 16) & 0xff;
    c[3] = (qstr >> 24) & 0xff;
Damien's avatar
Damien committed
72
73
}

74
STATIC void emit_write_code_info_bytes_lines(emit_t* emit, uint bytes_to_skip, uint lines_to_skip) {
75
76
77
78
79
80
81
    for (; bytes_to_skip > 31; bytes_to_skip -= 31) {
        *emit_get_cur_to_write_code_info(emit, 1) = 31;
    }
    for (; lines_to_skip > 7; lines_to_skip -= 7) {
        *emit_get_cur_to_write_code_info(emit, 1) = 7 << 5;
    }
    *emit_get_cur_to_write_code_info(emit, 1) = bytes_to_skip | (lines_to_skip << 5);
82
83
84
}

// all functions must go through this one to emit byte code
85
STATIC byte* emit_get_cur_to_write_byte_code(emit_t* emit, int num_bytes_to_write) {
Damien's avatar
Damien committed
86
87
    //printf("emit %d\n", num_bytes_to_write);
    if (emit->pass < PASS_3) {
88
        emit->byte_code_offset += num_bytes_to_write;
Damien's avatar
Damien committed
89
90
        return emit->dummy_data;
    } else {
91
92
93
        assert(emit->byte_code_offset + num_bytes_to_write <= emit->byte_code_size);
        byte *c = emit->code_base + emit->code_info_size + emit->byte_code_offset;
        emit->byte_code_offset += num_bytes_to_write;
Damien's avatar
Damien committed
94
95
96
97
        return c;
    }
}

98
STATIC void emit_write_byte_code_byte(emit_t* emit, byte b1) {
99
    byte* c = emit_get_cur_to_write_byte_code(emit, 1);
Damien's avatar
Damien committed
100
101
102
    c[0] = b1;
}

103
STATIC void emit_write_byte_code_byte_byte(emit_t* emit, byte b1, uint b2) {
Damien's avatar
Damien committed
104
    assert((b2 & (~0xff)) == 0);
105
    byte* c = emit_get_cur_to_write_byte_code(emit, 2);
Damien's avatar
Damien committed
106
107
108
109
    c[0] = b1;
    c[1] = b2;
}

110
STATIC void emit_write_byte_code_uint(emit_t* emit, uint num) {
111
    // We store each 7 bits in a separate byte, and that's how many bytes needed
112
    byte buf[(BYTES_PER_WORD * 8 + 6) / 7];
113
114
115
116
117
118
119
120
121
    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);
    byte* c = emit_get_cur_to_write_byte_code(emit, buf + sizeof(buf) - p);
    while (p != buf + sizeof(buf) - 1) {
        *c++ = *p++ | 0x80;
122
    }
123
    *c = *p;
124
125
}

126
// Similar to emit_write_byte_code_uint(), just some extra handling to encode sign
127
STATIC void emit_write_byte_code_byte_int(emit_t* emit, byte b1, machine_int_t num) {
128
129
130
    emit_write_byte_code_byte(emit, b1);

    // We store each 7 bits in a separate byte, and that's how many bytes needed
131
    byte buf[(BYTES_PER_WORD * 8 + 6) / 7];
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
    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;
    }

    byte* c = emit_get_cur_to_write_byte_code(emit, buf + sizeof(buf) - p);
    while (p != buf + sizeof(buf) - 1) {
        *c++ = *p++ | 0x80;
    }
    *c = *p;
Damien's avatar
Damien committed
151
152
}

153
STATIC void emit_write_byte_code_byte_uint(emit_t* emit, byte b, uint num) {
154
155
    emit_write_byte_code_byte(emit, b);
    emit_write_byte_code_uint(emit, num);
Damien's avatar
Damien committed
156
157
}

158
/* currently unused
159
STATIC void emit_write_byte_code_byte_uint_uint(emit_t* emit, byte b, uint num1, uint num2) {
160
161
162
163
164
165
    emit_write_byte_code_byte(emit, b);
    emit_write_byte_code_byte_uint(emit, num1);
    emit_write_byte_code_byte_uint(emit, num2);
}
*/

166
STATIC void emit_write_byte_code_byte_qstr(emit_t* emit, byte b, qstr qstr) {
167
    emit_write_byte_code_byte_uint(emit, b, qstr);
Damien's avatar
Damien committed
168
169
}

Damien's avatar
Damien committed
170
// unsigned labels are relative to ip following this instruction, stored as 16 bits
171
STATIC void emit_write_byte_code_byte_unsigned_label(emit_t* emit, byte b1, int label) {
172
    uint byte_code_offset;
Damien's avatar
Damien committed
173
    if (emit->pass < PASS_3) {
174
        byte_code_offset = 0;
Damien's avatar
Damien committed
175
    } else {
176
        byte_code_offset = emit->label_offsets[label] - emit->byte_code_offset - 3;
Damien's avatar
Damien committed
177
    }
178
    byte* c = emit_get_cur_to_write_byte_code(emit, 3);
Damien's avatar
Damien committed
179
    c[0] = b1;
180
181
    c[1] = byte_code_offset;
    c[2] = byte_code_offset >> 8;
Damien's avatar
Damien committed
182
183
184
}

// signed labels are relative to ip following this instruction, stored as 16 bits, in excess
185
STATIC void emit_write_byte_code_byte_signed_label(emit_t* emit, byte b1, int label) {
186
    int byte_code_offset;
Damien's avatar
Damien committed
187
    if (emit->pass < PASS_3) {
188
        byte_code_offset = 0;
Damien's avatar
Damien committed
189
    } else {
190
        byte_code_offset = emit->label_offsets[label] - emit->byte_code_offset - 3 + 0x8000;
Damien's avatar
Damien committed
191
    }
192
    byte* c = emit_get_cur_to_write_byte_code(emit, 3);
Damien's avatar
Damien committed
193
    c[0] = b1;
194
195
    c[1] = byte_code_offset;
    c[2] = byte_code_offset >> 8;
Damien's avatar
Damien committed
196
197
}

198
STATIC void emit_bc_set_native_types(emit_t *emit, bool do_native_types) {
Damien George's avatar
Damien George committed
199
200
}

201
STATIC void emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
Damien George's avatar
Damien George committed
202
203
204
205
    emit->pass = pass;
    emit->stack_size = 0;
    emit->last_emit_was_return_value = false;
    emit->scope = scope;
206
207
    emit->last_source_line_offset = 0;
    emit->last_source_line = 1;
Damien George's avatar
Damien George committed
208
209
210
    if (pass == PASS_2) {
        memset(emit->label_offsets, -1, emit->max_num_labels * sizeof(uint));
    }
211
212
213
214
215
216
217
218
219
220
221
222
223
224
    emit->byte_code_offset = 0;
    emit->code_info_offset = 0;

    // write code info size (don't know size at this stage in PASS_2 so need to use maximum space (4 bytes) to write it)
    {
        byte* c = emit_get_cur_to_write_code_info(emit, 4);
        machine_uint_t s = emit->code_info_size;
        c[0] = s & 0xff;
        c[1] = (s >> 8) & 0xff;
        c[2] = (s >> 16) & 0xff;
        c[3] = (s >> 24) & 0xff;
    }

    // code info
225
226
    emit_write_code_info_qstr(emit, scope->source_file);
    emit_write_code_info_qstr(emit, scope->simple_name);
Damien George's avatar
Damien George committed
227
228
229
230
231
232
233
234
235
236

    // prelude for initialising closed over variables
    int num_cell = 0;
    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) {
            num_cell += 1;
        }
    }
    assert(num_cell <= 255);
237
    emit_write_byte_code_byte(emit, num_cell); // write number of locals that are cells
Damien George's avatar
Damien George committed
238
239
240
    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) {
241
            emit_write_byte_code_byte(emit, id->local_num); // write the local which should be converted to a cell
Damien George's avatar
Damien George committed
242
243
244
245
        }
    }
}

246
STATIC void emit_bc_end_pass(emit_t *emit) {
Damien George's avatar
Damien George committed
247
248
249
250
251
    // check stack is back to zero size
    if (emit->stack_size != 0) {
        printf("ERROR: stack size not back to zero; got %d\n", emit->stack_size);
    }

252
    emit_write_code_info_bytes_lines(emit, 0, 0); // end of line number info
253

Damien George's avatar
Damien George committed
254
255
    if (emit->pass == PASS_2) {
        // calculate size of code in bytes
256
257
258
        emit->code_info_size = emit->code_info_offset;
        emit->byte_code_size = emit->byte_code_offset;
        emit->code_base = m_new(byte, emit->code_info_size + emit->byte_code_size);
Damien George's avatar
Damien George committed
259
260

    } else if (emit->pass == PASS_3) {
261
262
263
264
265
266
267
268
        qstr *arg_names = m_new(qstr, emit->scope->num_params);
        for (int i = 0; i < emit->scope->num_params; i++) {
            arg_names[i] = emit->scope->id_info[i].qstr;
        }
        rt_assign_byte_code(emit->scope->unique_code_id, emit->code_base,
            emit->code_info_size + emit->byte_code_size,
            emit->scope->num_params, emit->scope->num_locals, emit->scope->stack_size,
            emit->scope->scope_flags, arg_names);
Damien George's avatar
Damien George committed
269
270
271
    }
}

272
bool emit_bc_last_emit_was_return_value(emit_t *emit) {
Damien's avatar
Damien committed
273
274
275
    return emit->last_emit_was_return_value;
}

276
int emit_bc_get_stack_size(emit_t *emit) {
Damien's avatar
Damien committed
277
278
279
    return emit->stack_size;
}

280
STATIC void emit_bc_set_stack_size(emit_t *emit, int size) {
281
    emit->stack_size = size;
Damien's avatar
Damien committed
282
283
}

284
STATIC void emit_bc_set_source_line(emit_t *emit, int source_line) {
285
    //printf("source: line %d -> %d  offset %d -> %d\n", emit->last_source_line, source_line, emit->last_source_line_offset, emit->byte_code_offset);
286
#if MICROPY_ENABLE_SOURCE_LINE
287
    if (source_line > emit->last_source_line) {
288
289
290
        uint bytes_to_skip = emit->byte_code_offset - emit->last_source_line_offset;
        uint lines_to_skip = source_line - emit->last_source_line;
        emit_write_code_info_bytes_lines(emit, bytes_to_skip, lines_to_skip);
291
        //printf("  %d %d\n", bytes_to_skip, lines_to_skip);
292
293
294
        emit->last_source_line_offset = emit->byte_code_offset;
        emit->last_source_line = source_line;
    }
295
#endif
296
297
}

298
STATIC void emit_bc_load_id(emit_t *emit, qstr qstr) {
299
300
301
    emit_common_load_id(emit, &emit_bc_method_table, emit->scope, qstr);
}

302
STATIC void emit_bc_store_id(emit_t *emit, qstr qstr) {
303
304
305
    emit_common_store_id(emit, &emit_bc_method_table, emit->scope, qstr);
}

306
STATIC void emit_bc_delete_id(emit_t *emit, qstr qstr) {
307
308
309
    emit_common_delete_id(emit, &emit_bc_method_table, emit->scope, qstr);
}

310
// TODO: module-polymorphic function (read: name clash if made global)
311
static void emit_pre(emit_t *emit, int stack_size_delta) {
312
313
314
    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
315
316
317
318
    }
    emit->last_emit_was_return_value = false;
}

319
STATIC void emit_bc_label_assign(emit_t *emit, int l) {
Damien's avatar
Damien committed
320
    emit_pre(emit, 0);
321
322
323
324
    assert(l < emit->max_num_labels);
    if (emit->pass == PASS_2) {
        // assign label offset
        assert(emit->label_offsets[l] == -1);
325
        emit->label_offsets[l] = emit->byte_code_offset;
326
327
    } else if (emit->pass == PASS_3) {
        // ensure label offset has not changed from PASS_2 to PASS_3
328
329
        //printf("l%d: (at %d vs %d)\n", l, emit->byte_code_offset, emit->label_offsets[l]);
        assert(emit->label_offsets[l] == emit->byte_code_offset);
Damien's avatar
Damien committed
330
331
332
    }
}

333
STATIC void emit_bc_import_name(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
334
    emit_pre(emit, -1);
335
    emit_write_byte_code_byte_qstr(emit, MP_BC_IMPORT_NAME, qstr);
Damien's avatar
Damien committed
336
337
}

338
STATIC void emit_bc_import_from(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
339
    emit_pre(emit, 1);
340
    emit_write_byte_code_byte_qstr(emit, MP_BC_IMPORT_FROM, qstr);
Damien's avatar
Damien committed
341
342
}

343
STATIC void emit_bc_import_star(emit_t *emit) {
Damien's avatar
Damien committed
344
    emit_pre(emit, -1);
345
    emit_write_byte_code_byte(emit, MP_BC_IMPORT_STAR);
Damien's avatar
Damien committed
346
347
}

348
STATIC void emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
Damien's avatar
Damien committed
349
350
    emit_pre(emit, 1);
    switch (tok) {
351
352
353
354
        case MP_TOKEN_KW_FALSE: emit_write_byte_code_byte(emit, MP_BC_LOAD_CONST_FALSE); break;
        case MP_TOKEN_KW_NONE: emit_write_byte_code_byte(emit, MP_BC_LOAD_CONST_NONE); break;
        case MP_TOKEN_KW_TRUE: emit_write_byte_code_byte(emit, MP_BC_LOAD_CONST_TRUE); break;
        case MP_TOKEN_ELLIPSIS: emit_write_byte_code_byte(emit, MP_BC_LOAD_CONST_ELLIPSIS); break;
Damien's avatar
Damien committed
355
356
357
358
        default: assert(0);
    }
}

359
STATIC void emit_bc_load_const_small_int(emit_t *emit, machine_int_t arg) {
Damien's avatar
Damien committed
360
    emit_pre(emit, 1);
361
    emit_write_byte_code_byte_int(emit, MP_BC_LOAD_CONST_SMALL_INT, arg);
Damien's avatar
Damien committed
362
363
}

364
STATIC void emit_bc_load_const_int(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
365
    emit_pre(emit, 1);
366
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_INT, qstr);
Damien's avatar
Damien committed
367
368
}

369
STATIC void emit_bc_load_const_dec(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
370
    emit_pre(emit, 1);
371
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_DEC, qstr);
Damien's avatar
Damien committed
372
373
}

374
STATIC void emit_bc_load_const_id(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
375
    emit_pre(emit, 1);
376
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_ID, qstr);
Damien's avatar
Damien committed
377
378
}

379
STATIC void emit_bc_load_const_str(emit_t *emit, qstr qstr, bool bytes) {
Damien's avatar
Damien committed
380
381
    emit_pre(emit, 1);
    if (bytes) {
382
        emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_BYTES, qstr);
Damien's avatar
Damien committed
383
    } else {
384
        emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_STRING, qstr);
Damien's avatar
Damien committed
385
386
387
    }
}

388
STATIC void emit_bc_load_const_verbatim_str(emit_t *emit, const char *str) {
389
    // not needed/supported for BC
Damien's avatar
Damien committed
390
391
392
    assert(0);
}

393
STATIC void emit_bc_load_fast(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
394
395
396
    assert(local_num >= 0);
    emit_pre(emit, 1);
    switch (local_num) {
397
398
399
400
        case 0: emit_write_byte_code_byte(emit, MP_BC_LOAD_FAST_0); break;
        case 1: emit_write_byte_code_byte(emit, MP_BC_LOAD_FAST_1); break;
        case 2: emit_write_byte_code_byte(emit, MP_BC_LOAD_FAST_2); break;
        default: emit_write_byte_code_byte_uint(emit, MP_BC_LOAD_FAST_N, local_num); break;
Damien's avatar
Damien committed
401
402
403
    }
}

404
STATIC void emit_bc_load_deref(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
405
    emit_pre(emit, 1);
406
    emit_write_byte_code_byte_uint(emit, MP_BC_LOAD_DEREF, local_num);
Damien's avatar
Damien committed
407
408
}

409
STATIC void emit_bc_load_closure(emit_t *emit, qstr qstr, int local_num) {
Damien George's avatar
Damien George committed
410
411
    // not needed/supported for BC
    assert(0);
Damien's avatar
Damien committed
412
413
}

414
STATIC void emit_bc_load_name(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
415
    emit_pre(emit, 1);
416
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_NAME, qstr);
Damien's avatar
Damien committed
417
418
}

419
STATIC void emit_bc_load_global(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
420
    emit_pre(emit, 1);
421
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_GLOBAL, qstr);
Damien's avatar
Damien committed
422
423
}

424
STATIC void emit_bc_load_attr(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
425
    emit_pre(emit, 0);
426
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_ATTR, qstr);
Damien's avatar
Damien committed
427
428
}

429
STATIC void emit_bc_load_method(emit_t *emit, qstr qstr) {
430
    emit_pre(emit, 1);
431
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_METHOD, qstr);
Damien's avatar
Damien committed
432
433
}

434
STATIC void emit_bc_load_build_class(emit_t *emit) {
Damien's avatar
Damien committed
435
    emit_pre(emit, 1);
436
    emit_write_byte_code_byte(emit, MP_BC_LOAD_BUILD_CLASS);
Damien's avatar
Damien committed
437
438
}

439
STATIC void emit_bc_store_fast(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
440
441
442
    assert(local_num >= 0);
    emit_pre(emit, -1);
    switch (local_num) {
443
444
445
446
        case 0: emit_write_byte_code_byte(emit, MP_BC_STORE_FAST_0); break;
        case 1: emit_write_byte_code_byte(emit, MP_BC_STORE_FAST_1); break;
        case 2: emit_write_byte_code_byte(emit, MP_BC_STORE_FAST_2); break;
        default: emit_write_byte_code_byte_uint(emit, MP_BC_STORE_FAST_N, local_num); break;
Damien's avatar
Damien committed
447
448
449
    }
}

450
STATIC void emit_bc_store_deref(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
451
    emit_pre(emit, -1);
452
    emit_write_byte_code_byte_uint(emit, MP_BC_STORE_DEREF, local_num);
Damien's avatar
Damien committed
453
454
}

455
STATIC void emit_bc_store_name(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
456
    emit_pre(emit, -1);
457
    emit_write_byte_code_byte_qstr(emit, MP_BC_STORE_NAME, qstr);
Damien's avatar
Damien committed
458
459
}

460
STATIC void emit_bc_store_global(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
461
    emit_pre(emit, -1);
462
    emit_write_byte_code_byte_qstr(emit, MP_BC_STORE_GLOBAL, qstr);
Damien's avatar
Damien committed
463
464
}

465
STATIC void emit_bc_store_attr(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
466
    emit_pre(emit, -2);
467
    emit_write_byte_code_byte_qstr(emit, MP_BC_STORE_ATTR, qstr);
Damien's avatar
Damien committed
468
469
}

470
STATIC void emit_bc_store_subscr(emit_t *emit) {
Damien's avatar
Damien committed
471
    emit_pre(emit, -3);
472
    emit_write_byte_code_byte(emit, MP_BC_STORE_SUBSCR);
Damien's avatar
Damien committed
473
474
}

475
STATIC void emit_bc_store_locals(emit_t *emit) {
476
    // not needed
477
    emit_pre(emit, -1);
478
    emit_write_byte_code_byte(emit, MP_BC_POP_TOP);
479
480
}

481
STATIC void emit_bc_delete_fast(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
482
483
    assert(local_num >= 0);
    emit_pre(emit, 0);
484
    emit_write_byte_code_byte_uint(emit, MP_BC_DELETE_FAST_N, local_num);
Damien's avatar
Damien committed
485
486
}

487
STATIC void emit_bc_delete_deref(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
488
    emit_pre(emit, 0);
489
    emit_write_byte_code_byte_qstr(emit, MP_BC_DELETE_DEREF, local_num);
Damien's avatar
Damien committed
490
491
}

492
STATIC void emit_bc_delete_name(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
493
    emit_pre(emit, 0);
494
    emit_write_byte_code_byte_qstr(emit, MP_BC_DELETE_NAME, qstr);
Damien's avatar
Damien committed
495
496
}

497
STATIC void emit_bc_delete_global(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
498
    emit_pre(emit, 0);
499
    emit_write_byte_code_byte_qstr(emit, MP_BC_DELETE_GLOBAL, qstr);
Damien's avatar
Damien committed
500
501
}

502
STATIC void emit_bc_delete_attr(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
503
    emit_pre(emit, -1);
504
    emit_write_byte_code_byte_qstr(emit, MP_BC_DELETE_ATTR, qstr);
Damien's avatar
Damien committed
505
506
}

507
STATIC void emit_bc_delete_subscr(emit_t *emit) {
Damien's avatar
Damien committed
508
    emit_pre(emit, -2);
509
    emit_write_byte_code_byte(emit, MP_BC_DELETE_SUBSCR);
Damien's avatar
Damien committed
510
511
}

512
STATIC void emit_bc_dup_top(emit_t *emit) {
Damien's avatar
Damien committed
513
    emit_pre(emit, 1);
514
    emit_write_byte_code_byte(emit, MP_BC_DUP_TOP);
Damien's avatar
Damien committed
515
516
}

517
STATIC void emit_bc_dup_top_two(emit_t *emit) {
Damien's avatar
Damien committed
518
    emit_pre(emit, 2);
519
    emit_write_byte_code_byte(emit, MP_BC_DUP_TOP_TWO);
Damien's avatar
Damien committed
520
521
}

522
STATIC void emit_bc_pop_top(emit_t *emit) {
Damien's avatar
Damien committed
523
    emit_pre(emit, -1);
524
    emit_write_byte_code_byte(emit, MP_BC_POP_TOP);
Damien's avatar
Damien committed
525
526
}

527
STATIC void emit_bc_rot_two(emit_t *emit) {
Damien's avatar
Damien committed
528
    emit_pre(emit, 0);
529
    emit_write_byte_code_byte(emit, MP_BC_ROT_TWO);
Damien's avatar
Damien committed
530
531
}

532
STATIC void emit_bc_rot_three(emit_t *emit) {
Damien's avatar
Damien committed
533
    emit_pre(emit, 0);
534
    emit_write_byte_code_byte(emit, MP_BC_ROT_THREE);
Damien's avatar
Damien committed
535
536
}

537
STATIC void emit_bc_jump(emit_t *emit, int label) {
Damien's avatar
Damien committed
538
    emit_pre(emit, 0);
539
    emit_write_byte_code_byte_signed_label(emit, MP_BC_JUMP, label);
Damien's avatar
Damien committed
540
541
}

542
STATIC void emit_bc_pop_jump_if_true(emit_t *emit, int label) {
Damien's avatar
Damien committed
543
    emit_pre(emit, -1);
544
    emit_write_byte_code_byte_signed_label(emit, MP_BC_POP_JUMP_IF_TRUE, label);
Damien's avatar
Damien committed
545
546
}

547
STATIC void emit_bc_pop_jump_if_false(emit_t *emit, int label) {
Damien's avatar
Damien committed
548
    emit_pre(emit, -1);
549
    emit_write_byte_code_byte_signed_label(emit, MP_BC_POP_JUMP_IF_FALSE, label);
Damien's avatar
Damien committed
550
551
}

552
STATIC void emit_bc_jump_if_true_or_pop(emit_t *emit, int label) {
Damien's avatar
Damien committed
553
    emit_pre(emit, -1);
554
    emit_write_byte_code_byte_signed_label(emit, MP_BC_JUMP_IF_TRUE_OR_POP, label);
Damien's avatar
Damien committed
555
556
}

557
STATIC void emit_bc_jump_if_false_or_pop(emit_t *emit, int label) {
Damien's avatar
Damien committed
558
    emit_pre(emit, -1);
559
    emit_write_byte_code_byte_signed_label(emit, MP_BC_JUMP_IF_FALSE_OR_POP, label);
Damien's avatar
Damien committed
560
561
}

562
STATIC void emit_bc_setup_loop(emit_t *emit, int label) {
Damien's avatar
Damien committed
563
    emit_pre(emit, 0);
564
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_SETUP_LOOP, label);
Damien's avatar
Damien committed
565
566
}

567
STATIC void emit_bc_unwind_jump(emit_t *emit, int label, int except_depth) {
568
569
570
571
572
573
574
    if (except_depth == 0) {
        emit_bc_jump(emit, label);
    } else {
        emit_pre(emit, 0);
        emit_write_byte_code_byte_signed_label(emit, MP_BC_UNWIND_JUMP, label);
        emit_write_byte_code_byte(emit, except_depth);
    }
Damien's avatar
Damien committed
575
576
}

577
STATIC void emit_bc_setup_with(emit_t *emit, int label) {
Damien's avatar
Damien committed
578
    emit_pre(emit, 7);
579
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_SETUP_WITH, label);
Damien's avatar
Damien committed
580
581
}

582
STATIC void emit_bc_with_cleanup(emit_t *emit) {
Damien's avatar
Damien committed
583
    emit_pre(emit, -7);
584
    emit_write_byte_code_byte(emit, MP_BC_WITH_CLEANUP);
Damien's avatar
Damien committed
585
586
}

587
STATIC void emit_bc_setup_except(emit_t *emit, int label) {
Damien's avatar
Damien committed
588
    emit_pre(emit, 6);
589
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_SETUP_EXCEPT, label);
Damien's avatar
Damien committed
590
591
}

592
STATIC void emit_bc_setup_finally(emit_t *emit, int label) {
Damien's avatar
Damien committed
593
    emit_pre(emit, 6);
594
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_SETUP_FINALLY, label);
Damien's avatar
Damien committed
595
596
}

597
STATIC void emit_bc_end_finally(emit_t *emit) {
Damien's avatar
Damien committed
598
    emit_pre(emit, -1);
599
    emit_write_byte_code_byte(emit, MP_BC_END_FINALLY);
Damien's avatar
Damien committed
600
601
}

602
STATIC void emit_bc_get_iter(emit_t *emit) {
Damien's avatar
Damien committed
603
    emit_pre(emit, 0);
604
    emit_write_byte_code_byte(emit, MP_BC_GET_ITER);
Damien's avatar
Damien committed
605
606
}

607
STATIC void emit_bc_for_iter(emit_t *emit, int label) {
Damien's avatar
Damien committed
608
    emit_pre(emit, 1);
609
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_FOR_ITER, label);
Damien's avatar
Damien committed
610
611
}

612
STATIC void emit_bc_for_iter_end(emit_t *emit) {
Damien's avatar
Damien committed
613
614
615
    emit_pre(emit, -1);
}

616
STATIC void emit_bc_pop_block(emit_t *emit) {
Damien's avatar
Damien committed
617
    emit_pre(emit, 0);
618
    emit_write_byte_code_byte(emit, MP_BC_POP_BLOCK);
Damien's avatar
Damien committed
619
620
}

621
STATIC void emit_bc_pop_except(emit_t *emit) {
Damien's avatar
Damien committed
622
    emit_pre(emit, 0);
623
    emit_write_byte_code_byte(emit, MP_BC_POP_EXCEPT);
Damien's avatar
Damien committed
624
625
}

626
STATIC void emit_bc_unary_op(emit_t *emit, rt_unary_op_t op) {
627
628
629
630
631
632
633
634
635
    if (op == RT_UNARY_OP_NOT) {
        emit_pre(emit, 0);
        emit_write_byte_code_byte_byte(emit, MP_BC_UNARY_OP, RT_UNARY_OP_BOOL);
        emit_pre(emit, 0);
        emit_write_byte_code_byte(emit, MP_BC_NOT);
    } else {
        emit_pre(emit, 0);
        emit_write_byte_code_byte_byte(emit, MP_BC_UNARY_OP, op);
    }
Damien's avatar
Damien committed
636
637
}

638
STATIC void emit_bc_binary_op(emit_t *emit, rt_binary_op_t op) {
639
640
641
642
643
644
645
646
    bool invert = false;
    if (op == RT_BINARY_OP_NOT_IN) {
        invert = true;
        op = RT_BINARY_OP_IN;
    } else if (op == RT_BINARY_OP_IS_NOT) {
        invert = true;
        op = RT_BINARY_OP_IS;
    }
Damien's avatar
Damien committed
647
    emit_pre(emit, -1);
648
    emit_write_byte_code_byte_byte(emit, MP_BC_BINARY_OP, op);
649
650
651
652
    if (invert) {
        emit_pre(emit, 0);
        emit_write_byte_code_byte(emit, MP_BC_NOT);
    }
Damien's avatar
Damien committed
653
654
}

655
STATIC void emit_bc_build_tuple(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
656
657
    assert(n_args >= 0);
    emit_pre(emit, 1 - n_args);
658
    emit_write_byte_code_byte_uint(emit, MP_BC_BUILD_TUPLE, n_args);
Damien's avatar
Damien committed
659
660
}

661
STATIC void emit_bc_build_list(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
662
663
    assert(n_args >= 0);
    emit_pre(emit, 1 - n_args);
664
    emit_write_byte_code_byte_uint(emit, MP_BC_BUILD_LIST, n_args);
Damien's avatar
Damien committed
665
666
}

667
STATIC void emit_bc_list_append(emit_t *emit, int list_stack_index) {
Damien's avatar
Damien committed
668
669
    assert(list_stack_index >= 0);
    emit_pre(emit, -1);
670
    emit_write_byte_code_byte_uint(emit, MP_BC_LIST_APPEND, list_stack_index);
Damien's avatar
Damien committed
671
672
}

673
STATIC void emit_bc_build_map(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
674
675
    assert(n_args >= 0);
    emit_pre(emit, 1);
676
    emit_write_byte_code_byte_uint(emit, MP_BC_BUILD_MAP, n_args);
Damien's avatar
Damien committed
677
678
}

679
STATIC void emit_bc_store_map(emit_t *emit) {
Damien's avatar
Damien committed
680
    emit_pre(emit, -2);
681
    emit_write_byte_code_byte(emit, MP_BC_STORE_MAP);
Damien's avatar
Damien committed
682
683
}

684
STATIC void emit_bc_map_add(emit_t *emit, int map_stack_index) {
Damien's avatar
Damien committed
685
686
    assert(map_stack_index >= 0);
    emit_pre(emit, -2);
687
    emit_write_byte_code_byte_uint(emit, MP_BC_MAP_ADD, map_stack_index);
Damien's avatar
Damien committed
688
689
}

690
STATIC void emit_bc_build_set(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
691
692
    assert(n_args >= 0);
    emit_pre(emit, 1 - n_args);
693
    emit_write_byte_code_byte_uint(emit, MP_BC_BUILD_SET, n_args);
Damien's avatar
Damien committed
694
695
}

696
STATIC void emit_bc_set_add(emit_t *emit, int set_stack_index) {
Damien's avatar
Damien committed
697
698
    assert(set_stack_index >= 0);
    emit_pre(emit, -1);
699
    emit_write_byte_code_byte_uint(emit, MP_BC_SET_ADD, set_stack_index);
Damien's avatar
Damien committed
700
701
}

702
STATIC void emit_bc_build_slice(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
703
704
    assert(n_args >= 0);
    emit_pre(emit, 1 - n_args);
705
    emit_write_byte_code_byte_uint(emit, MP_BC_BUILD_SLICE, n_args);
Damien's avatar
Damien committed
706
707
}

708
STATIC void emit_bc_unpack_sequence(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
709
710
    assert(n_args >= 0);
    emit_pre(emit, -1 + n_args);
711
    emit_write_byte_code_byte_uint(emit, MP_BC_UNPACK_SEQUENCE, n_args);
Damien's avatar
Damien committed
712
713
}

714
STATIC void emit_bc_unpack_ex(emit_t *emit, int n_left, int n_right) {
Damien's avatar
Damien committed
715
716
    assert(n_left >=0 && n_right >= 0);
    emit_pre(emit, -1 + n_left + n_right + 1);
717
    emit_write_byte_code_byte_uint(emit, MP_BC_UNPACK_EX, n_left | (n_right << 8));
Damien's avatar
Damien committed
718
719
}

720
STATIC void emit_bc_make_function(emit_t *emit, scope_t *scope, int n_dict_params, int n_default_params) {
721
    assert(n_dict_params == 0);
722
723
724
725
    if (n_default_params == 0) {
        emit_pre(emit, 1);
        emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_FUNCTION, scope->unique_code_id);
    } else {
726
727
728
729
        emit_bc_build_tuple(emit, n_default_params);
        emit_pre(emit, 0);
        emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_FUNCTION_DEFARGS, scope->unique_code_id);
    }
Damien's avatar
Damien committed
730
731
}

732
STATIC void emit_bc_make_closure(emit_t *emit, scope_t *scope, int n_dict_params, int n_default_params) {
Damien's avatar
Damien committed
733
734
    assert(n_default_params == 0 && n_dict_params == 0);
    emit_pre(emit, 0);
735
    emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_CLOSURE, scope->unique_code_id);
Damien's avatar
Damien committed
736
737
}

738
STATIC void emit_bc_call_function(emit_t *emit, int n_positional, int n_keyword, bool have_star_arg, bool have_dbl_star_arg) {
Damien's avatar
Damien committed
739
740
741
742
743
744
745
746
747
748
749
    int s = 0;
    if (have_star_arg) {
        s += 1;
    }
    if (have_dbl_star_arg) {
        s += 1;
    }
    emit_pre(emit, -n_positional - 2 * n_keyword - s);
    int op;
    if (have_star_arg) {
        if (have_dbl_star_arg) {
750
            op = MP_BC_CALL_FUNCTION_VAR_KW;
Damien's avatar
Damien committed
751
        } else {
752
            op = MP_BC_CALL_FUNCTION_VAR;
Damien's avatar
Damien committed
753
754
755
        }
    } else {
        if (have_dbl_star_arg) {
756
            op = MP_BC_CALL_FUNCTION_KW;
Damien's avatar
Damien committed
757
        } else {
758
            op = MP_BC_CALL_FUNCTION;
Damien's avatar
Damien committed
759
760
        }
    }
761
    emit_write_byte_code_byte_uint(emit, op, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints
Damien's avatar
Damien committed
762
763
}

764
STATIC void emit_bc_call_method(emit_t *emit, int n_positional, int n_keyword, bool have_star_arg, bool have_dbl_star_arg) {
Damien's avatar
Damien committed
765
766
767
768
769
770
771
    int s = 0;
    if (have_star_arg) {
        s += 1;
    }
    if (have_dbl_star_arg) {
        s += 1;
    }
772
    emit_pre(emit, -1 - n_positional - 2 * n_keyword - s);
Damien's avatar
Damien committed
773
774
775
    int op;
    if (have_star_arg) {
        if (have_dbl_star_arg) {
776
            op = MP_BC_CALL_METHOD_VAR_KW;
Damien's avatar
Damien committed
777
        } else {
778
            op = MP_BC_CALL_METHOD_VAR;
Damien's avatar
Damien committed
779
780
781
        }
    } else {
        if (have_dbl_star_arg) {
782
            op = MP_BC_CALL_METHOD_KW;
Damien's avatar
Damien committed
783
        } else {
784
            op = MP_BC_CALL_METHOD;
Damien's avatar
Damien committed
785
786
        }
    }
787
    emit_write_byte_code_byte_uint(emit, op, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints
Damien's avatar
Damien committed
788
789
}

790
STATIC void emit_bc_return_value(emit_t *emit) {
Damien's avatar
Damien committed
791
792
    emit_pre(emit, -1);
    emit->last_emit_was_return_value = true;
793
    emit_write_byte_code_byte(emit, MP_BC_RETURN_VALUE);
Damien's avatar
Damien committed
794
795
}

796
STATIC void emit_bc_raise_varargs(emit_t *emit, int n_args) {
797
    assert(0 <= n_args && n_args <= 2);
Damien's avatar
Damien committed
798
    emit_pre(emit, -n_args);
799
    emit_write_byte_code_byte_byte(emit, MP_BC_RAISE_VARARGS, n_args);
Damien's avatar
Damien committed
800
801
}

802
STATIC void emit_bc_yield_value(emit_t *emit) {
Damien's avatar
Damien committed
803
804
    emit_pre(emit, 0);
    if (emit->pass == PASS_2) {
805
        emit->scope->scope_flags |= MP_SCOPE_FLAG_GENERATOR;
Damien's avatar
Damien committed
806
    }
807
    emit_write_byte_code_byte(emit, MP_BC_YIELD_VALUE);
Damien's avatar
Damien committed
808
809
}

810
STATIC void emit_bc_yield_from(emit_t *emit) {
Damien's avatar
Damien committed
811
812
    emit_pre(emit, -1);
    if (emit->pass == PASS_2) {
813
        emit->scope->scope_flags |= MP_SCOPE_FLAG_GENERATOR;
Damien's avatar
Damien committed
814
    }
815
    emit_write_byte_code_byte(emit, MP_BC_YIELD_FROM);
Damien's avatar
Damien committed
816
817
}

818
const emit_method_table_t emit_bc_method_table = {
819
820
821
822
823
824
    emit_bc_set_native_types,
    emit_bc_start_pass,
    emit_bc_end_pass,
    emit_bc_last_emit_was_return_value,
    emit_bc_get_stack_size,
    emit_bc_set_stack_size,
825
    emit_bc_set_source_line,
826

827
828
829
830
    emit_bc_load_id,
    emit_bc_store_id,
    emit_bc_delete_id,

831
832
833
834
835
836
837
838
839
840
841
842
843
844
    emit_bc_label_assign,
    emit_bc_import_name,
    emit_bc_import_from,
    emit_bc_import_star,
    emit_bc_load_const_tok,
    emit_bc_load_const_small_int,
    emit_bc_load_const_int,
    emit_bc_load_const_dec,
    emit_bc_load_const_id,
    emit_bc_load_const_str,
    emit_bc_load_const_verbatim_str,
    emit_bc_load_fast,
    emit_bc_load_deref,
    emit_bc_load_closure,
Damien's avatar
Damien committed
845
846
    emit_bc_load_name,
    emit_bc_load_global,
847
848
849
850
    emit_bc_load_attr,
    emit_bc_load_method,
    emit_bc_load_build_class,
    emit_bc_store_fast,
Damien's avatar
Damien committed
851
    emit_bc_store_deref,
852
853
854
855
    emit_bc_store_name,
    emit_bc_store_global,
    emit_bc_store_attr,
    emit_bc_store_subscr,
856
    emit_bc_store_locals,
857
    emit_bc_delete_fast,
Damien's avatar
Damien committed
858
    emit_bc_delete_deref,
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
    emit_bc_delete_name,
    emit_bc_delete_global,
    emit_bc_delete_attr,
    emit_bc_delete_subscr,
    emit_bc_dup_top,
    emit_bc_dup_top_two,
    emit_bc_pop_top,
    emit_bc_rot_two,
    emit_bc_rot_three,
    emit_bc_jump,
    emit_bc_pop_jump_if_true,
    emit_bc_pop_jump_if_false,
    emit_bc_jump_if_true_or_pop,
    emit_bc_jump_if_false_or_pop,
    emit_bc_setup_loop,
874
875
    emit_bc_unwind_jump,
    emit_bc_unwind_jump,
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
    emit_bc_setup_with,
    emit_bc_with_cleanup,
    emit_bc_setup_except,
    emit_bc_setup_finally,
    emit_bc_end_finally,
    emit_bc_get_iter,
    emit_bc_for_iter,
    emit_bc_for_iter_end,
    emit_bc_pop_block,
    emit_bc_pop_except,
    emit_bc_unary_op,
    emit_bc_binary_op,
    emit_bc_build_tuple,
    emit_bc_build_list,
    emit_bc_list_append,
    emit_bc_build_map,
    emit_bc_store_map,
    emit_bc_map_add,
    emit_bc_build_set,
    emit_bc_set_add,
    emit_bc_build_slice,
    emit_bc_unpack_sequence,
    emit_bc_unpack_ex,
    emit_bc_make_function,
    emit_bc_make_closure,
    emit_bc_call_function,
    emit_bc_call_method,
    emit_bc_return_value,
    emit_bc_raise_varargs,
    emit_bc_yield_value,
    emit_bc_yield_from,
};