Exemple #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);
    }
}
/// EmitFPutS - Emit a call to the puts function.  Str is required to be a
/// pointer and File is a pointer to FILE.
void llvm::EmitFPutS(Value *Str, Value *File, IRBuilder<> &B,
                     const TargetData *TD) {
  Module *M = B.GetInsertBlock()->getParent()->getParent();
  AttributeWithIndex AWI[3];
  AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture);
  AWI[1] = AttributeWithIndex::get(2, Attribute::NoCapture);
  AWI[2] = AttributeWithIndex::get(~0u, Attribute::NoUnwind);
  Constant *F;
  if (File->getType()->isPointerTy())
    F = M->getOrInsertFunction("fputs", AttrListPtr::get(AWI, 3),
                               B.getInt32Ty(),
                               B.getInt8PtrTy(),
                               File->getType(), NULL);
  else
    F = M->getOrInsertFunction("fputs", B.getInt32Ty(),
                               B.getInt8PtrTy(),
                               File->getType(), NULL);
  CallInst *CI = B.CreateCall2(F, CastToCStr(Str, B), File, "fputs");

  if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
    CI->setCallingConv(Fn->getCallingConv());
}
Exemple #3
0
Value*
code_emitter::setup_init_x_or_y_function (string function_name, const char *internal_name, StructType *vars_type)
{
    current_function = module->getFunction(function_name);

    Value *slice_arg;

    Function::arg_iterator args = current_function->arg_begin();

    slice_arg = args++;
    slice_arg->setName("slice");
    closure_arg = args++;
    closure_arg->setName("closure");
    set_internal(::lookup_internal(filter->v.mathmap.internals, internal_name, true), args++);
    set_internal(::lookup_internal(filter->v.mathmap.internals, "t", true), args++);

    BasicBlock *block = BasicBlock::Create("entry", current_function);

    builder = new IRBuilder<> (block);

    frame_arg = builder->CreateCall(module->getFunction(string("get_slice_frame")), slice_arg);
    invocation_arg = builder->CreateCall(module->getFunction(string("get_frame_invocation")), frame_arg);
    pools_arg = builder->CreateCall(module->getFunction("get_slice_pools"), slice_arg);

    set_internals_from_invocation(invocation_arg);

    set_xy_vars_from_frame();

    ret_var = builder->CreateCall2(module->getFunction(string("_mathmap_pools_alloc")),
				   pools_arg, emit_sizeof(vars_type));

    Value *vars_var = builder->CreateBitCast(ret_var, PointerType::getUnqual(vars_type));

    alloc_complex_copy_var();

    return vars_var;
}
Exemple #4
0
void
code_emitter::setup_init_frame_function ()
{
    Value *t_arg;
    Function::arg_iterator args = init_frame_function->arg_begin();

    invocation_arg = args++;
    invocation_arg->setName("invocation");
    //frame_arg = args++;
    //frame_arg->setName("frame");
    closure_arg = args++;
    closure_arg->setName("closure");
    t_arg = args++;
    t_arg->setName("t");
    pools_arg = args++;
    pools_arg->setName("pools");

    BasicBlock *block = BasicBlock::Create("entry", init_frame_function);

    builder = new IRBuilder<> (block);

    //invocation_arg = builder->CreateCall(module->getFunction(string("get_frame_invocation")), frame_arg);
    //pools_arg = builder->CreateCall(module->getFunction(string("get_frame_pools")), frame_arg);

    set_internal(::lookup_internal(filter->v.mathmap.internals, "t", true), t_arg);

    set_internals_from_invocation(invocation_arg);

    ret_var = builder->CreateCall2(module->getFunction(string("_mathmap_pools_alloc")),
				   pools_arg, emit_sizeof(xy_vars_type));
    xy_vars_var = builder->CreateBitCast(ret_var, PointerType::getUnqual(xy_vars_type));

    alloc_complex_copy_var();

    current_function = init_frame_function;
}
/// compile_if - Emit code for '['
void BrainFTraceRecorder::compile_if(BrainFTraceNode *node,
                                     IRBuilder<>& builder) {
  BasicBlock *ZeroChild = 0;
  BasicBlock *NonZeroChild = 0;
  BasicBlock *Parent = builder.GetInsertBlock();
  
  LLVMContext &Context = Header->getContext();
  
  // If both directions of the branch go back to the trace-head, just
  // jump there directly.
  if (node->left == (BrainFTraceNode*)~0ULL &&
      node->right == (BrainFTraceNode*)~0ULL) {
    HeaderPHI->addIncoming(DataPtr, builder.GetInsertBlock());
    builder.CreateBr(Header);
    return;
  }
  
  // Otherwise, there are two cases to handle for each direction:
  //   ~0ULL - A branch back to the trace head
  //   0 - A branch out of the trace
  //   * - A branch to a node we haven't compiled yet.
  // Go ahead and generate code for both targets.
  
  if (node->left == (BrainFTraceNode*)~0ULL) {
    NonZeroChild = Header;
    HeaderPHI->addIncoming(DataPtr, Parent);
  } else if (node->left == 0) {
    NonZeroChild = BasicBlock::Create(Context,
                                   "exit_left_"+utostr(node->pc),
                                   Header->getParent());
    builder.SetInsertPoint(NonZeroChild);
    
    // Set the extension leaf, which is a pointer to the leaf of the trace
    // tree from which we are side exiting.
    ConstantInt *ExtLeaf = ConstantInt::get(int_type, (intptr_t)node);
    builder.CreateStore(ExtLeaf, ext_leaf);
    
    ConstantInt *NewPc = ConstantInt::get(int_type, node->pc+1);
    Value *BytecodeIndex =
      builder.CreateConstInBoundsGEP1_32(bytecode_array, node->pc+1);
    Value *Target = builder.CreateLoad(BytecodeIndex);
    CallInst *Call =cast<CallInst>(builder.CreateCall2(Target, NewPc, DataPtr));
    Call->setTailCall();
    builder.CreateRetVoid();
  } else {
    NonZeroChild = BasicBlock::Create(Context, 
                                      utostr(node->left->pc), 
                                      Header->getParent());
    builder.SetInsertPoint(NonZeroChild);
    compile_opcode(node->left, builder);
  }
  
  if (node->right == (BrainFTraceNode*)~0ULL) {
    ZeroChild = Header;
    HeaderPHI->addIncoming(DataPtr, Parent);
  } else if (node->right == 0) {
    ZeroChild = BasicBlock::Create(Context,
                                   "exit_right_"+utostr(node->pc),
                                   Header->getParent());
    builder.SetInsertPoint(ZeroChild);
    
    // Set the extension leaf, which is a pointer to the leaf of the trace
    // tree from which we are side exiting.
    ConstantInt *ExtLeaf = ConstantInt::get(int_type, (intptr_t)node);
    builder.CreateStore(ExtLeaf, ext_leaf);
    
    ConstantInt *NewPc = ConstantInt::get(int_type, JumpMap[node->pc]+1);
    Value *BytecodeIndex =
      builder.CreateConstInBoundsGEP1_32(bytecode_array, JumpMap[node->pc]+1);
    Value *Target = builder.CreateLoad(BytecodeIndex);
    CallInst *Call =cast<CallInst>(builder.CreateCall2(Target, NewPc, DataPtr));
    Call->setTailCall();
    builder.CreateRetVoid();
  } else {
    ZeroChild = BasicBlock::Create(Context, 
                                      utostr(node->right->pc), 
                                      Header->getParent());
    builder.SetInsertPoint(ZeroChild);
    compile_opcode(node->right, builder);
  }
  
  // Generate the test and branch to select between the targets.
  builder.SetInsertPoint(Parent);
  Value *Loaded = builder.CreateLoad(DataPtr);
  Value *Cmp = builder.CreateICmpEQ(Loaded, 
                                       ConstantInt::get(Loaded->getType(), 0));
  builder.CreateCondBr(Cmp, ZeroChild, NonZeroChild);
}
Exemple #6
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();
    }
}
Exemple #7
0
Value*
code_emitter::emit_primary (primary_t *primary, bool need_float)
{
    switch (primary->kind)
    {
	case PRIMARY_VALUE :
	    if (primary->v.value->index < 0)
	    {
		switch (primary->v.value->compvar->type)
		{
		    case TYPE_INT :
			return make_int_const(0);
		    case TYPE_FLOAT :
			return make_float_const(0.0);
		    case TYPE_IMAGE :
			return builder->CreateCall(module->getFunction(string("get_uninited_image")));
		    default :
			g_assert_not_reached();
		}
	    }
	    else
	    {
		Value *val = lookup_value(primary->v.value);

		if (need_float)
		    val = promote(val, TYPE_FLOAT);
		return val;
	    }

	case PRIMARY_CONST :
	    switch (primary->const_type) {
		case TYPE_INT :
		    if (need_float)
			return make_float_const((float)primary->v.constant.int_value);
		    else
			return make_int_const(primary->v.constant.int_value);
		case TYPE_FLOAT :
		    return make_float_const(primary->v.constant.float_value);
		case TYPE_COMPLEX :
		    {
			assert(!need_float);
			Value *val = builder->CreateCall2(module->getFunction(string("make_complex")),
							  make_float_const(__real__ primary->v.constant.complex_value),
							  make_float_const(__imag__ primary->v.constant.complex_value));
			return convert_complex_return_value(val);
		    }
		case TYPE_COLOR :
		    assert(!need_float);
		    return builder->CreateCall4(module->getFunction(string("make_color")),
						make_int_const(RED(primary->v.constant.color_value)),
						make_int_const(GREEN(primary->v.constant.color_value)),
						make_int_const(BLUE(primary->v.constant.color_value)),
						make_int_const(ALPHA(primary->v.constant.color_value)));
		default :
		    g_assert_not_reached();
	    }

	default:
	    g_assert_not_reached();
    }
}