docs/native_exec.pod - Parrot Native Object Execution Subsystem


On supported platforms, Parrot can use the JIT subsystem to assemble a native executable binary from a Parrot program. This method wraps the VM runtime engine and a precompiled Parrot program into a single binary.

Generating a native executable

Generating a native executable is done in three steps: building a packfile, assembling a native object, and then linking the native executable.

The packfile is generated in the standard way from .pir or .pasm source by IMCC. For a program in myprog.pasm:

    ./parrot -o myprog.pbc myprog.pasm

This generates the myprog.pbc packfile. The native object is generated similarly:

    ./parrot -o myprog.o myprog.pbc

This creates a native object called myprog.o. Assembly of the executable is done by the "exec" target in the root Makefile like so:

    make EXEC=myprog exec

This generates the "myprog" executable, which runs equivalently to

    ./parrot -R jit myprog.pbc

minus the time required to JIT-compile the bytecode.

The "hello" target of the root Makefile demonstrates this method for a "Hello world" program.


Platform support

The exec subsystem is enabled if support is determined automatically by config/auto/, or if the option --execcapable is explicitly specified to The platform must support the JIT core, and some additional scaffold in the exec* sources must be provided. Implementation of such is beyond the scope of this document.

Native object generation

Native objects are generated by the "exec" run core. This core uses the JIT subsystem to compile a packfile to native instructions, then serializes it to the platform's native object format. This object is then loaded at runtime and executed using the normal JIT core.

Unlike the standard cores (switch, computed goto, etc.) which are activated by command-line switch, the exec core is invoked by IMCC when the output file specified by the -o option has a .o extension. When creating a native object this way, IMCC requires that the input be a packfile. This process therefore must be performed in two steps, building the packfile and assembling the native object, as demonstrated above.

Executable generation

A native executable is generated by linking a native object against the parrot library and the loader in exec_start.c. The "exec" target in the root Makefile does this with the compile flags used to build parrot itself. Alternatively it may be done by hand, e.g.

    gcc -o myprog myprog.o src/exec_start.o blib/lib/libparrot.a

Additional libraries may need to be included as appropriate for the platform.