Voodoo Compiler

Voodoo Compiler

Robbert Haarman

2014-11-09


Introduction

The Voodoo compiler is an implementation of the Voodoo programming language. The Voodoo programming language is a low-level programming language, abstracting over the platform's instruction set and calling conventions, but otherwise leaving the programmer free to do anything at all. The Voodoo compiler is written in Ruby and generates code for i386-compatible, AMD64, ARM, and MIPS CPUs.


The Voodoo Programming Language

The Voodoo programming language page provides a detailed description of the Voodoo programming language.


Download

The Voodoo compiler is open source and freely available under the terms of the GNU Lesser General Public License, version 2.1. There are two main ways to obtain Voodoo: releases and the development branch.

The development branch is where development occurs, and has the latest features, bug fixes, and new bugs. It is recommended for developers who wish to contribute to Voodoo or develop their own software based on it.

Releases are snapshots from the development branch that have been deemed ready for public consumption. They have received some amount of testing and the included documentation matches the included software. If you want to use Voodoo, but do not want to modify the compiler itself, you should probably get one of the releases.

Releases

The latest release of the Voodoo compiler is version 1.1.4, available here: voodoo-1.1.4.tar.bz2 (73 KB). This is a maintenance release, and contains the following bug fixes and improvements:

  • References to symbols are now always position-independent, even if the symbol is not exported or imported. This means shared libraries can now have symbols that are not externally visible.
  • On AMD64, tail-call now restores all callee-save registers in the active frame to their saved values before transferring control to the function being called. Before this fix, calling code generated by the Voodoo compiler from code generated by a different compiler would, under certain circumstances, cause callee-save registers to have wrong values upon return to the code from the other compiler.
  • On AMD64, rbx is now a callee-save register, as required by the ABI.
  • More rigorous tests for expressions have been added. These exposed some bugs in the generated code on AMD64, which have been fixed.
  • The ARM code generator now emits constant pools as necessary to keep them within limited distance from the code that uses them. Previously, constant pools were only emitted at the end of blocks, which could cause the offset between a constant and an instruction that uses that constant to be larger than what can be encoded in the instruction.

Development Branch

The latest version of the Voodoo compiler is available via Git from the Voodoo Git repository. It can be checked out with the following command:

git clone git://repo.or.cz/voodoo-lang.git voodoo

Note that this is the development branch of the Voodoo compiler, so it will generally have more features than the releases on this webpage, but be less thoroughly tested.


Installation

To run the Voodoo compiler, you need to have the following software installed:

  • A Ruby implementation. MRI 1.8 and 1.9 should work. If you use something a different Ruby implementation, please let me know if it worked or not.
  • To produce object files, you will need an assembler for your target architecture.
    • For i386 and AMD64, NASM and YASM are supported
    • For other architectures, the GNU Assembler is supported
  • To produce executables, you will need a linker. If you link with the C library, the easiest way is usually to use the C compiler (cc). GNU ld will work, too, if you pass it the right options. Other linkers have not been tested.

If you have RubyGems installed, the easiest way to install the Voodoo compiler is by running the command gem install voodoo.

If you have the source code of the compiler (see Download), you can install it using the common configure, make, make install mantra. This means that the steps to installation are:

  1. Obtain the files. You can either download a release, or fetch a current development snapshot using git. If you have downloaded a release tarball, you can extract the files in it using a command like bunzip < voodoo-1.1.4.tar.bz2 | tar xf -
  2. Run configure. Enter the directory where you have stored the files. There is a script there called configure. You can run it using a command like ./configure. The script will check if you have all the required software installed and create a file Makefile.cfg for you. If configure reports that some programs are missing, you should install them first.
  3. Run make. The command make is used to perform any steps required to build the compiler. Running make without arguments will perform a default build. Afterwards, you can run make test to run the provided tests, and you can run make rdoc to generate API documentation from the Ruby source code.
  4. Run make install. The final step is to run make install to install the software and the documentation. You may have to perform this action as root or using sudo, e.g. sudo make install.

Usage

There are two main ways to use the Voodoo compiler: by running the voodooc program, or by using the Ruby API.

The voodooc program compiles a Voodoo source files. Its usage is described in the voodooc.1 manpage, included in the distribution. The following is an example of how voodooc can be used to create an executable hello from a source file hello.voo:

$ voodooc hello.voo
$ cc hello.o -o hello
$ ./hello
Hello, world!

An implementation of hello.voo can be found in the directory test of the distribution.

The second way to use the Voodoo compiler is by using it from a Ruby program. This can be used, for example, to generate code for the target platform without having to create a .voo file. The following is an example which creates an object file called fact.o, containing a definition of a function fact which computes factorials:

require 'voodoo'

generator = Voodoo::CodeGenerator.get_generator

generator.add :functions, [:export, :fact], [:label, :fact]
generator.add_function [:n],
  [:ifle, [:n, 1],
    # then
    [[:return, 1]],
    # else
    [[:let, :x, :sub, :n, 1],
     [:set, :x, :call, :fact, :x],
     [:return, :mul, :n, :x]]]

File.open('fact.o', 'w') { |outfile| generator.write outfile }

The Voodoo compiler API that is a available to Ruby programs is described in the API documentation.


Test Matrix

The following table given an overview of the platforms the Voodoo compiler has been tested on. For each platform, the table lists the machine architecture, the name of the operating system, the version of the operating system, the latest version of the Voodoo compiler that was tested, and if it worked (passed all testcases).

Architecture Operating System OS Version Voodoo Version Works?
amd64 Debian GNU/Linux 7.1 1.1.4 yes
i386 Debian GNU/Linux 7.1 1.1.4 yes
i386 DragonFly BSD 2.4.1 1.1.4 yes
mipsel Debian GNU/Linux 5.0 1.1.4 yes
arm Raspbian wheezy 1.1.4 yes
Valid XHTML 1.1! Valid CSS! Viewable with Any Browser