emitbc.c 21.8 KB
Newer Older
Damien's avatar
Damien committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>

#include "misc.h"
#include "lexer.h"
#include "machine.h"
#include "parse.h"
#include "compile.h"
#include "scope.h"
#include "runtime.h"
#include "emit.h"
#include "bc.h"

18
19
struct _emit_t {
    pass_kind_t pass;
Damien's avatar
Damien committed
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    int next_label;
    int stack_size;
    bool last_emit_was_return_value;

    scope_t *scope;

    int max_num_labels;
    uint *label_offsets;

    uint code_offset;
    uint code_size;
    byte *code_base;
    byte dummy_data[8];
};

35
uint emit_bc_get_code_size(emit_t* emit) {
Damien's avatar
Damien committed
36
37
38
    return emit->code_size;
}

39
void* emit_bc_get_code(emit_t* emit) {
Damien's avatar
Damien committed
40
41
42
    return emit->code_base;
}

43
44
45
46
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) {
Damien's avatar
Damien committed
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
    emit->pass = pass;
    emit->next_label = 1;
    emit->stack_size = 0;
    emit->last_emit_was_return_value = false;
    emit->scope = scope;
    if (pass == PASS_1) {
        scope->unique_code_id = rt_get_new_unique_code_id();
    } else if (pass > PASS_1) {
        if (emit->label_offsets == NULL) {
            emit->label_offsets = m_new(uint, emit->max_num_labels);
        }
        if (pass == PASS_2) {
            memset(emit->label_offsets, -1, emit->max_num_labels * sizeof(uint));
        }
    }
    emit->code_offset = 0;
}

65
static void emit_bc_end_pass(emit_t *emit) {
Damien's avatar
Damien committed
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
    // 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);
    }

    if (emit->pass == PASS_1) {
        // calculate number of labels need
        if (emit->next_label > emit->max_num_labels) {
            emit->max_num_labels = emit->next_label;
        }

    } else if (emit->pass == PASS_2) {
        // calculate size of code in bytes
        emit->code_size = emit->code_offset;
        emit->code_base = m_new(byte, emit->code_size);
        printf("code_size: %u\n", emit->code_size);

    } else if (emit->pass == PASS_3) {
        rt_assign_byte_code(emit->scope->unique_code_id, emit->code_base, emit->code_size, emit->scope->num_params);
    }
}

// all functions must go through this one to emit bytes
89
static byte* emit_get_cur_to_write_bytes(emit_t* emit, int num_bytes_to_write) {
Damien's avatar
Damien committed
90
91
92
93
94
95
96
97
98
99
100
101
    //printf("emit %d\n", num_bytes_to_write);
    if (emit->pass < PASS_3) {
        emit->code_offset += num_bytes_to_write;
        return emit->dummy_data;
    } else {
        assert(emit->code_offset + num_bytes_to_write <= emit->code_size);
        byte *c = emit->code_base + emit->code_offset;
        emit->code_offset += num_bytes_to_write;
        return c;
    }
}

102
static void emit_write_byte_1(emit_t* emit, byte b1) {
Damien's avatar
Damien committed
103
104
105
106
    byte* c = emit_get_cur_to_write_bytes(emit, 1);
    c[0] = b1;
}

107
static void emit_write_byte_1_byte(emit_t* emit, byte b1, uint b2) {
Damien's avatar
Damien committed
108
109
110
111
112
113
    assert((b2 & (~0xff)) == 0);
    byte* c = emit_get_cur_to_write_bytes(emit, 2);
    c[0] = b1;
    c[1] = b2;
}

114
static void emit_write_byte_1_int(emit_t* emit, byte b1, int num) {
Damien's avatar
Damien committed
115
116
117
118
119
120
121
    assert((num & (~0x7fff)) == 0 || (num & (~0x7fff)) == (~0x7fff));
    byte* c = emit_get_cur_to_write_bytes(emit, 3);
    c[0] = b1;
    c[1] = num;
    c[2] = num >> 8;
}

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

140
static void emit_write_byte_1_qstr(emit_t* emit, byte b1, qstr qstr) {
Damien's avatar
Damien committed
141
142
143
    emit_write_byte_1_uint(emit, b1, qstr);
}

144
static void emit_write_byte_1_label(emit_t* emit, byte b1, int label) {
Damien's avatar
Damien committed
145
146
147
148
149
150
151
152
153
    uint code_offset;
    if (emit->pass < PASS_3) {
        code_offset = 0;
    } else {
        code_offset = emit->label_offsets[label];
    }
    emit_write_byte_1_uint(emit, b1, code_offset);
}

154
bool emit_bc_last_emit_was_return_value(emit_t *emit) {
Damien's avatar
Damien committed
155
156
157
    return emit->last_emit_was_return_value;
}

158
int emit_bc_get_stack_size(emit_t *emit) {
Damien's avatar
Damien committed
159
160
161
    return emit->stack_size;
}

162
static void emit_bc_set_stack_size(emit_t *emit, int size) {
Damien's avatar
Damien committed
163
164
165
166
167
    if (emit->pass > PASS_1) {
        emit->stack_size = size;
    }
}

168
static void emit_pre(emit_t *emit, int stack_size_delta) {
Damien's avatar
Damien committed
169
170
171
172
173
174
175
176
177
    if (emit->pass > PASS_1) {
        emit->stack_size += stack_size_delta;
        if (emit->stack_size > emit->scope->stack_size) {
            emit->scope->stack_size = emit->stack_size;
        }
    }
    emit->last_emit_was_return_value = false;
}

178
static int emit_bc_label_new(emit_t *emit) {
Damien's avatar
Damien committed
179
180
181
    return emit->next_label++;
}

182
static void emit_bc_label_assign(emit_t *emit, int l) {
Damien's avatar
Damien committed
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
    emit_pre(emit, 0);
    if (emit->pass > PASS_1) {
        assert(l < emit->max_num_labels);
        if (emit->pass == PASS_2) {
            // assign label offset
            assert(emit->label_offsets[l] == -1);
            emit->label_offsets[l] = emit->code_offset;
        } else if (emit->pass == PASS_3) {
            // ensure label offset has not changed from PASS_2 to PASS_3
            assert(emit->label_offsets[l] == emit->code_offset);
            //printf("l%d: (at %d)\n", l, emit->code_offset);
        }
    }
}

198
static void emit_bc_import_name(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
199
200
201
202
    emit_pre(emit, -1);
    emit_write_byte_1_qstr(emit, PYBC_IMPORT_NAME, qstr);
}

203
static void emit_bc_import_from(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
204
205
206
207
    emit_pre(emit, 1);
    emit_write_byte_1_qstr(emit, PYBC_IMPORT_FROM, qstr);
}

208
static void emit_bc_import_star(emit_t *emit) {
Damien's avatar
Damien committed
209
210
211
212
    emit_pre(emit, -1);
    emit_write_byte_1(emit, PYBC_IMPORT_STAR);
}

213
static void emit_bc_load_const_tok(emit_t *emit, py_token_kind_t tok) {
Damien's avatar
Damien committed
214
215
216
217
218
219
220
221
222
    emit_pre(emit, 1);
    switch (tok) {
        case PY_TOKEN_KW_FALSE: emit_write_byte_1(emit, PYBC_LOAD_CONST_FALSE); break;
        case PY_TOKEN_KW_NONE: emit_write_byte_1(emit, PYBC_LOAD_CONST_NONE); break;
        case PY_TOKEN_KW_TRUE: emit_write_byte_1(emit, PYBC_LOAD_CONST_TRUE); break;
        default: assert(0);
    }
}

223
static void emit_bc_load_const_small_int(emit_t *emit, int arg) {
Damien's avatar
Damien committed
224
225
226
227
    emit_pre(emit, 1);
    emit_write_byte_1_int(emit, PYBC_LOAD_CONST_SMALL_INT, arg);
}

228
static void emit_bc_load_const_int(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
229
230
231
232
    emit_pre(emit, 1);
    emit_write_byte_1_qstr(emit, PYBC_LOAD_CONST_INT, qstr);
}

233
static void emit_bc_load_const_dec(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
234
235
236
237
    emit_pre(emit, 1);
    emit_write_byte_1_qstr(emit, PYBC_LOAD_CONST_DEC, qstr);
}

238
static void emit_bc_load_const_id(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
239
240
241
242
    emit_pre(emit, 1);
    emit_write_byte_1_qstr(emit, PYBC_LOAD_CONST_ID, qstr);
}

243
static void emit_bc_load_const_str(emit_t *emit, qstr qstr, bool bytes) {
Damien's avatar
Damien committed
244
245
246
247
248
249
250
251
    emit_pre(emit, 1);
    if (bytes) {
        emit_write_byte_1_qstr(emit, PYBC_LOAD_CONST_BYTES, qstr);
    } else {
        emit_write_byte_1_qstr(emit, PYBC_LOAD_CONST_STRING, qstr);
    }
}

252
static void emit_bc_load_const_verbatim_start(emit_t *emit) {
Damien's avatar
Damien committed
253
254
255
256
    emit_pre(emit, 1);
    assert(0);
}

257
static void emit_bc_load_const_verbatim_int(emit_t *emit, int val) {
Damien's avatar
Damien committed
258
259
260
    assert(0);
}

261
static void emit_bc_load_const_verbatim_str(emit_t *emit, const char *str) {
Damien's avatar
Damien committed
262
263
264
    assert(0);
}

265
static void emit_bc_load_const_verbatim_strn(emit_t *emit, const char *str, int len) {
Damien's avatar
Damien committed
266
267
268
    assert(0);
}

269
static void emit_bc_load_const_verbatim_quoted_str(emit_t *emit, qstr qstr, bool bytes) {
Damien's avatar
Damien committed
270
271
272
    assert(0);
}

273
static void emit_bc_load_const_verbatim_end(emit_t *emit) {
Damien's avatar
Damien committed
274
275
276
    assert(0);
}

277
static void emit_bc_load_fast(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
278
279
280
281
282
283
284
285
286
287
    assert(local_num >= 0);
    emit_pre(emit, 1);
    switch (local_num) {
        case 0: emit_write_byte_1(emit, PYBC_LOAD_FAST_0); break;
        case 1: emit_write_byte_1(emit, PYBC_LOAD_FAST_1); break;
        case 2: emit_write_byte_1(emit, PYBC_LOAD_FAST_2); break;
        default: emit_write_byte_1_uint(emit, PYBC_LOAD_FAST_N, local_num); break;
    }
}

288
static void emit_bc_load_name(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
289
290
291
292
    emit_pre(emit, 1);
    emit_write_byte_1_qstr(emit, PYBC_LOAD_NAME, qstr);
}

293
static void emit_bc_load_global(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
294
295
296
297
    emit_pre(emit, 1);
    emit_write_byte_1_qstr(emit, PYBC_LOAD_GLOBAL, qstr);
}

298
static void emit_bc_load_deref(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
299
300
301
302
    emit_pre(emit, 1);
    assert(0);
}

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

308
static void emit_bc_load_attr(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
309
310
311
312
    emit_pre(emit, 0);
    emit_write_byte_1_qstr(emit, PYBC_LOAD_ATTR, qstr);
}

313
static void emit_bc_load_method(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
314
315
316
317
    emit_pre(emit, 0);
    emit_write_byte_1_qstr(emit, PYBC_LOAD_METHOD, qstr);
}

318
static void emit_bc_load_build_class(emit_t *emit) {
Damien's avatar
Damien committed
319
320
321
322
    emit_pre(emit, 1);
    emit_write_byte_1(emit, PYBC_LOAD_BUILD_CLASS);
}

323
static void emit_bc_store_fast(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
324
325
326
327
328
329
330
331
332
333
    assert(local_num >= 0);
    emit_pre(emit, -1);
    switch (local_num) {
        case 0: emit_write_byte_1(emit, PYBC_STORE_FAST_0); break;
        case 1: emit_write_byte_1(emit, PYBC_STORE_FAST_1); break;
        case 2: emit_write_byte_1(emit, PYBC_STORE_FAST_2); break;
        default: emit_write_byte_1_uint(emit, PYBC_STORE_FAST_N, local_num); break;
    }
}

334
static void emit_bc_store_name(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
335
336
337
338
    emit_pre(emit, -1);
    emit_write_byte_1_qstr(emit, PYBC_STORE_NAME, qstr);
}

339
static void emit_bc_store_global(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
340
341
342
343
    emit_pre(emit, -1);
    emit_write_byte_1_qstr(emit, PYBC_STORE_GLOBAL, qstr);
}

344
static void emit_bc_store_deref(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
345
346
347
348
    emit_pre(emit, -1);
    assert(0);
}

349
static void emit_bc_store_attr(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
350
351
352
353
    emit_pre(emit, -2);
    emit_write_byte_1_qstr(emit, PYBC_STORE_ATTR, qstr);
}

354
static void emit_bc_store_locals(emit_t *emit) {
Damien's avatar
Damien committed
355
356
357
358
    emit_pre(emit, -1);
    emit_write_byte_1(emit, PYBC_STORE_LOCALS);
}

359
static void emit_bc_store_subscr(emit_t *emit) {
Damien's avatar
Damien committed
360
361
362
363
    emit_pre(emit, -3);
    emit_write_byte_1(emit, PYBC_STORE_SUBSCR);
}

364
static void emit_bc_delete_fast(emit_t *emit, qstr qstr, int local_num) {
Damien's avatar
Damien committed
365
366
367
368
369
    assert(local_num >= 0);
    emit_pre(emit, 0);
    emit_write_byte_1_uint(emit, PYBC_DELETE_FAST_N, local_num);
}

370
static void emit_bc_delete_name(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
371
372
373
374
    emit_pre(emit, 0);
    emit_write_byte_1_qstr(emit, PYBC_DELETE_NAME, qstr);
}

375
static void emit_bc_delete_global(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
376
377
378
379
    emit_pre(emit, 0);
    emit_write_byte_1_qstr(emit, PYBC_DELETE_GLOBAL, qstr);
}

380
static void emit_bc_delete_deref(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
381
382
383
384
    emit_pre(emit, 0);
    emit_write_byte_1_qstr(emit, PYBC_DELETE_DEREF, qstr);
}

385
static void emit_bc_delete_attr(emit_t *emit, qstr qstr) {
Damien's avatar
Damien committed
386
387
388
389
    emit_pre(emit, -1);
    emit_write_byte_1_qstr(emit, PYBC_DELETE_ATTR, qstr);
}

390
static void emit_bc_delete_subscr(emit_t *emit) {
Damien's avatar
Damien committed
391
392
393
394
    emit_pre(emit, -2);
    emit_write_byte_1(emit, PYBC_DELETE_SUBSCR);
}

395
static void emit_bc_dup_top(emit_t *emit) {
Damien's avatar
Damien committed
396
397
398
399
    emit_pre(emit, 1);
    emit_write_byte_1(emit, PYBC_DUP_TOP);
}

400
static void emit_bc_dup_top_two(emit_t *emit) {
Damien's avatar
Damien committed
401
402
403
404
    emit_pre(emit, 2);
    emit_write_byte_1(emit, PYBC_DUP_TOP_TWO);
}

405
static void emit_bc_pop_top(emit_t *emit) {
Damien's avatar
Damien committed
406
407
408
409
    emit_pre(emit, -1);
    emit_write_byte_1(emit, PYBC_POP_TOP);
}

410
static void emit_bc_rot_two(emit_t *emit) {
Damien's avatar
Damien committed
411
412
413
414
    emit_pre(emit, 0);
    emit_write_byte_1(emit, PYBC_ROT_TWO);
}

415
static void emit_bc_rot_three(emit_t *emit) {
Damien's avatar
Damien committed
416
417
418
419
    emit_pre(emit, 0);
    emit_write_byte_1(emit, PYBC_ROT_THREE);
}

420
static void emit_bc_jump(emit_t *emit, int label) {
Damien's avatar
Damien committed
421
422
423
424
    emit_pre(emit, 0);
    emit_write_byte_1_label(emit, PYBC_JUMP, label);
}

425
static void emit_bc_pop_jump_if_true(emit_t *emit, int label) {
Damien's avatar
Damien committed
426
427
428
429
    emit_pre(emit, -1);
    emit_write_byte_1_label(emit, PYBC_POP_JUMP_IF_TRUE, label);
}

430
static void emit_bc_pop_jump_if_false(emit_t *emit, int label) {
Damien's avatar
Damien committed
431
432
433
434
    emit_pre(emit, -1);
    emit_write_byte_1_label(emit, PYBC_POP_JUMP_IF_FALSE, label);
}

435
static void emit_bc_jump_if_true_or_pop(emit_t *emit, int label) {
Damien's avatar
Damien committed
436
437
438
439
    emit_pre(emit, -1);
    emit_write_byte_1_label(emit, PYBC_JUMP_IF_TRUE_OR_POP, label);
}

440
static void emit_bc_jump_if_false_or_pop(emit_t *emit, int label) {
Damien's avatar
Damien committed
441
442
443
444
    emit_pre(emit, -1);
    emit_write_byte_1_label(emit, PYBC_JUMP_IF_FALSE_OR_POP, label);
}

445
static void emit_bc_setup_loop(emit_t *emit, int label) {
Damien's avatar
Damien committed
446
447
448
449
    emit_pre(emit, 0);
    emit_write_byte_1_label(emit, PYBC_SETUP_LOOP, label);
}

450
static void emit_bc_break_loop(emit_t *emit, int label) {
Damien's avatar
Damien committed
451
452
453
454
    emit_pre(emit, 0);
    emit_write_byte_1_label(emit, PYBC_BREAK_LOOP, label);
}

455
static void emit_bc_continue_loop(emit_t *emit, int label) {
Damien's avatar
Damien committed
456
457
458
459
    emit_pre(emit, 0);
    emit_write_byte_1_label(emit, PYBC_CONTINUE_LOOP, label);
}

460
static void emit_bc_setup_with(emit_t *emit, int label) {
Damien's avatar
Damien committed
461
462
463
464
    emit_pre(emit, 7);
    emit_write_byte_1_label(emit, PYBC_SETUP_WITH, label);
}

465
static void emit_bc_with_cleanup(emit_t *emit) {
Damien's avatar
Damien committed
466
467
468
469
    emit_pre(emit, -7);
    emit_write_byte_1(emit, PYBC_WITH_CLEANUP);
}

470
static void emit_bc_setup_except(emit_t *emit, int label) {
Damien's avatar
Damien committed
471
472
473
474
    emit_pre(emit, 6);
    emit_write_byte_1_label(emit, PYBC_SETUP_EXCEPT, label);
}

475
static void emit_bc_setup_finally(emit_t *emit, int label) {
Damien's avatar
Damien committed
476
477
478
479
    emit_pre(emit, 6);
    emit_write_byte_1_label(emit, PYBC_SETUP_FINALLY, label);
}

480
static void emit_bc_end_finally(emit_t *emit) {
Damien's avatar
Damien committed
481
482
483
484
    emit_pre(emit, -1);
    emit_write_byte_1(emit, PYBC_END_FINALLY);
}

485
static void emit_bc_get_iter(emit_t *emit) {
Damien's avatar
Damien committed
486
487
488
489
    emit_pre(emit, 0);
    emit_write_byte_1(emit, PYBC_GET_ITER);
}

490
static void emit_bc_for_iter(emit_t *emit, int label) {
Damien's avatar
Damien committed
491
492
493
494
    emit_pre(emit, 1);
    emit_write_byte_1_label(emit, PYBC_FOR_ITER, label);
}

495
static void emit_bc_for_iter_end(emit_t *emit) {
Damien's avatar
Damien committed
496
497
498
    emit_pre(emit, -1);
}

499
static void emit_bc_pop_block(emit_t *emit) {
Damien's avatar
Damien committed
500
501
502
503
    emit_pre(emit, 0);
    emit_write_byte_1(emit, PYBC_POP_BLOCK);
}

504
static void emit_bc_pop_except(emit_t *emit) {
Damien's avatar
Damien committed
505
506
507
508
    emit_pre(emit, 0);
    emit_write_byte_1(emit, PYBC_POP_EXCEPT);
}

509
static void emit_bc_unary_op(emit_t *emit, rt_unary_op_t op) {
Damien's avatar
Damien committed
510
511
512
513
    emit_pre(emit, 0);
    emit_write_byte_1_byte(emit, PYBC_UNARY_OP, op);
}

514
static void emit_bc_binary_op(emit_t *emit, rt_binary_op_t op) {
Damien's avatar
Damien committed
515
516
517
518
    emit_pre(emit, -1);
    emit_write_byte_1_byte(emit, PYBC_BINARY_OP, op);
}

519
static void emit_bc_compare_op(emit_t *emit, rt_compare_op_t op) {
Damien's avatar
Damien committed
520
521
522
523
    emit_pre(emit, -1);
    emit_write_byte_1_byte(emit, PYBC_COMPARE_OP, op);
}

524
static void emit_bc_build_tuple(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
525
526
527
528
529
    assert(n_args >= 0);
    emit_pre(emit, 1 - n_args);
    emit_write_byte_1_uint(emit, PYBC_BUILD_TUPLE, n_args);
}

530
static void emit_bc_build_list(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
531
532
533
534
535
    assert(n_args >= 0);
    emit_pre(emit, 1 - n_args);
    emit_write_byte_1_uint(emit, PYBC_BUILD_LIST, n_args);
}

536
static void emit_bc_list_append(emit_t *emit, int list_stack_index) {
Damien's avatar
Damien committed
537
538
539
540
541
    assert(list_stack_index >= 0);
    emit_pre(emit, -1);
    emit_write_byte_1_uint(emit, PYBC_LIST_APPEND, list_stack_index);
}

542
static void emit_bc_build_map(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
543
544
545
546
547
    assert(n_args >= 0);
    emit_pre(emit, 1);
    emit_write_byte_1_uint(emit, PYBC_BUILD_MAP, n_args);
}

548
static void emit_bc_store_map(emit_t *emit) {
Damien's avatar
Damien committed
549
550
551
552
    emit_pre(emit, -2);
    emit_write_byte_1(emit, PYBC_STORE_MAP);
}

553
static void emit_bc_map_add(emit_t *emit, int map_stack_index) {
Damien's avatar
Damien committed
554
555
556
557
558
    assert(map_stack_index >= 0);
    emit_pre(emit, -2);
    emit_write_byte_1_uint(emit, PYBC_MAP_ADD, map_stack_index);
}

559
static void emit_bc_build_set(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
560
561
562
563
564
    assert(n_args >= 0);
    emit_pre(emit, 1 - n_args);
    emit_write_byte_1_uint(emit, PYBC_BUILD_SET, n_args);
}

565
static void emit_bc_set_add(emit_t *emit, int set_stack_index) {
Damien's avatar
Damien committed
566
567
568
569
570
    assert(set_stack_index >= 0);
    emit_pre(emit, -1);
    emit_write_byte_1_uint(emit, PYBC_SET_ADD, set_stack_index);
}

571
static void emit_bc_build_slice(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
572
573
574
575
576
    assert(n_args >= 0);
    emit_pre(emit, 1 - n_args);
    emit_write_byte_1_uint(emit, PYBC_BUILD_SLICE, n_args);
}

577
static void emit_bc_unpack_sequence(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
578
579
580
581
582
    assert(n_args >= 0);
    emit_pre(emit, -1 + n_args);
    emit_write_byte_1_uint(emit, PYBC_UNPACK_SEQUENCE, n_args);
}

583
static void emit_bc_unpack_ex(emit_t *emit, int n_left, int n_right) {
Damien's avatar
Damien committed
584
585
586
587
588
    assert(n_left >=0 && n_right >= 0);
    emit_pre(emit, -1 + n_left + n_right + 1);
    emit_write_byte_1_uint(emit, PYBC_UNPACK_EX, n_left | (n_right << 8));
}

589
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
590
591
592
593
594
    assert(n_default_params == 0 && n_dict_params == 0);
    emit_pre(emit, 1);
    emit_write_byte_1_uint(emit, PYBC_MAKE_FUNCTION, scope->unique_code_id);
}

595
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
596
597
598
599
600
601
602
    assert(0);
    emit_pre(emit, -2 - n_default_params - 2 * n_dict_params);
    if (emit->pass == PASS_3) {
        printf("MAKE_CLOSURE %d\n", (n_dict_params << 8) | n_default_params);
    }
}

603
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
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
    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) {
            op = PYBC_CALL_FUNCTION_VAR_KW;
        } else {
            op = PYBC_CALL_FUNCTION_VAR;
        }
    } else {
        if (have_dbl_star_arg) {
            op = PYBC_CALL_FUNCTION_KW;
        } else {
            op = PYBC_CALL_FUNCTION;
        }
    }
    emit_write_byte_1_uint(emit, op, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints
}

629
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
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
    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) {
            op = PYBC_CALL_METHOD_VAR_KW;
        } else {
            op = PYBC_CALL_METHOD_VAR;
        }
    } else {
        if (have_dbl_star_arg) {
            op = PYBC_CALL_METHOD_KW;
        } else {
            op = PYBC_CALL_METHOD;
        }
    }
    emit_write_byte_1_uint(emit, op, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints
}

655
static void emit_bc_return_value(emit_t *emit) {
Damien's avatar
Damien committed
656
657
658
659
660
    emit_pre(emit, -1);
    emit->last_emit_was_return_value = true;
    emit_write_byte_1(emit, PYBC_RETURN_VALUE);
}

661
static void emit_bc_raise_varargs(emit_t *emit, int n_args) {
Damien's avatar
Damien committed
662
663
664
665
666
    assert(n_args >= 0);
    emit_pre(emit, -n_args);
    emit_write_byte_1_uint(emit, PYBC_RAISE_VARARGS, n_args);
}

667
static void emit_bc_yield_value(emit_t *emit) {
Damien's avatar
Damien committed
668
669
670
671
672
673
674
    emit_pre(emit, 0);
    if (emit->pass == PASS_2) {
        emit->scope->flags |= SCOPE_FLAG_GENERATOR;
    }
    emit_write_byte_1(emit, PYBC_YIELD_VALUE);
}

675
static void emit_bc_yield_from(emit_t *emit) {
Damien's avatar
Damien committed
676
677
678
679
680
681
682
    emit_pre(emit, -1);
    if (emit->pass == PASS_2) {
        emit->scope->flags |= SCOPE_FLAG_GENERATOR;
    }
    emit_write_byte_1(emit, PYBC_YIELD_FROM);
}

683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
static const emit_method_table_t emit_bc_method_table = {
    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,

    emit_bc_label_new,
    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_start,
    emit_bc_load_const_verbatim_int,
    emit_bc_load_const_verbatim_str,
    emit_bc_load_const_verbatim_strn,
    emit_bc_load_const_verbatim_quoted_str,
    emit_bc_load_const_verbatim_end,
    emit_bc_load_fast,
    emit_bc_load_name,
    emit_bc_load_global,
    emit_bc_load_deref,
    emit_bc_load_closure,
    emit_bc_load_attr,
    emit_bc_load_method,
    emit_bc_load_build_class,
    emit_bc_store_fast,
    emit_bc_store_name,
    emit_bc_store_global,
    emit_bc_store_deref,
    emit_bc_store_attr,
    emit_bc_store_locals,
    emit_bc_store_subscr,
    emit_bc_delete_fast,
    emit_bc_delete_name,
    emit_bc_delete_global,
    emit_bc_delete_deref,
    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_compare_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,
};

void emit_new_bc(emit_t **emit_out, const emit_method_table_t **emit_method_table_out) {
    emit_t *emit = m_new(emit_t, 1);
    emit->max_num_labels = 0;
    emit->label_offsets = NULL;
    emit->code_offset = 0;
    emit->code_size = 0;
    emit->code_base = NULL;

    *emit_out = emit;
    *emit_method_table_out = &emit_bc_method_table;
}