emitbc.c 25.9 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"
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
46
47
48
49
50
51
52
53
54
55
56
// 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
57
58
}

59
60
61
62
63
64
65
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
66
67
}

68
69
70
71
72
73
74
75
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
76
77
    //printf("emit %d\n", num_bytes_to_write);
    if (emit->pass < PASS_3) {
78
        emit->byte_code_offset += num_bytes_to_write;
Damien's avatar
Damien committed
79
80
        return emit->dummy_data;
    } else {
81
82
83
        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
84
85
86
87
        return c;
    }
}

88
89
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
90
91
92
    c[0] = b1;
}

93
static void emit_write_byte_code_byte_byte(emit_t* emit, byte b1, uint b2) {
Damien's avatar
Damien committed
94
    assert((b2 & (~0xff)) == 0);
95
    byte* c = emit_get_cur_to_write_byte_code(emit, 2);
Damien's avatar
Damien committed
96
97
98
99
    c[0] = b1;
    c[1] = b2;
}

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

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

129
130
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
131
132
}

Damien's avatar
Damien committed
133
// unsigned labels are relative to ip following this instruction, stored as 16 bits
134
135
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
136
    if (emit->pass < PASS_3) {
137
        byte_code_offset = 0;
Damien's avatar
Damien committed
138
    } else {
139
        byte_code_offset = emit->label_offsets[label] - emit->byte_code_offset - 3;
Damien's avatar
Damien committed
140
    }
141
    byte* c = emit_get_cur_to_write_byte_code(emit, 3);
Damien's avatar
Damien committed
142
    c[0] = b1;
143
144
    c[1] = byte_code_offset;
    c[2] = byte_code_offset >> 8;
Damien's avatar
Damien committed
145
146
147
}

// signed labels are relative to ip following this instruction, stored as 16 bits, in excess
148
149
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
150
    if (emit->pass < PASS_3) {
151
        byte_code_offset = 0;
Damien's avatar
Damien committed
152
    } else {
153
        byte_code_offset = emit->label_offsets[label] - emit->byte_code_offset - 3 + 0x8000;
Damien's avatar
Damien committed
154
    }
155
    byte* c = emit_get_cur_to_write_byte_code(emit, 3);
Damien's avatar
Damien committed
156
    c[0] = b1;
157
158
    c[1] = byte_code_offset;
    c[2] = byte_code_offset >> 8;
Damien's avatar
Damien committed
159
160
}

Damien George's avatar
Damien George committed
161
162
163
164
165
166
167
168
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;
169
170
    emit->last_source_line_offset = 0;
    emit->last_source_line = 1;
Damien George's avatar
Damien George committed
171
172
173
    if (pass == PASS_2) {
        memset(emit->label_offsets, -1, emit->max_num_labels * sizeof(uint));
    }
174
175
176
177
178
179
180
181
182
183
184
185
186
187
    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
188
189
    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
190
191
192
193
194
195
196
197
198
199

    // 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);
200
    emit_write_byte_code_byte(emit, num_cell); // write number of locals that are cells
Damien George's avatar
Damien George committed
201
202
203
    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) {
204
            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
205
206
207
208
209
210
211
212
213
214
        }
    }
}

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);
    }

215
216
    emit_write_code_info_byte_byte(emit, 0, 0); // end of line number info

Damien George's avatar
Damien George committed
217
218
    if (emit->pass == PASS_2) {
        // calculate size of code in bytes
219
220
221
        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
222
223

    } else if (emit->pass == PASS_3) {
224
        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
225
226
227
    }
}

228
bool emit_bc_last_emit_was_return_value(emit_t *emit) {
Damien's avatar
Damien committed
229
230
231
    return emit->last_emit_was_return_value;
}

232
int emit_bc_get_stack_size(emit_t *emit) {
Damien's avatar
Damien committed
233
234
235
    return emit->stack_size;
}

236
static void emit_bc_set_stack_size(emit_t *emit, int size) {
237
    emit->stack_size = size;
Damien's avatar
Damien committed
238
239
}

240
static void emit_bc_set_source_line(emit_t *emit, int source_line) {
241
    //printf("source: line %d -> %d  offset %d -> %d\n", emit->last_source_line, source_line, emit->last_source_line_offset, emit->byte_code_offset);
242
243
244
245
246
247
248
249
250
251
    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);
252
        //printf("  %d %d\n", bytes_to_skip, lines_to_skip);
253
254
255
256
257
        emit->last_source_line_offset = emit->byte_code_offset;
        emit->last_source_line = source_line;
    }
}

258
259
260
261
262
263
264
265
266
267
268
269
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);
}

270
static void emit_pre(emit_t *emit, int stack_size_delta) {
271
272
273
    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
274
275
276
277
    }
    emit->last_emit_was_return_value = false;
}

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

292
static void emit_bc_import_name(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
293
    emit_pre(emit, -1);
294
    emit_write_byte_code_byte_qstr(emit, MP_BC_IMPORT_NAME, qstr);
Damien's avatar
Damien committed
295
296
}

297
static void emit_bc_import_from(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
298
    emit_pre(emit, 1);
299
    emit_write_byte_code_byte_qstr(emit, MP_BC_IMPORT_FROM, qstr);
Damien's avatar
Damien committed
300
301
}

302
static void emit_bc_import_star(emit_t *emit) {
Damien's avatar
Damien committed
303
    emit_pre(emit, -1);
304
    emit_write_byte_code_byte(emit, MP_BC_IMPORT_STAR);
Damien's avatar
Damien committed
305
306
}

307
static void emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
Damien's avatar
Damien committed
308
309
    emit_pre(emit, 1);
    switch (tok) {
310
311
312
313
        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
314
315
316
317
        default: assert(0);
    }
}

318
static void emit_bc_load_const_small_int(emit_t *emit, int arg) {
Damien's avatar
Damien committed
319
    emit_pre(emit, 1);
320
    emit_write_byte_code_byte_int(emit, MP_BC_LOAD_CONST_SMALL_INT, arg);
Damien's avatar
Damien committed
321
322
}

323
static void emit_bc_load_const_int(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
324
    emit_pre(emit, 1);
325
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_INT, qstr);
Damien's avatar
Damien committed
326
327
}

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

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

338
static void emit_bc_load_const_str(emit_t *emit, qstr qstr, bool bytes) {
Damien's avatar
Damien committed
339
340
    emit_pre(emit, 1);
    if (bytes) {
341
        emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_BYTES, qstr);
Damien's avatar
Damien committed
342
    } else {
343
        emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_STRING, qstr);
Damien's avatar
Damien committed
344
345
346
    }
}

347
static void emit_bc_load_const_verbatim_str(emit_t *emit, const char *str) {
348
    // not needed/supported for BC
Damien's avatar
Damien committed
349
350
351
    assert(0);
}

352
static void emit_bc_load_fast(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
353
354
355
    assert(local_num >= 0);
    emit_pre(emit, 1);
    switch (local_num) {
356
357
358
359
        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
360
361
362
    }
}

Damien's avatar
Damien committed
363
static void emit_bc_load_deref(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
364
    emit_pre(emit, 1);
365
    emit_write_byte_code_byte_uint(emit, MP_BC_LOAD_DEREF, local_num);
Damien's avatar
Damien committed
366
367
}

Damien's avatar
Damien committed
368
static void emit_bc_load_closure(emit_t *emit, qstr qstr, int local_num) {
Damien George's avatar
Damien George committed
369
370
    // not needed/supported for BC
    assert(0);
Damien's avatar
Damien committed
371
372
}

Damien's avatar
Damien committed
373
static void emit_bc_load_name(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_NAME, qstr);
Damien's avatar
Damien committed
376
377
}

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

383
static void emit_bc_load_attr(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
384
    emit_pre(emit, 0);
385
    emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_ATTR, qstr);
Damien's avatar
Damien committed
386
387
}

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

393
static void emit_bc_load_build_class(emit_t *emit) {
Damien's avatar
Damien committed
394
    emit_pre(emit, 1);
395
    emit_write_byte_code_byte(emit, MP_BC_LOAD_BUILD_CLASS);
Damien's avatar
Damien committed
396
397
}

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

Damien's avatar
Damien committed
409
410
static void emit_bc_store_deref(emit_t *emit, qstr qstr, int local_num) {
    emit_pre(emit, -1);
411
    emit_write_byte_code_byte_uint(emit, MP_BC_STORE_DEREF, local_num);
Damien's avatar
Damien committed
412
413
}

414
static void emit_bc_store_name(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
415
    emit_pre(emit, -1);
416
    emit_write_byte_code_byte_qstr(emit, MP_BC_STORE_NAME, qstr);
Damien's avatar
Damien committed
417
418
}

419
static void emit_bc_store_global(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
420
    emit_pre(emit, -1);
421
    emit_write_byte_code_byte_qstr(emit, MP_BC_STORE_GLOBAL, qstr);
Damien's avatar
Damien committed
422
423
}

424
static void emit_bc_store_attr(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
425
    emit_pre(emit, -2);
426
    emit_write_byte_code_byte_qstr(emit, MP_BC_STORE_ATTR, qstr);
Damien's avatar
Damien committed
427
428
}

429
static void emit_bc_store_subscr(emit_t *emit) {
Damien's avatar
Damien committed
430
    emit_pre(emit, -3);
431
    emit_write_byte_code_byte(emit, MP_BC_STORE_SUBSCR);
Damien's avatar
Damien committed
432
433
}

434
static void emit_bc_store_locals(emit_t *emit) {
435
    // not needed
436
    emit_pre(emit, -1);
437
    emit_write_byte_code_byte(emit, MP_BC_POP_TOP);
438
439
}

440
static void emit_bc_delete_fast(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
441
442
    assert(local_num >= 0);
    emit_pre(emit, 0);
443
    emit_write_byte_code_byte_uint(emit, MP_BC_DELETE_FAST_N, local_num);
Damien's avatar
Damien committed
444
445
}

Damien's avatar
Damien committed
446
447
static void emit_bc_delete_deref(emit_t *emit, qstr qstr, int local_num) {
    emit_pre(emit, 0);
448
    emit_write_byte_code_byte_qstr(emit, MP_BC_DELETE_DEREF, local_num);
Damien's avatar
Damien committed
449
450
}

451
static void emit_bc_delete_name(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
452
    emit_pre(emit, 0);
453
    emit_write_byte_code_byte_qstr(emit, MP_BC_DELETE_NAME, qstr);
Damien's avatar
Damien committed
454
455
}

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

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

466
static void emit_bc_delete_subscr(emit_t *emit) {
Damien's avatar
Damien committed
467
    emit_pre(emit, -2);
468
    emit_write_byte_code_byte(emit, MP_BC_DELETE_SUBSCR);
Damien's avatar
Damien committed
469
470
}

471
static void emit_bc_dup_top(emit_t *emit) {
Damien's avatar
Damien committed
472
    emit_pre(emit, 1);
473
    emit_write_byte_code_byte(emit, MP_BC_DUP_TOP);
Damien's avatar
Damien committed
474
475
}

476
static void emit_bc_dup_top_two(emit_t *emit) {
Damien's avatar
Damien committed
477
    emit_pre(emit, 2);
478
    emit_write_byte_code_byte(emit, MP_BC_DUP_TOP_TWO);
Damien's avatar
Damien committed
479
480
}

481
static void emit_bc_pop_top(emit_t *emit) {
Damien's avatar
Damien committed
482
    emit_pre(emit, -1);
483
    emit_write_byte_code_byte(emit, MP_BC_POP_TOP);
Damien's avatar
Damien committed
484
485
}

486
static void emit_bc_rot_two(emit_t *emit) {
Damien's avatar
Damien committed
487
    emit_pre(emit, 0);
488
    emit_write_byte_code_byte(emit, MP_BC_ROT_TWO);
Damien's avatar
Damien committed
489
490
}

491
static void emit_bc_rot_three(emit_t *emit) {
Damien's avatar
Damien committed
492
    emit_pre(emit, 0);
493
    emit_write_byte_code_byte(emit, MP_BC_ROT_THREE);
Damien's avatar
Damien committed
494
495
}

496
static void emit_bc_jump(emit_t *emit, int label) {
Damien's avatar
Damien committed
497
    emit_pre(emit, 0);
498
    emit_write_byte_code_byte_signed_label(emit, MP_BC_JUMP, label);
Damien's avatar
Damien committed
499
500
}

501
static void emit_bc_pop_jump_if_true(emit_t *emit, int label) {
Damien's avatar
Damien committed
502
    emit_pre(emit, -1);
503
    emit_write_byte_code_byte_signed_label(emit, MP_BC_POP_JUMP_IF_TRUE, label);
Damien's avatar
Damien committed
504
505
}

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

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

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

521
static void emit_bc_setup_loop(emit_t *emit, int label) {
Damien's avatar
Damien committed
522
    emit_pre(emit, 0);
523
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_SETUP_LOOP, label);
Damien's avatar
Damien committed
524
525
}

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

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

536
static void emit_bc_setup_with(emit_t *emit, int label) {
Damien's avatar
Damien committed
537
    emit_pre(emit, 7);
538
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_SETUP_WITH, label);
Damien's avatar
Damien committed
539
540
}

541
static void emit_bc_with_cleanup(emit_t *emit) {
Damien's avatar
Damien committed
542
    emit_pre(emit, -7);
543
    emit_write_byte_code_byte(emit, MP_BC_WITH_CLEANUP);
Damien's avatar
Damien committed
544
545
}

546
static void emit_bc_setup_except(emit_t *emit, int label) {
Damien's avatar
Damien committed
547
    emit_pre(emit, 6);
548
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_SETUP_EXCEPT, label);
Damien's avatar
Damien committed
549
550
}

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

556
static void emit_bc_end_finally(emit_t *emit) {
Damien's avatar
Damien committed
557
    emit_pre(emit, -1);
558
    emit_write_byte_code_byte(emit, MP_BC_END_FINALLY);
Damien's avatar
Damien committed
559
560
}

561
static void emit_bc_get_iter(emit_t *emit) {
Damien's avatar
Damien committed
562
    emit_pre(emit, 0);
563
    emit_write_byte_code_byte(emit, MP_BC_GET_ITER);
Damien's avatar
Damien committed
564
565
}

566
static void emit_bc_for_iter(emit_t *emit, int label) {
Damien's avatar
Damien committed
567
    emit_pre(emit, 1);
568
    emit_write_byte_code_byte_unsigned_label(emit, MP_BC_FOR_ITER, label);
Damien's avatar
Damien committed
569
570
}

571
static void emit_bc_for_iter_end(emit_t *emit) {
Damien's avatar
Damien committed
572
573
574
    emit_pre(emit, -1);
}

575
static void emit_bc_pop_block(emit_t *emit) {
Damien's avatar
Damien committed
576
    emit_pre(emit, 0);
577
    emit_write_byte_code_byte(emit, MP_BC_POP_BLOCK);
Damien's avatar
Damien committed
578
579
}

580
static void emit_bc_pop_except(emit_t *emit) {
Damien's avatar
Damien committed
581
    emit_pre(emit, 0);
582
    emit_write_byte_code_byte(emit, MP_BC_POP_EXCEPT);
Damien's avatar
Damien committed
583
584
}

585
static void emit_bc_unary_op(emit_t *emit, rt_unary_op_t op) {
Damien's avatar
Damien committed
586
    emit_pre(emit, 0);
587
    emit_write_byte_code_byte_byte(emit, MP_BC_UNARY_OP, op);
Damien's avatar
Damien committed
588
589
}

590
static void emit_bc_binary_op(emit_t *emit, rt_binary_op_t op) {
Damien's avatar
Damien committed
591
    emit_pre(emit, -1);
592
    emit_write_byte_code_byte_byte(emit, MP_BC_BINARY_OP, op);
Damien's avatar
Damien committed
593
594
}

595
static void emit_bc_build_tuple(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
596
597
    assert(n_args >= 0);
    emit_pre(emit, 1 - n_args);
598
    emit_write_byte_code_byte_uint(emit, MP_BC_BUILD_TUPLE, n_args);
Damien's avatar
Damien committed
599
600
}

601
static void emit_bc_build_list(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_LIST, n_args);
Damien's avatar
Damien committed
605
606
}

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

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

619
static void emit_bc_store_map(emit_t *emit) {
Damien's avatar
Damien committed
620
    emit_pre(emit, -2);
621
    emit_write_byte_code_byte(emit, MP_BC_STORE_MAP);
Damien's avatar
Damien committed
622
623
}

624
static void emit_bc_map_add(emit_t *emit, int map_stack_index) {
Damien's avatar
Damien committed
625
626
    assert(map_stack_index >= 0);
    emit_pre(emit, -2);
627
    emit_write_byte_code_byte_uint(emit, MP_BC_MAP_ADD, map_stack_index);
Damien's avatar
Damien committed
628
629
}

630
static void emit_bc_build_set(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
631
632
    assert(n_args >= 0);
    emit_pre(emit, 1 - n_args);
633
    emit_write_byte_code_byte_uint(emit, MP_BC_BUILD_SET, n_args);
Damien's avatar
Damien committed
634
635
}

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

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

648
static void emit_bc_unpack_sequence(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_UNPACK_SEQUENCE, n_args);
Damien's avatar
Damien committed
652
653
}

654
static void emit_bc_unpack_ex(emit_t *emit, int n_left, int n_right) {
Damien's avatar
Damien committed
655
656
    assert(n_left >=0 && n_right >= 0);
    emit_pre(emit, -1 + n_left + n_right + 1);
657
    emit_write_byte_code_byte_uint(emit, MP_BC_UNPACK_EX, n_left | (n_right << 8));
Damien's avatar
Damien committed
658
659
}

660
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
661
662
    assert(n_default_params == 0 && n_dict_params == 0);
    emit_pre(emit, 1);
663
    emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_FUNCTION, scope->unique_code_id);
Damien's avatar
Damien committed
664
665
}

666
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
667
668
    assert(n_default_params == 0 && n_dict_params == 0);
    emit_pre(emit, 0);
669
    emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_CLOSURE, scope->unique_code_id);
Damien's avatar
Damien committed
670
671
}

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

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

724
static void emit_bc_return_value(emit_t *emit) {
Damien's avatar
Damien committed
725
726
    emit_pre(emit, -1);
    emit->last_emit_was_return_value = true;
727
    emit_write_byte_code_byte(emit, MP_BC_RETURN_VALUE);
Damien's avatar
Damien committed
728
729
}

730
static void emit_bc_raise_varargs(emit_t *emit, int n_args) {
731
    assert(0 <= n_args && n_args <= 2);
Damien's avatar
Damien committed
732
    emit_pre(emit, -n_args);
733
    emit_write_byte_code_byte_byte(emit, MP_BC_RAISE_VARARGS, n_args);
Damien's avatar
Damien committed
734
735
}

736
static void emit_bc_yield_value(emit_t *emit) {
Damien's avatar
Damien committed
737
738
739
740
    emit_pre(emit, 0);
    if (emit->pass == PASS_2) {
        emit->scope->flags |= SCOPE_FLAG_GENERATOR;
    }
741
    emit_write_byte_code_byte(emit, MP_BC_YIELD_VALUE);
Damien's avatar
Damien committed
742
743
}

744
static void emit_bc_yield_from(emit_t *emit) {
Damien's avatar
Damien committed
745
746
747
748
    emit_pre(emit, -1);
    if (emit->pass == PASS_2) {
        emit->scope->flags |= SCOPE_FLAG_GENERATOR;
    }
749
    emit_write_byte_code_byte(emit, MP_BC_YIELD_FROM);
Damien's avatar
Damien committed
750
751
}

752
const emit_method_table_t emit_bc_method_table = {
753
754
755
756
757
758
    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,
759
    emit_bc_set_source_line,
760

761
762
763
764
    emit_bc_load_id,
    emit_bc_store_id,
    emit_bc_delete_id,

765
766
767
768
769
770
771
772
773
774
775
776
777
778
    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
779
780
    emit_bc_load_name,
    emit_bc_load_global,
781
782
783
784
    emit_bc_load_attr,
    emit_bc_load_method,
    emit_bc_load_build_class,
    emit_bc_store_fast,
Damien's avatar
Damien committed
785
    emit_bc_store_deref,
786
787
788
789
    emit_bc_store_name,
    emit_bc_store_global,
    emit_bc_store_attr,
    emit_bc_store_subscr,
790
    emit_bc_store_locals,
791
    emit_bc_delete_fast,
Damien's avatar
Damien committed
792
    emit_bc_delete_deref,
793
794
795
796
797
798
799
800
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
    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,
};