Hi all,
I have recently been developing an extension to the Nim compiler to support JIT'd code in a private repository. It works by utilizing clang's "-emit-llvm" flag will will emit LLVM IR code, and then with this LLVM IR code we can feed it into LLVM's ORCv2 JIT engine and dynamically compile and link code.
This project is not complete, but I thought it would be valuable for the community if it were finished. I have been working on it as a proof of concept, but I am stuck on the implementation due to a lack of familiarity with the codebase / compiler API.
Here is the current status of progress so far / how it works:
I was hoping someone with more expertise in the compiler could help answer the unknowns I have yet to finish for the implementation. Or if someone has worked on something similar, they could help.
I am thinking a tighter coupling with the compiler is necessary to implement the REPL properly.
config.nims:
if defined(jit):
echo "jit is defined"
# --define:useNimRtl
--nimcache:"build/nim_cache"
--cc:clang
--app:staticLib
--noMain:on
--noLinking
--passC:"-emit-llvm"
--gc:orc
C API for LLVM ORCv2:
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
typedef enum NitType {
LLVM_ORC_V2,
// TODO: more
} NitType;
typedef struct LlvmCompileOptions {
int opt_level;
// TODO: optimization flags, etc.
} LlvmCompileOptions;
typedef struct NitInitParams {
NitType type;
// TODO: union
// union { };
LlvmCompileOptions llvm;
} NitInitParams;
typedef struct NitCtx NitCtx;
// TODO: errors
NitCtx* nit_init(NitInitParams params);
void nit_free(NitCtx* ctx);
void nit_load_module(
NitCtx* ctx,
const char* fp,
const char* unload_sym,
const char* reload_sym
// TODO: dep symbols?
//const char** dep_modules,
//int n_dep_modules,
);
void* nit_lookup_sym(NitCtx* ctx, const char* fn_name);
#ifdef __cplusplus
}
#endif
Initialize the JIT'd nim code via running "NimMain"
HELP NEEDED: Since the "nimrepl" process is written in nim, thus I would assume nimrepl's NimMain has already been called. Hence, I am a little confused as to what happens if two NimMain functions are called. Is this a bug?
Since you pass --noMain Nim won't generate a main procedure which in turn is what calls NimMain. So with --noMain you need to figure out where to call NimMain yourself.