Permalink
Switch branches/tags
Find file
Fetching contributors…
Cannot retrieve contributors at this time
293 lines (199 sloc) 5.86 KB
/*
* Copyright (C) 2002-2009, Parrot Foundation.
*/
/*
=head1 NAME
compilers/imcc/imc.c
=head1 DESCRIPTION
Routines for handling imc_units, which represent subs.
Moved all register allocation and spill code to reg_alloc.c
=head2 Functions
=over 4
=cut
*/
#include <string.h>
#include "imc.h"
#include "optimizer.h"
/* HEADERIZER HFILE: compilers/imcc/imc.h */
/* HEADERIZER BEGIN: static */
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
static void imc_free_unit(ARGMOD(imc_info_t * imcc), ARGMOD(IMC_Unit *unit))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
FUNC_MODIFIES(* imcc)
FUNC_MODIFIES(*unit);
PARROT_CANNOT_RETURN_NULL
PARROT_MALLOC
static IMC_Unit * imc_new_unit(ARGMOD(imc_info_t * imcc), IMC_Unit_Type t)
__attribute__nonnull__(1)
FUNC_MODIFIES(* imcc);
#define ASSERT_ARGS_imc_free_unit __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(imcc) \
, PARROT_ASSERT_ARG(unit))
#define ASSERT_ARGS_imc_new_unit __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(imcc))
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
/* HEADERIZER END: static */
#define COMPILE_IMMEDIATE 1
/*
=item C<void imc_compile_all_units(imc_info_t * imcc)>
Compiles all imc_units, and free all memory of instructions and structures
afterwards.
=cut
*/
void
imc_compile_all_units(ARGMOD(imc_info_t * imcc))
{
ASSERT_ARGS(imc_compile_all_units)
/* compile all units created during the parse */
IMC_Unit *unit;
#if ! COMPILE_IMMEDIATE
for (unit = imcc->imc_units; unit;) {
IMC_Unit * const unit_next = unit->next;
imc_compile_unit(imcc, unit);
unit = unit_next;
}
#endif
emit_close(imcc, NULL);
/* All done with compilation, now free all memory allocated
* for instructions and other structures. */
for (unit = imcc->imc_units; unit;) {
IMC_Unit * const unit_next = unit->next;
Instruction *ins;
for (ins = unit->instructions; ins;) {
Instruction * const ins_next = ins->next;
free_ins(ins);
ins = ins_next;
}
imc_free_unit(imcc, unit);
unit = unit_next;
}
imcc->imc_units = NULL;
imcc->cur_unit = NULL;
imcc->last_unit = NULL;
}
/*
=item C<void imc_compile_unit(imc_info_t * imcc, IMC_Unit *unit)>
Compiles each unit in IMCC. This is the main loop of the compiler; it operates
on a single compilation unit at a time.
=cut
*/
void
imc_compile_unit(ARGMOD(imc_info_t * imcc), ARGIN(IMC_Unit *unit))
{
ASSERT_ARGS(imc_compile_unit)
/* Not much here for now except the allocator */
imcc->cur_unit = unit;
imc_reg_alloc(imcc, unit);
emit_flush(imcc, NULL, unit);
}
/*
=item C<void imc_cleanup(imc_info_t * imcc, void *yyscanner)>
Cleans up the compiler state in preparation for another compiler invocation.
=cut
*/
void
imc_cleanup(ARGMOD(imc_info_t * imcc), ARGIN_NULLOK(void *yyscanner))
{
ASSERT_ARGS(imc_cleanup)
IMCC_pop_parser_state(imcc, yyscanner);
clear_globals(imcc);
mem_sys_free(imcc->ghash.data);
imcc->ghash.data = NULL;
if (imcc->state)
imcc->state->file = STRINGNULL;
imcc->last_unit = NULL;
}
/*
=item C<static IMC_Unit * imc_new_unit(imc_info_t * imcc, IMC_Unit_Type t)>
Creates a new IMC_Unit of the given IMC_Unit_Type C<t>.
=cut
*/
PARROT_CANNOT_RETURN_NULL
PARROT_MALLOC
static IMC_Unit *
imc_new_unit(ARGMOD(imc_info_t * imcc), IMC_Unit_Type t)
{
ASSERT_ARGS(imc_new_unit)
IMC_Unit * const unit = mem_gc_allocate_zeroed_typed(imcc->interp, IMC_Unit);
create_symhash(imcc, &unit->hash);
unit->type = t;
return unit;
}
/*
=item C<IMC_Unit * imc_open_unit(imc_info_t * imc_info, IMC_Unit_Type t)>
Creates a new IMC_Unit and "open" it for construction. This sets the current
state of the parser. You can close the unit later while retaining all the
current state.
=cut
*/
PARROT_CANNOT_RETURN_NULL
IMC_Unit *
imc_open_unit(ARGMOD(imc_info_t * imc_info), IMC_Unit_Type t)
{
ASSERT_ARGS(imc_open_unit)
IMC_Unit * const unit = imc_new_unit(imc_info, t);
if (!imc_info->imc_units)
imc_info->imc_units = unit;
if (!imc_info->ghash.data)
create_symhash(imc_info, &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;
}
/*
=item C<void imc_close_unit(imc_info_t * imcc, IMC_Unit *unit)>
Closes a unit from compilation. This does not destroy the unit, but leaves it
on the list of units.
=cut
*/
void
imc_close_unit(ARGMOD(imc_info_t * imcc), ARGIN_NULLOK(IMC_Unit *unit))
{
ASSERT_ARGS(imc_close_unit)
#if COMPILE_IMMEDIATE
if (unit)
imc_compile_unit(imcc, unit);
#endif
imcc->cur_unit = NULL;
}
/*
=item C<static void imc_free_unit(imc_info_t * imcc, IMC_Unit *unit)>
Frees an IMC_Unit and all of its associated memory.
=cut
*/
static void
imc_free_unit(ARGMOD(imc_info_t * imcc), ARGMOD(IMC_Unit *unit))
{
ASSERT_ARGS(imc_free_unit)
free_reglist(unit);
/* and cfg ... */
clear_basic_blocks(unit);
if (!imcc->n_comp_units)
IMCC_fatal(imcc, 1, "imc_free_unit: non existent unit\n");
imcc->n_comp_units--;
clear_locals(unit);
if (unit->_namespace && unit->owns_namespace)
free_sym(unit->_namespace);
if (unit->vtable_name)
mem_sys_free(unit->vtable_name);
if (unit->instance_of)
mem_sys_free(unit->instance_of);
mem_sys_free(unit->hash.data);
mem_sys_free(unit);
}
/*
=back
=cut
*/
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
*/