Coverage Report

Created: 2023-09-25 06:17

/src/mruby/mrbgems/mruby-compiler/core/codegen.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
** codegen.c - mruby code generator
3
**
4
** See Copyright Notice in mruby.h
5
*/
6
7
#include <mruby.h>
8
#include <mruby/compile.h>
9
#include <mruby/proc.h>
10
#include <mruby/dump.h>
11
#include <mruby/numeric.h>
12
#include <mruby/string.h>
13
#include <mruby/debug.h>
14
#include <mruby/presym.h>
15
#include "node.h"
16
#include <mruby/opcode.h>
17
#include <mruby/re.h>
18
#include <mruby/throw.h>
19
#include <ctype.h>
20
#include <string.h>
21
#include <mruby/internal.h>
22
23
#ifndef MRB_CODEGEN_LEVEL_MAX
24
1.58M
#define MRB_CODEGEN_LEVEL_MAX 256
25
#endif
26
27
#define MAXARG_S (1<<16)
28
29
typedef mrb_ast_node node;
30
typedef struct mrb_parser_state parser_state;
31
32
enum looptype {
33
  LOOP_NORMAL,
34
  LOOP_BLOCK,
35
  LOOP_FOR,
36
  LOOP_BEGIN,
37
  LOOP_RESCUE,
38
};
39
40
struct loopinfo {
41
  enum looptype type;
42
  uint32_t pc0;                 /* `next` destination */
43
  uint32_t pc1;                 /* `redo` destination */
44
  uint32_t pc2;                 /* `break` destination */
45
  int reg;                      /* destination register */
46
  struct loopinfo *prev;
47
};
48
49
typedef struct scope {
50
  mrb_state *mrb;
51
  mrb_pool *mpool;
52
53
  struct scope *prev;
54
55
  node *lv;
56
57
  uint16_t sp;
58
  uint32_t pc;
59
  uint32_t lastpc;
60
  uint32_t lastlabel;
61
  uint16_t ainfo:15;
62
  mrb_bool mscope:1;
63
64
  struct loopinfo *loop;
65
  mrb_sym filename_sym;
66
  uint16_t lineno;
67
68
  mrb_code *iseq;
69
  uint16_t *lines;
70
  uint32_t icapa;
71
72
  mrb_irep *irep;
73
  mrb_pool_value *pool;
74
  mrb_sym *syms;
75
  mrb_irep **reps;
76
  struct mrb_irep_catch_handler *catch_table;
77
  uint32_t pcapa, scapa, rcapa;
78
79
  uint16_t nlocals;
80
  uint16_t nregs;
81
  int ai;
82
83
  int debug_start_pos;
84
  uint16_t filename_index;
85
  parser_state* parser;
86
87
  int rlev;                     /* recursion levels */
88
} codegen_scope;
89
90
static codegen_scope* scope_new(mrb_state *mrb, codegen_scope *prev, node *lv);
91
static void scope_finish(codegen_scope *s);
92
static struct loopinfo *loop_push(codegen_scope *s, enum looptype t);
93
static void loop_break(codegen_scope *s, node *tree);
94
static void loop_pop(codegen_scope *s, int val);
95
96
/*
97
 * The search for catch handlers starts at the end of the table in mrb_vm_run().
98
 * Therefore, the next handler to be added must meet one of the following conditions.
99
 * - Larger start position
100
 * - Same start position but smaller end position
101
 */
102
static int catch_handler_new(codegen_scope *s);
103
static void catch_handler_set(codegen_scope *s, int ent, enum mrb_catch_type type, uint32_t begin, uint32_t end, uint32_t target);
104
105
static void gen_assignment(codegen_scope *s, node *tree, node *rhs, int sp, int val);
106
static void gen_massignment(codegen_scope *s, node *tree, int sp, int val);
107
108
static void codegen(codegen_scope *s, node *tree, int val);
109
static void raise_error(codegen_scope *s, const char *msg);
110
111
static void
112
codegen_error(codegen_scope *s, const char *message)
113
72
{
114
72
  if (!s) return;
115
72
#ifndef MRB_NO_STDIO
116
72
  if (s->filename_sym && s->lineno) {
117
0
    const char *filename = mrb_sym_name_len(s->mrb, s->filename_sym, NULL);
118
0
    fprintf(stderr, "%s:%d: %s\n", filename, s->lineno, message);
119
0
  }
120
72
  else {
121
72
    fprintf(stderr, "%s\n", message);
122
72
  }
123
72
#endif
124
216
  while (s->prev) {
125
144
    codegen_scope *tmp = s->prev;
126
144
    if (s->irep) {
127
144
      mrb_free(s->mrb, s->iseq);
128
675
      for (int i=0; i<s->irep->plen; i++) {
129
531
        mrb_pool_value *pv = &s->pool[i];
130
531
        if ((pv->tt & 0x3) == IREP_TT_STR || pv->tt == IREP_TT_BIGINT) {
131
465
          mrb_free(s->mrb, (void*)pv->u.str);
132
465
        }
133
531
      }
134
144
      mrb_free(s->mrb, s->pool);
135
144
      mrb_free(s->mrb, s->syms);
136
144
      mrb_free(s->mrb, s->catch_table);
137
144
      if (s->reps) {
138
        /* copied from mrb_irep_free() in state.c */
139
216
        for (int i=0; i<s->irep->rlen; i++) {
140
72
          if (s->reps[i])
141
72
            mrb_irep_decref(s->mrb, (mrb_irep*)s->reps[i]);
142
72
        }
143
144
        mrb_free(s->mrb, s->reps);
144
144
      }
145
144
      mrb_free(s->mrb, s->lines);
146
144
    }
147
144
    mrb_pool_close(s->mpool);
148
144
    s = tmp;
149
144
  }
150
72
  MRB_THROW(s->mrb->jmp);
151
0
}
152
153
static void*
154
codegen_palloc(codegen_scope *s, size_t len)
155
0
{
156
0
  void *p = mrb_pool_alloc(s->mpool, len);
157
158
0
  if (!p) codegen_error(s, "pool memory allocation");
159
0
  return p;
160
0
}
161
162
static void*
163
codegen_realloc(codegen_scope *s, void *p, size_t len)
164
7.65k
{
165
7.65k
  p = mrb_realloc_simple(s->mrb, p, len);
166
167
7.65k
  if (!p && len > 0) codegen_error(s, "mrb_realloc");
168
7.65k
  return p;
169
7.65k
}
170
171
static void
172
check_no_ext_ops(codegen_scope *s, uint16_t a, uint16_t b)
173
1.48M
{
174
1.48M
  if (s->parser->no_ext_ops && (a | b) > 0xff) {
175
0
    codegen_error(s, "need OP_EXTs instruction (currently OP_EXTs are prohibited)");
176
0
  }
177
1.48M
}
178
179
static int
180
new_label(codegen_scope *s)
181
466
{
182
466
  return s->lastlabel = s->pc;
183
466
}
184
185
static void
186
emit_B(codegen_scope *s, uint32_t pc, uint8_t i)
187
5.14M
{
188
5.14M
  if (pc >= s->icapa) {
189
1.24k
    if (pc == UINT32_MAX) {
190
0
      codegen_error(s, "too big code block");
191
0
    }
192
1.24k
    if (pc >= UINT32_MAX / 2) {
193
0
      pc = UINT32_MAX;
194
0
    }
195
1.24k
    else {
196
1.24k
      s->icapa *= 2;
197
1.24k
    }
198
1.24k
    s->iseq = (mrb_code*)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa);
199
1.24k
    if (s->lines) {
200
0
      s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->icapa);
201
0
    }
202
1.24k
  }
203
5.14M
  if (s->lines) {
204
0
    if (s->lineno > 0 || pc == 0)
205
0
      s->lines[pc] = s->lineno;
206
0
    else
207
0
      s->lines[pc] = s->lines[pc-1];
208
0
  }
209
5.14M
  s->iseq[pc] = i;
210
5.14M
}
211
212
static void
213
emit_S(codegen_scope *s, int pc, uint16_t i)
214
631k
{
215
631k
  uint8_t hi = i>>8;
216
631k
  uint8_t lo = i&0xff;
217
218
631k
  emit_B(s, pc,   hi);
219
631k
  emit_B(s, pc+1, lo);
220
631k
}
221
222
static void
223
gen_B(codegen_scope *s, uint8_t i)
224
3.88M
{
225
3.88M
  emit_B(s, s->pc, i);
226
3.88M
  s->pc++;
227
3.88M
}
228
229
static void
230
gen_S(codegen_scope *s, uint16_t i)
231
580k
{
232
580k
  emit_S(s, s->pc, i);
233
580k
  s->pc += 2;
234
580k
}
235
236
static void
237
genop_0(codegen_scope *s, mrb_code i)
238
50.9k
{
239
50.9k
  s->lastpc = s->pc;
240
50.9k
  gen_B(s, i);
241
50.9k
}
242
243
static void
244
genop_1(codegen_scope *s, mrb_code i, uint16_t a)
245
736k
{
246
736k
  s->lastpc = s->pc;
247
736k
  check_no_ext_ops(s, a, 0);
248
736k
  if (a > 0xff) {
249
291k
    gen_B(s, OP_EXT1);
250
291k
    gen_B(s, i);
251
291k
    gen_S(s, a);
252
291k
  }
253
444k
  else {
254
444k
    gen_B(s, i);
255
444k
    gen_B(s, (uint8_t)a);
256
444k
  }
257
736k
}
258
259
static void
260
genop_2(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b)
261
746k
{
262
746k
  s->lastpc = s->pc;
263
746k
  check_no_ext_ops(s, a, b);
264
746k
  if (a > 0xff && b > 0xff) {
265
2.86k
    gen_B(s, OP_EXT3);
266
2.86k
    gen_B(s, i);
267
2.86k
    gen_S(s, a);
268
2.86k
    gen_S(s, b);
269
2.86k
  }
270
743k
  else if (b > 0xff) {
271
1.34k
    gen_B(s, OP_EXT2);
272
1.34k
    gen_B(s, i);
273
1.34k
    gen_B(s, (uint8_t)a);
274
1.34k
    gen_S(s, b);
275
1.34k
  }
276
742k
  else if (a > 0xff) {
277
224k
    gen_B(s, OP_EXT1);
278
224k
    gen_B(s, i);
279
224k
    gen_S(s, a);
280
224k
    gen_B(s, (uint8_t)b);
281
224k
  }
282
517k
  else {
283
517k
    gen_B(s, i);
284
517k
    gen_B(s, (uint8_t)a);
285
517k
    gen_B(s, (uint8_t)b);
286
517k
  }
287
746k
}
288
289
static void
290
genop_3(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b, uint16_t c)
291
82.9k
{
292
82.9k
  genop_2(s, i, a, b);
293
82.9k
  gen_B(s, (uint8_t)c);
294
82.9k
}
295
296
static void
297
genop_2S(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b)
298
1.30k
{
299
1.30k
  genop_1(s, i, a);
300
1.30k
  gen_S(s, b);
301
1.30k
}
302
303
static void
304
genop_2SS(codegen_scope *s, mrb_code i, uint16_t a, uint32_t b)
305
1.12k
{
306
1.12k
  genop_1(s, i, a);
307
1.12k
  gen_S(s, b>>16);
308
1.12k
  gen_S(s, b&0xffff);
309
1.12k
}
310
311
static void
312
genop_W(codegen_scope *s, mrb_code i, uint32_t a)
313
466
{
314
466
  uint8_t a1 = (a>>16) & 0xff;
315
466
  uint8_t a2 = (a>>8) & 0xff;
316
466
  uint8_t a3 = a & 0xff;
317
318
466
  s->lastpc = s->pc;
319
466
  gen_B(s, i);
320
466
  gen_B(s, a1);
321
466
  gen_B(s, a2);
322
466
  gen_B(s, a3);
323
466
}
324
325
225k
#define NOVAL  0
326
484k
#define VAL    1
327
328
static mrb_bool
329
no_optimize(codegen_scope *s)
330
472k
{
331
472k
  if (s && s->parser && s->parser->no_optimize)
332
0
    return TRUE;
333
472k
  return FALSE;
334
472k
}
335
336
struct mrb_insn_data
337
mrb_decode_insn(const mrb_code *pc)
338
390k
{
339
390k
  struct mrb_insn_data data = { 0 };
340
390k
  if (pc == 0) return data;
341
390k
  data.addr = pc;
342
390k
  mrb_code insn = READ_B();
343
390k
  uint16_t a = 0;
344
390k
  uint16_t b = 0;
345
390k
  uint16_t c = 0;
346
347
390k
  switch (insn) {
348
0
#define FETCH_Z() /* empty */
349
390k
#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x (); break;
350
390k
#include "mruby/ops.h"
351
390k
#undef OPCODE
352
390k
  }
353
390k
  switch (insn) {
354
118k
  case OP_EXT1:
355
118k
    insn = READ_B();
356
118k
    switch (insn) {
357
118k
#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _1 (); break;
358
118k
#include "mruby/ops.h"
359
118k
#undef OPCODE
360
118k
    }
361
118k
    break;
362
118k
  case OP_EXT2:
363
471
    insn = READ_B();
364
471
    switch (insn) {
365
471
#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _2 (); break;
366
471
#include "mruby/ops.h"
367
471
#undef OPCODE
368
471
    }
369
471
    break;
370
1.45k
  case OP_EXT3:
371
1.45k
    insn = READ_B();
372
1.45k
    switch (insn) {
373
1.45k
#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _3 (); break;
374
1.45k
#include "mruby/ops.h"
375
1.45k
#undef OPCODE
376
1.45k
    }
377
1.45k
    break;
378
269k
  default:
379
269k
    break;
380
390k
  }
381
390k
  data.insn = insn;
382
390k
  data.a = a;
383
390k
  data.b = b;
384
390k
  data.c = c;
385
390k
  return data;
386
390k
}
387
388
#undef OPCODE
389
#define Z 1
390
#define S 3
391
#define W 4
392
#define OPCODE(_,x) x,
393
/* instruction sizes */
394
static uint8_t mrb_insn_size[] = {
395
#define B 2
396
#define BB 3
397
#define BBB 4
398
#define BS 4
399
#define BSS 6
400
#include "mruby/ops.h"
401
#undef B
402
#undef BB
403
#undef BBB
404
#undef BS
405
#undef BSS
406
};
407
/* EXT1 instruction sizes */
408
static uint8_t mrb_insn_size1[] = {
409
#define B 3
410
#define BB 4
411
#define BBB 5
412
#define BS 5
413
#define BSS 7
414
#include "mruby/ops.h"
415
#undef B
416
#undef BS
417
#undef BSS
418
};
419
/* EXT2 instruction sizes */
420
static uint8_t mrb_insn_size2[] = {
421
#define B 2
422
#define BS 4
423
#define BSS 6
424
#include "mruby/ops.h"
425
#undef B
426
#undef BB
427
#undef BBB
428
#undef BS
429
#undef BSS
430
};
431
/* EXT3 instruction sizes */
432
#define B 3
433
#define BB 5
434
#define BBB 6
435
#define BS 5
436
#define BSS 7
437
static uint8_t mrb_insn_size3[] = {
438
#include "mruby/ops.h"
439
};
440
#undef B
441
#undef BB
442
#undef BBB
443
#undef BS
444
#undef BSS
445
#undef OPCODE
446
447
static const mrb_code*
448
mrb_prev_pc(codegen_scope *s, const mrb_code *pc)
449
98.9k
{
450
98.9k
  const mrb_code *prev_pc = NULL;
451
98.9k
  const mrb_code *i = s->iseq;
452
453
172M
  while (i<pc) {
454
171M
    uint8_t insn = i[0];
455
171M
    prev_pc = i;
456
171M
    switch (insn) {
457
17.9M
    case OP_EXT1:
458
17.9M
      i += mrb_insn_size1[i[1]] + 1;
459
17.9M
      break;
460
210k
    case OP_EXT2:
461
210k
      i += mrb_insn_size2[i[1]] + 1;
462
210k
      break;
463
216k
    case OP_EXT3:
464
216k
      i += mrb_insn_size3[i[1]] + 1;
465
216k
      break;
466
153M
    default:
467
153M
      i += mrb_insn_size[insn];
468
153M
      break;
469
171M
    }
470
171M
  }
471
98.9k
  return prev_pc;
472
98.9k
}
473
474
#define pc_addr(s) &((s)->iseq[(s)->pc])
475
159k
#define addr_pc(s, addr) (uint32_t)((addr) - s->iseq)
476
115k
#define rewind_pc(s) s->pc = s->lastpc
477
478
static struct mrb_insn_data
479
mrb_last_insn(codegen_scope *s)
480
295k
{
481
295k
  if (s->pc == 0) {
482
0
    struct mrb_insn_data data = { OP_NOP, 0 };
483
0
    return data;
484
0
  }
485
295k
  return mrb_decode_insn(&s->iseq[s->lastpc]);
486
295k
}
487
488
static mrb_bool
489
no_peephole(codegen_scope *s)
490
317k
{
491
317k
  return no_optimize(s) || s->lastlabel == s->pc || s->pc == 0 || s->pc == s->lastpc;
492
317k
}
493
494
161k
#define JMPLINK_START UINT32_MAX
495
496
static void
497
gen_jmpdst(codegen_scope *s, uint32_t pc)
498
50.5k
{
499
500
50.5k
  if (pc == JMPLINK_START) {
501
50.5k
    pc = 0;
502
50.5k
  }
503
50.5k
  uint32_t pos2 = s->pc+2;
504
50.5k
  int32_t off = pc - pos2;
505
506
50.5k
  if (off > INT16_MAX || INT16_MIN > off) {
507
9
    codegen_error(s, "too big jump offset");
508
9
  }
509
50.5k
  gen_S(s, (uint16_t)off);
510
50.5k
}
511
512
static uint32_t
513
genjmp(codegen_scope *s, mrb_code i, uint32_t pc)
514
14.9k
{
515
14.9k
  uint32_t pos;
516
517
14.9k
  genop_0(s, i);
518
14.9k
  pos = s->pc;
519
14.9k
  gen_jmpdst(s, pc);
520
14.9k
  return pos;
521
14.9k
}
522
523
14.3k
#define genjmp_0(s,i) genjmp(s,i,JMPLINK_START)
524
525
static uint32_t
526
genjmp2(codegen_scope *s, mrb_code i, uint16_t a, uint32_t pc, int val)
527
39.4k
{
528
39.4k
  uint32_t pos;
529
530
39.4k
  if (!no_peephole(s) && !val) {
531
24.7k
    struct mrb_insn_data data = mrb_last_insn(s);
532
533
24.7k
    switch (data.insn) {
534
1.59k
    case OP_MOVE:
535
1.59k
      if (data.a == a && data.a > s->nlocals) {
536
0
        rewind_pc(s);
537
0
        a = data.b;
538
0
      }
539
1.59k
      break;
540
0
    case OP_LOADNIL:
541
0
    case OP_LOADF:
542
0
      if (data.a == a || data.a > s->nlocals) {
543
0
        s->pc = addr_pc(s, data.addr);
544
0
        if (i == OP_JMPNOT || (i == OP_JMPNIL && data.insn == OP_LOADNIL)) {
545
0
          return genjmp(s, OP_JMP, pc);
546
0
        }
547
0
        else {                  /* OP_JMPIF */
548
0
          return JMPLINK_START;
549
0
        }
550
0
      }
551
0
      break;
552
857
    case OP_LOADT: case OP_LOADI: case OP_LOADINEG: case OP_LOADI__1:
553
2.66k
    case OP_LOADI_0: case OP_LOADI_1: case OP_LOADI_2: case OP_LOADI_3:
554
3.87k
    case OP_LOADI_4: case OP_LOADI_5: case OP_LOADI_6: case OP_LOADI_7:
555
3.87k
      if (data.a == a || data.a > s->nlocals) {
556
3.87k
        s->pc = addr_pc(s, data.addr);
557
3.87k
        if (i == OP_JMPIF) {
558
605
          return genjmp(s, OP_JMP, pc);
559
605
        }
560
3.27k
        else {                  /* OP_JMPNOT and OP_JMPNIL */
561
3.27k
          return JMPLINK_START;
562
3.27k
        }
563
3.87k
      }
564
0
      break;
565
24.7k
    }
566
24.7k
  }
567
568
35.5k
  if (a > 0xff) {
569
2.88k
    check_no_ext_ops(s, a, 0);
570
2.88k
    gen_B(s, OP_EXT1);
571
2.88k
    genop_0(s, i);
572
2.88k
    gen_S(s, a);
573
2.88k
  }
574
32.7k
  else {
575
32.7k
    genop_0(s, i);
576
32.7k
    gen_B(s, (uint8_t)a);
577
32.7k
  }
578
35.5k
  pos = s->pc;
579
35.5k
  gen_jmpdst(s, pc);
580
35.5k
  return pos;
581
39.4k
}
582
583
40.2k
#define genjmp2_0(s,i,a,val) genjmp2(s,i,a,JMPLINK_START,val)
584
585
static mrb_bool get_int_operand(codegen_scope *s, struct mrb_insn_data *data, mrb_int *ns);
586
static void gen_int(codegen_scope *s, uint16_t dst, mrb_int i);
587
588
static void
589
gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
590
180k
{
591
180k
  if (nopeep || no_peephole(s)) goto normal;
592
119k
  else if (dst == src) return;
593
119k
  else {
594
119k
    struct mrb_insn_data data = mrb_last_insn(s);
595
596
119k
    switch (data.insn) {
597
4.97k
    case OP_MOVE:
598
4.97k
      if (dst == src) return;   /* remove useless MOVE */
599
4.97k
      if (data.a == src) {
600
4.50k
        if (data.b == dst)      /* skip swapping MOVE */
601
0
          return;
602
4.50k
        if (data.a < s->nlocals) goto normal;
603
4.49k
        rewind_pc(s);
604
4.49k
        s->lastpc = addr_pc(s, mrb_prev_pc(s, data.addr));
605
4.49k
        gen_move(s, dst, data.b, FALSE);
606
4.49k
        return;
607
4.50k
      }
608
470
      if (dst == data.a) {      /* skip overwritten move */
609
0
        rewind_pc(s);
610
0
        s->lastpc = addr_pc(s, mrb_prev_pc(s, data.addr));
611
0
        gen_move(s, dst, src, FALSE);
612
0
        return;
613
0
      }
614
470
      goto normal;
615
470
    case OP_LOADNIL: case OP_LOADSELF: case OP_LOADT: case OP_LOADF:
616
110
    case OP_LOADI__1:
617
105k
    case OP_LOADI_0: case OP_LOADI_1: case OP_LOADI_2: case OP_LOADI_3:
618
106k
    case OP_LOADI_4: case OP_LOADI_5: case OP_LOADI_6: case OP_LOADI_7:
619
106k
      if (data.a != src || data.a < s->nlocals) goto normal;
620
104k
      rewind_pc(s);
621
104k
      genop_1(s, data.insn, dst);
622
104k
      return;
623
0
    case OP_HASH:
624
0
      if (data.b != 0) goto normal;
625
      /* fall through */
626
919
    case OP_LOADI: case OP_LOADINEG:
627
1.07k
    case OP_LOADL: case OP_LOADSYM:
628
1.07k
    case OP_GETGV: case OP_GETSV: case OP_GETIV: case OP_GETCV:
629
1.07k
    case OP_GETCONST: case OP_STRING:
630
1.07k
    case OP_LAMBDA: case OP_BLOCK: case OP_METHOD: case OP_BLKPUSH:
631
1.07k
      if (data.a != src || data.a < s->nlocals) goto normal;
632
1.04k
      rewind_pc(s);
633
1.04k
      genop_2(s, data.insn, dst, data.b);
634
1.04k
      return;
635
260
    case OP_LOADI16:
636
260
      if (data.a != src || data.a < s->nlocals) goto normal;
637
176
      rewind_pc(s);
638
176
      genop_2S(s, data.insn, dst, data.b);
639
176
      return;
640
274
    case OP_LOADI32:
641
274
      if (data.a != src || data.a < s->nlocals) goto normal;
642
196
      else {
643
196
        uint32_t i = (uint32_t)data.b<<16|data.c;
644
196
        rewind_pc(s);
645
196
        genop_2SS(s, data.insn, dst, i);
646
196
      }
647
196
      return;
648
196
    case OP_ARRAY:
649
0
      if (data.a != src || data.a < s->nlocals || data.a < dst) goto normal;
650
0
      rewind_pc(s);
651
0
      if (data.b == 0 || dst == data.a)
652
0
        genop_2(s, OP_ARRAY, dst, 0);
653
0
      else
654
0
        genop_3(s, OP_ARRAY2, dst, data.a, data.b);
655
0
      return;
656
0
    case OP_ARRAY2:
657
0
      if (data.a != src || data.a < s->nlocals || data.a < dst) goto normal;
658
0
      rewind_pc(s);
659
0
      genop_3(s, OP_ARRAY2, dst, data.b, data.c);
660
0
      return;
661
0
    case OP_AREF:
662
0
    case OP_GETUPVAR:
663
0
      if (data.a != src || data.a < s->nlocals) goto normal;
664
0
      rewind_pc(s);
665
0
      genop_3(s, data.insn, dst, data.b, data.c);
666
0
      return;
667
865
    case OP_ADDI: case OP_SUBI:
668
865
      if (addr_pc(s, data.addr) == s->lastlabel || data.a != src || data.a < s->nlocals) goto normal;
669
849
      else {
670
849
        struct mrb_insn_data data0 = mrb_decode_insn(mrb_prev_pc(s, data.addr));
671
849
        if (data0.insn != OP_MOVE || data0.a != data.a || data0.b != dst) goto normal;
672
0
        s->pc = addr_pc(s, data0.addr);
673
0
        if (addr_pc(s, data0.addr) != s->lastlabel) {
674
          /* constant folding */
675
0
          data0 = mrb_decode_insn(mrb_prev_pc(s, data0.addr));
676
0
          mrb_int n;
677
0
          if (data0.a == dst && get_int_operand(s, &data0, &n)) {
678
0
            if ((data.insn == OP_ADDI && !mrb_int_add_overflow(n, data.b, &n)) ||
679
0
                (data.insn == OP_SUBI && !mrb_int_sub_overflow(n, data.b, &n))) {
680
0
              s->pc = addr_pc(s, data0.addr);
681
0
              gen_int(s, dst, n);
682
0
              return;
683
0
            }
684
0
          }
685
0
        }
686
0
      }
687
0
      genop_2(s, data.insn, dst, data.b);
688
0
      return;
689
5.36k
    default:
690
5.36k
      break;
691
119k
    }
692
119k
  }
693
69.9k
 normal:
694
69.9k
  genop_2(s, OP_MOVE, dst, src);
695
69.9k
  return;
696
180k
}
697
698
static int search_upvar(codegen_scope *s, mrb_sym id, int *idx);
699
700
static void
701
gen_getupvar(codegen_scope *s, uint16_t dst, mrb_sym id)
702
0
{
703
0
  int idx;
704
0
  int lv = search_upvar(s, id, &idx);
705
706
0
  if (!no_peephole(s)) {
707
0
    struct mrb_insn_data data = mrb_last_insn(s);
708
0
    if (data.insn == OP_SETUPVAR && data.a == dst && data.b == idx && data.c == lv) {
709
      /* skip GETUPVAR right after SETUPVAR */
710
0
      return;
711
0
    }
712
0
  }
713
0
  genop_3(s, OP_GETUPVAR, dst, idx, lv);
714
0
}
715
716
static void
717
gen_setupvar(codegen_scope *s, uint16_t dst, mrb_sym id)
718
0
{
719
0
  int idx;
720
0
  int lv = search_upvar(s, id, &idx);
721
722
0
  if (!no_peephole(s)) {
723
0
    struct mrb_insn_data data = mrb_last_insn(s);
724
0
    if (data.insn == OP_MOVE && data.a == dst) {
725
0
      dst = data.b;
726
0
      rewind_pc(s);
727
0
    }
728
0
  }
729
0
  genop_3(s, OP_SETUPVAR, dst, idx, lv);
730
0
}
731
732
static void
733
gen_return(codegen_scope *s, uint8_t op, uint16_t src)
734
845
{
735
845
  if (no_peephole(s)) {
736
451
    genop_1(s, op, src);
737
451
  }
738
394
  else {
739
394
    struct mrb_insn_data data = mrb_last_insn(s);
740
741
394
    if (data.insn == OP_MOVE && src == data.a) {
742
0
      rewind_pc(s);
743
0
      genop_1(s, op, data.b);
744
0
    }
745
394
    else if (data.insn != OP_RETURN) {
746
394
      genop_1(s, op, src);
747
394
    }
748
394
  }
749
845
}
750
751
static mrb_bool
752
get_int_operand(codegen_scope *s, struct mrb_insn_data *data, mrb_int *n)
753
233k
{
754
233k
  switch (data->insn) {
755
1.52k
  case OP_LOADI__1:
756
1.52k
    *n = -1;
757
1.52k
    return TRUE;
758
759
5.57k
  case OP_LOADINEG:
760
5.57k
    *n = -data->b;
761
5.57k
    return TRUE;
762
763
94.3k
  case OP_LOADI_0: case OP_LOADI_1: case OP_LOADI_2: case OP_LOADI_3:
764
101k
  case OP_LOADI_4: case OP_LOADI_5: case OP_LOADI_6: case OP_LOADI_7:
765
101k
    *n = data->insn - OP_LOADI_0;
766
101k
    return TRUE;
767
768
10.3k
  case OP_LOADI:
769
11.1k
  case OP_LOADI16:
770
11.1k
    *n = (int16_t)data->b;
771
11.1k
    return TRUE;
772
773
699
  case OP_LOADI32:
774
699
    *n = (int32_t)((uint32_t)data->b<<16)+data->c;
775
699
    return TRUE;
776
777
1.59k
  case OP_LOADL:
778
1.59k
    {
779
1.59k
      mrb_pool_value *pv = &s->pool[data->b];
780
781
1.59k
      if (pv->tt == IREP_TT_INT32) {
782
0
        *n = (mrb_int)pv->u.i32;
783
0
      }
784
1.59k
#ifdef MRB_INT64
785
1.59k
      else if (pv->tt == IREP_TT_INT64) {
786
1.59k
        *n = (mrb_int)pv->u.i64;
787
1.59k
      }
788
0
#endif
789
0
      else {
790
0
        return FALSE;
791
0
      }
792
1.59k
    }
793
1.59k
    return TRUE;
794
795
110k
  default:
796
110k
    return FALSE;
797
233k
  }
798
233k
}
799
800
static void
801
gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst)
802
32.8k
{
803
32.8k
  if (no_peephole(s)) {
804
14.0k
  normal:
805
14.0k
    genop_1(s, op, dst);
806
14.0k
    return;
807
193
  }
808
32.6k
  else {
809
32.6k
    struct mrb_insn_data data = mrb_last_insn(s);
810
32.6k
    mrb_int n;
811
812
32.6k
    if (!get_int_operand(s, &data, &n)) {
813
      /* not integer immediate */
814
13.4k
      goto normal;
815
13.4k
    }
816
19.1k
    struct mrb_insn_data data0 = mrb_decode_insn(mrb_prev_pc(s, data.addr));
817
19.1k
    mrb_int n0;
818
19.1k
    if (addr_pc(s, data.addr) == s->lastlabel || !get_int_operand(s, &data0, &n0)) {
819
      /* OP_ADDI/OP_SUBI takes upto 8bits */
820
5.08k
      if (n > INT8_MAX || n < INT8_MIN) goto normal;
821
4.67k
      rewind_pc(s);
822
4.67k
      if (n == 0) return;
823
4.33k
      if (n > 0) {
824
4.15k
        if (op == OP_ADD) genop_2(s, OP_ADDI, dst, (uint16_t)n);
825
2.31k
        else genop_2(s, OP_SUBI, dst, (uint16_t)n);
826
4.15k
      }
827
174
      else {                    /* n < 0 */
828
174
        n = -n;
829
174
        if (op == OP_ADD) genop_2(s, OP_SUBI, dst, (uint16_t)n);
830
28
        else genop_2(s, OP_ADDI, dst, (uint16_t)n);
831
174
      }
832
4.33k
      return;
833
4.67k
    }
834
14.1k
    if (op == OP_ADD) {
835
4.31k
      if (mrb_int_add_overflow(n0, n, &n)) goto normal;
836
4.31k
    }
837
9.79k
    else { /* OP_SUB */
838
9.79k
      if (mrb_int_sub_overflow(n0, n, &n)) goto normal;
839
9.79k
    }
840
14.0k
    s->pc = addr_pc(s, data0.addr);
841
14.0k
    gen_int(s, dst, n);
842
14.0k
  }
843
32.8k
}
844
845
static void
846
gen_muldiv(codegen_scope *s, uint8_t op, uint16_t dst)
847
20.6k
{
848
20.6k
  if (no_peephole(s)) {
849
14.8k
  normal:
850
14.8k
    genop_1(s, op, dst);
851
14.8k
    return;
852
972
  }
853
19.6k
  else {
854
19.6k
    struct mrb_insn_data data = mrb_last_insn(s);
855
19.6k
    mrb_int n, n0;
856
19.6k
    if (addr_pc(s, data.addr) == s->lastlabel || !get_int_operand(s, &data, &n)) {
857
      /* not integer immediate */
858
11.5k
      goto normal;
859
11.5k
    }
860
8.10k
    struct mrb_insn_data data0 = mrb_decode_insn(mrb_prev_pc(s, data.addr));
861
8.10k
    if (!get_int_operand(s, &data0, &n0)) {
862
2.13k
      goto normal;
863
2.13k
    }
864
5.97k
    if (op == OP_MUL) {
865
3.15k
      if (mrb_int_mul_overflow(n0, n, &n)) goto normal;
866
3.15k
    }
867
2.82k
    else { /* OP_DIV */
868
2.82k
      if (n == 0) goto normal;
869
2.65k
      if (n0 == MRB_INT_MIN && n == -1) goto normal;
870
2.60k
      n = mrb_div_int(n0, n);
871
2.60k
    }
872
5.75k
    s->pc = addr_pc(s, data0.addr);
873
5.75k
    gen_int(s, dst, n);
874
5.75k
  }
875
20.6k
}
876
877
mrb_bool mrb_num_shift(mrb_state *mrb, mrb_int val, mrb_int width, mrb_int *num);
878
879
static mrb_bool
880
gen_binop(codegen_scope *s, mrb_sym op, uint16_t dst)
881
84.1k
{
882
84.1k
  if (no_peephole(s)) return FALSE;
883
84.0k
  else if (op == MRB_OPSYM_2(s->mrb, aref)) {
884
0
    genop_1(s, OP_GETIDX, dst);
885
0
    return TRUE;
886
0
  }
887
84.0k
  else {
888
84.0k
    struct mrb_insn_data data = mrb_last_insn(s);
889
84.0k
    mrb_int n, n0;
890
84.0k
    if (addr_pc(s, data.addr) == s->lastlabel || !get_int_operand(s, &data, &n)) {
891
      /* not integer immediate */
892
17.7k
      return FALSE;
893
17.7k
    }
894
66.3k
    struct mrb_insn_data data0 = mrb_decode_insn(mrb_prev_pc(s, data.addr));
895
66.3k
    if (!get_int_operand(s, &data0, &n0)) {
896
57.6k
      return FALSE;
897
57.6k
    }
898
8.65k
    if (op == MRB_OPSYM_2(s->mrb, lshift)) {
899
0
      if (!mrb_num_shift(s->mrb, n0, n, &n)) return FALSE;
900
0
    }
901
8.65k
    else if (op == MRB_OPSYM_2(s->mrb, rshift)) {
902
6.23k
      if (n == MRB_INT_MIN) return FALSE;
903
5.94k
      if (!mrb_num_shift(s->mrb, n0, -n, &n)) return FALSE;
904
5.94k
    }
905
2.41k
    else if (op == MRB_OPSYM_2(s->mrb, mod) && n != 0) {
906
687
      if (n0 == MRB_INT_MIN && n == -1) {
907
1
        n = 0;
908
1
      }
909
686
      else {
910
686
        mrb_int n1 = n0 % n;
911
686
        if ((n0 < 0) != (n < 0) && n1 != 0) {
912
310
          n1 += n;
913
310
        }
914
686
        n = n1;
915
686
      }
916
687
    }
917
1.73k
    else if (op == MRB_OPSYM_2(s->mrb, and)) {
918
0
      n = n0 & n;
919
0
    }
920
1.73k
    else if (op == MRB_OPSYM_2(s->mrb, or)) {
921
0
      n = n0 | n;
922
0
    }
923
1.73k
    else if (op == MRB_OPSYM_2(s->mrb, xor)) {
924
1.21k
      n = n0 ^ n;
925
1.21k
    }
926
514
    else {
927
514
      return FALSE;
928
514
    }
929
7.47k
    s->pc = addr_pc(s, data0.addr);
930
7.47k
    gen_int(s, dst, n);
931
7.47k
    return TRUE;
932
8.65k
  }
933
84.1k
}
934
935
static uint32_t
936
dispatch(codegen_scope *s, uint32_t pos0)
937
53.7k
{
938
53.7k
  int32_t pos1;
939
53.7k
  int32_t offset;
940
53.7k
  int16_t newpos;
941
942
53.7k
  if (pos0 == JMPLINK_START) return 0;
943
944
50.5k
  pos1 = pos0 + 2;
945
50.5k
  offset = s->pc - pos1;
946
50.5k
  if (offset > INT16_MAX) {
947
6
    codegen_error(s, "too big jmp offset");
948
6
  }
949
50.5k
  s->lastlabel = s->pc;
950
50.5k
  newpos = (int16_t)PEEK_S(s->iseq+pos0);
951
50.5k
  emit_S(s, pos0, (uint16_t)offset);
952
50.5k
  if (newpos == 0) return 0;
953
50.5k
  return pos1+newpos;
954
50.5k
}
955
956
static void
957
dispatch_linked(codegen_scope *s, uint32_t pos)
958
0
{
959
0
  if (pos==JMPLINK_START) return;
960
0
  for (;;) {
961
0
    pos = dispatch(s, pos);
962
0
    if (pos==0) break;
963
0
  }
964
0
}
965
966
1.44M
#define nregs_update do {if (s->sp > s->nregs) s->nregs = s->sp;} while (0)
967
static void
968
push_n_(codegen_scope *s, int n)
969
1.44M
{
970
1.44M
  if (s->sp+n >= 0xffff) {
971
0
    codegen_error(s, "too complex expression");
972
0
  }
973
1.44M
  s->sp+=n;
974
1.44M
  nregs_update;
975
1.44M
}
976
977
static void
978
pop_n_(codegen_scope *s, int n)
979
645k
{
980
645k
  if ((int)s->sp-n < 0) {
981
0
    codegen_error(s, "stack pointer underflow");
982
0
  }
983
645k
  s->sp-=n;
984
645k
}
985
986
1.44M
#define push() push_n_(s,1)
987
0
#define push_n(n) push_n_(s,n)
988
468k
#define pop() pop_n_(s,1)
989
177k
#define pop_n(n) pop_n_(s,n)
990
2.57M
#define cursp() (s->sp)
991
992
static mrb_pool_value*
993
lit_pool_extend(codegen_scope *s)
994
3.46k
{
995
3.46k
  if (s->irep->plen == s->pcapa) {
996
47
    s->pcapa *= 2;
997
47
    s->pool = (mrb_pool_value*)codegen_realloc(s, s->pool, sizeof(mrb_pool_value)*s->pcapa);
998
47
  }
999
1000
3.46k
  return &s->pool[s->irep->plen++];
1001
3.46k
}
1002
1003
static int
1004
new_litbint(codegen_scope *s, const char *p, int base, mrb_bool neg)
1005
0
{
1006
0
  int i;
1007
0
  size_t plen;
1008
0
  mrb_pool_value *pv;
1009
1010
0
  plen = strlen(p);
1011
0
  if (plen > 255) {
1012
0
    codegen_error(s, "integer too big");
1013
0
  }
1014
0
  for (i=0; i<s->irep->plen; i++) {
1015
0
    size_t len;
1016
0
    pv = &s->pool[i];
1017
0
    if (pv->tt != IREP_TT_BIGINT) continue;
1018
0
    len = pv->u.str[0];
1019
0
    if (len == plen && pv->u.str[1] == base && memcmp(pv->u.str+2, p, len) == 0)
1020
0
      return i;
1021
0
  }
1022
1023
0
  pv = lit_pool_extend(s);
1024
1025
0
  char *buf;
1026
0
  pv->tt = IREP_TT_BIGINT;
1027
0
  buf = (char*)codegen_realloc(s, NULL, plen+3);
1028
0
  buf[0] = (char)plen;
1029
0
  if (neg) buf[1] = -base;
1030
0
  else buf[1] = base;
1031
0
  memcpy(buf+2, p, plen);
1032
0
  buf[plen+2] = '\0';
1033
0
  pv->u.str = buf;
1034
1035
0
  return i;
1036
0
}
1037
1038
static int
1039
new_lit_str(codegen_scope *s, const char *str, mrb_int len)
1040
327k
{
1041
327k
  int i;
1042
327k
  mrb_pool_value *pv;
1043
1044
681k
  for (i=0; i<s->irep->plen; i++) {
1045
678k
    pv = &s->pool[i];
1046
678k
    if (pv->tt & IREP_TT_NFLAG) continue;
1047
670k
    mrb_int plen = pv->tt>>2;
1048
670k
    if (len != plen) continue;
1049
351k
    if (memcmp(pv->u.str, str, plen) == 0)
1050
324k
      return i;
1051
351k
  }
1052
1053
3.20k
  pv = lit_pool_extend(s);
1054
1055
3.20k
  if (mrb_ro_data_p(str)) {
1056
0
    pv->tt = (uint32_t)(len<<2) | IREP_TT_SSTR;
1057
0
    pv->u.str = str;
1058
0
  }
1059
3.20k
  else {
1060
3.20k
    char *p;
1061
3.20k
    pv->tt = (uint32_t)(len<<2) | IREP_TT_STR;
1062
3.20k
    p = (char*)codegen_realloc(s, NULL, len+1);
1063
3.20k
    memcpy(p, str, len);
1064
3.20k
    p[len] = '\0';
1065
3.20k
    pv->u.str = p;
1066
3.20k
  }
1067
1068
3.20k
  return i;
1069
327k
}
1070
1071
static int
1072
new_lit_cstr(codegen_scope *s, const char *str)
1073
0
{
1074
0
  return new_lit_str(s, str, (mrb_int)strlen(str));
1075
0
}
1076
1077
static int
1078
new_lit_int(codegen_scope *s, mrb_int num)
1079
1.84k
{
1080
1.84k
  int i;
1081
1.84k
  mrb_pool_value *pv;
1082
1083
87.6k
  for (i=0; i<s->irep->plen; i++) {
1084
87.4k
    pv = &s->pool[i];
1085
87.4k
    if (pv->tt == IREP_TT_INT32) {
1086
0
      if (num == pv->u.i32) return i;
1087
0
    }
1088
87.4k
#ifdef MRB_64BIT
1089
87.4k
    else if (pv->tt == IREP_TT_INT64) {
1090
10.9k
      if (num == pv->u.i64) return i;
1091
10.9k
    }
1092
85.8k
    continue;
1093
87.4k
#endif
1094
87.4k
  }
1095
1096
262
  pv = lit_pool_extend(s);
1097
1098
262
#ifdef MRB_INT64
1099
262
  pv->tt = IREP_TT_INT64;
1100
262
  pv->u.i64 = num;
1101
#else
1102
  pv->tt = IREP_TT_INT32;
1103
  pv->u.i32 = num;
1104
#endif
1105
1106
262
  return i;
1107
1.84k
}
1108
1109
#ifndef MRB_NO_FLOAT
1110
static int
1111
new_lit_float(codegen_scope *s, mrb_float num)
1112
0
{
1113
0
  int i;
1114
0
  mrb_pool_value *pv;
1115
1116
0
  for (i=0; i<s->irep->plen; i++) {
1117
0
    mrb_float f;
1118
0
    pv = &s->pool[i];
1119
0
    if (pv->tt != IREP_TT_FLOAT) continue;
1120
0
    f = pv->u.f;
1121
0
    if (f == num && !signbit(f) == !signbit(num)) return i;
1122
0
  }
1123
1124
0
  pv = lit_pool_extend(s);
1125
1126
0
  pv->tt = IREP_TT_FLOAT;
1127
0
  pv->u.f = num;
1128
1129
0
  return i;
1130
0
}
1131
#endif
1132
1133
static int
1134
new_sym(codegen_scope *s, mrb_sym sym)
1135
144k
{
1136
144k
  int i, len;
1137
1138
144k
  mrb_assert(s->irep);
1139
1140
144k
  len = s->irep->slen;
1141
531k
  for (i=0; i<len; i++) {
1142
525k
    if (s->syms[i] == sym) return i;
1143
525k
  }
1144
5.31k
  if (s->irep->slen >= s->scapa) {
1145
0
    s->scapa *= 2;
1146
0
    if (s->scapa > 0xffff) {
1147
0
      codegen_error(s, "too many symbols");
1148
0
    }
1149
0
    s->syms = (mrb_sym*)codegen_realloc(s, s->syms, sizeof(mrb_sym)*s->scapa);
1150
0
  }
1151
5.31k
  s->syms[s->irep->slen] = sym;
1152
5.31k
  return s->irep->slen++;
1153
144k
}
1154
1155
static void
1156
gen_setxv(codegen_scope *s, uint8_t op, uint16_t dst, mrb_sym sym, int val)
1157
20.1k
{
1158
20.1k
  int idx = new_sym(s, sym);
1159
20.1k
  if (!val && !no_peephole(s)) {
1160
8.61k
    struct mrb_insn_data data = mrb_last_insn(s);
1161
8.61k
    if (data.insn == OP_MOVE && data.a == dst) {
1162
186
      dst = data.b;
1163
186
      rewind_pc(s);
1164
186
    }
1165
8.61k
  }
1166
20.1k
  genop_2(s, op, dst, idx);
1167
20.1k
}
1168
1169
static void
1170
gen_int(codegen_scope *s, uint16_t dst, mrb_int i)
1171
602k
{
1172
602k
  if (i < 0) {
1173
10.0k
    if (i == -1) genop_1(s, OP_LOADI__1, dst);
1174
8.21k
    else if (i >= -0xff) genop_2(s, OP_LOADINEG, dst, (uint16_t)-i);
1175
1.92k
    else if (i >= INT16_MIN) genop_2S(s, OP_LOADI16, dst, (uint16_t)i);
1176
1.48k
    else if (i >= INT32_MIN) genop_2SS(s, OP_LOADI32, dst, (uint32_t)i);
1177
1.01k
    else goto int_lit;
1178
10.0k
  }
1179
592k
  else if (i < 8) genop_1(s, OP_LOADI_0 + (uint8_t)i, dst);
1180
15.9k
  else if (i <= 0xff) genop_2(s, OP_LOADI, dst, (uint16_t)i);
1181
1.97k
  else if (i <= INT16_MAX) genop_2S(s, OP_LOADI16, dst, (uint16_t)i);
1182
1.28k
  else if (i <= INT32_MAX) genop_2SS(s, OP_LOADI32, dst, (uint32_t)i);
1183
830
  else {
1184
1.84k
  int_lit:
1185
1.84k
    genop_2(s, OP_LOADL, dst, new_lit_int(s, i));
1186
1.84k
  }
1187
602k
}
1188
1189
static mrb_bool
1190
gen_uniop(codegen_scope *s, mrb_sym sym, uint16_t dst)
1191
5.91k
{
1192
5.91k
  if (no_peephole(s)) return FALSE;
1193
5.91k
  struct mrb_insn_data data = mrb_last_insn(s);
1194
5.91k
  mrb_int n;
1195
1196
5.91k
  if (!get_int_operand(s, &data, &n)) return FALSE;
1197
0
  if (sym == MRB_OPSYM_2(s->mrb, plus)) {
1198
    /* unary plus does nothing */
1199
0
  }
1200
0
  else if (sym == MRB_OPSYM_2(s->mrb, minus)) {
1201
0
    if (n == MRB_INT_MIN) return FALSE;
1202
0
    n = -n;
1203
0
  }
1204
0
  else if (sym == MRB_OPSYM_2(s->mrb, neg)) {
1205
0
    n = ~n;
1206
0
  }
1207
0
  else {
1208
0
    return FALSE;
1209
0
  }
1210
0
  s->pc = addr_pc(s, data.addr);
1211
0
  gen_int(s, dst, n);
1212
0
  return TRUE;
1213
0
}
1214
1215
static int
1216
node_len(node *tree)
1217
2.33k
{
1218
2.33k
  int n = 0;
1219
1220
71.5k
  while (tree) {
1221
69.2k
    n++;
1222
69.2k
    tree = tree->cdr;
1223
69.2k
  }
1224
2.33k
  return n;
1225
2.33k
}
1226
1227
3.43M
#define nint(x) ((int)(intptr_t)(x))
1228
0
#define nchar(x) ((char)(intptr_t)(x))
1229
57.3M
#define nsym(x) ((mrb_sym)(intptr_t)(x))
1230
1231
56.8M
#define lv_name(lv) nsym((lv)->car)
1232
1233
static int
1234
lv_idx(codegen_scope *s, mrb_sym id)
1235
176k
{
1236
176k
  node *lv = s->lv;
1237
176k
  int n = 1;
1238
1239
56.8M
  while (lv) {
1240
56.8M
    if (lv_name(lv) == id) return n;
1241
56.6M
    n++;
1242
56.6M
    lv = lv->cdr;
1243
56.6M
  }
1244
0
  return 0;
1245
176k
}
1246
1247
static int
1248
search_upvar(codegen_scope *s, mrb_sym id, int *idx)
1249
0
{
1250
0
  const struct RProc *u;
1251
0
  int lv = 0;
1252
0
  codegen_scope *up = s->prev;
1253
1254
0
  while (up) {
1255
0
    *idx = lv_idx(up, id);
1256
0
    if (*idx > 0) {
1257
0
      return lv;
1258
0
    }
1259
0
    lv++;
1260
0
    up = up->prev;
1261
0
  }
1262
1263
0
  if (lv < 1) lv = 1;
1264
0
  u = s->parser->upper;
1265
0
  while (u && !MRB_PROC_CFUNC_P(u)) {
1266
0
    const struct mrb_irep *ir = u->body.irep;
1267
0
    uint_fast16_t n = ir->nlocals;
1268
0
    int i;
1269
1270
0
    const mrb_sym *v = ir->lv;
1271
0
    if (v) {
1272
0
      for (i=1; n > 1; n--, v++, i++) {
1273
0
        if (*v == id) {
1274
0
          *idx = i;
1275
0
          return lv - 1;
1276
0
        }
1277
0
      }
1278
0
    }
1279
0
    if (MRB_PROC_SCOPE_P(u)) break;
1280
0
    u = u->upper;
1281
0
    lv++;
1282
0
  }
1283
1284
0
  if (id == MRB_OPSYM_2(s->mrb, and)) {
1285
0
    codegen_error(s, "No anonymous block parameter");
1286
0
  }
1287
0
  else if (id == MRB_OPSYM_2(s->mrb, mul)) {
1288
0
    codegen_error(s, "No anonymous rest parameter");
1289
0
  }
1290
0
  else if (id == MRB_OPSYM_2(s->mrb, pow)) {
1291
0
    codegen_error(s, "No anonymous keyword rest parameter");
1292
0
  }
1293
0
  else {
1294
0
    codegen_error(s, "Can't find local variables");
1295
0
  }
1296
0
  return -1; /* not reached */
1297
0
}
1298
1299
static void
1300
for_body(codegen_scope *s, node *tree)
1301
0
{
1302
0
  codegen_scope *prev = s;
1303
0
  int idx;
1304
0
  struct loopinfo *lp;
1305
0
  node *n2;
1306
1307
  /* generate receiver */
1308
0
  codegen(s, tree->cdr->car, VAL);
1309
  /* generate loop-block */
1310
0
  s = scope_new(s->mrb, s, NULL);
1311
1312
0
  push();                       /* push for a block parameter */
1313
1314
  /* generate loop variable */
1315
0
  n2 = tree->car;
1316
0
  genop_W(s, OP_ENTER, 0x40000);
1317
0
  if (n2->car && !n2->car->cdr && !n2->cdr) {
1318
0
    gen_assignment(s, n2->car->car, NULL, 1, NOVAL);
1319
0
  }
1320
0
  else {
1321
0
    gen_massignment(s, n2, 1, VAL);
1322
0
  }
1323
  /* construct loop */
1324
0
  lp = loop_push(s, LOOP_FOR);
1325
0
  lp->pc1 = new_label(s);
1326
1327
  /* loop body */
1328
0
  codegen(s, tree->cdr->cdr->car, VAL);
1329
0
  pop();
1330
0
  gen_return(s, OP_RETURN, cursp());
1331
0
  loop_pop(s, NOVAL);
1332
0
  scope_finish(s);
1333
0
  s = prev;
1334
0
  genop_2(s, OP_BLOCK, cursp(), s->irep->rlen-1);
1335
0
  push();pop(); /* space for a block */
1336
0
  pop();
1337
0
  idx = new_sym(s, MRB_SYM_2(s->mrb, each));
1338
0
  genop_3(s, OP_SENDB, cursp(), idx, 0);
1339
0
}
1340
1341
static int
1342
lambda_body(codegen_scope *s, node *tree, int blk)
1343
466
{
1344
466
  codegen_scope *parent = s;
1345
466
  s = scope_new(s->mrb, s, tree->car);
1346
1347
466
  s->mscope = !blk;
1348
1349
466
  if (blk) {
1350
0
    struct loopinfo *lp = loop_push(s, LOOP_BLOCK);
1351
0
    lp->pc0 = new_label(s);
1352
0
  }
1353
466
  tree = tree->cdr;
1354
466
  if (tree->car == NULL) {
1355
0
    genop_W(s, OP_ENTER, 0);
1356
0
    s->ainfo = 0;
1357
0
  }
1358
466
  else {
1359
466
    mrb_aspec a;
1360
466
    int ma, oa, ra, pa, ka, kd, ba, i;
1361
466
    uint32_t pos;
1362
466
    node *opt;
1363
466
    node *margs, *pargs;
1364
466
    node *tail;
1365
1366
    /* mandatory arguments */
1367
466
    ma = node_len(tree->car->car);
1368
466
    margs = tree->car->car;
1369
466
    tail = tree->car->cdr->cdr->cdr->cdr;
1370
1371
    /* optional arguments */
1372
466
    oa = node_len(tree->car->cdr->car);
1373
    /* rest argument? */
1374
466
    ra = tree->car->cdr->cdr->car ? 1 : 0;
1375
    /* mandatory arguments after rest argument */
1376
466
    pa = node_len(tree->car->cdr->cdr->cdr->car);
1377
466
    pargs = tree->car->cdr->cdr->cdr->car;
1378
    /* keyword arguments */
1379
466
    ka = tail? node_len(tail->cdr->car) : 0;
1380
    /* keyword dictionary? */
1381
466
    kd = tail && tail->cdr->cdr->car? 1 : 0;
1382
    /* block argument? */
1383
466
    ba = tail && tail->cdr->cdr->cdr->car ? 1 : 0;
1384
1385
466
    if (ma > 0x1f || oa > 0x1f || pa > 0x1f || ka > 0x1f) {
1386
0
      codegen_error(s, "too many formal arguments");
1387
0
    }
1388
    /* (23bits = 5:5:1:5:5:1:1) */
1389
466
    a = MRB_ARGS_REQ(ma)
1390
466
      | MRB_ARGS_OPT(oa)
1391
466
      | (ra? MRB_ARGS_REST() : 0)
1392
466
      | MRB_ARGS_POST(pa)
1393
466
      | MRB_ARGS_KEY(ka, kd)
1394
466
      | (ba? MRB_ARGS_BLOCK() : 0);
1395
466
    genop_W(s, OP_ENTER, a);
1396
    /* (12bits = 5:1:5:1) */
1397
466
    s->ainfo = (((ma+oa) & 0x3f) << 7)
1398
466
      | ((ra & 0x1) << 6)
1399
466
      | ((pa & 0x1f) << 1)
1400
466
      | ((ka | kd) ? 1 : 0);
1401
    /* generate jump table for optional arguments initializer */
1402
466
    pos = new_label(s);
1403
466
    for (i=0; i<oa; i++) {
1404
0
      new_label(s);
1405
0
      genjmp_0(s, OP_JMP);
1406
0
    }
1407
466
    if (oa > 0) {
1408
0
      genjmp_0(s, OP_JMP);
1409
0
    }
1410
466
    opt = tree->car->cdr->car;
1411
466
    i = 0;
1412
466
    while (opt) {
1413
0
      int idx;
1414
0
      mrb_sym id = nsym(opt->car->car);
1415
1416
0
      dispatch(s, pos+i*3+1);
1417
0
      codegen(s, opt->car->cdr, VAL);
1418
0
      pop();
1419
0
      idx = lv_idx(s, id);
1420
0
      if (idx > 0) {
1421
0
        gen_move(s, idx, cursp(), 0);
1422
0
      }
1423
0
      else {
1424
0
        gen_getupvar(s, cursp(), id);
1425
0
      }
1426
0
      i++;
1427
0
      opt = opt->cdr;
1428
0
    }
1429
466
    if (oa > 0) {
1430
0
      dispatch(s, pos+i*3+1);
1431
0
    }
1432
1433
    /* keyword arguments */
1434
466
    if (tail) {
1435
0
      node *kwds = tail->cdr->car;
1436
0
      int kwrest = 0;
1437
1438
0
      if (tail->cdr->cdr->car) {
1439
0
        kwrest = 1;
1440
0
      }
1441
0
      mrb_assert(nint(tail->car) == NODE_ARGS_TAIL);
1442
0
      mrb_assert(node_len(tail) == 4);
1443
1444
0
      while (kwds) {
1445
0
        int jmpif_key_p, jmp_def_set = -1;
1446
0
        node *kwd = kwds->car, *def_arg = kwd->cdr->cdr->car;
1447
0
        mrb_sym kwd_sym = nsym(kwd->cdr->car);
1448
1449
0
        mrb_assert(nint(kwd->car) == NODE_KW_ARG);
1450
1451
0
        if (def_arg) {
1452
0
          int idx;
1453
0
          genop_2(s, OP_KEY_P, lv_idx(s, kwd_sym), new_sym(s, kwd_sym));
1454
0
          jmpif_key_p = genjmp2_0(s, OP_JMPIF, lv_idx(s, kwd_sym), NOVAL);
1455
0
          codegen(s, def_arg, VAL);
1456
0
          pop();
1457
0
          idx = lv_idx(s, kwd_sym);
1458
0
          if (idx > 0) {
1459
0
            gen_move(s, idx, cursp(), 0);
1460
0
          }
1461
0
          else {
1462
0
            gen_getupvar(s, cursp(), kwd_sym);
1463
0
          }
1464
0
          jmp_def_set = genjmp_0(s, OP_JMP);
1465
0
          dispatch(s, jmpif_key_p);
1466
0
        }
1467
0
        genop_2(s, OP_KARG, lv_idx(s, kwd_sym), new_sym(s, kwd_sym));
1468
0
        if (jmp_def_set != -1) {
1469
0
          dispatch(s, jmp_def_set);
1470
0
        }
1471
0
        i++;
1472
1473
0
        kwds = kwds->cdr;
1474
0
      }
1475
0
      if (tail->cdr->car && !kwrest) {
1476
0
        genop_0(s, OP_KEYEND);
1477
0
      }
1478
0
    }
1479
1480
    /* argument destructuring */
1481
466
    if (margs) {
1482
0
      node *n = margs;
1483
1484
0
      pos = 1;
1485
0
      while (n) {
1486
0
        if (nint(n->car->car) == NODE_MASGN) {
1487
0
          gen_massignment(s, n->car->cdr->car, pos, NOVAL);
1488
0
        }
1489
0
        pos++;
1490
0
        n = n->cdr;
1491
0
      }
1492
0
    }
1493
466
    if (pargs) {
1494
0
      node *n = pargs;
1495
1496
0
      pos = ma+oa+ra+1;
1497
0
      while (n) {
1498
0
        if (nint(n->car->car) == NODE_MASGN) {
1499
0
          gen_massignment(s, n->car->cdr->car, pos, NOVAL);
1500
0
        }
1501
0
        pos++;
1502
0
        n = n->cdr;
1503
0
      }
1504
0
    }
1505
466
  }
1506
1507
466
  codegen(s, tree->cdr->car, VAL);
1508
466
  pop();
1509
466
  if (s->pc > 0) {
1510
451
    gen_return(s, OP_RETURN, cursp());
1511
451
  }
1512
466
  if (blk) {
1513
0
    loop_pop(s, NOVAL);
1514
0
  }
1515
466
  scope_finish(s);
1516
466
  return parent->irep->rlen - 1;
1517
466
}
1518
1519
static int
1520
scope_body(codegen_scope *s, node *tree, int val)
1521
466
{
1522
466
  codegen_scope *scope = scope_new(s->mrb, s, tree->car);
1523
1524
466
  codegen(scope, tree->cdr, VAL);
1525
466
  gen_return(scope, OP_RETURN, scope->sp-1);
1526
466
  if (!s->iseq) {
1527
394
    genop_0(scope, OP_STOP);
1528
394
  }
1529
466
  scope_finish(scope);
1530
466
  if (!s->irep) {
1531
    /* should not happen */
1532
0
    return 0;
1533
0
  }
1534
466
  return s->irep->rlen - 1;
1535
466
}
1536
1537
static mrb_bool
1538
nosplat(node *t)
1539
0
{
1540
0
  while (t) {
1541
0
    if (nint(t->car->car) == NODE_SPLAT) return FALSE;
1542
0
    t = t->cdr;
1543
0
  }
1544
0
  return TRUE;
1545
0
}
1546
1547
static mrb_sym
1548
attrsym(codegen_scope *s, mrb_sym a)
1549
0
{
1550
0
  const char *name;
1551
0
  mrb_int len;
1552
0
  char *name2;
1553
1554
0
  name = mrb_sym_name_len(s->mrb, a, &len);
1555
0
  name2 = (char*)codegen_palloc(s,
1556
0
                                (size_t)len
1557
0
                                + 1 /* '=' */
1558
0
                                + 1 /* '\0' */
1559
0
                                );
1560
0
  mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
1561
0
  memcpy(name2, name, (size_t)len);
1562
0
  name2[len] = '=';
1563
0
  name2[len+1] = '\0';
1564
1565
0
  return mrb_intern(s->mrb, name2, len+1);
1566
0
}
1567
1568
0
#define CALL_MAXARGS 15
1569
52.5k
#define GEN_LIT_ARY_MAX 64
1570
196k
#define GEN_VAL_STACK_MAX 99
1571
1572
static int
1573
gen_values(codegen_scope *s, node *t, int val, int limit)
1574
194k
{
1575
194k
  int n = 0;
1576
194k
  int first = 1;
1577
194k
  int slimit = GEN_VAL_STACK_MAX;
1578
1579
194k
  if (limit == 0) limit = GEN_LIT_ARY_MAX;
1580
194k
  if (cursp() >= slimit) slimit = INT16_MAX;
1581
1582
194k
  if (!val) {
1583
0
    while (t) {
1584
0
      codegen(s, t->car, NOVAL);
1585
0
      n++;
1586
0
      t = t->cdr;
1587
0
    }
1588
0
    return n;
1589
0
  }
1590
1591
688k
  while (t) {
1592
493k
    int is_splat = nint(t->car->car) == NODE_SPLAT;
1593
1594
493k
    if (is_splat || cursp() >= slimit) { /* flush stack */
1595
127k
      pop_n(n);
1596
127k
      if (first) {
1597
2.05k
        if (n == 0) {
1598
0
          genop_1(s, OP_LOADNIL, cursp());
1599
0
        }
1600
2.05k
        else {
1601
2.05k
          genop_2(s, OP_ARRAY, cursp(), n);
1602
2.05k
        }
1603
2.05k
        push();
1604
2.05k
        first = 0;
1605
2.05k
        limit = GEN_LIT_ARY_MAX;
1606
2.05k
      }
1607
125k
      else if (n > 0) {
1608
125k
        pop();
1609
125k
        genop_2(s, OP_ARYPUSH, cursp(), n);
1610
125k
        push();
1611
125k
      }
1612
127k
      n = 0;
1613
127k
    }
1614
493k
    codegen(s, t->car, val);
1615
493k
    if (is_splat) {
1616
0
      pop(); pop();
1617
0
      genop_1(s, OP_ARYCAT, cursp());
1618
0
      push();
1619
0
    }
1620
493k
    else {
1621
493k
      n++;
1622
493k
    }
1623
493k
    t = t->cdr;
1624
493k
  }
1625
194k
  if (!first) {
1626
2.05k
    pop();
1627
2.05k
    if (n > 0) {
1628
2.05k
      pop_n(n);
1629
2.05k
      genop_2(s, OP_ARYPUSH, cursp(), n);
1630
2.05k
    }
1631
2.05k
    return -1;                  /* variable length */
1632
2.05k
  }
1633
192k
  else if (n > limit) {
1634
96
    pop_n(n);
1635
96
    genop_2(s, OP_ARRAY, cursp(), n);
1636
96
    return -1;
1637
96
  }
1638
192k
  return n;
1639
194k
}
1640
1641
static int
1642
gen_hash(codegen_scope *s, node *tree, int val, int limit)
1643
2.01k
{
1644
2.01k
  int slimit = GEN_VAL_STACK_MAX;
1645
2.01k
  if (cursp() >= GEN_LIT_ARY_MAX) slimit = INT16_MAX;
1646
2.01k
  int len = 0;
1647
2.01k
  mrb_bool update = FALSE;
1648
2.01k
  mrb_bool first = TRUE;
1649
1650
165k
  while (tree) {
1651
163k
    if (nint(tree->car->car->car) == NODE_KW_REST_ARGS) {
1652
0
      if (val && first) {
1653
0
        genop_2(s, OP_HASH, cursp(), 0);
1654
0
        push();
1655
0
        update = TRUE;
1656
0
      }
1657
0
      else if (val && len > 0) {
1658
0
        pop_n(len*2);
1659
0
        if (!update) {
1660
0
          genop_2(s, OP_HASH, cursp(), len);
1661
0
        }
1662
0
        else {
1663
0
          pop();
1664
0
          genop_2(s, OP_HASHADD, cursp(), len);
1665
0
        }
1666
0
        push();
1667
0
      }
1668
0
      codegen(s, tree->car->cdr, val);
1669
0
      if (val && (len > 0 || update)) {
1670
0
        pop(); pop();
1671
0
        genop_1(s, OP_HASHCAT, cursp());
1672
0
        push();
1673
0
      }
1674
0
      update = TRUE;
1675
0
      len = 0;
1676
0
    }
1677
163k
    else {
1678
163k
      codegen(s, tree->car->car, val);
1679
163k
      codegen(s, tree->car->cdr, val);
1680
163k
      len++;
1681
163k
    }
1682
163k
    tree = tree->cdr;
1683
163k
    if (val && cursp() >= slimit) {
1684
1.33k
      pop_n(len*2);
1685
1.33k
      if (!update) {
1686
200
        genop_2(s, OP_HASH, cursp(), len);
1687
200
      }
1688
1.13k
      else {
1689
1.13k
        pop();
1690
1.13k
        genop_2(s, OP_HASHADD, cursp(), len);
1691
1.13k
      }
1692
1.33k
      push();
1693
1.33k
      update = TRUE;
1694
1.33k
      len = 0;
1695
1.33k
    }
1696
163k
    first = FALSE;
1697
163k
  }
1698
2.01k
  if (val && len > limit) {
1699
333
    pop_n(len*2);
1700
333
    genop_2(s, OP_HASH, cursp(), len);
1701
333
    push();
1702
333
    return -1;
1703
333
  }
1704
1.68k
  if (update) {
1705
200
    if (val && len > 0) {
1706
200
      pop_n(len*2+1);
1707
200
      genop_2(s, OP_HASHADD, cursp(), len);
1708
200
      push();
1709
200
    }
1710
200
    return -1;                  /* variable length */
1711
200
  }
1712
1.48k
  return len;
1713
1.68k
}
1714
1715
static void
1716
gen_call(codegen_scope *s, node *tree, int val, int safe)
1717
154k
{
1718
154k
  mrb_sym sym = nsym(tree->cdr->car);
1719
154k
  int skip = 0, n = 0, nk = 0, noop = no_optimize(s), noself = 0, blk = 0, sp_save = cursp();
1720
1721
154k
  if (!tree->car) {
1722
394
    noself = noop = 1;
1723
394
    push();
1724
394
  }
1725
154k
  else {
1726
154k
    codegen(s, tree->car, VAL); /* receiver */
1727
154k
  }
1728
154k
  if (safe) {
1729
0
    int recv = cursp()-1;
1730
0
    gen_move(s, cursp(), recv, 1);
1731
0
    skip = genjmp2_0(s, OP_JMPNIL, cursp(), val);
1732
0
  }
1733
154k
  tree = tree->cdr->cdr->car;
1734
154k
  if (tree) {
1735
148k
    if (tree->car) {            /* positional arguments */
1736
148k
      n = gen_values(s, tree->car, VAL, 14);
1737
148k
      if (n < 0) {              /* variable length */
1738
0
        noop = 1;               /* not operator */
1739
0
        n = 15;
1740
0
        push();
1741
0
      }
1742
148k
    }
1743
148k
    if (tree->cdr->car) {       /* keyword arguments */
1744
0
      noop = 1;
1745
0
      nk = gen_hash(s, tree->cdr->car->cdr, VAL, 14);
1746
0
      if (nk < 0) nk = 15;
1747
0
    }
1748
148k
  }
1749
154k
  if (tree && tree->cdr && tree->cdr->cdr) {
1750
0
    codegen(s, tree->cdr->cdr, VAL);
1751
0
    pop();
1752
0
    noop = 1;
1753
0
    blk = 1;
1754
0
  }
1755
154k
  push();pop();
1756
154k
  s->sp = sp_save;
1757
154k
  if (!noop && sym == MRB_OPSYM_2(s->mrb, add) && n == 1)  {
1758
11.9k
    gen_addsub(s, OP_ADD, cursp());
1759
11.9k
  }
1760
142k
  else if (!noop && sym == MRB_OPSYM_2(s->mrb, sub) && n == 1)  {
1761
20.8k
    gen_addsub(s, OP_SUB, cursp());
1762
20.8k
  }
1763
121k
  else if (!noop && sym == MRB_OPSYM_2(s->mrb, mul) && n == 1)  {
1764
8.24k
    gen_muldiv(s, OP_MUL, cursp());
1765
8.24k
  }
1766
113k
  else if (!noop && sym == MRB_OPSYM_2(s->mrb, div) && n == 1)  {
1767
12.3k
    gen_muldiv(s, OP_DIV, cursp());
1768
12.3k
  }
1769
101k
  else if (!noop && sym == MRB_OPSYM_2(s->mrb, lt) && n == 1)  {
1770
1.30k
    genop_1(s, OP_LT, cursp());
1771
1.30k
  }
1772
100k
  else if (!noop && sym == MRB_OPSYM_2(s->mrb, le) && n == 1)  {
1773
3.70k
    genop_1(s, OP_LE, cursp());
1774
3.70k
  }
1775
96.3k
  else if (!noop && sym == MRB_OPSYM_2(s->mrb, gt) && n == 1)  {
1776
2.27k
    genop_1(s, OP_GT, cursp());
1777
2.27k
  }
1778
94.0k
  else if (!noop && sym == MRB_OPSYM_2(s->mrb, ge) && n == 1)  {
1779
1.64k
    genop_1(s, OP_GE, cursp());
1780
1.64k
  }
1781
92.4k
  else if (!noop && sym == MRB_OPSYM_2(s->mrb, eq) && n == 1)  {
1782
1.93k
    genop_1(s, OP_EQ, cursp());
1783
1.93k
  }
1784
90.4k
  else if (!noop && sym == MRB_OPSYM_2(s->mrb, aset) && n == 2)  {
1785
0
    genop_1(s, OP_SETIDX, cursp());
1786
0
  }
1787
90.4k
  else if (!noop && n == 0 && gen_uniop(s, sym, cursp())) {
1788
    /* constant folding succeeded */
1789
0
  }
1790
90.4k
  else if (!noop && n == 1 && gen_binop(s, sym, cursp())) {
1791
    /* constant folding succeeded */
1792
7.47k
  }
1793
82.9k
  else if (noself){
1794
394
    genop_3(s, blk ? OP_SSENDB : OP_SSEND, cursp(), new_sym(s, sym), n|(nk<<4));
1795
394
  }
1796
82.6k
  else {
1797
82.6k
    genop_3(s, blk ? OP_SENDB : OP_SEND, cursp(), new_sym(s, sym), n|(nk<<4));
1798
82.6k
  }
1799
154k
  if (safe) {
1800
0
    dispatch(s, skip);
1801
0
  }
1802
154k
  if (val) {
1803
91.1k
    push();
1804
91.1k
  }
1805
154k
}
1806
1807
static void
1808
gen_assignment(codegen_scope *s, node *tree, node *rhs, int sp, int val)
1809
139k
{
1810
139k
  int idx;
1811
139k
  int type = nint(tree->car);
1812
1813
139k
  switch (type) {
1814
0
  case NODE_GVAR:
1815
0
  case NODE_ARG:
1816
119k
  case NODE_LVAR:
1817
139k
  case NODE_IVAR:
1818
139k
  case NODE_CVAR:
1819
139k
  case NODE_CONST:
1820
139k
  case NODE_NIL:
1821
139k
  case NODE_MASGN:
1822
139k
    if (rhs) {
1823
119k
      codegen(s, rhs, VAL);
1824
119k
      pop();
1825
119k
      sp = cursp();
1826
119k
    }
1827
139k
    break;
1828
1829
0
  case NODE_COLON2:
1830
0
  case NODE_COLON3:
1831
0
  case NODE_CALL:
1832
0
  case NODE_SCALL:
1833
    /* keep evaluation order */
1834
0
    break;
1835
1836
0
  case NODE_NVAR:
1837
    /* never happens; should have already checked in the parser */
1838
0
    codegen_error(s, "Can't assign to numbered parameter");
1839
0
    break;
1840
1841
0
  default:
1842
0
    codegen_error(s, "unknown lhs");
1843
0
    break;
1844
139k
  }
1845
1846
139k
  tree = tree->cdr;
1847
139k
  switch (type) {
1848
0
  case NODE_GVAR:
1849
0
    gen_setxv(s, OP_SETGV, sp, nsym(tree), val);
1850
0
    break;
1851
0
  case NODE_ARG:
1852
119k
  case NODE_LVAR:
1853
119k
    idx = lv_idx(s, nsym(tree));
1854
119k
    if (idx > 0) {
1855
119k
      if (idx != sp) {
1856
119k
        gen_move(s, idx, sp, val);
1857
119k
      }
1858
119k
      break;
1859
119k
    }
1860
0
    else {                      /* upvar */
1861
0
      gen_setupvar(s, sp, nsym(tree));
1862
0
    }
1863
0
    break;
1864
20.1k
  case NODE_IVAR:
1865
20.1k
    gen_setxv(s, OP_SETIV, sp, nsym(tree), val);
1866
20.1k
    break;
1867
0
  case NODE_CVAR:
1868
0
    gen_setxv(s, OP_SETCV, sp, nsym(tree), val);
1869
0
    break;
1870
0
  case NODE_CONST:
1871
0
    gen_setxv(s, OP_SETCONST, sp, nsym(tree), val);
1872
0
    break;
1873
0
  case NODE_COLON2:
1874
0
  case NODE_COLON3:
1875
0
    if (sp) {
1876
0
      gen_move(s, cursp(), sp, 0);
1877
0
    }
1878
0
    sp = cursp();
1879
0
    push();
1880
0
    if (type == NODE_COLON2) {
1881
0
      codegen(s, tree->car, VAL);
1882
0
      idx = new_sym(s, nsym(tree->cdr));
1883
0
    }
1884
0
    else {   /* NODE_COLON3 */
1885
0
      genop_1(s, OP_OCLASS, cursp());
1886
0
      push();
1887
0
      idx = new_sym(s, nsym(tree));
1888
0
    }
1889
0
    if (rhs) {
1890
0
      codegen(s, rhs, VAL); pop();
1891
0
      gen_move(s, sp, cursp(), 0);
1892
0
    }
1893
0
    pop_n(2);
1894
0
    genop_2(s, OP_SETMCNST, sp, idx);
1895
0
    break;
1896
1897
0
  case NODE_CALL:
1898
0
  case NODE_SCALL:
1899
0
    {
1900
0
      int noself = 0, safe = (type == NODE_SCALL), skip = 0, top, call, n = 0;
1901
0
      mrb_sym mid = nsym(tree->cdr->car);
1902
1903
0
      top = cursp();
1904
0
      if (val || sp == cursp()) {
1905
0
        push();                   /* room for retval */
1906
0
      }
1907
0
      call = cursp();
1908
0
      if (!tree->car) {
1909
0
        noself = 1;
1910
0
        push();
1911
0
      }
1912
0
      else {
1913
0
        codegen(s, tree->car, VAL); /* receiver */
1914
0
      }
1915
0
      if (safe) {
1916
0
        int recv = cursp()-1;
1917
0
        gen_move(s, cursp(), recv, 1);
1918
0
        skip = genjmp2_0(s, OP_JMPNIL, cursp(), val);
1919
0
      }
1920
0
      tree = tree->cdr->cdr->car;
1921
0
      if (tree) {
1922
0
        if (tree->car) {            /* positional arguments */
1923
0
          n = gen_values(s, tree->car, VAL, (tree->cdr->car)?13:14);
1924
0
          if (n < 0) {              /* variable length */
1925
0
            n = 15;
1926
0
            push();
1927
0
          }
1928
0
        }
1929
0
        if (tree->cdr->car) {       /* keyword arguments */
1930
0
          if (n == 13 || n == 14) {
1931
0
            pop_n(n);
1932
0
            genop_2(s, OP_ARRAY, cursp(), n);
1933
0
            push();
1934
0
            n = 15;
1935
0
          }
1936
0
          gen_hash(s, tree->cdr->car->cdr, VAL, 0);
1937
0
          if (n < 14) {
1938
0
            n++;
1939
0
          }
1940
0
          else {
1941
0
            pop_n(2);
1942
0
            genop_2(s, OP_ARYPUSH, cursp(), 1);
1943
0
          }
1944
0
          push();
1945
0
        }
1946
0
      }
1947
0
      if (rhs) {
1948
0
        codegen(s, rhs, VAL);
1949
0
        pop();
1950
0
      }
1951
0
      else {
1952
0
        gen_move(s, cursp(), sp, 0);
1953
0
      }
1954
0
      if (val) {
1955
0
        gen_move(s, top, cursp(), 1);
1956
0
      }
1957
0
      if (n < 15) {
1958
0
        n++;
1959
0
        if (n == 15) {
1960
0
          pop_n(14);
1961
0
          genop_2(s, OP_ARRAY, cursp(), 15);
1962
0
        }
1963
0
      }
1964
0
      else {
1965
0
        pop();
1966
0
        genop_2(s, OP_ARYPUSH, cursp(), 1);
1967
0
      }
1968
0
      push(); pop();
1969
0
      s->sp = call;
1970
0
      if (mid == MRB_OPSYM_2(s->mrb, aref) && n == 2) {
1971
0
        push_n(4); pop_n(4); /* self + idx + value + (invisible block for OP_SEND) */
1972
0
        genop_1(s, OP_SETIDX, cursp());
1973
0
      }
1974
0
      else {
1975
0
        int st = 2 /* self + block */ +
1976
0
                 (((n >> 0) & 0x0f) < 15 ? ((n >> 0) & 0x0f)     : 1) +
1977
0
                 (((n >> 4) & 0x0f) < 15 ? ((n >> 4) & 0x0f) * 2 : 1);
1978
0
        push_n(st); pop_n(st);
1979
0
        genop_3(s, noself ? OP_SSEND : OP_SEND, cursp(), new_sym(s, attrsym(s, mid)), n);
1980
0
      }
1981
0
      if (safe) {
1982
0
        dispatch(s, skip);
1983
0
      }
1984
0
      s->sp = top;
1985
0
    }
1986
0
    break;
1987
1988
0
  case NODE_MASGN:
1989
0
    gen_massignment(s, tree->car, sp, val);
1990
0
    break;
1991
1992
  /* splat without assignment */
1993
0
  case NODE_NIL:
1994
0
    break;
1995
1996
0
  default:
1997
0
    codegen_error(s, "unknown lhs");
1998
0
    break;
1999
139k
  }
2000
139k
  if (val) push();
2001
139k
}
2002
2003
static void
2004
gen_massignment(codegen_scope *s, node *tree, int rhs, int val)
2005
0
{
2006
0
  int n = 0, post = 0;
2007
0
  node *t, *p;
2008
2009
0
  if (tree->car) {              /* pre */
2010
0
    t = tree->car;
2011
0
    n = 0;
2012
0
    while (t) {
2013
0
      int sp = cursp();
2014
2015
0
      genop_3(s, OP_AREF, sp, rhs, n);
2016
0
      push();
2017
0
      gen_assignment(s, t->car, NULL, sp, NOVAL);
2018
0
      pop();
2019
0
      n++;
2020
0
      t = t->cdr;
2021
0
    }
2022
0
  }
2023
0
  t = tree->cdr;
2024
0
  if (t) {
2025
0
    if (t->cdr) {               /* post count */
2026
0
      p = t->cdr->car;
2027
0
      while (p) {
2028
0
        post++;
2029
0
        p = p->cdr;
2030
0
      }
2031
0
    }
2032
0
    gen_move(s, cursp(), rhs, val);
2033
0
    push_n(post+1);
2034
0
    pop_n(post+1);
2035
0
    genop_3(s, OP_APOST, cursp(), n, post);
2036
0
    n = 1;
2037
0
    if (t->car && t->car != (node*)-1) { /* rest */
2038
0
      gen_assignment(s, t->car, NULL, cursp(), NOVAL);
2039
0
    }
2040
0
    if (t->cdr && t->cdr->car) {
2041
0
      t = t->cdr->car;
2042
0
      while (t) {
2043
0
        gen_assignment(s, t->car, NULL, cursp()+n, NOVAL);
2044
0
        t = t->cdr;
2045
0
        n++;
2046
0
      }
2047
0
    }
2048
0
    if (val) {
2049
0
      gen_move(s, cursp(), rhs, 0);
2050
0
    }
2051
0
  }
2052
0
}
2053
2054
static void
2055
gen_intern(codegen_scope *s)
2056
0
{
2057
0
  pop();
2058
0
  if (!no_peephole(s)) {
2059
0
    struct mrb_insn_data data = mrb_last_insn(s);
2060
2061
0
    if (data.insn == OP_STRING && data.a == cursp()) {
2062
0
      rewind_pc(s);
2063
0
      genop_2(s, OP_SYMBOL, data.a, data.b);
2064
0
      push();
2065
0
      return;
2066
0
    }
2067
0
  }
2068
0
  genop_1(s, OP_INTERN, cursp());
2069
0
  push();
2070
0
}
2071
2072
static void
2073
gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
2074
0
{
2075
0
  if (val) {
2076
0
    int i = 0, j = 0, gen = 0;
2077
2078
0
    while (tree) {
2079
0
      switch (nint(tree->car->car)) {
2080
0
      case NODE_STR:
2081
0
        if ((tree->cdr == NULL) && (nint(tree->car->cdr->cdr) == 0))
2082
0
          break;
2083
        /* fall through */
2084
0
      case NODE_BEGIN:
2085
0
        codegen(s, tree->car, VAL);
2086
0
        j++;
2087
0
        break;
2088
2089
0
      case NODE_LITERAL_DELIM:
2090
0
        if (j > 0) {
2091
0
          j = 0;
2092
0
          i++;
2093
0
          if (sym)
2094
0
            gen_intern(s);
2095
0
        }
2096
0
        break;
2097
0
      }
2098
0
      while (j >= 2) {
2099
0
        pop(); pop();
2100
0
        genop_1(s, OP_STRCAT, cursp());
2101
0
        push();
2102
0
        j--;
2103
0
      }
2104
0
      if (i > GEN_LIT_ARY_MAX) {
2105
0
        pop_n(i);
2106
0
        if (gen) {
2107
0
          pop();
2108
0
          genop_2(s, OP_ARYPUSH, cursp(), i);
2109
0
        }
2110
0
        else {
2111
0
          genop_2(s, OP_ARRAY, cursp(), i);
2112
0
          gen = 1;
2113
0
        }
2114
0
        push();
2115
0
        i = 0;
2116
0
      }
2117
0
      tree = tree->cdr;
2118
0
    }
2119
0
    if (j > 0) {
2120
0
      i++;
2121
0
      if (sym)
2122
0
        gen_intern(s);
2123
0
    }
2124
0
    pop_n(i);
2125
0
    if (gen) {
2126
0
      pop();
2127
0
      genop_2(s, OP_ARYPUSH, cursp(), i);
2128
0
    }
2129
0
    else {
2130
0
      genop_2(s, OP_ARRAY, cursp(), i);
2131
0
    }
2132
0
    push();
2133
0
  }
2134
0
  else {
2135
0
    while (tree) {
2136
0
      switch (nint(tree->car->car)) {
2137
0
      case NODE_BEGIN: case NODE_BLOCK:
2138
0
        codegen(s, tree->car, NOVAL);
2139
0
      }
2140
0
      tree = tree->cdr;
2141
0
    }
2142
0
  }
2143
0
}
2144
2145
static void
2146
raise_error(codegen_scope *s, const char *msg)
2147
0
{
2148
0
  int idx = new_lit_cstr(s, msg);
2149
2150
0
  genop_1(s, OP_ERR, idx);
2151
0
}
2152
2153
static mrb_int
2154
readint(codegen_scope *s, const char *p, int base, mrb_bool neg, mrb_bool *overflow)
2155
575k
{
2156
575k
  const char *e = p + strlen(p);
2157
575k
  mrb_int result = 0;
2158
2159
575k
  mrb_assert(base >= 2 && base <= 16);
2160
575k
  if (*p == '+') p++;
2161
1.15M
  while (p < e) {
2162
579k
    int n;
2163
579k
    char c = *p;
2164
579k
    switch (c) {
2165
560k
    case '0': case '1': case '2': case '3':
2166
571k
    case '4': case '5': case '6': case '7':
2167
571k
      n = c - '0'; break;
2168
7.98k
    case '8': case '9':
2169
7.98k
      n = c - '0'; break;
2170
0
    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
2171
0
      n = c - 'a' + 10; break;
2172
0
    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
2173
0
      n = c - 'A' + 10; break;
2174
0
    default:
2175
0
      codegen_error(s, "malformed readint input");
2176
0
      *overflow = TRUE;
2177
      /* not reached */
2178
0
      return result;
2179
579k
    }
2180
579k
    if (mrb_int_mul_overflow(result, base, &result)) {
2181
0
    overflow:
2182
0
      *overflow = TRUE;
2183
0
      return 0;
2184
0
    }
2185
579k
    mrb_uint tmp = ((mrb_uint)result)+n;
2186
579k
    if (neg && tmp == (mrb_uint)MRB_INT_MAX+1) {
2187
0
      *overflow = FALSE;
2188
0
      return MRB_INT_MIN;
2189
0
    }
2190
579k
    if (tmp > MRB_INT_MAX) goto overflow;
2191
579k
    result = (mrb_int)tmp;
2192
579k
    p++;
2193
579k
  }
2194
575k
  *overflow = FALSE;
2195
575k
  if (neg) return -result;
2196
575k
  return result;
2197
575k
}
2198
2199
static void
2200
gen_retval(codegen_scope *s, node *tree)
2201
0
{
2202
0
  if (nint(tree->car) == NODE_SPLAT) {
2203
0
    codegen(s, tree, VAL);
2204
0
    pop();
2205
0
    genop_1(s, OP_ARYSPLAT, cursp());
2206
0
  }
2207
0
  else {
2208
0
    codegen(s, tree, VAL);
2209
0
    pop();
2210
0
  }
2211
0
}
2212
2213
static mrb_bool
2214
true_always(node *tree)
2215
31.0k
{
2216
31.0k
  switch (nint(tree->car)) {
2217
0
  case NODE_TRUE:
2218
11.7k
  case NODE_INT:
2219
11.7k
  case NODE_STR:
2220
11.7k
  case NODE_SYM:
2221
11.7k
    return TRUE;
2222
19.3k
  default:
2223
19.3k
    return FALSE;
2224
31.0k
  }
2225
31.0k
}
2226
2227
static mrb_bool
2228
false_always(node *tree)
2229
19.3k
{
2230
19.3k
  switch (nint(tree->car)) {
2231
0
  case NODE_FALSE:
2232
0
  case NODE_NIL:
2233
0
    return TRUE;
2234
19.3k
  default:
2235
19.3k
    return FALSE;
2236
19.3k
  }
2237
19.3k
}
2238
2239
static void
2240
gen_blkmove(codegen_scope *s, uint16_t ainfo, int lv)
2241
0
{
2242
0
  int m1 = (ainfo>>7)&0x3f;
2243
0
  int r  = (ainfo>>6)&0x1;
2244
0
  int m2 = (ainfo>>1)&0x1f;
2245
0
  int kd = (ainfo)&0x1;
2246
0
  int off = m1+r+m2+kd+1;
2247
0
  if (lv == 0) {
2248
0
    gen_move(s, cursp(), off, 0);
2249
0
  }
2250
0
  else {
2251
0
    genop_3(s, OP_GETUPVAR, cursp(), off, lv);
2252
0
  }
2253
0
  push();
2254
0
}
2255
2256
static void
2257
codegen(codegen_scope *s, node *tree, int val)
2258
1.58M
{
2259
1.58M
  int nt;
2260
1.58M
  int rlev = s->rlev;
2261
2262
1.58M
  if (!tree) {
2263
0
    if (val) {
2264
0
      genop_1(s, OP_LOADNIL, cursp());
2265
0
      push();
2266
0
    }
2267
0
    return;
2268
0
  }
2269
2270
1.58M
  s->rlev++;
2271
1.58M
  if (s->rlev > MRB_CODEGEN_LEVEL_MAX) {
2272
0
    codegen_error(s, "too complex expression");
2273
0
  }
2274
1.58M
  if (s->irep && s->filename_index != tree->filename_index) {
2275
0
    mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index);
2276
0
    const char *filename = mrb_sym_name_len(s->mrb, fname, NULL);
2277
2278
0
    mrb_debug_info_append_file(s->mrb, s->irep->debug_info,
2279
0
                               filename, s->lines, s->debug_start_pos, s->pc);
2280
0
    s->debug_start_pos = s->pc;
2281
0
    s->filename_index = tree->filename_index;
2282
0
    s->filename_sym = mrb_parser_get_filename(s->parser, tree->filename_index);
2283
0
  }
2284
2285
1.58M
  nt = nint(tree->car);
2286
1.58M
  s->lineno = tree->lineno;
2287
1.58M
  tree = tree->cdr;
2288
1.58M
  switch (nt) {
2289
189k
  case NODE_BEGIN:
2290
189k
    if (val && !tree) {
2291
9.21k
      genop_1(s, OP_LOADNIL, cursp());
2292
9.21k
      push();
2293
9.21k
    }
2294
576k
    while (tree) {
2295
386k
      codegen(s, tree->car, tree->cdr ? NOVAL : val);
2296
386k
      tree = tree->cdr;
2297
386k
    }
2298
189k
    break;
2299
2300
0
  case NODE_RESCUE:
2301
0
    {
2302
0
      int noexc;
2303
0
      uint32_t exend, pos1, pos2, tmp;
2304
0
      struct loopinfo *lp;
2305
0
      int catch_entry, begin, end;
2306
2307
0
      if (tree->car == NULL) goto exit;
2308
0
      lp = loop_push(s, LOOP_BEGIN);
2309
0
      lp->pc0 = new_label(s);
2310
0
      catch_entry = catch_handler_new(s);
2311
0
      begin = s->pc;
2312
0
      codegen(s, tree->car, VAL);
2313
0
      pop();
2314
0
      lp->type = LOOP_RESCUE;
2315
0
      end = s->pc;
2316
0
      noexc = genjmp_0(s, OP_JMP);
2317
0
      catch_handler_set(s, catch_entry, MRB_CATCH_RESCUE, begin, end, s->pc);
2318
0
      tree = tree->cdr;
2319
0
      exend = JMPLINK_START;
2320
0
      pos1 = JMPLINK_START;
2321
0
      if (tree->car) {
2322
0
        node *n2 = tree->car;
2323
0
        int exc = cursp();
2324
2325
0
        genop_1(s, OP_EXCEPT, exc);
2326
0
        push();
2327
0
        while (n2) {
2328
0
          node *n3 = n2->car;
2329
0
          node *n4 = n3->car;
2330
2331
0
          dispatch(s, pos1);
2332
0
          pos2 = JMPLINK_START;
2333
0
          do {
2334
0
            if (n4 && n4->car && nint(n4->car->car) == NODE_SPLAT) {
2335
0
              codegen(s, n4->car, VAL);
2336
0
              gen_move(s, cursp(), exc, 0);
2337
0
              push_n(2); pop_n(2); /* space for one arg and a block */
2338
0
              pop();
2339
0
              genop_3(s, OP_SEND, cursp(), new_sym(s, MRB_SYM_2(s->mrb, __case_eqq)), 1);
2340
0
            }
2341
0
            else {
2342
0
              if (n4) {
2343
0
                codegen(s, n4->car, VAL);
2344
0
              }
2345
0
              else {
2346
0
                genop_2(s, OP_GETCONST, cursp(), new_sym(s, MRB_SYM_2(s->mrb, StandardError)));
2347
0
                push();
2348
0
              }
2349
0
              pop();
2350
0
              genop_2(s, OP_RESCUE, exc, cursp());
2351
0
            }
2352
0
            tmp = genjmp2(s, OP_JMPIF, cursp(), pos2, val);
2353
0
            pos2 = tmp;
2354
0
            if (n4) {
2355
0
              n4 = n4->cdr;
2356
0
            }
2357
0
          } while (n4);
2358
0
          pos1 = genjmp_0(s, OP_JMP);
2359
0
          dispatch_linked(s, pos2);
2360
2361
0
          pop();
2362
0
          if (n3->cdr->car) {
2363
0
            gen_assignment(s, n3->cdr->car, NULL, exc, NOVAL);
2364
0
          }
2365
0
          if (n3->cdr->cdr->car) {
2366
0
            codegen(s, n3->cdr->cdr->car, val);
2367
0
            if (val) pop();
2368
0
          }
2369
0
          tmp = genjmp(s, OP_JMP, exend);
2370
0
          exend = tmp;
2371
0
          n2 = n2->cdr;
2372
0
          push();
2373
0
        }
2374
0
        if (pos1 != JMPLINK_START) {
2375
0
          dispatch(s, pos1);
2376
0
          genop_1(s, OP_RAISEIF, exc);
2377
0
        }
2378
0
      }
2379
0
      pop();
2380
0
      tree = tree->cdr;
2381
0
      dispatch(s, noexc);
2382
0
      if (tree->car) {
2383
0
        codegen(s, tree->car, val);
2384
0
      }
2385
0
      else if (val) {
2386
0
        push();
2387
0
      }
2388
0
      dispatch_linked(s, exend);
2389
0
      loop_pop(s, NOVAL);
2390
0
    }
2391
0
    break;
2392
2393
0
  case NODE_ENSURE:
2394
0
    if (!tree->cdr || !tree->cdr->cdr ||
2395
0
        (nint(tree->cdr->cdr->car) == NODE_BEGIN &&
2396
0
         tree->cdr->cdr->cdr)) {
2397
0
      int catch_entry, begin, end, target;
2398
0
      int idx;
2399
2400
0
      catch_entry = catch_handler_new(s);
2401
0
      begin = s->pc;
2402
0
      codegen(s, tree->car, val);
2403
0
      end = target = s->pc;
2404
0
      push();
2405
0
      idx = cursp();
2406
0
      genop_1(s, OP_EXCEPT, idx);
2407
0
      push();
2408
0
      codegen(s, tree->cdr->cdr, NOVAL);
2409
0
      pop();
2410
0
      genop_1(s, OP_RAISEIF, idx);
2411
0
      pop();
2412
0
      catch_handler_set(s, catch_entry, MRB_CATCH_ENSURE, begin, end, target);
2413
0
    }
2414
0
    else {                      /* empty ensure ignored */
2415
0
      codegen(s, tree->car, val);
2416
0
    }
2417
0
    break;
2418
2419
0
  case NODE_LAMBDA:
2420
0
    if (val) {
2421
0
      int idx = lambda_body(s, tree, 1);
2422
2423
0
      genop_2(s, OP_LAMBDA, cursp(), idx);
2424
0
      push();
2425
0
    }
2426
0
    break;
2427
2428
0
  case NODE_BLOCK:
2429
0
    if (val) {
2430
0
      int idx = lambda_body(s, tree, 1);
2431
2432
0
      genop_2(s, OP_BLOCK, cursp(), idx);
2433
0
      push();
2434
0
    }
2435
0
    break;
2436
2437
24.9k
  case NODE_IF:
2438
24.9k
    {
2439
24.9k
      uint32_t pos1, pos2;
2440
24.9k
      mrb_bool nil_p = FALSE;
2441
24.9k
      node *elsepart = tree->cdr->cdr->car;
2442
2443
24.9k
      if (!tree->car) {
2444
0
        codegen(s, elsepart, val);
2445
0
        goto exit;
2446
0
      }
2447
24.9k
      if (true_always(tree->car)) {
2448
10.6k
        codegen(s, tree->cdr->car, val);
2449
10.6k
        goto exit;
2450
10.6k
      }
2451
14.3k
      if (false_always(tree->car)) {
2452
0
        codegen(s, elsepart, val);
2453
0
        goto exit;
2454
0
      }
2455
14.3k
      if (nint(tree->car->car) == NODE_CALL) {
2456
0
        node *n = tree->car->cdr;
2457
0
        mrb_sym mid = nsym(n->cdr->car);
2458
0
        mrb_sym sym_nil_p = MRB_SYM_Q_2(s->mrb, nil);
2459
0
        if (mid == sym_nil_p && n->cdr->cdr->car == NULL) {
2460
0
          nil_p = TRUE;
2461
0
          codegen(s, n->car, VAL);
2462
0
        }
2463
0
      }
2464
14.3k
      if (!nil_p) {
2465
14.3k
        codegen(s, tree->car, VAL);
2466
14.3k
      }
2467
14.3k
      pop();
2468
14.3k
      if (val || tree->cdr->car) {
2469
14.3k
        if (nil_p) {
2470
0
          pos2 = genjmp2_0(s, OP_JMPNIL, cursp(), val);
2471
0
          pos1 = genjmp_0(s, OP_JMP);
2472
0
          dispatch(s, pos2);
2473
0
        }
2474
14.3k
        else {
2475
14.3k
          pos1 = genjmp2_0(s, OP_JMPNOT, cursp(), val);
2476
14.3k
        }
2477
14.3k
        codegen(s, tree->cdr->car, val);
2478
14.3k
        if (val) pop();
2479
14.3k
        if (elsepart || val) {
2480
14.3k
          pos2 = genjmp_0(s, OP_JMP);
2481
14.3k
          dispatch(s, pos1);
2482
14.3k
          codegen(s, elsepart, val);
2483
14.3k
          dispatch(s, pos2);
2484
14.3k
        }
2485
4
        else {
2486
4
          dispatch(s, pos1);
2487
4
        }
2488
14.3k
      }
2489
0
      else {                    /* empty then-part */
2490
0
        if (elsepart) {
2491
0
          if (nil_p) {
2492
0
            pos1 = genjmp2_0(s, OP_JMPNIL, cursp(), val);
2493
0
          }
2494
0
          else {
2495
0
            pos1 = genjmp2_0(s, OP_JMPIF, cursp(), val);
2496
0
          }
2497
0
          codegen(s, elsepart, val);
2498
0
          dispatch(s, pos1);
2499
0
        }
2500
0
        else if (val && !nil_p) {
2501
0
          genop_1(s, OP_LOADNIL, cursp());
2502
0
          push();
2503
0
        }
2504
0
      }
2505
14.3k
    }
2506
0
    break;
2507
2508
4.33k
  case NODE_AND:
2509
4.33k
    {
2510
4.33k
      uint32_t pos;
2511
2512
4.33k
      if (true_always(tree->car)) {
2513
739
        codegen(s, tree->cdr, val);
2514
739
        goto exit;
2515
739
      }
2516
3.59k
      if (false_always(tree->car)) {
2517
0
        codegen(s, tree->car, val);
2518
0
        goto exit;
2519
0
      }
2520
3.59k
      codegen(s, tree->car, VAL);
2521
3.59k
      pop();
2522
3.59k
      pos = genjmp2_0(s, OP_JMPNOT, cursp(), val);
2523
3.59k
      codegen(s, tree->cdr, val);
2524
3.59k
      dispatch(s, pos);
2525
3.59k
    }
2526
0
    break;
2527
2528
1.78k
  case NODE_OR:
2529
1.78k
    {
2530
1.78k
      uint32_t pos;
2531
2532
1.78k
      if (true_always(tree->car)) {
2533
376
        codegen(s, tree->car, val);
2534
376
        goto exit;
2535
376
      }
2536
1.40k
      if (false_always(tree->car)) {
2537
0
        codegen(s, tree->cdr, val);
2538
0
        goto exit;
2539
0
      }
2540
1.40k
      codegen(s, tree->car, VAL);
2541
1.40k
      pop();
2542
1.40k
      pos = genjmp2_0(s, OP_JMPIF, cursp(), val);
2543
1.40k
      codegen(s, tree->cdr, val);
2544
1.40k
      dispatch(s, pos);
2545
1.40k
    }
2546
0
    break;
2547
2548
0
  case NODE_WHILE:
2549
0
  case NODE_UNTIL:
2550
0
    {
2551
0
      if (true_always(tree->car)) {
2552
0
        if (nt == NODE_UNTIL) {
2553
0
          if (val) {
2554
0
            genop_1(s, OP_LOADNIL, cursp());
2555
0
            push();
2556
0
          }
2557
0
          goto exit;
2558
0
        }
2559
0
      }
2560
0
      else if (false_always(tree->car)) {
2561
0
        if (nt == NODE_WHILE) {
2562
0
          if (val) {
2563
0
            genop_1(s, OP_LOADNIL, cursp());
2564
0
            push();
2565
0
          }
2566
0
          goto exit;
2567
0
        }
2568
0
      }
2569
2570
0
      uint32_t pos = JMPLINK_START;
2571
0
      struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
2572
2573
0
      if (!val) lp->reg = -1;
2574
0
      lp->pc0 = new_label(s);
2575
0
      codegen(s, tree->car, VAL);
2576
0
      pop();
2577
0
      if (nt == NODE_WHILE) {
2578
0
        pos = genjmp2_0(s, OP_JMPNOT, cursp(), NOVAL);
2579
0
      }
2580
0
      else {
2581
0
        pos = genjmp2_0(s, OP_JMPIF, cursp(), NOVAL);
2582
0
      }
2583
0
      lp->pc1 = new_label(s);
2584
0
      codegen(s, tree->cdr, NOVAL);
2585
0
      genjmp(s, OP_JMP, lp->pc0);
2586
0
      dispatch(s, pos);
2587
0
      loop_pop(s, val);
2588
0
    }
2589
0
    break;
2590
2591
0
  case NODE_FOR:
2592
0
    for_body(s, tree);
2593
0
    if (val) push();
2594
0
    break;
2595
2596
0
  case NODE_CASE:
2597
0
    {
2598
0
      int head = 0;
2599
0
      uint32_t pos1, pos2, pos3, tmp;
2600
0
      node *n;
2601
2602
0
      pos3 = JMPLINK_START;
2603
0
      if (tree->car) {
2604
0
        head = cursp();
2605
0
        codegen(s, tree->car, VAL);
2606
0
      }
2607
0
      tree = tree->cdr;
2608
0
      while (tree) {
2609
0
        n = tree->car->car;
2610
0
        pos1 = pos2 = JMPLINK_START;
2611
0
        while (n) {
2612
0
          codegen(s, n->car, VAL);
2613
0
          if (head) {
2614
0
            gen_move(s, cursp(), head, 0);
2615
0
            push(); push(); pop(); pop(); pop();
2616
0
            if (nint(n->car->car) == NODE_SPLAT) {
2617
0
              genop_3(s, OP_SEND, cursp(), new_sym(s, MRB_SYM_2(s->mrb, __case_eqq)), 1);
2618
0
            }
2619
0
            else {
2620
0
              genop_3(s, OP_SEND, cursp(), new_sym(s, MRB_OPSYM_2(s->mrb, eqq)), 1);
2621
0
            }
2622
0
          }
2623
0
          else {
2624
0
            pop();
2625
0
          }
2626
0
          tmp = genjmp2(s, OP_JMPIF, cursp(), pos2, !head);
2627
0
          pos2 = tmp;
2628
0
          n = n->cdr;
2629
0
        }
2630
0
        if (tree->car->car) {
2631
0
          pos1 = genjmp_0(s, OP_JMP);
2632
0
          dispatch_linked(s, pos2);
2633
0
        }
2634
0
        codegen(s, tree->car->cdr, val);
2635
0
        if (val) pop();
2636
0
        tmp = genjmp(s, OP_JMP, pos3);
2637
0
        pos3 = tmp;
2638
0
        dispatch(s, pos1);
2639
0
        tree = tree->cdr;
2640
0
      }
2641
0
      if (val) {
2642
0
        uint32_t pos = cursp();
2643
0
        genop_1(s, OP_LOADNIL, cursp());
2644
0
        if (pos3 != JMPLINK_START) dispatch_linked(s, pos3);
2645
0
        if (head) pop();
2646
0
        if (cursp() != pos) {
2647
0
          gen_move(s, cursp(), pos, 0);
2648
0
        }
2649
0
        push();
2650
0
      }
2651
0
      else {
2652
0
        if (pos3 != JMPLINK_START) {
2653
0
          dispatch_linked(s, pos3);
2654
0
        }
2655
0
        if (head) {
2656
0
          pop();
2657
0
        }
2658
0
      }
2659
0
    }
2660
0
    break;
2661
2662
466
  case NODE_SCOPE:
2663
466
    scope_body(s, tree, NOVAL);
2664
466
    break;
2665
2666
394
  case NODE_FCALL:
2667
154k
  case NODE_CALL:
2668
154k
    gen_call(s, tree, val, 0);
2669
154k
    break;
2670
0
  case NODE_SCALL:
2671
0
    gen_call(s, tree, val, 1);
2672
0
    break;
2673
2674
0
  case NODE_DOT2:
2675
0
    codegen(s, tree->car, val);
2676
0
    codegen(s, tree->cdr, val);
2677
0
    if (val) {
2678
0
      pop(); pop();
2679
0
      genop_1(s, OP_RANGE_INC, cursp());
2680
0
      push();
2681
0
    }
2682
0
    break;
2683
2684
0
  case NODE_DOT3:
2685
0
    codegen(s, tree->car, val);
2686
0
    codegen(s, tree->cdr, val);
2687
0
    if (val) {
2688
0
      pop(); pop();
2689
0
      genop_1(s, OP_RANGE_EXC, cursp());
2690
0
      push();
2691
0
    }
2692
0
    break;
2693
2694
774
  case NODE_COLON2:
2695
774
    {
2696
774
      int sym = new_sym(s, nsym(tree->cdr));
2697
2698
774
      codegen(s, tree->car, VAL);
2699
774
      pop();
2700
774
      genop_2(s, OP_GETMCNST, cursp(), sym);
2701
774
      if (val) push();
2702
774
    }
2703
774
    break;
2704
2705
0
  case NODE_COLON3:
2706
0
    {
2707
0
      int sym = new_sym(s, nsym(tree));
2708
2709
0
      genop_1(s, OP_OCLASS, cursp());
2710
0
      genop_2(s, OP_GETMCNST, cursp(), sym);
2711
0
      if (val) push();
2712
0
    }
2713
0
    break;
2714
2715
46.4k
  case NODE_ARRAY:
2716
46.4k
    {
2717
46.4k
      int n;
2718
2719
46.4k
      n = gen_values(s, tree, val, 0);
2720
46.4k
      if (val) {
2721
46.4k
        if (n >= 0) {
2722
44.2k
          pop_n(n);
2723
44.2k
          genop_2(s, OP_ARRAY, cursp(), n);
2724
44.2k
        }
2725
46.4k
        push();
2726
46.4k
      }
2727
46.4k
    }
2728
46.4k
    break;
2729
2730
2.01k
  case NODE_HASH:
2731
2.01k
  case NODE_KW_HASH:
2732
2.01k
    {
2733
2.01k
      int nk = gen_hash(s, tree, val, GEN_LIT_ARY_MAX);
2734
2.01k
      if (val && nk >= 0) {
2735
1.48k
        pop_n(nk*2);
2736
1.48k
        genop_2(s, OP_HASH, cursp(), nk);
2737
1.48k
        push();
2738
1.48k
      }
2739
2.01k
    }
2740
2.01k
    break;
2741
2742
0
  case NODE_SPLAT:
2743
0
    codegen(s, tree, val);
2744
0
    break;
2745
2746
119k
  case NODE_ASGN:
2747
119k
    gen_assignment(s, tree->car, tree->cdr, 0, val);
2748
119k
    break;
2749
2750
0
  case NODE_MASGN:
2751
0
    {
2752
0
      int len = 0, n = 0, post = 0;
2753
0
      node *t = tree->cdr, *p;
2754
0
      int rhs = cursp();
2755
2756
0
      if (!val && nint(t->car) == NODE_ARRAY && t->cdr && nosplat(t->cdr)) {
2757
        /* fixed rhs */
2758
0
        t = t->cdr;
2759
0
        while (t) {
2760
0
          codegen(s, t->car, VAL);
2761
0
          len++;
2762
0
          t = t->cdr;
2763
0
        }
2764
0
        tree = tree->car;
2765
0
        if (tree->car) {                /* pre */
2766
0
          t = tree->car;
2767
0
          n = 0;
2768
0
          while (t) {
2769
0
            if (n < len) {
2770
0
              gen_assignment(s, t->car, NULL, rhs+n, NOVAL);
2771
0
              n++;
2772
0
            }
2773
0
            else {
2774
0
              genop_1(s, OP_LOADNIL, rhs+n);
2775
0
              gen_assignment(s, t->car, NULL, rhs+n, NOVAL);
2776
0
            }
2777
0
            t = t->cdr;
2778
0
          }
2779
0
        }
2780
0
        t = tree->cdr;
2781
0
        if (t) {
2782
0
          if (t->cdr) {         /* post count */
2783
0
            p = t->cdr->car;
2784
0
            while (p) {
2785
0
              post++;
2786
0
              p = p->cdr;
2787
0
            }
2788
0
          }
2789
0
          if (t->car) {         /* rest (len - pre - post) */
2790
0
            int rn;
2791
2792
0
            if (len < post + n) {
2793
0
              rn = 0;
2794
0
            }
2795
0
            else {
2796
0
              rn = len - post - n;
2797
0
            }
2798
0
            if (cursp() == rhs+n) {
2799
0
              genop_2(s, OP_ARRAY, cursp(), rn);
2800
0
            }
2801
0
            else {
2802
0
              genop_3(s, OP_ARRAY2, cursp(), rhs+n, rn);
2803
0
            }
2804
0
            gen_assignment(s, t->car, NULL, cursp(), NOVAL);
2805
0
            n += rn;
2806
0
          }
2807
0
          if (t->cdr && t->cdr->car) {
2808
0
            t = t->cdr->car;
2809
0
            while (t) {
2810
0
              if (n<len) {
2811
0
                gen_assignment(s, t->car, NULL, rhs+n, NOVAL);
2812
0
              }
2813
0
              else {
2814
0
                genop_1(s, OP_LOADNIL, cursp());
2815
0
                gen_assignment(s, t->car, NULL, cursp(), NOVAL);
2816
0
              }
2817
0
              t = t->cdr;
2818
0
              n++;
2819
0
            }
2820
0
          }
2821
0
        }
2822
0
        pop_n(len);
2823
0
      }
2824
0
      else {
2825
        /* variable rhs */
2826
0
        codegen(s, t, VAL);
2827
0
        gen_massignment(s, tree->car, rhs, val);
2828
0
        if (!val) {
2829
0
          pop();
2830
0
        }
2831
0
      }
2832
0
    }
2833
0
    break;
2834
2835
20.1k
  case NODE_OP_ASGN:
2836
20.1k
    {
2837
20.1k
      mrb_sym sym = nsym(tree->cdr->car);
2838
20.1k
      mrb_int len;
2839
20.1k
      const char *name = mrb_sym_name_len(s->mrb, sym, &len);
2840
20.1k
      int idx, callargs = -1, vsp = -1;
2841
2842
20.1k
      if ((len == 2 && name[0] == '|' && name[1] == '|') &&
2843
20.1k
          (nint(tree->car->car) == NODE_CONST ||
2844
20.1k
           nint(tree->car->car) == NODE_CVAR)) {
2845
0
        int catch_entry, begin, end;
2846
0
        int noexc, exc;
2847
0
        struct loopinfo *lp;
2848
2849
0
        lp = loop_push(s, LOOP_BEGIN);
2850
0
        lp->pc0 = new_label(s);
2851
0
        catch_entry = catch_handler_new(s);
2852
0
        begin = s->pc;
2853
0
        exc = cursp();
2854
0
        codegen(s, tree->car, VAL);
2855
0
        end = s->pc;
2856
0
        noexc = genjmp_0(s, OP_JMP);
2857
0
        lp->type = LOOP_RESCUE;
2858
0
        catch_handler_set(s, catch_entry, MRB_CATCH_RESCUE, begin, end, s->pc);
2859
0
        genop_1(s, OP_EXCEPT, exc);
2860
0
        genop_1(s, OP_LOADF, exc);
2861
0
        dispatch(s, noexc);
2862
0
        loop_pop(s, NOVAL);
2863
0
      }
2864
20.1k
      else if (nint(tree->car->car) == NODE_CALL) {
2865
0
        node *n = tree->car->cdr;
2866
0
        int base, i, nargs = 0;
2867
0
        callargs = 0;
2868
2869
0
        if (val) {
2870
0
          vsp = cursp();
2871
0
          push();
2872
0
        }
2873
0
        codegen(s, n->car, VAL);   /* receiver */
2874
0
        idx = new_sym(s, nsym(n->cdr->car));
2875
0
        base = cursp()-1;
2876
0
        if (n->cdr->cdr->car) {
2877
0
          nargs = gen_values(s, n->cdr->cdr->car->car, VAL, 13);
2878
0
          if (nargs >= 0) {
2879
0
            callargs = nargs;
2880
0
          }
2881
0
          else { /* varargs */
2882
0
            push();
2883
0
            nargs = 1;
2884
0
            callargs = CALL_MAXARGS;
2885
0
          }
2886
0
        }
2887
        /* copy receiver and arguments */
2888
0
        gen_move(s, cursp(), base, 1);
2889
0
        for (i=0; i<nargs; i++) {
2890
0
          gen_move(s, cursp()+i+1, base+i+1, 1);
2891
0
        }
2892
0
        push_n(nargs+2);pop_n(nargs+2); /* space for receiver, arguments and a block */
2893
0
        genop_3(s, OP_SEND, cursp(), idx, callargs);
2894
0
        push();
2895
0
      }
2896
20.1k
      else {
2897
20.1k
        codegen(s, tree->car, VAL);
2898
20.1k
      }
2899
20.1k
      if (len == 2 &&
2900
20.1k
          ((name[0] == '|' && name[1] == '|') ||
2901
20.1k
           (name[0] == '&' && name[1] == '&'))) {
2902
20.1k
        uint32_t pos;
2903
2904
20.1k
        pop();
2905
20.1k
        if (val) {
2906
6.51k
          if (vsp >= 0) {
2907
0
            gen_move(s, vsp, cursp(), 1);
2908
0
          }
2909
6.51k
          pos = genjmp2_0(s, name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), val);
2910
6.51k
        }
2911
13.6k
        else {
2912
13.6k
          pos = genjmp2_0(s, name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), val);
2913
13.6k
        }
2914
20.1k
        codegen(s, tree->cdr->cdr->car, VAL);
2915
20.1k
        pop();
2916
20.1k
        if (val && vsp >= 0) {
2917
0
          gen_move(s, vsp, cursp(), 1);
2918
0
        }
2919
20.1k
        if (nint(tree->car->car) == NODE_CALL) {
2920
0
          if (callargs == CALL_MAXARGS) {
2921
0
            pop();
2922
0
            genop_2(s, OP_ARYPUSH, cursp(), 1);
2923
0
          }
2924
0
          else {
2925
0
            pop_n(callargs);
2926
0
            callargs++;
2927
0
          }
2928
0
          pop();
2929
0
          idx = new_sym(s, attrsym(s, nsym(tree->car->cdr->cdr->car)));
2930
0
          genop_3(s, OP_SEND, cursp(), idx, callargs);
2931
0
        }
2932
20.1k
        else {
2933
20.1k
          gen_assignment(s, tree->car, NULL, cursp(), val);
2934
20.1k
        }
2935
20.1k
        dispatch(s, pos);
2936
20.1k
        goto exit;
2937
20.1k
      }
2938
0
      codegen(s, tree->cdr->cdr->car, VAL);
2939
0
      push(); pop();
2940
0
      pop(); pop();
2941
2942
0
      if (len == 1 && name[0] == '+')  {
2943
0
        gen_addsub(s, OP_ADD, cursp());
2944
0
      }
2945
0
      else if (len == 1 && name[0] == '-')  {
2946
0
        gen_addsub(s, OP_SUB, cursp());
2947
0
      }
2948
0
      else if (len == 1 && name[0] == '*')  {
2949
0
        genop_1(s, OP_MUL, cursp());
2950
0
      }
2951
0
      else if (len == 1 && name[0] == '/')  {
2952
0
        genop_1(s, OP_DIV, cursp());
2953
0
      }
2954
0
      else if (len == 1 && name[0] == '<')  {
2955
0
        genop_1(s, OP_LT, cursp());
2956
0
      }
2957
0
      else if (len == 2 && name[0] == '<' && name[1] == '=')  {
2958
0
        genop_1(s, OP_LE, cursp());
2959
0
      }
2960
0
      else if (len == 1 && name[0] == '>')  {
2961
0
        genop_1(s, OP_GT, cursp());
2962
0
      }
2963
0
      else if (len == 2 && name[0] == '>' && name[1] == '=')  {
2964
0
        genop_1(s, OP_GE, cursp());
2965
0
      }
2966
0
      else {
2967
0
        idx = new_sym(s, sym);
2968
0
        genop_3(s, OP_SEND, cursp(), idx, 1);
2969
0
      }
2970
0
      if (callargs < 0) {
2971
0
        gen_assignment(s, tree->car, NULL, cursp(), val);
2972
0
      }
2973
0
      else {
2974
0
        if (val && vsp >= 0) {
2975
0
          gen_move(s, vsp, cursp(), 0);
2976
0
        }
2977
0
        if (callargs == CALL_MAXARGS) {
2978
0
          pop();
2979
0
          genop_2(s, OP_ARYPUSH, cursp(), 1);
2980
0
        }
2981
0
        else {
2982
0
          pop_n(callargs);
2983
0
          callargs++;
2984
0
        }
2985
0
        pop();
2986
0
        idx = new_sym(s, attrsym(s,nsym(tree->car->cdr->cdr->car)));
2987
0
        genop_3(s, OP_SEND, cursp(), idx, callargs);
2988
0
      }
2989
0
    }
2990
0
    break;
2991
2992
0
  case NODE_SUPER:
2993
0
    {
2994
0
      codegen_scope *s2 = s;
2995
0
      int lv = 0;
2996
0
      int n = 0, nk = 0, st = 0;
2997
2998
0
      push();
2999
0
      while (!s2->mscope) {
3000
0
        lv++;
3001
0
        s2 = s2->prev;
3002
0
        if (!s2) break;
3003
0
      }
3004
0
      if (tree) {
3005
0
        node *args = tree->car;
3006
0
        if (args) {
3007
0
          st = n = gen_values(s, args, VAL, 14);
3008
0
          if (n < 0) {
3009
0
            st = 1; n = 15;
3010
0
            push();
3011
0
          }
3012
0
        }
3013
        /* keyword arguments */
3014
0
        if (tree->cdr->car) {
3015
0
          nk = gen_hash(s, tree->cdr->car->cdr, VAL, 14);
3016
0
          if (nk < 0) {st++; nk = 15;}
3017
0
          else st += nk*2;
3018
0
          n |= nk<<4;
3019
0
        }
3020
        /* block arguments */
3021
0
        if (tree->cdr->cdr) {
3022
0
          codegen(s, tree->cdr->cdr, VAL);
3023
0
        }
3024
0
        else if (s2) gen_blkmove(s, s2->ainfo, lv);
3025
0
        else {
3026
0
          genop_1(s, OP_LOADNIL, cursp());
3027
0
          push();
3028
0
        }
3029
0
      }
3030
0
      else {
3031
0
        if (s2) gen_blkmove(s, s2->ainfo, lv);
3032
0
        else {
3033
0
          genop_1(s, OP_LOADNIL, cursp());
3034
0
          push();
3035
0
        }
3036
0
      }
3037
0
      st++;
3038
0
      pop_n(st+1);
3039
0
      genop_2(s, OP_SUPER, cursp(), n);
3040
0
      if (val) push();
3041
0
    }
3042
0
    break;
3043
3044
0
  case NODE_ZSUPER:
3045
0
    {
3046
0
      codegen_scope *s2 = s;
3047
0
      int lv = 0;
3048
0
      uint16_t ainfo = 0;
3049
0
      int n = CALL_MAXARGS;
3050
0
      int sp = cursp();
3051
3052
0
      push();        /* room for receiver */
3053
0
      while (!s2->mscope) {
3054
0
        lv++;
3055
0
        s2 = s2->prev;
3056
0
        if (!s2) break;
3057
0
      }
3058
0
      if (s2 && s2->ainfo > 0) {
3059
0
        ainfo = s2->ainfo;
3060
0
      }
3061
0
      if (ainfo > 0) {
3062
0
        genop_2S(s, OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf));
3063
0
        push(); push(); push();   /* ARGARY pushes 3 values at most */
3064
0
        pop(); pop(); pop();
3065
        /* keyword arguments */
3066
0
        if (ainfo & 0x1) {
3067
0
          n |= CALL_MAXARGS<<4;
3068
0
          push();
3069
0
        }
3070
        /* block argument */
3071
0
        if (tree && tree->cdr && tree->cdr->cdr) {
3072
0
          push();
3073
0
          codegen(s, tree->cdr->cdr, VAL);
3074
0
        }
3075
0
      }
3076
0
      else {
3077
        /* block argument */
3078
0
        if (tree && tree->cdr && tree->cdr->cdr) {
3079
0
          codegen(s, tree->cdr->cdr, VAL);
3080
0
        }
3081
0
        else {
3082
0
          gen_blkmove(s, 0, lv);
3083
0
        }
3084
0
        n = 0;
3085
0
      }
3086
0
      s->sp = sp;
3087
0
      genop_2(s, OP_SUPER, cursp(), n);
3088
0
      if (val) push();
3089
0
    }
3090
0
    break;
3091
3092
0
  case NODE_RETURN:
3093
0
    if (tree) {
3094
0
      gen_retval(s, tree);
3095
0
    }
3096
0
    else {
3097
0
      genop_1(s, OP_LOADNIL, cursp());
3098
0
    }
3099
0
    if (s->loop) {
3100
0
      gen_return(s, OP_RETURN_BLK, cursp());
3101
0
    }
3102
0
    else {
3103
0
      gen_return(s, OP_RETURN, cursp());
3104
0
    }
3105
0
    if (val) push();
3106
0
    break;
3107
3108
0
  case NODE_YIELD:
3109
0
    {
3110
0
      codegen_scope *s2 = s;
3111
0
      int lv = 0, ainfo = -1;
3112
0
      int n = 0, sendv = 0;
3113
3114
0
      while (!s2->mscope) {
3115
0
        lv++;
3116
0
        s2 = s2->prev;
3117
0
        if (!s2) break;
3118
0
      }
3119
0
      if (s2) {
3120
0
        ainfo = (int)s2->ainfo;
3121
0
      }
3122
0
      if (ainfo < 0) codegen_error(s, "invalid yield (SyntaxError)");
3123
0
      push();
3124
0
      if (tree) {
3125
0
        n = gen_values(s, tree, VAL, 14);
3126
0
        if (n < 0) {
3127
0
          n = sendv = 1;
3128
0
          push();
3129
0
        }
3130
0
      }
3131
0
      push();pop(); /* space for a block */
3132
0
      pop_n(n+1);
3133
0
      genop_2S(s, OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf));
3134
0
      if (sendv) n = CALL_MAXARGS;
3135
0
      genop_3(s, OP_SEND, cursp(), new_sym(s, MRB_SYM_2(s->mrb, call)), n);
3136
0
      if (val) push();
3137
0
    }
3138
0
    break;
3139
3140
0
  case NODE_BREAK:
3141
0
    loop_break(s, tree);
3142
0
    if (val) push();
3143
0
    break;
3144
3145
0
  case NODE_NEXT:
3146
0
    if (!s->loop) {
3147
0
      raise_error(s, "unexpected next");
3148
0
    }
3149
0
    else if (s->loop->type == LOOP_NORMAL) {
3150
0
      codegen(s, tree, NOVAL);
3151
0
      genjmp(s, OP_JMPUW, s->loop->pc0);
3152
0
    }
3153
0
    else {
3154
0
      if (tree) {
3155
0
        codegen(s, tree, VAL);
3156
0
        pop();
3157
0
      }
3158
0
      else {
3159
0
        genop_1(s, OP_LOADNIL, cursp());
3160
0
      }
3161
0
      gen_return(s, OP_RETURN, cursp());
3162
0
    }
3163
0
    if (val) push();
3164
0
    break;
3165
3166
0
  case NODE_REDO:
3167
0
    if (!s->loop || s->loop->type == LOOP_BEGIN || s->loop->type == LOOP_RESCUE) {
3168
0
      raise_error(s, "unexpected redo");
3169
0
    }
3170
0
    else {
3171
0
      genjmp(s, OP_JMPUW, s->loop->pc1);
3172
0
    }
3173
0
    if (val) push();
3174
0
    break;
3175
3176
0
  case NODE_RETRY:
3177
0
    {
3178
0
      const char *msg = "unexpected retry";
3179
0
      const struct loopinfo *lp = s->loop;
3180
3181
0
      while (lp && lp->type != LOOP_RESCUE) {
3182
0
        lp = lp->prev;
3183
0
      }
3184
0
      if (!lp) {
3185
0
        raise_error(s, msg);
3186
0
      }
3187
0
      else {
3188
0
        genjmp(s, OP_JMPUW, lp->pc0);
3189
0
      }
3190
0
      if (val) push();
3191
0
    }
3192
0
    break;
3193
3194
57.3k
  case NODE_LVAR:
3195
57.3k
    if (val) {
3196
56.6k
      int idx = lv_idx(s, nsym(tree));
3197
3198
56.6k
      if (idx > 0) {
3199
56.6k
        gen_move(s, cursp(), idx, val);
3200
56.6k
      }
3201
0
      else {
3202
0
        gen_getupvar(s, cursp(), nsym(tree));
3203
0
      }
3204
56.6k
      push();
3205
56.6k
    }
3206
57.3k
    break;
3207
3208
0
  case NODE_NVAR:
3209
0
    if (val) {
3210
0
      int idx = nint(tree);
3211
3212
0
      gen_move(s, cursp(), idx, val);
3213
3214
0
      push();
3215
0
    }
3216
0
    break;
3217
3218
0
  case NODE_GVAR:
3219
0
    {
3220
0
      int sym = new_sym(s, nsym(tree));
3221
3222
0
      genop_2(s, OP_GETGV, cursp(), sym);
3223
0
      if (val) push();
3224
0
    }
3225
0
    break;
3226
3227
20.1k
  case NODE_IVAR:
3228
20.1k
    {
3229
20.1k
      int sym = new_sym(s, nsym(tree));
3230
3231
20.1k
      genop_2(s, OP_GETIV, cursp(), sym);
3232
20.1k
      if (val) push();
3233
20.1k
    }
3234
20.1k
    break;
3235
3236
0
  case NODE_CVAR:
3237
0
    {
3238
0
      int sym = new_sym(s, nsym(tree));
3239
3240
0
      genop_2(s, OP_GETCV, cursp(), sym);
3241
0
      if (val) push();
3242
0
    }
3243
0
    break;
3244
3245
19.8k
  case NODE_CONST:
3246
19.8k
    {
3247
19.8k
      int sym = new_sym(s, nsym(tree));
3248
3249
19.8k
      genop_2(s, OP_GETCONST, cursp(), sym);
3250
19.8k
      if (val) push();
3251
19.8k
    }
3252
19.8k
    break;
3253
3254
0
  case NODE_BACK_REF:
3255
0
    if (val) {
3256
0
      char buf[] = {'$', nchar(tree)};
3257
0
      int sym = new_sym(s, mrb_intern(s->mrb, buf, sizeof(buf)));
3258
3259
0
      genop_2(s, OP_GETGV, cursp(), sym);
3260
0
      push();
3261
0
    }
3262
0
    break;
3263
3264
0
  case NODE_NTH_REF:
3265
0
    if (val) {
3266
0
      mrb_state *mrb = s->mrb;
3267
0
      mrb_value str;
3268
0
      int sym;
3269
3270
0
      str = mrb_format(mrb, "$%d", nint(tree));
3271
0
      sym = new_sym(s, mrb_intern_str(mrb, str));
3272
0
      genop_2(s, OP_GETGV, cursp(), sym);
3273
0
      push();
3274
0
    }
3275
0
    break;
3276
3277
0
  case NODE_ARG:
3278
    /* should not happen */
3279
0
    break;
3280
3281
0
  case NODE_BLOCK_ARG:
3282
0
    if (!tree) {
3283
0
      int idx = lv_idx(s, MRB_OPSYM_2(s->mrb, and));
3284
3285
0
      if (idx == 0) {
3286
0
        gen_getupvar(s, cursp(), MRB_OPSYM_2(s->mrb, and));
3287
0
      }
3288
0
      else {
3289
0
        gen_move(s, cursp(), idx, val);
3290
0
      }
3291
0
      if (val) push();
3292
0
    }
3293
0
    else {
3294
0
      codegen(s, tree, val);
3295
0
    }
3296
0
    break;
3297
3298
598k
  case NODE_INT:
3299
598k
    if (val) {
3300
575k
      char *p = (char*)tree->car;
3301
575k
      int base = nint(tree->cdr->car);
3302
575k
      mrb_int i;
3303
575k
      mrb_bool overflow;
3304
3305
575k
      i = readint(s, p, base, FALSE, &overflow);
3306
575k
      if (overflow) {
3307
0
        int off = new_litbint(s, p, base, FALSE);
3308
0
        genop_2(s, OP_LOADL, cursp(), off);
3309
0
      }
3310
575k
      else {
3311
575k
        gen_int(s, cursp(), i);
3312
575k
      }
3313
575k
      push();
3314
575k
    }
3315
598k
    break;
3316
3317
0
#ifndef MRB_NO_FLOAT
3318
0
  case NODE_FLOAT:
3319
0
    if (val) {
3320
0
      char *p = (char*)tree;
3321
0
      double f;
3322
0
      mrb_read_float(p, NULL, &f);
3323
0
      int off = new_lit_float(s, (mrb_float)f);
3324
3325
0
      genop_2(s, OP_LOADL, cursp(), off);
3326
0
      push();
3327
0
    }
3328
0
    break;
3329
0
#endif
3330
3331
0
  case NODE_NEGATE:
3332
0
    {
3333
0
      nt = nint(tree->car);
3334
0
      switch (nt) {
3335
0
#ifndef MRB_NO_FLOAT
3336
0
      case NODE_FLOAT:
3337
0
        if (val) {
3338
0
          char *p = (char*)tree->cdr;
3339
0
          double f;
3340
0
          mrb_read_float(p, NULL, &f);
3341
0
          int off = new_lit_float(s, (mrb_float)-f);
3342
3343
0
          genop_2(s, OP_LOADL, cursp(), off);
3344
0
          push();
3345
0
        }
3346
0
        break;
3347
0
#endif
3348
3349
0
      case NODE_INT:
3350
0
        if (val) {
3351
0
          char *p = (char*)tree->cdr->car;
3352
0
          int base = nint(tree->cdr->cdr->car);
3353
0
          mrb_int i;
3354
0
          mrb_bool overflow;
3355
3356
0
          i = readint(s, p, base, TRUE, &overflow);
3357
0
          if (overflow) {
3358
0
            int off = new_litbint(s, p, base, TRUE);
3359
0
            genop_2(s, OP_LOADL, cursp(), off);
3360
0
          }
3361
0
          else {
3362
0
            gen_int(s, cursp(), i);
3363
0
          }
3364
0
          push();
3365
0
        }
3366
0
        break;
3367
3368
0
      default:
3369
0
        if (val) {
3370
0
          codegen(s, tree, VAL);
3371
0
          pop();
3372
0
          push_n(2);pop_n(2); /* space for receiver&block */
3373
0
          mrb_sym minus = MRB_OPSYM_2(s->mrb, minus);
3374
0
          if (!gen_uniop(s, minus, cursp())) {
3375
0
            genop_3(s, OP_SEND, cursp(), new_sym(s, minus), 0);
3376
0
          }
3377
0
          push();
3378
0
        }
3379
0
        else {
3380
0
          codegen(s, tree, NOVAL);
3381
0
        }
3382
0
        break;
3383
0
      }
3384
0
    }
3385
0
    break;
3386
3387
327k
  case NODE_STR:
3388
327k
    if (val) {
3389
327k
      char *p = (char*)tree->car;
3390
327k
      mrb_int len = nint(tree->cdr);
3391
327k
      int off = new_lit_str(s, p, len);
3392
3393
327k
      genop_2(s, OP_STRING, cursp(), off);
3394
327k
      push();
3395
327k
    }
3396
327k
    break;
3397
3398
0
  case NODE_HEREDOC:
3399
0
    tree = ((struct mrb_parser_heredoc_info*)tree)->doc;
3400
    /* fall through */
3401
0
  case NODE_DSTR:
3402
0
    if (val) {
3403
0
      node *n = tree;
3404
3405
0
      if (!n) {
3406
0
        genop_1(s, OP_LOADNIL, cursp());
3407
0
        push();
3408
0
        break;
3409
0
      }
3410
0
      codegen(s, n->car, VAL);
3411
0
      n = n->cdr;
3412
0
      while (n) {
3413
0
        codegen(s, n->car, VAL);
3414
0
        pop(); pop();
3415
0
        genop_1(s, OP_STRCAT, cursp());
3416
0
        push();
3417
0
        n = n->cdr;
3418
0
      }
3419
0
    }
3420
0
    else {
3421
0
      node *n = tree;
3422
3423
0
      while (n) {
3424
0
        if (nint(n->car->car) != NODE_STR) {
3425
0
          codegen(s, n->car, NOVAL);
3426
0
        }
3427
0
        n = n->cdr;
3428
0
      }
3429
0
    }
3430
0
    break;
3431
3432
0
  case NODE_WORDS:
3433
0
    gen_literal_array(s, tree, FALSE, val);
3434
0
    break;
3435
3436
0
  case NODE_SYMBOLS:
3437
0
    gen_literal_array(s, tree, TRUE, val);
3438
0
    break;
3439
3440
0
  case NODE_DXSTR:
3441
0
    {
3442
0
      node *n;
3443
0
      int sym = new_sym(s, MRB_SYM_2(s->mrb, Kernel));
3444
3445
0
      genop_1(s, OP_LOADSELF, cursp());
3446
0
      push();
3447
0
      codegen(s, tree->car, VAL);
3448
0
      n = tree->cdr;
3449
0
      while (n) {
3450
0
        if (nint(n->car->car) == NODE_XSTR) {
3451
0
          n->car->car = (struct mrb_ast_node*)(intptr_t)NODE_STR;
3452
0
          mrb_assert(!n->cdr); /* must be the end */
3453
0
        }
3454
0
        codegen(s, n->car, VAL);
3455
0
        pop(); pop();
3456
0
        genop_1(s, OP_STRCAT, cursp());
3457
0
        push();
3458
0
        n = n->cdr;
3459
0
      }
3460
0
      push();                   /* for block */
3461
0
      pop_n(3);
3462
0
      sym = new_sym(s, MRB_OPSYM_2(s->mrb, tick)); /* ` */
3463
0
      genop_3(s, OP_SEND, cursp(), sym, 1);
3464
0
      if (val) push();
3465
0
    }
3466
0
    break;
3467
3468
0
  case NODE_XSTR:
3469
0
    {
3470
0
      char *p = (char*)tree->car;
3471
0
      mrb_int len = nint(tree->cdr);
3472
0
      int off = new_lit_str(s, p, len);
3473
0
      int sym;
3474
3475
0
      genop_1(s, OP_LOADSELF, cursp());
3476
0
      push();
3477
0
      genop_2(s, OP_STRING, cursp(), off);
3478
0
      push(); push();
3479
0
      pop_n(3);
3480
0
      sym = new_sym(s, MRB_OPSYM_2(s->mrb, tick)); /* ` */
3481
0
      genop_3(s, OP_SEND, cursp(), sym, 1);
3482
0
      if (val) push();
3483
0
    }
3484
0
    break;
3485
3486
0
  case NODE_REGX:
3487
0
    if (val) {
3488
0
      char *p1 = (char*)tree->car;
3489
0
      char *p2 = (char*)tree->cdr->car;
3490
0
      char *p3 = (char*)tree->cdr->cdr;
3491
0
      int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
3492
0
      int off = new_lit_cstr(s, p1);
3493
0
      int argc = 1;
3494
3495
0
      genop_1(s, OP_OCLASS, cursp());
3496
0
      genop_2(s, OP_GETMCNST, cursp(), sym);
3497
0
      push();
3498
0
      genop_2(s, OP_STRING, cursp(), off);
3499
0
      push();
3500
0
      if (p2 || p3) {
3501
0
        if (p2) { /* opt */
3502
0
          off = new_lit_cstr(s, p2);
3503
0
          genop_2(s, OP_STRING, cursp(), off);
3504
0
        }
3505
0
        else {
3506
0
          genop_1(s, OP_LOADNIL, cursp());
3507
0
        }
3508
0
        push();
3509
0
        argc++;
3510
0
        if (p3) { /* enc */
3511
0
          off = new_lit_str(s, p3, 1);
3512
0
          genop_2(s, OP_STRING, cursp(), off);
3513
0
          push();
3514
0
          argc++;
3515
0
        }
3516
0
      }
3517
0
      push(); /* space for a block */
3518
0
      pop_n(argc+2);
3519
0
      sym = new_sym(s, MRB_SYM_2(s->mrb, compile));
3520
0
      genop_3(s, OP_SEND, cursp(), sym, argc);
3521
0
      push();
3522
0
    }
3523
0
    break;
3524
3525
0
  case NODE_DREGX:
3526
0
    if (val) {
3527
0
      node *n = tree->car;
3528
0
      int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
3529
0
      int argc = 1;
3530
0
      int off;
3531
0
      char *p;
3532
3533
0
      genop_1(s, OP_OCLASS, cursp());
3534
0
      genop_2(s, OP_GETMCNST, cursp(), sym);
3535
0
      push();
3536
0
      codegen(s, n->car, VAL);
3537
0
      n = n->cdr;
3538
0
      while (n) {
3539
0
        codegen(s, n->car, VAL);
3540
0
        pop(); pop();
3541
0
        genop_1(s, OP_STRCAT, cursp());
3542
0
        push();
3543
0
        n = n->cdr;
3544
0
      }
3545
0
      n = tree->cdr->cdr;
3546
0
      if (n->car) { /* tail */
3547
0
        p = (char*)n->car;
3548
0
        off = new_lit_cstr(s, p);
3549
0
        codegen(s, tree->car, VAL);
3550
0
        genop_2(s, OP_STRING, cursp(), off);
3551
0
        pop();
3552
0
        genop_1(s, OP_STRCAT, cursp());
3553
0
        push();
3554
0
      }
3555
0
      if (n->cdr->car) { /* opt */
3556
0
        char *p2 = (char*)n->cdr->car;
3557
0
        off = new_lit_cstr(s, p2);
3558
0
        genop_2(s, OP_STRING, cursp(), off);
3559
0
        push();
3560
0
        argc++;
3561
0
      }
3562
0
      if (n->cdr->cdr) { /* enc */
3563
0
        char *p2 = (char*)n->cdr->cdr;
3564
0
        off = new_lit_cstr(s, p2);
3565
0
        genop_2(s, OP_STRING, cursp(), off);
3566
0
        push();
3567
0
        argc++;
3568
0
      }
3569
0
      push(); /* space for a block */
3570
0
      pop_n(argc+2);
3571
0
      sym = new_sym(s, MRB_SYM_2(s->mrb, compile));
3572
0
      genop_3(s, OP_SEND, cursp(), sym, argc);
3573
0
      push();
3574
0
    }
3575
0
    else {
3576
0
      node *n = tree->car;
3577
3578
0
      while (n) {
3579
0
        if (nint(n->car->car) != NODE_STR) {
3580
0
          codegen(s, n->car, NOVAL);
3581
0
        }
3582
0
        n = n->cdr;
3583
0
      }
3584
0
    }
3585
0
    break;
3586
3587
0
  case NODE_SYM:
3588
0
    if (val) {
3589
0
      int sym = new_sym(s, nsym(tree));
3590
3591
0
      genop_2(s, OP_LOADSYM, cursp(), sym);
3592
0
      push();
3593
0
    }
3594
0
    break;
3595
3596
0
  case NODE_DSYM:
3597
0
    codegen(s, tree, val);
3598
0
    if (val) {
3599
0
      gen_intern(s);
3600
0
    }
3601
0
    break;
3602
3603
0
  case NODE_SELF:
3604
0
    if (val) {
3605
0
      genop_1(s, OP_LOADSELF, cursp());
3606
0
      push();
3607
0
    }
3608
0
    break;
3609
3610
0
  case NODE_NIL:
3611
0
    if (val) {
3612
0
      genop_1(s, OP_LOADNIL, cursp());
3613
0
      push();
3614
0
    }
3615
0
    break;
3616
3617
0
  case NODE_TRUE:
3618
0
    if (val) {
3619
0
      genop_1(s, OP_LOADT, cursp());
3620
0
      push();
3621
0
    }
3622
0
    break;
3623
3624
0
  case NODE_FALSE:
3625
0
    if (val) {
3626
0
      genop_1(s, OP_LOADF, cursp());
3627
0
      push();
3628
0
    }
3629
0
    break;
3630
3631
0
  case NODE_ALIAS:
3632
0
    {
3633
0
      int a = new_sym(s, nsym(tree->car));
3634
0
      int b = new_sym(s, nsym(tree->cdr));
3635
3636
0
      genop_2(s, OP_ALIAS, a, b);
3637
0
      if (val) {
3638
0
        genop_1(s, OP_LOADNIL, cursp());
3639
0
        push();
3640
0
      }
3641
0
    }
3642
0
   break;
3643
3644
0
  case NODE_UNDEF:
3645
0
    {
3646
0
      node *t = tree;
3647
3648
0
      while (t) {
3649
0
        int symbol = new_sym(s, nsym(t->car));
3650
0
        genop_1(s, OP_UNDEF, symbol);
3651
0
        t = t->cdr;
3652
0
      }
3653
0
      if (val) {
3654
0
        genop_1(s, OP_LOADNIL, cursp());
3655
0
        push();
3656
0
      }
3657
0
    }
3658
0
    break;
3659
3660
0
  case NODE_CLASS:
3661
0
    {
3662
0
      int idx;
3663
0
      node *body;
3664
3665
0
      if (tree->car->car == (node*)0) {
3666
0
        genop_1(s, OP_LOADNIL, cursp());
3667
0
        push();
3668
0
      }
3669
0
      else if (tree->car->car == (node*)1) {
3670
0
        genop_1(s, OP_OCLASS, cursp());
3671
0
        push();
3672
0
      }
3673
0
      else {
3674
0
        codegen(s, tree->car->car, VAL);
3675
0
      }
3676
0
      if (tree->cdr->car) {
3677
0
        codegen(s, tree->cdr->car, VAL);
3678
0
      }
3679
0
      else {
3680
0
        genop_1(s, OP_LOADNIL, cursp());
3681
0
        push();
3682
0
      }
3683
0
      pop(); pop();
3684
0
      idx = new_sym(s, nsym(tree->car->cdr));
3685
0
      genop_2(s, OP_CLASS, cursp(), idx);
3686
0
      body = tree->cdr->cdr->car;
3687
0
      if (nint(body->cdr->car) == NODE_BEGIN && body->cdr->cdr == NULL) {
3688
0
        genop_1(s, OP_LOADNIL, cursp());
3689
0
      }
3690
0
      else {
3691
0
        idx = scope_body(s, body, val);
3692
0
        genop_2(s, OP_EXEC, cursp(), idx);
3693
0
      }
3694
0
      if (val) {
3695
0
        push();
3696
0
      }
3697
0
    }
3698
0
    break;
3699
3700
0
  case NODE_MODULE:
3701
0
    {
3702
0
      int idx;
3703
3704
0
      if (tree->car->car == (node*)0) {
3705
0
        genop_1(s, OP_LOADNIL, cursp());
3706
0
        push();
3707
0
      }
3708
0
      else if (tree->car->car == (node*)1) {
3709
0
        genop_1(s, OP_OCLASS, cursp());
3710
0
        push();
3711
0
      }
3712
0
      else {
3713
0
        codegen(s, tree->car->car, VAL);
3714
0
      }
3715
0
      pop();
3716
0
      idx = new_sym(s, nsym(tree->car->cdr));
3717
0
      genop_2(s, OP_MODULE, cursp(), idx);
3718
0
      if (nint(tree->cdr->car->cdr->car) == NODE_BEGIN &&
3719
0
          tree->cdr->car->cdr->cdr == NULL) {
3720
0
        genop_1(s, OP_LOADNIL, cursp());
3721
0
      }
3722
0
      else {
3723
0
        idx = scope_body(s, tree->cdr->car, val);
3724
0
        genop_2(s, OP_EXEC, cursp(), idx);
3725
0
      }
3726
0
      if (val) {
3727
0
        push();
3728
0
      }
3729
0
    }
3730
0
    break;
3731
3732
0
  case NODE_SCLASS:
3733
0
    {
3734
0
      int idx;
3735
3736
0
      codegen(s, tree->car, VAL);
3737
0
      pop();
3738
0
      genop_1(s, OP_SCLASS, cursp());
3739
0
      if (nint(tree->cdr->car->cdr->car) == NODE_BEGIN &&
3740
0
          tree->cdr->car->cdr->cdr == NULL) {
3741
0
        genop_1(s, OP_LOADNIL, cursp());
3742
0
      }
3743
0
      else {
3744
0
        idx = scope_body(s, tree->cdr->car, val);
3745
0
        genop_2(s, OP_EXEC, cursp(), idx);
3746
0
      }
3747
0
      if (val) {
3748
0
        push();
3749
0
      }
3750
0
    }
3751
0
    break;
3752
3753
466
  case NODE_DEF:
3754
466
    {
3755
466
      int sym = new_sym(s, nsym(tree->car));
3756
466
      int idx = lambda_body(s, tree->cdr, 0);
3757
3758
466
      genop_1(s, OP_TCLASS, cursp());
3759
466
      push();
3760
466
      genop_2(s, OP_METHOD, cursp(), idx);
3761
466
      push(); pop();
3762
466
      pop();
3763
466
      genop_2(s, OP_DEF, cursp(), sym);
3764
466
      if (val) push();
3765
466
    }
3766
466
    break;
3767
3768
0
  case NODE_SDEF:
3769
0
    {
3770
0
      node *recv = tree->car;
3771
0
      int sym = new_sym(s, nsym(tree->cdr->car));
3772
0
      int idx = lambda_body(s, tree->cdr->cdr, 0);
3773
3774
0
      codegen(s, recv, VAL);
3775
0
      pop();
3776
0
      genop_1(s, OP_SCLASS, cursp());
3777
0
      push();
3778
0
      genop_2(s, OP_METHOD, cursp(), idx);
3779
0
      push(); pop();
3780
0
      pop();
3781
0
      genop_2(s, OP_DEF, cursp(), sym);
3782
0
      if (val) push();
3783
0
    }
3784
0
    break;
3785
3786
0
  case NODE_POSTEXE:
3787
0
    codegen(s, tree, NOVAL);
3788
0
    break;
3789
3790
0
  default:
3791
0
    break;
3792
1.58M
  }
3793
1.58M
 exit:
3794
1.58M
  s->rlev = rlev;
3795
1.58M
}
3796
3797
static void
3798
scope_add_irep(codegen_scope *s)
3799
932
{
3800
932
  mrb_irep *irep;
3801
932
  codegen_scope *prev = s->prev;
3802
3803
932
  if (prev->irep == NULL) {
3804
466
    irep = mrb_add_irep(s->mrb);
3805
466
    prev->irep = s->irep = irep;
3806
466
    return;
3807
466
  }
3808
466
  else {
3809
466
    if (prev->irep->rlen == UINT16_MAX) {
3810
0
      codegen_error(s, "too many nested blocks/methods");
3811
0
    }
3812
466
    s->irep = irep = mrb_add_irep(s->mrb);
3813
466
    if (prev->irep->rlen == prev->rcapa) {
3814
0
      prev->rcapa *= 2;
3815
0
      prev->reps = (mrb_irep**)codegen_realloc(s, prev->reps, sizeof(mrb_irep*)*prev->rcapa);
3816
0
    }
3817
466
    prev->reps[prev->irep->rlen] = irep;
3818
466
    prev->irep->rlen++;
3819
466
  }
3820
932
}
3821
3822
static codegen_scope*
3823
scope_new(mrb_state *mrb, codegen_scope *prev, node *nlv)
3824
1.39k
{
3825
1.39k
  static const codegen_scope codegen_scope_zero = { 0 };
3826
1.39k
  mrb_pool *pool = mrb_pool_open(mrb);
3827
1.39k
  codegen_scope *s = (codegen_scope*)mrb_pool_alloc(pool, sizeof(codegen_scope));
3828
3829
1.39k
  if (!s) {
3830
0
    if (prev)
3831
0
      codegen_error(prev, "unexpected scope");
3832
0
    return NULL;
3833
0
  }
3834
1.39k
  *s = codegen_scope_zero;
3835
1.39k
  s->mrb = mrb;
3836
1.39k
  s->mpool = pool;
3837
1.39k
  if (!prev) return s;
3838
932
  s->prev = prev;
3839
932
  s->ainfo = 0;
3840
932
  s->mscope = 0;
3841
3842
932
  scope_add_irep(s);
3843
3844
932
  s->rcapa = 8;
3845
932
  s->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*s->rcapa);
3846
3847
932
  s->icapa = 1024;
3848
932
  s->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*s->icapa);
3849
3850
932
  s->pcapa = 32;
3851
932
  s->pool = (mrb_pool_value*)mrb_malloc(mrb, sizeof(mrb_pool_value)*s->pcapa);
3852
3853
932
  s->scapa = 256;
3854
932
  s->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*s->scapa);
3855
3856
932
  s->lv = nlv;
3857
932
  s->sp += node_len(nlv)+1;        /* add self */
3858
932
  s->nlocals = s->sp;
3859
932
  if (nlv) {
3860
466
    mrb_sym *lv;
3861
466
    node *n = nlv;
3862
466
    size_t i = 0;
3863
3864
466
    s->irep->lv = lv = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*(s->nlocals-1));
3865
69.7k
    for (i=0, n=nlv; n; i++,n=n->cdr) {
3866
69.2k
      lv[i] = lv_name(n);
3867
69.2k
    }
3868
466
    mrb_assert(i + 1 == s->nlocals);
3869
466
  }
3870
932
  s->ai = mrb_gc_arena_save(mrb);
3871
3872
932
  s->filename_sym = prev->filename_sym;
3873
932
  if (s->filename_sym) {
3874
0
    s->lines = (uint16_t*)mrb_malloc(mrb, sizeof(short)*s->icapa);
3875
0
  }
3876
932
  s->lineno = prev->lineno;
3877
3878
  /* debug setting */
3879
932
  s->debug_start_pos = 0;
3880
932
  if (s->filename_sym) {
3881
0
    mrb_debug_info_alloc(mrb, s->irep);
3882
0
  }
3883
932
  else {
3884
932
    s->irep->debug_info = NULL;
3885
932
  }
3886
932
  s->parser = prev->parser;
3887
932
  s->filename_index = prev->filename_index;
3888
3889
932
  s->rlev = prev->rlev+1;
3890
3891
932
  return s;
3892
1.39k
}
3893
3894
static void
3895
scope_finish(codegen_scope *s)
3896
845
{
3897
845
  mrb_state *mrb = s->mrb;
3898
845
  mrb_irep *irep = s->irep;
3899
3900
845
  if (s->nlocals > 0xff) {
3901
57
    codegen_error(s, "too many local variables");
3902
57
  }
3903
845
  irep->flags = 0;
3904
845
  if (s->iseq) {
3905
788
    size_t catchsize = sizeof(struct mrb_irep_catch_handler) * irep->clen;
3906
788
    irep->iseq = (const mrb_code*)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc + catchsize);
3907
788
    irep->ilen = s->pc;
3908
788
    if (irep->clen > 0) {
3909
0
      memcpy((void*)(irep->iseq + irep->ilen), s->catch_table, catchsize);
3910
0
    }
3911
788
  }
3912
57
  else {
3913
57
    irep->clen = 0;
3914
57
  }
3915
845
  mrb_free(s->mrb, s->catch_table);
3916
845
  s->catch_table = NULL;
3917
845
  irep->pool = (const mrb_pool_value*)codegen_realloc(s, s->pool, sizeof(mrb_pool_value)*irep->plen);
3918
845
  irep->syms = (const mrb_sym*)codegen_realloc(s, s->syms, sizeof(mrb_sym)*irep->slen);
3919
845
  irep->reps = (const mrb_irep**)codegen_realloc(s, s->reps, sizeof(mrb_irep*)*irep->rlen);
3920
845
  if (s->filename_sym) {
3921
0
    mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index);
3922
0
    const char *filename = mrb_sym_name_len(s->mrb, fname, NULL);
3923
3924
0
    mrb_debug_info_append_file(s->mrb, s->irep->debug_info,
3925
0
                               filename, s->lines, s->debug_start_pos, s->pc);
3926
0
  }
3927
845
  mrb_free(s->mrb, s->lines);
3928
3929
845
  irep->nlocals = s->nlocals;
3930
845
  irep->nregs = s->nregs;
3931
3932
845
  mrb_gc_arena_restore(mrb, s->ai);
3933
845
  mrb_pool_close(s->mpool);
3934
845
}
3935
3936
static struct loopinfo*
3937
loop_push(codegen_scope *s, enum looptype t)
3938
0
{
3939
0
  struct loopinfo *p = (struct loopinfo*)codegen_palloc(s, sizeof(struct loopinfo));
3940
3941
0
  p->type = t;
3942
0
  p->pc0 = p->pc1 = p->pc2 = JMPLINK_START;
3943
0
  p->prev = s->loop;
3944
0
  p->reg = cursp();
3945
0
  s->loop = p;
3946
3947
0
  return p;
3948
0
}
3949
3950
static void
3951
loop_break(codegen_scope *s, node *tree)
3952
0
{
3953
0
  if (!s->loop) {
3954
0
    codegen(s, tree, NOVAL);
3955
0
    raise_error(s, "unexpected break");
3956
0
  }
3957
0
  else {
3958
0
    struct loopinfo *loop;
3959
3960
3961
0
    loop = s->loop;
3962
0
    if (tree) {
3963
0
      if (loop->reg < 0) {
3964
0
        codegen(s, tree, NOVAL);
3965
0
      }
3966
0
      else {
3967
0
        gen_retval(s, tree);
3968
0
      }
3969
0
    }
3970
0
    while (loop) {
3971
0
      if (loop->type == LOOP_BEGIN) {
3972
0
        loop = loop->prev;
3973
0
      }
3974
0
      else if (loop->type == LOOP_RESCUE) {
3975
0
        loop = loop->prev;
3976
0
      }
3977
0
      else{
3978
0
        break;
3979
0
      }
3980
0
    }
3981
0
    if (!loop) {
3982
0
      raise_error(s, "unexpected break");
3983
0
      return;
3984
0
    }
3985
3986
0
    if (loop->type == LOOP_NORMAL) {
3987
0
      int tmp;
3988
3989
0
      if (loop->reg >= 0) {
3990
0
        if (tree) {
3991
0
          gen_move(s, loop->reg, cursp(), 0);
3992
0
        }
3993
0
        else {
3994
0
          genop_1(s, OP_LOADNIL, loop->reg);
3995
0
        }
3996
0
      }
3997
0
      tmp = genjmp(s, OP_JMPUW, loop->pc2);
3998
0
      loop->pc2 = tmp;
3999
0
    }
4000
0
    else {
4001
0
      if (!tree) {
4002
0
        genop_1(s, OP_LOADNIL, cursp());
4003
0
      }
4004
0
      gen_return(s, OP_BREAK, cursp());
4005
0
    }
4006
0
  }
4007
0
}
4008
4009
static void
4010
loop_pop(codegen_scope *s, int val)
4011
0
{
4012
0
  if (val) {
4013
0
    genop_1(s, OP_LOADNIL, cursp());
4014
0
  }
4015
0
  dispatch_linked(s, s->loop->pc2);
4016
0
  s->loop = s->loop->prev;
4017
0
  if (val) push();
4018
0
}
4019
4020
static int
4021
catch_handler_new(codegen_scope *s)
4022
0
{
4023
0
  size_t newsize = sizeof(struct mrb_irep_catch_handler) * (s->irep->clen + 1);
4024
0
  s->catch_table = (struct mrb_irep_catch_handler*)codegen_realloc(s, (void*)s->catch_table, newsize);
4025
0
  return s->irep->clen++;
4026
0
}
4027
4028
static void
4029
catch_handler_set(codegen_scope *s, int ent, enum mrb_catch_type type, uint32_t begin, uint32_t end, uint32_t target)
4030
0
{
4031
0
  struct mrb_irep_catch_handler *e;
4032
4033
0
  mrb_assert(ent >= 0 && ent < s->irep->clen);
4034
4035
0
  e = &s->catch_table[ent];
4036
0
  uint8_to_bin(type, &e->type);
4037
0
  mrb_irep_catch_handler_pack(begin, e->begin);
4038
0
  mrb_irep_catch_handler_pack(end, e->end);
4039
0
  mrb_irep_catch_handler_pack(target, e->target);
4040
0
}
4041
4042
static struct RProc*
4043
generate_code(mrb_state *mrb, parser_state *p, int val)
4044
466
{
4045
466
  codegen_scope *scope = scope_new(mrb, 0, 0);
4046
466
  struct mrb_jmpbuf *prev_jmp = mrb->jmp;
4047
466
  struct mrb_jmpbuf jmpbuf;
4048
466
  struct RProc *proc;
4049
4050
466
  mrb->jmp = &jmpbuf;
4051
4052
466
  scope->mrb = mrb;
4053
466
  scope->parser = p;
4054
466
  scope->filename_sym = p->filename_sym;
4055
466
  scope->filename_index = p->current_filename_index;
4056
4057
466
  MRB_TRY(mrb->jmp) {
4058
    /* prepare irep */
4059
466
    codegen(scope, p->tree, val);
4060
466
    proc = mrb_proc_new(mrb, scope->irep);
4061
466
    mrb_irep_decref(mrb, scope->irep);
4062
466
    mrb_pool_close(scope->mpool);
4063
466
    proc->c = NULL;
4064
466
    if (mrb->c->cibase && mrb->c->cibase->proc == proc->upper) {
4065
394
      proc->upper = NULL;
4066
394
    }
4067
466
    mrb->jmp = prev_jmp;
4068
466
    return proc;
4069
466
  }
4070
466
  MRB_CATCH(mrb->jmp) {
4071
0
    mrb_irep_decref(mrb, scope->irep);
4072
0
    mrb_pool_close(scope->mpool);
4073
0
    mrb->jmp = prev_jmp;
4074
0
    return NULL;
4075
0
  }
4076
0
  MRB_END_EXC(mrb->jmp);
4077
0
}
4078
4079
MRB_API struct RProc*
4080
mrb_generate_code(mrb_state *mrb, parser_state *p)
4081
466
{
4082
466
  return generate_code(mrb, p, VAL);
4083
466
}
4084
4085
void
4086
mrb_irep_remove_lv(mrb_state *mrb, mrb_irep *irep)
4087
0
{
4088
0
  int i;
4089
4090
0
  if (irep->flags & MRB_IREP_NO_FREE) return;
4091
0
  if (irep->lv) {
4092
0
    mrb_free(mrb, (void*)irep->lv);
4093
0
    irep->lv = NULL;
4094
0
  }
4095
0
  if (!irep->reps) return;
4096
0
  for (i = 0; i < irep->rlen; i++) {
4097
0
    mrb_irep_remove_lv(mrb, (mrb_irep*)irep->reps[i]);
4098
0
  }
4099
0
}