VPC - The Virgil Prototype Compiler
Virgil is designed to be a statically compiled language, and the first release [B-01] includes a prototype compiler that parses, typechecks, and compiles Virgil source programs and emits C source code. The C source code can then be compiled using any C compiler for the platform. Currently, VPC is tested on the x86-linux, ppc-darwin, and the AVR platforms, but the C code emitted by the compiler is not inherently limited to these platforms.
Virgil Interpreter
The Virgil language includes the notion of initialization time,
where an application can execute an initialization routine consisting of arbitrary
Virgil code during the compilation process. To support this, every Virgil compiler
must include an interpreter for the complete language. For experimentation purposes,
one can write any Virgil code and run it through the compiler's interpreter by
simply calling it in any constructor
in any component
of the program. This makes it easy to prototype algorithms and test them
inside the compiler, before they ever execute on the device! Thus,
you can make programs that test themselves as they are compiled, and the test
code is automatically thrown away by the compiler's dead code elimination pass.
You can also see a trace of the initialization code as it executes by can supplying the
-trace
option to the compiler.
Basic Usage
VPC is a whole-program compiler, and thus requires all of the code
of your Virgil program in order to produce C output code. This is because
the concept of initialization time, where your
program initializes itself and allocates its data structures during
compilation, may transitively reference any part of the program. At
the command line, you must supply VPC with all of the files that contain
your program, which can be done manually or through the use of a build
tool such as make
. Virgil then parses them all together,
typechecks, initializes, optimizes, and generates code that implements
the program into a single standalone C file.
% vpc my_files
The result is a C program output.c
which contains the translated,
optimized program, including the entire initialized heap. This file can then
be compiled with a standard compiler such as gcc
(or
avr-gcc
for the AVR platform). In order for
this program to compile correctly, the Virgil program must include a
master program declaration that declares an entrypoint
method in the Virgil program. The entrypoint will correspond to the
main()
method of the C program.
Linkage Model
The C code generator can generate code for the program to run directly on
a device such as the AVR
, which has no notion of
parameters to the main method. Or the code generator can produce
a program intended to run on a UNIX system that provides
parameters to the main method. To select between these two C environments,
VPC accepts a -linkage
option that can be set to one of c:unix
or c:avr
. These linkage models also differ in how a failure of a safety
check (such as null checks or bounds checks) are reported, because Virgil's exception
model is not fully developed yet.
% vpc -linkage=c:avr my_files
Device Selection
The Virgil Language also exposes device registers and hardware interrupts to the program. The selection of the device for which to compile the program is done through a compiler option that specifies a HIL specification file that describes the device. You can find an example of a HIL specification here, as well as in the source release of VPC or in the applications section. A HIL specification is only required if your program accesses hardware state or handles hardware interrupts directly.
% vpc -device=atmega128.hil -linkage=c:avr my_files