예제 #1
0
파일: genoperator.c 프로젝트: jonas-l/ponyc
static bool is_always_false(compile_t* c, LLVMValueRef val)
{
  if(!is_constant_i1(c, val))
    return false;

  return LLVMConstIntGetZExtValue(val) == 0;
}
예제 #2
0
파일: genoperator.c 프로젝트: enigma/ponyc
static bool is_always_false(LLVMValueRef val)
{
  if(!LLVMIsAConstantInt(val))
    return false;

  return LLVMConstIntGetZExtValue(val) == 0;
}
예제 #3
0
파일: codegen.c 프로젝트: dobyrch/dbc
LLVMValueRef gen_init(struct node *ast)
{
	LLVMValueRef var, array;
	char *name;
	int size;

	name = ast->one->val;
	var = LLVMBuildAlloca(builder, TYPE_INT, name);

	if (ast->two) {
		size = LLVMConstIntGetZExtValue(codegen(ast->two));
		array = LLVMBuildAlloca(builder, TYPE_ARRAY(size), "");
		LLVMBuildStore(builder, lvalue_to_rvalue(array), var);
	}

	symtab_enter(name, var);

	return NULL;
}
예제 #4
0
파일: codegen.c 프로젝트: dobyrch/dbc
LLVMValueRef gen_vecdef(struct node *ast)
{
	LLVMValueRef global, array, init, *ival_list;
	struct node *n;
	int size, initsize, i;

	initsize = count_chain(ast->three);

	if (ast->two)
		size = LLVMConstIntGetZExtValue(codegen(ast->two));
	else
		size = 0;

	if (initsize > size)
		size = initsize;

	ival_list = calloc(sizeof(LLVMValueRef), size);

	if (size > 0 && ival_list == NULL)
		generror("out of memory");

	for (i = 0, n = ast->three; i < initsize; i++, n = n->two)
		/* TODO: handle NAMES (convert global pointer to int) */
		ival_list[initsize - i - 1] = codegen(n->one);

	for (i = initsize; i < size; i++)
		ival_list[i] = CONST(0);

	global = find_or_add_global(ast->one->val);
	array = LLVMAddGlobal(module, TYPE_ARRAY(size), ".gvec");
	LLVMSetLinkage(array, LLVMPrivateLinkage);

	if (initsize)
		init = LLVMConstArray(TYPE_INT, ival_list, size);
	else
		init = LLVMConstNull(TYPE_ARRAY(size));

	LLVMSetInitializer(array, init);
	LLVMSetInitializer(global, LLVMBuildPtrToInt(builder, array, TYPE_INT, ""));

	return NULL;
}
예제 #5
0
void ac_optimize_vs_outputs(struct ac_llvm_context *ctx,
			    LLVMValueRef main_fn,
			    uint8_t *vs_output_param_offset,
			    uint32_t num_outputs,
			    uint8_t *num_param_exports)
{
	LLVMBasicBlockRef bb;
	bool removed_any = false;
	struct ac_vs_exports exports;

	exports.num = 0;

	/* Process all LLVM instructions. */
	bb = LLVMGetFirstBasicBlock(main_fn);
	while (bb) {
		LLVMValueRef inst = LLVMGetFirstInstruction(bb);

		while (inst) {
			LLVMValueRef cur = inst;
			inst = LLVMGetNextInstruction(inst);
			struct ac_vs_exp_inst exp;

			if (LLVMGetInstructionOpcode(cur) != LLVMCall)
				continue;

			LLVMValueRef callee = ac_llvm_get_called_value(cur);

			if (!ac_llvm_is_function(callee))
				continue;

			const char *name = LLVMGetValueName(callee);
			unsigned num_args = LLVMCountParams(callee);

			/* Check if this is an export instruction. */
			if ((num_args != 9 && num_args != 8) ||
			    (strcmp(name, "llvm.SI.export") &&
			     strcmp(name, "llvm.amdgcn.exp.f32")))
				continue;

			LLVMValueRef arg = LLVMGetOperand(cur, AC_EXP_TARGET);
			unsigned target = LLVMConstIntGetZExtValue(arg);

			if (target < V_008DFC_SQ_EXP_PARAM)
				continue;

			target -= V_008DFC_SQ_EXP_PARAM;

			/* Parse the instruction. */
			memset(&exp, 0, sizeof(exp));
			exp.offset = target;
			exp.inst = cur;

			for (unsigned i = 0; i < 4; i++) {
				LLVMValueRef v = LLVMGetOperand(cur, AC_EXP_OUT0 + i);

				exp.chan[i].value = v;

				if (LLVMIsUndef(v)) {
					exp.chan[i].type = AC_IR_UNDEF;
				} else if (LLVMIsAConstantFP(v)) {
					LLVMBool loses_info;
					exp.chan[i].type = AC_IR_CONST;
					exp.chan[i].const_float =
						LLVMConstRealGetDouble(v, &loses_info);
				} else {
					exp.chan[i].type = AC_IR_VALUE;
				}
			}

			/* Eliminate constant and duplicated PARAM exports. */
			if (ac_eliminate_const_output(vs_output_param_offset,
						      num_outputs, &exp) ||
			    ac_eliminate_duplicated_output(vs_output_param_offset,
							   num_outputs, &exports,
							   &exp)) {
				removed_any = true;
			} else {
				exports.exp[exports.num++] = exp;
			}
		}
		bb = LLVMGetNextBasicBlock(bb);
	}

	/* Remove holes in export memory due to removed PARAM exports.
	 * This is done by renumbering all PARAM exports.
	 */
	if (removed_any) {
		uint8_t old_offset[VARYING_SLOT_MAX];
		unsigned out, i;

		/* Make a copy of the offsets. We need the old version while
		 * we are modifying some of them. */
		memcpy(old_offset, vs_output_param_offset,
		       sizeof(old_offset));

		for (i = 0; i < exports.num; i++) {
			unsigned offset = exports.exp[i].offset;

			/* Update vs_output_param_offset. Multiple outputs can
			 * have the same offset.
			 */
			for (out = 0; out < num_outputs; out++) {
				if (old_offset[out] == offset)
					vs_output_param_offset[out] = i;
			}

			/* Change the PARAM offset in the instruction. */
			LLVMSetOperand(exports.exp[i].inst, AC_EXP_TARGET,
				       LLVMConstInt(ctx->i32,
						    V_008DFC_SQ_EXP_PARAM + i, 0));
		}
		*num_param_exports = exports.num;
	}
}
예제 #6
0
파일: gencontrol.c 프로젝트: Sendence/ponyc
LLVMValueRef gen_if(compile_t* c, ast_t* ast)
{
  bool needed = is_result_needed(ast);
  ast_t* type = ast_type(ast);
  AST_GET_CHILDREN(ast, cond, left, right);

  ast_t* left_type = ast_type(left);
  ast_t* right_type = ast_type(right);

  // We will have no type if both branches have return statements.
  reach_type_t* phi_type = NULL;

  if(!is_control_type(type))
    phi_type = reach_type(c->reach, type);

  LLVMValueRef c_value = gen_expr(c, cond);

  if(c_value == NULL)
    return NULL;

  // If the conditional is constant, generate only one branch.
  bool gen_left = true;
  bool gen_right = true;

  if(LLVMIsAConstantInt(c_value))
  {
    int value = (int)LLVMConstIntGetZExtValue(c_value);

    if(value == 0)
      gen_left = false;
    else
      gen_right = false;
  }

  LLVMBasicBlockRef then_block = codegen_block(c, "if_then");
  LLVMBasicBlockRef else_block = codegen_block(c, "if_else");
  LLVMBasicBlockRef post_block = NULL;

  // If both branches return, we have no post block.
  if(!is_control_type(type))
    post_block = codegen_block(c, "if_post");

  LLVMValueRef test = LLVMBuildTrunc(c->builder, c_value, c->i1, "");
  LLVMBuildCondBr(c->builder, test, then_block, else_block);

  // Left branch.
  LLVMPositionBuilderAtEnd(c->builder, then_block);
  LLVMValueRef l_value;

  if(gen_left)
  {
    l_value = gen_expr(c, left);
  } else if(phi_type != NULL) {
    l_value = LLVMConstNull(phi_type->use_type);
  } else {
    LLVMBuildUnreachable(c->builder);
    l_value = GEN_NOVALUE;
  }

  if(l_value != GEN_NOVALUE)
  {
    if(needed)
      l_value = gen_assign_cast(c, phi_type->use_type, l_value, left_type);

    if(l_value == NULL)
      return NULL;

    then_block = LLVMGetInsertBlock(c->builder);
    LLVMBuildBr(c->builder, post_block);
  }

  // Right branch.
  LLVMPositionBuilderAtEnd(c->builder, else_block);
  LLVMValueRef r_value;

  if(gen_right)
  {
    r_value = gen_expr(c, right);
  } else if(phi_type != NULL) {
    r_value = LLVMConstNull(phi_type->use_type);
  } else {
    LLVMBuildUnreachable(c->builder);
    r_value = GEN_NOVALUE;
  }

  // If the right side returns, we don't branch to the post block.
  if(r_value != GEN_NOVALUE)
  {
    if(needed)
      r_value = gen_assign_cast(c, phi_type->use_type, r_value, right_type);

    if(r_value == NULL)
      return NULL;

    else_block = LLVMGetInsertBlock(c->builder);
    LLVMBuildBr(c->builder, post_block);
  }

  // If both sides return, we return a sentinal value.
  if(is_control_type(type))
    return GEN_NOVALUE;

  // Continue in the post block.
  LLVMPositionBuilderAtEnd(c->builder, post_block);

  if(needed)
  {
    LLVMValueRef phi = LLVMBuildPhi(c->builder, phi_type->use_type, "");

    if(l_value != GEN_NOVALUE)
      LLVMAddIncoming(phi, &l_value, &then_block, 1);

    if(r_value != GEN_NOVALUE)
      LLVMAddIncoming(phi, &r_value, &else_block, 1);

    return phi;
  }

  return GEN_NOTNEEDED;
}