aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2017-02-03 12:09:13 -0500
committerAndrew Kelley <superjoe30@gmail.com>2017-02-03 12:09:13 -0500
commite00eec1c299ccc721f4272a506321939be7094f1 (patch)
treea1069f5a6fa80841338bcd5d4a77a95b2ecfa03b /src
parentaae168550fa3d8b21478deb7198513dad8cc0b37 (diff)
downloadzig-e00eec1c299ccc721f4272a506321939be7094f1.tar.gz
zig-e00eec1c299ccc721f4272a506321939be7094f1.zip
typedefs work for binary math operations
Diffstat (limited to 'src')
-rw-r--r--src/codegen.cpp59
-rw-r--r--src/ir.cpp43
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"));