/
imc.c
178 lines (155 loc) · 3.89 KB
/
imc.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/*
* imc.c
*
* Main entry point and top level of IMCC compiler.
*
* Moved all register allocation and spill code to reg_alloc.c
*/
#include <string.h>
#include <assert.h>
#include "imc.h"
#include "optimizer.h"
#define COMPILE_IMMEDIATE 1
static void imc_free_unit(Parrot_Interp interp, IMC_Unit * unit);
/*
extern FILE* yyin;
*/
/* AST doesn't honor COMPILE_IMMEDIATE yet. So we need to make sure that
* the units get compiled.
*/
void
imc_compile_all_units_for_ast(Interp *interp)
{
IMC_Unit *unit, *unit_next;
#if COMPILE_IMMEDIATE
for (unit = IMCC_INFO(interp)->imc_units; unit; unit = unit_next) {
unit_next = unit->next;
imc_compile_unit(interp, unit);
}
#endif
return;
}
void
imc_compile_all_units(Interp *interp)
{
IMC_Unit *unit, *unit_next;
Instruction *ins, *ins_next;
#if ! COMPILE_IMMEDIATE
for (unit = IMCC_INFO(interp)->imc_units; unit; unit = unit_next) {
unit_next = unit->next;
imc_compile_unit(interp, unit);
}
#endif
emit_close(interp, NULL);
/* All done with compilation, now free instructions and other structures */
for (unit = IMCC_INFO(interp)->imc_units; unit;) {
unit_next = unit->next;
for (ins = unit->instructions; ins; ) {
ins_next = ins->next;
free_ins(ins);
ins = ins_next;
}
imc_free_unit(interp, unit);
unit = unit_next;
}
IMCC_INFO(interp)->imc_units = NULL;
IMCC_INFO(interp)->last_unit = NULL;
}
/* imc_compile_unit is the main loop of the IMC compiler for each unit. It
* operates on a single compilation unit at a time.
*/
void
imc_compile_unit(Interp *interp, IMC_Unit * unit) {
/* Not much here for now except the allocator */
cur_unit = unit;
imc_reg_alloc(interp, unit);
emit_flush(interp, NULL, unit);
}
/*
* Any activity required to cleanup the compiler state and be
* ready for a new compiler invocation goes here.
*/
void
imc_cleanup(Interp *interp)
{
clear_globals(interp);
mem_sys_free(IMCC_INFO(interp)->ghash.data);
IMCC_INFO(interp)->ghash.data = NULL;
}
/*
* Create a new IMC_Unit.
*/
static IMC_Unit *
imc_new_unit(IMC_Unit_Type t)
{
IMC_Unit * unit = calloc(1, sizeof(IMC_Unit));
create_symhash(&unit->hash);
unit->type = t;
return unit;
}
/*
* Create a new IMC_Unit and "open" it for construction.
* This sets the current state of the parser. The unit
* can be closed later retaining all the current state.
*/
IMC_Unit *
imc_open_unit(Parrot_Interp interp, IMC_Unit_Type t)
{
IMC_Unit * unit;
imc_info_t *imc_info;
unit = imc_new_unit(t);
imc_info = IMCC_INFO(interp);
if (!imc_info->imc_units)
imc_info->imc_units = unit;
if (!imc_info->ghash.data)
create_symhash(&imc_info->ghash);
unit->prev = imc_info->last_unit;
if (imc_info->last_unit)
imc_info->last_unit->next = unit;
imc_info->last_unit = unit;
imc_info->n_comp_units++;
unit->file = imc_info->state->file;
unit->pasm_file = imc_info->state->pasm_file;
return unit;
}
/*
* Close a unit from compilation.
* Does not destroy the unit, leaves it on the
* list.
*/
void
imc_close_unit(Parrot_Interp interp, IMC_Unit * unit)
{
UNUSED(interp);
if (unit) {
#if COMPILE_IMMEDIATE
imc_compile_unit(interp, unit);
#endif
}
cur_unit = NULL;
}
static void
imc_free_unit(Parrot_Interp interp, IMC_Unit * unit)
{
imc_info_t *imc = IMCC_INFO(interp);
#if IMC_TRACE_HIGH
fprintf(stderr, "imc_free_unit()\n");
#endif
free_reglist(unit);
clear_basic_blocks(unit); /* and cfg ... */
if (!imc->n_comp_units)
IMCC_fatal(interp, 1, "imc_free_unit: non existent unit\n");
imc->n_comp_units--;
clear_locals(unit);
free(unit->hash.data);
free(unit);
}
/*
* Local variables:
* c-indentation-style: bsd
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*
* vim: expandtab shiftwidth=4:
*/