aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2016-10-02 23:48:48 -0400
committerAndrew Kelley <superjoe30@gmail.com>2016-10-02 23:48:48 -0400
commitcd1bd78aa9b4120ee95cd6347b7adce0d460f9d2 (patch)
treedb1b897859fb6a1be751aa413d77b20ad411dc74 /src/codegen.cpp
parent633781e31dedaa27d9692d56f6cf073931ca311a (diff)
downloadzig-cd1bd78aa9b4120ee95cd6347b7adce0d460f9d2.tar.gz
zig-cd1bd78aa9b4120ee95cd6347b7adce0d460f9d2.zip
simple add function works with IR
Diffstat (limited to 'src/codegen.cpp')
-rw-r--r--src/codegen.cpp114
1 files changed, 105 insertions, 9 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp
index f2d7c8bb6a..2cf56169a6 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -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) {