Step 05 · Symbol lookup & calling main
auto sym = jit->lookup("main");
if (!sym) /* surface toString(sym.takeError()) */;
auto fnPtr = sym->toPtr<int(*)()>();
int exitCode = fnPtr();
lookup triggers materialisation: parsing/optimising hasn't finished
when addIRModule returns; the work happens when a symbol is
asked for. This is the entry point to ORC's laziness.
Type-safe call
toPtr<Fn>() is a templated cast that returns a function pointer of
the requested signature. Get the signature wrong and you'll see UB —
since mlcc always produces define i32 @main(), we ask for
int(*)().
Capturing stdout
Tests need to assert on what printf printed. We dup fd 1 to a
temp file around the call, then slurp the file. POSIX-only, but
plenty for cp-12. Production code would either:
- register a custom
puts/printfsymbol that writes to a buffer, or - run the JIT in a subprocess and read its stdout.