/interpiler

Turn an interpreter into a code generator

Primary LanguageC++

Interpiler – turn an interpreter into a code generator

Interpiler is a tool that takes the LLVM IR of an interpreter and outputs a C++ class that generates code (roughly) equivalent to what the interpreter would execute if you ran it on the same input.

For instance, if you had this trivial interpreter function:

void add(int* result, int a, int b)
{
	*result = a + b;
}

Interpiler would create a class with an add method, accepting 3 llvm::Value* operands, that would append the following instructions to a BasicBlock:

%0 = add i32 %a, i32 %b
store i32 %0, i32* %result, align 4

LLVM's optimization passes can then be used to optimize the generated code and obtain something that's much more efficient than a simple interpreter would ever let you do. The biggest opportunities are probably constant folding and dead store elimination.

Additionally, you get the convenience of writing your code generation routines in a high level language (C, C++, or almost anything that can produce LLVM IR), rather than in a pseudo-readable C++ DSL for code generation.

Usage

Interpiler accepts a file representing a LLVM Module. This file can either be in LLVM IR (textual assembly) or LLVM bitcode (binary). Each function declared there will be transposed into a method in a C++ class that will emit the instructions that the function would normally execute.

USAGE: interpiler [options] <input module>

  -c=<classname>    - Output class name (defaults to module name)
  -o=<filename>     - Output files name (defaults to <classname>)
  -oh=<header.h>    - Output header file name (defaults to <filename>.h)
  -oi=<impl.cpp>    - Output implementation file name (defaults to <filename>.cpp)

License

Interpiler itself is licensed under the terms of the GPL v3 license.

As a special exception to the GPL license, you may create a larger work that contains part or all of the Interpiler code generator skeleton and distribute that work under the terms of your choice.

Building

Interpiler links against LLVM and as such needs a host of its libraries. The Xcode project links against said libraries with my own local path, which is unlikely to be the same as yours.

I'll probably eventually make it a "normal" LLVM tool in the future, that uses CMake like the others. For now, poke me if you need help to build it on Linux, this may motivate me to accelerate the changes.

Limitations

Interpiler cannot generate calls to functions that have a declaration in the same module (because that function will be "interpiled" as well and will no longer have a definition). Calling externals is not an issue, though. Be sure that the functions that you call are either inlined or not declared in the same module.

Interpiler has only been (somewhat) tested on modules generated by Clang. YMMV with other compilers.

Branches need special treatment. See brainfuck's compile.cpp for an example.

So far, I've only implemented generation for the instructions that I needed to get my things going. Feel free to contribute!