Very experimental support for LLVM in DWScript is now in the googlecode repository, thanks to the efforts of Christian-W Budde.
This is the beginning of the opening of new realms of possibilities for DWS!
LLVM support is currently centered around jit compilation, and at the moment doesn’t extend much beyond the needs of the Mandelbrot demo (see below for what is supported right now).
LLVM CodeGen vs dwsJIT
Note that it is a different effort from the recently announced JITter for DWS, the TdwsJIT is a simple greedy just in time compiler, which works on the same structures as the interpreter, and where a goal is that jitting should be lightweight and fast enough to be applied all the time. It’s a “cheap” boost to script execution, and a hybrid architecture (cf. future article).
The LLVM codegen on the other hand involves a bit more overhead, in terms of a large DLL and longer compilation/JITting times, but has a wealth of other benefits.
The LLVM codegen isn’t tied to the interpreted structures, so it means more work down the road to get everything working, but there is much greater optimization potential, and the natively compiled code can be cached or persisted (thus mitigating or negating the compilation overhead).
Finally LLVM is of course cross-platform, and there is the potential for compiling standalone binaries as well…
Performance
No exact performance figures just yet, it’s too early and they change too often!
From initial tests, LLVM with optimization level zero (no optimization) is in the same ballpark as the dwsJIT, though with a slight JIT overhead (dwsJIT has none).
When increasing the optimization level, LLVM takes a measurable amount of time, but produces the best compiled binary on the benchmark so far! It’s only behind the hand-optimized version, and not all optimizations in LLVM are active just yet…
What’s working
Note that this is a very temporary list, as things change rapidly, so use it more as “cheat list” for what you can test right now.
What is working so far:
- Primitive expressions
- Integer
- Arithmetrical (Add, Sub, Mul, Div, Mod, Neg, Sqr & Abs)
- Arithmetrical assigns (+=, *=, -=, …, see above)
- Bit Manipulations (Sar, Shr, Shl, And, Or, Xor, Not)
- Comparisons (Less, LessEqual, Equal, GreaterEqual, Greater)
- Shortcuts such as Inc & Dec
- Min & Max (inlined)
- Float
- Arithmetrical (Add, Sub, Mul, Div, Neg, Sqr, Abs, Sqrt, Sin, Cos, Power, Exp, Ln, Log10, Log2)
- Arithmetrical assigns (+=, *=, -=, …, see above)
- Conversions (Floor, Ceil, Trunc, Round)
- Comparisons (Less, LessEqual, Equal, GreaterEqual, Greater)
- Min & Max (inlined)
- Boolean
- Logical (And, Or, Xor, Not)
- Integer
- Aggregate Types
- Arrays
- simple array types (read only!)
- only primitive types
- Records
- simple record types
- nesting is not thoroughly tested yet
- may not contain arrays
- Strings
- only constant strings
- Arrays
- Control Flow Expressions
- Branches
- If / Then
- If / Then / Else
- If / Then / Else -> Value
- Loops
- while
- repeat
- for (upward / downward, fixed / variable steps)
- Functions
- using simple variables (no var or const yet)
- main function (typically without declaration in DWS)
- may be called from other functions
- PrintLn (to print constant strings, rely on external definition)
- Branches
And here’s the list of things that are not working:
- Strings and string management (except for string constants)
- obviously no helpers as well
- Resource strings
- Dynamic arrays
- Variants
- complex array types (containing non-primitive values)
- complex record types (containing non-primitive values)
- Classes
- Fields
- Methods
- Constructors
- Self
- Visibility
- Interfaces
- Objects
- Case
- Special loop aware
- ForCharIn / ForCharCodeIn
- Continue / Break / Exit / Exit(Value)
- Exceptions (try, finally, except, raise, assert)
- Helpers
- Connectors
- Special math functions like Tan, Arc*, etc.