Value* code_emitter::emit_closure (filter_t *closure_filter, primary_t *args) { int num_args = compiler_num_filter_args(closure_filter) - 3; Value *closure = NULL, *uservals; userval_info_t *info; int i; g_assert(closure_filter->kind == FILTER_MATHMAP || closure_filter->kind == FILTER_NATIVE); if (closure_filter->kind == FILTER_MATHMAP) { vector<Value*> args; args.push_back(invocation_arg); args.push_back(pools_arg); args.push_back(make_int_const(num_args)); args.push_back(lookup_filter_function(module, closure_filter)); args.push_back(lookup_init_frame_function(module, closure_filter)); args.push_back(lookup_main_filter_function(module, closure_filter)); args.push_back(lookup_init_x_function(module, closure_filter)); args.push_back(lookup_init_y_function(module, closure_filter)); closure = builder->CreateCall(module->getFunction(string("alloc_closure_image")), args.begin(), args.end()); uservals = builder->CreateCall(module->getFunction(string("get_closure_uservals")), closure); } else uservals = builder->CreateCall2(module->getFunction(string("alloc_uservals")), pools_arg, make_int_const(compiler_num_filter_args(closure_filter) - 3)); for (i = 0, info = closure_filter->userval_infos; info != 0; ++i, info = info->next) { const char *set_func_name = get_userval_set_func_name(info->type); Value *arg = emit_primary(&args[i]); /* FIXME: remove this eventually - bool needs to be an int */ if (info->type == USERVAL_BOOL_CONST) arg = promote(arg, TYPE_FLOAT); builder->CreateCall3(module->getFunction(string(set_func_name)), uservals, make_int_const(i), arg); } g_assert(i == num_args); if (closure_filter->kind == FILTER_MATHMAP) { builder->CreateCall3(module->getFunction(string("set_closure_pixel_size")), closure, lookup_internal("__canvasPixelW"), lookup_internal("__canvasPixelH")); return closure; } else { string filter_func_name = string("llvm_") + string(closure_filter->v.native.func_name); return builder->CreateCall3(module->getFunction(filter_func_name), invocation_arg, uservals, pools_arg); } }
Value* code_emitter::emit_rhs (rhs_t *rhs) { switch (rhs->kind) { case RHS_PRIMARY : return emit_primary(&rhs->v.primary); case RHS_INTERNAL : return lookup_internal(rhs->v.internal); case RHS_OP : { operation_t *op = rhs->v.op.op; type_t promotion_type = TYPE_NIL; char *function_name = compiler_function_name_for_op_rhs(rhs, &promotion_type); if (promotion_type == TYPE_NIL) assert(op->type_prop == TYPE_PROP_CONST); if (op->type_prop != TYPE_PROP_CONST) assert(promotion_type != TYPE_NIL); Function *func = module->getFunction(string(function_name)); g_assert(func); vector<Value*> args; args.push_back(invocation_arg); args.push_back(closure_arg); args.push_back(pools_arg); for (int i = 0; i < rhs->v.op.op->num_args; ++i) { type_t type = promotion_type == TYPE_NIL ? op->arg_types[i] : promotion_type; Value *val = emit_primary(&rhs->v.op.args[i], type == TYPE_FLOAT); val = promote(val, type); #ifndef __MINGW32__ if (sizeof(gpointer) == 4 && val->getType() == llvm_type_for_type(module, TYPE_COMPLEX)) { Value *copy = builder->CreateAlloca(llvm_type_for_type(module, TYPE_COMPLEX)); builder->CreateStore(val, copy); val = copy; } #endif #ifdef DEBUG_OUTPUT val->dump(); #endif args.push_back(val); } #ifdef DEBUG_OUTPUT func->dump(); #endif Value *result = builder->CreateCall(func, args.begin(), args.end()); /* FIXME: this is ugly - we should check for the type of the operation or resulting value */ if (is_complex_return_type(result->getType())) result = convert_complex_return_value(result); return result; } case RHS_FILTER : { int num_args = compiler_num_filter_args(rhs->v.filter.filter); Value *closure = emit_closure(rhs->v.filter.filter, rhs->v.filter.args); Function *func = lookup_filter_function(module, rhs->v.filter.filter); vector<Value*> args; args.push_back(invocation_arg); args.push_back(closure); args.push_back(emit_primary(&rhs->v.filter.args[num_args - 3])); args.push_back(emit_primary(&rhs->v.filter.args[num_args - 2])); args.push_back(emit_primary(&rhs->v.filter.args[num_args - 1])); args.push_back(pools_arg); return builder->CreateCall(func, args.begin(), args.end()); } case RHS_CLOSURE : return emit_closure(rhs->v.closure.filter, rhs->v.closure.args); case RHS_TUPLE : case RHS_TREE_VECTOR : { Function *set_func = module->getFunction(string("tuple_set")); Value *tuple = builder->CreateCall2(module->getFunction(string("alloc_tuple")), pools_arg, make_int_const(rhs->v.tuple.length)); int i; for (i = 0; i < rhs->v.tuple.length; ++i) { Value *val = emit_primary(&rhs->v.tuple.args[i], true); builder->CreateCall3(set_func, tuple, make_int_const(i), val); } if (rhs->kind == RHS_TREE_VECTOR) { return builder->CreateCall3(module->getFunction(string("alloc_tree_vector")), pools_arg, make_int_const(rhs->v.tuple.length), tuple); } else return tuple; } default : g_assert_not_reached(); } }