-
Notifications
You must be signed in to change notification settings - Fork 8
JIT with mulle clang
JIT compilation should be easy, if you have the proper mulle-objc-runtime.h
header accessible. Your JIT code should import it, which it usually does by virtue of including Foundation.h
, MulleObjC.h
or some such header.
The resulting compiled object will contain a function __load_mulle_objc
that is an __attribute__(( constructor))
function, meaning that it should execute as soon as loaded.
Depending on the JIT setup you may have to call __load_mulle_objc
yourself, to get classes, categories, strings, selectors etc. added to the runtime, if you can get at the static function symbol somehow.
There are multiple JIT options available in llvm. Make sure the JIT is able to execute static constructor functions. This is how to do it fairly lowlevel:
static int Execute(std::unique_ptr<llvm::Module> Mod, char *const *envp)
{
llvm::Module &M = *Mod;
std::string Error;
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
std::unique_ptr<llvm::ExecutionEngine> EE(
createExecutionEngine(std::move(Mod), &Error));
if (!EE) {
llvm::errs() << "unable to make execution engine: " << Error << "\n";
return 255;
}
EE->finalizeObject();
EE->runStaticConstructorsDestructors( false); # the IMPORTANT part
llvm::Function *EntryFn = M.getFunction("main");
if( EntryFn)
{
// pass in something to main
std::vector<std::string> Args;
Args.push_back(M.getModuleIdentifier());
return EE->runFunctionAsMain(EntryFn, Args, envp);
}
return( 0);
}
The lldb debugger does some funky JIT stuff, as the mulle-objc-runtime.h
header is not readily available. To support such scenarios, your code must define a top level variable __mulle_objc_objccompilerinfo
like so:
static const
struct mulle_clang_objccompilerinfo
{
unsigned int load_version;
unsigned int runtime_version;
} __mulle_objc_objccompilerinfo =
{
12, // load version must match!
// check with: mulle-clang --version
0 // 0 to not emit __load_mulle_objc
// otherwise provide the current runtime version
// as: ((0 << 20) | (13 << 8) | 1) for 0.13.1
};