emitbc.c 28.2 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
235

    // 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);
236
    emit_write_byte_code_byte(emit, num_cell); // write number of locals that are cells
Damien George's avatar
Damien George committed
237
238
239
    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) {
240
            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
241
242
243
244
        }
    }
}

245
STATIC void emit_bc_end_pass(emit_t *emit) {
Damien George's avatar
Damien George committed
246
247
248
249
250
    // 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);
    }

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

Damien George's avatar
Damien George committed
253
254
    if (emit->pass == PASS_2) {
        // calculate size of code in bytes
255
256
257
        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
258
259

    } else if (emit->pass == PASS_3) {
260
261
262
263
264
265
266
267
        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
268
269
270
    }
}

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

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

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

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

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

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

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

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

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

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

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

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

347
STATIC void emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
Damien's avatar
Damien committed
348
349
    emit_pre(emit, 1);
    switch (tok) {
350
351
352
353
        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
354
355
356
357
        default: assert(0);
    }
}

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

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

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

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

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

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

392
STATIC void emit_bc_load_fast(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
393
394
395
    assert(local_num >= 0);
    emit_pre(emit, 1);
    switch (local_num) {
396
397
398
399
        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
400
401
402
    }
}

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

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

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

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

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

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

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

438
STATIC void emit_bc_store_fast(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
439
440
441
    assert(local_num >= 0);
    emit_pre(emit, -1);
    switch (local_num) {
442
443
444
445
        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
446
447
448
    }
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

541
STATIC void emit_bc_pop_jump_if_true(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_POP_JUMP_IF_TRUE, label);
Damien's avatar
Damien committed
544
545
}

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

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

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

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

566
STATIC void emit_bc_unwind_jump(emit_t *emit, int label, int except_depth) {
567
568
569
570
571
572
573
    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
574
575
}

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

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

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

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

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

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

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

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

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

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

625
STATIC void emit_bc_unary_op(emit_t *emit, rt_unary_op_t op) {
626
627
628
629
630
631
632
633
634
    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
635
636
}

637
STATIC void emit_bc_binary_op(emit_t *emit, rt_binary_op_t op) {
638
639
640
641
642
643
644
645
    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
646
    emit_pre(emit, -1);
647
    emit_write_byte_code_byte_byte(emit, MP_BC_BINARY_OP, op);
648
649
650
651
    if (invert) {
        emit_pre(emit, 0);
        emit_write_byte_code_byte(emit, MP_BC_NOT);
    }
Damien's avatar
Damien committed
652
653
}

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

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

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

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

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

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

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

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

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

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

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

719
STATIC void emit_bc_make_function(emit_t *emit, scope_t *scope, int n_dict_params, int n_default_params) {
720
    assert(n_dict_params == 0);
721
722
723
724
    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 {
725
726
727
728
        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
729
730
}

731
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
732
733
    assert(n_default_params == 0 && n_dict_params == 0);
    emit_pre(emit, 0);
734
    emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_CLOSURE, scope->unique_code_id);
Damien's avatar
Damien committed
735
736
}

737
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
738
739
740
741
742
743
744
745
746
747
748
    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) {
749
            op = MP_BC_CALL_FUNCTION_VAR_KW;
Damien's avatar
Damien committed
750
        } else {
751
            op = MP_BC_CALL_FUNCTION_VAR;
Damien's avatar
Damien committed
752
753
754
        }
    } else {
        if (have_dbl_star_arg) {
755
            op = MP_BC_CALL_FUNCTION_KW;
Damien's avatar
Damien committed
756
        } else {
757
            op = MP_BC_CALL_FUNCTION;
Damien's avatar
Damien committed
758
759
        }
    }
760
    emit_write_byte_code_byte_uint(emit, op, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints
Damien's avatar
Damien committed
761
762
}

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

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

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

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

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

817
const emit_method_table_t emit_bc_method_table = {
818
819
820
821
822
823
    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,
824
    emit_bc_set_source_line,
825

826
827
828
829
    emit_bc_load_id,
    emit_bc_store_id,
    emit_bc_delete_id,

830
831
832
833
834
835
836
837
838
839
840
841
842
843
    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
844
845
    emit_bc_load_name,
    emit_bc_load_global,
846
847
848
849
    emit_bc_load_attr,
    emit_bc_load_method,
    emit_bc_load_build_class,
    emit_bc_store_fast,
Damien's avatar
Damien committed
850
    emit_bc_store_deref,
851
852
853
854
    emit_bc_store_name,
    emit_bc_store_global,
    emit_bc_store_attr,
    emit_bc_store_subscr,
855
    emit_bc_store_locals,
856
    emit_bc_delete_fast,
Damien's avatar
Damien committed
857
    emit_bc_delete_deref,
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
    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,
873
874
    emit_bc_unwind_jump,
    emit_bc_unwind_jump,
875
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
    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,
};