emitbc.c 26.1 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
47
48
49
50
static void emit_bc_free(emit_t *emit) {
    m_del(uint, emit->label_offsets, emit->max_num_labels);
    m_del_obj(emit_t, emit);
}

51
52
53
54
55
56
57
58
59
60
61
62
// all functions must go through this one to emit code info
static byte* emit_get_cur_to_write_code_info(emit_t* emit, int num_bytes_to_write) {
    //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
66
67
68
69
70
71
static void emit_write_code_info_qstr(emit_t* emit, qstr qstr) {
    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
75
76
77
78
79
80
81
static void emit_write_code_info_byte_byte(emit_t* emit, byte b1, uint b2) {
    byte* c = emit_get_cur_to_write_code_info(emit, 2);
    c[0] = b1;
    c[1] = b2;
}

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

94
95
static void emit_write_byte_code_byte(emit_t* emit, byte b1) {
    byte* c = emit_get_cur_to_write_byte_code(emit, 1);
Damien's avatar
Damien committed
96
97
98
    c[0] = b1;
}

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

Damien's avatar
Damien committed
106
// integers (for small ints) are stored as 24 bits, in excess
107
static void emit_write_byte_code_byte_int(emit_t* emit, byte b1, int num) {
Damien's avatar
Damien committed
108
109
    num += 0x800000;
    assert(0 <= num && num <= 0xffffff);
110
    byte* c = emit_get_cur_to_write_byte_code(emit, 4);
Damien's avatar
Damien committed
111
112
113
    c[0] = b1;
    c[1] = num;
    c[2] = num >> 8;
114
    c[3] = num >> 16;
Damien's avatar
Damien committed
115
116
}

117
static void emit_write_byte_code_byte_uint(emit_t* emit, byte b1, uint num) {
Damien's avatar
Damien committed
118
119
    if (num <= 127) { // fits in 0x7f
        // fit argument in single byte
120
        byte* c = emit_get_cur_to_write_byte_code(emit, 2);
Damien's avatar
Damien committed
121
122
123
124
        c[0] = b1;
        c[1] = num;
    } else if (num <= 16383) { // fits in 0x3fff
        // fit argument in two bytes
125
        byte* c = emit_get_cur_to_write_byte_code(emit, 3);
Damien's avatar
Damien committed
126
127
128
129
130
131
132
133
134
        c[0] = b1;
        c[1] = (num >> 8) | 0x80;
        c[2] = num;
    } else {
        // larger numbers not implemented/supported
        assert(0);
    }
}

135
136
static void emit_write_byte_code_byte_qstr(emit_t* emit, byte b1, qstr qstr) {
    emit_write_byte_code_byte_uint(emit, b1, qstr);
Damien's avatar
Damien committed
137
138
}

Damien's avatar
Damien committed
139
// unsigned labels are relative to ip following this instruction, stored as 16 bits
140
141
static void emit_write_byte_code_byte_unsigned_label(emit_t* emit, byte b1, int label) {
    uint byte_code_offset;
Damien's avatar
Damien committed
142
    if (emit->pass < PASS_3) {
143
        byte_code_offset = 0;
Damien's avatar
Damien committed
144
    } else {
145
        byte_code_offset = emit->label_offsets[label] - emit->byte_code_offset - 3;
Damien's avatar
Damien committed
146
    }
147
    byte* c = emit_get_cur_to_write_byte_code(emit, 3);
Damien's avatar
Damien committed
148
    c[0] = b1;
149
150
    c[1] = byte_code_offset;
    c[2] = byte_code_offset >> 8;
Damien's avatar
Damien committed
151
152
153
}

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

Damien George's avatar
Damien George committed
167
168
169
170
171
172
173
174
static void emit_bc_set_native_types(emit_t *emit, bool do_native_types) {
}

static void emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
    emit->pass = pass;
    emit->stack_size = 0;
    emit->last_emit_was_return_value = false;
    emit->scope = scope;
175
176
    emit->last_source_line_offset = 0;
    emit->last_source_line = 1;
Damien George's avatar
Damien George committed
177
178
179
    if (pass == PASS_2) {
        memset(emit->label_offsets, -1, emit->max_num_labels * sizeof(uint));
    }
180
181
182
183
184
185
186
187
188
189
190
191
192
193
    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
194
195
    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
196
197
198
199
200
201
202
203
204
205

    // 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);
206
    emit_write_byte_code_byte(emit, num_cell); // write number of locals that are cells
Damien George's avatar
Damien George committed
207
208
209
    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) {
210
            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
211
212
213
214
215
216
217
218
219
220
        }
    }
}

static void emit_bc_end_pass(emit_t *emit) {
    // 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);
    }

221
222
    emit_write_code_info_byte_byte(emit, 0, 0); // end of line number info

Damien George's avatar
Damien George committed
223
224
    if (emit->pass == PASS_2) {
        // calculate size of code in bytes
225
226
227
        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
228
229

    } else if (emit->pass == PASS_3) {
230
        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->flags & SCOPE_FLAG_GENERATOR) != 0);
Damien George's avatar
Damien George committed
231
232
233
    }
}

234
bool emit_bc_last_emit_was_return_value(emit_t *emit) {
Damien's avatar
Damien committed
235
236
237
    return emit->last_emit_was_return_value;
}

238
int emit_bc_get_stack_size(emit_t *emit) {
Damien's avatar
Damien committed
239
240
241
    return emit->stack_size;
}

242
static void emit_bc_set_stack_size(emit_t *emit, int size) {
243
    emit->stack_size = size;
Damien's avatar
Damien committed
244
245
}

246
static void emit_bc_set_source_line(emit_t *emit, int source_line) {
247
    //printf("source: line %d -> %d  offset %d -> %d\n", emit->last_source_line, source_line, emit->last_source_line_offset, emit->byte_code_offset);
248
249
250
251
252
253
254
255
256
257
    if (source_line > emit->last_source_line) {
        int bytes_to_skip = emit->byte_code_offset - emit->last_source_line_offset;
        for (; bytes_to_skip > 255; bytes_to_skip -= 255) {
            emit_write_code_info_byte_byte(emit, 255, 0);
        }
        int lines_to_skip = source_line - emit->last_source_line;
        for (; lines_to_skip > 255; lines_to_skip -= 255) {
            emit_write_code_info_byte_byte(emit, 0, 255);
        }
        emit_write_code_info_byte_byte(emit, bytes_to_skip, lines_to_skip);
258
        //printf("  %d %d\n", bytes_to_skip, lines_to_skip);
259
260
261
262
263
        emit->last_source_line_offset = emit->byte_code_offset;
        emit->last_source_line = source_line;
    }
}

264
265
266
267
268
269
270
271
272
273
274
275
static void emit_bc_load_id(emit_t *emit, qstr qstr) {
    emit_common_load_id(emit, &emit_bc_method_table, emit->scope, qstr);
}

static void emit_bc_store_id(emit_t *emit, qstr qstr) {
    emit_common_store_id(emit, &emit_bc_method_table, emit->scope, qstr);
}

static void emit_bc_delete_id(emit_t *emit, qstr qstr) {
    emit_common_delete_id(emit, &emit_bc_method_table, emit->scope, qstr);
}

276
static void emit_pre(emit_t *emit, int stack_size_delta) {
277
278
279
    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
280
281
282
283
    }
    emit->last_emit_was_return_value = false;
}

284
static void emit_bc_label_assign(emit_t *emit, int l) {
Damien's avatar
Damien committed
285
    emit_pre(emit, 0);
286
287
288
289
    assert(l < emit->max_num_labels);
    if (emit->pass == PASS_2) {
        // assign label offset
        assert(emit->label_offsets[l] == -1);
290
        emit->label_offsets[l] = emit->byte_code_offset;
291
292
    } else if (emit->pass == PASS_3) {
        // ensure label offset has not changed from PASS_2 to PASS_3
293
294
        //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
295
296
297
    }
}

298
static void emit_bc_import_name(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
299
    emit_pre(emit, -1);
300
    emit_write_byte_code_byte_qstr(emit, MP_BC_IMPORT_NAME, qstr);
Damien's avatar
Damien committed
301
302
}

303
static void emit_bc_import_from(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
304
    emit_pre(emit, 1);
305
    emit_write_byte_code_byte_qstr(emit, MP_BC_IMPORT_FROM, qstr);
Damien's avatar
Damien committed
306
307
}

308
static void emit_bc_import_star(emit_t *emit) {
Damien's avatar
Damien committed
309
    emit_pre(emit, -1);
310
    emit_write_byte_code_byte(emit, MP_BC_IMPORT_STAR);
Damien's avatar
Damien committed
311
312
}

313
static void emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
Damien's avatar
Damien committed
314
315
    emit_pre(emit, 1);
    switch (tok) {
316
317
318
319
        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
320
321
322
323
        default: assert(0);
    }
}

324
static void emit_bc_load_const_small_int(emit_t *emit, int arg) {
Damien's avatar
Damien committed
325
    emit_pre(emit, 1);
326
    emit_write_byte_code_byte_int(emit, MP_BC_LOAD_CONST_SMALL_INT, arg);
Damien's avatar
Damien committed
327
328
}

329
static void emit_bc_load_const_int(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
330
    emit_pre(emit, 1);
331
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_INT, qstr);
Damien's avatar
Damien committed
332
333
}

334
static void emit_bc_load_const_dec(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
335
    emit_pre(emit, 1);
336
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_DEC, qstr);
Damien's avatar
Damien committed
337
338
}

339
static void emit_bc_load_const_id(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_LOAD_CONST_ID, qstr);
Damien's avatar
Damien committed
342
343
}

344
static void emit_bc_load_const_str(emit_t *emit, qstr qstr, bool bytes) {
Damien's avatar
Damien committed
345
346
    emit_pre(emit, 1);
    if (bytes) {
347
        emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_BYTES, qstr);
Damien's avatar
Damien committed
348
    } else {
349
        emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_STRING, qstr);
Damien's avatar
Damien committed
350
351
352
    }
}

353
static void emit_bc_load_const_verbatim_str(emit_t *emit, const char *str) {
354
    // not needed/supported for BC
Damien's avatar
Damien committed
355
356
357
    assert(0);
}

358
static void emit_bc_load_fast(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
359
360
361
    assert(local_num >= 0);
    emit_pre(emit, 1);
    switch (local_num) {
362
363
364
365
        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
366
367
368
    }
}

Damien's avatar
Damien committed
369
static void emit_bc_load_deref(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
370
    emit_pre(emit, 1);
371
    emit_write_byte_code_byte_uint(emit, MP_BC_LOAD_DEREF, local_num);
Damien's avatar
Damien committed
372
373
}

Damien's avatar
Damien committed
374
static void emit_bc_load_closure(emit_t *emit, qstr qstr, int local_num) {
Damien George's avatar
Damien George committed
375
376
    // not needed/supported for BC
    assert(0);
Damien's avatar
Damien committed
377
378
}

Damien's avatar
Damien committed
379
static void emit_bc_load_name(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
380
    emit_pre(emit, 1);
381
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_NAME, qstr);
Damien's avatar
Damien committed
382
383
}

Damien's avatar
Damien committed
384
static void emit_bc_load_global(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
385
    emit_pre(emit, 1);
386
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_GLOBAL, qstr);
Damien's avatar
Damien committed
387
388
}

389
static void emit_bc_load_attr(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
390
    emit_pre(emit, 0);
391
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_ATTR, qstr);
Damien's avatar
Damien committed
392
393
}

394
static void emit_bc_load_method(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
395
    emit_pre(emit, 0);
396
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_METHOD, qstr);
Damien's avatar
Damien committed
397
398
}

399
static void emit_bc_load_build_class(emit_t *emit) {
Damien's avatar
Damien committed
400
    emit_pre(emit, 1);
401
    emit_write_byte_code_byte(emit, MP_BC_LOAD_BUILD_CLASS);
Damien's avatar
Damien committed
402
403
}

404
static void emit_bc_store_fast(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
405
406
407
    assert(local_num >= 0);
    emit_pre(emit, -1);
    switch (local_num) {
408
409
410
411
        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
412
413
414
    }
}

Damien's avatar
Damien committed
415
416
static void emit_bc_store_deref(emit_t *emit, qstr qstr, int local_num) {
    emit_pre(emit, -1);
417
    emit_write_byte_code_byte_uint(emit, MP_BC_STORE_DEREF, local_num);
Damien's avatar
Damien committed
418
419
}

420
static void emit_bc_store_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_STORE_NAME, qstr);
Damien's avatar
Damien committed
423
424
}

425
static void emit_bc_store_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_STORE_GLOBAL, qstr);
Damien's avatar
Damien committed
428
429
}

430
static void emit_bc_store_attr(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
431
    emit_pre(emit, -2);
432
    emit_write_byte_code_byte_qstr(emit, MP_BC_STORE_ATTR, qstr);
Damien's avatar
Damien committed
433
434
}

435
static void emit_bc_store_subscr(emit_t *emit) {
Damien's avatar
Damien committed
436
    emit_pre(emit, -3);
437
    emit_write_byte_code_byte(emit, MP_BC_STORE_SUBSCR);
Damien's avatar
Damien committed
438
439
}

440
static void emit_bc_store_locals(emit_t *emit) {
441
    // not needed
442
    emit_pre(emit, -1);
443
    emit_write_byte_code_byte(emit, MP_BC_POP_TOP);
444
445
}

446
static void emit_bc_delete_fast(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
447
448
    assert(local_num >= 0);
    emit_pre(emit, 0);
449
    emit_write_byte_code_byte_uint(emit, MP_BC_DELETE_FAST_N, local_num);
Damien's avatar
Damien committed
450
451
}

Damien's avatar
Damien committed
452
453
static void emit_bc_delete_deref(emit_t *emit, qstr qstr, int local_num) {
    emit_pre(emit, 0);
454
    emit_write_byte_code_byte_qstr(emit, MP_BC_DELETE_DEREF, local_num);
Damien's avatar
Damien committed
455
456
}

457
static void emit_bc_delete_name(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
458
    emit_pre(emit, 0);
459
    emit_write_byte_code_byte_qstr(emit, MP_BC_DELETE_NAME, qstr);
Damien's avatar
Damien committed
460
461
}

462
static void emit_bc_delete_global(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
463
    emit_pre(emit, 0);
464
    emit_write_byte_code_byte_qstr(emit, MP_BC_DELETE_GLOBAL, qstr);
Damien's avatar
Damien committed
465
466
}

467
static void emit_bc_delete_attr(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
468
    emit_pre(emit, -1);
469
    emit_write_byte_code_byte_qstr(emit, MP_BC_DELETE_ATTR, qstr);
Damien's avatar
Damien committed
470
471
}

472
static void emit_bc_delete_subscr(emit_t *emit) {
Damien's avatar
Damien committed
473
    emit_pre(emit, -2);
474
    emit_write_byte_code_byte(emit, MP_BC_DELETE_SUBSCR);
Damien's avatar
Damien committed
475
476
}

477
static void emit_bc_dup_top(emit_t *emit) {
Damien's avatar
Damien committed
478
    emit_pre(emit, 1);
479
    emit_write_byte_code_byte(emit, MP_BC_DUP_TOP);
Damien's avatar
Damien committed
480
481
}

482
static void emit_bc_dup_top_two(emit_t *emit) {
Damien's avatar
Damien committed
483
    emit_pre(emit, 2);
484
    emit_write_byte_code_byte(emit, MP_BC_DUP_TOP_TWO);
Damien's avatar
Damien committed
485
486
}

487
static void emit_bc_pop_top(emit_t *emit) {
Damien's avatar
Damien committed
488
    emit_pre(emit, -1);
489
    emit_write_byte_code_byte(emit, MP_BC_POP_TOP);
Damien's avatar
Damien committed
490
491
}

492
static void emit_bc_rot_two(emit_t *emit) {
Damien's avatar
Damien committed
493
    emit_pre(emit, 0);
494
    emit_write_byte_code_byte(emit, MP_BC_ROT_TWO);
Damien's avatar
Damien committed
495
496
}

497
static void emit_bc_rot_three(emit_t *emit) {
Damien's avatar
Damien committed
498
    emit_pre(emit, 0);
499
    emit_write_byte_code_byte(emit, MP_BC_ROT_THREE);
Damien's avatar
Damien committed
500
501
}

502
static void emit_bc_jump(emit_t *emit, int label) {
Damien's avatar
Damien committed
503
    emit_pre(emit, 0);
504
    emit_write_byte_code_byte_signed_label(emit, MP_BC_JUMP, label);
Damien's avatar
Damien committed
505
506
}

507
static void emit_bc_pop_jump_if_true(emit_t *emit, int label) {
Damien's avatar
Damien committed
508
    emit_pre(emit, -1);
509
    emit_write_byte_code_byte_signed_label(emit, MP_BC_POP_JUMP_IF_TRUE, label);
Damien's avatar
Damien committed
510
511
}

512
static void emit_bc_pop_jump_if_false(emit_t *emit, int label) {
Damien's avatar
Damien committed
513
    emit_pre(emit, -1);
514
    emit_write_byte_code_byte_signed_label(emit, MP_BC_POP_JUMP_IF_FALSE, label);
Damien's avatar
Damien committed
515
516
}

517
static void emit_bc_jump_if_true_or_pop(emit_t *emit, int label) {
Damien's avatar
Damien committed
518
    emit_pre(emit, -1);
519
    emit_write_byte_code_byte_signed_label(emit, MP_BC_JUMP_IF_TRUE_OR_POP, label);
Damien's avatar
Damien committed
520
521
}

522
static void emit_bc_jump_if_false_or_pop(emit_t *emit, int label) {
Damien's avatar
Damien committed
523
    emit_pre(emit, -1);
524
    emit_write_byte_code_byte_signed_label(emit, MP_BC_JUMP_IF_FALSE_OR_POP, label);
Damien's avatar
Damien committed
525
526
}

527
static void emit_bc_setup_loop(emit_t *emit, int label) {
Damien's avatar
Damien committed
528
    emit_pre(emit, 0);
529
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_SETUP_LOOP, label);
Damien's avatar
Damien committed
530
531
}

532
static void emit_bc_break_loop(emit_t *emit, int label) {
Damien's avatar
Damien committed
533
    emit_pre(emit, 0);
534
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_BREAK_LOOP, label);
Damien's avatar
Damien committed
535
536
}

537
static void emit_bc_continue_loop(emit_t *emit, int label) {
Damien's avatar
Damien committed
538
    emit_pre(emit, 0);
539
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_CONTINUE_LOOP, label);
Damien's avatar
Damien committed
540
541
}

542
static void emit_bc_setup_with(emit_t *emit, int label) {
Damien's avatar
Damien committed
543
    emit_pre(emit, 7);
544
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_SETUP_WITH, label);
Damien's avatar
Damien committed
545
546
}

547
static void emit_bc_with_cleanup(emit_t *emit) {
Damien's avatar
Damien committed
548
    emit_pre(emit, -7);
549
    emit_write_byte_code_byte(emit, MP_BC_WITH_CLEANUP);
Damien's avatar
Damien committed
550
551
}

552
static void emit_bc_setup_except(emit_t *emit, int label) {
Damien's avatar
Damien committed
553
    emit_pre(emit, 6);
554
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_SETUP_EXCEPT, label);
Damien's avatar
Damien committed
555
556
}

557
static void emit_bc_setup_finally(emit_t *emit, int label) {
Damien's avatar
Damien committed
558
    emit_pre(emit, 6);
559
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_SETUP_FINALLY, label);
Damien's avatar
Damien committed
560
561
}

562
static void emit_bc_end_finally(emit_t *emit) {
Damien's avatar
Damien committed
563
    emit_pre(emit, -1);
564
    emit_write_byte_code_byte(emit, MP_BC_END_FINALLY);
Damien's avatar
Damien committed
565
566
}

567
static void emit_bc_get_iter(emit_t *emit) {
Damien's avatar
Damien committed
568
    emit_pre(emit, 0);
569
    emit_write_byte_code_byte(emit, MP_BC_GET_ITER);
Damien's avatar
Damien committed
570
571
}

572
static void emit_bc_for_iter(emit_t *emit, int label) {
Damien's avatar
Damien committed
573
    emit_pre(emit, 1);
574
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_FOR_ITER, label);
Damien's avatar
Damien committed
575
576
}

577
static void emit_bc_for_iter_end(emit_t *emit) {
Damien's avatar
Damien committed
578
579
580
    emit_pre(emit, -1);
}

581
static void emit_bc_pop_block(emit_t *emit) {
Damien's avatar
Damien committed
582
    emit_pre(emit, 0);
583
    emit_write_byte_code_byte(emit, MP_BC_POP_BLOCK);
Damien's avatar
Damien committed
584
585
}

586
static void emit_bc_pop_except(emit_t *emit) {
Damien's avatar
Damien committed
587
    emit_pre(emit, 0);
588
    emit_write_byte_code_byte(emit, MP_BC_POP_EXCEPT);
Damien's avatar
Damien committed
589
590
}

591
static void emit_bc_unary_op(emit_t *emit, rt_unary_op_t op) {
Damien's avatar
Damien committed
592
    emit_pre(emit, 0);
593
    emit_write_byte_code_byte_byte(emit, MP_BC_UNARY_OP, op);
Damien's avatar
Damien committed
594
595
}

596
static void emit_bc_binary_op(emit_t *emit, rt_binary_op_t op) {
Damien's avatar
Damien committed
597
    emit_pre(emit, -1);
598
    emit_write_byte_code_byte_byte(emit, MP_BC_BINARY_OP, op);
Damien's avatar
Damien committed
599
600
}

601
static void emit_bc_build_tuple(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
602
603
    assert(n_args >= 0);
    emit_pre(emit, 1 - n_args);
604
    emit_write_byte_code_byte_uint(emit, MP_BC_BUILD_TUPLE, n_args);
Damien's avatar
Damien committed
605
606
}

607
static void emit_bc_build_list(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
608
609
    assert(n_args >= 0);
    emit_pre(emit, 1 - n_args);
610
    emit_write_byte_code_byte_uint(emit, MP_BC_BUILD_LIST, n_args);
Damien's avatar
Damien committed
611
612
}

613
static void emit_bc_list_append(emit_t *emit, int list_stack_index) {
Damien's avatar
Damien committed
614
615
    assert(list_stack_index >= 0);
    emit_pre(emit, -1);
616
    emit_write_byte_code_byte_uint(emit, MP_BC_LIST_APPEND, list_stack_index);
Damien's avatar
Damien committed
617
618
}

619
static void emit_bc_build_map(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
620
621
    assert(n_args >= 0);
    emit_pre(emit, 1);
622
    emit_write_byte_code_byte_uint(emit, MP_BC_BUILD_MAP, n_args);
Damien's avatar
Damien committed
623
624
}

625
static void emit_bc_store_map(emit_t *emit) {
Damien's avatar
Damien committed
626
    emit_pre(emit, -2);
627
    emit_write_byte_code_byte(emit, MP_BC_STORE_MAP);
Damien's avatar
Damien committed
628
629
}

630
static void emit_bc_map_add(emit_t *emit, int map_stack_index) {
Damien's avatar
Damien committed
631
632
    assert(map_stack_index >= 0);
    emit_pre(emit, -2);
633
    emit_write_byte_code_byte_uint(emit, MP_BC_MAP_ADD, map_stack_index);
Damien's avatar
Damien committed
634
635
}

636
static void emit_bc_build_set(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
637
638
    assert(n_args >= 0);
    emit_pre(emit, 1 - n_args);
639
    emit_write_byte_code_byte_uint(emit, MP_BC_BUILD_SET, n_args);
Damien's avatar
Damien committed
640
641
}

642
static void emit_bc_set_add(emit_t *emit, int set_stack_index) {
Damien's avatar
Damien committed
643
644
    assert(set_stack_index >= 0);
    emit_pre(emit, -1);
645
    emit_write_byte_code_byte_uint(emit, MP_BC_SET_ADD, set_stack_index);
Damien's avatar
Damien committed
646
647
}

648
static void emit_bc_build_slice(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
649
650
    assert(n_args >= 0);
    emit_pre(emit, 1 - n_args);
651
    emit_write_byte_code_byte_uint(emit, MP_BC_BUILD_SLICE, n_args);
Damien's avatar
Damien committed
652
653
}

654
static void emit_bc_unpack_sequence(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_UNPACK_SEQUENCE, n_args);
Damien's avatar
Damien committed
658
659
}

660
static void emit_bc_unpack_ex(emit_t *emit, int n_left, int n_right) {
Damien's avatar
Damien committed
661
662
    assert(n_left >=0 && n_right >= 0);
    emit_pre(emit, -1 + n_left + n_right + 1);
663
    emit_write_byte_code_byte_uint(emit, MP_BC_UNPACK_EX, n_left | (n_right << 8));
Damien's avatar
Damien committed
664
665
}

666
static void emit_bc_make_function(emit_t *emit, scope_t *scope, int n_dict_params, int n_default_params) {
Damien's avatar
Damien committed
667
668
    assert(n_default_params == 0 && n_dict_params == 0);
    emit_pre(emit, 1);
669
    emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_FUNCTION, scope->unique_code_id);
Damien's avatar
Damien committed
670
671
}

672
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
673
674
    assert(n_default_params == 0 && n_dict_params == 0);
    emit_pre(emit, 0);
675
    emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_CLOSURE, scope->unique_code_id);
Damien's avatar
Damien committed
676
677
}

678
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
679
680
681
682
683
684
685
686
687
688
689
    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) {
690
            op = MP_BC_CALL_FUNCTION_VAR_KW;
Damien's avatar
Damien committed
691
        } else {
692
            op = MP_BC_CALL_FUNCTION_VAR;
Damien's avatar
Damien committed
693
694
695
        }
    } else {
        if (have_dbl_star_arg) {
696
            op = MP_BC_CALL_FUNCTION_KW;
Damien's avatar
Damien committed
697
        } else {
698
            op = MP_BC_CALL_FUNCTION;
Damien's avatar
Damien committed
699
700
        }
    }
701
    emit_write_byte_code_byte_uint(emit, op, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints
Damien's avatar
Damien committed
702
703
}

704
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
705
706
707
708
709
710
711
712
713
714
715
    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) {
716
            op = MP_BC_CALL_METHOD_VAR_KW;
Damien's avatar
Damien committed
717
        } else {
718
            op = MP_BC_CALL_METHOD_VAR;
Damien's avatar
Damien committed
719
720
721
        }
    } else {
        if (have_dbl_star_arg) {
722
            op = MP_BC_CALL_METHOD_KW;
Damien's avatar
Damien committed
723
        } else {
724
            op = MP_BC_CALL_METHOD;
Damien's avatar
Damien committed
725
726
        }
    }
727
    emit_write_byte_code_byte_uint(emit, op, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints
Damien's avatar
Damien committed
728
729
}

730
static void emit_bc_return_value(emit_t *emit) {
Damien's avatar
Damien committed
731
732
    emit_pre(emit, -1);
    emit->last_emit_was_return_value = true;
733
    emit_write_byte_code_byte(emit, MP_BC_RETURN_VALUE);
Damien's avatar
Damien committed
734
735
}

736
static void emit_bc_raise_varargs(emit_t *emit, int n_args) {
737
    assert(0 <= n_args && n_args <= 2);
Damien's avatar
Damien committed
738
    emit_pre(emit, -n_args);
739
    emit_write_byte_code_byte_byte(emit, MP_BC_RAISE_VARARGS, n_args);
Damien's avatar
Damien committed
740
741
}

742
static void emit_bc_yield_value(emit_t *emit) {
Damien's avatar
Damien committed
743
744
745
746
    emit_pre(emit, 0);
    if (emit->pass == PASS_2) {
        emit->scope->flags |= SCOPE_FLAG_GENERATOR;
    }
747
    emit_write_byte_code_byte(emit, MP_BC_YIELD_VALUE);
Damien's avatar
Damien committed
748
749
}

750
static void emit_bc_yield_from(emit_t *emit) {
Damien's avatar
Damien committed
751
752
753
754
    emit_pre(emit, -1);
    if (emit->pass == PASS_2) {
        emit->scope->flags |= SCOPE_FLAG_GENERATOR;
    }
755
    emit_write_byte_code_byte(emit, MP_BC_YIELD_FROM);
Damien's avatar
Damien committed
756
757
}

758
const emit_method_table_t emit_bc_method_table = {
759
760
    emit_bc_free,

761
762
763
764
765
766
    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,
767
    emit_bc_set_source_line,
768

769
770
771
772
    emit_bc_load_id,
    emit_bc_store_id,
    emit_bc_delete_id,

773
774
775
776
777
778
779
780
781
782
783
784
785
786
    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
787
788
    emit_bc_load_name,
    emit_bc_load_global,
789
790
791
792
    emit_bc_load_attr,
    emit_bc_load_method,
    emit_bc_load_build_class,
    emit_bc_store_fast,
Damien's avatar
Damien committed
793
    emit_bc_store_deref,
794
795
796
797
    emit_bc_store_name,
    emit_bc_store_global,
    emit_bc_store_attr,
    emit_bc_store_subscr,
798
    emit_bc_store_locals,
799
    emit_bc_delete_fast,
Damien's avatar
Damien committed
800
    emit_bc_delete_deref,
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
    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,
    emit_bc_break_loop,
    emit_bc_continue_loop,
    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,
};