本文整理汇总了C++中IRBuilder::CreateRet方法的典型用法代码示例。如果您正苦于以下问题:C++ IRBuilder::CreateRet方法的具体用法?C++ IRBuilder::CreateRet怎么用?C++ IRBuilder::CreateRet使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类IRBuilder
的用法示例。
在下文中一共展示了IRBuilder::CreateRet方法的12个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: printf
void
code_emitter::emit_main_filter_funcs ()
{
// init x
#ifdef DEBUG_OUTPUT
printf("emitting init x for %s\n", filter->name);
#endif
x_vars_var = setup_init_x_or_y_function(init_x_function_name(filter), "y", x_vars_type);
compiler_slice_code_for_const(filter_code->first_stmt, CONST_X);
emit_stmts(filter_code->first_stmt, SLICE_X_CONST);
builder->CreateRet(ret_var);
finish_function();
// init y
#ifdef DEBUG_OUTPUT
printf("emitting init y for %s\n", filter->name);
#endif
y_vars_var = setup_init_x_or_y_function(init_y_function_name(filter), "x", y_vars_type);
compiler_slice_code_for_const(filter_code->first_stmt, CONST_Y);
emit_stmts(filter_code->first_stmt, SLICE_Y_CONST);
builder->CreateRet(ret_var);
finish_function();
// filter
#ifdef DEBUG_OUTPUT
printf("emitting main filter func for %s\n", filter->name);
#endif
setup_filter_function(true);
compiler_slice_code_for_const(filter_code->first_stmt, CONST_NONE);
//fetch_all_const_values();
emit_stmts(filter_code->first_stmt, SLICE_NO_CONST);
finish_function();
}
示例2: Codegen
Function* FunctionAST::Codegen()
{
Function* theFunction = Proto->Codegen();
if(theFunction == 0)
return 0;
BasicBlock* BB = BasicBlock::Create(getGlobalContext(),"entry",theFunction);
Builder.SetInsertPoint(BB);
Proto->CreateArgumentAllocas(theFunction);
vector<ExprAST*>::iterator it = Body.begin();
Value* last;
for(it = Body.begin(); it != Body.end(); ++it)
{
last = (*it)->Codegen();
if (!last)
break;
}
if(last)
{
Builder.CreateRet(last);
verifyFunction(*theFunction);
NamedValues.clear();
return theFunction;
}
//If it gets here there's an error! erase the function
theFunction->eraseFromParent();
return 0;
}
示例3:
/*
* float t1(float p) { return (p>0)?p:-p; }
*/
Function *createAbs(Module *m, LLVMContext &Context) {
Type *floatTy = Type::getFloatTy(Context);
Type *ArgTypes[] = { floatTy };
FunctionType *Ty = FunctionType::get(floatTy, ArgTypes, false);
Function *func = Function::Create(Ty,
GlobalValue::ExternalLinkage, "fabs", m);
BasicBlock *bb = BasicBlock::Create(Context, "EntryBlock", func);
IRBuilder<> *builder = new IRBuilder<>(bb);
Value *arg0 = func->arg_begin();arg0->setName("arg0");
Value *v = builder->CreateFCmpOGE(arg0, ConstantFP::get(floatTy, 0.0));
Value *v0 = builder->CreateFNeg(arg0);
Value *ret = builder->CreateSelect(v, arg0, v0);
builder->CreateRet(ret);
return func;
}
示例4: main
int main(int argc, char **argv)
{
InitializeNativeTarget();
LLVMContext &Context = getGlobalContext();
Module *m = new Module("test", Context);
Type *intTy = Type::getInt64Ty(Context);
StructType* structTy = StructType::create(Context, "struct.list");
std::vector<Type*> fields;
fields.push_back(intTy);
fields.push_back(PointerType::get(structTy, 0));
if (structTy->isOpaque()) {
structTy->setBody(fields, false);
}
/*
* int f1(struct x *p) { return p->next->l1; }
*/
std::vector<Type*> args_type;
args_type.push_back(PointerType::get(structTy, 0));
FunctionType *fnTy = FunctionType::get(intTy, args_type, false);
Function *func = Function::Create(fnTy,
GlobalValue::ExternalLinkage, "f1", m);
Value *v = func->arg_begin();
BasicBlock *bb = BasicBlock::Create(Context, "EntryBlock", func);
IRBuilder<> *builder = new IRBuilder<>(bb);
v = builder->CreateStructGEP(v, 1);
v = builder->CreateLoad(v, "load0");
v = builder->CreateStructGEP(v, 0);
v = builder->CreateLoad(v, "load1");
builder->CreateRet(v);
(*m).dump();
{
ExecutionEngine *ee = EngineBuilder(m).
setEngineKind(EngineKind::JIT).create();
void *f = ee->getPointerToFunction(func);
typedef int (*func_t) (struct x *);
struct x o = {10, NULL}, v = {};
v.next = &o;
std::cout << ((func_t)f)(&v) << std::endl;
}
return 0;
}
示例5: doubles
Value *UserFunctionSexp::codegen(SexpCompilerContext& ctx)
{
vector<const Type*> doubles(args ? args->length(): 0, ctx.getDoubleTy());
FunctionType *type = FunctionType::get(ctx.getDoubleTy(), doubles, false);
Function *func = Function::Create(type, Function::ExternalLinkage, name, &ctx.getToplevelModule());
if (args) {
Function::arg_iterator it = func->arg_begin();
ConsSexp *cons = args;
SymbolSexp *sym;
while (cons && (sym = dynamic_cast<SymbolSexp*>(cons->car))) {
it->setName(sym->getName());
cons = dynamic_cast<ConsSexp*>(cons->cdr);
++it;
}
}
if (body) {
BasicBlock *block = BasicBlock::Create(ctx.getLLVMContext(), "entry", func);
Value *val = NULL;
IRBuilder<> *builder = ctx.pushBuilder(block);
for (ConsSexp *cons = body; cons; cons = dynamic_cast<ConsSexp*>(cons->cdr)) {
if (cons->car)
val = cons->car->codegen(ctx);
}
if (val)
builder->CreateRet(val);
ctx.popBuilder();
}
return func;
}
示例6: codegen_call
codegen_value ast::distribution::createConstructor(Module *module, IRBuilder<> &builder,
const string &ctor_name,
Type *parameter_type,
const vector<type_spec> ¶m_type_list,
Value *eval, Value *sample, Value *pdf, Value *emit,
Function *dtor) {
//create function accepting parameters as arguments
vector<Type*> arg_types;
for (auto it = param_type_list.begin(); it != param_type_list.end(); ++it) arg_types.push_back((*it)->llvm_type());
FunctionType *ft = FunctionType::get(state->types["dfunc"]->llvm_type(), arg_types, false);
Function *f = Function::Create(ft, Function::ExternalLinkage, ctor_name, module);
BasicBlock *bb = BasicBlock::Create(getGlobalContext(), "func_entry", f);
builder.SetInsertPoint(bb);
//setup arguments for the alloc call
Value *gd_scene = module->getNamedGlobal(".__gd_scene");
assert(gd_scene != NULL);
Value *scene_ptr = builder.CreateLoad(gd_scene);
//compute the shader flags
codegen_value flag_val = codegen_all_flags(module, builder);
return errors::codegen_call(flag_val, [&] (Value *&flag_bitmask) -> codegen_value {
//get memory for a new distribution object
Value *dfunc_ptr = state->types["dfunc"]->allocate(module, builder);
//initialize the object and dynamically allocate parameter memory (calling a builtin function)
Type* int_ptr_ty = Type::getInt32Ty(getGlobalContext())->getPointerTo();
vector<Type*> alloc_arg_types({state->types["scene_ptr"]->llvm_type(),
Type::getInt32Ty(getGlobalContext()), state->types["shader_flag"]->llvm_type(),
int_ptr_ty, int_ptr_ty, int_ptr_ty, int_ptr_ty,
dtor->getType(), dfunc_ptr->getType()});
FunctionType *alloc_type = FunctionType::get(Type::getInt32PtrTy(getGlobalContext()), alloc_arg_types, false);
Function *alloc_func = GetExternalFunction(module, "gd_builtin_alloc_dfunc", alloc_type);
int param_data_size = DataLayout(module).getTypeAllocSize(parameter_type);
Constant *param_size_arg = ConstantInt::get(getGlobalContext(), APInt(8*sizeof(int), param_data_size));
vector<Value*> alloc_args({scene_ptr, param_size_arg, flag_bitmask,
builder.CreatePointerCast(eval, int_ptr_ty),
builder.CreatePointerCast(sample, int_ptr_ty),
builder.CreatePointerCast(pdf, int_ptr_ty),
builder.CreatePointerCast(emit, int_ptr_ty),
dtor, dfunc_ptr});
Value *param_ptr = builder.CreatePointerCast(builder.CreateCall(alloc_func, alloc_args),
parameter_type->getPointerTo(), "dfunc_param_ptr");
//set each parameter
auto arg_it = f->arg_begin();
unsigned int field_idx = 0;
for (auto it = param_type_list.begin(); it != param_type_list.end(); ++it, ++arg_it, ++field_idx) {
Value *param_copy = (*it)->copy(arg_it, module, builder);
(*it)->store(param_copy, builder.CreateStructGEP(param_ptr, field_idx), module, builder);
}
//return the object
Value *rt_val = builder.CreateLoad(dfunc_ptr, "dist_ref");
builder.CreateRet(rt_val);
return f;
});
}
示例7: i
// =============================================================================
// andOOPIsGone (formerly: createProcess)
//
// Formerly, OOP permitted the same SC_{METHOD,THREAD} functions to apply
// to each copy of a SC_MODULE. Aaaaand it's gone !
// (but OTOH we enable better optimizations)
// Creates a new C-style function that calls the old member function with the
// given sc_module. The call is then inlined.
// FIXME: assumes the method is non-virtual and that sc_module is the first
// inherited class of the SC_MODULE
// =============================================================================
Function *TwetoPassImpl::andOOPIsGone(Function * oldProc,
sc_core::sc_module * initiatorMod)
{
if (!oldProc)
return NULL;
// can't statically optimize if the address of the module isn't predictible
// TODO: also handle already-static variables, which also have
// fixed $pc-relative addresses
if (staticopt == optlevel && !permalloc::is_from (initiatorMod))
return NULL;
LLVMContext & context = getGlobalContext();
FunctionType *funType = oldProc->getFunctionType();
Type *type = funType->getParamType(0);
FunctionType *newProcType =
FunctionType::get(oldProc->getReturnType(),
ArrayRef < Type * >(), false);
// Create the new function
std::ostringstream id;
id << proc_counter++;
std::string name =
oldProc->getName().str() + std::string("_clone_") + id.str();
Function *newProc =
Function::Create(newProcType, Function::ExternalLinkage, name,
this->llvmMod);
assert(newProc->empty());
newProc->addFnAttr(Attribute::InlineHint);
// Create call to old function
BasicBlock *bb = BasicBlock::Create(context, "entry", newProc);
IRBuilder <> *irb = new IRBuilder <> (context);
irb->SetInsertPoint(bb);
Value* thisAddr = createRelocatablePointer (type, initiatorMod, irb);
CallInst *ci = irb->CreateCall(oldProc,
ArrayRef < Value * >(std::vector<Value*>(1,thisAddr)));
//bb->getInstList().insert(ci, thisAddr);
if (ci->getType()->isVoidTy())
irb->CreateRetVoid();
else
irb->CreateRet(ci);
// The function should be valid now
verifyFunction(*newProc);
{ // Inline the call
DataLayout *td = new DataLayout(this->llvmMod);
InlineFunctionInfo i(NULL, td);
bool success = InlineFunction(ci, i);
assert(success);
verifyFunction(*newProc);
}
// further optimize the function
inlineBasicIO (initiatorMod, newProc);
newProc->dump();
return newProc;
}
示例8: main
int main(int argc, char **argv)
{
InitializeNativeTarget();
LLVMContext &Context = getGlobalContext();
Module *m = new Module("test", Context);
Module *TheM = LoadModule("struct.c.bc");
std::string ErrMsg;
if (Linker::LinkModules(m, TheM, Linker::DestroySource, &ErrMsg)) {
std::cout << "error" << ErrMsg << std::endl;
return 1;
}
StructType* ctxTy = StructType::create(Context, "struct.kcontext_t");
StructType* sfpTy = StructType::create(Context, "struct.ksfp_t");
Type *Int64Ty = Type::getInt64Ty(Context);
Type *ArgsTy[] = {
PointerType::get(ctxTy, 0),
PointerType::get(sfpTy, 0),
Int64Ty
};
Type *floatTy = Type::getDoubleTy(Context);
FunctionType *fnTy = FunctionType::get(floatTy, ArgsTy, false);
Function *Frand = CreateF(m, ctxTy, sfpTy);
Function *F = Function::Create(fnTy, GlobalValue::ExternalLinkage, "test", m);
BasicBlock *bb = BasicBlock::Create(Context, "EntryBlock", F);
IRBuilder<> *builder = new IRBuilder<>(bb);
Function::arg_iterator I = F->arg_begin();
Value *Ctx = I++;
Value *Sfp = I++;
Value *Rix = I;
Value *Args[] = {
Ctx, Sfp, Rix
};
Value *v = builder->CreateCall(Frand, Args);
builder->CreateRet(v);
std::cout << "before" << std::endl;
(*m).dump();
ExecutionEngine *ee = EngineBuilder(m).setEngineKind(EngineKind::JIT).create();
PassManager mpm;
mpm.add(createIPSCCPPass());
mpm.add(createFunctionInliningPass());
mpm.add(createLICMPass());
mpm.add(createGVNPass());
mpm.add(createGlobalDCEPass());
mpm.run(*m);
std::cout << std::endl << "before" << std::endl;
(*m).dump();
//{
// void *ptr = ee->getPointerToFunction(F);
// typedef struct ksfp_t {
// double v;
// void *p;
// } ksfp_t;
// typedef float (*F_t)(void *, ksfp_t *, long);
// ksfp_t sfp_[100] = {};
// F_t fptr = (F_t) ptr;
// std::cout << fptr(NULL, sfp_, 0) << std::endl;
// asm volatile("int3");
// std::cout << ((float (*)())ptr)() << std::endl;
//}
return 0;
}
示例9: IntToPtrInst
// =============================================================================
// createProcess
//
// Create a new function that contains a call to the old function.
// We inline the call in order to clone the old function's implementation.
// =============================================================================
Function *TLMBasicPassImpl::createProcess(Function *oldProc,
sc_core::sc_module *initiatorMod) {
LLVMContext &context = getGlobalContext();
IntegerType *intType;
if (this->is64Bit) {
intType = Type::getInt64Ty(context);
} else {
intType = Type::getInt32Ty(context);
}
// Retrieve a pointer to the initiator module
ConstantInt *initiatorModVal =
ConstantInt::getSigned(intType,reinterpret_cast<intptr_t>(initiatorMod));
FunctionType *funType = oldProc->getFunctionType();
Type *type = funType->getParamType(0);
IntToPtrInst *thisAddr =
new IntToPtrInst(initiatorModVal, type, "");
// Compute the type of the new function
FunctionType *oldProcType = oldProc->getFunctionType();
Value **argsBegin = new Value*[1];
Value **argsEnd = argsBegin;
*argsEnd++ = thisAddr;
const unsigned argsSize = argsEnd-argsBegin;
Value **args = argsBegin;
assert(oldProcType->getNumParams()==argsSize);
assert(!oldProc->isDeclaration());
std::vector<Type*> argTypes;
for (unsigned i = 0; i!=argsSize; ++i)
argTypes.push_back(oldProcType->getParamType(i));
FunctionType *newProcType =
FunctionType::get(oldProc->getReturnType(), ArrayRef<Type*>(argTypes), false);
// Create the new function
std::ostringstream id;
id << proc_counter++;
std::string name = oldProc->getName().str()+std::string("_clone_")+id.str();
Function *newProc =
Function::Create(newProcType, Function::ExternalLinkage, name, this->llvmMod);
assert(newProc->empty());
newProc->addFnAttr(Attributes::InlineHint);
{ // Set name of newfunc arguments and complete args
Function::arg_iterator nai = newProc->arg_begin();
Function::arg_iterator oai = oldProc->arg_begin();
for (unsigned i = 0; i!=argsSize; ++i, ++oai) {
nai->setName(oai->getName());
args[i] = nai;
++nai;
}
assert(nai==newProc->arg_end());
assert(oai==oldProc->arg_end());
}
// Create call to old function
BasicBlock *bb = BasicBlock::Create(context, "entry", newProc);
IRBuilder<> *irb = new IRBuilder<>(context);
irb->SetInsertPoint(bb);
CallInst *ci = irb->CreateCall(oldProc, ArrayRef<Value*>(argsBegin, argsEnd));
bb->getInstList().insert(ci, thisAddr);
if (ci->getType()->isVoidTy())
irb->CreateRetVoid();
else
irb->CreateRet(ci);
// The function should be valid now
verifyFunction(*newProc);
{ // Inline the call
DataLayout *td = new DataLayout(this->llvmMod);
InlineFunctionInfo i(NULL, td);
bool success = InlineFunction(ci, i);
assert(success);
verifyFunction(*newProc);
}
//newProc->dump();
return newProc;
}
示例10: if
void
code_emitter::emit_stmts (statement_t *stmt, unsigned int slice_flag)
{
for (; stmt != NULL; stmt = stmt->next)
{
if (!must_emit_stmt(stmt, slice_flag))
continue;
switch (stmt->kind)
{
case STMT_NIL :
g_assert(slice_flag == SLICE_IGNORE);
break;
case STMT_ASSIGN :
#ifdef DEBUG_OUTPUT
compiler_print_assign_statement(stmt);
printf("\n");
#endif
if (stmt->v.assign.rhs->kind == RHS_OP
&& stmt->v.assign.rhs->v.op.op->index == OP_OUTPUT_TUPLE)
builder->CreateRet(emit_primary(&stmt->v.assign.rhs->v.op.args[0]));
else
set_value(stmt->v.assign.lhs, emit_rhs(stmt->v.assign.rhs));
break;
case STMT_IF_COND :
{
Value *condition_number = emit_rhs(stmt->v.if_cond.condition);
Value *condition;
map<rhs_t*, Value*> rhs_map;
if (condition_number->getType() == Type::Int32Ty)
condition = builder->CreateICmpNE(condition_number, make_int_const(0));
else if (condition_number->getType() == Type::FloatTy)
condition = builder->CreateFCmpONE(condition_number, make_float_const(0.0));
else
g_assert_not_reached();
BasicBlock *then_bb = BasicBlock::Create("then", current_function);
BasicBlock *else_bb = BasicBlock::Create("else");
BasicBlock *merge_bb = BasicBlock::Create("ifcont");
builder->CreateCondBr(condition, then_bb, else_bb);
builder->SetInsertPoint(then_bb);
emit_stmts(stmt->v.if_cond.consequent, slice_flag);
emit_phi_rhss(stmt->v.if_cond.exit, true, &rhs_map, slice_flag);
builder->CreateBr(merge_bb);
then_bb = builder->GetInsertBlock();
current_function->getBasicBlockList().push_back(else_bb);
builder->SetInsertPoint(else_bb);
emit_stmts(stmt->v.if_cond.alternative, slice_flag);
emit_phi_rhss(stmt->v.if_cond.exit, false, &rhs_map, slice_flag);
builder->CreateBr(merge_bb);
else_bb = builder->GetInsertBlock();
current_function->getBasicBlockList().push_back(merge_bb);
builder->SetInsertPoint(merge_bb);
emit_phis(stmt->v.if_cond.exit, then_bb, else_bb, rhs_map, slice_flag);
}
break;
case STMT_WHILE_LOOP:
{
BasicBlock *start_bb = builder->GetInsertBlock();
BasicBlock *entry_bb = BasicBlock::Create("entry", current_function);
BasicBlock *body_bb = BasicBlock::Create("body");
BasicBlock *exit_bb = BasicBlock::Create("exit");
map<rhs_t*, Value*> rhs_map;
emit_phi_rhss(stmt->v.while_loop.entry, true, &rhs_map, slice_flag);
builder->CreateBr(entry_bb);
builder->SetInsertPoint(entry_bb);
emit_phis(stmt->v.while_loop.entry, start_bb, NULL, rhs_map, slice_flag);
Value *invariant_number = emit_rhs(stmt->v.while_loop.invariant);
Value *invariant;
if (invariant_number->getType() == Type::Int32Ty)
invariant = builder->CreateICmpNE(invariant_number, make_int_const(0));
else if (invariant_number->getType() == Type::FloatTy)
invariant = builder->CreateFCmpONE(invariant_number, make_float_const(0.0));
else
g_assert_not_reached();
builder->CreateCondBr(invariant, body_bb, exit_bb);
current_function->getBasicBlockList().push_back(body_bb);
builder->SetInsertPoint(body_bb);
emit_stmts(stmt->v.while_loop.body, slice_flag);
body_bb = builder->GetInsertBlock();
emit_phi_rhss(stmt->v.while_loop.entry, false, &rhs_map, slice_flag);
emit_phis(stmt->v.while_loop.entry, NULL, body_bb, rhs_map, slice_flag);
builder->CreateBr(entry_bb);
//.........这里部分代码省略.........
示例11: codeGen
Value* Return::codeGen(CodeGenContext &context) {
IRBuilder<> *builder = context.currentBuilder();
Value *returnValue = returnExpr.codeGen(context);
return builder->CreateRet(returnValue);
}
示例12: CreatePassManager
//.........这里部分代码省略.........
args++; i++;
argument_addresses[i] = builder->CreateAlloca(arguments[5], nullptr, argument_names[i]);
builder->CreateStore(&*args, argument_addresses[i]);
args++; i++;
assert(args == function->arg_end());
assert(i == arg_count);
info.index_addr = argument_addresses[start_addr];
info.thread_addr = argument_addresses[thread_nr_addr];
PerformInitialization(info, pipeline->operation);
builder->CreateBr(loop_cond);
}
// for loop condition: index < end
builder->SetInsertPoint(loop_cond);
{
LoadInst *index = builder->CreateLoad(argument_addresses[start_addr], "index");
LoadInst *end = builder->CreateLoad(argument_addresses[end_addr], "end");
Value *condition = builder->CreateICmpSLT(index, end, "index < end");
builder->CreateCondBr(condition, loop_body, loop_end);
}
// loop body: perform the computation
builder->SetInsertPoint(loop_body);
{
LoadInst *index = builder->CreateLoad(argument_addresses[start_addr], "index");
info.index = index;
info.index_addr = argument_addresses[start_addr];
// perform the computation over the given index
// we don't use the return value because the final assignment has already taken place
Value *v = PerformOperation(info, thread->builder, thread->context, pipeline->operation, pipeline->inputData, pipeline->outputData);
if (v == NULL) {
// failed to perform operation
printf("Failed to compile pipeline %s\n", pipeline->name);
return NULL;
}
builder->CreateBr(loop_inc);
}
// loop increment: index++
builder->SetInsertPoint(loop_inc);
{
LoadInst *index = builder->CreateLoad(argument_addresses[start_addr], "index");
Value *incremented_index = builder->CreateAdd(index, ConstantInt::get(int64_tpe, 1, true), "index++");
builder->CreateStore(incremented_index, argument_addresses[start_addr]);
builder->CreateBr(loop_cond);
}
// loop end: return; (nothing happens here because we have no return value)
builder->SetInsertPoint(loop_end);
{
// return the output size of each of the columns
int i = 0;
Value *result_sizes = builder->CreateLoad(argument_addresses[result_sizes_addr], "result_sizes[]");
for(auto it = pipeline->outputData->objects.begin(); it != pipeline->outputData->objects.end(); it++) {
Value* output_count;
if (it->index_addr) {
output_count = builder->CreateLoad((Value*) it->index_addr, "count");
} else {
output_count = ConstantInt::get(int64_tpe, 1, true);
}
Value *output_addr = builder->CreateGEP(int64_tpe, result_sizes, ConstantInt::get(int64_tpe, i, true));
builder->CreateStore(output_count, output_addr);
i++;
}
builder->CreateRet(ConstantInt::get(int64_tpe, 0, true));
}
#ifndef _NOTDEBUG
verifyFunction(*function);
verifyModule(*module);
#endif
//printf("LLVM for pipeline %s\n", pipeline->name);
module->dump();
passmanager->run(*function);
// dump generated LLVM code
//module->dump();
auto handle = thread->jit->addModule(std::move(owner));
jit_function compiled_function = (jit_function) thread->jit->findSymbol(fname).getAddress();
if (!compiled_function) {
printf("Error creating function.\n");
return NULL;
}
JITFunction *jf = CreateJITFunction(thread, pipeline);
jf->size = size;
jf->function = compiled_function;
jf->jit = thread->jit.get();
jf->handle = handle;
assert(jf->function);
return jf;
}