/*
 * $Id: instructions.h 23777 2007-12-12 03:36:35Z petdance $
 * Copyright (C) 2002-2007, The Perl Foundation.
 */

#ifndef PARROT_IMCC_INSTRUCTIONS_H_GUARD
#define PARROT_IMCC_INSTRUCTIONS_H_GUARD

/* Types */

enum INSTYPE {    /*instruction type can be   */
    ITBRANCH   =   0x10000, /*  branch        */
    ITPCCRET   =   0x20000, /*  PCC sub return */
    ITCALL     =   0x40000, /*  function call */
    ITLABEL    =   0x80000, /*  label         */
    ITALIAS    =  0x100000, /*  set P,P  */
    ITADDR     =  0x200000, /*  set_addr P, addr*/
    ITRESULT   =  0x400000, /*  .get_results */
    ITEXT      =  0x800000, /*  instruction is extcall in JIT */
    ITSAVES    = 0x1000000, /*  saveall/restoreall in a bsr */
    ITPCCSUB   = 0x2000000, /*  PCC sub call */
    ITPCCYIELD = 0x4000000  /*  yield from PCC call instead of return */
};


typedef struct _Instruction {
    char * op;          /* opstring w/o params */
    char * fmt;         /* printf style format string for params   */
    unsigned int flags; /* how the instruction affects each of the values */
    unsigned int type;  /* 16 bit register branches, + ITxxx */
    int keys;           /* bitmask of keys used in this instruction */
    int index;          /* index on instructions[] */
    int bbindex;        /* number of basic block containing instruction */
    struct _Instruction * prev;
    struct _Instruction * next;
    int opnum;          /* parrot op number */
    int opsize;         /* parrot op size   */
    int line;           /* source code line number */
    int n_r;            /* count of regs in **r */
    SymReg * r[1];      /* instruction is allocated variabled sized
                           to hold more SymRegs */
} Instruction;


/* XXX fix flags [bitmap]
 * int flags_r
 * int flags_w
 * int flags_jump
 */
#define INSTRUCTION_BIT(n) ((UINTVAL)1 << (n))
typedef enum {
    /* Indicate how the instruction affects each of the registers */
    IF_r0_read      = INSTRUCTION_BIT(0),
    IF_r1_read      = INSTRUCTION_BIT(1),
    IF_r2_read      = INSTRUCTION_BIT(2),
    IF_r3_read      = INSTRUCTION_BIT(3),
    /* .... */
    IF_r0_write     = INSTRUCTION_BIT(16),
    IF_r1_write     = INSTRUCTION_BIT(17),
    IF_r2_write     = INSTRUCTION_BIT(18),
    IF_r3_write     = INSTRUCTION_BIT(19),
    /* .... */
    IF_binary       = (IF_r0_write|IF_r1_read|IF_r2_read), /* templ for binary op */
    IF_unary        = (IF_r0_write|IF_r1_read),           /* templ for unary  op */
    IF_inplace      = (IF_r0_write|IF_r0_read),    /* templ for inplace unary  op */
    /* the branch flags are the low 16 bits of type
     * for upper 16 see ITXX above */
    IF_r0_branch    = INSTRUCTION_BIT(0),
    IF_r1_branch    = INSTRUCTION_BIT(1),
    IF_r2_branch    = INSTRUCTION_BIT(2),
    IF_r3_branch    = INSTRUCTION_BIT(3),
    IF_goto         = INSTRUCTION_BIT(15)
} Instruction_Flags;
#undef INSTRUCTION_BIT


/* Forward decl */
struct _IMC_Unit;


/* Functions */
/*
 * _mk_instruction and iANY are not intended for outside usage
 * please use INS
 */
#ifdef _PARSER
Instruction * _mk_instruction(const char *, const char *, int n, SymReg **, int);
#else
#  define _mk_instruction(a, b, n, c, d) dont_use(a, b)
#endif

/* Globals */

typedef struct _emittert {
    int (*open)(PARROT_INTERP, void *param);
    int (*emit)(PARROT_INTERP, void *param, struct _IMC_Unit *, const Instruction *ins);
    int (*new_sub)(PARROT_INTERP, void *param, struct _IMC_Unit *);
    int (*end_sub)(PARROT_INTERP, void *param, struct _IMC_Unit *);
    int (*close)(PARROT_INTERP, void *param);
} Emitter;

enum Emitter_type { EMIT_FILE, EMIT_PBC };

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

PARROT_API
int emit_close(PARROT_INTERP, NULLOK(void *param))
        __attribute__nonnull__(1);

PARROT_API
int emit_flush(PARROT_INTERP,
    NULLOK(void *param),
    NOTNULL(struct _IMC_Unit *unit))
        __attribute__nonnull__(1)
        __attribute__nonnull__(3);

PARROT_API
int emit_open(PARROT_INTERP, int type, NULLOK(void *param))
        __attribute__nonnull__(1);

PARROT_MALLOC
PARROT_CANNOT_RETURN_NULL
Instruction * _mk_instruction(
    ARGIN(const char *op),
    ARGIN(const char *fmt),
    int n,
    SymReg **r,
    int flags)
        __attribute__nonnull__(1)
        __attribute__nonnull__(2);

PARROT_CAN_RETURN_NULL
Instruction * delete_ins(
    NOTNULL(struct _IMC_Unit *unit),
    NOTNULL(Instruction *ins),
    int needs_freeing)
        __attribute__nonnull__(1)
        __attribute__nonnull__(2);

PARROT_CAN_RETURN_NULL
Instruction * emitb(PARROT_INTERP,
    NULLOK(struct _IMC_Unit *unit),
    NULLOK(Instruction *i))
        __attribute__nonnull__(1);

void free_ins(NOTNULL(Instruction *ins))
        __attribute__nonnull__(1);

PARROT_WARN_UNUSED_RESULT
PARROT_CAN_RETURN_NULL
SymReg * get_branch_reg(ARGIN(const Instruction *ins))
        __attribute__nonnull__(1);

int get_branch_regno(ARGIN(const Instruction *ins))
        __attribute__nonnull__(1);

void imcc_init_tables(PARROT_INTERP)
        __attribute__nonnull__(1);

int ins_print(PARROT_INTERP,
    NOTNULL(FILE *fd),
    ARGIN(const Instruction *ins))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2)
        __attribute__nonnull__(3);

int ins_reads2(ARGIN(const Instruction *ins), int t)
        __attribute__nonnull__(1);

int ins_writes2(ARGIN(const Instruction *ins), int t)
        __attribute__nonnull__(1);

void insert_ins(
    NOTNULL(struct _IMC_Unit *unit),
    NULLOK(Instruction *ins),
    NOTNULL(Instruction *tmp))
        __attribute__nonnull__(1)
        __attribute__nonnull__(3);

int instruction_reads(ARGIN(const Instruction *ins), ARGIN(const SymReg *r))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2);

int instruction_writes(
    ARGIN(const Instruction *ins),
    ARGIN(const SymReg *r))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2);

PARROT_CAN_RETURN_NULL
Instruction * move_ins(
    NOTNULL(struct _IMC_Unit *unit),
    NOTNULL(Instruction *ins),
    NOTNULL(Instruction *to))
        __attribute__nonnull__(1)
        __attribute__nonnull__(2)
        __attribute__nonnull__(3);

void prepend_ins(
    NOTNULL(struct _IMC_Unit *unit),
    NULLOK(Instruction *ins),
    NOTNULL(Instruction *tmp))
        __attribute__nonnull__(1)
        __attribute__nonnull__(3);

void subst_ins(
    NOTNULL(struct _IMC_Unit *unit),
    NOTNULL(Instruction *ins),
    NOTNULL(Instruction *tmp),
    int needs_freeing)
        __attribute__nonnull__(1)
        __attribute__nonnull__(2)
        __attribute__nonnull__(3);

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

#endif /* PARROT_IMCC_INSTRUCTIONS_H_GUARD */


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



syntax highlighted by Code2HTML, v. 0.9.1