/*
 * $Id: imc.c 23531 2007-12-06 16:39:18Z paultcochrane $
 * Copyright (C) 2002-2007, The Perl Foundation.
 */

/*

=head1 NAME

compilers/imcc/imc.c

=head1 DESCRIPTION

Main entry point and top level of IMCC compiler.

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 */

static void imc_free_unit(PARROT_INTERP, NOTNULL(IMC_Unit *unit))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2);

PARROT_CANNOT_RETURN_NULL
static IMC_Unit * imc_new_unit(IMC_Unit_Type t);

/* HEADERIZER END: static */

#define COMPILE_IMMEDIATE 1
/*
extern FILE* yyin;
*/


/*

=item C<PARROT_API
void
imc_compile_all_units(PARROT_INTERP)>

RT#48260: Not yet documented!!!

=cut

*/

PARROT_API
void
imc_compile_all_units(PARROT_INTERP)
{
    IMC_Unit *unit;
#if ! COMPILE_IMMEDIATE
    for (unit = IMCC_INFO(interp)->imc_units; unit;) {
        IMC_Unit * const unit_next = unit->next;
        imc_compile_unit(interp, unit);
        unit = unit_next;
    }
#endif
    emit_close(interp, NULL);
    /* All done with compilation, now free instructions and other structures */

    for (unit = IMCC_INFO(interp)->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(interp, unit);
        unit = unit_next;
    }

    IMCC_INFO(interp)->imc_units = NULL;
    IMCC_INFO(interp)->last_unit = NULL;
}

/*

=item C<PARROT_API
void
imc_compile_unit(PARROT_INTERP, NOTNULL(IMC_Unit *unit))>

imc_compile_unit is the main loop of the IMC compiler for each unit. It
operates on a single compilation unit at a time.

=cut

*/

PARROT_API
void
imc_compile_unit(PARROT_INTERP, NOTNULL(IMC_Unit *unit))
{
    /* Not much here for now except the allocator */
    IMCC_INFO(interp)->cur_unit = unit;

    imc_reg_alloc(interp, unit);
    emit_flush(interp, NULL, unit);
}

/*

=item C<PARROT_API
void
imc_cleanup(PARROT_INTERP, NULLOK(void *yyscanner))>

Any activity required to cleanup the compiler state and be
ready for a new compiler invocation goes here.

=cut

*/

PARROT_API
void
imc_cleanup(PARROT_INTERP, NULLOK(void *yyscanner))
{
    IMCC_pop_parser_state(interp, yyscanner);
    clear_globals(interp);
    mem_sys_free(IMCC_INFO(interp)->ghash.data);
    IMCC_INFO(interp)->ghash.data = NULL;
}

/*

=item C<PARROT_CANNOT_RETURN_NULL
static IMC_Unit *
imc_new_unit(IMC_Unit_Type t)>

Create a new IMC_Unit.

=cut

*/

PARROT_CANNOT_RETURN_NULL
static IMC_Unit *
imc_new_unit(IMC_Unit_Type t)
{
    IMC_Unit * const unit = (IMC_Unit *)calloc(1, sizeof (IMC_Unit));
    create_symhash(&unit->hash);
    unit->type = t;
    return unit;
}

/*

=item C<PARROT_CANNOT_RETURN_NULL
IMC_Unit *
imc_open_unit(PARROT_INTERP, IMC_Unit_Type t)>

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.

=cut

*/

PARROT_CANNOT_RETURN_NULL
IMC_Unit *
imc_open_unit(PARROT_INTERP, IMC_Unit_Type t)
{
    IMC_Unit * const unit = imc_new_unit(t);
    imc_info_t * const 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;
}

/*

=item C<void
imc_close_unit(PARROT_INTERP, NULLOK(IMC_Unit *unit))>

Close a unit from compilation.
Does not destroy the unit, leaves it on the list.

=cut

*/

void
imc_close_unit(PARROT_INTERP, NULLOK(IMC_Unit *unit))
{
#if COMPILE_IMMEDIATE
    if (unit) {
        imc_compile_unit(interp, unit);
    }
#endif

    IMCC_INFO(interp)->cur_unit = NULL;
}

/*

=item C<static void
imc_free_unit(PARROT_INTERP, NOTNULL(IMC_Unit *unit))>

RT#48260: Not yet documented!!!

=cut

*/

static void
imc_free_unit(PARROT_INTERP, NOTNULL(IMC_Unit *unit))
{
    imc_info_t * const 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);
}

/*

=back

=cut

*/

/*
 * Local variables:
 *   c-file-style: "parrot"
 * End:
 * vim: expandtab shiftwidth=4:
 */


syntax highlighted by Code2HTML, v. 0.9.1