emitbc.c 27.6 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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
    if (num <= 127) { // fits in 0x7f
        // fit argument in single byte
        byte* c = emit_get_cur_to_write_byte_code(emit, 1);
        c[0] = num;
    } else if (num <= 16383) { // fits in 0x3fff
        // fit argument in two bytes
        byte* c = emit_get_cur_to_write_byte_code(emit, 2);
        c[0] = (num >> 8) | 0x80;
        c[1] = num;
    } else {
        // larger numbers not implemented/supported
        assert(0);
    }
}

Damien's avatar
Damien committed
126
// integers (for small ints) are stored as 24 bits, in excess
127
STATIC void emit_write_byte_code_byte_int(emit_t* emit, byte b1, machine_int_t num) {
Damien's avatar
Damien committed
128
129
    num += 0x800000;
    assert(0 <= num && num <= 0xffffff);
130
    byte* c = emit_get_cur_to_write_byte_code(emit, 4);
Damien's avatar
Damien committed
131
132
133
    c[0] = b1;
    c[1] = num;
    c[2] = num >> 8;
134
    c[3] = num >> 16;
Damien's avatar
Damien committed
135
136
}

137
STATIC void emit_write_byte_code_byte_uint(emit_t* emit, byte b, uint num) {
138
139
    emit_write_byte_code_byte(emit, b);
    emit_write_byte_code_uint(emit, num);
Damien's avatar
Damien committed
140
141
}

142
/* currently unused
143
STATIC void emit_write_byte_code_byte_uint_uint(emit_t* emit, byte b, uint num1, uint num2) {
144
145
146
147
148
149
    emit_write_byte_code_byte(emit, b);
    emit_write_byte_code_byte_uint(emit, num1);
    emit_write_byte_code_byte_uint(emit, num2);
}
*/

150
STATIC void emit_write_byte_code_byte_qstr(emit_t* emit, byte b, qstr qstr) {
151
    emit_write_byte_code_byte_uint(emit, b, qstr);
Damien's avatar
Damien committed
152
153
}

Damien's avatar
Damien committed
154
// unsigned labels are relative to ip following this instruction, stored as 16 bits
155
STATIC void emit_write_byte_code_byte_unsigned_label(emit_t* emit, byte b1, int label) {
156
    uint byte_code_offset;
Damien's avatar
Damien committed
157
    if (emit->pass < PASS_3) {
158
        byte_code_offset = 0;
Damien's avatar
Damien committed
159
    } else {
160
        byte_code_offset = emit->label_offsets[label] - emit->byte_code_offset - 3;
Damien's avatar
Damien committed
161
    }
162
    byte* c = emit_get_cur_to_write_byte_code(emit, 3);
Damien's avatar
Damien committed
163
    c[0] = b1;
164
165
    c[1] = byte_code_offset;
    c[2] = byte_code_offset >> 8;
Damien's avatar
Damien committed
166
167
168
}

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

182
STATIC void emit_bc_set_native_types(emit_t *emit, bool do_native_types) {
Damien George's avatar
Damien George committed
183
184
}

185
STATIC void emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
Damien George's avatar
Damien George committed
186
187
188
189
    emit->pass = pass;
    emit->stack_size = 0;
    emit->last_emit_was_return_value = false;
    emit->scope = scope;
190
191
    emit->last_source_line_offset = 0;
    emit->last_source_line = 1;
Damien George's avatar
Damien George committed
192
193
194
    if (pass == PASS_2) {
        memset(emit->label_offsets, -1, emit->max_num_labels * sizeof(uint));
    }
195
196
197
198
199
200
201
202
203
204
205
206
207
208
    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
209
210
    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
211
212
213
214
215
216
217
218
219
220

    // 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);
221
    emit_write_byte_code_byte(emit, num_cell); // write number of locals that are cells
Damien George's avatar
Damien George committed
222
223
224
    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) {
225
            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
226
227
228
229
        }
    }
}

230
STATIC void emit_bc_end_pass(emit_t *emit) {
Damien George's avatar
Damien George committed
231
232
233
234
235
    // 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);
    }

236
    emit_write_code_info_bytes_lines(emit, 0, 0); // end of line number info
237

Damien George's avatar
Damien George committed
238
239
    if (emit->pass == PASS_2) {
        // calculate size of code in bytes
240
241
242
        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
243
244

    } else if (emit->pass == PASS_3) {
245
246
247
248
249
250
251
252
        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
253
254
255
    }
}

256
bool emit_bc_last_emit_was_return_value(emit_t *emit) {
Damien's avatar
Damien committed
257
258
259
    return emit->last_emit_was_return_value;
}

260
int emit_bc_get_stack_size(emit_t *emit) {
Damien's avatar
Damien committed
261
262
263
    return emit->stack_size;
}

264
STATIC void emit_bc_set_stack_size(emit_t *emit, int size) {
265
    emit->stack_size = size;
Damien's avatar
Damien committed
266
267
}

268
STATIC void emit_bc_set_source_line(emit_t *emit, int source_line) {
269
    //printf("source: line %d -> %d  offset %d -> %d\n", emit->last_source_line, source_line, emit->last_source_line_offset, emit->byte_code_offset);
270
#if MICROPY_ENABLE_SOURCE_LINE
271
    if (source_line > emit->last_source_line) {
272
273
274
        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);
275
        //printf("  %d %d\n", bytes_to_skip, lines_to_skip);
276
277
278
        emit->last_source_line_offset = emit->byte_code_offset;
        emit->last_source_line = source_line;
    }
279
#endif
280
281
}

282
STATIC void emit_bc_load_id(emit_t *emit, qstr qstr) {
283
284
285
    emit_common_load_id(emit, &emit_bc_method_table, emit->scope, qstr);
}

286
STATIC void emit_bc_store_id(emit_t *emit, qstr qstr) {
287
288
289
    emit_common_store_id(emit, &emit_bc_method_table, emit->scope, qstr);
}

290
STATIC void emit_bc_delete_id(emit_t *emit, qstr qstr) {
291
292
293
    emit_common_delete_id(emit, &emit_bc_method_table, emit->scope, qstr);
}

294
// TODO: module-polymorphic function (read: name clash if made global)
295
static void emit_pre(emit_t *emit, int stack_size_delta) {
296
297
298
    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
299
300
301
302
    }
    emit->last_emit_was_return_value = false;
}

303
STATIC void emit_bc_label_assign(emit_t *emit, int l) {
Damien's avatar
Damien committed
304
    emit_pre(emit, 0);
305
306
307
308
    assert(l < emit->max_num_labels);
    if (emit->pass == PASS_2) {
        // assign label offset
        assert(emit->label_offsets[l] == -1);
309
        emit->label_offsets[l] = emit->byte_code_offset;
310
311
    } else if (emit->pass == PASS_3) {
        // ensure label offset has not changed from PASS_2 to PASS_3
312
313
        //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
314
315
316
    }
}

317
STATIC void emit_bc_import_name(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
318
    emit_pre(emit, -1);
319
    emit_write_byte_code_byte_qstr(emit, MP_BC_IMPORT_NAME, qstr);
Damien's avatar
Damien committed
320
321
}

322
STATIC void emit_bc_import_from(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
323
    emit_pre(emit, 1);
324
    emit_write_byte_code_byte_qstr(emit, MP_BC_IMPORT_FROM, qstr);
Damien's avatar
Damien committed
325
326
}

327
STATIC void emit_bc_import_star(emit_t *emit) {
Damien's avatar
Damien committed
328
    emit_pre(emit, -1);
329
    emit_write_byte_code_byte(emit, MP_BC_IMPORT_STAR);
Damien's avatar
Damien committed
330
331
}

332
STATIC void emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
Damien's avatar
Damien committed
333
334
    emit_pre(emit, 1);
    switch (tok) {
335
336
337
338
        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
339
340
341
342
        default: assert(0);
    }
}

343
STATIC void emit_bc_load_const_small_int(emit_t *emit, machine_int_t arg) {
Damien's avatar
Damien committed
344
    emit_pre(emit, 1);
345
    emit_write_byte_code_byte_int(emit, MP_BC_LOAD_CONST_SMALL_INT, arg);
Damien's avatar
Damien committed
346
347
}

348
STATIC void emit_bc_load_const_int(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
349
    emit_pre(emit, 1);
350
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_INT, qstr);
Damien's avatar
Damien committed
351
352
}

353
STATIC void emit_bc_load_const_dec(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
354
    emit_pre(emit, 1);
355
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_DEC, qstr);
Damien's avatar
Damien committed
356
357
}

358
STATIC void emit_bc_load_const_id(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
359
    emit_pre(emit, 1);
360
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_ID, qstr);
Damien's avatar
Damien committed
361
362
}

363
STATIC void emit_bc_load_const_str(emit_t *emit, qstr qstr, bool bytes) {
Damien's avatar
Damien committed
364
365
    emit_pre(emit, 1);
    if (bytes) {
366
        emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_BYTES, qstr);
Damien's avatar
Damien committed
367
    } else {
368
        emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_STRING, qstr);
Damien's avatar
Damien committed
369
370
371
    }
}

372
STATIC void emit_bc_load_const_verbatim_str(emit_t *emit, const char *str) {
373
    // not needed/supported for BC
Damien's avatar
Damien committed
374
375
376
    assert(0);
}

377
STATIC void emit_bc_load_fast(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
378
379
380
    assert(local_num >= 0);
    emit_pre(emit, 1);
    switch (local_num) {
381
382
383
384
        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
385
386
387
    }
}

388
STATIC void emit_bc_load_deref(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
389
    emit_pre(emit, 1);
390
    emit_write_byte_code_byte_uint(emit, MP_BC_LOAD_DEREF, local_num);
Damien's avatar
Damien committed
391
392
}

393
STATIC void emit_bc_load_closure(emit_t *emit, qstr qstr, int local_num) {
Damien George's avatar
Damien George committed
394
395
    // not needed/supported for BC
    assert(0);
Damien's avatar
Damien committed
396
397
}

398
STATIC void emit_bc_load_name(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
399
    emit_pre(emit, 1);
400
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_NAME, qstr);
Damien's avatar
Damien committed
401
402
}

403
STATIC void emit_bc_load_global(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
404
    emit_pre(emit, 1);
405
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_GLOBAL, qstr);
Damien's avatar
Damien committed
406
407
}

408
STATIC void emit_bc_load_attr(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
409
    emit_pre(emit, 0);
410
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_ATTR, qstr);
Damien's avatar
Damien committed
411
412
}

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

418
STATIC void emit_bc_load_build_class(emit_t *emit) {
Damien's avatar
Damien committed
419
    emit_pre(emit, 1);
420
    emit_write_byte_code_byte(emit, MP_BC_LOAD_BUILD_CLASS);
Damien's avatar
Damien committed
421
422
}

423
STATIC void emit_bc_store_fast(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
424
425
426
    assert(local_num >= 0);
    emit_pre(emit, -1);
    switch (local_num) {
427
428
429
430
        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
431
432
433
    }
}

434
STATIC void emit_bc_store_deref(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
435
    emit_pre(emit, -1);
436
    emit_write_byte_code_byte_uint(emit, MP_BC_STORE_DEREF, local_num);
Damien's avatar
Damien committed
437
438
}

439
STATIC void emit_bc_store_name(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
440
    emit_pre(emit, -1);
441
    emit_write_byte_code_byte_qstr(emit, MP_BC_STORE_NAME, qstr);
Damien's avatar
Damien committed
442
443
}

444
STATIC void emit_bc_store_global(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
445
    emit_pre(emit, -1);
446
    emit_write_byte_code_byte_qstr(emit, MP_BC_STORE_GLOBAL, qstr);
Damien's avatar
Damien committed
447
448
}

449
STATIC void emit_bc_store_attr(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
450
    emit_pre(emit, -2);
451
    emit_write_byte_code_byte_qstr(emit, MP_BC_STORE_ATTR, qstr);
Damien's avatar
Damien committed
452
453
}

454
STATIC void emit_bc_store_subscr(emit_t *emit) {
Damien's avatar
Damien committed
455
    emit_pre(emit, -3);
456
    emit_write_byte_code_byte(emit, MP_BC_STORE_SUBSCR);
Damien's avatar
Damien committed
457
458
}

459
STATIC void emit_bc_store_locals(emit_t *emit) {
460
    // not needed
461
    emit_pre(emit, -1);
462
    emit_write_byte_code_byte(emit, MP_BC_POP_TOP);
463
464
}

465
STATIC void emit_bc_delete_fast(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
466
467
    assert(local_num >= 0);
    emit_pre(emit, 0);
468
    emit_write_byte_code_byte_uint(emit, MP_BC_DELETE_FAST_N, local_num);
Damien's avatar
Damien committed
469
470
}

471
STATIC void emit_bc_delete_deref(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
472
    emit_pre(emit, 0);
473
    emit_write_byte_code_byte_qstr(emit, MP_BC_DELETE_DEREF, local_num);
Damien's avatar
Damien committed
474
475
}

476
STATIC void emit_bc_delete_name(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
477
    emit_pre(emit, 0);
478
    emit_write_byte_code_byte_qstr(emit, MP_BC_DELETE_NAME, qstr);
Damien's avatar
Damien committed
479
480
}

481
STATIC void emit_bc_delete_global(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
482
    emit_pre(emit, 0);
483
    emit_write_byte_code_byte_qstr(emit, MP_BC_DELETE_GLOBAL, qstr);
Damien's avatar
Damien committed
484
485
}

486
STATIC void emit_bc_delete_attr(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
487
    emit_pre(emit, -1);
488
    emit_write_byte_code_byte_qstr(emit, MP_BC_DELETE_ATTR, qstr);
Damien's avatar
Damien committed
489
490
}

491
STATIC void emit_bc_delete_subscr(emit_t *emit) {
Damien's avatar
Damien committed
492
    emit_pre(emit, -2);
493
    emit_write_byte_code_byte(emit, MP_BC_DELETE_SUBSCR);
Damien's avatar
Damien committed
494
495
}

496
STATIC void emit_bc_dup_top(emit_t *emit) {
Damien's avatar
Damien committed
497
    emit_pre(emit, 1);
498
    emit_write_byte_code_byte(emit, MP_BC_DUP_TOP);
Damien's avatar
Damien committed
499
500
}

501
STATIC void emit_bc_dup_top_two(emit_t *emit) {
Damien's avatar
Damien committed
502
    emit_pre(emit, 2);
503
    emit_write_byte_code_byte(emit, MP_BC_DUP_TOP_TWO);
Damien's avatar
Damien committed
504
505
}

506
STATIC void emit_bc_pop_top(emit_t *emit) {
Damien's avatar
Damien committed
507
    emit_pre(emit, -1);
508
    emit_write_byte_code_byte(emit, MP_BC_POP_TOP);
Damien's avatar
Damien committed
509
510
}

511
STATIC void emit_bc_rot_two(emit_t *emit) {
Damien's avatar
Damien committed
512
    emit_pre(emit, 0);
513
    emit_write_byte_code_byte(emit, MP_BC_ROT_TWO);
Damien's avatar
Damien committed
514
515
}

516
STATIC void emit_bc_rot_three(emit_t *emit) {
Damien's avatar
Damien committed
517
    emit_pre(emit, 0);
518
    emit_write_byte_code_byte(emit, MP_BC_ROT_THREE);
Damien's avatar
Damien committed
519
520
}

521
STATIC void emit_bc_jump(emit_t *emit, int label) {
Damien's avatar
Damien committed
522
    emit_pre(emit, 0);
523
    emit_write_byte_code_byte_signed_label(emit, MP_BC_JUMP, label);
Damien's avatar
Damien committed
524
525
}

526
STATIC void emit_bc_pop_jump_if_true(emit_t *emit, int label) {
Damien's avatar
Damien committed
527
    emit_pre(emit, -1);
528
    emit_write_byte_code_byte_signed_label(emit, MP_BC_POP_JUMP_IF_TRUE, label);
Damien's avatar
Damien committed
529
530
}

531
STATIC void emit_bc_pop_jump_if_false(emit_t *emit, int label) {
Damien's avatar
Damien committed
532
    emit_pre(emit, -1);
533
    emit_write_byte_code_byte_signed_label(emit, MP_BC_POP_JUMP_IF_FALSE, label);
Damien's avatar
Damien committed
534
535
}

536
STATIC void emit_bc_jump_if_true_or_pop(emit_t *emit, int label) {
Damien's avatar
Damien committed
537
    emit_pre(emit, -1);
538
    emit_write_byte_code_byte_signed_label(emit, MP_BC_JUMP_IF_TRUE_OR_POP, label);
Damien's avatar
Damien committed
539
540
}

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

546
STATIC void emit_bc_setup_loop(emit_t *emit, int label) {
Damien's avatar
Damien committed
547
    emit_pre(emit, 0);
548
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_SETUP_LOOP, label);
Damien's avatar
Damien committed
549
550
}

551
STATIC void emit_bc_unwind_jump(emit_t *emit, int label, int except_depth) {
552
553
554
555
556
557
558
    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
559
560
}

561
STATIC void emit_bc_setup_with(emit_t *emit, int label) {
Damien's avatar
Damien committed
562
    emit_pre(emit, 7);
563
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_SETUP_WITH, label);
Damien's avatar
Damien committed
564
565
}

566
STATIC void emit_bc_with_cleanup(emit_t *emit) {
Damien's avatar
Damien committed
567
    emit_pre(emit, -7);
568
    emit_write_byte_code_byte(emit, MP_BC_WITH_CLEANUP);
Damien's avatar
Damien committed
569
570
}

571
STATIC void emit_bc_setup_except(emit_t *emit, int label) {
Damien's avatar
Damien committed
572
    emit_pre(emit, 6);
573
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_SETUP_EXCEPT, label);
Damien's avatar
Damien committed
574
575
}

576
STATIC void emit_bc_setup_finally(emit_t *emit, int label) {
Damien's avatar
Damien committed
577
    emit_pre(emit, 6);
578
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_SETUP_FINALLY, label);
Damien's avatar
Damien committed
579
580
}

581
STATIC void emit_bc_end_finally(emit_t *emit) {
Damien's avatar
Damien committed
582
    emit_pre(emit, -1);
583
    emit_write_byte_code_byte(emit, MP_BC_END_FINALLY);
Damien's avatar
Damien committed
584
585
}

586
STATIC void emit_bc_get_iter(emit_t *emit) {
Damien's avatar
Damien committed
587
    emit_pre(emit, 0);
588
    emit_write_byte_code_byte(emit, MP_BC_GET_ITER);
Damien's avatar
Damien committed
589
590
}

591
STATIC void emit_bc_for_iter(emit_t *emit, int label) {
Damien's avatar
Damien committed
592
    emit_pre(emit, 1);
593
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_FOR_ITER, label);
Damien's avatar
Damien committed
594
595
}

596
STATIC void emit_bc_for_iter_end(emit_t *emit) {
Damien's avatar
Damien committed
597
598
599
    emit_pre(emit, -1);
}

600
STATIC void emit_bc_pop_block(emit_t *emit) {
Damien's avatar
Damien committed
601
    emit_pre(emit, 0);
602
    emit_write_byte_code_byte(emit, MP_BC_POP_BLOCK);
Damien's avatar
Damien committed
603
604
}

605
STATIC void emit_bc_pop_except(emit_t *emit) {
Damien's avatar
Damien committed
606
    emit_pre(emit, 0);
607
    emit_write_byte_code_byte(emit, MP_BC_POP_EXCEPT);
Damien's avatar
Damien committed
608
609
}

610
STATIC void emit_bc_unary_op(emit_t *emit, rt_unary_op_t op) {
611
612
613
614
615
616
617
618
619
    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
620
621
}

622
STATIC void emit_bc_binary_op(emit_t *emit, rt_binary_op_t op) {
623
624
625
626
627
628
629
630
    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
631
    emit_pre(emit, -1);
632
    emit_write_byte_code_byte_byte(emit, MP_BC_BINARY_OP, op);
633
634
635
636
    if (invert) {
        emit_pre(emit, 0);
        emit_write_byte_code_byte(emit, MP_BC_NOT);
    }
Damien's avatar
Damien committed
637
638
}

639
STATIC void emit_bc_build_tuple(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
640
641
    assert(n_args >= 0);
    emit_pre(emit, 1 - n_args);
642
    emit_write_byte_code_byte_uint(emit, MP_BC_BUILD_TUPLE, n_args);
Damien's avatar
Damien committed
643
644
}

645
STATIC void emit_bc_build_list(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
646
647
    assert(n_args >= 0);
    emit_pre(emit, 1 - n_args);
648
    emit_write_byte_code_byte_uint(emit, MP_BC_BUILD_LIST, n_args);
Damien's avatar
Damien committed
649
650
}

651
STATIC void emit_bc_list_append(emit_t *emit, int list_stack_index) {
Damien's avatar
Damien committed
652
653
    assert(list_stack_index >= 0);
    emit_pre(emit, -1);
654
    emit_write_byte_code_byte_uint(emit, MP_BC_LIST_APPEND, list_stack_index);
Damien's avatar
Damien committed
655
656
}

657
STATIC void emit_bc_build_map(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
658
659
    assert(n_args >= 0);
    emit_pre(emit, 1);
660
    emit_write_byte_code_byte_uint(emit, MP_BC_BUILD_MAP, n_args);
Damien's avatar
Damien committed
661
662
}

663
STATIC void emit_bc_store_map(emit_t *emit) {
Damien's avatar
Damien committed
664
    emit_pre(emit, -2);
665
    emit_write_byte_code_byte(emit, MP_BC_STORE_MAP);
Damien's avatar
Damien committed
666
667
}

668
STATIC void emit_bc_map_add(emit_t *emit, int map_stack_index) {
Damien's avatar
Damien committed
669
670
    assert(map_stack_index >= 0);
    emit_pre(emit, -2);
671
    emit_write_byte_code_byte_uint(emit, MP_BC_MAP_ADD, map_stack_index);
Damien's avatar
Damien committed
672
673
}

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

680
STATIC void emit_bc_set_add(emit_t *emit, int set_stack_index) {
Damien's avatar
Damien committed
681
682
    assert(set_stack_index >= 0);
    emit_pre(emit, -1);
683
    emit_write_byte_code_byte_uint(emit, MP_BC_SET_ADD, set_stack_index);
Damien's avatar
Damien committed
684
685
}

686
STATIC void emit_bc_build_slice(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
687
688
    assert(n_args >= 0);
    emit_pre(emit, 1 - n_args);
689
    emit_write_byte_code_byte_uint(emit, MP_BC_BUILD_SLICE, n_args);
Damien's avatar
Damien committed
690
691
}

692
STATIC void emit_bc_unpack_sequence(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
693
694
    assert(n_args >= 0);
    emit_pre(emit, -1 + n_args);
695
    emit_write_byte_code_byte_uint(emit, MP_BC_UNPACK_SEQUENCE, n_args);
Damien's avatar
Damien committed
696
697
}

698
STATIC void emit_bc_unpack_ex(emit_t *emit, int n_left, int n_right) {
Damien's avatar
Damien committed
699
700
    assert(n_left >=0 && n_right >= 0);
    emit_pre(emit, -1 + n_left + n_right + 1);
701
    emit_write_byte_code_byte_uint(emit, MP_BC_UNPACK_EX, n_left | (n_right << 8));
Damien's avatar
Damien committed
702
703
}

704
STATIC void emit_bc_make_function(emit_t *emit, scope_t *scope, int n_dict_params, int n_default_params) {
705
    assert(n_dict_params == 0);
706
707
708
709
    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 {
710
711
712
713
        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
714
715
}

716
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
717
718
    assert(n_default_params == 0 && n_dict_params == 0);
    emit_pre(emit, 0);
719
    emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_CLOSURE, scope->unique_code_id);
Damien's avatar
Damien committed
720
721
}

722
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
723
724
725
726
727
728
729
730
731
732
733
    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) {
734
            op = MP_BC_CALL_FUNCTION_VAR_KW;
Damien's avatar
Damien committed
735
        } else {
736
            op = MP_BC_CALL_FUNCTION_VAR;
Damien's avatar
Damien committed
737
738
739
        }
    } else {
        if (have_dbl_star_arg) {
740
            op = MP_BC_CALL_FUNCTION_KW;
Damien's avatar
Damien committed
741
        } else {
742
            op = MP_BC_CALL_FUNCTION;
Damien's avatar
Damien committed
743
744
        }
    }
745
    emit_write_byte_code_byte_uint(emit, op, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints
Damien's avatar
Damien committed
746
747
}

748
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
749
750
751
752
753
754
755
    int s = 0;
    if (have_star_arg) {
        s += 1;
    }
    if (have_dbl_star_arg) {
        s += 1;
    }
756
    emit_pre(emit, -1 - n_positional - 2 * n_keyword - s);
Damien's avatar
Damien committed
757
758
759
    int op;
    if (have_star_arg) {
        if (have_dbl_star_arg) {
760
            op = MP_BC_CALL_METHOD_VAR_KW;
Damien's avatar
Damien committed
761
        } else {
762
            op = MP_BC_CALL_METHOD_VAR;
Damien's avatar
Damien committed
763
764
765
        }
    } else {
        if (have_dbl_star_arg) {
766
            op = MP_BC_CALL_METHOD_KW;
Damien's avatar
Damien committed
767
        } else {
768
            op = MP_BC_CALL_METHOD;
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_return_value(emit_t *emit) {
Damien's avatar
Damien committed
775
776
    emit_pre(emit, -1);
    emit->last_emit_was_return_value = true;
777
    emit_write_byte_code_byte(emit, MP_BC_RETURN_VALUE);
Damien's avatar
Damien committed
778
779
}

780
STATIC void emit_bc_raise_varargs(emit_t *emit, int n_args) {
781
    assert(0 <= n_args && n_args <= 2);
Damien's avatar
Damien committed
782
    emit_pre(emit, -n_args);
783
    emit_write_byte_code_byte_byte(emit, MP_BC_RAISE_VARARGS, n_args);
Damien's avatar
Damien committed
784
785
}

786
STATIC void emit_bc_yield_value(emit_t *emit) {
Damien's avatar
Damien committed
787
788
    emit_pre(emit, 0);
    if (emit->pass == PASS_2) {
789
        emit->scope->scope_flags |= MP_SCOPE_FLAG_GENERATOR;
Damien's avatar
Damien committed
790
    }
791
    emit_write_byte_code_byte(emit, MP_BC_YIELD_VALUE);
Damien's avatar
Damien committed
792
793
}

794
STATIC void emit_bc_yield_from(emit_t *emit) {
Damien's avatar
Damien committed
795
796
    emit_pre(emit, -1);
    if (emit->pass == PASS_2) {
797
        emit->scope->scope_flags |= MP_SCOPE_FLAG_GENERATOR;
Damien's avatar
Damien committed
798
    }
799
    emit_write_byte_code_byte(emit, MP_BC_YIELD_FROM);
Damien's avatar
Damien committed
800
801
}

802
const emit_method_table_t emit_bc_method_table = {
803
804
805
806
807
808
    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,
809
    emit_bc_set_source_line,
810

811
812
813
814
    emit_bc_load_id,
    emit_bc_store_id,
    emit_bc_delete_id,

815
816
817
818
819
820
821
822
823
824
825
826
827
828
    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
829
830
    emit_bc_load_name,
    emit_bc_load_global,
831
832
833
834
    emit_bc_load_attr,
    emit_bc_load_method,
    emit_bc_load_build_class,
    emit_bc_store_fast,
Damien's avatar
Damien committed
835
    emit_bc_store_deref,
836
837
838
839
    emit_bc_store_name,
    emit_bc_store_global,
    emit_bc_store_attr,
    emit_bc_store_subscr,
840
    emit_bc_store_locals,
841
    emit_bc_delete_fast,
Damien's avatar
Damien committed
842
    emit_bc_delete_deref,
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
    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,
858
859
    emit_bc_unwind_jump,
    emit_bc_unwind_jump,
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
    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,
};