/*
 * $Id: /mirror/trunk/compilers/imcc/imc.h 34933 2009-01-03T21:47:27.372369Z chromatic  $
 * Copyright (C) 2002-2008, The Perl Foundation.
 */

/* $Id: /mirror/trunk/compilers/imcc/imc.h 34933 2009-01-03T21:47:27.372369Z chromatic  $ */

#ifndef PARROT_IMCC_IMC_H_GUARD
#define PARROT_IMCC_IMC_H_GUARD

#include <stdio.h>
#include <stdlib.h>

#ifdef PARROT_HAS_HEADER_SYSEXITS
#  include <sysexits.h>
#else
#  define EX_DATAERR     1
#  define EX_SOFTWARE    1
#  define EX_NOINPUT     1
#  define EX_IOERR       1
#  define EX_USAGE       1
#  define EX_UNAVAILABLE 1
#endif  /* PARROT_HAS_HEADER_SYSEXITS */

#include "parrot/parrot.h"
#include "parrot/oplib/ops.h"

/* For people without unistd.h to compile Flex lexer
 * unistd.h probably isn't required on most if any
 * platforms anyway.
 */
#ifndef PARROT_HAS_HEADER_UNISTD
#  define YY_NO_UNISTD_H 1
#endif

#define IMCC_MAX_FIX_REGS PARROT_MAX_ARGS
#if IMCC_MAX_FIX_REGS > 16
 #  error: flags wont fit
#endif

#ifdef MAIN
#  define EXTERN
#else
#  define EXTERN extern
#endif

/* IMCC reserves this character for internally generated labels
 * and identifiers that won't collide with high level compiler generated names.
 */
#define IMCC_INTERNAL_CHAR '@'

typedef struct _IMC_Unit IMC_Unit;

#include "symreg.h"
#include "instructions.h"
#include "sets.h"
#include "cfg.h"
#include "unit.h"
#include "debug.h"

#define IMCC_TRY(a, e)     do{ (e)=0; switch (setjmp(a)){ case 0:
#define IMCC_CATCH(x)     break; case (x):
#define IMCC_END_TRY      default: break; } }while (0)

#define IMCC_THROW(a, x)  longjmp((a), (x))

#define IMCC_FATAL_EXCEPTION      1
#define IMCC_FATALY_EXCEPTION     2

#define N_ELEMENTS(x) (sizeof (x)/sizeof ((x)[0]))

/* HEADERIZER BEGIN: compilers/imcc/imcc.y */
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */

PARROT_CANNOT_RETURN_NULL
Instruction * IMCC_create_itcall_label(PARROT_INTERP)
        __attribute__nonnull__(1);

void IMCC_itcall_sub(PARROT_INTERP, ARGIN(SymReg *sub))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2);

PARROT_CANNOT_RETURN_NULL
Instruction * INS_LABEL(PARROT_INTERP,
    ARGMOD_NULLOK(IMC_Unit *unit),
    ARGMOD(SymReg *r0),
    int emit)
        __attribute__nonnull__(1)
        __attribute__nonnull__(3)
        FUNC_MODIFIES(*unit)
        FUNC_MODIFIES(*r0);

#define ASSERT_ARGS_IMCC_create_itcall_label __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp)
#define ASSERT_ARGS_IMCC_itcall_sub __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(sub)
#define ASSERT_ARGS_INS_LABEL __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(r0)
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
/* HEADERIZER END: compilers/imcc/imcc.y */


/*
 * imc.c
 */

/* HEADERIZER BEGIN: compilers/imcc/imc.c */
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */

PARROT_EXPORT
void imc_cleanup(PARROT_INTERP, ARGIN_NULLOK(void *yyscanner))
        __attribute__nonnull__(1);

PARROT_EXPORT
void imc_compile_all_units(PARROT_INTERP)
        __attribute__nonnull__(1);

PARROT_EXPORT
void imc_compile_unit(PARROT_INTERP, ARGIN(IMC_Unit *unit))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2);

void imc_close_unit(PARROT_INTERP, ARGIN_NULLOK(IMC_Unit *unit))
        __attribute__nonnull__(1);

PARROT_CANNOT_RETURN_NULL
IMC_Unit * imc_open_unit(PARROT_INTERP, IMC_Unit_Type t)
        __attribute__nonnull__(1);

#define ASSERT_ARGS_imc_cleanup __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp)
#define ASSERT_ARGS_imc_compile_all_units __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp)
#define ASSERT_ARGS_imc_compile_unit __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(unit)
#define ASSERT_ARGS_imc_close_unit __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp)
#define ASSERT_ARGS_imc_open_unit __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp)
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
/* HEADERIZER END: compilers/imcc/imc.c */


/* HEADERIZER BEGIN: compilers/imcc/reg_alloc.c */
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */

void free_reglist(ARGMOD(IMC_Unit *unit))
        __attribute__nonnull__(1)
        FUNC_MODIFIES(*unit);

void graph_coloring_reg_alloc(PARROT_INTERP, ARGMOD(IMC_Unit *unit))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2)
        FUNC_MODIFIES(*unit);

unsigned int ig_test(int i, int j, int N, ARGIN(unsigned int *graph))
        __attribute__nonnull__(4);

void imc_reg_alloc(PARROT_INTERP, ARGIN_NULLOK(IMC_Unit *unit))
        __attribute__nonnull__(1);

#define ASSERT_ARGS_free_reglist __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(unit)
#define ASSERT_ARGS_graph_coloring_reg_alloc __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(unit)
#define ASSERT_ARGS_ig_test __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(graph)
#define ASSERT_ARGS_imc_reg_alloc __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp)
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
/* HEADERIZER END: compilers/imcc/reg_alloc.c */

#ifndef YY_TYPEDEF_YY_SCANNER_T
#  define YY_TYPEDEF_YY_SCANNER_T
typedef void* yyscan_t;
#endif


/* HEADERIZER BEGIN: compilers/imcc/imcparser.c */

PARROT_WARN_UNUSED_RESULT
PARROT_CAN_RETURN_NULL
Instruction * IMCC_create_itcall_label(PARROT_INTERP)
        __attribute__nonnull__(1);

void IMCC_itcall_sub(PARROT_INTERP, ARGIN(SymReg *sub))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2);

PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
Instruction * INS_LABEL(PARROT_INTERP,
    ARGMOD_NULLOK(IMC_Unit *unit),
    ARGIN(SymReg *r0),
    int emit)
        __attribute__nonnull__(1)
        __attribute__nonnull__(3);

/* HEADERIZER END: compilers/imcc/imcparser.c */

/* HEADERIZER BEGIN: compilers/imcc/parser_util.c */
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */

PARROT_EXPORT
int do_yylex_init(PARROT_INTERP, ARGOUT(yyscan_t* yyscanner))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2)
        FUNC_MODIFIES(* yyscanner);

PARROT_EXPORT
void imcc_destroy(PARROT_INTERP)
        __attribute__nonnull__(1);

PARROT_EXPORT
void imcc_init(PARROT_INTERP)
        __attribute__nonnull__(1);

PARROT_WARN_UNUSED_RESULT
int check_op(PARROT_INTERP,
    ARGOUT(char *fullname),
    ARGIN(const char *name),
    ARGIN(SymReg * const * r),
    int narg,
    int keyvec)
        __attribute__nonnull__(1)
        __attribute__nonnull__(2)
        __attribute__nonnull__(3)
        __attribute__nonnull__(4)
        FUNC_MODIFIES(*fullname);

PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
PMC * imcc_compile(PARROT_INTERP,
    ARGIN(const char *s),
    int pasm_file,
    ARGOUT(STRING **error_message))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2)
        __attribute__nonnull__(4)
        FUNC_MODIFIES(*error_message);

PARROT_CANNOT_RETURN_NULL
void * IMCC_compile_file(PARROT_INTERP, ARGIN(const char *s))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2);

PARROT_CANNOT_RETURN_NULL
void * IMCC_compile_file_s(PARROT_INTERP,
    ARGIN(const char *s),
    ARGOUT(STRING **error_message))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2)
        __attribute__nonnull__(3)
        FUNC_MODIFIES(*error_message);

PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
PMC * imcc_compile_pasm(PARROT_INTERP, ARGIN(const char *s))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2);

PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
PMC * imcc_compile_pasm_ex(PARROT_INTERP, ARGIN(const char *s))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2);

PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
PMC * IMCC_compile_pasm_s(PARROT_INTERP,
    ARGIN(const char *s),
    ARGOUT(STRING **error_message))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2)
        __attribute__nonnull__(3)
        FUNC_MODIFIES(*error_message);

PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
PMC * imcc_compile_pir(PARROT_INTERP, ARGIN(const char *s))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2);

PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
PMC * imcc_compile_pir_ex(PARROT_INTERP, ARGIN(const char *s))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2);

PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
PMC * IMCC_compile_pir_s(PARROT_INTERP,
    ARGIN(const char *s),
    ARGOUT(STRING **error_message))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2)
        __attribute__nonnull__(3)
        FUNC_MODIFIES(*error_message);

int imcc_vfprintf(PARROT_INTERP,
    ARGIN(PMC *io),
    ARGIN(const char *format),
    va_list ap)
        __attribute__nonnull__(1)
        __attribute__nonnull__(2)
        __attribute__nonnull__(3);

PARROT_WARN_UNUSED_RESULT
PARROT_CAN_RETURN_NULL
Instruction * iNEW(PARROT_INTERP,
    ARGMOD(IMC_Unit *unit),
    ARGMOD(SymReg *r0),
    ARGMOD(char *type),
    ARGIN_NULLOK(SymReg *init),
    int emit)
        __attribute__nonnull__(1)
        __attribute__nonnull__(2)
        __attribute__nonnull__(3)
        __attribute__nonnull__(4)
        FUNC_MODIFIES(*unit)
        FUNC_MODIFIES(*r0)
        FUNC_MODIFIES(*type);

PARROT_IGNORABLE_RESULT
PARROT_CAN_RETURN_NULL
Instruction * INS(PARROT_INTERP,
    ARGMOD(IMC_Unit *unit),
    ARGIN(const char *name),
    ARGIN_NULLOK(const char *fmt),
    ARGIN(SymReg **r),
    int n,
    int keyvec,
    int emit)
        __attribute__nonnull__(1)
        __attribute__nonnull__(2)
        __attribute__nonnull__(3)
        __attribute__nonnull__(5)
        FUNC_MODIFIES(*unit);

PARROT_WARN_UNUSED_RESULT
int is_op(PARROT_INTERP, ARGIN(const char *name))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2);

void op_fullname(
    ARGOUT(char *dest),
    ARGIN(const char *name),
    ARGIN(SymReg * const *args),
    int narg,
    int keyvec)
        __attribute__nonnull__(1)
        __attribute__nonnull__(2)
        __attribute__nonnull__(3)
        FUNC_MODIFIES(*dest);

void register_compilers(PARROT_INTERP)
        __attribute__nonnull__(1);

PARROT_WARN_UNUSED_RESULT
int try_find_op(PARROT_INTERP,
    ARGMOD(IMC_Unit *unit),
    ARGIN(const char *name),
    ARGMOD(SymReg **r),
    int n,
    int keyvec,
    int emit)
        __attribute__nonnull__(1)
        __attribute__nonnull__(2)
        __attribute__nonnull__(3)
        __attribute__nonnull__(4)
        FUNC_MODIFIES(*unit)
        FUNC_MODIFIES(*r);

#define ASSERT_ARGS_do_yylex_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(yyscanner)
#define ASSERT_ARGS_imcc_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp)
#define ASSERT_ARGS_imcc_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp)
#define ASSERT_ARGS_check_op __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(fullname) \
    || PARROT_ASSERT_ARG(name) \
    || PARROT_ASSERT_ARG(r)
#define ASSERT_ARGS_imcc_compile __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(s) \
    || PARROT_ASSERT_ARG(error_message)
#define ASSERT_ARGS_IMCC_compile_file __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(s)
#define ASSERT_ARGS_IMCC_compile_file_s __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(s) \
    || PARROT_ASSERT_ARG(error_message)
#define ASSERT_ARGS_imcc_compile_pasm __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(s)
#define ASSERT_ARGS_imcc_compile_pasm_ex __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(s)
#define ASSERT_ARGS_IMCC_compile_pasm_s __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(s) \
    || PARROT_ASSERT_ARG(error_message)
#define ASSERT_ARGS_imcc_compile_pir __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(s)
#define ASSERT_ARGS_imcc_compile_pir_ex __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(s)
#define ASSERT_ARGS_IMCC_compile_pir_s __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(s) \
    || PARROT_ASSERT_ARG(error_message)
#define ASSERT_ARGS_imcc_vfprintf __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(io) \
    || PARROT_ASSERT_ARG(format)
#define ASSERT_ARGS_iNEW __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(unit) \
    || PARROT_ASSERT_ARG(r0) \
    || PARROT_ASSERT_ARG(type)
#define ASSERT_ARGS_INS __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(unit) \
    || PARROT_ASSERT_ARG(name) \
    || PARROT_ASSERT_ARG(r)
#define ASSERT_ARGS_is_op __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(name)
#define ASSERT_ARGS_op_fullname __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(dest) \
    || PARROT_ASSERT_ARG(name) \
    || PARROT_ASSERT_ARG(args)
#define ASSERT_ARGS_register_compilers __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp)
#define ASSERT_ARGS_try_find_op __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(unit) \
    || PARROT_ASSERT_ARG(name) \
    || PARROT_ASSERT_ARG(r)
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
/* HEADERIZER END: compilers/imcc/parser_util.c */

/* imclexer.c */
void IMCC_print_inc(PARROT_INTERP);

/* Call convention independant API */

/* HEADERIZER BEGIN: compilers/imcc/pcc.c */
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */

void expand_pcc_sub(PARROT_INTERP,
    ARGMOD(IMC_Unit *unit),
    ARGIN(Instruction *ins))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2)
        __attribute__nonnull__(3)
        FUNC_MODIFIES(*unit);

void expand_pcc_sub_call(PARROT_INTERP,
    ARGMOD(IMC_Unit *unit),
    ARGMOD(Instruction *ins))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2)
        __attribute__nonnull__(3)
        FUNC_MODIFIES(*unit)
        FUNC_MODIFIES(*ins);

void expand_pcc_sub_ret(PARROT_INTERP,
    ARGMOD(IMC_Unit *unit),
    ARGIN(Instruction *ins))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2)
        __attribute__nonnull__(3)
        FUNC_MODIFIES(*unit);

PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
SymReg* get_const(PARROT_INTERP, ARGIN(const char *name), int type)
        __attribute__nonnull__(1)
        __attribute__nonnull__(2);

PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
SymReg* get_pasm_reg(PARROT_INTERP, ARGIN(const char *name))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2);

#define ASSERT_ARGS_expand_pcc_sub __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(unit) \
    || PARROT_ASSERT_ARG(ins)
#define ASSERT_ARGS_expand_pcc_sub_call __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(unit) \
    || PARROT_ASSERT_ARG(ins)
#define ASSERT_ARGS_expand_pcc_sub_ret __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(unit) \
    || PARROT_ASSERT_ARG(ins)
#define ASSERT_ARGS_get_const __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(name)
#define ASSERT_ARGS_get_pasm_reg __attribute__unused__ int _ASSERT_ARGS_CHECK = \
       PARROT_ASSERT_ARG(interp) \
    || PARROT_ASSERT_ARG(name)
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
/* HEADERIZER END: compilers/imcc/pcc.c */

#define PARROT_MAX_RECOVER_ERRORS 40
/* this is the number of times parrot will try to retry while compiling. */

typedef enum _enum_opt {
    OPT_NONE,
    OPT_PRE,
    OPT_CFG  = 0x002,
    OPT_SUB  = 0x004,
    OPT_PASM = 0x100,
    OPT_J    = 0x200
} enum_opt_t;

struct nodeType_t;

/* see also imcc/imcc.l struct macro_frame_t */
struct parser_state_t {
    struct parser_state_t *next;
    Interp                *interp;
    const char            *file;
    FILE                  *handle;
    int                    file_needs_free; /* is *file malloced? */
    int                    line;
    int                    pasm_file;       /* pasm_file mode of this frame */
};

typedef enum _AsmState {
    AsmDefault,
    AsmInDef,
    AsmInReturn,
    AsmInYield
} AsmState;

typedef enum _imcc_reg_allocator_t {
    IMCC_VANILLA_ALLOCATOR = 0,
    IMCC_GRAPH_ALLOCATOR
} imcc_reg_allocator;

PARROT_EXPORT void IMCC_push_parser_state(PARROT_INTERP);
PARROT_EXPORT void IMCC_pop_parser_state(PARROT_INTERP, void *yyscanner);

/* globals store the state between individual e_pbc_emit calls */
typedef struct subs_t {
    IMC_Unit      *unit;
    struct subs_t *prev;
    struct subs_t *next;
    SymHash        fixup;              /* currently set_p_pc sub names only */
    int            ins_line;           /* line number for debug */
    int            n_basic_blocks;     /* block count */
    int            pmc_const;          /* index in const table */
    size_t         size;               /* code size in ops */
} subs_t;

/* subs are kept per code segment */
typedef struct code_segment_t {
    PackFile_ByteCode     *seg;           /* bytecode segment */
    PackFile_Segment      *jit_info;      /* bblocks, register usage */
    subs_t                *subs;          /* current sub data */
    subs_t                *first;         /* first sub of code segment */
    struct code_segment_t *prev;          /* previous code segment */
    struct code_segment_t *next;          /* next code segment */
    SymHash                key_consts;    /* this seg's cached key constants */
    int                    pic_idx;       /* next index of PIC */
} code_segment_t;

typedef struct _imcc_globals_t {
    code_segment_t *cs;           /* current code segment */
    code_segment_t *first;        /* first code segment   */
    int             inter_seg_n;
} imcc_globals;

typedef struct _imc_info_t {
    void                  *yyscanner;
    struct _imc_info_t    *prev;
    IMC_Unit              *imc_units;
    IMC_Unit              *last_unit;
    IMC_Unit              *cur_unit;
    SymReg                *sr_return;
    SymReg                *cur_namespace;
    struct nodeType_t     *top_node;
    struct parser_state_t *state;
    STRING                *error_message;   /* The Error message */

    /* some values that were global... */
    SymReg               *cur_call;
    SymReg               *cur_obj;
    const char           *adv_named_id;

    /* Lex globals */
    char                 *heredoc_end;
    char                 *heredoc_content;
    char                 *cur_macro_name;

    struct macro_frame_t *frames;
    imcc_globals         *globals;

    char                 *macro_buffer;
    Hash                 *macros;
    PackFile_Debug       *debug_seg;
    opcode_t             *pc;

    /* these are used for constructing one INS */
#define IMCC_MAX_STATIC_REGS 100
    SymReg               *regs[IMCC_MAX_STATIC_REGS];
    SymReg               *keys[IMCC_MAX_FIX_REGS]; /* TODO key overflow check */
    AsmState              asm_state;
    SymHash               ghash;
    jmp_buf               jump_buf;        /* The jump for error  handling */
    int                   IMCC_DEBUG;
    int                   allocated;
    int                   allocator;
    int                   cnr;
    int                   cur_pmc_type;
    int                   debug;
    int                   dont_optimize;
    int                   emitter;
    int                   error_code;      /* The Error code. */
    int                   expect_pasm;
    int                   gc_off;
    int                   has_compile;
    int                   imcc_warn;
    int                   in_pod;
    int                   in_slice;
    int                   ins_line;
    int                   keyvec;
    int                   line;                   /* current line number */
    int                   optimizer_level;
    int                   nargs;
    int                   n_comp_units;
    int                   nkeys;
    int                   compiler_state;         /* see PBC_* flags */
    int                   verbose;
    int                   write_pbc;
    opcode_t              npc;
} imc_info_t;

/* macro structs */
#define MAX_PARAM 16

typedef struct params_t {
    char *name[MAX_PARAM];
    int   num_param;
} params_t;

typedef struct macro_t {
    char    *expansion;
    int      line;
    params_t params;
} macro_t;

#define IMCC_INFO(i) (((Parrot_Interp)(i))->imc_info)

#define IMC_TRACE      0
#define IMC_TRACE_HIGH 0

/* main.c */
#define PBC_LOAD        (1 << 0)
#define PBC_RUN         (1 << 1)
#define PBC_WRITE       (1 << 2)
#define PBC_PRE_PROCESS (1 << 3)
#define PBC_PASM_FILE   (1 << 4)
#define PBC_RUN_FILE    (1 << 5)

#define COMPILER_STATE(i) IMCC_INFO(i)->compiler_state

#define STATE_LOAD_PBC(i)      (COMPILER_STATE(i) & PBC_LOAD)
#define STATE_RUN_PBC(i)       (COMPILER_STATE(i) & PBC_RUN)
#define STATE_WRITE_PBC(i)     (COMPILER_STATE(i) & PBC_WRITE)
#define STATE_PRE_PROCESS(i)   (COMPILER_STATE(i) & PBC_PRE_PROCESS)
#define STATE_PASM_FILE(i)     (COMPILER_STATE(i) & PBC_PASM_FILE)
#define STATE_RUN_FROM_FILE(i) (COMPILER_STATE(i) & (PBC_RUN_FILE | PBC_RUN))

#define SET_STATE_LOAD_PBC(i)      (COMPILER_STATE(i) |= PBC_LOAD)
#define SET_STATE_RUN_PBC(i)       (COMPILER_STATE(i) |= PBC_RUN)
#define SET_STATE_WRITE_PBC(i)     (COMPILER_STATE(i) |= PBC_WRITE)
#define SET_STATE_PRE_PROCESS(i)   (COMPILER_STATE(i) |= PBC_PRE_PROCESS)
#define SET_STATE_PASM_FILE(i)     (COMPILER_STATE(i) |= PBC_PASM_FILE)
#define SET_STATE_RUN_FROM_FILE(i) (COMPILER_STATE(i) |= PBC_RUN_FILE)

#define UNSET_STATE_LOAD_PBC(i)      (COMPILER_STATE(i) &= ~PBC_LOAD)
#define UNSET_STATE_RUN_PBC(i)       (COMPILER_STATE(i) &= ~PBC_RUN)
#define UNSET_STATE_WRITE_PBC(i)     (COMPILER_STATE(i) &= ~PBC_WRITE)
#define UNSET_STATE_PRE_PROCESS(i)   (COMPILER_STATE(i) &= ~PBC_PRE_PROCESS)
#define UNSET_STATE_PASM_FILE(i)     (COMPILER_STATE(i) &= ~PBC_PASM_FILE)
#define UNSET_STATE_RUN_FROM_FILE(i) (COMPILER_STATE(i) &= ~PBC_RUN_FILE)

/* imclexer.c */
PARROT_EXPORT FILE * imc_yyin_set(FILE *new_yyin, void *yyscanner);
PARROT_EXPORT FILE * imc_yyin_get(void *yyscanner);


#endif /* PARROT_IMCC_IMC_H_GUARD */


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