1 /*
2  * Copyright (C) 2002-2009, Parrot Foundation.
3  */
4 
5 /*
6 
7 =head1 NAME
8 
9 compilers/imcc/imc.c
10 
11 =head1 DESCRIPTION
12 
13 Routines for handling imc_units, which represent subs.
14 
15 Moved all register allocation and spill code to reg_alloc.c
16 
17 =head2 Functions
18 
19 =over 4
20 
21 =cut
22 
23 */
24 
25 #include <string.h>
26 #include "imc.h"
27 #include "optimizer.h"
28 
29 /* HEADERIZER HFILE: compilers/imcc/imc.h */
30 
31 /* HEADERIZER BEGIN: static */
32 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
33 
34 static void imc_free_unit(ARGMOD(imc_info_t * imcc), ARGMOD(IMC_Unit *unit))
35         __attribute__nonnull__(1)
36         __attribute__nonnull__(2)
37         FUNC_MODIFIES(* imcc)
38         FUNC_MODIFIES(*unit);
39 
40 PARROT_CANNOT_RETURN_NULL
41 PARROT_MALLOC
42 static IMC_Unit * imc_new_unit(ARGMOD(imc_info_t * imcc), IMC_Unit_Type t)
43         __attribute__nonnull__(1)
44         FUNC_MODIFIES(* imcc);
45 
46 #define ASSERT_ARGS_imc_free_unit __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
47        PARROT_ASSERT_ARG(imcc) \
48     , PARROT_ASSERT_ARG(unit))
49 #define ASSERT_ARGS_imc_new_unit __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
50        PARROT_ASSERT_ARG(imcc))
51 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
52 /* HEADERIZER END: static */
53 
54 #define COMPILE_IMMEDIATE 1
55 
56 /*
57 
58 =item C<void imc_compile_all_units(imc_info_t * imcc)>
59 
60 Compiles all imc_units, and free all memory of instructions and structures
61 afterwards.
62 
63 =cut
64 
65 */
66 
67 void
imc_compile_all_units(ARGMOD (imc_info_t * imcc))68 imc_compile_all_units(ARGMOD(imc_info_t * imcc))
69 {
70     ASSERT_ARGS(imc_compile_all_units)
71     /* compile all units created during the parse */
72     IMC_Unit *unit;
73 
74 #if ! COMPILE_IMMEDIATE
75     for (unit = imcc->imc_units; unit;) {
76         IMC_Unit * const unit_next = unit->next;
77         imc_compile_unit(imcc, unit);
78         unit = unit_next;
79     }
80 #endif
81 
82     emit_close(imcc, NULL);
83 
84     /* All done with compilation, now free all memory allocated
85      * for instructions and other structures.  */
86     for (unit = imcc->imc_units; unit;) {
87         IMC_Unit    * const unit_next = unit->next;
88         Instruction *ins;
89 
90         for (ins = unit->instructions; ins;) {
91             Instruction * const ins_next = ins->next;
92             free_ins(ins);
93             ins = ins_next;
94         }
95 
96         imc_free_unit(imcc, unit);
97         unit = unit_next;
98     }
99 
100     imcc->imc_units = NULL;
101     imcc->cur_unit  = NULL;
102     imcc->last_unit = NULL;
103 }
104 
105 
106 /*
107 
108 =item C<void imc_compile_unit(imc_info_t * imcc, IMC_Unit *unit)>
109 
110 Compiles each unit in IMCC.  This is the main loop of the compiler; it operates
111 on a single compilation unit at a time.
112 
113 =cut
114 
115 */
116 
117 void
imc_compile_unit(ARGMOD (imc_info_t * imcc),ARGIN (IMC_Unit * unit))118 imc_compile_unit(ARGMOD(imc_info_t * imcc), ARGIN(IMC_Unit *unit))
119 {
120     ASSERT_ARGS(imc_compile_unit)
121     /* Not much here for now except the allocator */
122     imcc->cur_unit = unit;
123 
124     imc_reg_alloc(imcc, unit);
125     emit_flush(imcc, NULL, unit);
126 }
127 
128 
129 /*
130 
131 =item C<void imc_cleanup(imc_info_t * imcc, void *yyscanner)>
132 
133 Cleans up the compiler state in preparation for another compiler invocation.
134 
135 =cut
136 
137 */
138 
139 void
imc_cleanup(ARGMOD (imc_info_t * imcc),ARGIN_NULLOK (void * yyscanner))140 imc_cleanup(ARGMOD(imc_info_t * imcc), ARGIN_NULLOK(void *yyscanner))
141 {
142     ASSERT_ARGS(imc_cleanup)
143     IMCC_pop_parser_state(imcc, yyscanner);
144     clear_globals(imcc);
145     mem_sys_free(imcc->ghash.data);
146     imcc->ghash.data = NULL;
147 
148     if (imcc->state)
149         imcc->state->file = STRINGNULL;
150     imcc->last_unit = NULL;
151 }
152 
153 
154 /*
155 
156 =item C<static IMC_Unit * imc_new_unit(imc_info_t * imcc, IMC_Unit_Type t)>
157 
158 Creates a new IMC_Unit of the given IMC_Unit_Type C<t>.
159 
160 =cut
161 
162 */
163 
164 PARROT_CANNOT_RETURN_NULL
165 PARROT_MALLOC
166 static IMC_Unit *
imc_new_unit(ARGMOD (imc_info_t * imcc),IMC_Unit_Type t)167 imc_new_unit(ARGMOD(imc_info_t * imcc), IMC_Unit_Type t)
168 {
169     ASSERT_ARGS(imc_new_unit)
170     IMC_Unit * const unit = mem_gc_allocate_zeroed_typed(imcc->interp, IMC_Unit);
171     create_symhash(imcc, &unit->hash);
172     unit->type = t;
173     return unit;
174 }
175 
176 
177 /*
178 
179 =item C<IMC_Unit * imc_open_unit(imc_info_t * imc_info, IMC_Unit_Type t)>
180 
181 Creates a new IMC_Unit and "open" it for construction.  This sets the current
182 state of the parser.  You can close the unit later while retaining all the
183 current state.
184 
185 =cut
186 
187 */
188 
189 PARROT_CANNOT_RETURN_NULL
190 IMC_Unit *
imc_open_unit(ARGMOD (imc_info_t * imc_info),IMC_Unit_Type t)191 imc_open_unit(ARGMOD(imc_info_t * imc_info), IMC_Unit_Type t)
192 {
193     ASSERT_ARGS(imc_open_unit)
194     IMC_Unit * const unit = imc_new_unit(imc_info, t);
195 
196     if (!imc_info->imc_units)
197         imc_info->imc_units = unit;
198 
199     if (!imc_info->ghash.data)
200         create_symhash(imc_info, &imc_info->ghash);
201 
202     unit->prev = imc_info->last_unit;
203 
204     if (imc_info->last_unit)
205         imc_info->last_unit->next = unit;
206 
207     imc_info->last_unit = unit;
208     imc_info->n_comp_units++;
209 
210     unit->file      = imc_info->state->file;
211     unit->pasm_file = imc_info->state->pasm_file;
212 
213     return unit;
214 }
215 
216 
217 /*
218 
219 =item C<void imc_close_unit(imc_info_t * imcc, IMC_Unit *unit)>
220 
221 Closes a unit from compilation.  This does not destroy the unit, but leaves it
222 on the list of units.
223 
224 =cut
225 
226 */
227 
228 void
imc_close_unit(ARGMOD (imc_info_t * imcc),ARGIN_NULLOK (IMC_Unit * unit))229 imc_close_unit(ARGMOD(imc_info_t * imcc), ARGIN_NULLOK(IMC_Unit *unit))
230 {
231     ASSERT_ARGS(imc_close_unit)
232 #if COMPILE_IMMEDIATE
233     if (unit)
234         imc_compile_unit(imcc, unit);
235 #endif
236 
237     imcc->cur_unit = NULL;
238 }
239 
240 
241 /*
242 
243 =item C<static void imc_free_unit(imc_info_t * imcc, IMC_Unit *unit)>
244 
245 Frees an IMC_Unit and all of its associated memory.
246 
247 =cut
248 
249 */
250 
251 static void
imc_free_unit(ARGMOD (imc_info_t * imcc),ARGMOD (IMC_Unit * unit))252 imc_free_unit(ARGMOD(imc_info_t * imcc), ARGMOD(IMC_Unit *unit))
253 {
254     ASSERT_ARGS(imc_free_unit)
255 
256     free_reglist(unit);
257 
258     /* and cfg ... */
259     clear_basic_blocks(unit);
260 
261     if (!imcc->n_comp_units)
262         IMCC_fatal(imcc, 1, "imc_free_unit: non existent unit\n");
263 
264     imcc->n_comp_units--;
265 
266     clear_locals(unit);
267 
268     if (unit->_namespace && unit->owns_namespace)
269         free_sym(unit->_namespace);
270     if (unit->vtable_name)
271         mem_sys_free(unit->vtable_name);
272     if (unit->instance_of)
273         mem_sys_free(unit->instance_of);
274 
275     mem_sys_free(unit->hash.data);
276     mem_sys_free(unit);
277 }
278 
279 /*
280 
281 =back
282 
283 =cut
284 
285 */
286 
287 /*
288  * Local variables:
289  *   c-file-style: "parrot"
290  * End:
291  * vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
292  */
293