diff options
Diffstat (limited to 'src/codegen.cpp')
| -rw-r--r-- | src/codegen.cpp | 251 |
1 files changed, 5 insertions, 246 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp index 278e983e93..89af7dedab 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -526,240 +526,6 @@ static LLVMValueRef gen_overflow_op(CodeGen *g, TypeTableEntry *type_entry, AddS return result; } -static LLVMValueRef gen_overflow_shl_op(CodeGen *g, TypeTableEntry *type_entry, - LLVMValueRef val1, LLVMValueRef val2) -{ - // for unsigned left shifting, we do the wrapping shift, then logically shift - // right the same number of bits - // if the values don't match, we have an overflow - // for signed left shifting we do the same except arithmetic shift right - - assert(type_entry->id == TypeTableEntryIdInt); - - LLVMValueRef result = LLVMBuildShl(g->builder, val1, val2, ""); - LLVMValueRef orig_val; - if (type_entry->data.integral.is_signed) { - orig_val = LLVMBuildAShr(g->builder, result, val2, ""); - } else { - orig_val = LLVMBuildLShr(g->builder, result, val2, ""); - } - LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, val1, orig_val, ""); - - LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "OverflowOk"); - LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "OverflowFail"); - LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); - - LLVMPositionBuilderAtEnd(g->builder, fail_block); - gen_debug_safety_crash(g); - - LLVMPositionBuilderAtEnd(g->builder, ok_block); - return result; -} - -static LLVMValueRef gen_div(CodeGen *g, AstNode *source_node, LLVMValueRef val1, LLVMValueRef val2, - TypeTableEntry *type_entry, bool exact) -{ - - if (want_debug_safety(g, source_node)) { - LLVMValueRef zero = LLVMConstNull(type_entry->type_ref); - LLVMValueRef is_zero_bit; - if (type_entry->id == TypeTableEntryIdInt) { - is_zero_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, val2, zero, ""); - } else if (type_entry->id == TypeTableEntryIdFloat) { - is_zero_bit = LLVMBuildFCmp(g->builder, LLVMRealOEQ, val2, zero, ""); - } else { - zig_unreachable(); - } - LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DivZeroOk"); - LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DivZeroFail"); - LLVMBuildCondBr(g->builder, is_zero_bit, fail_block, ok_block); - - LLVMPositionBuilderAtEnd(g->builder, fail_block); - gen_debug_safety_crash(g); - - LLVMPositionBuilderAtEnd(g->builder, ok_block); - } - - if (type_entry->id == TypeTableEntryIdFloat) { - assert(!exact); - return LLVMBuildFDiv(g->builder, val1, val2, ""); - } - - assert(type_entry->id == TypeTableEntryIdInt); - - if (exact) { - if (want_debug_safety(g, source_node)) { - LLVMValueRef remainder_val; - if (type_entry->data.integral.is_signed) { - remainder_val = LLVMBuildSRem(g->builder, val1, val2, ""); - } else { - remainder_val = LLVMBuildURem(g->builder, val1, val2, ""); - } - LLVMValueRef zero = LLVMConstNull(type_entry->type_ref); - LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, remainder_val, zero, ""); - - LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DivExactOk"); - LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DivExactFail"); - LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); - - LLVMPositionBuilderAtEnd(g->builder, fail_block); - gen_debug_safety_crash(g); - - LLVMPositionBuilderAtEnd(g->builder, ok_block); - } - if (type_entry->data.integral.is_signed) { - return LLVMBuildExactSDiv(g->builder, val1, val2, ""); - } else { - return ZigLLVMBuildExactUDiv(g->builder, val1, val2, ""); - } - } else { - if (type_entry->data.integral.is_signed) { - return LLVMBuildSDiv(g->builder, val1, val2, ""); - } else { - return LLVMBuildUDiv(g->builder, val1, val2, ""); - } - } -} - -static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node, - LLVMValueRef val1, LLVMValueRef val2, - TypeTableEntry *op1_type, TypeTableEntry *op2_type, - BinOpType bin_op) -{ - assert(op1_type == op2_type); - - switch (bin_op) { - case BinOpTypeBinOr: - case BinOpTypeAssignBitOr: - return LLVMBuildOr(g->builder, val1, val2, ""); - case BinOpTypeBinXor: - case BinOpTypeAssignBitXor: - return LLVMBuildXor(g->builder, val1, val2, ""); - case BinOpTypeBinAnd: - case BinOpTypeAssignBitAnd: - return LLVMBuildAnd(g->builder, val1, val2, ""); - case BinOpTypeBitShiftLeft: - case BinOpTypeBitShiftLeftWrap: - case BinOpTypeAssignBitShiftLeft: - case BinOpTypeAssignBitShiftLeftWrap: - { - assert(op1_type->id == TypeTableEntryIdInt); - bool is_wrapping = (bin_op == BinOpTypeBitShiftLeftWrap) || - (bin_op == BinOpTypeAssignBitShiftLeftWrap); - if (is_wrapping) { - return LLVMBuildShl(g->builder, val1, val2, ""); - } else if (want_debug_safety(g, source_node)) { - return gen_overflow_shl_op(g, op1_type, val1, val2); - } else if (op1_type->data.integral.is_signed) { - return ZigLLVMBuildNSWShl(g->builder, val1, val2, ""); - } else { - return ZigLLVMBuildNUWShl(g->builder, val1, val2, ""); - } - } - case BinOpTypeBitShiftRight: - case BinOpTypeAssignBitShiftRight: - assert(op1_type->id == TypeTableEntryIdInt); - assert(op2_type->id == TypeTableEntryIdInt); - - if (op1_type->data.integral.is_signed) { - return LLVMBuildAShr(g->builder, val1, val2, ""); - } else { - return LLVMBuildLShr(g->builder, val1, val2, ""); - } - case BinOpTypeAdd: - case BinOpTypeAddWrap: - case BinOpTypeAssignPlus: - case BinOpTypeAssignPlusWrap: - if (op1_type->id == TypeTableEntryIdFloat) { - return LLVMBuildFAdd(g->builder, val1, val2, ""); - } else if (op1_type->id == TypeTableEntryIdInt) { - bool is_wrapping = (bin_op == BinOpTypeAddWrap) || (bin_op == BinOpTypeAssignPlusWrap); - if (is_wrapping) { - return LLVMBuildAdd(g->builder, val1, val2, ""); - } else if (want_debug_safety(g, source_node)) { - return gen_overflow_op(g, op1_type, AddSubMulAdd, val1, val2); - } else if (op1_type->data.integral.is_signed) { - return LLVMBuildNSWAdd(g->builder, val1, val2, ""); - } else { - return LLVMBuildNUWAdd(g->builder, val1, val2, ""); - } - } else { - zig_unreachable(); - } - case BinOpTypeSub: - case BinOpTypeSubWrap: - case BinOpTypeAssignMinus: - case BinOpTypeAssignMinusWrap: - if (op1_type->id == TypeTableEntryIdFloat) { - return LLVMBuildFSub(g->builder, val1, val2, ""); - } else if (op1_type->id == TypeTableEntryIdInt) { - bool is_wrapping = (bin_op == BinOpTypeSubWrap || bin_op == BinOpTypeAssignMinusWrap); - if (is_wrapping) { - return LLVMBuildSub(g->builder, val1, val2, ""); - } else if (want_debug_safety(g, source_node)) { - return gen_overflow_op(g, op1_type, AddSubMulSub, val1, val2); - } else if (op1_type->data.integral.is_signed) { - return LLVMBuildNSWSub(g->builder, val1, val2, ""); - } else { - return LLVMBuildNUWSub(g->builder, val1, val2, ""); - } - } else { - zig_unreachable(); - } - case BinOpTypeMult: - case BinOpTypeMultWrap: - case BinOpTypeAssignTimes: - case BinOpTypeAssignTimesWrap: - if (op1_type->id == TypeTableEntryIdFloat) { - return LLVMBuildFMul(g->builder, val1, val2, ""); - } else if (op1_type->id == TypeTableEntryIdInt) { - bool is_wrapping = (bin_op == BinOpTypeMultWrap || bin_op == BinOpTypeAssignTimesWrap); - if (is_wrapping) { - return LLVMBuildMul(g->builder, val1, val2, ""); - } else if (want_debug_safety(g, source_node)) { - return gen_overflow_op(g, op1_type, AddSubMulMul, val1, val2); - } else if (op1_type->data.integral.is_signed) { - return LLVMBuildNSWMul(g->builder, val1, val2, ""); - } else { - return LLVMBuildNUWMul(g->builder, val1, val2, ""); - } - } else { - zig_unreachable(); - } - case BinOpTypeDiv: - case BinOpTypeAssignDiv: - return gen_div(g, source_node, val1, val2, op1_type, false); - case BinOpTypeMod: - case BinOpTypeAssignMod: - if (op1_type->id == TypeTableEntryIdFloat) { - return LLVMBuildFRem(g->builder, val1, val2, ""); - } else { - assert(op1_type->id == TypeTableEntryIdInt); - if (op1_type->data.integral.is_signed) { - return LLVMBuildSRem(g->builder, val1, val2, ""); - } else { - return LLVMBuildURem(g->builder, val1, val2, ""); - } - } - case BinOpTypeBoolOr: - case BinOpTypeBoolAnd: - case BinOpTypeCmpEq: - case BinOpTypeCmpNotEq: - case BinOpTypeCmpLessThan: - case BinOpTypeCmpGreaterThan: - case BinOpTypeCmpLessOrEq: - case BinOpTypeCmpGreaterOrEq: - case BinOpTypeInvalid: - case BinOpTypeAssign: - case BinOpTypeAssignBoolAnd: - case BinOpTypeAssignBoolOr: - case BinOpTypeUnwrapMaybe: - case BinOpTypeArrayCat: - case BinOpTypeArrayMult: - zig_unreachable(); - } - zig_unreachable(); -} static LLVMIntPredicate cmp_op_to_int_predicate(IrBinOp cmp_op, bool is_signed) { switch (cmp_op) { case IrBinOpCmpEq: @@ -825,7 +591,7 @@ static LLVMValueRef gen_struct_memcpy(CodeGen *g, LLVMValueRef src, LLVMValueRef return LLVMBuildCall(g->builder, g->memcpy_fn_val, params, 5, ""); } -static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType bin_op, +static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, LLVMValueRef target_ref, LLVMValueRef value, TypeTableEntry *op1_type, TypeTableEntry *op2_type) { @@ -834,18 +600,10 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b } if (handle_is_ptr(op1_type)) { assert(op1_type == op2_type); - assert(bin_op == BinOpTypeAssign); return gen_struct_memcpy(g, value, target_ref, op1_type); } - if (bin_op != BinOpTypeAssign) { - assert(source_node->type == NodeTypeBinOpExpr); - LLVMValueRef left_value = LLVMBuildLoad(g->builder, target_ref, ""); - - value = gen_arithmetic_bin_op(g, source_node, left_value, value, op1_type, op2_type, bin_op); - } - LLVMBuildStore(g->builder, value, target_ref); return nullptr; } @@ -1036,7 +794,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, return expr_val; } else { LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, 0, ""); - gen_assign_raw(g, cast_instruction->base.source_node, BinOpTypeAssign, + gen_assign_raw(g, cast_instruction->base.source_node, val_ptr, expr_val, child_type, actual_type); LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, 1, ""); @@ -1065,7 +823,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, LLVMBuildStore(g->builder, ok_err_val, err_tag_ptr); LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, 1, ""); - gen_assign_raw(g, cast_instruction->base.source_node, BinOpTypeAssign, + gen_assign_raw(g, cast_instruction->base.source_node, payload_ptr, expr_val, child_type, actual_type); return cast_instruction->tmp_ptr; @@ -1414,7 +1172,7 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, want_zeroes = true; if (have_init_expr) { - gen_assign_raw(g, init_value->source_node, BinOpTypeAssign, var->value_ref, + gen_assign_raw(g, init_value->source_node, var->value_ref, ir_llvm_value(g, init_value), var->type, init_value->type_entry); } else { bool ignore_uninit = false; @@ -1685,6 +1443,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, case IrInstructionIdSetDebugSafety: case IrInstructionIdArrayType: case IrInstructionIdSliceType: + case IrInstructionIdCompileVar: zig_unreachable(); case IrInstructionIdReturn: return ir_render_return(g, executable, (IrInstructionReturn *)instruction); |
