Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

557 lines (472 sloc) 18.035 kb
/*
* Copyright (C) 2002-2014, Parrot Foundation.
*/
#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
/* 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;
typedef struct _imc_info_t imc_info_t;
/* This macro helps to prevent duplicate typedefs if some IMCC header files
are used in an embedding situation. */
#define IMCC_IMC_H_HAVE_TYPEDEFS
#include "imcc/yyscanner.h"
#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))
enum {
IMCC_FATAL_EXCEPTION = 1,
IMCC_FATALY_EXCEPTION = 2,
IMCC_PARSEFAIL_EXCEPTION = 3
};
#define N_ELEMENTS(x) (sizeof (x)/sizeof ((x)[0]))
#include "imcc/embed.h"
/* HEADERIZER BEGIN: compilers/imcc/imcc.y */
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
Instruction * IMCC_create_itcall_label(ARGMOD(imc_info_t *imcc))
__attribute__nonnull__(1)
FUNC_MODIFIES(*imcc);
void IMCC_itcall_sub(ARGMOD(imc_info_t *imcc), ARGIN(SymReg *sub))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
FUNC_MODIFIES(*imcc);
PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
Instruction * INS_LABEL(
ARGMOD(imc_info_t *imcc),
ARGMOD_NULLOK(IMC_Unit *unit),
ARGMOD(SymReg *r0),
int emit)
__attribute__nonnull__(1)
__attribute__nonnull__(3)
FUNC_MODIFIES(*imcc)
FUNC_MODIFIES(*unit)
FUNC_MODIFIES(*r0);
#define ASSERT_ARGS_IMCC_create_itcall_label __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(imcc))
#define ASSERT_ARGS_IMCC_itcall_sub __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(imcc) \
, PARROT_ASSERT_ARG(sub))
#define ASSERT_ARGS_INS_LABEL __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(imcc) \
, 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. */
void imc_cleanup(ARGMOD(imc_info_t * imcc), ARGIN_NULLOK(void *yyscanner))
__attribute__nonnull__(1)
FUNC_MODIFIES(* imcc);
void imc_close_unit(ARGMOD(imc_info_t * imcc), ARGIN_NULLOK(IMC_Unit *unit))
__attribute__nonnull__(1)
FUNC_MODIFIES(* imcc);
void imc_compile_all_units(ARGMOD(imc_info_t * imcc))
__attribute__nonnull__(1)
FUNC_MODIFIES(* imcc);
void imc_compile_unit(ARGMOD(imc_info_t * imcc), ARGIN(IMC_Unit *unit))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
FUNC_MODIFIES(* imcc);
PARROT_CANNOT_RETURN_NULL
IMC_Unit * imc_open_unit(ARGMOD(imc_info_t * imc_info), IMC_Unit_Type t)
__attribute__nonnull__(1)
FUNC_MODIFIES(* imc_info);
#define ASSERT_ARGS_imc_cleanup __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(imcc))
#define ASSERT_ARGS_imc_close_unit __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(imcc))
#define ASSERT_ARGS_imc_compile_all_units __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(imcc))
#define ASSERT_ARGS_imc_compile_unit __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(imcc) \
, PARROT_ASSERT_ARG(unit))
#define ASSERT_ARGS_imc_open_unit __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(imc_info))
/* 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 imc_reg_alloc(ARGMOD(imc_info_t * imcc), ARGIN_NULLOK(IMC_Unit *unit))
__attribute__nonnull__(1)
FUNC_MODIFIES(* imcc);
#define ASSERT_ARGS_free_reglist __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(unit))
#define ASSERT_ARGS_imc_reg_alloc __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: 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/parser_util.c */
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
void check_op(
ARGMOD(imc_info_t * imcc),
ARGOUT(op_info_t **op_info),
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)
__attribute__nonnull__(5)
FUNC_MODIFIES(* imcc)
FUNC_MODIFIES(*op_info)
FUNC_MODIFIES(*fullname);
int imcc_string_ends_with(
ARGMOD(imc_info_t * imcc),
ARGIN(const STRING *str),
ARGIN(const char *ext))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
FUNC_MODIFIES(* imcc);
PARROT_IGNORABLE_RESULT
int /*@alt void@*/
imcc_vfprintf(
ARGMOD(imc_info_t * imcc),
ARGMOD(PMC *io),
ARGIN_FORMAT(const char *format),
va_list ap)
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__format__(3, 0)
__attribute__nonnull__(3)
FUNC_MODIFIES(* imcc)
FUNC_MODIFIES(*io);
PARROT_IGNORABLE_RESULT
PARROT_CAN_RETURN_NULL
Instruction * INS(
ARGMOD(imc_info_t * imcc),
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(* imcc)
FUNC_MODIFIES(*unit);
PARROT_WARN_UNUSED_RESULT
int is_op(ARGMOD(imc_info_t * imcc), ARGIN(const char *name))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
FUNC_MODIFIES(* imcc);
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);
#define ASSERT_ARGS_check_op __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(imcc) \
, PARROT_ASSERT_ARG(op_info) \
, PARROT_ASSERT_ARG(fullname) \
, PARROT_ASSERT_ARG(name) \
, PARROT_ASSERT_ARG(r))
#define ASSERT_ARGS_imcc_string_ends_with __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(imcc) \
, PARROT_ASSERT_ARG(str) \
, PARROT_ASSERT_ARG(ext))
#define ASSERT_ARGS_imcc_vfprintf __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(imcc) \
, PARROT_ASSERT_ARG(io) \
, PARROT_ASSERT_ARG(format))
#define ASSERT_ARGS_INS __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(imcc) \
, 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(imcc) \
, 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))
/* 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(imc_info_t * imcc);
/* Call convention independent API */
/* HEADERIZER BEGIN: compilers/imcc/pcc.c */
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
void expand_pcc_sub(
ARGMOD(imc_info_t * imcc),
ARGMOD(IMC_Unit *unit),
ARGIN(Instruction *ins))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
FUNC_MODIFIES(* imcc)
FUNC_MODIFIES(*unit);
void expand_pcc_sub_call(
ARGMOD(imc_info_t * imcc),
ARGMOD(IMC_Unit *unit),
ARGMOD(Instruction *ins))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
FUNC_MODIFIES(* imcc)
FUNC_MODIFIES(*unit)
FUNC_MODIFIES(*ins);
void expand_pcc_sub_ret(
ARGMOD(imc_info_t * imcc),
ARGMOD(IMC_Unit *unit),
ARGIN(Instruction *ins))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
FUNC_MODIFIES(* imcc)
FUNC_MODIFIES(*unit);
PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
SymReg* get_const(
ARGMOD(imc_info_t * imcc),
ARGIN(const char *name),
int type)
__attribute__nonnull__(1)
__attribute__nonnull__(2)
FUNC_MODIFIES(* imcc);
PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
SymReg* get_pasm_reg(ARGMOD(imc_info_t * imcc), ARGIN(const char *name))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
FUNC_MODIFIES(* imcc);
#define ASSERT_ARGS_expand_pcc_sub __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(imcc) \
, PARROT_ASSERT_ARG(unit) \
, PARROT_ASSERT_ARG(ins))
#define ASSERT_ARGS_expand_pcc_sub_call __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(imcc) \
, PARROT_ASSERT_ARG(unit) \
, PARROT_ASSERT_ARG(ins))
#define ASSERT_ARGS_expand_pcc_sub_ret __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(imcc) \
, PARROT_ASSERT_ARG(unit) \
, PARROT_ASSERT_ARG(ins))
#define ASSERT_ARGS_get_const __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(imcc) \
, PARROT_ASSERT_ARG(name))
#define ASSERT_ARGS_get_pasm_reg __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(imcc) \
, 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, /*0x001 */
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;
STRING *file;
PIOHANDLE handle;
int line;
int pasm_file; /* pasm_file mode of this frame */
};
typedef enum _AsmState {
AsmDefault,
AsmInDef,
AsmInReturn,
AsmInYield
} AsmState;
void IMCC_push_parser_state(imc_info_t *info, STRING *filename, int is_file,
int is_pasm);
void IMCC_pop_parser_state(imc_info_t *info, void *yyscanner);
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; /* sub pmc index in const table */
int lexinfo_const; /* lexinfo pmc 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 */
} code_segment_t;
/* globals store the state between individual e_pbc_emit calls */
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;
struct _imc_info_t {
Parrot_Interp interp;
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;
SymReg *adv_named_id;
/* Lex globals */
char *heredoc_end;
char *heredoc_content;
char *cur_macro_name;
int is_def;
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 cnr;
int debug;
int dont_optimize;
int emitter;
int error_code; /* The Error code. */
int expect_pasm;
int imcc_warn;
int in_pod;
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 seen_main;
int unique_count; /* A compile-time unique value */
opcode_t npc;
};
/* 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;
typedef struct parser_state_t parser_state_t;
struct yy_buffer_state;
/* parser state structure
* the first few items are common to struct parser_state, but
* we AFAIK need this hack as flex doesn't export YY_BUFFER_STATE */
typedef struct macro_frame_t {
struct parser_state_t s;
/* macro stuff */
params_t *params;
char *heredoc_rest;
params_t expansion;
int label;
int is_macro;
struct yy_buffer_state * buffer;
} macro_frame_t;
/* main.c */
#define PBC_LOAD (1 << 0)
#define PBC_RUN (1 << 1)
#define PBC_PASM_FILE (1 << 4)
#define PBC_RUN_FILE (1 << 5)
#define COMPILER_STATE(i) (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_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_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_PASM_FILE(i) (COMPILER_STATE(i) &= ~PBC_PASM_FILE)
#define UNSET_STATE_RUN_FROM_FILE(i) (COMPILER_STATE(i) &= ~PBC_RUN_FILE)
/* imclexer.c */
void imc_yyin_set(PIOHANDLE new_yyin, void *yyscanner);
PIOHANDLE imc_yyin_get(void *yyscanner);
#endif /* PARROT_IMCC_IMC_H_GUARD */
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
*/
Jump to Line
Something went wrong with that request. Please try again.