tagged release 0.7.1
[parrot.git] / compilers / imcc / pbc.c
blob2e3636078ce9cf1ab241bf62bed63b956db510f6
1 /*
2 * Copyright (C) 2002-2008, The Perl Foundation.
3 * $Id$
4 */
6 #include "imc.h"
7 #include "pbc.h"
8 #include "parrot/packfile.h"
10 /* HEADERIZER HFILE: compilers/imcc/pbc.h */
14 =head1 NAME
16 compilers/imcc/pbc.c
18 =head1 DESCRIPTION
20 emit imcc instructions into Parrot interpreter
22 the e_pbc_emit function is called per instruction
24 Notes:
26 I'm using existing data structures here (SymReg*) to store
27 various global items (currently only PMC constants).
28 The index in the constant table is in SymReg* ->color
29 data member. This looks odd, but the register number
30 from imc.c:allocate is also there for variables,
31 so it's a little bit consistent at least.
33 So when reading color here it's either a constant table index
34 or a Parrot register number, depending on data type.
36 TODO memory clean up
38 -lt
40 =head2 Functions
42 =over 4
44 =cut
49 * globals store the state between individual e_pbc_emit calls
52 typedef struct subs_t {
53 size_t size; /* code size in ops */
54 int ins_line; /* line number for debug */
55 int n_basic_blocks; /* block count */
56 SymHash fixup; /* currently set_p_pc sub names only */
57 IMC_Unit *unit;
58 int pmc_const; /* index in const table */
59 struct subs_t *prev;
60 struct subs_t *next;
61 } subs_t;
63 /* subs are kept per code segment */
64 typedef struct code_segment_t {
65 PackFile_ByteCode *seg; /* bytecode segment */
66 PackFile_Segment *jit_info; /* bblocks, register usage */
67 subs_t *subs; /* current sub data */
68 subs_t *first; /* first sub of code segment */
69 struct code_segment_t *prev; /* previous code segment */
70 struct code_segment_t *next; /* next code segment */
71 SymHash key_consts; /* this seg's cached key constants */
72 int pic_idx; /* next index of PIC */
73 } code_segment_t;
75 static struct globals {
76 code_segment_t *cs; /* current code segment */
77 code_segment_t *first; /* first code segment */
78 int inter_seg_n;
79 } globals;
82 /* HEADERIZER BEGIN: static */
83 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
85 static void add_1_const(PARROT_INTERP, ARGMOD(SymReg *r))
86 __attribute__nonnull__(1)
87 __attribute__nonnull__(2)
88 FUNC_MODIFIES(*r);
90 static int add_const_key(PARROT_INTERP,
91 ARGIN(const opcode_t *key),
92 int size,
93 ARGIN(const char *s_key))
94 __attribute__nonnull__(1)
95 __attribute__nonnull__(2)
96 __attribute__nonnull__(4);
98 PARROT_WARN_UNUSED_RESULT
99 static int add_const_num(PARROT_INTERP, ARGIN_NULLOK(const char *buf))
100 __attribute__nonnull__(1);
102 static int add_const_pmc_sub(PARROT_INTERP,
103 ARGMOD(SymReg *r),
104 int offs,
105 int end)
106 __attribute__nonnull__(1)
107 __attribute__nonnull__(2)
108 FUNC_MODIFIES(*r);
110 PARROT_WARN_UNUSED_RESULT
111 static int add_const_str(PARROT_INTERP, ARGIN(const SymReg *r))
112 __attribute__nonnull__(1)
113 __attribute__nonnull__(2);
115 static int add_const_table(PARROT_INTERP)
116 __attribute__nonnull__(1);
118 static int add_const_table_key(PARROT_INTERP, PMC *key)
119 __attribute__nonnull__(1);
121 static int add_const_table_pmc(PARROT_INTERP, PMC *pmc)
122 __attribute__nonnull__(1);
124 static opcode_t build_key(PARROT_INTERP, ARGIN(SymReg *key_reg))
125 __attribute__nonnull__(1)
126 __attribute__nonnull__(2);
128 static void constant_folding(PARROT_INTERP, ARGIN(const IMC_Unit *unit))
129 __attribute__nonnull__(1)
130 __attribute__nonnull__(2);
132 PARROT_WARN_UNUSED_RESULT
133 PARROT_CANNOT_RETURN_NULL
134 static PMC* create_lexinfo(PARROT_INTERP,
135 ARGMOD(IMC_Unit *unit),
136 ARGIN(PMC *sub),
137 int need_lex)
138 __attribute__nonnull__(1)
139 __attribute__nonnull__(2)
140 __attribute__nonnull__(3)
141 FUNC_MODIFIES(*unit);
143 PARROT_WARN_UNUSED_RESULT
144 PARROT_CAN_RETURN_NULL
145 static subs_t * find_global_label(
146 ARGIN(const char *name),
147 ARGIN(const subs_t *sym),
148 ARGOUT(int *pc))
149 __attribute__nonnull__(1)
150 __attribute__nonnull__(2)
151 __attribute__nonnull__(3)
152 FUNC_MODIFIES(*pc);
154 PARROT_WARN_UNUSED_RESULT
155 PARROT_CAN_RETURN_NULL
156 static PMC* find_outer(PARROT_INTERP, ARGIN(const IMC_Unit *unit))
157 __attribute__nonnull__(1)
158 __attribute__nonnull__(2);
160 static void fixup_globals(PARROT_INTERP)
161 __attribute__nonnull__(1);
163 PARROT_WARN_UNUSED_RESULT
164 static int get_codesize(PARROT_INTERP,
165 ARGIN(const IMC_Unit *unit),
166 ARGOUT(int *src_lines))
167 __attribute__nonnull__(1)
168 __attribute__nonnull__(2)
169 __attribute__nonnull__(3)
170 FUNC_MODIFIES(*src_lines);
172 PARROT_WARN_UNUSED_RESULT
173 static int get_old_size(PARROT_INTERP, ARGOUT(int *ins_line))
174 __attribute__nonnull__(1)
175 __attribute__nonnull__(2)
176 FUNC_MODIFIES(*ins_line);
178 static void imcc_globals_destroy(SHIM_INTERP,
179 SHIM(int ex),
180 SHIM(void *param));
182 static void make_new_sub(ARGIN(IMC_Unit *unit))
183 __attribute__nonnull__(1);
185 static void make_pmc_const(PARROT_INTERP, ARGMOD(SymReg *r))
186 __attribute__nonnull__(1)
187 __attribute__nonnull__(2)
188 FUNC_MODIFIES(*r);
190 PARROT_CANNOT_RETURN_NULL
191 PARROT_MALLOC
192 static PMC* mk_multi_sig(PARROT_INTERP, ARGIN(const SymReg *r))
193 __attribute__nonnull__(1)
194 __attribute__nonnull__(2);
196 PARROT_WARN_UNUSED_RESULT
197 static int old_blocks(void);
199 PARROT_CONST_FUNCTION
200 PARROT_WARN_UNUSED_RESULT
201 PARROT_CANNOT_RETURN_NULL
202 static const char * slice_deb(int bits);
204 static void store_fixup(PARROT_INTERP,
205 ARGIN(const SymReg *r),
206 int pc,
207 int offset)
208 __attribute__nonnull__(1)
209 __attribute__nonnull__(2);
211 static void store_key_const(ARGIN(const char *str), int idx)
212 __attribute__nonnull__(1);
214 static void store_sub_size(size_t size, size_t ins_line);
215 static void verify_signature(PARROT_INTERP,
216 ARGIN(const Instruction *ins),
217 ARGIN(opcode_t *pc))
218 __attribute__nonnull__(1)
219 __attribute__nonnull__(2)
220 __attribute__nonnull__(3);
222 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
223 /* HEADERIZER END: static */
225 #ifdef HAS_JIT
227 PARROT_WARN_UNUSED_RESULT
228 static int old_blocks(void);
230 #endif /* HAS_JIT */
234 =item C<static void imcc_globals_destroy>
236 RT #48260: Not yet documented!!!
238 =cut
242 static void
243 imcc_globals_destroy(SHIM_INTERP, SHIM(int ex), SHIM(void *param))
245 code_segment_t *cs = globals.cs;
247 while (cs) {
248 subs_t *s = cs->subs;
249 code_segment_t *prev_cs = cs->prev;
251 while (s) {
252 subs_t * const prev_s = s->prev;
253 clear_sym_hash(&s->fixup);
254 mem_sys_free(s);
255 s = prev_s;
258 clear_sym_hash(&cs->key_consts);
259 mem_sys_free(cs);
260 cs = prev_cs;
263 globals.cs = NULL;
269 =item C<static int add_const_table>
271 Adds an empty item to constant table, returning its position.
273 =cut
277 static int
278 add_const_table(PARROT_INTERP)
280 const size_t oldcount = interp->code->const_table->const_count;
281 const size_t newcount = oldcount + 1;
283 /* Allocate a new constant */
284 PackFile_Constant * new_constant = PackFile_Constant_new(interp);
286 /* Update the constant count and reallocate */
287 if (interp->code->const_table->constants) {
288 interp->code->const_table->constants =
289 (PackFile_Constant **)mem_sys_realloc(interp->code->const_table->constants,
290 newcount * sizeof (PackFile_Constant *));
292 else {
293 interp->code->const_table->constants =
294 (PackFile_Constant **)mem_sys_allocate(newcount * sizeof (PackFile_Constant *));
297 interp->code->const_table->constants[newcount - 1] = new_constant;
298 interp->code->const_table->const_count = newcount;
300 return oldcount;
306 =item C<static int add_const_table_pmc>
308 Adds a PMC to the const table, returning its position.
310 =cut
314 static int
315 add_const_table_pmc(PARROT_INTERP, PMC *pmc)
317 int newitem = add_const_table(interp);
319 interp->code->const_table->constants[newitem]->type = PFC_PMC;
320 interp->code->const_table->constants[newitem]->u.key = pmc;
322 return newitem;
328 =item C<static int add_const_table_key>
330 Adds a key to the const table, returning its position.
332 =cut
336 static int
337 add_const_table_key(PARROT_INTERP, PMC *key)
339 int newitem = add_const_table(interp);
341 interp->code->const_table->constants[newitem]->type = PFC_KEY;
342 interp->code->const_table->constants[newitem]->u.key = key;
344 return newitem;
350 =item C<int e_pbc_open>
352 RT #48260: Not yet documented!!!
354 =cut
359 e_pbc_open(PARROT_INTERP, SHIM(void *param))
361 code_segment_t *cs = mem_allocate_zeroed_typed(code_segment_t);
363 /* register cleanup code */
364 if (!globals.cs)
365 Parrot_on_exit(interp, imcc_globals_destroy, NULL);
367 cs->prev = globals.cs;
369 /* free previous cached key constants if any */
370 if (globals.cs)
371 clear_sym_hash(&globals.cs->key_consts);
373 create_symhash(&cs->key_consts);
375 cs->next = NULL;
376 cs->subs = NULL;
377 cs->first = NULL;
378 cs->jit_info = NULL;
380 if (!globals.first)
381 globals.first = cs;
382 else
383 cs->prev->next = cs;
385 /* we need some segments */
386 if (!interp->code) {
387 PMC *self;
389 cs->seg = interp->code =
390 PF_create_default_segs(interp,
391 IMCC_INFO(interp)->state->file, 1);
394 * create a PMC constant holding the interpreter state
396 * see also ParrotInterpreter.thaw and .thawfinish
397 * currently just HLL_info is saved/restored
399 self = VTABLE_get_pmc_keyed_int(interp, interp->iglobals,
400 IGLOBALS_INTERPRETER);
401 (void) add_const_table_pmc(interp, self);
404 globals.cs = cs;
406 return 0;
409 #ifdef HAS_JIT
413 =item C<static int old_blocks>
415 get size/line of bytecode in ops till now
417 =cut
421 PARROT_WARN_UNUSED_RESULT
422 static int
423 old_blocks(void)
425 size_t size = 0;
426 const subs_t *s;
428 for (s = globals.cs->subs; s; s = s->prev) {
429 size += s->n_basic_blocks;
432 return size;
437 =item C<opcode_t * make_jit_info>
439 RT #48260: Not yet documented!!!
441 =cut
445 PARROT_WARN_UNUSED_RESULT
446 PARROT_CANNOT_RETURN_NULL
447 opcode_t *
448 make_jit_info(PARROT_INTERP, ARGIN(const IMC_Unit *unit))
450 const size_t old = old_blocks();
451 const size_t size = unit->n_basic_blocks + old;
453 if (!globals.cs->jit_info) {
454 const size_t len = strlen(globals.cs->seg->base.name) + 5;
455 char * const name = mem_allocate_n_typed(len, char);
457 snprintf(name, len, "%s_JIT", globals.cs->seg->base.name);
458 globals.cs->jit_info = PackFile_Segment_new_seg(interp,
459 interp->code->base.dir, PF_UNKNOWN_SEG, name, 1);
461 mem_sys_free(name);
464 /* store current size */
465 globals.cs->subs->n_basic_blocks = unit->n_basic_blocks;
467 /* offset of block start and end, 4 * registers_used */
468 globals.cs->jit_info->data =
469 mem_realloc_n_typed(globals.cs->jit_info->data, size * 4, opcode_t);
471 globals.cs->jit_info->size = size * 4;
473 return globals.cs->jit_info->data + old * 4;
476 #endif /* HAS_JIT */
480 =item C<static void make_new_sub>
482 allocate a new globals.cs->subs structure
484 =cut
488 static void
489 make_new_sub(ARGIN(IMC_Unit *unit))
491 subs_t * const s = mem_allocate_zeroed_typed(subs_t);
493 s->prev = globals.cs->subs;
494 s->unit = unit;
495 s->pmc_const = -1;
497 if (globals.cs->subs)
498 globals.cs->subs->next = s;
500 if (!globals.cs->first)
501 globals.cs->first = s;
503 globals.cs->subs = s;
505 create_symhash(&s->fixup);
510 =item C<static int get_old_size>
512 get size/line of bytecode in ops till now
514 =cut
518 PARROT_WARN_UNUSED_RESULT
519 static int
520 get_old_size(PARROT_INTERP, ARGOUT(int *ins_line))
522 size_t size = 0;
524 *ins_line = 0;
526 if (globals.cs && interp->code->base.data) {
527 subs_t *s;
528 for (s = globals.cs->subs; s; s = s->prev) {
529 size += s->size;
530 *ins_line += s->ins_line;
534 return size;
539 =item C<static void store_sub_size>
541 RT #48260: Not yet documented!!!
543 =cut
547 static void
548 store_sub_size(size_t size, size_t ins_line)
550 globals.cs->subs->size = size;
551 globals.cs->subs->ins_line = ins_line;
556 =item C<static void store_fixup>
558 RT #48260: Not yet documented!!!
560 =cut
564 static void
565 store_fixup(PARROT_INTERP, ARGIN(const SymReg *r), int pc, int offset)
567 SymReg * const fixup = _mk_address(interp, &globals.cs->subs->fixup,
568 r->name, U_add_all);
570 if (r->set == 'p')
571 fixup->set = 'p';
573 if (r->type & VT_ENCODED)
574 fixup->type |= VT_ENCODED;
576 /* set_p_pc = 2 */
577 fixup->color = pc;
578 fixup->offset = offset;
583 =item C<static void store_key_const>
585 RT #48260: Not yet documented!!!
587 =cut
591 static void
592 store_key_const(ARGIN(const char *str), int idx)
594 SymReg * const c = _mk_const(&globals.cs->key_consts, str, 0);
595 c->color = idx;
600 =item C<static int get_codesize>
602 store globals for later fixup
603 return size in ops
605 =cut
609 PARROT_WARN_UNUSED_RESULT
610 static int
611 get_codesize(PARROT_INTERP, ARGIN(const IMC_Unit *unit), ARGOUT(int *src_lines))
613 Instruction *ins = unit->instructions;
614 int code_size;
616 /* run through instructions:
617 * - sanity check
618 * - calc code size
619 * - calc nr of src lines for debug info
620 * - remember addr of labels
621 * - remember set_p_pc for global fixup
624 *src_lines = 0;
626 for (code_size = 0; ins ; ins = ins->next) {
627 if (ins->type & ITLABEL)
628 ins->symregs[0]->color = code_size;
630 if (ins->opname && *ins->opname) {
631 (*src_lines)++;
632 if (ins->opnum < 0)
633 IMCC_fatal(interp, 1, "get_codesize: "
634 "no opnum ins#%d %I\n",
635 ins->index, ins);
637 if (ins->opnum == PARROT_OP_set_p_pc) {
638 /* set_p_pc opcode */
639 IMCC_debug(interp, DEBUG_PBC_FIXUP, "PMC constant %s\n",
640 ins->symregs[1]->name);
642 if (ins->symregs[1]->usage & U_FIXUP)
643 store_fixup(interp, ins->symregs[1], code_size, 2);
646 code_size += ins->opsize;
648 else if (ins->opsize)
649 IMCC_fatal(interp, 1, "get_codesize: "
650 "non instruction with size found\n");
653 return code_size;
659 =item C<static subs_t * find_global_label>
661 get a global label, return the pc (absolute)
663 =cut
667 PARROT_WARN_UNUSED_RESULT
668 PARROT_CAN_RETURN_NULL
669 static subs_t *
670 find_global_label(ARGIN(const char *name), ARGIN(const subs_t *sym), ARGOUT(int *pc))
672 subs_t *s;
674 *pc = 0;
676 for (s = globals.cs->first; s; s = s->next) {
677 SymReg * const r = s->unit->instructions->symregs[0];
679 /* if names and namespaces are matching - ok */
680 if (r && (strcmp(r->name, name) == 0)
681 && ((sym->unit->_namespace && s->unit->_namespace
682 && (strcmp(sym->unit->_namespace->name, s->unit->_namespace->name) == 0))
683 || (!sym->unit->_namespace && !s->unit->_namespace)))
684 return s;
686 *pc += s->size;
689 return NULL;
694 =item C<static void fixup_globals>
696 fix global stuff
698 =cut
702 static void
703 fixup_globals(PARROT_INTERP)
705 subs_t *s;
706 int jumppc = 0;
708 for (s = globals.cs->first; s; s = s->next) {
709 const SymHash * const hsh = &s->fixup;
710 int i;
712 for (i = 0; i < hsh->size; i++) {
713 SymReg *fixup;
714 for (fixup = hsh->data[i]; fixup; fixup = fixup->next) {
715 int pc, pmc_const;
716 int addr = jumppc + fixup->color;
718 /* check in matching namespace */
719 subs_t *s1 = find_global_label(fixup->name, s, &pc);
722 * if failed change opcode:
723 * set_p_pc => find_name p_sc
724 * if a sub label is found
725 * convert to find_name, if the sub is a multi
727 if (s1) {
728 PARROT_ASSERT(s1->unit);
729 if (s1->unit->type & IMC_PCCSUB) {
730 const Instruction * const ins = s1->unit->instructions;
731 SymReg *r1;
732 pcc_sub_t *pcc_sub;
734 PARROT_ASSERT(ins);
736 r1 = ins->symregs[0];
737 PARROT_ASSERT(r1);
739 pcc_sub = r1->pcc_sub;
740 PARROT_ASSERT(pcc_sub);
742 /* if the sub is multi, don't insert constant */
743 if (pcc_sub->nmulti)
744 s1 = NULL;
747 if (!s1) {
748 int op, col;
749 SymReg * const nam = mk_const(interp, fixup->name,
750 fixup->type & VT_ENCODED ? 'U' : 'S');
752 op = interp->op_lib->op_code("find_sub_not_null_p_sc", 1);
753 PARROT_ASSERT(op);
755 interp->code->base.data[addr] = op;
757 if (nam->color >= 0)
758 col = nam->color;
759 else
760 col = nam->color = add_const_str(interp, nam);
762 interp->code->base.data[addr+2] = col;
764 IMCC_debug(interp, DEBUG_PBC_FIXUP,
765 "fixup const PMC"
766 " find_name sub '%s' const nr: %d\n",
767 fixup->name, col);
768 continue;
771 pmc_const = s1->pmc_const;
773 if (pmc_const < 0) {
774 IMCC_fatal(interp, 1, "fixup_globals: "
775 "couldn't find sub 2 '%s'\n", fixup->name);
778 interp->code->base.data[addr+fixup->offset] = pmc_const;
779 IMCC_debug(interp, DEBUG_PBC_FIXUP, "fixup const PMC"
780 " sub '%s' const nr: %d\n", fixup->name, pmc_const);
782 continue;
786 jumppc += s->size;
792 =item C<STRING * IMCC_string_from_reg>
794 RT #48260: Not yet documented!!!
796 =cut
800 PARROT_WARN_UNUSED_RESULT
801 PARROT_CANNOT_RETURN_NULL
802 STRING *
803 IMCC_string_from_reg(PARROT_INTERP, ARGIN(const SymReg *r))
805 const char *buf = r->name;
807 if (r->type & VT_ENCODED) {
809 * the lexer parses: foo:"string"
810 * get first part as charset, rest as string
812 STRING *s;
813 const char *charset;
814 char * const p = strchr(r->name, '"');
815 PARROT_ASSERT(p && p[-1] == ':');
817 p[-1] = 0;
818 charset = r->name;
820 /* past delim */
821 buf = p + 1;
822 s = string_unescape_cstring(interp, buf, '"', charset);
824 /* restore colon, as we may reuse this string */
825 p[-1] = ':';
826 return s;
828 else if (*buf == '"') {
829 buf++;
830 return string_unescape_cstring(interp, buf, '"', NULL);
832 else if (*buf == '\'') { /* TODO handle python raw strings */
833 buf++;
834 return string_make(interp, buf, strlen(buf) - 1, "ascii",
835 PObj_constant_FLAG);
838 /* unquoted bare name - ascii only don't unescape it */
839 return string_make(interp, buf, strlen(buf), "ascii", PObj_constant_FLAG);
844 =item C<static int add_const_str>
846 add constant string to constant_table
848 =cut
852 PARROT_WARN_UNUSED_RESULT
853 static int
854 add_const_str(PARROT_INTERP, ARGIN(const SymReg *r))
856 const int k = add_const_table(interp);
857 STRING * const s = IMCC_string_from_reg(interp, r);
859 interp->code->const_table->constants[k]->type = PFC_STRING;
860 interp->code->const_table->constants[k]->u.string = s;
862 return k;
867 =item C<static int add_const_num>
869 RT #48260: Not yet documented!!!
871 =cut
875 PARROT_WARN_UNUSED_RESULT
876 static int
877 add_const_num(PARROT_INTERP, ARGIN_NULLOK(const char *buf))
879 const int k = add_const_table(interp);
880 STRING * const s = string_from_cstring(interp, buf, 0);
882 interp->code->const_table->constants[k]->type = PFC_NUMBER;
883 interp->code->const_table->constants[k]->u.number = string_to_num(interp, s);
885 return k;
890 =item C<static PMC* mk_multi_sig>
892 RT #48260: Not yet documented!!!
894 =cut
898 PARROT_CANNOT_RETURN_NULL
899 PARROT_MALLOC
900 static PMC*
901 mk_multi_sig(PARROT_INTERP, ARGIN(const SymReg *r))
903 PMC * const multi_sig = pmc_new(interp, enum_class_FixedPMCArray);
904 pcc_sub_t * const pcc_sub = r->pcc_sub;
905 const INTVAL n = pcc_sub->nmulti;
906 INTVAL i;
908 PackFile_ConstTable *ct;
910 VTABLE_set_integer_native(interp, multi_sig, n);
912 /* :multi() n = 1, reg = NULL */
913 if (!pcc_sub->multi[0]) {
914 STRING * const sig = string_from_literal(interp, "__VOID");
915 PMC * const sig_pmc = pmc_new(interp, enum_class_String);
917 VTABLE_set_string_native(interp, sig_pmc, sig);
918 VTABLE_set_pmc_keyed_int(interp, multi_sig, 0, sig_pmc);
920 return multi_sig;
923 ct = interp->code->const_table;
925 for (i = 0; i < n; ++i) {
926 /* multi[i] can be a Key too -
927 * store PMC constants instead of bare strings */
928 PMC *sig_pmc;
929 r = pcc_sub->multi[i];
931 if (r->set == 'S') {
932 sig_pmc = pmc_new(interp, enum_class_String);
933 VTABLE_set_string_native(interp, sig_pmc,
934 ct->constants[r->color]->u.string);
936 else {
937 PARROT_ASSERT(r->set == 'K');
938 sig_pmc = ct->constants[r->color]->u.key;
941 VTABLE_set_pmc_keyed_int(interp, multi_sig, i, sig_pmc);
944 return multi_sig;
947 typedef void (*decl_func_t)(Interp *, PMC *, STRING *, INTVAL);
951 =item C<static PMC* create_lexinfo>
953 RT #48260: Not yet documented!!!
955 =cut
959 PARROT_WARN_UNUSED_RESULT
960 PARROT_CANNOT_RETURN_NULL
961 static PMC*
962 create_lexinfo(PARROT_INTERP, ARGMOD(IMC_Unit *unit), ARGIN(PMC *sub),
963 int need_lex)
965 int i;
967 PMC *lex_info = NULL;
968 SymHash *hsh = &unit->hash;
969 PackFile_Constant **constants = interp->code->const_table->constants;
970 const INTVAL lex_info_id = Parrot_get_ctx_HLL_type(interp,
971 enum_class_LexInfo);
973 for (i = 0; i < hsh->size; i++) {
974 SymReg *r;
975 for (r = hsh->data[i]; r; r = r->next) {
976 if (r->set == 'P' && r->usage & U_LEXICAL) {
977 SymReg *n;
978 if (!lex_info) {
979 lex_info = pmc_new_noinit(interp, lex_info_id);
980 VTABLE_init_pmc(interp, lex_info, sub);
983 /* at least one lexical name */
984 n = r->reg;
985 PARROT_ASSERT(n);
987 while (n) {
988 STRING *lex_name;
989 const int k = n->color;
990 PARROT_ASSERT(k >= 0);
992 lex_name = constants[k]->u.string;
993 PARROT_ASSERT(PObj_is_string_TEST(lex_name));
995 IMCC_debug(interp, DEBUG_PBC_CONST,
996 "add lexical '%s' to sub name '%s'\n",
997 n->name, (char*)PMC_sub(sub)->name->strstart);
999 Parrot_PCCINVOKE(interp, lex_info,
1000 string_from_literal(interp, "declare_lex_preg"),
1001 "SI->", lex_name, r->color);
1003 /* next possible name */
1004 n = n->reg;
1010 if (!lex_info && (unit->outer || need_lex)) {
1011 lex_info = pmc_new_noinit(interp, lex_info_id);
1012 VTABLE_init_pmc(interp, lex_info, sub);
1015 return lex_info;
1020 =item C<static PMC* find_outer>
1022 RT #48260: Not yet documented!!!
1024 =cut
1028 PARROT_WARN_UNUSED_RESULT
1029 PARROT_CAN_RETURN_NULL
1030 static PMC*
1031 find_outer(PARROT_INTERP, ARGIN(const IMC_Unit *unit))
1033 subs_t *s;
1034 size_t len;
1035 PMC *current;
1036 STRING *cur_name;
1038 if (!unit->outer)
1039 return NULL;
1042 * we need that the :outer sub is already compiled,
1043 * because we are freezing the outer Sub PMC along with this
1044 * one
1047 len = strlen(unit->outer->name);
1049 if (!len)
1050 return NULL;
1052 for (s = globals.cs->first; s; s = s->next) {
1053 if (STREQ(s->unit->lexid->name, unit->outer->name)) {
1054 PObj_get_FLAGS(s->unit->sub_pmc) |= SUB_FLAG_IS_OUTER;
1055 return s->unit->sub_pmc;
1059 /* could be eval too; check if :outer is the current sub */
1060 current = CONTEXT(interp)->current_sub;
1062 if (!current)
1063 IMCC_fatal(interp, 1, "Undefined :outer sub '%s'.\n",
1064 unit->outer->name);
1066 cur_name = PMC_sub(current)->name;
1068 if (cur_name->strlen == len
1069 && (memcmp((char*)cur_name->strstart, unit->outer->name, len) == 0))
1070 return current;
1072 return NULL;
1077 =item C<static int add_const_pmc_sub>
1079 RT #48260: Not yet documented!!!
1081 =cut
1085 static int
1086 add_const_pmc_sub(PARROT_INTERP, ARGMOD(SymReg *r), int offs, int end)
1088 int i;
1089 int ns_const = -1;
1090 PMC *ns_pmc;
1091 PMC *sub_pmc;
1092 Parrot_sub *sub;
1094 const int k = add_const_table(interp);
1095 IMC_Unit * const unit = globals.cs->subs->unit;
1096 PackFile_ConstTable *ct = interp->code->const_table;
1097 PackFile_Constant *pfc = ct->constants[k];
1099 INTVAL type =
1100 (r->pcc_sub->calls_a_sub & ITPCCYIELD) ?
1101 enum_class_Coroutine :
1102 unit->outer ? enum_class_Closure : enum_class_Sub;
1104 globals.cs->subs->pmc_const = k;
1106 if (unit->_namespace) {
1107 /* strip namespace off from front */
1108 const char *real_name = strrchr(r->name, '@');
1109 SymReg * const ns = unit->_namespace->reg;
1111 IMCC_debug(interp, DEBUG_PBC_CONST,
1112 "name space const = %d ns name '%s'\n", ns->color, ns->name);
1114 ns_const = ns->color;
1116 if (real_name) {
1117 char * const p = str_dup(real_name + 1);
1118 free(r->name);
1119 r->name = p;
1123 /* Do we have to create an instance of a specific type for this sub? */
1124 if (unit->instance_of) {
1125 /* Look it up as a class and as a PMC type. */
1126 STRING * const classname = string_from_cstring(interp, unit->instance_of + 1,
1127 strlen(unit->instance_of) - 2);
1128 PMC * const classobj = Parrot_oo_get_class_str(interp, classname);
1129 if (!PMC_IS_NULL(classobj))
1130 sub_pmc = VTABLE_instantiate(interp, classobj, PMCNULL);
1131 else {
1132 const INTVAL type = pmc_type(interp, classname);
1133 if (type <= 0)
1134 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_NO_CLASS,
1135 "Class '%Ss' specified in :instanceof(...) not found", classname);
1136 sub_pmc = pmc_new(interp, type);
1139 else {
1140 /* use a possible type mapping for the Sub PMCs, and create it */
1141 type = Parrot_get_ctx_HLL_type(interp, type);
1143 /* TODO create constant - see also src/packfile.c */
1144 sub_pmc = pmc_new(interp, type);
1147 /* Set flags and get the sub info. */
1148 PObj_get_FLAGS(sub_pmc) |= (r->pcc_sub->pragma & SUB_FLAG_PF_MASK);
1149 Sub_comp_get_FLAGS(sub_pmc) |= (r->pcc_sub->pragma & SUB_COMP_FLAG_MASK);
1150 sub = PMC_sub(sub_pmc);
1152 r->color = add_const_str(interp, r);
1153 sub->name = ct->constants[r->color]->u.string;
1155 /* If the unit has no lexid, set the lexid to match the name. */
1156 if (!unit->lexid) {
1157 unit->lexid = r;
1159 else {
1160 /* trim the quotes */
1161 unit->lexid->name = str_dup(unit->lexid->name + 1);
1163 /* Otherwise, create string constant for it. */
1164 unit->lexid->name[strlen(unit->lexid->name) - 1] = 0;
1165 unit->lexid->color = add_const_str(interp, unit->lexid);
1167 sub->lexid = ct->constants[unit->lexid->color]->u.string;
1169 ns_pmc = NULL;
1171 if (ns_const >= 0 && ns_const < ct->const_count) {
1172 switch (ct->constants[ns_const]->type) {
1173 case PFC_KEY:
1174 ns_pmc = ct->constants[ns_const]->u.key;
1175 break;
1176 case PFC_STRING:
1177 ns_pmc = constant_pmc_new(interp, enum_class_String);
1178 PMC_str_val(ns_pmc) = ct->constants[ns_const]->u.string;
1179 break;
1180 default:
1181 break;
1185 sub->namespace_name = ns_pmc;
1186 sub->start_offs = offs;
1187 sub->end_offs = end;
1188 sub->HLL_id = CONTEXT(interp)->current_HLL;
1190 for (i = 0; i < 4; ++i)
1191 sub->n_regs_used[i] = unit->n_regs_used[i];
1193 sub->lex_info = create_lexinfo(interp, unit, sub_pmc,
1194 r->pcc_sub->pragma & P_NEED_LEX);
1195 sub->outer_sub = find_outer(interp, unit);
1196 sub->vtable_index = -1;
1198 /* check if it's declared multi */
1199 if (r->pcc_sub->nmulti)
1200 sub->multi_signature = mk_multi_sig(interp, r);
1201 else
1202 sub->multi_signature = NULL;
1204 if (unit->is_vtable_method == 1) {
1205 STRING *vtable_name;
1206 INTVAL vtable_index;
1208 /* Work out the name of the vtable method. */
1209 if (unit->vtable_name)
1210 vtable_name = string_from_cstring(interp, unit->vtable_name + 1,
1211 strlen(unit->vtable_name) - 2);
1212 else
1213 vtable_name = sub->name;
1215 /* Check this is a valid vtable method to override. */
1216 vtable_index = Parrot_get_vtable_index(interp, vtable_name);
1218 if (vtable_index == -1) {
1219 IMCC_fatal(interp, 1,
1220 "'%S' is not a v-table method, but was used with :vtable.\n",
1221 vtable_name);
1224 /* TODO check for duplicates */
1225 sub->vtable_index = vtable_index;
1228 Parrot_store_sub_in_namespace(interp, sub_pmc);
1230 pfc->type = PFC_PMC;
1231 pfc->u.key = sub_pmc;
1232 unit->sub_pmc = sub_pmc;
1234 IMCC_debug(interp, DEBUG_PBC_CONST,
1235 "add_const_pmc_sub '%s' flags %x color %d (%s) "
1236 "lex_info %s :outer(%s)\n",
1237 r->name, r->pcc_sub->pragma, k,
1238 (char *) sub_pmc->vtable->whoami->strstart,
1239 sub->lex_info ? "yes" : "no",
1240 sub->outer_sub ?
1241 (char *)PMC_sub(sub->outer_sub)->name->strstart :
1242 "*none*");
1244 * create entry in our fixup (=symbol) table
1245 * the offset is the index in the constant table of this Sub
1247 PackFile_FixupTable_new_entry(interp, r->name, enum_fixup_sub, k);
1248 return k;
1253 =item C<static int add_const_key>
1255 add constant key to constant_table
1257 =cut
1261 static int
1262 add_const_key(PARROT_INTERP, ARGIN(const opcode_t *key), int size, ARGIN(const char *s_key))
1264 int k;
1265 const opcode_t *rc;
1266 PackFile_Constant *pfc;
1268 const SymReg * const r = _get_sym(&globals.cs->key_consts, s_key);
1270 if (r)
1271 return r->color;
1273 pfc = mem_allocate_typed(PackFile_Constant);
1274 rc = PackFile_Constant_unpack_key(interp,
1275 interp->code->const_table, pfc, key);
1277 if (!rc) {
1278 mem_sys_free(pfc);
1279 IMCC_fatal(interp, 1,
1280 "add_const_key: PackFile_Constant error\n");
1283 k = add_const_table_key(interp, pfc->u.key);
1285 store_key_const(s_key, k);
1287 IMCC_debug(interp, DEBUG_PBC_CONST, "\t=> %s #%d size %d\n",
1288 s_key, k, size);
1289 IMCC_debug(interp, DEBUG_PBC_CONST, "\t %x /%x %x/ /%x %x/\n",
1290 key[0], key[1], key[2], key[3], key[4]);
1292 mem_sys_free(pfc);
1294 return k;
1299 =item C<static const char * slice_deb>
1301 RT #48260: Not yet documented!!!
1303 =cut
1307 PARROT_CONST_FUNCTION
1308 PARROT_WARN_UNUSED_RESULT
1309 PARROT_CANNOT_RETURN_NULL
1310 static const char *
1311 slice_deb(int bits)
1313 if ((bits & VT_SLICE_BITS) == (VT_START_SLICE|VT_END_SLICE))
1314 return "start+end";
1316 if ((bits & VT_SLICE_BITS) == (VT_START_ZERO|VT_END_SLICE))
1317 return "..end";
1319 if ((bits & VT_SLICE_BITS) == (VT_START_SLICE|VT_END_INF))
1320 return "start..";
1322 if (bits & VT_START_SLICE)
1323 return "start";
1325 if (bits & VT_END_SLICE)
1326 return "end";
1328 return "";
1333 =item C<static opcode_t build_key>
1335 color is a Parrot register number or a constant table index
1337 for the rest, please consult PDD08_KEYS(1)
1339 additionally, I build a string representation of the key,
1340 which gets cached in the globals.keys
1342 =cut
1346 static opcode_t
1347 build_key(PARROT_INTERP, ARGIN(SymReg *key_reg))
1349 #define KEYLEN 21
1350 char s_key[KEYLEN * 10];
1351 opcode_t key[KEYLEN];
1352 opcode_t size;
1353 int key_length; /* P0["hi;there"; S0; 2] has length 3 */
1354 int k;
1355 SymReg *reg;
1357 /* 0 is length */
1358 opcode_t *pc = key + 1;
1360 /* stringified key */
1361 char *s = s_key;
1362 *s = 0;
1364 reg = key_reg->set == 'K' ? key_reg->nextkey : key_reg;
1366 for (key_length = 0; reg ; reg = reg->nextkey, key_length++) {
1367 SymReg *r = reg;
1368 int var_type, slice_bits, type;
1370 if ((pc - key - 2) >= KEYLEN)
1371 IMCC_fatal(interp, 1, "build_key:"
1372 "key too complex increase KEYLEN\n");
1374 /* if key is a register, the original sym is in r->reg */
1375 type = r->type;
1377 if (r->reg)
1378 r = r->reg;
1380 var_type = type & ~VT_SLICE_BITS;
1381 slice_bits = type & VT_SLICE_BITS;
1383 switch (var_type) {
1384 case VTIDENTIFIER: /* P[S0] */
1385 case VTPASM: /* P[S0] */
1386 case VTREG: /* P[S0] */
1387 if (r->set == 'I')
1388 *pc++ = PARROT_ARG_I | slice_bits; /* register type */
1389 else if (r->set == 'S')
1390 *pc++ = PARROT_ARG_S | slice_bits;
1391 else
1392 IMCC_fatal(interp, 1, "build_key: wrong register set\n");
1394 /* don't emit mapped regs in key parts */
1395 if (r->color < 0)
1396 *pc++ = -1 - r->color;
1397 else
1398 *pc++ = r->color;
1400 sprintf(s+strlen(s), "%c%d", r->set, (int)r->color);
1402 IMCC_debug(interp, DEBUG_PBC_CONST,
1403 " keypart reg %s %c%d slice %s\n",
1404 r->name, r->set, (int)r->color,
1405 slice_deb(slice_bits));
1406 break;
1407 case VT_CONSTP:
1408 case VTCONST:
1409 case VTCONST|VT_ENCODED:
1410 switch (r->set) {
1411 case 'S': /* P["key"] */
1412 /* str constant */
1413 *pc++ = PARROT_ARG_SC | slice_bits;
1415 /* constant idx */
1416 *pc++ = r->color;
1418 IMCC_debug(interp, DEBUG_PBC_CONST,
1419 " keypart SC %s #%d slice %s\n",
1420 r->name, r->color,
1421 slice_deb(slice_bits));
1422 break;
1423 case 'I': /* P[;42;..] */
1424 /* int constant */
1425 *pc++ = PARROT_ARG_IC | slice_bits;
1427 /* value */
1428 *pc++ = r->color = atol(r->name);
1430 IMCC_debug(interp, DEBUG_PBC_CONST,
1431 " keypart IC %s #%d slice %s\n",
1432 r->name, r->color,
1433 slice_deb(slice_bits));
1434 break;
1435 default:
1436 IMCC_fatal(interp, 1, "build_key: unknown set\n");
1438 sprintf(s+strlen(s), "%cc" INTVAL_FMT, r->set, r->color);
1439 break;
1440 default:
1441 IMCC_fatal(interp, 1, "build_key: "
1442 "unknown type 0x%x on %s\n", var_type, r->name);
1446 key[0] = key_length;
1447 size = pc - key;
1449 /* now we have a packed key, which packfile can work on */
1450 /* XXX endianess? probably no, we pack/unpack on the very
1451 * same computer */
1452 k = add_const_key(interp, key, size, s_key);
1454 /* single 'S' keys already have their color assigned */
1455 if (key_reg->set == 'K')
1456 key_reg->color = k;
1458 return k;
1463 =item C<INTVAL IMCC_int_from_reg>
1465 RT #48260: Not yet documented!!!
1467 =cut
1471 INTVAL
1472 IMCC_int_from_reg(PARROT_INTERP, ARGIN(const SymReg *r))
1474 INTVAL i;
1476 errno = 0;
1478 if (r->type & VT_CONSTP)
1479 r = r->reg;
1481 if (r->name[0] == '0' && (r->name[1] == 'x' || r->name[1] == 'X'))
1482 i = strtoul(r->name+2, 0, 16);
1484 else if (r->name[0] == '0' && (r->name[1] == 'O' || r->name[1] == 'o'))
1485 i = strtoul(r->name+2, 0, 8);
1487 else if (r->name[0] == '0' && (r->name[1] == 'b' || r->name[1] == 'B'))
1488 i = strtoul(r->name+2, 0, 2);
1490 else
1491 i = strtol(r->name, 0, 10);
1494 * TODO
1495 * - is this portable?
1496 * - there are some more atol()s in this file
1498 if (errno == ERANGE)
1499 IMCC_fatal(interp, 1, "add_1_const:" "Integer overflow '%s'", r->name);
1501 return i;
1506 =item C<static void make_pmc_const>
1508 RT #48260: Not yet documented!!!
1510 =cut
1514 static void
1515 make_pmc_const(PARROT_INTERP, ARGMOD(SymReg *r))
1517 STRING *s;
1518 PMC *p;
1519 PMC *_class = interp->vtables[r->pmc_type]->pmc_class;
1520 int k;
1522 if (*r->name == '"')
1523 s = string_unescape_cstring(interp, r->name + 1, '"', NULL);
1525 else if (*r->name == '\'')
1526 s = string_unescape_cstring(interp, r->name + 1, '\'', NULL);
1528 else
1529 s = string_unescape_cstring(interp, r->name, 0, NULL);
1531 p = VTABLE_new_from_string(interp, _class, s, PObj_constant_FLAG);
1533 /* append PMC constant */
1534 k = add_const_table_pmc(interp, p);
1536 r->color = k;
1541 =item C<static void add_1_const>
1543 RT #48260: Not yet documented!!!
1545 =cut
1549 static void
1550 add_1_const(PARROT_INTERP, ARGMOD(SymReg *r))
1552 if (r->color >= 0)
1553 return;
1555 if (r->use_count <= 0)
1556 return;
1558 switch (r->set) {
1559 case 'I':
1560 r->color = IMCC_int_from_reg(interp, r);
1561 break;
1562 case 'S':
1563 if (r->type & VT_CONSTP)
1564 r = r->reg;
1565 r->color = add_const_str(interp, r);
1566 break;
1567 case 'N':
1568 r->color = add_const_num(interp, r->name);
1569 break;
1570 case 'K':
1572 SymReg *key = r;
1574 for (r = r->nextkey; r; r = r->nextkey)
1575 if (r->type & VTCONST)
1576 add_1_const(interp, r);
1577 build_key(interp, key);
1579 break;
1580 case 'P':
1581 make_pmc_const(interp, r);
1582 IMCC_debug(interp, DEBUG_PBC_CONST,
1583 "PMC const %s\tcolor %d\n", r->name, r->color);
1584 break;
1585 default:
1586 break;
1589 if (r)
1590 IMCC_debug(interp, DEBUG_PBC_CONST, "const %s\tcolor %d use_count %d\n",
1591 r->name, r->color, r->use_count);
1596 =item C<static void constant_folding>
1598 store a constants idx for later reuse
1600 =cut
1604 static void
1605 constant_folding(PARROT_INTERP, ARGIN(const IMC_Unit *unit))
1607 int i;
1608 const SymHash *hsh = &IMCC_INFO(interp)->ghash;
1610 /* go through all consts of current sub */
1611 for (i = 0; i < hsh->size; i++) {
1612 SymReg *r;
1613 /* normally constants are in ghash ... */
1614 for (r = hsh->data[i]; r; r = r->next) {
1615 if (r->type & (VTCONST|VT_CONSTP))
1616 add_1_const(interp, r);
1618 if (r->usage & U_LEXICAL) {
1619 SymReg *n = r->reg;
1621 /* r->reg is a chain of names for the same lex sym */
1622 while (n) {
1623 /* lex_name */
1624 add_1_const(interp, n);
1625 n = n->reg;
1631 /* ... but keychains 'K' are in local hash, they may contain
1632 * variables and constants */
1633 hsh = &unit->hash;
1635 for (i = 0; i < hsh->size; i++) {
1636 SymReg *r;
1637 /* normally constants are in ghash ... */
1638 for (r = hsh->data[i]; r; r = r->next) {
1639 if (r->type & VTCONST)
1640 add_1_const(interp, r);
1644 /* and finally, there may be an outer Sub */
1645 if (unit->outer)
1646 add_1_const(interp, unit->outer);
1651 =item C<int e_pbc_new_sub>
1653 RT #48260: Not yet documented!!!
1655 =cut
1660 e_pbc_new_sub(SHIM_INTERP, SHIM(void *param), ARGIN(IMC_Unit *unit))
1662 if (!unit->instructions)
1663 return 0;
1665 /* we start a new compilation unit */
1666 make_new_sub(unit);
1668 return 0;
1673 =item C<int e_pbc_end_sub>
1675 RT #48260: Not yet documented!!!
1677 =cut
1682 e_pbc_end_sub(PARROT_INTERP, SHIM(void *param), ARGIN(IMC_Unit *unit))
1684 Instruction *ins;
1685 int pragma;
1687 if (!unit->instructions)
1688 return 0;
1691 * if the sub was marked IMMEDIATE, we run it now
1692 * This is *dangerous*: all possible global state can be messed
1693 * up, e.g. when that sub starts loading bytecode
1695 ins = unit->instructions;
1697 /* we run only PCC subs */
1698 if (!ins->symregs[0] || !ins->symregs[0]->pcc_sub)
1699 return 0;
1701 pragma = ins->symregs[0]->pcc_sub->pragma;
1703 if (pragma & P_IMMEDIATE) {
1704 IMCC_debug(interp, DEBUG_PBC, "immediate sub '%s'",
1705 ins->symregs[0]->name);
1706 PackFile_fixup_subs(interp, PBC_IMMEDIATE, NULL);
1709 return 0;
1714 =item C<static void verify_signature>
1716 - check if any get_ argument contains constants
1717 - fill in type bits for argument types and constants, if missing
1719 =cut
1723 static void
1724 verify_signature(PARROT_INTERP, ARGIN(const Instruction *ins), ARGIN(opcode_t *pc))
1726 INTVAL i, n;
1727 int needed = 0;
1728 int no_consts = (ins->opnum == PARROT_OP_get_results_pc
1729 || ins->opnum == PARROT_OP_get_params_pc);
1730 PMC *changed_sig = NULL;
1731 PMC * const sig_arr = interp->code->const_table->constants[pc[-1]]->u.key;
1733 PARROT_ASSERT(PObj_is_PMC_TEST(sig_arr));
1734 PARROT_ASSERT(sig_arr->vtable->base_type == enum_class_FixedIntegerArray);
1736 n = VTABLE_elements(interp, sig_arr);
1738 if (n != ins->symreg_count - 1)
1739 IMCC_fatal(interp, 1, "syntax error: parameter count mismatch in '%s'"
1740 " -- have %d, want %d",
1741 ins->opname, ins->symreg_count - 1, n);
1743 for (i = 0; i < n; ++i) {
1744 SymReg * const r = ins->symregs[i + 1];
1745 INTVAL sig = VTABLE_get_integer_keyed_int(interp, sig_arr, i);
1747 if (! (sig & PARROT_ARG_NAME)
1748 && no_consts && (r->type & VTCONST))
1749 IMCC_fatal(interp, 1, "e_pbc_emit: "
1750 "constant argument '%s' in get param/result\n", r->name);
1752 if ((r->type & VTCONST) && !(sig & PARROT_ARG_CONSTANT)) {
1753 if (!changed_sig)
1754 changed_sig = VTABLE_clone(interp, sig_arr);
1756 sig |= PARROT_ARG_CONSTANT;
1758 VTABLE_set_integer_keyed_int(interp, changed_sig, i, sig);
1761 switch (r->set) {
1762 case 'I': needed = PARROT_ARG_INTVAL; break;
1763 case 'S': needed = PARROT_ARG_STRING; break;
1764 case 'P': needed = PARROT_ARG_PMC; break;
1765 case 'N': needed = PARROT_ARG_FLOATVAL; break;
1766 default : break;
1769 if (needed != (sig & PARROT_ARG_TYPE_MASK)) {
1770 if (!changed_sig)
1771 changed_sig = VTABLE_clone(interp, sig_arr);
1773 sig &= ~PARROT_ARG_TYPE_MASK;
1774 sig |= needed;
1776 VTABLE_set_integer_keyed_int(interp, changed_sig, i, sig);
1780 if (changed_sig) {
1781 /* append PMC constant */
1782 const int k = add_const_table_pmc(interp, changed_sig);
1783 pc[-1] = k;
1789 =item C<int e_pbc_emit>
1791 now let the fun begin, actually emit code for one ins
1793 =cut
1798 e_pbc_emit(PARROT_INTERP, SHIM(void *param), ARGIN(const IMC_Unit *unit),
1799 ARGIN(const Instruction *ins))
1801 int op, i;
1802 int ok = 0;
1803 op_info_t *op_info;
1805 /* XXX move these statics into IMCC_INFO */
1806 static PackFile_Debug *debug_seg;
1807 static int ins_line;
1808 static opcode_t *pc;
1809 static opcode_t npc;
1810 /* XXX end */
1812 #if IMC_TRACE_HIGH
1813 PIO_eprintf(NULL, "e_pbc_emit\n");
1814 #endif
1816 /* first instruction, do initialisation ... */
1817 if (ins == unit->instructions) {
1818 int ins_size;
1820 const int oldsize = get_old_size(interp, &ins_line);
1821 const int code_size = get_codesize(interp, unit, &ins_size);
1822 const int bytes = (oldsize + code_size) * sizeof (opcode_t);
1824 IMCC_debug(interp, DEBUG_PBC, "code_size(ops) %d oldsize %d\n",
1825 code_size, oldsize);
1827 constant_folding(interp, unit);
1828 store_sub_size(code_size, ins_size);
1831 * allocate code and pic_index
1833 * pic_index is half the size of the code, as one PIC-cachable opcode
1834 * is at least two opcodes wide - see below how to further decrease
1835 * this storage
1837 interp->code->base.data = (opcode_t *)
1838 mem_sys_realloc(interp->code->base.data, bytes);
1840 interp->code->pic_index->data = (opcode_t *)
1841 mem_sys_realloc(interp->code->pic_index->data, bytes/2);
1843 interp->code->base.size = oldsize + code_size;
1844 interp->code->pic_index->size = (oldsize + code_size) / 2;
1846 pc = (opcode_t *)interp->code->base.data + oldsize;
1847 npc = 0;
1849 /* add debug if necessary */
1850 if (IMCC_INFO(interp)->optimizer_level == 0
1851 || IMCC_INFO(interp)->optimizer_level == OPT_PASM) {
1852 const char * const sourcefile = unit->file;
1854 /* FIXME length and multiple subs */
1855 debug_seg = Parrot_new_debug_seg(interp,
1856 interp->code, (size_t) ins_line + ins_size + 1);
1858 Parrot_debug_add_mapping(interp, debug_seg, ins_line,
1859 PF_DEBUGMAPPINGTYPE_FILENAME, sourcefile, 0);
1861 else
1862 debug_seg = NULL;
1864 /* if item is a PCC_SUB entry then store it constants */
1865 if (ins->symregs[0] && ins->symregs[0]->pcc_sub) {
1867 #if IMC_TRACE
1868 PIO_eprintf(NULL, "pbc.c: e_pbc_emit (pcc_sub=%s)\n",
1869 ins->symregs[0]->name);
1870 #endif
1872 add_const_pmc_sub(interp, ins->symregs[0], oldsize,
1873 oldsize + code_size);
1875 else {
1876 /* need a dummy to hold register usage */
1877 SymReg * const r = mk_sub_label(interp, "(null)");
1878 r->type = VT_PCC_SUB;
1879 r->pcc_sub = mem_allocate_zeroed_typed(pcc_sub_t);
1881 add_const_pmc_sub(interp, r, oldsize, oldsize + code_size);
1885 /* if this is not the first sub then store the sub */
1886 if (npc && unit->pasm_file && ins->symregs[0] && ins->symregs[0]->pcc_sub) {
1887 /* we can only set the offset for PASM code */
1888 add_const_pmc_sub(interp, ins->symregs[0], npc, npc);
1891 if (ins->opname && *ins->opname) {
1892 SymReg *addr, *r;
1893 opcode_t last_label;
1894 last_label = 1;
1895 #if IMC_TRACE_HIGH
1896 PIO_eprintf(NULL, "emit_pbc: op [%d %s]\n", ins->opnum, ins->opname);
1897 #endif
1898 if ((ins->type & ITBRANCH)
1899 && (addr = get_branch_reg(ins)) != 0
1900 && !REG_NEEDS_ALLOC(addr)) {
1901 /* fixup local jumps - calc offset */
1902 if (addr->color == -1)
1903 IMCC_fatal(interp, 1, "e_pbc_emit: "
1904 "no label offset defined for '%s'\n", addr->name);
1905 last_label = addr->color - npc;
1906 IMCC_debug(interp, DEBUG_PBC_FIXUP,
1907 "branch label at pc %d addr %d %s %d\n",
1908 npc, addr->color, addr->name, last_label);
1911 /* add debug line info */
1912 if (debug_seg)
1913 debug_seg->base.data[ins_line++] = (opcode_t) ins->line;
1915 op = (opcode_t)ins->opnum;
1917 /* add PIC idx */
1918 if (parrot_PIC_op_is_cached(op)) {
1919 const size_t offs = pc - interp->code->base.data;
1921 * for pic_idx fitting into a short, we could
1922 * further reduce the size by storing shorts
1923 * the relation code_size / pic_index_size could
1924 * indicate the used storage
1926 * drawback: if we reach 0xffff, we'd have to resize again
1928 interp->code->pic_index->data[offs / 2] = ++globals.cs->pic_idx;
1931 /* Start generating the bytecode */
1932 *pc++ = op;
1934 /* Get the info for that opcode */
1935 op_info = &interp->op_info_table[op];
1937 IMCC_debug(interp, DEBUG_PBC, "%d %s", npc, op_info->full_name);
1939 for (i = 0; i < op_info->op_count-1; i++) {
1940 switch (op_info->types[i]) {
1941 case PARROT_ARG_IC:
1942 /* branch instruction */
1943 if (op_info->labels[i]) {
1944 if (last_label == 1)
1945 /* we don't have a branch with offset 1 !? */
1946 IMCC_fatal(interp, 1, "e_pbc_emit: "
1947 "no label offset found\n");
1948 *pc++ = last_label;
1949 last_label = 1;
1950 break;
1951 /* else fall through */
1953 case PARROT_ARG_I:
1954 case PARROT_ARG_N:
1955 case PARROT_ARG_S:
1956 case PARROT_ARG_P:
1957 case PARROT_ARG_K:
1958 case PARROT_ARG_KI:
1959 case PARROT_ARG_KIC:
1960 case PARROT_ARG_SC:
1961 case PARROT_ARG_NC:
1962 case PARROT_ARG_PC:
1963 r = ins->symregs[i];
1965 if (r->type & VT_CONSTP)
1966 r = r->reg;
1968 *pc++ = (opcode_t) r->color;
1969 IMCC_debug(interp, DEBUG_PBC, " %d", r->color);
1970 break;
1971 case PARROT_ARG_KC:
1972 r = ins->symregs[i];
1973 if (r->set == 'K') {
1974 PARROT_ASSERT(r->color >= 0);
1975 *pc++ = r->color;
1977 else {
1978 *pc++ = build_key(interp, r);
1980 IMCC_debug(interp, DEBUG_PBC, " %d", pc[-1]);
1981 break;
1982 default:
1983 IMCC_fatal(interp, 1, "e_pbc_emit:"
1984 "unknown argtype in parrot op\n");
1985 break;
1988 if (ins->opnum == PARROT_OP_set_args_pc
1989 || ins->opnum == PARROT_OP_get_results_pc
1990 || ins->opnum == PARROT_OP_get_params_pc
1991 || ins->opnum == PARROT_OP_set_returns_pc) {
1993 /* TODO get rid of verify_signature - PIR call sigs are already
1994 * fixed, but PASM still needs it */
1995 verify_signature(interp, ins, pc);
1997 /* emit var_args part */
1998 for (; i < ins->opsize - 1; ++i) {
1999 r = ins->symregs[i];
2000 if (r->type & VT_CONSTP)
2001 r = r->reg;
2002 *pc++ = (opcode_t) r->color;
2003 IMCC_debug(interp, DEBUG_PBC, " %d", r->color);
2007 IMCC_debug(interp, DEBUG_PBC, "\t%I\n", ins);
2008 npc += ins->opsize;
2011 return ok;
2016 =item C<int e_pbc_close>
2018 RT #48260: Not yet documented!!!
2020 =cut
2025 e_pbc_close(PARROT_INTERP, SHIM(void *param))
2027 fixup_globals(interp);
2029 return 0;
2034 =back
2036 =cut
2041 * Local variables:
2042 * c-file-style: "parrot"
2043 * End:
2044 * vim: expandtab shiftwidth=4: