simple add function works with IR

This commit is contained in:
Andrew Kelley
2016-10-02 23:48:48 -04:00
parent 633781e31d
commit cd1bd78aa9
6 changed files with 1014 additions and 132 deletions

View File

@@ -65,8 +65,6 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
g->is_test_build = false;
g->want_h_file = true;
g->invalid_instruction = allocate<IrInstruction>(1);
// the error.Ok value
g->error_decls.append(nullptr);
@@ -252,10 +250,6 @@ static void set_debug_source_node(CodeGen *g, AstNode *node) {
ZigLLVMSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1, node->block_context->di_scope);
}
static void ir_set_debug(CodeGen *g, IrInstruction *instruction) {
set_debug_source_node(g, instruction->source_node);
}
static void clear_debug_source_node(CodeGen *g) {
ZigLLVMClearCurrentDebugLocation(g->builder);
}
@@ -375,6 +369,10 @@ static bool want_debug_safety(CodeGen *g, AstNode *node) {
return want_debug_safety_recursive(g, node->block_context);
}
static bool ir_want_debug_safety(CodeGen *g, IrInstruction *instruction) {
return want_debug_safety(g, instruction->source_node);
}
static void gen_debug_safety_crash(CodeGen *g) {
LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");
LLVMBuildUnreachable(g->builder);
@@ -2800,12 +2798,104 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {
}
static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) {
ir_set_debug(g, &return_instruction->base);
LLVMBuildRet(g->builder, return_instruction->value->llvm_value);
return nullptr;
}
static LLVMValueRef ir_render_load_var(CodeGen *g, IrExecutable *executable,
IrInstructionLoadVar *load_var_instruction)
{
VariableTableEntry *var = load_var_instruction->var;
if (!type_has_bits(var->type))
return nullptr;
assert(var->value_ref);
return get_handle_value(g, load_var_instruction->base.source_node, var->value_ref, var->type);
}
static LLVMValueRef ir_render_bin_op_bool(CodeGen *g, IrExecutable *executable,
IrInstructionBinOp *bin_op_instruction)
{
IrBinOp op_id = bin_op_instruction->op_id;
LLVMValueRef op1 = bin_op_instruction->op1->llvm_value;
LLVMValueRef op2 = bin_op_instruction->op2->llvm_value;
if (op_id == IrBinOpBoolOr) {
return LLVMBuildOr(g->builder, op1, op2, "");
} else if (op_id == IrBinOpBoolAnd) {
return LLVMBuildAnd(g->builder, op1, op2, "");
} else {
zig_unreachable();
}
}
static LLVMValueRef ir_render_bin_op_add(CodeGen *g, IrExecutable *executable,
IrInstructionBinOp *bin_op_instruction)
{
IrBinOp op_id = bin_op_instruction->op_id;
IrInstruction *op1 = bin_op_instruction->op1;
IrInstruction *op2 = bin_op_instruction->op2;
assert(op1->type_entry == op2->type_entry);
if (op1->type_entry->id == TypeTableEntryIdFloat) {
return LLVMBuildFAdd(g->builder, op1->llvm_value, op2->llvm_value, "");
} else if (op1->type_entry->id == TypeTableEntryIdInt) {
bool is_wrapping = (op_id == IrBinOpAddWrap);
if (is_wrapping) {
return LLVMBuildAdd(g->builder, op1->llvm_value, op2->llvm_value, "");
} else if (ir_want_debug_safety(g, &bin_op_instruction->base)) {
return gen_overflow_op(g, op1->type_entry, AddSubMulAdd, op1->llvm_value, op2->llvm_value);
} else if (op1->type_entry->data.integral.is_signed) {
return LLVMBuildNSWAdd(g->builder, op1->llvm_value, op2->llvm_value, "");
} else {
return LLVMBuildNUWAdd(g->builder, op1->llvm_value, op2->llvm_value, "");
}
} else {
zig_unreachable();
}
}
static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
IrInstructionBinOp *bin_op_instruction)
{
IrBinOp op_id = bin_op_instruction->op_id;
switch (op_id) {
case IrBinOpInvalid:
case IrBinOpArrayCat:
case IrBinOpArrayMult:
zig_unreachable();
case IrBinOpBoolOr:
case IrBinOpBoolAnd:
return ir_render_bin_op_bool(g, executable, bin_op_instruction);
case IrBinOpCmpEq:
case IrBinOpCmpNotEq:
case IrBinOpCmpLessThan:
case IrBinOpCmpGreaterThan:
case IrBinOpCmpLessOrEq:
case IrBinOpCmpGreaterOrEq:
zig_panic("TODO bin op cmp");
case IrBinOpAdd:
case IrBinOpAddWrap:
return ir_render_bin_op_add(g, executable, bin_op_instruction);
case IrBinOpBinOr:
case IrBinOpBinXor:
case IrBinOpBinAnd:
case IrBinOpBitShiftLeft:
case IrBinOpBitShiftLeftWrap:
case IrBinOpBitShiftRight:
case IrBinOpSub:
case IrBinOpSubWrap:
case IrBinOpMult:
case IrBinOpMultWrap:
case IrBinOpDiv:
case IrBinOpMod:
zig_panic("TODO render more bin ops to LLVM");
}
zig_unreachable();
}
static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
set_debug_source_node(g, instruction->source_node);
switch (instruction->id) {
case IrInstructionIdInvalid:
zig_unreachable();
@@ -2813,14 +2903,17 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return gen_const_val(g, instruction->type_entry, &instruction->static_value);
case IrInstructionIdReturn:
return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
case IrInstructionIdLoadVar:
return ir_render_load_var(g, executable, (IrInstructionLoadVar *)instruction);
case IrInstructionIdBinOp:
return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction);
case IrInstructionIdCondBr:
case IrInstructionIdSwitchBr:
case IrInstructionIdPhi:
case IrInstructionIdBinOp:
case IrInstructionIdLoadVar:
case IrInstructionIdStoreVar:
case IrInstructionIdCall:
case IrInstructionIdBuiltinCall:
case IrInstructionIdCast:
zig_panic("TODO render more IR instructions to LLVM");
}
zig_unreachable();
@@ -5013,6 +5106,9 @@ static void init(CodeGen *g, Buf *source_path) {
define_builtin_types(g);
define_builtin_fns(g);
g->invalid_instruction = allocate<IrInstruction>(1);
g->invalid_instruction->type_entry = g->builtin_types.entry_invalid;
}
void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code) {