Skip to content

Latest commit

 

History

History
661 lines (360 loc) · 17 KB

packfile-c.pod

File metadata and controls

661 lines (360 loc) · 17 KB

NAME

src/packfile.c - Parrot PackFile API

DESCRIPTION

This file represents the public API for the packfile subsystem. It provides several routines for working with PackFile* structures, and various packfile-related PMC types. Any PMC type for which VTABLE_get_pointer returns a PackFile* structure, and VTABLE_set_pointer takes a PackFile* can be used with this system to represent a PackFile*.

See docs/pdds/pdd13_bytecode.pod for details about the subsystem and the format of bytecode.

PackFile Manipulation Functions

void Parrot_pf_destroy(PARROT_INTERP, PackFile *pf)

Destroys a PackFile, and frees resources. This does not automatically free garbage collectable objects contained in that packfile (STRING and PMC) if they are referenced from other places.

Notice that this can cause problems, if a Packfile is destroyed, but some of its contents are not destroyed, but those contents contain indirect references to other things in the packfile which are destroyed. Use with caution.

void PackFile_destroy(PARROT_INTERP, PackFile *pf)

Deprecated. Use Parrot_pf_destroy instead. GH #1170

INTVAL Parrot_pf_serialized_size(PARROT_INTERP, PackFile *pf)

Returns the size, in bytes, that a packfile will be if serialized

STRING * Parrot_pf_serialize(PARROT_INTERP, PackFile * const pf)

Serialize a PackFile * into a STRING buffer

PackFile * Parrot_pf_deserialize(PARROT_INTERP, STRING *str)

Deserialize a packfile which is stored in a STRING buffer

void Parrot_pf_tag_constant(PARROT_INTERP, PackFile_ConstTable *ct, const int tag_idx, const int const_idx)

Tag a constant PMC with a constant STRING

PMC * Parrot_pf_subs_by_tag(PARROT_INTERP, PMC * pfpmc, STRING * flag)

Get an array of Subs in the packfile by named flag.

PMC * Parrot_pf_single_sub_by_tag(PARROT_INTERP, PMC * pfpmc, STRING * flag)

Get a single Sub from the packfile by named flag. If there are more than one Subs with the given flag, it is unspecified which one is returned.

PMC * Parrot_pf_all_tags_list(PARROT_INTERP, PMC * pfpmc)

Return a ResizableStringArray of all tags in the packfile.

PMC * Parrot_pf_all_tagged_pmcs(PARROT_INTERP, PMC * pfpmc)

Return a hash of all tags in the packfile. Each tag is a key in the hash. Each value is a ResizablePMCArray of pmcs with that tag.

PMC * Parrot_pf_all_subs(PARROT_INTERP, PMC *pfpmc)

Return an array of all Sub PMCs from the packfile

static int sub_pragma(PARROT_INTERP, pbc_action_enum_t action, const PMC *sub_pmc)

Checks sub_pmc's pragmas (e.g. flags like :load, :main, etc.) returning 1 if the sub should be run for action, a pbc_action_enum_t.

static PMC* do_1_sub_pragma(PARROT_INTERP, PMC *sub_pmc, pbc_action_enum_t action)

Runs autoloaded or immediate bytecode, marking the MAIN subroutine entry.

static void mark_1_ct_seg(PARROT_INTERP, PackFile_ConstTable *ct)

Mark one ConstTable segment for GC.

static void mark_1_bc_seg(PARROT_INTERP, PackFile_ByteCode *bc)

Mark gcables in bytecode header.

static INTVAL find_const_iter(PARROT_INTERP, PackFile_Segment *seg, void *user_data)

Iterates over a PackFile_Directory, marking any constant segments. Internal use only.

void Parrot_pf_mark_packfile(PARROT_INTERP, PackFile * pf)

Mark the contents of a PackFile.

PMC * Parrot_pf_get_packfile_main_sub(PARROT_INTERP, PMC * pbc)

Get the main function of the bytecode segment, if any.

static PMC * packfile_main(PackFile_ByteCode *bc)

Access the main function of a bytecode segment.

static void pf_do_sub_pragmas(PARROT_INTERP, PMC *pfpmc, pbc_action_enum_t action)

action is one of PBC_LOADED, PBC_INIT, or PBC_MAIN. These determine which subs get executed at this point. Some rules:

:immediate subs always execute immediately
:postcomp subs always execute immediately
:main subs execute when we have the PBC_MAIN action
:init subs execute when :main does
:load subs execute on PBC_LOAD

The argument eval_pmc is ignored.

TODO: This function and the entire underlying mechanism should be deprecated and removed. See GH #428 for details.

void do_sub_pragmas(PARROT_INTERP, PMC *pfpmc, pbc_action_enum_t action, PMC *eval_pmc)

This function and the entire underlying mechanism is deprecated and will be removed. See GH #428 for details.

For now use pf_do_sub_pragmas instead.

static void PackFile_Header_validate(PARROT_INTERP, const PackFile_Header *self, INTVAL pf_options)

Validates a PackFile_Header, ensuring that the magic number is valid and that Parrot can read this bytecode version.

Raises an exception if the header doesn't validate.

static void PackFile_Header_read_uuid(PARROT_INTERP, PackFile_Header *self, const opcode_t *packed, size_t packed_size)

Reads a PackFile_Header's UUID from a block of memory and verifies that it is valid.

static int PackFile_Header_unpack(PARROT_INTERP, PackFile_Header *self, const opcode_t *packed, size_t packed_size, INTVAL pf_options)

Unpacks a PackFile_Header from a block of memory and perform some validation to check that the head is correct.

Returns size of unpacked header.

opcode_t Parrot_pf_unpack(PARROT_INTERP, PackFile *self, const opcode_t *packed, size_t packed_size)

Unpacks a 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).

opcode_t PackFile_unpack(PARROT_INTERP, PackFile *self, const opcode_t *packed, size_t packed_size)

Deprecated: Use Parrot_pf_unpack instead. See GH #1170

PackFile Structure Functions

static void PackFile_set_header(PackFile_Header *header)

Fills a PackFile header with system specific data.

PackFile * Parrot_pf_new(PARROT_INTERP, INTVAL is_mapped)

Allocates a new empty 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
PackFile * PackFile_new(PARROT_INTERP, INTVAL is_mapped)

Deprecated: Use Parrot_pf_new instead. See GH #1170

PMC * Parrot_pf_get_packfile_pmc(PARROT_INTERP, PackFile *pf, STRING *path)

Get a new PMC to hold the PackFile* structure. The exact type of PMC returned is not important, and consuming code should not rely on any particular type being returned. The only guarantees which are made by this interface are that:

1) The PackFile* structure can be retrieved by VTABLE_get_pointer 2) The PackFile* structure is marked for GC when the PMC is marked for GC

PMC * Parrot_pf_get_current_packfile(PARROT_INTERP)

Get the interpreter's currently active PackFile

PackFile_ByteCode * Parrot_pf_get_current_code_segment(PARROT_INTERP)

Get's the interpreter's currently active bytecode segment

void Parrot_pf_set_current_packfile(PARROT_INTERP, PMC *pbc)

Set's the current packfile for the interpreter.

PackFile_ByteCode * Parrot_pf_create_default_segments(PARROT_INTERP, PMC * const pf_pmc, STRING * file_name, int add)

Create the default seguments for the given packfile. Return the ByteCode segment created.

PackFile_Debug * Parrot_pf_new_debug_segment(PARROT_INTERP, PackFile_ByteCode *cs, size_t size)

Creates and appends (or resizes) a new debug seg for a code segment. Uses the given size as its size.

PackFile_Debug * Parrot_new_debug_seg(PARROT_INTERP, PackFile_ByteCode *cs, size_t size)

Deprecated: Use Parrot_pf_new_debug_segment instead. GH #1170

void Parrot_pf_debug_add_mapping(PARROT_INTERP, PackFile_Debug *debug, opcode_t offset, STRING *filename)

Adds a bytecode offset to a filename mapping for a PackFile_Debug.

TODO: Refactor this function, it is too large and complicated.

void Parrot_debug_add_mapping(PARROT_INTERP, PackFile_Debug *debug, opcode_t offset, STRING *filename)

Deprecated: Use Parrot_pf_debug_add_mapping instead. GH #1170

STRING * Parrot_pf_debug_pc_to_filename(PARROT_INTERP, const PackFile_Debug *debug, opcode_t pc)

Returns the filename of the source for the given position in the bytecode.

STRING * Parrot_debug_pc_to_filename(PARROT_INTERP, const PackFile_Debug *debug, opcode_t pc)

Deprecated: Use Parrot_pf_debug_pc_to_filename instead. GH #1170

PackFile_ByteCode * Parrot_pf_switch_to_cs(PARROT_INTERP, PackFile_ByteCode *new_cs, int really)

Switches to a bytecode segment new_cs, returning the old segment.

PackFile_ByteCode * Parrot_switch_to_cs(PARROT_INTERP, PackFile_ByteCode *new_cs, int really)

Deprecated: Use Parrot_pf_switch_to_cs instead. GH #1170

static INTVAL find_pf_ann_idx(PackFile_Annotations *pfa, PackFile_Annotations_Key *key, UINTVAL offs)

Find the index of the active annotation at the given offset.

void Parrot_pf_annotations_add_entry(PARROT_INTERP, PackFile_Annotations *self, opcode_t offset, opcode_t key, opcode_t type, opcode_t value)

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 constants 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.

void PackFile_Annotations_add_entry(PARROT_INTERP, PackFile_Annotations *self, opcode_t offset, opcode_t key, opcode_t type, opcode_t value)

Deprecated: Use Parrot_pf_annotations_add_entry instead. GH #1170

PMC * Parrot_pf_annotations_lookup(PARROT_INTERP, PackFile_Annotations *self, opcode_t offset, STRING *name)

Looks up the annotation(s) in force at the given bytecode offset. If just one particular annotation is required, it can be passed as name, 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.

PackFile_Annotations * Parrot_pf_get_annotations_segment(PARROT_INTERP, PackFile *pf, PackFile_ByteCode *bc)

Returns the annotations segment. If none exists, create an empty one.

static void push_context(PARROT_INTERP)

Create a new context to isolate the effects of compiling code or loading pbc.

static void compile_file(PARROT_INTERP, STRING *path, INTVAL is_pasm)

Compile a PIR or PASM file from source.

Deprecate: Do not use this. The packfile subsystem should not be in the business of compiling things, and should absolutely not default to any one particular compiler object (which might not exist). Use compreg opcode to get a compiler object and the interface there to get a packfile or equivalent.

static void load_file(PARROT_INTERP, STRING *path)

Load a bytecode file and append it to the current packfile directory.

void Parrot_load_language(PARROT_INTERP, STRING *lang_name)

Load the compiler libraries for a given high-level language into the interpreter.

Deprecated: This function should either be renamed to Parrot_pf_load_language, or should not be exposed through this API. GH #1170

TODO: Refactor this function and try to reduce the size of it. It is too big.

void Parrot_load_bytecode(PARROT_INTERP, Parrot_String file_str)

Load a bytecode, PIR, or PASM file into the interpreter.

Deprecated: This function should either be renamed to Parrot_pf_load_bytecode, or should not be exposed through this API. GH #1170

TODO: We need to cleanup the way bytecode is loaded. This probably needs some major changes.

PMC * Parrot_pf_load_bytecode_search(PARROT_INTERP, STRING *file)

Load a .pbc bytecode by short name, looking in standard search paths. Return a PackfileView PMC

void Parrot_pf_fixup_subs(PARROT_INTERP, pbc_action_enum_t what, PMC *eval)

Calls :load, :init, :main, :immediate and/or :postcomp subroutines in the current packfile, depending on the value of action. See do_sub_pragmas for more details.

Use Parrot_pf_prepare_packfile_init and Parrot_pf_prepare_packfile_load (and any other variants we need to create in the future) instead.

void PackFile_fixup_subs(PARROT_INTERP, pbc_action_enum_t what, PMC *eval)

Deprecated: Use <Parrot_pf_fixup_subs> instead. GH #1170

void Parrot_pf_prepare_packfile_init(PARROT_INTERP, PMC * const pfpmc)

Ready a PackFile which has just been loaded in to Parrot. Sort out the :main function and trigger :init functions. This is for packfiles which are intended to be executed as a program.

void Parrot_pf_prepare_packfile_load(PARROT_INTERP, PMC * const pfpmc)

Ready a PackFile which has just been loaded in to Parrot. Trigger any :load functions. This is for packfiles which are intended to be used as libraries.

void Parrot_pf_write_pbc_file(PARROT_INTERP, PMC *pf_pmc, STRING *filename)

Take a Packfile or PackfileView PMC and write its contents out as a .pbc file

PackFile * Parrot_pf_read_pbc_file(PARROT_INTERP, STRING * const fullname)

Read a .pbc file with the given fullname into a PackFile structure.

static PackFile* read_pbc_file_packfile_handle(PARROT_INTERP, STRING * const fullname, PIOHANDLE io, INTVAL program_size)

Read a PackFile in from an open PIOHANDLE.

static char * read_pbc_file_bytes_handle(PARROT_INTERP, PIOHANDLE io, INTVAL program_size)

Read in the raw bytes of the packfile into a buffer. The buffer is allocated with mem_gc_realloc_n_typed, so needs to be freed by the caller.

static PackFile * read_pbc_file_packfile(PARROT_INTERP, STRING * const fullname, INTVAL program_size)

Read a pbc file into a PackFile*. May use mmap if available or direct reads from the file.

static PMC* set_current_sub(PARROT_INTERP)

Search the fixup table for a PMC matching the argument. On a match, set up the appropriate context.

If no match, set up a dummy PMC entry. In either case, return a pointer to the PMC.

void Parrot_pf_execute_bytecode_program(PARROT_INTERP, PMC *pbc, PMC *args)

Execute a PackFile* as if it were a main program. This is an entrypoint into executing a Parrot program, it is not intended (and can be dangerous) if you try to call it from within a running Parrot program

STRING * Parrot_pf_get_version_string(PARROT_INTERP, PMC * pbc)

Get a Major.Minor.Patch version number for the given packfile

static PackFile_Segment * create_seg(PARROT_INTERP, PackFile_Directory *dir, pack_file_types t, STRING *name, STRING *file_name, int add)

Creates a new PackFile_Segment for the given file_name. See Parrot_pf_new_segment() for the other arguments.

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