emitbc.c 28.5 KB
Newer Older
xbe's avatar
xbe committed
1
#include <stdbool.h>
Damien's avatar
Damien committed
2
3
4
5
6
7
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>

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

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

    scope_t *scope;

24
25
26
    uint last_source_line_offset;
    uint last_source_line;

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

30
31
32
33
34
    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
35
36
37
    byte dummy_data[8];
};

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

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

50
// all functions must go through this one to emit code info
51
STATIC byte* emit_get_cur_to_write_code_info(emit_t* emit, int num_bytes_to_write) {
52
53
54
55
56
57
58
59
60
61
    //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
62
63
}

64
STATIC void emit_write_code_info_qstr(emit_t* emit, qstr qstr) {
65
66
67
68
69
70
    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
71
72
}

73
STATIC void emit_write_code_info_bytes_lines(emit_t* emit, uint bytes_to_skip, uint lines_to_skip) {
74
75
76
77
78
79
80
    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);
81
82
83
}

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

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

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

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

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

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

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

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

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

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

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

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

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

227
228
229
230
231
232
233
234
    // bytecode prelude: exception stack size; 16 bit uint for now
    {
        byte* c = emit_get_cur_to_write_byte_code(emit, 2);
        c[0] = scope->exc_stack_size & 0xff;
        c[1] = (scope->exc_stack_size >> 8) & 0xff;
    }

    // bytecode prelude: initialise closed over variables
Damien George's avatar
Damien George committed
235
236
237
238
239
240
241
242
    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);
243
    emit_write_byte_code_byte(emit, num_cell); // write number of locals that are cells
Damien George's avatar
Damien George committed
244
245
246
    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) {
247
            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
248
249
250
251
        }
    }
}

252
STATIC void emit_bc_end_pass(emit_t *emit) {
Damien George's avatar
Damien George committed
253
254
255
256
257
    // 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);
    }

258
    emit_write_code_info_bytes_lines(emit, 0, 0); // end of line number info
259

Damien George's avatar
Damien George committed
260
261
    if (emit->pass == PASS_2) {
        // calculate size of code in bytes
262
263
264
        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
265
266

    } else if (emit->pass == PASS_3) {
267
268
269
270
271
272
273
274
        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
275
276
277
    }
}

278
bool emit_bc_last_emit_was_return_value(emit_t *emit) {
Damien's avatar
Damien committed
279
280
281
    return emit->last_emit_was_return_value;
}

282
int emit_bc_get_stack_size(emit_t *emit) {
Damien's avatar
Damien committed
283
284
285
    return emit->stack_size;
}

286
STATIC void emit_bc_set_stack_size(emit_t *emit, int size) {
287
    emit->stack_size = size;
Damien's avatar
Damien committed
288
289
}

290
STATIC void emit_bc_set_source_line(emit_t *emit, int source_line) {
291
    //printf("source: line %d -> %d  offset %d -> %d\n", emit->last_source_line, source_line, emit->last_source_line_offset, emit->byte_code_offset);
292
#if MICROPY_ENABLE_SOURCE_LINE
293
    if (source_line > emit->last_source_line) {
294
295
296
        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);
297
        //printf("  %d %d\n", bytes_to_skip, lines_to_skip);
298
299
300
        emit->last_source_line_offset = emit->byte_code_offset;
        emit->last_source_line = source_line;
    }
301
#endif
302
303
}

304
STATIC void emit_bc_load_id(emit_t *emit, qstr qstr) {
305
306
307
    emit_common_load_id(emit, &emit_bc_method_table, emit->scope, qstr);
}

308
STATIC void emit_bc_store_id(emit_t *emit, qstr qstr) {
309
310
311
    emit_common_store_id(emit, &emit_bc_method_table, emit->scope, qstr);
}

312
STATIC void emit_bc_delete_id(emit_t *emit, qstr qstr) {
313
314
315
    emit_common_delete_id(emit, &emit_bc_method_table, emit->scope, qstr);
}

316
// TODO: module-polymorphic function (read: name clash if made global)
317
static void emit_pre(emit_t *emit, int stack_size_delta) {
318
319
320
    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
321
322
323
324
    }
    emit->last_emit_was_return_value = false;
}

325
STATIC void emit_bc_label_assign(emit_t *emit, int l) {
Damien's avatar
Damien committed
326
    emit_pre(emit, 0);
327
328
329
330
    assert(l < emit->max_num_labels);
    if (emit->pass == PASS_2) {
        // assign label offset
        assert(emit->label_offsets[l] == -1);
331
        emit->label_offsets[l] = emit->byte_code_offset;
332
333
    } else if (emit->pass == PASS_3) {
        // ensure label offset has not changed from PASS_2 to PASS_3
334
335
        //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
336
337
338
    }
}

339
STATIC void emit_bc_import_name(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
340
    emit_pre(emit, -1);
341
    emit_write_byte_code_byte_qstr(emit, MP_BC_IMPORT_NAME, qstr);
Damien's avatar
Damien committed
342
343
}

344
STATIC void emit_bc_import_from(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
345
    emit_pre(emit, 1);
346
    emit_write_byte_code_byte_qstr(emit, MP_BC_IMPORT_FROM, qstr);
Damien's avatar
Damien committed
347
348
}

349
STATIC void emit_bc_import_star(emit_t *emit) {
Damien's avatar
Damien committed
350
    emit_pre(emit, -1);
351
    emit_write_byte_code_byte(emit, MP_BC_IMPORT_STAR);
Damien's avatar
Damien committed
352
353
}

354
STATIC void emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
Damien's avatar
Damien committed
355
356
    emit_pre(emit, 1);
    switch (tok) {
357
358
359
360
        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
361
362
363
364
        default: assert(0);
    }
}

365
STATIC void emit_bc_load_const_small_int(emit_t *emit, machine_int_t arg) {
Damien's avatar
Damien committed
366
    emit_pre(emit, 1);
367
    emit_write_byte_code_byte_int(emit, MP_BC_LOAD_CONST_SMALL_INT, arg);
Damien's avatar
Damien committed
368
369
}

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

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

380
STATIC void emit_bc_load_const_id(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
381
    emit_pre(emit, 1);
382
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_ID, qstr);
Damien's avatar
Damien committed
383
384
}

385
STATIC void emit_bc_load_const_str(emit_t *emit, qstr qstr, bool bytes) {
Damien's avatar
Damien committed
386
387
    emit_pre(emit, 1);
    if (bytes) {
388
        emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_BYTES, qstr);
Damien's avatar
Damien committed
389
    } else {
390
        emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_STRING, qstr);
Damien's avatar
Damien committed
391
392
393
    }
}

394
STATIC void emit_bc_load_const_verbatim_str(emit_t *emit, const char *str) {
395
    // not needed/supported for BC
Damien's avatar
Damien committed
396
397
398
    assert(0);
}

399
STATIC void emit_bc_load_fast(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
400
401
402
    assert(local_num >= 0);
    emit_pre(emit, 1);
    switch (local_num) {
403
404
405
406
        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
407
408
409
    }
}

410
STATIC void emit_bc_load_deref(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
411
    emit_pre(emit, 1);
412
    emit_write_byte_code_byte_uint(emit, MP_BC_LOAD_DEREF, local_num);
Damien's avatar
Damien committed
413
414
}

415
STATIC void emit_bc_load_closure(emit_t *emit, qstr qstr, int local_num) {
Damien George's avatar
Damien George committed
416
417
    // not needed/supported for BC
    assert(0);
Damien's avatar
Damien committed
418
419
}

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

425
STATIC void emit_bc_load_global(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
426
    emit_pre(emit, 1);
427
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_GLOBAL, qstr);
Damien's avatar
Damien committed
428
429
}

430
STATIC void emit_bc_load_attr(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
431
    emit_pre(emit, 0);
432
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_ATTR, qstr);
Damien's avatar
Damien committed
433
434
}

435
STATIC void emit_bc_load_method(emit_t *emit, qstr qstr) {
436
    emit_pre(emit, 1);
437
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_METHOD, qstr);
Damien's avatar
Damien committed
438
439
}

440
STATIC void emit_bc_load_build_class(emit_t *emit) {
Damien's avatar
Damien committed
441
    emit_pre(emit, 1);
442
    emit_write_byte_code_byte(emit, MP_BC_LOAD_BUILD_CLASS);
Damien's avatar
Damien committed
443
444
}

445
STATIC void emit_bc_store_fast(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
446
447
448
    assert(local_num >= 0);
    emit_pre(emit, -1);
    switch (local_num) {
449
450
451
452
        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
453
454
455
    }
}

456
STATIC void emit_bc_store_deref(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
457
    emit_pre(emit, -1);
458
    emit_write_byte_code_byte_uint(emit, MP_BC_STORE_DEREF, local_num);
Damien's avatar
Damien committed
459
460
}

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

466
STATIC void emit_bc_store_global(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
467
    emit_pre(emit, -1);
468
    emit_write_byte_code_byte_qstr(emit, MP_BC_STORE_GLOBAL, qstr);
Damien's avatar
Damien committed
469
470
}

471
STATIC void emit_bc_store_attr(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
472
    emit_pre(emit, -2);
473
    emit_write_byte_code_byte_qstr(emit, MP_BC_STORE_ATTR, qstr);
Damien's avatar
Damien committed
474
475
}

476
STATIC void emit_bc_store_subscr(emit_t *emit) {
Damien's avatar
Damien committed
477
    emit_pre(emit, -3);
478
    emit_write_byte_code_byte(emit, MP_BC_STORE_SUBSCR);
Damien's avatar
Damien committed
479
480
}

481
STATIC void emit_bc_store_locals(emit_t *emit) {
482
    // not needed
483
    emit_pre(emit, -1);
484
    emit_write_byte_code_byte(emit, MP_BC_POP_TOP);
485
486
}

487
STATIC void emit_bc_delete_fast(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
488
489
    assert(local_num >= 0);
    emit_pre(emit, 0);
490
    emit_write_byte_code_byte_uint(emit, MP_BC_DELETE_FAST_N, local_num);
Damien's avatar
Damien committed
491
492
}

493
STATIC void emit_bc_delete_deref(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
494
    emit_pre(emit, 0);
495
    emit_write_byte_code_byte_qstr(emit, MP_BC_DELETE_DEREF, local_num);
Damien's avatar
Damien committed
496
497
}

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

503
STATIC void emit_bc_delete_global(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
504
    emit_pre(emit, 0);
505
    emit_write_byte_code_byte_qstr(emit, MP_BC_DELETE_GLOBAL, qstr);
Damien's avatar
Damien committed
506
507
}

508
STATIC void emit_bc_delete_attr(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
509
    emit_pre(emit, -1);
510
    emit_write_byte_code_byte_qstr(emit, MP_BC_DELETE_ATTR, qstr);
Damien's avatar
Damien committed
511
512
}

513
STATIC void emit_bc_delete_subscr(emit_t *emit) {
Damien's avatar
Damien committed
514
    emit_pre(emit, -2);
515
    emit_write_byte_code_byte(emit, MP_BC_DELETE_SUBSCR);
Damien's avatar
Damien committed
516
517
}

518
STATIC void emit_bc_dup_top(emit_t *emit) {
Damien's avatar
Damien committed
519
    emit_pre(emit, 1);
520
    emit_write_byte_code_byte(emit, MP_BC_DUP_TOP);
Damien's avatar
Damien committed
521
522
}

523
STATIC void emit_bc_dup_top_two(emit_t *emit) {
Damien's avatar
Damien committed
524
    emit_pre(emit, 2);
525
    emit_write_byte_code_byte(emit, MP_BC_DUP_TOP_TWO);
Damien's avatar
Damien committed
526
527
}

528
STATIC void emit_bc_pop_top(emit_t *emit) {
Damien's avatar
Damien committed
529
    emit_pre(emit, -1);
530
    emit_write_byte_code_byte(emit, MP_BC_POP_TOP);
Damien's avatar
Damien committed
531
532
}

533
STATIC void emit_bc_rot_two(emit_t *emit) {
Damien's avatar
Damien committed
534
    emit_pre(emit, 0);
535
    emit_write_byte_code_byte(emit, MP_BC_ROT_TWO);
Damien's avatar
Damien committed
536
537
}

538
STATIC void emit_bc_rot_three(emit_t *emit) {
Damien's avatar
Damien committed
539
    emit_pre(emit, 0);
540
    emit_write_byte_code_byte(emit, MP_BC_ROT_THREE);
Damien's avatar
Damien committed
541
542
}

543
STATIC void emit_bc_jump(emit_t *emit, int label) {
Damien's avatar
Damien committed
544
    emit_pre(emit, 0);
545
    emit_write_byte_code_byte_signed_label(emit, MP_BC_JUMP, label);
Damien's avatar
Damien committed
546
547
}

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

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

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

563
STATIC void emit_bc_jump_if_false_or_pop(emit_t *emit, int label) {
Damien's avatar
Damien committed
564
    emit_pre(emit, -1);
565
    emit_write_byte_code_byte_signed_label(emit, MP_BC_JUMP_IF_FALSE_OR_POP, label);
Damien's avatar
Damien committed
566
567
}

568
STATIC void emit_bc_setup_loop(emit_t *emit, int label) {
Damien's avatar
Damien committed
569
    emit_pre(emit, 0);
570
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_SETUP_LOOP, label);
Damien's avatar
Damien committed
571
572
}

573
STATIC void emit_bc_unwind_jump(emit_t *emit, int label, int except_depth) {
574
575
576
577
578
579
580
    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
581
582
}

583
STATIC void emit_bc_setup_with(emit_t *emit, int label) {
Damien's avatar
Damien committed
584
    emit_pre(emit, 7);
585
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_SETUP_WITH, label);
Damien's avatar
Damien committed
586
587
}

588
STATIC void emit_bc_with_cleanup(emit_t *emit) {
Damien's avatar
Damien committed
589
    emit_pre(emit, -7);
590
    emit_write_byte_code_byte(emit, MP_BC_WITH_CLEANUP);
Damien's avatar
Damien committed
591
592
}

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

598
STATIC void emit_bc_setup_finally(emit_t *emit, int label) {
Damien's avatar
Damien committed
599
    emit_pre(emit, 6);
600
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_SETUP_FINALLY, label);
Damien's avatar
Damien committed
601
602
}

603
STATIC void emit_bc_end_finally(emit_t *emit) {
Damien's avatar
Damien committed
604
    emit_pre(emit, -1);
605
    emit_write_byte_code_byte(emit, MP_BC_END_FINALLY);
Damien's avatar
Damien committed
606
607
}

608
STATIC void emit_bc_get_iter(emit_t *emit) {
Damien's avatar
Damien committed
609
    emit_pre(emit, 0);
610
    emit_write_byte_code_byte(emit, MP_BC_GET_ITER);
Damien's avatar
Damien committed
611
612
}

613
STATIC void emit_bc_for_iter(emit_t *emit, int label) {
Damien's avatar
Damien committed
614
    emit_pre(emit, 1);
615
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_FOR_ITER, label);
Damien's avatar
Damien committed
616
617
}

618
STATIC void emit_bc_for_iter_end(emit_t *emit) {
Damien's avatar
Damien committed
619
620
621
    emit_pre(emit, -1);
}

622
STATIC void emit_bc_pop_block(emit_t *emit) {
Damien's avatar
Damien committed
623
    emit_pre(emit, 0);
624
    emit_write_byte_code_byte(emit, MP_BC_POP_BLOCK);
Damien's avatar
Damien committed
625
626
}

627
STATIC void emit_bc_pop_except(emit_t *emit) {
Damien's avatar
Damien committed
628
    emit_pre(emit, 0);
629
    emit_write_byte_code_byte(emit, MP_BC_POP_EXCEPT);
Damien's avatar
Damien committed
630
631
}

632
STATIC void emit_bc_unary_op(emit_t *emit, rt_unary_op_t op) {
633
634
635
636
637
638
639
640
641
    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
642
643
}

644
STATIC void emit_bc_binary_op(emit_t *emit, rt_binary_op_t op) {
645
646
647
648
649
650
651
652
    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
653
    emit_pre(emit, -1);
654
    emit_write_byte_code_byte_byte(emit, MP_BC_BINARY_OP, op);
655
656
657
658
    if (invert) {
        emit_pre(emit, 0);
        emit_write_byte_code_byte(emit, MP_BC_NOT);
    }
Damien's avatar
Damien committed
659
660
}

661
STATIC void emit_bc_build_tuple(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_TUPLE, n_args);
Damien's avatar
Damien committed
665
666
}

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

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

679
STATIC void emit_bc_build_map(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
680
681
    assert(n_args >= 0);
    emit_pre(emit, 1);
682
    emit_write_byte_code_byte_uint(emit, MP_BC_BUILD_MAP, n_args);
Damien's avatar
Damien committed
683
684
}

685
STATIC void emit_bc_store_map(emit_t *emit) {
Damien's avatar
Damien committed
686
    emit_pre(emit, -2);
687
    emit_write_byte_code_byte(emit, MP_BC_STORE_MAP);
Damien's avatar
Damien committed
688
689
}

690
STATIC void emit_bc_map_add(emit_t *emit, int map_stack_index) {
Damien's avatar
Damien committed
691
692
    assert(map_stack_index >= 0);
    emit_pre(emit, -2);
693
    emit_write_byte_code_byte_uint(emit, MP_BC_MAP_ADD, map_stack_index);
Damien's avatar
Damien committed
694
695
}

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

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

708
STATIC void emit_bc_build_slice(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_BUILD_SLICE, n_args);
Damien's avatar
Damien committed
712
713
}

714
STATIC void emit_bc_unpack_sequence(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
715
716
    assert(n_args >= 0);
    emit_pre(emit, -1 + n_args);
717
    emit_write_byte_code_byte_uint(emit, MP_BC_UNPACK_SEQUENCE, n_args);
Damien's avatar
Damien committed
718
719
}

720
STATIC void emit_bc_unpack_ex(emit_t *emit, int n_left, int n_right) {
Damien's avatar
Damien committed
721
722
    assert(n_left >=0 && n_right >= 0);
    emit_pre(emit, -1 + n_left + n_right + 1);
723
    emit_write_byte_code_byte_uint(emit, MP_BC_UNPACK_EX, n_left | (n_right << 8));
Damien's avatar
Damien committed
724
725
}

726
STATIC void emit_bc_make_function(emit_t *emit, scope_t *scope, int n_dict_params, int n_default_params) {
727
    assert(n_dict_params == 0);
728
729
730
731
    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 {
732
733
734
        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
735
736
}

737
STATIC void emit_bc_make_closure(emit_t *emit, scope_t *scope, int n_dict_params, int n_default_params) {
738
739
740
741
742
743
744
745
    assert(n_dict_params == 0);
    if (n_default_params == 0) {
        emit_pre(emit, 0);
        emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_CLOSURE, scope->unique_code_id);
    } else {
        emit_pre(emit, -1);
        emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_CLOSURE_DEFARGS, scope->unique_code_id);
    }
Damien's avatar
Damien committed
746
747
}

748
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
749
750
751
752
753
754
755
756
757
758
759
    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) {
760
            op = MP_BC_CALL_FUNCTION_VAR_KW;
Damien's avatar
Damien committed
761
        } else {
762
            op = MP_BC_CALL_FUNCTION_VAR;
Damien's avatar
Damien committed
763
764
765
        }
    } else {
        if (have_dbl_star_arg) {
766
            op = MP_BC_CALL_FUNCTION_KW;
Damien's avatar
Damien committed
767
        } else {
768
            op = MP_BC_CALL_FUNCTION;
Damien's avatar
Damien committed
769
770
        }
    }
771
    emit_write_byte_code_byte_uint(emit, op, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints
Damien's avatar
Damien committed
772
773
}

774
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
775
776
777
778
779
780
781
    int s = 0;
    if (have_star_arg) {
        s += 1;
    }
    if (have_dbl_star_arg) {
        s += 1;
    }
782
    emit_pre(emit, -1 - n_positional - 2 * n_keyword - s);
Damien's avatar
Damien committed
783
784
785
    int op;
    if (have_star_arg) {
        if (have_dbl_star_arg) {
786
            op = MP_BC_CALL_METHOD_VAR_KW;
Damien's avatar
Damien committed
787
        } else {
788
            op = MP_BC_CALL_METHOD_VAR;
Damien's avatar
Damien committed
789
790
791
        }
    } else {
        if (have_dbl_star_arg) {
792
            op = MP_BC_CALL_METHOD_KW;
Damien's avatar
Damien committed
793
        } else {
794
            op = MP_BC_CALL_METHOD;
Damien's avatar
Damien committed
795
796
        }
    }
797
    emit_write_byte_code_byte_uint(emit, op, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints
Damien's avatar
Damien committed
798
799
}

800
STATIC void emit_bc_return_value(emit_t *emit) {
Damien's avatar
Damien committed
801
802
    emit_pre(emit, -1);
    emit->last_emit_was_return_value = true;
803
    emit_write_byte_code_byte(emit, MP_BC_RETURN_VALUE);
Damien's avatar
Damien committed
804
805
}

806
STATIC void emit_bc_raise_varargs(emit_t *emit, int n_args) {
807
    assert(0 <= n_args && n_args <= 2);
Damien's avatar
Damien committed
808
    emit_pre(emit, -n_args);
809
    emit_write_byte_code_byte_byte(emit, MP_BC_RAISE_VARARGS, n_args);
Damien's avatar
Damien committed
810
811
}

812
STATIC void emit_bc_yield_value(emit_t *emit) {
Damien's avatar
Damien committed
813
814
    emit_pre(emit, 0);
    if (emit->pass == PASS_2) {
815
        emit->scope->scope_flags |= MP_SCOPE_FLAG_GENERATOR;
Damien's avatar
Damien committed
816
    }
817
    emit_write_byte_code_byte(emit, MP_BC_YIELD_VALUE);
Damien's avatar
Damien committed
818
819
}

820
STATIC void emit_bc_yield_from(emit_t *emit) {
Damien's avatar
Damien committed
821
822
    emit_pre(emit, -1);
    if (emit->pass == PASS_2) {
823
        emit->scope->scope_flags |= MP_SCOPE_FLAG_GENERATOR;
Damien's avatar
Damien committed
824
    }
825
    emit_write_byte_code_byte(emit, MP_BC_YIELD_FROM);
Damien's avatar
Damien committed
826
827
}

828
const emit_method_table_t emit_bc_method_table = {
829
830
831
832
833
834
    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,
835
    emit_bc_set_source_line,
836

837
838
839
840
    emit_bc_load_id,
    emit_bc_store_id,
    emit_bc_delete_id,

841
842
843
844
845
846
847
848
849
850
851
852
853
854
    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
855
856
    emit_bc_load_name,
    emit_bc_load_global,
857
858
859
860
    emit_bc_load_attr,
    emit_bc_load_method,
    emit_bc_load_build_class,
    emit_bc_store_fast,
Damien's avatar
Damien committed
861
    emit_bc_store_deref,
862
863
864
865
    emit_bc_store_name,
    emit_bc_store_global,
    emit_bc_store_attr,
    emit_bc_store_subscr,
866
    emit_bc_store_locals,
867
    emit_bc_delete_fast,
Damien's avatar
Damien committed
868
    emit_bc_delete_deref,
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
    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,
884
885
    emit_bc_unwind_jump,
    emit_bc_unwind_jump,
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
    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,
};