From 37eba2a88de8151f8acff3b69e60c4d030c41e2f Mon Sep 17 00:00:00 2001 From: Saleh Dindar Date: Sun, 14 Apr 2013 03:31:18 -0400 Subject: [PATCH] Naive and exploratory implementation of caching LLVM code and importing it back as .so object. --- base/sysimg.jl | 9 +++++ code_generation_llvm.txt | 15 ++++++++ compile_sys.sh | 2 ++ src/codegen.cpp | 78 +++++++++++++++++++++++++++++++++++----- src/init.c | 1 + src/julia.expmap | 2 ++ src/julia.h | 2 ++ 7 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 code_generation_llvm.txt create mode 100644 compile_sys.sh diff --git a/base/sysimg.jl b/base/sysimg.jl index b098f0db48dcd..6b961a4d88724 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -50,6 +50,8 @@ include("cell.jl") include("expr.jl") include("error.jl") + + # core numeric operations & types include("promotion.jl") include("bool.jl") @@ -96,6 +98,9 @@ import Grisu.print_shortest include("printf.jl") importall Printf + + + # concurrency and parallelism include("iterator.jl") include("task.jl") @@ -318,4 +323,8 @@ let JL_PRIVATE_LIBDIR = get(ENV, "JL_PRIVATE_LIBDIR", "lib/julia") # create system image file ccall(:jl_save_system_image, Void, (Ptr{Uint8},), "$JULIA_HOME/../$JL_PRIVATE_LIBDIR/sys.ji") + +ccall(:write_module_to_bitcode, Void, (Ptr{Uint8},), + "$JULIA_HOME/../$JL_PRIVATE_LIBDIR/sys.bc") + end diff --git a/code_generation_llvm.txt b/code_generation_llvm.txt new file mode 100644 index 0000000000000..bd22968b2f084 --- /dev/null +++ b/code_generation_llvm.txt @@ -0,0 +1,15 @@ +The code generation is done in src/codegen.cpp + +All the functions and global variables are added to jl_Module which is +initialized with the name "julia" + +Interface functions to src/codegen.cpp are + jl_Compile : generate LLVM code from AST for a function + jl_generate_fptr: Add the LLVM code to ExecutionEngine JIT compile and returno it. + +Code is generated at several places: + jl_compile_hint -> jl_get_specialization + Here a generic function is specialized and compiled to LLVM + + jl_eval_with_compiler_p + This is just eval but compiles the function before executing it diff --git a/compile_sys.sh b/compile_sys.sh new file mode 100644 index 0000000000000..d3e43962cf89b --- /dev/null +++ b/compile_sys.sh @@ -0,0 +1,2 @@ +llc -relocation-model=pic usr/lib/julia/sys.bc -o usr/lib/julia/sys.s +cc -shared usr/lib/julia/sys.s -o usr/lib/julia/sys.ji.so diff --git a/src/codegen.cpp b/src/codegen.cpp index 9527933f39793..498cbc6c74373 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -151,6 +151,12 @@ static Function *box16_func; static Function *box32_func; static Function *box64_func; +/** + * This is the handle to the shared library + * that contains compiled version of functions + * it it loaded at loading along with sys.ji + */ +static void* handleNativeCodeSharedObject; /* stuff to fix up: - function/var name (un)mangling @@ -163,6 +169,16 @@ static Function *box64_func; // --- entry point --- +void* native_function_lookup(const char* fn); + +inline std::string native_funcName(jl_lambda_info_t *lam) +{ + std::string name = lam->name->name; + // try to avoid conflicts in the global symbol table + return "julia_" + name; +} + + static Function *emit_function(jl_lambda_info_t *lam); //static int n_compile=0; static Function *to_function(jl_lambda_info_t *li) @@ -238,11 +254,21 @@ extern "C" void jl_generate_fptr(jl_function_t *f) extern "C" void jl_compile(jl_function_t *f) { jl_lambda_info_t *li = f->linfo; - if (li->functionObject == NULL) { - // objective: assign li->functionObject - li->inCompile = 1; - (void)to_function(li); - li->inCompile = 0; + if ((li->fptr == &jl_trampoline) && (li->functionObject == NULL)) { + + void* fp = native_function_lookup(native_funcName(li).c_str()); + + if(fp) + { + f->fptr = li->fptr = (jl_fptr_t)fp; + } + else + { + // objective: assign li->functionObject + li->inCompile = 1; + (void)to_function(li); + li->inCompile = 0; + } } } @@ -1826,6 +1852,7 @@ static Function *gen_jlcall_wrapper(jl_lambda_info_t *lam, Function *f) return w; } + static Function *emit_function(jl_lambda_info_t *lam) { // step 1. unpack AST and allocate codegen context for this function @@ -1932,9 +1959,7 @@ static Function *emit_function(jl_lambda_info_t *lam) specsig = true; } - std::string funcName = lam->name->name; - // try to avoid conflicts in the global symbol table - funcName = "julia_" + funcName; + std::string funcName = native_funcName(lam); jl_value_t *jlrettype = jl_ast_rettype(lam, (jl_value_t*)ast); if (specsig) { @@ -2822,6 +2847,43 @@ extern "C" void jl_init_codegen(void) (void*)&restore_arg_area_loc); } +#include +#include +#include + +extern "C" DLLEXPORT void write_module_to_bitcode(const char* s) +{ + std::string errorinfo; + raw_fd_ostream stream(s, errorinfo); + WriteBitcodeToFile(jl_Module, stream); + +} + +extern "C" void jl_load_system_so(const char* baseName) +{ + std::string bn(baseName); + std::string soname = bn + ".so"; + + handleNativeCodeSharedObject = dlopen(soname.c_str(), RTLD_NOW | RTLD_GLOBAL); + if(!handleNativeCodeSharedObject) + { + fprintf(stderr, "%s\n", dlerror()); + fprintf(stderr, "compiled libraries are could not be loaded"); + } +} + +/** + * This function returns NULL if the function name is not found + * this should only be used as a cache + */ +void* native_function_lookup(const char* fn) +{ + if(handleNativeCodeSharedObject) + return dlsym(handleNativeCodeSharedObject, fn); + else + return NULL; +} + /* maybe this reads the dwarf info for a MachineFunction: diff --git a/src/init.c b/src/init.c index 0c43049e12708..7588705befbaa 100755 --- a/src/init.c +++ b/src/init.c @@ -425,6 +425,7 @@ void julia_init(char *imageFile) if (imageFile) { JL_TRY { jl_restore_system_image(imageFile); + jl_load_system_so(imageFile); } JL_CATCH { JL_PRINTF(JL_STDERR, "error during init:\n"); diff --git a/src/julia.expmap b/src/julia.expmap index a3ade94350728..4dfabc1de9246 100644 --- a/src/julia.expmap +++ b/src/julia.expmap @@ -298,7 +298,9 @@ u8_strlen; u8_strwidth; uv_*; + write_module_to_bitcode; add_library_mapping; + jl_bounds_exception; /* freebsd */ environ; diff --git a/src/julia.h b/src/julia.h index 116fbb1dcf550..21e7103a30cea 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1163,6 +1163,8 @@ static inline void jl_eh_restore_state(jl_handler_t *eh) JL_SIGATOMIC_END(); } +DLLEXPORT void jl_load_system_so(const char* s); + DLLEXPORT void jl_enter_handler(jl_handler_t *eh); DLLEXPORT void jl_pop_handler(int n);