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

51
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_bytes_lines(emit_t* emit, uint bytes_to_skip, uint lines_to_skip) {
    for (; bytes_to_skip > 31; bytes_to_skip -= 31) {
        *emit_get_cur_to_write_code_info(emit, 1) = 31;
    }
    for (; lines_to_skip > 7; lines_to_skip -= 7) {
        *emit_get_cur_to_write_code_info(emit, 1) = 7 << 5;
    }
    *emit_get_cur_to_write_code_info(emit, 1) = bytes_to_skip | (lines_to_skip << 5);
82
83
84
85
}

// 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
86
87
    //printf("emit %d\n", num_bytes_to_write);
    if (emit->pass < PASS_3) {
88
        emit->byte_code_offset += num_bytes_to_write;
Damien's avatar
Damien committed
89
90
        return emit->dummy_data;
    } else {
91
92
93
        assert(emit->byte_code_offset + num_bytes_to_write <= emit->byte_code_size);
        byte *c = emit->code_base + emit->code_info_size + emit->byte_code_offset;
        emit->byte_code_offset += num_bytes_to_write;
Damien's avatar
Damien committed
94
95
96
97
        return c;
    }
}

98
99
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
100
101
102
    c[0] = b1;
}

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

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

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

139
140
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
141
142
}

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

// signed labels are relative to ip following this instruction, stored as 16 bits, in excess
158
159
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
160
    if (emit->pass < PASS_3) {
161
        byte_code_offset = 0;
Damien's avatar
Damien committed
162
    } else {
163
        byte_code_offset = emit->label_offsets[label] - emit->byte_code_offset - 3 + 0x8000;
Damien's avatar
Damien committed
164
    }
165
    byte* c = emit_get_cur_to_write_byte_code(emit, 3);
Damien's avatar
Damien committed
166
    c[0] = b1;
167
168
    c[1] = byte_code_offset;
    c[2] = byte_code_offset >> 8;
Damien's avatar
Damien committed
169
170
}

Damien George's avatar
Damien George committed
171
172
173
174
175
176
177
178
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;
179
180
    emit->last_source_line_offset = 0;
    emit->last_source_line = 1;
Damien George's avatar
Damien George committed
181
182
183
    if (pass == PASS_2) {
        memset(emit->label_offsets, -1, emit->max_num_labels * sizeof(uint));
    }
184
185
186
187
188
189
190
191
192
193
194
195
196
197
    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
198
199
    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
200
201
202
203
204
205
206
207
208
209

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

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

225
    emit_write_code_info_bytes_lines(emit, 0, 0); // end of line number info
226

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

    } else if (emit->pass == PASS_3) {
234
        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
235
236
237
    }
}

238
bool emit_bc_last_emit_was_return_value(emit_t *emit) {
Damien's avatar
Damien committed
239
240
241
    return emit->last_emit_was_return_value;
}

242
int emit_bc_get_stack_size(emit_t *emit) {
Damien's avatar
Damien committed
243
244
245
    return emit->stack_size;
}

246
static void emit_bc_set_stack_size(emit_t *emit, int size) {
247
    emit->stack_size = size;
Damien's avatar
Damien committed
248
249
}

250
static void emit_bc_set_source_line(emit_t *emit, int source_line) {
251
    //printf("source: line %d -> %d  offset %d -> %d\n", emit->last_source_line, source_line, emit->last_source_line_offset, emit->byte_code_offset);
252
    if (source_line > emit->last_source_line) {
253
254
255
        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);
256
        //printf("  %d %d\n", bytes_to_skip, lines_to_skip);
257
258
259
260
261
        emit->last_source_line_offset = emit->byte_code_offset;
        emit->last_source_line = source_line;
    }
}

262
263
264
265
266
267
268
269
270
271
272
273
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);
}

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

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

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

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

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

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

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

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

332
static void emit_bc_load_const_dec(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_LOAD_CONST_DEC, qstr);
Damien's avatar
Damien committed
335
336
}

337
static void emit_bc_load_const_id(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_LOAD_CONST_ID, qstr);
Damien's avatar
Damien committed
340
341
}

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

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

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

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

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

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

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

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

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

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

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

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

418
static void emit_bc_store_name(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_STORE_NAME, qstr);
Damien's avatar
Damien committed
421
422
}

423
static void emit_bc_store_global(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
424
    emit_pre(emit, -1);
425
    emit_write_byte_code_byte_qstr(emit, MP_BC_STORE_GLOBAL, qstr);
Damien's avatar
Damien committed
426
427
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

652
static void emit_bc_unpack_sequence(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
653
654
    assert(n_args >= 0);
    emit_pre(emit, -1 + n_args);
655
    emit_write_byte_code_byte_uint(emit, MP_BC_UNPACK_SEQUENCE, n_args);
Damien's avatar
Damien committed
656
657
}

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

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

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

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

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

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

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

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

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

756
const emit_method_table_t emit_bc_method_table = {
757
758
759
760
761
762
    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,
763
    emit_bc_set_source_line,
764

765
766
767
768
    emit_bc_load_id,
    emit_bc_store_id,
    emit_bc_delete_id,

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