|parrotcode: Parrot Native Object Execution Subsystem|
|Contents | Documentation|
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 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 -j 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.
The exec subsystem is enabled if support is determined automatically by config/auto/jit.pl, or if the option --execcapable is explicitly specified to Configure.pl. 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 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.
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.