Example #1
0
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);
    }
}
Example #2
0
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();
    }
}