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.

SYNOPSIS ^

  // create a bytecode object
  bytecode *bc = new_bytecode(interp, "foo.pir", codesize, bytes);

  // add a subroutine PMC
  add_sub_pmc(bc, mysub->info, sub->needlex, mysub->pragmas);

  while ( ... ) {

      // write opcodes
      int opcode = ...
      emit_opcode(bc, opcode);

      // emit constants
      int mystring = add_string_const(bc, "hello");

      // emit the constant index into bytecode stream
      emit_int_arg(bc, mystring);
  }

  // write the pbc file
  write_pbc_file(bc, "foo.pbc");

  // clean up
  destroy_bytecode(bc);

FUNCTIONS ^

static int new_pbc_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, char const *charset)
Add the string constant str to the constant table. This function returns the index in the constant table where str is stored. str is assumed to be a C-string; it is converted to a Parrot STRING object, using the character set passed in charset.XXX what to do with "encoding"?
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. The index where key is stored in the constants table is returned.
static void check_requested_constant(bytecode *const bc, unsigned index, int expectedtype)
Perform a sanity check on a requested constant. The constant at index index is requested; this function checks whether the index is valid. Then, if so, the constant is checked for its type, which must be expectedtype. This must be one of: PFC_PMC, PFC_NUMBER, PFC_STRING.
PMC *get_pmc_const(bytecode *const bc, unsigned index)
Get the PMC constant at index index in the PBC constant table.
FLOATVAL get_num_const(bytecode *const bc, unsigned index)
Get the FLOATVAL constant at index index in the PBC constant table.
STRING *get_string_const(bytecode *const bc, unsigned index)
Get the STRING constant at index index in the PBC constant table.
bytecode *new_bytecode(Interp *interp, char const *const filename)
Create a new bytecode struct, representing the bytecode for file filename. The bytecode struct contains a PackFile, which is initialized and loaded into the Parrot interpreter interp. Default bytecode segments are created, and the interpreter's iglobals field is stored as a constant PMC in the bytecode's constant table.
void create_codesegment(bytecode *const bc, int codesize)
Create a code segment of size codesize. bc's opcursor attribute is initialized; this is the pointer used to write opcodes and operands into the code segment.
void create_debugsegment(bytecode *const bc, size_t size, char const *const file)
Create a debug segment of size size.
void emit_debug_info(bytecode *const bc, int sourceline)
Emit the sourceline number in the debug segment.
void create_annotations_segment(bytecode *const bc, char const *const name)
Create an annotations segment, and an initial annotations group.
void add_annotation(bytecode *const bc, opcode_t offset, opcode_t key, opcode_t type, opcode_t value)
Add an annotation for the bytecode at offset, having a key key, of type type and a value passed in value.
void destroy_bytecode(bytecode *bc)
Destructor for bytecode struct; frees all memory.
opcode_t emit_opcode(bytecode *const bc, opcode_t op)
Write the opcode op into the bytecode stream. The bytecode offset where the instruction is written is returned.
opcode_t emit_int_arg(bytecode *const bc, int intval)
Write an integer argument into the bytecode stream. The offset in bytecode where the instruction is written is returned.
int store_key_bytecode(bytecode *const bc, opcode_t *key)
Store the bytecode for a key. The bytecode was emitted in an array, passed in key. The bytecode is unpacked into the current PackFile, pointed to by the interpreter in bc. The key PMC is added to the constants table, and the index in the constants table is returned.
static STRING *add_string_const_from_cstring(bytecode *const bc, char const *const str)
Utility function to add a C-string to the constants table. Before adding it to the constants table, the C-string is converted to a Parrot STRING first, which is returned. This function is handy if you don't want to retrieve the index in the constants table (where the string is stored), but you want the STRING representing the string instead.
PMC *generate_multi_signature(bytecode *const bc)
Generate a PMC for the multi signature, based on the types defined in multi_types type_count indicates the number of types in the list.
static PMC *create_lexinfo(bytecode *const bc, PMC *sub, lexical *const lexicals, int needlex)
Create a lexinfo PMC for the sub sub. If there are no lexicals, but the :lex flag was specified, or the sub has an :outer flag, then a lexinfo is created after all. The created lexinfo is returned.
static PMC *find_outer_sub(bytecode *const bc, char const *const outername)
Find the outer sub that has name outername. If not found, NULL is returned.XXX this function needs access to lexer, which adds a dependency. XXX This should be fixed, to make bcgen.c a complete independent module.
static PMC *get_namespace_pmc(bytecode *const bc, multi_type *const ns)
Get a PMC representing the namespace for a sub. The namespace information is passed in ns.
static PMC *create_sub_pmc(bytecode *const bc, char const *const instanceof)
Create a Sub PMC. If instanceof is not NULL, it indicates the name of a class to be used. If it's NULL, and iscoroutine is true, a Coroutine sub PMC is created; otherwise it's a normal Sub. If there was a .HLL_map directive that maps either Coroutine or Sub to some user-defined class, then that mapped class is created.
void add_sub_pmc(bytecode *const bc, sub_info *const info, int needlex, int subpragmas)
Add a sub PMC to the constant table. This function initializes the sub PMC. The index where the PMC is stored in the constant table is returned. If needlex is true, the sub will always get a lexpad; otherwise it will only have a lexpad if it has lexicals, or if it's lexically nested. The subpragmas parameter encode flags such as :immediate etc.
void write_pbc_file(bytecode *const bc, char const *const filename)
Write the generated bytecode (stored somewhere in a packfile) to the file filename.


parrot