Math-JIT
Math-JIT is a limited-scope implementation of a JIT compiler using cranelift. It compiles arithmetic expressions for the host architecture and exposes a function pointer to the result.
Functionality
The expression parsing is implemented in meval. The common arithmetic operations supported by the compiler are:
- Binary:
- Addition
- Subtraction
- Multiplication
- Division
- Powers
- Unary:
- Negation
- Functions:
- Sine, cosine, tangent
- Absolute value
- Square root
The expressions can utilize 8 variables, values of which are supplied by the
caller: x, y, a, b, c, d, sig1 and sig2. sig1 and sig2 are
in-out variables -- they can be overriden by calling special functions _1(..)
and _2(..), which set the values of the two signals to that of their arguments.
Do note that a write may override a signal before it is read, but all reads will
observe the same value. Ordering the memory read before all writes is a
possible improvement for the future.
Extendability
New 1+ argument functions can be added. Operators and syntax cannot be extended, and 0-argument functions don't work due to a bug in the parser.
What for
Walking the AST or evaluating RPN manually is slow. I'm working on a real-time modular software synthesiser, Modal, which requires 44100 executions per second for multiple modules. Interpreters are sufficient in such cases, but greatly lower the margin of safety.
Other than that, I found the toy language example in cranelift to be quite unapproachable for a complete beginner like myself. This project may prove more useful as introductory material for the codegen-related part of compilers.
Optimizations
After translating expressions to RPN, simple constant propagation is performed.
If this matters to you, make sure to wrap constant sub-expressions in
parentheses to ensure the optimization works. That is, x*pi/4 won't currently
optimize, but x*(pi/4) will.
Code please
use ;
let program = parse_from_infix.unwrap;
let mut compiler = new.unwrap;
let func = compiler.compile.unwrap;
let mut sig1 = 0.0;
let mut sig2 = 0.0;
let result = func;
assert_eq!;
assert_eq!;
assert_eq!;