예제 #1
0
파일: codegen.c 프로젝트: dobyrch/dbc
LLVMValueRef gen_case(struct node *ast)
{
	LLVMValueRef func;
	LLVMBasicBlockRef this_block, next_block;

	this_block = LLVMGetInsertBlock(builder);
	func = LLVMGetBasicBlockParent(this_block);
	next_block = LLVMAppendBasicBlock(func, "");
	LLVMMoveBasicBlockAfter(next_block, this_block);

	case_blocks[case_count] = next_block;
	case_vals[case_count] = codegen(ast->one);

	LLVMBuildBr(builder, next_block);
	LLVMPositionBuilderAtEnd(builder, next_block);

	case_count++;

	if (case_count >= MAX_CASES)
		generror(">c");

	codegen(ast->two);

	return NULL;
}
예제 #2
0
파일: vm_state.c 프로젝트: ehostunreach/toy
void
vm_state_destroy(struct vm_state *vm)
{
   LLVMBasicBlockRef current_block, return_block;
   char *error;

   current_block = LLVMGetInsertBlock(vm->builder);
   return_block = LLVMInsertBasicBlock(current_block, "ret");

   LLVMPositionBuilderAtEnd(vm->builder, current_block);
   LLVMBuildBr(vm->builder, return_block);

   LLVMPositionBuilderAtEnd(vm->builder, return_block);
   LLVMBuildRetVoid(vm->builder);

   LLVMMoveBasicBlockAfter(return_block, current_block);

   LLVMDumpModule(vm->module);

   error = NULL;
   LLVMVerifyModule(vm->module, LLVMAbortProcessAction, &error);
   LLVMDisposeMessage(error);

   LLVMDisposeBuilder(vm->builder);
   LLVMDisposeModule(vm->module);
   symbol_table_destroy(vm->symtab);
}
예제 #3
0
파일: codegen.c 프로젝트: dobyrch/dbc
LLVMValueRef gen_label(struct node *ast)
{
	LLVMBasicBlockRef label_block, prev_block;

	prev_block = LLVMGetInsertBlock(builder);
	label_block = symtab_find(ast->one->val);

	LLVMMoveBasicBlockAfter(label_block, prev_block);
	LLVMPositionBuilderAtEnd(builder, prev_block);
	LLVMBuildBr(builder, label_block);
	LLVMPositionBuilderAtEnd(builder, label_block);

	codegen(ast->two);

	return NULL;
}
예제 #4
0
파일: gencall.c 프로젝트: killerswan/ponyc
static LLVMValueRef invoke_fun(compile_t* c, LLVMValueRef fun,
  LLVMValueRef* args, int count, const char* ret, bool setcc)
{
  if(fun == NULL)
    return NULL;

  LLVMBasicBlockRef this_block = LLVMGetInsertBlock(c->builder);
  LLVMBasicBlockRef then_block = LLVMInsertBasicBlockInContext(c->context,
    this_block, "invoke");
  LLVMMoveBasicBlockAfter(then_block, this_block);
  LLVMBasicBlockRef else_block = c->frame->invoke_target;

  LLVMValueRef invoke = LLVMBuildInvoke(c->builder, fun, args, count,
    then_block, else_block, ret);

  if(setcc)
    LLVMSetInstructionCallConv(invoke, c->callconv);

  LLVMPositionBuilderAtEnd(c->builder, then_block);
  return invoke;
}
예제 #5
0
파일: codegen.c 프로젝트: dobyrch/dbc
LLVMValueRef gen_funcdef(struct node *ast)
{
	LLVMValueRef global, func, retval;
	LLVMTypeRef func_type, *param_types;
	LLVMBasicBlockRef body_block, ret_block;
	int param_count, i;

	if (hcreate(SYMTAB_SIZE) == 0)
		generror(">s");

	param_count = count_chain(ast->two);
	param_types = calloc(sizeof(LLVMTypeRef), param_count);

	if (param_count > 0 && param_types == NULL)
		generror("out of memory");

	for (i = 0; i < param_count; i++)
		param_types[i] = TYPE_INT;

	func_type = LLVMFunctionType(TYPE_INT, param_types, param_count, 0);
	func = LLVMAddFunction(module, ".gfunc", func_type);
	LLVMSetLinkage(func, LLVMPrivateLinkage);
	/* TODO: How to specify stack alignment? Should be 16 bytes */
	LLVMAddFunctionAttr(func, LLVMStackAlignment);

	global = find_or_add_global(ast->one->val);
	LLVMSetInitializer(global, LLVMBuildPtrToInt(builder, func, TYPE_INT, ""));

	body_block = LLVMAppendBasicBlock(func, "");
	ret_block = LLVMAppendBasicBlock(func, "");
	LLVMPositionBuilderAtEnd(builder, body_block);

	retval = LLVMBuildAlloca(builder, TYPE_INT, "");
	LLVMBuildStore(builder, CONST(0), retval);

	symtab_enter(ast->one->val, global);
	symtab_enter(".return", ret_block);
	symtab_enter(".retval", retval);

	label_count = 0;
	predeclare_labels(ast->three);

	if (ast->two)
		codegen(ast->two);

	codegen(ast->three);

	LLVMBuildBr(builder, ret_block);
	/* TODO: Untangle out-of-order blocks */
	LLVMPositionBuilderAtEnd(builder, ret_block);
	LLVMBuildRet(builder, LLVMBuildLoad(builder, retval, ""));

	LLVMMoveBasicBlockAfter(ret_block, LLVMGetLastBasicBlock(func));

	/* TODO: Handle failed verification and print internal compiler error */
	LLVMVerifyFunction(func, LLVMPrintMessageAction);

	hdestroy();

	return NULL;
}
예제 #6
0
void Build::visit_select(ast::Select& x) {
  // Get the current LLVM block and function
  auto current_block = LLVMGetInsertBlock(_ctx.irb);
  auto current_fn = LLVMGetBasicBlockParent(current_block);

  std::vector<LLVMBasicBlockRef> blocks;
  std::vector<LLVMValueRef> values;
  std::vector<LLVMBasicBlockRef> value_blocks;

  // Resolve the type of us (in full; only used if we have a value)
  auto type = Resolve(_scope).run(x);

  // A Select expression has a value IIF it has an else and
  // each of its branches have a value
  bool has_value = !!type;

  auto do_select_branch = [&](ast::Block& block) -> bool {
    // Build the block
    auto value = Build(_ctx, _scope).run_scalar(block);
    auto iblock = LLVMGetInsertBlock(_ctx.irb);

    if (has_value && value && !value->type.is<code::TypeNone>()) {
      // Cast the value to the type analyzed result
      value = util::cast(_ctx, value, block, type, false);
      if (!value) return false;

      // Append to the value chain
      values.push_back(value->get_value(_ctx));
      value_blocks.push_back(iblock);
    } else if (!LLVMGetBasicBlockTerminator(iblock)) {
      // This block wasn't terminated and it has no value
      // We no longer have a value
      has_value = false;
    }

    // Append to the block chain
    blocks.push_back(iblock);

    return true;
  };

  // Iterate through each branch and build its contained block ..
  for (auto& br : x.branches) {
    // Build the condition expression
    auto cond = Build(_ctx, _scope).run_scalar(*br->condition);
    if (!cond) return;

    // Create the THEN and NEXT LLVM blocks
    auto then_block = LLVMAppendBasicBlock(current_fn, "select-then");
    auto next_block = LLVMAppendBasicBlock(current_fn, "select-next");

    // Build the conditional branch
    LLVMBuildCondBr(_ctx.irb, cond->get_value(_ctx), then_block, next_block);

    // Activate the THEN block
    LLVMPositionBuilderAtEnd(_ctx.irb, then_block);

    // Process the branch ..
    if (!do_select_branch(*br->block)) return;

    // Insert the `next` block after our current block.
    LLVMMoveBasicBlockAfter(next_block, LLVMGetInsertBlock(_ctx.irb));

    // Replace the outer-block with our new "merge" block.
    LLVMPositionBuilderAtEnd(_ctx.irb, next_block);
  }

  // Check for and build the else_block
  LLVMBasicBlockRef merge_block;
  if (x.else_block) {
    // Process the branch ..
    do_select_branch(*x.else_block);

    // Create the final "merge" block
    merge_block = LLVMAppendBasicBlock(current_fn, "select-merge");
  } else {
    // Use the elided "else" block as the "merge" block
    merge_block = LLVMGetLastBasicBlock(current_fn);
  }

  // Iterate through the established branches and have them return to
  // the "merge" block (if they are not otherwise terminated).
  unsigned term = 0;
  for (auto& ib : blocks) {
    if (!LLVMGetBasicBlockTerminator(ib)) {
      // Insert the non-conditional branch.
      LLVMPositionBuilderAtEnd(_ctx.irb, ib);
      LLVMBuildBr(_ctx.irb, merge_block);
    } else {
      term += 1;
    }
  }

  // If all blocks were terminated and there is an ELSE present;
  // remove the merge block
  if (term == blocks.size() && x.else_block) {
    LLVMDeleteBasicBlock(merge_block);
  }

  // Re-establish our insertion point.
  LLVMPositionBuilderAtEnd(_ctx.irb, merge_block);

  // If we still have a value ..
  if (has_value && values.size() > 0) {
    // Make the PHI value
    auto res = LLVMBuildPhi(_ctx.irb, type->handle(), "");
    LLVMAddIncoming(res, values.data(), value_blocks.data(), values.size());
    Ref<code::Value> res_value = new code::Value(res, type);

    _stack.push_front(res_value);
  }
}