Skip to content

Commit

Permalink
Generate generic wrappers
Browse files Browse the repository at this point in the history
  • Loading branch information
yuyichao committed May 27, 2015
1 parent 33b133e commit fd39aa5
Showing 1 changed file with 41 additions and 26 deletions.
67 changes: 41 additions & 26 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3731,75 +3731,69 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t
return cw;
}

// generate a julia-callable function that calls f (AKA lam)
static Function *gen_jlcall_wrapper(jl_lambda_info_t *lam, jl_expr_t *ast, Function *f)
// generate a generic julia-callable function
// It is uniquely determined by (ftype, jl_rettype, nargs, specTypes)
static Function *gen_generic_jlcall_wrapper(FunctionType *ftype,
jl_value_t *jl_rettype,
size_t nargs,
jl_value_t **specTypes,
Type **specLTypes,
Module *m)
{
std::stringstream funcName;
const std::string &fname = f->getName().str();
funcName << "jlcall_";
if (fname.compare(0, 6, "julia_") == 0)
funcName << fname.substr(6);
else
funcName << fname;
const std::string funcName = "jlcall___generic_wrapper__";

Function *w = Function::Create(jl_func_sig, imaging_mode ? GlobalVariable::InternalLinkage : GlobalVariable::ExternalLinkage,
funcName.str(), f->getParent());
funcName, m);
addComdat(w);
Function::arg_iterator AI = w->arg_begin();
// const Argument &fArg = *AI++;
// AI++;
Value *fArg = AI++;
Value *argArray = AI++;
//const Argument &argCount = *AI++;
// const Argument &argCount = *AI++;
BasicBlock *b0 = BasicBlock::Create(jl_LLVMContext, "top", w);

builder.SetInsertPoint(b0);
DebugLoc noDbg;
builder.SetCurrentDebugLocation(noDbg);

jl_lambda_info_t *lam = jl_new_lambda_info(NULL, jl_emptysvec);
JL_GC_PUSH1(&lam);
jl_codectx_t ctx;
ctx.linfo = lam;
allocate_gc_frame(0, b0, &ctx);

size_t nargs = jl_array_dim0(jl_lam_args(ast));
size_t nfargs = f->getFunctionType()->getNumParams();
size_t nfargs = ftype->getNumParams();
Value **args = (Value**) alloca(nfargs*sizeof(Value*));
unsigned idx = 0;
for(size_t i=0; i < nargs; i++) {
jl_value_t *ty = jl_nth_slot_type(lam->specTypes, i);
Type *lty = julia_type_to_llvm(ty);
for (size_t i=0; i < nargs; i++) {
Type *lty = specLTypes[i];
if (lty != NULL && type_is_ghost(lty))
continue;
Value *argPtr = builder.CreateGEP(argArray,
ConstantInt::get(T_size, i));
Value *theArg = builder.CreateLoad(argPtr, false);
Value *theNewArg = theArg;
if (lty != NULL && lty != jl_pvalue_llvmt) {
theNewArg = emit_unbox(lty, theArg, ty);
if (specTypes[i]) {
theNewArg = emit_unbox(lty, theArg, specTypes[i]);
}
assert(dyn_cast<UndefValue>(theNewArg) == NULL);
args[idx] = theNewArg;
idx++;
}
// TODO: consider pulling the function pointer out of fArg so these
// wrappers can be reused for different functions of the same type.
Value *theLam = emit_nthptr(
fArg,
(ssize_t)(offsetof(jl_function_t, linfo)/sizeof(void*)),
tbaa_value);

FunctionType *ftype = f->getFunctionType();
Type *fptrtype = PointerType::get(PointerType::get(ftype, 0), 0);

Value *theFptr = emit_nthptr_recast(
theLam,
(ssize_t)(offsetof(jl_lambda_info_t, specFunctionPtr)/sizeof(void*)),
tbaa_func,
fptrtype);
Value *r = builder.CreateCall(prepare_call(theFptr),
ArrayRef<Value*>(&args[0], nfargs));
if (r->getType() != jl_pvalue_llvmt) {
r = boxed(r, &ctx, jl_ast_rettype(lam, (jl_value_t*)ast));
if (jl_rettype) {
r = boxed(r, &ctx, jl_rettype);
}

// gc pop. Usually this is done when we encounter the return statement
Expand All @@ -3815,9 +3809,30 @@ static Function *gen_jlcall_wrapper(jl_lambda_info_t *lam, jl_expr_t *ast, Funct

FPM->run(*w);

JL_GC_POP();
return w;
}

// generate a julia-callable function that calls f (AKA lam)
static Function *gen_jlcall_wrapper(jl_lambda_info_t *lam, jl_expr_t *ast,
Function *f)
{
size_t nargs = jl_array_dim0(jl_lam_args(ast));
FunctionType *ftype = f->getFunctionType();
jl_value_t *jl_rettype = (ftype->getReturnType() != jl_pvalue_llvmt ?
jl_ast_rettype(lam, (jl_value_t*)ast) : NULL);
jl_value_t **specTypes = (jl_value_t**)alloca(nargs * sizeof(jl_value_t*));
Type **specLTypes = (Type**)alloca(nargs * sizeof(Type*));
for (size_t i = 0;i < nargs;i++) {
jl_value_t *ty = jl_nth_slot_type(lam->specTypes, i);
Type *lty = julia_type_to_llvm(ty);
specLTypes[i] = lty;
specTypes[i] = (lty != NULL && lty != jl_pvalue_llvmt) ? ty : NULL;
}
return gen_generic_jlcall_wrapper(ftype, jl_rettype, nargs, specTypes,
specLTypes, f->getParent());
}

// cstyle = compile with c-callable signature, not jlcall
static Function *emit_function(jl_lambda_info_t *lam)
{
Expand Down

0 comments on commit fd39aa5

Please sign in to comment.