diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2017-02-03 12:09:13 -0500 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2017-02-03 12:09:13 -0500 |
| commit | e00eec1c299ccc721f4272a506321939be7094f1 (patch) | |
| tree | a1069f5a6fa80841338bcd5d4a77a95b2ecfa03b /src | |
| parent | aae168550fa3d8b21478deb7198513dad8cc0b37 (diff) | |
| download | zig-e00eec1c299ccc721f4272a506321939be7094f1.tar.gz zig-e00eec1c299ccc721f4272a506321939be7094f1.zip | |
typedefs work for binary math operations
Diffstat (limited to 'src')
| -rw-r--r-- | src/codegen.cpp | 59 | ||||
| -rw-r--r-- | src/ir.cpp | 43 |
2 files changed, 52 insertions, 50 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp index c86b6ac56d..2b3dbfa0af 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -816,6 +816,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, IrInstruction *op2 = bin_op_instruction->op2; assert(op1->value.type == op2->value.type); + TypeTableEntry *canon_type = get_underlying_type(op1->value.type); bool want_debug_safety = bin_op_instruction->safety_check_on && ir_want_debug_safety(g, &bin_op_instruction->base); @@ -837,22 +838,22 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, case IrBinOpCmpGreaterThan: case IrBinOpCmpLessOrEq: case IrBinOpCmpGreaterOrEq: - if (op1->value.type->id == TypeTableEntryIdFloat) { + if (canon_type->id == TypeTableEntryIdFloat) { LLVMRealPredicate pred = cmp_op_to_real_predicate(op_id); return LLVMBuildFCmp(g->builder, pred, op1_value, op2_value, ""); - } else if (op1->value.type->id == TypeTableEntryIdInt) { - LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, op1->value.type->data.integral.is_signed); + } else if (canon_type->id == TypeTableEntryIdInt) { + LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, canon_type->data.integral.is_signed); return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, ""); - } else if (op1->value.type->id == TypeTableEntryIdEnum) { - if (op1->value.type->data.enumeration.gen_field_count == 0) { + } else if (canon_type->id == TypeTableEntryIdEnum) { + if (canon_type->data.enumeration.gen_field_count == 0) { LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false); return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, ""); } else { zig_unreachable(); } - } else if (op1->value.type->id == TypeTableEntryIdPureError || - op1->value.type->id == TypeTableEntryIdPointer || - op1->value.type->id == TypeTableEntryIdBool) + } else if (canon_type->id == TypeTableEntryIdPureError || + canon_type->id == TypeTableEntryIdPointer || + canon_type->id == TypeTableEntryIdBool) { LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false); return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, ""); @@ -861,15 +862,15 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, } case IrBinOpAdd: case IrBinOpAddWrap: - if (op1->value.type->id == TypeTableEntryIdFloat) { + if (canon_type->id == TypeTableEntryIdFloat) { return LLVMBuildFAdd(g->builder, op1_value, op2_value, ""); - } else if (op1->value.type->id == TypeTableEntryIdInt) { + } else if (canon_type->id == TypeTableEntryIdInt) { bool is_wrapping = (op_id == IrBinOpAddWrap); if (is_wrapping) { return LLVMBuildAdd(g->builder, op1_value, op2_value, ""); } else if (want_debug_safety) { - return gen_overflow_op(g, op1->value.type, AddSubMulAdd, op1_value, op2_value); - } else if (op1->value.type->data.integral.is_signed) { + return gen_overflow_op(g, canon_type, AddSubMulAdd, op1_value, op2_value); + } else if (canon_type->data.integral.is_signed) { return LLVMBuildNSWAdd(g->builder, op1_value, op2_value, ""); } else { return LLVMBuildNUWAdd(g->builder, op1_value, op2_value, ""); @@ -886,36 +887,36 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, case IrBinOpBitShiftLeft: case IrBinOpBitShiftLeftWrap: { - assert(op1->value.type->id == TypeTableEntryIdInt); + assert(canon_type->id == TypeTableEntryIdInt); bool is_wrapping = (op_id == IrBinOpBitShiftLeftWrap); if (is_wrapping) { return LLVMBuildShl(g->builder, op1_value, op2_value, ""); } else if (want_debug_safety) { - return gen_overflow_shl_op(g, op1->value.type, op1_value, op2_value); - } else if (op1->value.type->data.integral.is_signed) { + return gen_overflow_shl_op(g, canon_type, op1_value, op2_value); + } else if (canon_type->data.integral.is_signed) { return ZigLLVMBuildNSWShl(g->builder, op1_value, op2_value, ""); } else { return ZigLLVMBuildNUWShl(g->builder, op1_value, op2_value, ""); } } case IrBinOpBitShiftRight: - assert(op1->value.type->id == TypeTableEntryIdInt); - if (op1->value.type->data.integral.is_signed) { + assert(canon_type->id == TypeTableEntryIdInt); + if (canon_type->data.integral.is_signed) { return LLVMBuildAShr(g->builder, op1_value, op2_value, ""); } else { return LLVMBuildLShr(g->builder, op1_value, op2_value, ""); } case IrBinOpSub: case IrBinOpSubWrap: - if (op1->value.type->id == TypeTableEntryIdFloat) { + if (canon_type->id == TypeTableEntryIdFloat) { return LLVMBuildFSub(g->builder, op1_value, op2_value, ""); - } else if (op1->value.type->id == TypeTableEntryIdInt) { + } else if (canon_type->id == TypeTableEntryIdInt) { bool is_wrapping = (op_id == IrBinOpSubWrap); if (is_wrapping) { return LLVMBuildSub(g->builder, op1_value, op2_value, ""); } else if (want_debug_safety) { - return gen_overflow_op(g, op1->value.type, AddSubMulSub, op1_value, op2_value); - } else if (op1->value.type->data.integral.is_signed) { + return gen_overflow_op(g, canon_type, AddSubMulSub, op1_value, op2_value); + } else if (canon_type->data.integral.is_signed) { return LLVMBuildNSWSub(g->builder, op1_value, op2_value, ""); } else { return LLVMBuildNUWSub(g->builder, op1_value, op2_value, ""); @@ -925,15 +926,15 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, } case IrBinOpMult: case IrBinOpMultWrap: - if (op1->value.type->id == TypeTableEntryIdFloat) { + if (canon_type->id == TypeTableEntryIdFloat) { return LLVMBuildFMul(g->builder, op1_value, op2_value, ""); - } else if (op1->value.type->id == TypeTableEntryIdInt) { + } else if (canon_type->id == TypeTableEntryIdInt) { bool is_wrapping = (op_id == IrBinOpMultWrap); if (is_wrapping) { return LLVMBuildMul(g->builder, op1_value, op2_value, ""); } else if (want_debug_safety) { - return gen_overflow_op(g, op1->value.type, AddSubMulMul, op1_value, op2_value); - } else if (op1->value.type->data.integral.is_signed) { + return gen_overflow_op(g, canon_type, AddSubMulMul, op1_value, op2_value); + } else if (canon_type->data.integral.is_signed) { return LLVMBuildNSWMul(g->builder, op1_value, op2_value, ""); } else { return LLVMBuildNUWMul(g->builder, op1_value, op2_value, ""); @@ -942,13 +943,13 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, zig_unreachable(); } case IrBinOpDiv: - return gen_div(g, want_debug_safety, op1_value, op2_value, op1->value.type, false); + return gen_div(g, want_debug_safety, op1_value, op2_value, canon_type, false); case IrBinOpMod: - if (op1->value.type->id == TypeTableEntryIdFloat) { + if (canon_type->id == TypeTableEntryIdFloat) { return LLVMBuildFRem(g->builder, op1_value, op2_value, ""); } else { - assert(op1->value.type->id == TypeTableEntryIdInt); - if (op1->value.type->data.integral.is_signed) { + assert(canon_type->id == TypeTableEntryIdInt); + if (canon_type->data.integral.is_signed) { return LLVMBuildSRem(g->builder, op1_value, op2_value, ""); } else { return LLVMBuildURem(g->builder, op1_value, op2_value, ""); diff --git a/src/ir.cpp b/src/ir.cpp index 573e4cefad..e6c29bf8df 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -7302,8 +7302,8 @@ static int ir_eval_bignum(ConstExprValue *op1_val, ConstExprValue *op2_val, return 0; } -static int ir_eval_math_op(ConstExprValue *op1_val, TypeTableEntry *op1_type, - IrBinOp op_id, ConstExprValue *op2_val, TypeTableEntry *op2_type, ConstExprValue *out_val) +static int ir_eval_math_op(TypeTableEntry *canon_type, ConstExprValue *op1_val, + IrBinOp op_id, ConstExprValue *op2_val, ConstExprValue *out_val) { switch (op_id) { case IrBinOpInvalid: @@ -7319,33 +7319,33 @@ static int ir_eval_math_op(ConstExprValue *op1_val, TypeTableEntry *op1_type, case IrBinOpArrayMult: zig_unreachable(); case IrBinOpBinOr: - return ir_eval_bignum(op1_val, op2_val, out_val, bignum_or, op1_type, false); + return ir_eval_bignum(op1_val, op2_val, out_val, bignum_or, canon_type, false); case IrBinOpBinXor: - return ir_eval_bignum(op1_val, op2_val, out_val, bignum_xor, op1_type, false); + return ir_eval_bignum(op1_val, op2_val, out_val, bignum_xor, canon_type, false); case IrBinOpBinAnd: - return ir_eval_bignum(op1_val, op2_val, out_val, bignum_and, op1_type, false); + return ir_eval_bignum(op1_val, op2_val, out_val, bignum_and, canon_type, false); case IrBinOpBitShiftLeft: - return ir_eval_bignum(op1_val, op2_val, out_val, bignum_shl, op1_type, false); + return ir_eval_bignum(op1_val, op2_val, out_val, bignum_shl, canon_type, false); case IrBinOpBitShiftLeftWrap: - return ir_eval_bignum(op1_val, op2_val, out_val, bignum_shl, op1_type, true); + return ir_eval_bignum(op1_val, op2_val, out_val, bignum_shl, canon_type, true); case IrBinOpBitShiftRight: - return ir_eval_bignum(op1_val, op2_val, out_val, bignum_shr, op1_type, false); + return ir_eval_bignum(op1_val, op2_val, out_val, bignum_shr, canon_type, false); case IrBinOpAdd: - return ir_eval_bignum(op1_val, op2_val, out_val, bignum_add, op1_type, false); + return ir_eval_bignum(op1_val, op2_val, out_val, bignum_add, canon_type, false); case IrBinOpAddWrap: - return ir_eval_bignum(op1_val, op2_val, out_val, bignum_add, op1_type, true); + return ir_eval_bignum(op1_val, op2_val, out_val, bignum_add, canon_type, true); case IrBinOpSub: - return ir_eval_bignum(op1_val, op2_val, out_val, bignum_sub, op1_type, false); + return ir_eval_bignum(op1_val, op2_val, out_val, bignum_sub, canon_type, false); case IrBinOpSubWrap: - return ir_eval_bignum(op1_val, op2_val, out_val, bignum_sub, op1_type, true); + return ir_eval_bignum(op1_val, op2_val, out_val, bignum_sub, canon_type, true); case IrBinOpMult: - return ir_eval_bignum(op1_val, op2_val, out_val, bignum_mul, op1_type, false); + return ir_eval_bignum(op1_val, op2_val, out_val, bignum_mul, canon_type, false); case IrBinOpMultWrap: - return ir_eval_bignum(op1_val, op2_val, out_val, bignum_mul, op1_type, true); + return ir_eval_bignum(op1_val, op2_val, out_val, bignum_mul, canon_type, true); case IrBinOpDiv: - return ir_eval_bignum(op1_val, op2_val, out_val, bignum_div, op1_type, false); + return ir_eval_bignum(op1_val, op2_val, out_val, bignum_div, canon_type, false); case IrBinOpMod: - return ir_eval_bignum(op1_val, op2_val, out_val, bignum_mod, op1_type, false); + return ir_eval_bignum(op1_val, op2_val, out_val, bignum_mod, canon_type, false); } zig_unreachable(); } @@ -7357,14 +7357,15 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, bin_op_instruction->base.source_node, instructions, 2); if (resolved_type->id == TypeTableEntryIdInvalid) return resolved_type; + TypeTableEntry *canon_resolved_type = get_underlying_type(resolved_type); IrBinOp op_id = bin_op_instruction->op_id; - if (resolved_type->id == TypeTableEntryIdInt || - resolved_type->id == TypeTableEntryIdNumLitInt) + if (canon_resolved_type->id == TypeTableEntryIdInt || + canon_resolved_type->id == TypeTableEntryIdNumLitInt) { // int - } else if ((resolved_type->id == TypeTableEntryIdFloat || - resolved_type->id == TypeTableEntryIdNumLitFloat) && + } else if ((canon_resolved_type->id == TypeTableEntryIdFloat || + canon_resolved_type->id == TypeTableEntryIdNumLitFloat) && (op_id == IrBinOpAdd || op_id == IrBinOpSub || op_id == IrBinOpMult || @@ -7398,7 +7399,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp bin_op_instruction->base.other = &bin_op_instruction->base; int err; - if ((err = ir_eval_math_op(op1_val, resolved_type, op_id, op2_val, resolved_type, out_val))) { + if ((err = ir_eval_math_op(canon_resolved_type, op1_val, op_id, op2_val, out_val))) { if (err == ErrorDivByZero) { ir_add_error_node(ira, bin_op_instruction->base.source_node, buf_sprintf("division by zero is undefined")); |
