parrotcode: Untitled | |
Contents | Compilers |
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.
// 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);
static int new_pbc_const(bytecode *const bc)
int add_pmc_const(bytecode *const bc, PMC *pmc)
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)
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"?
f
is stored is returned.
int add_key_const(bytecode *const bc, PMC *key)
key
is stored in the constants table is returned.
static void check_requested_constant(bytecode *const bc, unsigned index, int expectedtype)
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)
index
in the PBC constant table.
FLOATVAL get_num_const(bytecode *const bc, unsigned index)
index
in the PBC constant table.
STRING *get_string_const(bytecode *const bc, unsigned index)
index
in the PBC constant table.
bytecode *new_bytecode(Interp *interp, char const *const filename)
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)
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)
size
.
void emit_debug_info(bytecode *const bc, int sourceline)
sourceline
number in the debug segment.
void create_annotations_segment(bytecode *const bc, char const *const name)
void add_annotation(bytecode *const bc, opcode_t offset, opcode_t key, opcode_t type, opcode_t value)
offset
, having a key key
, of type type
and a value passed in value
.
void destroy_bytecode(bytecode *bc)
opcode_t emit_opcode(bytecode *const bc, opcode_t op)
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)
int store_key_bytecode(bytecode *const bc, opcode_t *key)
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)
PMC *generate_multi_signature(bytecode *const bc)
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)
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)
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)
ns
.
static PMC *create_sub_pmc(bytecode *const bc, char const *const instanceof)
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)
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)
filename
.
|