NAME
src/packfile.c - Parrot PackFile API
DESCRIPTION
PackFile Manipulation Functions
This file contains all the functions required for the processing of the structure of a PackFile. It is not intended to understand the byte code stream itself, but merely to dissect and reconstruct data from the various segments. See docs/pdds/pdd13_bytecode.pod for information about the structure of the frozen bytecode.
void PackFile_destroy
Deletes a static void make_code_pointers
Makes compact/shorthand pointers.The first segments read are the default segments.
static int sub_pragma
Checks sub_pmc's pragmas (e.g.
flags like static PMC *run_sub
Runs the sub_pmc due to its :load,
:immediate,
...
pragma
static PMC *do_1_sub_pragma
Runs autoloaded or immediate bytecode,
marking the MAIN subroutine entry.
static void mark_1_seg
While the PMCs should be constant,
their possible contents such as properties aren't constructed const,
so we have to mark them.
static INTVAL find_const_iter
Iterates over a PackFile_Directory,
marking any constant segments.
Internal use only.
void mark_const_subs
Iterates over all directories and PackFile_Segments,
finding and marking any constant Subs.
void do_sub_pragmas
opcode_t PackFile_unpack
Unpacks a INTVAL PackFile_map_segments
Calls the callback function INTVAL PackFile_add_segment
Adds the Segment PackFile_Segment *PackFile_find_segment
Finds the segment with the name PackFile_Segment *PackFile_remove_segment_by_name
Finds,
removes,
and returns the segment with name
PackFile
.
:load
,
:main
,
etc.) returning 1 if the sub should be run for action
,
a pbc_action_enum_t
.
action
is one of PBC_PBC
,
PBC_LOADED
,
PBC_INIT
,
or PBC_MAIN
.
Also store the eval_pmc
in the sub structure,
so that the eval PMC is kept alive by living subs.
PackFile
from a block of memory,
ensuring that the magic number is valid and that Parrot can read this bytecode version,
Parrot,
and performing any required endian and word size transforms.Returns size of unpacked opcodes if everything is okay,
else zero (0).
callback
for each segment in the directory dir
called.
The pointer user_data
is included in each call.If a callback returns non-zero,
segment processing stops,
returning this value.
seg
to the directory dir
.
The PackFile becomes the owner of the segment; it gets destroyed when the PackFile does.
name
in the PackFile_Directory
if sub_dir
is true,
searches directories recursively.
The returned segment is still owned by the PackFile
.
name
in the PackFile_Directory
.
The caller is responsible for destroying the segment.PackFile Structure Functions
static void PackFile_set_header
Fills a PackFile *PackFile_new
Allocates a new empty PackFile *PackFile_new_dummy
Creates a new (initial) dummy PackFile. This is necessary if the interpreter doesn't load any bytecode but instead uses INTVAL PackFile_funcs_register
Registers the static const opcode_t *default_unpack
Unpacks a PackFile given a cursor into PBC. This is the default unpack.
void default_dump_header
Dumps the header of a given PackFile_Segment.
static void default_dump
Dumps a PackFile_Segment.
static void pf_register_standard_funcs
Registers a PackFile's functions; called from within PackFile_Segment *PackFile_Segment_new_seg
Creates a new segment in the given PackFile_Directory of the given static PackFile_Segment *create_seg
Creates a new PackFile_Segment for the given PackFile_ByteCode *PF_create_default_segs
Creates the bytecode, constant, and fixup segments for void PackFile_Segment_destroy
Destroys the given PackFile_Segment.
size_t PackFile_Segment_packed_size
Returns the size of the given segment, when packed, taking into account padding and alignment.
opcode_t *PackFile_Segment_pack
Packs a PackFile_Segment, returning a cursor to the start of the results.
const opcode_t *PackFile_Segment_unpack
Unpacks a PackFile_Segment, returning a cursor to the results on success and NULL otherwise.All all these functions call the related void PackFile_Segment_dump
Dumps the segment
PackFile
header with system specific data.
PackFile
and sets up the directory.Directory segment:
+----------+----------+----------+----------+ | Segment Header | | .............. | +----------+----------+----------+----------+ +----------+----------+----------+----------+ | number of directory items | +----------+----------+----------+----------+followed by a sequence of items
+----------+----------+----------+----------+ | Segment type | +----------+----------+----------+----------+ | "name" | | ... '\0' padding bytes | +----------+----------+----------+----------+ | Offset in the file | +----------+----------+----------+----------+ | Size of the segment | +----------+----------+----------+----------+"name" is a NUL-terminated c-string encoded in plain ASCII.Segment types are defined in include/parrot/packfile.h.Offset and size are in
opcode_t
.A Segment Header has these entries:
- op_count total ops of segment incl. this count - itype internal type of segment - id internal id e.g code seg nr - size size of following op array, 0 if none * data possibly empty data, or e.g. byte code
Parrot_compile_string
.
pack
/unpack
/... functions for a packfile type.
PackFile_new()
.
type
with the given name
. If add
is true, adds the segment to the directory.
file_name
. See PackFile_Segment_new_seg()
for the other arguments.
file_name
. If add
is true, the current packfile becomes the owner of these segments by adding the segments to the directory.
default_*
function.If a special is defined this gets called after.
self
.Standard Directory Functions
static PackFile_Segment *directory_new
Returns a new static void directory_dump
Dumps the directory static const opcode_t *directory_unpack
Unpacks the directory from the provided cursor.
static void directory_destroy
Destroys the directory.
static void sort_segs
Sorts the segments in static size_t directory_packed_size
Returns the size of the directory minus the value returned by static opcode_t *directory_pack
Packs the directory
PackFile_Directory
cast as a PackFile_Segment
.
self
.
dir
.
default_packed_size()
.
self
, using the given cursor.PackFile_Segment
Functions
static void segment_init
Initializes the segment PackFile_Segment *PackFile_Segment_new
Creates a new default section.
self
with the provided PackFile and the given name. Note that this duplicates the given name.
Default Function Implementations
The default functions are called before the segment specific functions and can read a block of opcode_t
data.
static void default_destroy
The default destroy function. Destroys a PackFile_Segment.
static size_t default_packed_size
Returns the default size of the segment static opcode_t *default_pack
Performs the default pack.
self
.
ByteCode
static void byte_code_destroy
Destroys the static PackFile_Segment *byte_code_new
Creates a new
PackFile_ByteCode
segment self
.
PackFile_ByteCode
segment. Ignores pf
, name
, and add
are ignored.Debug Info
static void pf_debug_destroy
Destroys the static PackFile_Segment *pf_debug_new
Creates and returns a new static size_t pf_debug_packed_size
Returns the size of the static opcode_t *pf_debug_pack
Packs the debug segment, using the given cursor.
static const opcode_t *pf_debug_unpack
Unpacks a debug segment into a PackFile_Debug structure, given the cursor.
static void pf_debug_dump
Dumps a debug segment to a human readable form.
PackFile_Debug *Parrot_new_debug_seg
Creates and appends (or resizes) a new debug seg for a code segment. Uses the given size as its size.
void Parrot_debug_add_mapping
Adds a bytecode offset to a filename mapping for a PackFile_Debug.
STRING *Parrot_debug_pc_to_filename
Returns the filename of the source for the given position in the bytecode.
void Parrot_switch_to_cs_by_nr
Switches the current bytecode segment to the segment keyed by number PackFile_ByteCode *Parrot_switch_to_cs
Switches to a bytecode segment static PackFile_Constant *clone_constant
Clones a constant (at least, if it's a Sub PMC), returning the clone.
static PackFile_Constant ** find_constants
Finds the constant table associated with a thread. For now, we need to copy constant tables because some entries aren't really constant; e.g. subroutines need to refer to namespace pointers.
void Parrot_destroy_constants
Destroys the constants for an interpreter.
PackFile_Debug
segment self
.
PackFile_Debug
segment. Ignores pf
, name
, and add
ignored.
PackFile_Debug
segment's filename in opcode_t
units.
seg
.
new_cs
, returning the old segment.
PackFile FixupTable Structure Functions
void PackFile_FixupTable_clear
Clears a PackFile FixupTable.
static void fixup_destroy
Calls static size_t fixup_packed_size
What does this do?RT #48260: Not yet documented!!!
static opcode_t *fixup_pack
Packs the fixup table for a given packfile.
static PackFile_Segment *fixup_new
Returns a new static const opcode_t *fixup_unpack
Unpacks a PackFile FixupTable from a block of memory, given a cursor.Returns one (1) if everything is okay, else zero (0).
void PackFile_FixupTable_new_entry
Adds a new fix-up entry with label and type. Creates a new PackFile FixupTable if none is present.
static PackFile_FixupEntry *find_fixup
Finds the fix-up entry in a given FixupTable static INTVAL find_fixup_iter
Internal iterator for PackFile_FixupEntry *PackFile_find_fixup_entry
Searches the whole PackFile recursively for a fix-up entry with the given
PackFile_FixupTable_clear()
with self
.
PackFile_FixupTable
segment.
ft
for type
and name
and returns it.This ignores directories. For a recursive version see PackFile_find_fixup_entry()
.
PackFile_find_fixup_entry
; recurses into directories.
type
and name
, and returns the found entry or NULL.This also recurses into directories, compared to the simplier find_fixup
which just searches one PackFile_FixupTable.PackFile ConstTable Structure Functions
void PackFile_ConstTable_clear
Clear the const opcode_t *PackFile_ConstTable_unpack
Unpacks a PackFile ConstTable from a block of memory. The format is:
static PackFile_Segment *const_new
Returns a new static void const_destroy
Destroys the
PackFile_ConstTable
self
.
opcode_t const_count * constantsReturns cursor if everything is OK, else zero (0).
PackFile_ConstTable
segment.
PackFile_ConstTable
self
.PackFile Constant Structure Functions
PackFile_Constant *PackFile_Constant_new
Allocates a new empty PackFile Constant.This is only here so we can make a new one and then do an unpack.
void PackFile_Constant_destroy
Deletes the size_t PackFile_Constant_pack_size
Determines the size of the buffer needed in order to pack the PackFile Constant into a contiguous region of memory.
const opcode_t *PackFile_Constant_unpack
Unpacks a PackFile Constant from a block of memory. The format is:
const opcode_t *PackFile_Constant_unpack_pmc
Unpacks a constant PMC.
const opcode_t *PackFile_Constant_unpack_key
Unpacks a PackFile Constant from a block of memory. The format consists of a sequence of key atoms, each with the following format:
PackFile_Segment *PackFile_Annotations_new
Creates a new annotations segment structure. Ignores the parameters void PackFile_Annotations_destroy
Frees all memory associated with an annotations segment.
size_t PackFile_Annotations_packed_size
Computes the number of opcode_ts needed to store the passed annotations segment.
opcode_t *PackFile_Annotations_pack
Packs this segment into bytecode.
const opcode_t *PackFile_Annotations_unpack
Unpacks this segment from the bytecode.
void PackFile_Annotations_dump
Produces a dump of the annotations segment.
void PackFile_Annotations_add_group
Starts a new bytecode annotation group. Takes the offset in the bytecode where the new annotations group starts.
void PackFile_Annotations_add_entry
Adds a new bytecode annotation entry. Takes the annotations segment to add the entry to, the current bytecode offset (assumed to be the greatest one so far in the currently active group), the annotation key (as an index into the constats table), the annotation value type (one of PF_ANNOTATION_KEY_TYPE_INT, PF_ANNOTATION_KEY_TYPE_STR or PF_ANNOTATION_KEY_TYPE_NUM) and the value. The value will be an integer literal in the case of type being PF_ANNOTATION_KEY_TYPE_INT, or an index into the constants table otherwise.
static PMC *make_annotation_value_pmc
Makes a PMC of the right type holding the value. Helper for PMC *PackFile_Annotations_lookup
Looks up the annotation(s) in force at the given bytecode offset. If just one particular annotation is required, it can be passed as key, and the value will be returned (or a NULL PMC if no annotation of that name is in force). Otherwise, a Hash will be returned of the all annotations. If there are none in force, an empty hash will be returned.
static PackFile *PackFile_append_pbc
Reads and appends a PBC it to the current directory. Fixes up sub addresses in newly loaded bytecode and runs void Parrot_load_bytecode
Loads and append a bytecode, PIR, or PASM file into interpreter in the current directory.
void PackFile_fixup_subs
Runs
PackFile_Constant
self
.Don't delete PMC
s or STRING
s. The GC will claim them.
opcode_t type * dataReturns cursor if everything is okay, else NULL.
opcode_t type opcode_t valueReturns cursor if everything is OK, else NULL.
name
and add
.
PackFile_Annotations_lookup()
.
:load
subs.
:load
or :immediate
subroutines for the current code segment. If eval
is given, set this as the owner of the subroutines.HISTORY
Parrot_readbc and Parrot_loadbc renamed. Trace macros, long double and 64-bit conversion work by Reini Urban 2009.
Rework by Melvin; new bytecode format, make bytecode portable. (Do endian conversion and wordsize transforms on the fly.)
leo applied and modified Juergen Boemmels packfile patch giving an extensible packfile format with directory reworked again, with common chunks (default_*
).
2003.11.21 leo: moved low level item fetch routines to new pf/pf_items.c