コード例 #1
0
ファイル: genfun.c プロジェクト: fydot/ponyc
static LLVMTypeRef send_message(compile_t* c, ast_t* fun, LLVMValueRef to,
  LLVMValueRef func, uint32_t index)
{
  // Get the parameter types.
  LLVMTypeRef f_type = LLVMGetElementType(LLVMTypeOf(func));
  int count = LLVMCountParamTypes(f_type) + 2;
  VLA(LLVMTypeRef, f_params, count);
  LLVMGetParamTypes(f_type, &f_params[2]);

  // The first one becomes the message size, the second the message ID.
  f_params[0] = c->i32;
  f_params[1] = c->i32;
  f_params[2] = c->void_ptr;
  LLVMTypeRef msg_type = LLVMStructTypeInContext(c->context, f_params, count,
    false);
  LLVMTypeRef msg_type_ptr = LLVMPointerType(msg_type, 0);

  // Allocate the message, setting its size and ID.
  size_t msg_size = LLVMABISizeOfType(c->target_data, msg_type);
  LLVMValueRef args[2];

  args[0] = LLVMConstInt(c->i32, pool_index(msg_size), false);
  args[1] = LLVMConstInt(c->i32, index, false);
  LLVMValueRef msg = gencall_runtime(c, "pony_alloc_msg", args, 2, "");
  LLVMValueRef msg_ptr = LLVMBuildBitCast(c->builder, msg, msg_type_ptr, "");

  // Trace while populating the message contents.
  LLVMValueRef start_trace = gencall_runtime(c, "pony_gc_send", NULL, 0, "");
  ast_t* params = ast_childidx(fun, 3);
  ast_t* param = ast_child(params);
  bool need_trace = false;

  for(int i = 3; i < count; i++)
  {
    LLVMValueRef arg = LLVMGetParam(func, i - 2);
    LLVMValueRef arg_ptr = LLVMBuildStructGEP(c->builder, msg_ptr, i, "");
    LLVMBuildStore(c->builder, arg, arg_ptr);

    need_trace |= gentrace(c, arg, ast_type(param));
    param = ast_sibling(param);
  }

  if(need_trace)
    gencall_runtime(c, "pony_send_done", NULL, 0, "");
  else
    LLVMInstructionEraseFromParent(start_trace);

  // Send the message.
  args[0] = LLVMBuildBitCast(c->builder, to, c->object_ptr, "");
  args[1] = msg;
  gencall_runtime(c, "pony_sendv", args, 2, "");

  // Return the type of the message.
  return msg_type_ptr;
}
コード例 #2
0
ファイル: genfun.c プロジェクト: jonas-l/ponyc
static void add_dispatch_case(compile_t* c, gentype_t* g, ast_t* fun,
  uint32_t index, LLVMValueRef handler, LLVMTypeRef type)
{
  // Add a case to the dispatch function to handle this message.
  codegen_startfun(c, g->dispatch_fn, false);
  LLVMBasicBlockRef block = codegen_block(c, "handler");
  LLVMValueRef id = LLVMConstInt(c->i32, index, false);
  LLVMAddCase(g->dispatch_switch, id, block);

  // Destructure the message.
  LLVMPositionBuilderAtEnd(c->builder, block);
  LLVMValueRef ctx = LLVMGetParam(g->dispatch_fn, 0);
  LLVMValueRef this_ptr = LLVMGetParam(g->dispatch_fn, 1);
  LLVMValueRef msg = LLVMBuildBitCast(c->builder,
    LLVMGetParam(g->dispatch_fn, 2), type, "");

  int count = LLVMCountParams(handler);
  size_t buf_size = count * sizeof(LLVMValueRef);
  LLVMValueRef* args = (LLVMValueRef*)pool_alloc_size(buf_size);
  args[0] = LLVMBuildBitCast(c->builder, this_ptr, g->use_type, "");

  // Trace the message.
  LLVMValueRef start_trace = gencall_runtime(c, "pony_gc_recv", &ctx, 1, "");
  ast_t* params = ast_childidx(fun, 3);
  ast_t* param = ast_child(params);
  bool need_trace = false;

  for(int i = 1; i < count; i++)
  {
    LLVMValueRef field = LLVMBuildStructGEP(c->builder, msg, i + 2, "");
    args[i] = LLVMBuildLoad(c->builder, field, "");

    need_trace |= gentrace(c, ctx, args[i], ast_type(param));
    param = ast_sibling(param);
  }

  if(need_trace)
  {
    gencall_runtime(c, "pony_recv_done", &ctx, 1, "");
  } else {
    LLVMInstructionEraseFromParent(start_trace);
  }

  // Call the handler.
  codegen_call(c, handler, args, count);
  LLVMBuildRetVoid(c->builder);
  codegen_finishfun(c);
  pool_free_size(buf_size, args);
}
コード例 #3
0
ファイル: ac_llvm_build.c プロジェクト: ndesh26/Mesa
/* Return true if the PARAM export has been eliminated. */
static bool ac_eliminate_const_output(uint8_t *vs_output_param_offset,
				      uint32_t num_outputs,
				      struct ac_vs_exp_inst *exp)
{
	unsigned i, default_val; /* SPI_PS_INPUT_CNTL_i.DEFAULT_VAL */
	bool is_zero[4] = {}, is_one[4] = {};

	for (i = 0; i < 4; i++) {
		/* It's a constant expression. Undef outputs are eliminated too. */
		if (exp->chan[i].type == AC_IR_UNDEF) {
			is_zero[i] = true;
			is_one[i] = true;
		} else if (exp->chan[i].type == AC_IR_CONST) {
			if (exp->chan[i].const_float == 0)
				is_zero[i] = true;
			else if (exp->chan[i].const_float == 1)
				is_one[i] = true;
			else
				return false; /* other constant */
		} else
			return false;
	}

	/* Only certain combinations of 0 and 1 can be eliminated. */
	if (is_zero[0] && is_zero[1] && is_zero[2])
		default_val = is_zero[3] ? 0 : 1;
	else if (is_one[0] && is_one[1] && is_one[2])
		default_val = is_zero[3] ? 2 : 3;
	else
		return false;

	/* The PARAM export can be represented as DEFAULT_VAL. Kill it. */
	LLVMInstructionEraseFromParent(exp->inst);

	/* Change OFFSET to DEFAULT_VAL. */
	for (i = 0; i < num_outputs; i++) {
		if (vs_output_param_offset[i] == exp->offset) {
			vs_output_param_offset[i] =
				AC_EXP_PARAM_DEFAULT_VAL_0000 + default_val;
			break;
		}
	}
	return true;
}
コード例 #4
0
ファイル: genoperator.c プロジェクト: jonas-l/ponyc
LLVMValueRef make_short_circuit(compile_t* c, ast_t* left, ast_t* right,
  bool is_and)
{
  LLVMBasicBlockRef entry_block = LLVMGetInsertBlock(c->builder);
  LLVMBasicBlockRef left_block = codegen_block(c, "sc_left");
  LLVMValueRef branch = LLVMBuildBr(c->builder, left_block);

  LLVMPositionBuilderAtEnd(c->builder, left_block);
  LLVMValueRef l_value = gen_expr(c, left);

  if(l_value == NULL)
    return NULL;

  if(is_constant_i1(c, l_value))
  {
    LLVMInstructionEraseFromParent(branch);
    LLVMDeleteBasicBlock(left_block);
    LLVMPositionBuilderAtEnd(c->builder, entry_block);

    if(is_and)
    {
      if(is_always_false(c, l_value))
        return gen_expr(c, left);
    } else {
      if(is_always_true(c, l_value))
        return gen_expr(c, left);
    }

    return gen_expr(c, right);
  }

  LLVMBasicBlockRef left_exit_block = LLVMGetInsertBlock(c->builder);

  LLVMBasicBlockRef right_block = codegen_block(c, "sc_right");
  LLVMBasicBlockRef post_block = codegen_block(c, "sc_post");

  if(is_and)
    LLVMBuildCondBr(c->builder, l_value, right_block, post_block);
  else
    LLVMBuildCondBr(c->builder, l_value, post_block, right_block);

  LLVMPositionBuilderAtEnd(c->builder, right_block);
  LLVMValueRef r_value = gen_expr(c, right);

  if(r_value == NULL)
    return NULL;

  LLVMBasicBlockRef right_exit_block = LLVMGetInsertBlock(c->builder);
  LLVMBuildBr(c->builder, post_block);

  LLVMPositionBuilderAtEnd(c->builder, post_block);
  LLVMValueRef phi = LLVMBuildPhi(c->builder, c->i1, "");

  LLVMAddIncoming(phi, &l_value, &left_exit_block, 1);
  LLVMAddIncoming(phi, &r_value, &right_exit_block, 1);

  if(is_constant_i1(c, r_value))
  {
    if(is_and)
    {
      if(is_always_false(c, r_value))
        return r_value;
    } else {
      if(is_always_true(c, r_value))
        return r_value;
    }

    return l_value;
  }

  return phi;
}
コード例 #5
0
ファイル: ac_llvm_build.c プロジェクト: ndesh26/Mesa
static bool ac_eliminate_duplicated_output(uint8_t *vs_output_param_offset,
					   uint32_t num_outputs,
					   struct ac_vs_exports *processed,
				           struct ac_vs_exp_inst *exp)
{
	unsigned p, copy_back_channels = 0;

	/* See if the output is already in the list of processed outputs.
	 * The LLVMValueRef comparison relies on SSA.
	 */
	for (p = 0; p < processed->num; p++) {
		bool different = false;

		for (unsigned j = 0; j < 4; j++) {
			struct ac_vs_exp_chan *c1 = &processed->exp[p].chan[j];
			struct ac_vs_exp_chan *c2 = &exp->chan[j];

			/* Treat undef as a match. */
			if (c2->type == AC_IR_UNDEF)
				continue;

			/* If c1 is undef but c2 isn't, we can copy c2 to c1
			 * and consider the instruction duplicated.
			 */
			if (c1->type == AC_IR_UNDEF) {
				copy_back_channels |= 1 << j;
				continue;
			}

			/* Test whether the channels are not equal. */
			if (c1->type != c2->type ||
			    (c1->type == AC_IR_CONST &&
			     c1->const_float != c2->const_float) ||
			    (c1->type == AC_IR_VALUE &&
			     c1->value != c2->value)) {
				different = true;
				break;
			}
		}
		if (!different)
			break;

		copy_back_channels = 0;
	}
	if (p == processed->num)
		return false;

	/* If a match was found, but the matching export has undef where the new
	 * one has a normal value, copy the normal value to the undef channel.
	 */
	struct ac_vs_exp_inst *match = &processed->exp[p];

	while (copy_back_channels) {
		unsigned chan = u_bit_scan(&copy_back_channels);

		assert(match->chan[chan].type == AC_IR_UNDEF);
		LLVMSetOperand(match->inst, AC_EXP_OUT0 + chan,
			       exp->chan[chan].value);
		match->chan[chan] = exp->chan[chan];
	}

	/* The PARAM export is duplicated. Kill it. */
	LLVMInstructionEraseFromParent(exp->inst);

	/* Change OFFSET to the matching export. */
	for (unsigned i = 0; i < num_outputs; i++) {
		if (vs_output_param_offset[i] == exp->offset) {
			vs_output_param_offset[i] = match->offset;
			break;
		}
	}
	return true;
}
コード例 #6
0
ファイル: function.c プロジェクト: dasfaha/sky
// Recursively generates LLVM code for the function AST node.
//
// node    - The node to generate an LLVM value for.
// module  - The compilation unit this node is a part of.
// value   - A pointer to where the LLVM value should be returned.
//
// Returns 0 if successful, otherwise returns -1.
int qip_ast_function_codegen(qip_ast_node *node, qip_module *module,
                             LLVMValueRef *value)
{
    int rc;

    LLVMBuilderRef builder = module->compiler->llvm_builder;

    // Create function prototype.
    LLVMValueRef func = NULL;
    rc = qip_ast_function_codegen_prototype(node, module, &func);
    check(rc == 0, "Unable to generate function prototype");
    
    // Store the current function on the module.
    qip_scope *scope = qip_scope_create_function(func); check_mem(scope);
    rc = qip_module_push_scope(module, scope);
    check(rc == 0, "Unable to add function scope");

    // Grab the External metadata node if there is one.
    qip_ast_node *external_metadata_node = NULL;
    rc = qip_ast_function_get_external_metadata_node(node, &external_metadata_node);
    check(rc == 0, "Unable to retrieve external metadata node");
    
    // Generate basic block for body.
    LLVMBasicBlockRef block = LLVMAppendBasicBlock(scope->llvm_function, "");

    // Generate function arguments.
    LLVMPositionBuilderAtEnd(builder, block);
    rc = qip_ast_function_codegen_args(node, module);
    check(rc == 0, "Unable to codegen function arguments");

    // If this function is marked as external then dynamically generate the
    // code to call the function and return the value.
    if(external_metadata_node != NULL) {
        rc = qip_ast_function_generate_external_call(node, module, block);
        check(rc == 0, "Unable to generate call to external function");
    }
    // Otherwise generate the body if it exists.
    else if(node->function.body != NULL) {
        rc = qip_ast_block_codegen_with_block(node->function.body, module, block);
        check(rc == 0, "Unable to generate function body statements");

        // If this is a void return type and there is no explicit return then
        // add one before the end.
        if(qip_ast_type_ref_is_void(node->function.return_type)) {
            if(node->function.body->block.expr_count > 0 &&
               node->function.body->block.exprs[node->function.body->block.expr_count-1]->type != QIP_AST_TYPE_FRETURN)
            {
                LLVMBuildRetVoid(builder);
            }
        }
    }
    // If there's no body or it's not external then we have a problem.
    else {
        sentinel("Function must be external or have a body");
    }
    
    // Dump before verification.
    //LLVMDumpValue(func);
    
    // Verify function.
    rc = LLVMVerifyFunction(func, LLVMPrintMessageAction);
    check(rc != 1, "Invalid function");

    // Unset the current function.
    rc = qip_module_pop_scope(module);
    check(rc == 0, "Unable to remove function scope");
    if(scope->llvm_last_alloca != NULL) {
        LLVMInstructionEraseFromParent(scope->llvm_last_alloca);
        scope->llvm_last_alloca = NULL;
    }

    // Reset the builder position at the end of the new function scope if
    // one still exists.
    qip_scope *new_scope = NULL;
    rc = qip_module_get_current_function_scope(module, &new_scope);
    check(rc == 0, "Unable to retrieve new function scope");
    
    if(new_scope != NULL) {
        LLVMPositionBuilderAtEnd(builder, LLVMGetLastBasicBlock(new_scope->llvm_function));
    }

    // Return function as a value.
    *value = func;
    
    return 0;

error:
    //if(func) LLVMDeleteFunction(func);
    *value = NULL;
    return -1;
}