views:

274

answers:

8

I'm working on a program that renders iterated fractal systems. I wanted to add the functionality where someone could define their own iteration process, and compile that code so that it would run efficiently.

I currently don't know how to do this and would like tips on what to read to learn how to do this.

The main program is written in C++ and I'm familiar with C++. In fact given most of the scenarios I know how to convert it to assembly code that would accomplish the goal, but I don't know how to take the extra step to convert it to machine code. If possible I'd like to dynamically compile the code like how I believe many game system emulators work.

If it is unclear what I'm asking, tell me so I can clarify.

Thanks!

+1  A: 

LLVM should be able to do what you want to do. It allows you to form a description of the program you'd like to compile in an object-oriented manner, and then it can compile that program description into native machine code at runtime.

Adam Rosenfield
+2  A: 

Some CPU emulators treat the machine code as if it was byte code and they do a JIT compile, almost as if it was Java. This is very efficient, but it means that the developers need to write a version of the compiler for each CPU their emulator runs on and for each CPU emulated.

That usually means it only works on x86 and is annoying to anyone who would like to use something different.

They could also translate it to LLVM or Java byte code or .Net CIL and then compile it, which would also work.

In your case I am not sure that sort of thing is the best way to go. I think that I would do this by using dynamic libraries. Make a directory that is supposed to contain "plugins" and let the user compile their own. Make your program scan the directory and load each DLL or .so it finds.

Doing it this way means you spend less time writing code compilers and more time actually getting stuff done.

Zan Lynx
+2  A: 

Does the routine to be compiled dynamically need to be in any particular language. If the answer to that question is "Yes, it must be C++" you're probably out of luck. C++ is about the worst possible choice for online recompilation.

Is the dynamic portion of your application (the fractal iterator routine) a major CPU bottleneck? If you can afford using a language that isn't compiled, you can probably save yourself an awful lot of trouble. Lua and JavaScript are both heavily optimized interpreted languages that only run a few times slower than native, compiled code.

If you really need the dynamic functionality to be compiled to machine code, your best bet is probably going to be using clang/llvm. clang is the C/Objective-C front end being developed by Apple (and a few others) to make online, dynamic recompilation perform well. llvm is the backend clang uses to translate from a portable bytecode to native machine code. Be advised that clang does not currently support much of C++, since that's such a difficult language to get right.

TokenMacGuy
efficiency is a huge concern as an IFS may require anywhere from 1,000 to 100,000 iterations per pixel so making each iteration run just a little bit faster has a huge impact on the application as a whole. That is why I need to compile the scripts. I'm currently looking at LLVM at the moment.
Mark
+2  A: 

If you can write your dynamic extensions in C (not C++), you might find the Tiny C Compiler to be of use. It's available under the LGPL, it's compatible for Windows and Linux, and it's a small executable (or library) at ~100kb for the preprocessor, compiler, linker and assembler, all of which it does very fast. The downside to that, of course, is that it can't compare to the optimizations you can get with GCC. Another potential downside is that it's X86 only AFAIK.

If you did decide to write assembly, TCC can handle that -- the documentation says it supports a gas-like syntax, and it does support X86 opcodes.

TCC also fully supports ANSI C, and it's nearly fully compliant with C99.

That being said, you could either include TCC as an executable with your application or use libtcc (there's not too much documentation of libtcc online, but it's available in the source package). Either way, you can use tcc to generate dynamic or shared libraries, or executables. If you went the dynamic library route, you would just put in a Render (or whatever) function in it, and dlopen or LoadLibrary on it, and call Render to finally run the user-designed rendering. Alternatively, you could make a standalone executable and popen it, and do all your communication through the standalone's stdin and stdout.

Mark Rushakoff
+1  A: 

Nanojit is a pretty good example of what you want. It generates machine code from an intermediate langauge. It's C++, and it's small and cross-platform. I haven't used it very extensively, but I enjoyed toying around just for demos.

Lee Baldwin
+3  A: 

Since you're generating pixels to be displayed on a screen, have you considered using HLSL with dynamic shader compile? That will give you access to SIMD hardware designed for exactly this sort of thing, as well as the dynamic compiler built right into DirectX.

Crashworks
I did consider that, but I wanted support for variable precision, and most graphics cards only support 32bit precision. What I'll probably do is if they have it set for 32bit precision, I'll use HLSL, but otherwise I won't. But I do plan on the program to support infinite precision. Granted I could emulate higher precision on video cards, but I also can't depend on everyone having a video card with good processing power either. I'm not sure if an integrated video card would actually have more throughput than its coupled cpu.
Mark
For the thing they're designed to do -- linear transforms on huge arrays of floating point numbers -- GPUs are definitely faster than CPUs, because of the dedicated hardware, wide ALUs, and deep pipes. But you're right, they wouldn't be much use for other than 32-bit precision.
Crashworks
A: 

Spit the code to a file and compile it as a dynamically loaded library, then load it and call it.

Pete Kirkham
A: 

Is there are reason why you can't use a GPU-based solutions? This seems to be screaming for one.

Adhemar