DESCRIPTION ^

This file implements an API for generating bytecode. All gory details are hidden. In order to improve modularity, all bytecode generating functions take a bytecode struct parameter, which keeps track of the state; this includes a Parrot interpreter.

Since this state is private, the bytecode struct is declared in this C file, not in the header file. It is, however, declared in the header file as a struct, so you can use it as a type, but not touch its private bits. Everything you need to know should be accessible through accessor functions.

FUNCTIONS ^

static int new_const(bytecode *const bc)

Add a new constant to the constant table.

XXX This function needs to be cleaned up, as it's not really efficient: constant table is resized each time a constant is added.

int add_pmc_const(bytecode *const bc, PMC *pmc)

Add the PMC constant pmc to the constant table. This function returns the index in the constant table where pmc is stored.

int add_string_const(bytecode *const bc, char const *const str)

Add the string constant str to the constant table. This function returns the index in the constant table where str is stored.

XXX what to do with encoding-thingy "ascii"? Probably should be an extra parameter? Or should it be a STRING at this point already?

c<int add_num_const(bytecode * const bc, double f)>

XXX should f be a FLOATVAL?

Add a number constant to the constants list. The index in the constant table where f is stored is returned.

int add_key_const(bytecode *const bc, PMC *key)

Add a key constant to the constants list. XXX Implement this.

bytecode *new_bytecode(Interp *interp, char const *const filename, int bytes, int codesize)

Create a new bytecode struct, representing the bytecode for file filename

Create a new bytecode struct and return a pointer to it.

void emit_opcode(bytecode *const bc, opcode_t op)

Write the opcode op into the bytecode stream.

void emit_int_arg(bytecode *const bc, int intval)

Write an integer argument into the bytecode stream. XXX Possibly use 1 function for emitting opcodes and ints; they're the same anyway?

void emit_op_by_name(bytecode *const bc, char const *const opname)

Emit the opcode by name. opname must be a valid, signatured opname. So, print is not valid, whereas print_ic is. The opcode of the opname is looked up and written into the bytecode stream. If opname is not valid, an error message is written.

XXX Possibly bail out if error? No need to continue.

void add_sub_pmc(bytecode *const bc, char const *const subname, -- the name of this sub char const *const nsentry, -- the value of the :nsentry flag char const *const subid, -- the value of the :subid flag int vtable_index, -- vtable index, or -1 if no :vtable unsigned regs_used[], -- register usage of this sub int startoffset, -- start offset of this sub in bytecode int endoffset) -- end offset of this sub in bytecode

Add a sub PMC to the constant table. This function initializes the sub PMC.

void write_pbc_file(bytecode *const bc, char const *const filename)

Write the generated bytecode (stored somewhere in a packfile) to the file filename.

*/ void write_pbc_file(bytecode * const bc, char const * const filename) { size_t size; opcode_t *packed; FILE *fp; int result;

    /* pack the packfile */
    size   = PackFile_pack_size(bc->interp, bc->interp->code->base.pf) * sizeof (opcode_t);
    packed = (opcode_t*) mem_sys_allocate(size);
    PackFile_pack(bc->interp, bc->interp->code->base.pf, packed);

    /* write to file */
    fp = fopen(filename, "wb");

    if (fp == NULL)
        fprintf(stderr, "Couldn't open %s\n", filename);

    result = fwrite(packed, size, 1, fp);

    if (result != 1)
        fprintf(stderr, "Couldn't write %s\n", filename);

    fclose(fp);

    /* done! */
}
/*


parrot