Skip to content

Commit

Permalink
Naive and exploratory implementation of caching LLVM code and importi…
Browse files Browse the repository at this point in the history
…ng it back as .so object.
  • Loading branch information
Saleh Dindar committed Apr 14, 2013
1 parent 8b50b9f commit 37eba2a
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 8 deletions.
9 changes: 9 additions & 0 deletions base/sysimg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ include("cell.jl")
include("expr.jl")
include("error.jl")



# core numeric operations & types
include("promotion.jl")
include("bool.jl")
Expand Down Expand Up @@ -96,6 +98,9 @@ import Grisu.print_shortest
include("printf.jl")
importall Printf




# concurrency and parallelism
include("iterator.jl")
include("task.jl")
Expand Down Expand Up @@ -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
15 changes: 15 additions & 0 deletions code_generation_llvm.txt
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions compile_sys.sh
Original file line number Diff line number Diff line change
@@ -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
78 changes: 70 additions & 8 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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;
}
}
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -2822,6 +2847,43 @@ extern "C" void jl_init_codegen(void)
(void*)&restore_arg_area_loc);
}

#include <llvm/Bitcode/ReaderWriter.h>
#include <llvm/Support/raw_ostream.h>
#include <dlfcn.h>

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:
Expand Down
1 change: 1 addition & 0 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
2 changes: 2 additions & 0 deletions src/julia.expmap
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,9 @@
u8_strlen;
u8_strwidth;
uv_*;
write_module_to_bitcode;
add_library_mapping;
jl_bounds_exception;

/* freebsd */
environ;
Expand Down
2 changes: 2 additions & 0 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down

0 comments on commit 37eba2a

Please sign in to comment.