mirror of
https://github.com/ziglang/zig.git
synced 2026-02-15 13:58:27 +00:00
typedefs work for binary math operations
This commit is contained in:
parent
aae168550f
commit
e00eec1c29
@ -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, "");
|
||||
|
||||
43
src/ir.cpp
43
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"));
|
||||
|
||||
12
test/cases/typedef.zig
Normal file
12
test/cases/typedef.zig
Normal file
@ -0,0 +1,12 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
type int = u8;
|
||||
|
||||
fn add(a: int, b: int) -> int {
|
||||
a + b
|
||||
}
|
||||
fn typedef() {
|
||||
@setFnTest(this);
|
||||
|
||||
assert(add(12, 34) == 46);
|
||||
}
|
||||
@ -29,6 +29,7 @@ const test_switch_prong_err_enum = @import("cases/switch_prong_err_enum.zig");
|
||||
const test_switch_prong_implicit_cast = @import("cases/switch_prong_implicit_cast.zig");
|
||||
const test_this = @import("cases/this.zig");
|
||||
const test_try = @import("cases/try.zig");
|
||||
const test_typedef = @import("cases/typedef.zig");
|
||||
const test_undefined = @import("cases/undefined.zig");
|
||||
const test_var_args = @import("cases/var_args.zig");
|
||||
const test_while = @import("cases/while.zig");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user