4 * Copyright (C) 2002-2008, The Perl Foundation.
12 #include "optimizer.h"
18 compilers/imcc/instructions.c
22 When generating the code, the instructions of the program
23 are stored in an array.
25 After the register allocation is resolved, the instructions
28 These functions operate over this array and its contents.
38 /* Global variables , forward def */
41 static Instruction
* last_ins
;
46 /* HEADERIZER HFILE: compilers/imcc/instructions.h */
48 /* HEADERIZER BEGIN: static */
49 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
51 static int e_file_close(PARROT_INTERP
, SHIM(void *param
))
52 __attribute__nonnull__(1);
54 static int e_file_emit(PARROT_INTERP
,
56 SHIM(const IMC_Unit
*unit
),
57 ARGIN(const Instruction
*ins
))
58 __attribute__nonnull__(1)
59 __attribute__nonnull__(4);
61 static int e_file_open(SHIM_INTERP
, ARGIN(void *param
))
62 __attribute__nonnull__(2);
64 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
65 /* HEADERIZER END: static */
67 static const char types
[] = "INPS";
69 static const Emitter emitters
[] = {
83 static int emitter
; /* XXX */
87 =item C<Instruction * _mk_instruction>
89 Creates a new instruction
96 PARROT_CANNOT_RETURN_NULL
98 _mk_instruction(ARGIN(const char *op
), ARGIN(const char *fmt
), int n
,
99 ARGIN(SymReg
* const *r
), int flags
)
101 const size_t reg_space
= (n
> 1) ? (sizeof (SymReg
*) * (n
- 1)) : 0;
102 Instruction
* const ins
=
103 (Instruction
*)mem_sys_allocate_zeroed(sizeof (Instruction
) + reg_space
);
106 ins
->opname
= str_dup(op
);
107 ins
->format
= str_dup(fmt
);
108 ins
->symreg_count
= n
;
110 for (i
= 0; i
< n
; i
++)
111 ins
->symregs
[i
] = r
[i
];
121 * Some instructions don't have a hint in op_info that they work
122 * on all registers or all registers of a given type (e.g., cleari)
123 * These instructions need special handling at various points in the code.
126 static int w_special
[1+4*3];
130 =item C<void imcc_init_tables>
132 RT#48260: Not yet documented!!!
139 imcc_init_tables(PARROT_INTERP
)
141 const char *writes
[] = {
142 "cleari", "clearn", "clearp", "clears",
147 for (i
= 0; i
< N_ELEMENTS(writes
); i
++) {
148 const int n
= interp
->op_lib
->op_code(writes
[i
], 1);
157 =item C<int ins_writes2>
159 Returns TRUE if instruction ins writes to a register of type t
166 ins_writes2(ARGIN(const Instruction
*ins
), int t
)
170 if (ins
->opnum
== w_special
[0])
173 p
= strchr(types
, t
);
176 const size_t idx
= p
- types
;
179 for (i
= 1; i
< N_ELEMENTS(w_special
); i
+= 4)
180 if (ins
->opnum
== w_special
[i
+ idx
])
189 =item C<int instruction_reads>
191 next two functions are called very often, says gprof
199 instruction_reads(ARGIN(const Instruction
*ins
), ARGIN(const SymReg
*r
))
203 if (ins
->opnum
== PARROT_OP_set_args_pc
204 || ins
->opnum
== PARROT_OP_set_returns_pc
) {
206 for (i
= ins
->symreg_count
- 1; i
>= 0; --i
)
207 if (r
== ins
->symregs
[i
])
212 else if (ins
->opnum
== PARROT_OP_get_params_pc
||
213 ins
->opnum
== PARROT_OP_get_results_pc
) {
219 for (i
= ins
->symreg_count
- 1; i
>= 0; --i
) {
221 const SymReg
* const ri
= ins
->symregs
[i
];
226 /* this additional test for _kc ops seems to slow
227 * down instruction_reads by a huge amount compared to the
230 if (ri
->set
== 'K') {
232 for (key
= ri
->nextkey
; key
; key
= key
->nextkey
)
239 /* a sub call reads the previous args */
240 if (ins
->type
& ITPCCSUB
) {
241 while (ins
&& ins
->opnum
!= PARROT_OP_set_args_pc
)
247 for (i
= ins
->symreg_count
- 1; i
>= 0; --i
) {
248 if (ins
->symregs
[i
] == r
)
258 =item C<int instruction_writes>
260 RT#48260: Not yet documented!!!
267 instruction_writes(ARGIN(const Instruction
*ins
), ARGIN(const SymReg
*r
))
269 const int f
= ins
->flags
;
273 * a get_results opcode is before the actual sub call
274 * but for the register allocator, the effect matters, thus
275 * postpone the effect after the invoke
277 if (ins
->opnum
== PARROT_OP_get_results_pc
) {
280 /* but only if it isn't the get_results opcode of
281 * an exception_handler, which doesn't have
284 if (ins
->next
&& (ins
->next
->type
& ITPCCSUB
))
287 for (i
= ins
->symreg_count
- 1; i
>= 0; --i
) {
288 if (ins
->symregs
[i
] == r
)
294 else if (ins
->type
& ITPCCSUB
) {
297 /* can't used pcc_sub->ret due to bug #38406
298 * it seems that all sub SymRegs are shared
299 * and point to the most recemt pcc_sub
302 while (ins
&& ins
->opnum
!= PARROT_OP_get_results_pc
)
308 for (i
= ins
->symreg_count
- 1; i
>= 0; --i
) {
309 if (ins
->symregs
[i
] == r
)
316 if (ins
->opnum
== PARROT_OP_get_params_pc
) {
319 for (i
= ins
->symreg_count
- 1; i
>= 0; --i
) {
320 if (ins
->symregs
[i
] == r
)
326 else if (ins
->opnum
== PARROT_OP_set_args_pc
327 || ins
->opnum
== PARROT_OP_set_returns_pc
) {
331 for (i
= 0; i
< ins
->symreg_count
; i
++)
332 if (f
& (1 << (16 + i
)))
333 if (ins
->symregs
[i
] == r
)
341 =item C<int get_branch_regno>
343 Get the register number of an address which is a branch target
350 get_branch_regno(ARGIN(const Instruction
*ins
))
354 for (j
= ins
->opsize
- 2; j
>= 0 && ins
->symregs
[j
] ; --j
)
355 if (ins
->type
& (1 << j
))
363 =item C<SymReg * get_branch_reg>
365 Get the register corresponding to an address which is a branch target
371 PARROT_WARN_UNUSED_RESULT
372 PARROT_CAN_RETURN_NULL
374 get_branch_reg(ARGIN(const Instruction
*ins
))
376 const int r
= get_branch_regno(ins
);
379 return ins
->symregs
[r
];
384 /* some useful instruction routines */
388 =item C<Instruction * _delete_ins>
390 Delete instruction ins. It's up to the caller to actually free the memory
391 of ins, if appropriate.
393 The instruction following ins is returned.
399 PARROT_WARN_UNUSED_RESULT
400 PARROT_CAN_RETURN_NULL
402 _delete_ins(ARGMOD(struct _IMC_Unit
*unit
), ARGIN(Instruction
*ins
))
404 Instruction
* const next
= ins
->next
;
405 Instruction
* const prev
= ins
->prev
;
410 unit
->instructions
= next
;
415 unit
->last_ins
= prev
;
422 =item C<Instruction * delete_ins>
424 Delete instruction ins, and then free it.
426 The instruction following ins is returned.
432 PARROT_WARN_UNUSED_RESULT
433 PARROT_CAN_RETURN_NULL
435 delete_ins(ARGMOD(struct _IMC_Unit
*unit
), ARGMOD(Instruction
*ins
))
437 Instruction
* next
= _delete_ins(unit
, ins
);
446 =item C<void insert_ins>
455 insert_ins(ARGMOD(struct _IMC_Unit
*unit
), ARGMOD_NULLOK(Instruction
*ins
),
456 ARGMOD(Instruction
*tmp
))
459 Instruction
* const next
= unit
->instructions
;
461 unit
->instructions
= tmp
;
466 tmp
->line
= next
->line
;
469 unit
->last_ins
= tmp
;
473 Instruction
* const next
= ins
->next
;
482 unit
->last_ins
= tmp
;
485 tmp
->line
= ins
->line
;
491 =item C<void prepend_ins>
493 insert tmp before ins
500 prepend_ins(ARGMOD(struct _IMC_Unit
*unit
), ARGMOD_NULLOK(Instruction
*ins
),
501 ARGMOD(Instruction
*tmp
))
504 Instruction
* const next
= unit
->instructions
;
506 unit
->instructions
= tmp
;
509 tmp
->line
= next
->line
;
512 Instruction
* const prev
= ins
->prev
;
522 tmp
->line
= ins
->line
;
528 =item C<void subst_ins>
530 Substitute tmp for ins. Free ins if needs_freeing is true.
537 subst_ins(ARGMOD(struct _IMC_Unit
*unit
), ARGMOD(Instruction
*ins
),
538 ARGMOD(Instruction
*tmp
), int needs_freeing
)
540 Instruction
* const prev
= ins
->prev
;
545 unit
->instructions
= tmp
;
548 tmp
->next
= ins
->next
;
551 ins
->next
->prev
= tmp
;
553 unit
->last_ins
= tmp
;
556 tmp
->line
= ins
->line
;
564 =item C<Instruction * move_ins>
566 Move instruction ins from its current position to the position
567 following instruction to. Returns the instruction following the
568 initial position of ins.
574 PARROT_CAN_RETURN_NULL
576 move_ins(ARGMOD(struct _IMC_Unit
*unit
), ARGMOD(Instruction
*ins
), ARGMOD(Instruction
*to
))
578 Instruction
* const next
= _delete_ins(unit
, ins
);
579 insert_ins(unit
, to
, ins
);
586 =item C<Instruction * emitb>
588 Emit a single instruction into the current unit buffer.
594 PARROT_CAN_RETURN_NULL
596 emitb(PARROT_INTERP
, ARGMOD_NULLOK(struct _IMC_Unit
*unit
), ARGIN_NULLOK(Instruction
*i
))
602 if (!unit
->instructions
)
603 unit
->last_ins
= unit
->instructions
= i
;
605 unit
->last_ins
->next
= i
;
606 i
->prev
= unit
->last_ins
;
610 /* lexer is in next line already */
611 i
->line
= IMCC_INFO(interp
)->line
- 1;
618 =item C<void free_ins>
620 Free the Instruction structure ins.
627 free_ins(ARGMOD(Instruction
*ins
))
636 =item C<int ins_print>
638 Print details of instruction ins in file fd.
644 #define REGB_SIZE 256
646 ins_print(PARROT_INTERP
, ARGMOD(FILE *fd
), ARGIN(const Instruction
*ins
))
648 char regb
[IMCC_MAX_FIX_REGS
][REGB_SIZE
];
649 /* only long key constants can overflow */
650 char *regstr
[IMCC_MAX_FIX_REGS
];
655 PIO_eprintf(NULL
, "ins_print\n");
658 /* comments, labels and such */
659 if (!ins
->symregs
[0] || !strchr(ins
->format
, '%'))
660 return fprintf(fd
, "%s", ins
->format
);
662 for (i
= 0; i
< ins
->symreg_count
; i
++) {
663 const SymReg
*p
= ins
->symregs
[i
];
667 if (p
->type
& VT_CONSTP
)
670 if (p
->color
>= 0 && REG_NEEDS_ALLOC(p
)) {
671 snprintf(regb
[i
], REGB_SIZE
, "%c%d", p
->set
, (int)p
->color
);
674 else if (IMCC_INFO(interp
)->allocated
675 && (IMCC_INFO(interp
)->optimizer_level
& OPT_J
)
678 && REG_NEEDS_ALLOC(p
)) {
679 snprintf(regb
[i
], REGB_SIZE
,
680 "r%c%d", tolower((unsigned char)p
->set
),
684 else if (p
->type
& VTREGKEY
) {
689 while ((k
= k
->nextkey
) != NULL
) {
690 const size_t used
= strlen(regb
[i
]);
692 if (k
->reg
&& k
->reg
->color
>= 0)
693 snprintf(regb
[i
]+used
, REGB_SIZE
- used
, "%c%d",
694 k
->reg
->set
, (int)k
->reg
->color
);
695 else if (IMCC_INFO(interp
)->allocated
696 && (IMCC_INFO(interp
)->optimizer_level
& OPT_J
)
698 && k
->reg
->color
< 0)
699 snprintf(regb
[i
]+used
, REGB_SIZE
- used
, "r%c%d",
700 tolower((unsigned char)k
->reg
->set
),
701 -1 -(int)k
->reg
->color
);
703 strncat(regb
[i
], k
->name
, REGB_SIZE
- used
- 1);
706 strncat(regb
[i
], ";", REGB_SIZE
- strlen(regb
[i
]) - 1);
711 else if (p
->type
== VTCONST
714 && *p
->name
!= '\'') {
715 /* unquoted string const */
716 snprintf(regb
[i
], REGB_SIZE
, "\"%s\"", p
->name
);
723 switch (ins
->opsize
-1) {
724 case -1: /* labels */
726 len
= fprintf(fd
, ins
->format
, regstr
[0]);
729 len
= fprintf(fd
, ins
->format
, regstr
[0], regstr
[1]);
732 len
= fprintf(fd
, ins
->format
, regstr
[0], regstr
[1], regstr
[2]);
735 len
= fprintf(fd
, ins
->format
, regstr
[0], regstr
[1], regstr
[2],
739 len
= fprintf(fd
, ins
->format
, regstr
[0], regstr
[1], regstr
[2],
740 regstr
[3], regstr
[4]);
743 len
= fprintf(fd
, ins
->format
, regstr
[0], regstr
[1], regstr
[2],
744 regstr
[3], regstr
[4], regstr
[5]);
747 fprintf(stderr
, "unhandled: opsize (%d), op %s, fmt %s\n",
748 ins
->opsize
, ins
->opname
, ins
->format
);
761 =item C<static int e_file_open>
763 RT#48260: Not yet documented!!!
770 e_file_open(SHIM_INTERP
, ARGIN(void *param
))
772 char * const file
= (char *) param
;
774 if (!STREQ(file
, "-"))
775 freopen(file
, "w", stdout
);
777 printf("# IMCC does produce b0rken PASM files\n");
778 printf("# see http://guest@rt.perl.org/rt3/Ticket/Display.html?id=32392\n");
784 =item C<static int e_file_close>
786 RT#48260: Not yet documented!!!
793 e_file_close(PARROT_INTERP
, SHIM(void *param
))
797 IMCC_info(interp
, 1, "assembly module %s written.\n", output
);
803 =item C<static int e_file_emit>
805 RT#48260: Not yet documented!!!
812 e_file_emit(PARROT_INTERP
,
814 SHIM(const IMC_Unit
*unit
),
815 ARGIN(const Instruction
*ins
))
818 PIO_eprintf(NULL
, "e_file_emit\n");
820 if ((ins
->type
& ITLABEL
) || ! *ins
->opname
)
821 ins_print(interp
, stdout
, ins
);
823 imcc_fprintf(interp
, stdout
, "\t%I ", ins
);
831 =item C<int emit_open>
833 RT#48260: Not yet documented!!!
841 emit_open(PARROT_INTERP
, int type
, ARGIN_NULLOK(void *param
))
844 IMCC_INFO(interp
)->has_compile
= 0;
845 IMCC_INFO(interp
)->dont_optimize
= 0;
847 return (emitters
[emitter
]).open(interp
, param
);
852 =item C<int emit_flush>
854 RT#48260: Not yet documented!!!
862 emit_flush(PARROT_INTERP
, ARGIN_NULLOK(void *param
), ARGIN(struct _IMC_Unit
*unit
))
866 if (emitters
[emitter
].new_sub
)
867 (emitters
[emitter
]).new_sub(interp
, param
, unit
);
869 for (ins
= unit
->instructions
; ins
; ins
= ins
->next
) {
870 IMCC_debug(interp
, DEBUG_IMC
, "emit %I\n", ins
);
871 (emitters
[emitter
]).emit(interp
, param
, unit
, ins
);
874 if (emitters
[emitter
].end_sub
)
875 (emitters
[emitter
]).end_sub(interp
, param
, unit
);
882 =item C<int emit_close>
884 RT#48260: Not yet documented!!!
892 emit_close(PARROT_INTERP
, ARGIN_NULLOK(void *param
))
894 return (emitters
[emitter
]).close(interp
, param
);
907 * c-file-style: "parrot"
909 * vim: expandtab shiftwidth=4: