Skip to content

Commit

Permalink
simplify interaction between new JITs and codegen
Browse files Browse the repository at this point in the history
this treats the new JITs (MCJIT, ORCJIT) much like the old JIT,
but using Module as the atomic unit instead of Function

this gets codegen closer to being separable (cachable) at the
module level, with the remerging happening in the JIT after object
file emission

TODO: memory optimization of strings in the JIT needs to be reimplemented

fix #15533
  • Loading branch information
vtjnash committed Mar 18, 2016
1 parent a9a7bce commit 2a65a90
Show file tree
Hide file tree
Showing 14 changed files with 1,028 additions and 1,456 deletions.
4 changes: 3 additions & 1 deletion src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,10 @@ $(BUILDDIR)/julia_flisp.boot: $(addprefix $(SRCDIR)/,jlfrontend.scm \

# additional dependency links
$(BUILDDIR)/ast.o $(BUILDDIR)/ast.dbg.obj: $(BUILDDIR)/julia_flisp.boot.inc $(SRCDIR)/flisp/*.h
$(BUILDDIR)/codegen.o $(BUILDDIR)/codegen.dbg.obj: $(addprefix $(SRCDIR)/,intrinsics.cpp intrinsics.h cgutils.cpp ccall.cpp jitlayers.cpp abi_*.cpp)
$(BUILDDIR)/codegen.o $(BUILDDIR)/codegen.dbg.obj: $(addprefix $(SRCDIR)/,intrinsics.cpp jitlayers.cpp intrinsics.h codegen_internal.h cgutils.cpp ccall.cpp abi_*.cpp)
$(BUILDDIR)/anticodegen.o $(BUILDDIR)/anticodegen.dbg.obj: $(SRCDIR)/intrinsics.h
$(BUILDDIR)/debuginfo.o $(BUILDDIR)/debuginfo.dbg.obj: $(SRCDIR)/codegen_internal.h
$(BUILDDIR)/disasm.o $(BUILDDIR)/disasm.dbg.obj: $(SRCDIR)/codegen_internal.h
$(BUILDDIR)/builtins.o $(BUILDDIR)/builtins.dbg.obj: $(SRCDIR)/table.c
$(BUILDDIR)/gc.o $(BUILDDIR)/gc.dbg.obj: $(SRCDIR)/gc-debug.c
$(BUILDDIR)/signal-handling.o $(BUILDDIR)/signal-handling.dbg.obj: $(addprefix $(SRCDIR)/,signals-*.c)
Expand Down
141 changes: 42 additions & 99 deletions src/ccall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,8 @@

// --- the ccall, cglobal, and llvm intrinsics ---

// keep track of llvmcall declarations
#if defined(USE_MCJIT) || defined(USE_ORCJIT)
static std::map<uint64_t,llvm::GlobalValue*> llvmcallDecls;
#else
static std::set<uint64_t> llvmcallDecls;
#endif

static std::map<std::string, GlobalVariable*> libMapGV;
static std::map<std::string, GlobalVariable*> symMapGV;

static Value *GetStringPtr(llvm::IRBuilder <> *builder, GlobalValue *GV, const Twine &Name)
{
Value *zero = ConstantInt::get(Type::getInt32Ty(jl_LLVMContext), 0);
Value *Args[] = { zero, zero };
#ifdef LLVM37
return builder->CreateInBoundsGEP(GV->getValueType(), GV, Args, Name);
#else
return builder->CreateInBoundsGEP(GV, Args, Name);
#endif
}
static StringMap<GlobalVariable*> libMapGV;
static StringMap<GlobalVariable*> symMapGV;

static Value *runtime_sym_lookup(PointerType *funcptype, const char *f_lib, const char *f_name, jl_codectx_t *ctx)
{
Expand Down Expand Up @@ -53,52 +35,47 @@ static Value *runtime_sym_lookup(PointerType *funcptype, const char *f_lib, cons
libsym = jl_RTLD_DEFAULT_handle;
}
else {
std::string name = "ccalllib_";
name += f_lib;
runtime_lib = true;
libptrgv = libMapGV[f_lib];
if (libptrgv == NULL) {
libptrgv = new GlobalVariable(imaging_mode ? *shadow_module : *active_module, T_pint8,
false, GlobalVariable::PrivateLinkage,
ConstantPointerNull::get((PointerType*)T_pint8), f_lib);
libMapGV[f_lib] = libptrgv;
libptrgv = new GlobalVariable(*jl_Module, T_pint8,
false, GlobalVariable::ExternalLinkage,
NULL, name);
libMapGV[f_lib] = global_proto(libptrgv);
libsym = jl_get_library(f_lib);
assert(libsym != NULL);
#ifdef USE_MCJIT
jl_llvm_to_jl_value[libptrgv] = libsym;
#else
*((void**)jl_ExecutionEngine->getPointerToGlobal(libptrgv)) = libsym;
#endif
*(void**)jl_emit_and_add_to_shadow(libptrgv) = libsym;
}
else {
libptrgv = prepare_global(libptrgv);
}
}
if (libsym == NULL) {
#ifdef USE_MCJIT
libsym = (void*)jl_llvm_to_jl_value[libptrgv];
#else
libsym = *((void**)jl_ExecutionEngine->getPointerToGlobal(libptrgv));
#endif
libsym = *(void**)jl_get_global(libptrgv);
}

assert(libsym != NULL);

GlobalVariable *llvmgv = symMapGV[f_name];
Constant *initnul = ConstantPointerNull::get((PointerType*)T_pvoidfunc);
if (llvmgv == NULL) {
// MCJIT forces this to have external linkage eventually, so we would clobber
// the symbol of the actual function.
std::string name = f_name;
name = "ccall_" + name;
llvmgv = new GlobalVariable(imaging_mode ? *shadow_module : *active_module, T_pvoidfunc,
false, GlobalVariable::PrivateLinkage,
initnul, name);
symMapGV[f_name] = llvmgv;
#ifdef USE_MCJIT
jl_llvm_to_jl_value[llvmgv] = jl_dlsym_e(libsym, f_name);
#else
*((void**)jl_ExecutionEngine->getPointerToGlobal(llvmgv)) = jl_dlsym_e(libsym, f_name);
#endif
std::string name = "ccall_";
name += f_name;
llvmgv = new GlobalVariable(*jl_Module, T_pvoidfunc,
false, GlobalVariable::ExternalLinkage,
NULL, name);
symMapGV[f_name] = global_proto(llvmgv);
*(void**)jl_emit_and_add_to_shadow(llvmgv) = jl_dlsym_e(libsym, f_name);
}
else {
llvmgv = prepare_global(llvmgv);
}

BasicBlock *dlsym_lookup = BasicBlock::Create(jl_LLVMContext, "dlsym"),
*ccall_bb = BasicBlock::Create(jl_LLVMContext, "ccall");
Constant *initnul = ConstantPointerNull::get((PointerType*)T_pvoidfunc);
builder.CreateCondBr(builder.CreateICmpNE(builder.CreateLoad(llvmgv), initnul), ccall_bb, dlsym_lookup);

assert(ctx->f->getParent() != NULL);
Expand Down Expand Up @@ -598,7 +575,7 @@ static jl_cgval_t emit_llvmcall(jl_value_t **args, size_t nargs, jl_codectx_t *c
std::stringstream name;
name << (ctx->f->getName().str()) << "u" << i++;
ir_name = name.str();
if (builtins_module->getFunction(ir_name) == NULL)
if (jl_Module->getFunction(ir_name) == NULL)
break;
}

Expand All @@ -615,43 +592,24 @@ static jl_cgval_t emit_llvmcall(jl_value_t **args, size_t nargs, jl_codectx_t *c
std::string rstring;
llvm::raw_string_ostream rtypename(rstring);
rettype->print(rtypename);
#if defined(USE_MCJIT) || defined(USE_ORCJIT)
std::map<uint64_t,std::string> localDecls;
#endif

if (decl != NULL) {
std::stringstream declarations(jl_string_data(decl));

// parse string line by line
std::string declstr;
while (std::getline(declarations, declstr, '\n')) {
uint64_t declhash = memhash(declstr.c_str(), declstr.length());
#if defined(USE_MCJIT) || defined(USE_ORCJIT)
auto it = llvmcallDecls.find(declhash);
if (it != llvmcallDecls.end()) {
prepare_call(it->second);
}
else {
#else
if (llvmcallDecls.count(declhash) == 0) {
#endif
// Find name of declaration by searching for '@'
std::string::size_type atpos = declstr.find('@') + 1;
// Find end of declaration by searching for '('
std::string::size_type bracepos = declstr.find('(', atpos);
// Declaration name is the string between @ and (
std::string declname = declstr.substr(atpos, bracepos - atpos);

// Check if declaration already present in module
if(jl_Module->getNamedValue(declname) == NULL) {
ir_stream << "; Declarations\n" << declstr << "\n";
}

#if defined(USE_MCJIT) || defined(USE_ORCJIT)
localDecls[declhash] = declname;
#else
llvmcallDecls.insert(declhash);
#endif
// Find name of declaration by searching for '@'
std::string::size_type atpos = declstr.find('@') + 1;
// Find end of declaration by searching for '('
std::string::size_type bracepos = declstr.find('(', atpos);
// Declaration name is the string between @ and (
std::string declname = declstr.substr(atpos, bracepos - atpos);

// Check if declaration already present in module
if(jl_Module->getNamedValue(declname) == NULL) {
ir_stream << "; Declarations\n" << declstr << "\n";
}
}
}
Expand All @@ -662,9 +620,9 @@ static jl_cgval_t emit_llvmcall(jl_value_t **args, size_t nargs, jl_codectx_t *c
std::string ir_string = ir_stream.str();
#ifdef LLVM36
Module *m = NULL;
bool failed = parseAssemblyInto(llvm::MemoryBufferRef(ir_string,"llvmcall"),*builtins_module,Err);
bool failed = parseAssemblyInto(llvm::MemoryBufferRef(ir_string,"llvmcall"),*jl_Module,Err);
if (!failed)
m = builtins_module;
m = jl_Module;
#else
Module *m = ParseAssemblyString(ir_string.c_str(),jl_Module,Err,jl_LLVMContext);
#endif
Expand All @@ -675,12 +633,8 @@ static jl_cgval_t emit_llvmcall(jl_value_t **args, size_t nargs, jl_codectx_t *c
jl_error(stream.str().c_str());
}
f = m->getFunction(ir_name);

f->removeFromParent();
#if defined(USE_MCJIT) || defined(USE_ORCJIT)
for (auto it : localDecls) {
llvmcallDecls[it.first] = cast<GlobalValue>(prepare_call(m->getNamedValue(it.second)));
}
#endif
}
else {
assert(isPtr);
Expand All @@ -692,13 +646,6 @@ static jl_cgval_t emit_llvmcall(jl_value_t **args, size_t nargs, jl_codectx_t *c
it != argtypes.end(); ++it, ++i)
assert(*it == f->getFunctionType()->getParamType(i));

#ifdef USE_MCJIT
if (f->getParent() != active_module) {
FunctionMover mover(active_module,f->getParent());
f = mover.CloneFunction(f);
}
#endif

//f->dump();
#ifndef LLVM35
if (verifyFunction(*f,PrintMessageAction)) {
Expand Down Expand Up @@ -1174,8 +1121,7 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx)
if (jl_is_tuple_type(fargt) && jl_is_leaf_type(fargt)) {
frt = jl_tparam0(frt);
JL_TRY {
Value *llvmf = prepare_call(
jl_cfunction_object((jl_function_t*)f, frt, (jl_tupletype_t*)fargt));
Value *llvmf = prepare_call(jl_cfunction_object((jl_function_t*)f, frt, (jl_tupletype_t*)fargt));
// make sure to emit any side-effects that may have been part of the original expression
emit_expr(args[4], ctx);
emit_expr(args[6], ctx);
Expand Down Expand Up @@ -1353,8 +1299,8 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx)
}

if (needStackRestore) {
stacksave = CallInst::Create(prepare_call(Intrinsic::getDeclaration(builtins_module,
Intrinsic::stacksave)));
stacksave = CallInst::Create(Intrinsic::getDeclaration(jl_Module,
Intrinsic::stacksave));
if (savespot) {
#ifdef LLVM38
instList.insertAfter(savespot->getIterator(), (Instruction*)stacksave);
Expand All @@ -1381,10 +1327,7 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx)
result = ret;
if (needStackRestore) {
assert(stacksave != NULL);
builder.CreateCall(prepare_call(
Intrinsic::getDeclaration(builtins_module,
Intrinsic::stackrestore)),
stacksave);
builder.CreateCall(Intrinsic::getDeclaration(jl_Module, Intrinsic::stackrestore), stacksave);
}
if (0) { // Enable this to turn on SSPREQ (-fstack-protector) on the function containing this ccall
ctx->f->addFnAttr(Attribute::StackProtectReq);
Expand Down
Loading

0 comments on commit 2a65a90

Please sign in to comment.