authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-03 12:09:13-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-03 12:09:13-05:00
loge00eec1c299ccc721f4272a506321939be7094f1
treea1069f5a6fa80841338bcd5d4a77a95b2ecfa03b
parentaae168550fa3d8b21478deb7198513dad8cc0b37

typedefs work for binary math operations


4 files changed, 65 insertions(+), 50 deletions(-)

src/codegen.cpp+30-29
......@@ -816,6 +816,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
816816 IrInstruction *op2 = bin_op_instruction->op2;
817817
818818 assert(op1->value.type == op2->value.type);
819 TypeTableEntry *canon_type = get_underlying_type(op1->value.type);
819820
820821 bool want_debug_safety = bin_op_instruction->safety_check_on &&
821822 ir_want_debug_safety(g, &bin_op_instruction->base);
......@@ -837,22 +838,22 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
837838 case IrBinOpCmpGreaterThan:
838839 case IrBinOpCmpLessOrEq:
839840 case IrBinOpCmpGreaterOrEq:
840 if (op1->value.type->id == TypeTableEntryIdFloat) {
841 if (canon_type->id == TypeTableEntryIdFloat) {
841842 LLVMRealPredicate pred = cmp_op_to_real_predicate(op_id);
842843 return LLVMBuildFCmp(g->builder, pred, op1_value, op2_value, "");
843 } else if (op1->value.type->id == TypeTableEntryIdInt) {
844 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, op1->value.type->data.integral.is_signed);
844 } else if (canon_type->id == TypeTableEntryIdInt) {
845 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, canon_type->data.integral.is_signed);
845846 return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
846 } else if (op1->value.type->id == TypeTableEntryIdEnum) {
847 if (op1->value.type->data.enumeration.gen_field_count == 0) {
847 } else if (canon_type->id == TypeTableEntryIdEnum) {
848 if (canon_type->data.enumeration.gen_field_count == 0) {
848849 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);
849850 return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
850851 } else {
851852 zig_unreachable();
852853 }
853 } else if (op1->value.type->id == TypeTableEntryIdPureError ||
854 op1->value.type->id == TypeTableEntryIdPointer ||
855 op1->value.type->id == TypeTableEntryIdBool)
854 } else if (canon_type->id == TypeTableEntryIdPureError ||
855 canon_type->id == TypeTableEntryIdPointer ||
856 canon_type->id == TypeTableEntryIdBool)
856857 {
857858 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);
858859 return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
......@@ -861,15 +862,15 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
861862 }
862863 case IrBinOpAdd:
863864 case IrBinOpAddWrap:
864 if (op1->value.type->id == TypeTableEntryIdFloat) {
865 if (canon_type->id == TypeTableEntryIdFloat) {
865866 return LLVMBuildFAdd(g->builder, op1_value, op2_value, "");
866 } else if (op1->value.type->id == TypeTableEntryIdInt) {
867 } else if (canon_type->id == TypeTableEntryIdInt) {
867868 bool is_wrapping = (op_id == IrBinOpAddWrap);
868869 if (is_wrapping) {
869870 return LLVMBuildAdd(g->builder, op1_value, op2_value, "");
870871 } else if (want_debug_safety) {
871 return gen_overflow_op(g, op1->value.type, AddSubMulAdd, op1_value, op2_value);
872 } else if (op1->value.type->data.integral.is_signed) {
872 return gen_overflow_op(g, canon_type, AddSubMulAdd, op1_value, op2_value);
873 } else if (canon_type->data.integral.is_signed) {
873874 return LLVMBuildNSWAdd(g->builder, op1_value, op2_value, "");
874875 } else {
875876 return LLVMBuildNUWAdd(g->builder, op1_value, op2_value, "");
......@@ -886,36 +887,36 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
886887 case IrBinOpBitShiftLeft:
887888 case IrBinOpBitShiftLeftWrap:
888889 {
889 assert(op1->value.type->id == TypeTableEntryIdInt);
890 assert(canon_type->id == TypeTableEntryIdInt);
890891 bool is_wrapping = (op_id == IrBinOpBitShiftLeftWrap);
891892 if (is_wrapping) {
892893 return LLVMBuildShl(g->builder, op1_value, op2_value, "");
893894 } else if (want_debug_safety) {
894 return gen_overflow_shl_op(g, op1->value.type, op1_value, op2_value);
895 } else if (op1->value.type->data.integral.is_signed) {
895 return gen_overflow_shl_op(g, canon_type, op1_value, op2_value);
896 } else if (canon_type->data.integral.is_signed) {
896897 return ZigLLVMBuildNSWShl(g->builder, op1_value, op2_value, "");
897898 } else {
898899 return ZigLLVMBuildNUWShl(g->builder, op1_value, op2_value, "");
899900 }
900901 }
901902 case IrBinOpBitShiftRight:
902 assert(op1->value.type->id == TypeTableEntryIdInt);
903 if (op1->value.type->data.integral.is_signed) {
903 assert(canon_type->id == TypeTableEntryIdInt);
904 if (canon_type->data.integral.is_signed) {
904905 return LLVMBuildAShr(g->builder, op1_value, op2_value, "");
905906 } else {
906907 return LLVMBuildLShr(g->builder, op1_value, op2_value, "");
907908 }
908909 case IrBinOpSub:
909910 case IrBinOpSubWrap:
910 if (op1->value.type->id == TypeTableEntryIdFloat) {
911 if (canon_type->id == TypeTableEntryIdFloat) {
911912 return LLVMBuildFSub(g->builder, op1_value, op2_value, "");
912 } else if (op1->value.type->id == TypeTableEntryIdInt) {
913 } else if (canon_type->id == TypeTableEntryIdInt) {
913914 bool is_wrapping = (op_id == IrBinOpSubWrap);
914915 if (is_wrapping) {
915916 return LLVMBuildSub(g->builder, op1_value, op2_value, "");
916917 } else if (want_debug_safety) {
917 return gen_overflow_op(g, op1->value.type, AddSubMulSub, op1_value, op2_value);
918 } else if (op1->value.type->data.integral.is_signed) {
918 return gen_overflow_op(g, canon_type, AddSubMulSub, op1_value, op2_value);
919 } else if (canon_type->data.integral.is_signed) {
919920 return LLVMBuildNSWSub(g->builder, op1_value, op2_value, "");
920921 } else {
921922 return LLVMBuildNUWSub(g->builder, op1_value, op2_value, "");
......@@ -925,15 +926,15 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
925926 }
926927 case IrBinOpMult:
927928 case IrBinOpMultWrap:
928 if (op1->value.type->id == TypeTableEntryIdFloat) {
929 if (canon_type->id == TypeTableEntryIdFloat) {
929930 return LLVMBuildFMul(g->builder, op1_value, op2_value, "");
930 } else if (op1->value.type->id == TypeTableEntryIdInt) {
931 } else if (canon_type->id == TypeTableEntryIdInt) {
931932 bool is_wrapping = (op_id == IrBinOpMultWrap);
932933 if (is_wrapping) {
933934 return LLVMBuildMul(g->builder, op1_value, op2_value, "");
934935 } else if (want_debug_safety) {
935 return gen_overflow_op(g, op1->value.type, AddSubMulMul, op1_value, op2_value);
936 } else if (op1->value.type->data.integral.is_signed) {
936 return gen_overflow_op(g, canon_type, AddSubMulMul, op1_value, op2_value);
937 } else if (canon_type->data.integral.is_signed) {
937938 return LLVMBuildNSWMul(g->builder, op1_value, op2_value, "");
938939 } else {
939940 return LLVMBuildNUWMul(g->builder, op1_value, op2_value, "");
......@@ -942,13 +943,13 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
942943 zig_unreachable();
943944 }
944945 case IrBinOpDiv:
945 return gen_div(g, want_debug_safety, op1_value, op2_value, op1->value.type, false);
946 return gen_div(g, want_debug_safety, op1_value, op2_value, canon_type, false);
946947 case IrBinOpMod:
947 if (op1->value.type->id == TypeTableEntryIdFloat) {
948 if (canon_type->id == TypeTableEntryIdFloat) {
948949 return LLVMBuildFRem(g->builder, op1_value, op2_value, "");
949950 } else {
950 assert(op1->value.type->id == TypeTableEntryIdInt);
951 if (op1->value.type->data.integral.is_signed) {
951 assert(canon_type->id == TypeTableEntryIdInt);
952 if (canon_type->data.integral.is_signed) {
952953 return LLVMBuildSRem(g->builder, op1_value, op2_value, "");
953954 } else {
954955 return LLVMBuildURem(g->builder, op1_value, op2_value, "");
src/ir.cpp+22-21
......@@ -7302,8 +7302,8 @@ static int ir_eval_bignum(ConstExprValue *op1_val, ConstExprValue *op2_val,
73027302 return 0;
73037303}
73047304
7305static int ir_eval_math_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
7306 IrBinOp op_id, ConstExprValue *op2_val, TypeTableEntry *op2_type, ConstExprValue *out_val)
7305static int ir_eval_math_op(TypeTableEntry *canon_type, ConstExprValue *op1_val,
7306 IrBinOp op_id, ConstExprValue *op2_val, ConstExprValue *out_val)
73077307{
73087308 switch (op_id) {
73097309 case IrBinOpInvalid:
......@@ -7319,33 +7319,33 @@ static int ir_eval_math_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
73197319 case IrBinOpArrayMult:
73207320 zig_unreachable();
73217321 case IrBinOpBinOr:
7322 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_or, op1_type, false);
7322 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_or, canon_type, false);
73237323 case IrBinOpBinXor:
7324 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_xor, op1_type, false);
7324 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_xor, canon_type, false);
73257325 case IrBinOpBinAnd:
7326 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_and, op1_type, false);
7326 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_and, canon_type, false);
73277327 case IrBinOpBitShiftLeft:
7328 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_shl, op1_type, false);
7328 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_shl, canon_type, false);
73297329 case IrBinOpBitShiftLeftWrap:
7330 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_shl, op1_type, true);
7330 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_shl, canon_type, true);
73317331 case IrBinOpBitShiftRight:
7332 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_shr, op1_type, false);
7332 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_shr, canon_type, false);
73337333 case IrBinOpAdd:
7334 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_add, op1_type, false);
7334 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_add, canon_type, false);
73357335 case IrBinOpAddWrap:
7336 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_add, op1_type, true);
7336 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_add, canon_type, true);
73377337 case IrBinOpSub:
7338 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_sub, op1_type, false);
7338 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_sub, canon_type, false);
73397339 case IrBinOpSubWrap:
7340 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_sub, op1_type, true);
7340 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_sub, canon_type, true);
73417341 case IrBinOpMult:
7342 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_mul, op1_type, false);
7342 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_mul, canon_type, false);
73437343 case IrBinOpMultWrap:
7344 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_mul, op1_type, true);
7344 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_mul, canon_type, true);
73457345 case IrBinOpDiv:
7346 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_div, op1_type, false);
7346 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_div, canon_type, false);
73477347 case IrBinOpMod:
7348 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_mod, op1_type, false);
7348 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_mod, canon_type, false);
73497349 }
73507350 zig_unreachable();
73517351}
......@@ -7357,14 +7357,15 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
73577357 TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, bin_op_instruction->base.source_node, instructions, 2);
73587358 if (resolved_type->id == TypeTableEntryIdInvalid)
73597359 return resolved_type;
7360 TypeTableEntry *canon_resolved_type = get_underlying_type(resolved_type);
73607361 IrBinOp op_id = bin_op_instruction->op_id;
73617362
7362 if (resolved_type->id == TypeTableEntryIdInt ||
7363 resolved_type->id == TypeTableEntryIdNumLitInt)
7363 if (canon_resolved_type->id == TypeTableEntryIdInt ||
7364 canon_resolved_type->id == TypeTableEntryIdNumLitInt)
73647365 {
73657366 // int
7366 } else if ((resolved_type->id == TypeTableEntryIdFloat ||
7367 resolved_type->id == TypeTableEntryIdNumLitFloat) &&
7367 } else if ((canon_resolved_type->id == TypeTableEntryIdFloat ||
7368 canon_resolved_type->id == TypeTableEntryIdNumLitFloat) &&
73687369 (op_id == IrBinOpAdd ||
73697370 op_id == IrBinOpSub ||
73707371 op_id == IrBinOpMult ||
......@@ -7398,7 +7399,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
73987399 bin_op_instruction->base.other = &bin_op_instruction->base;
73997400
74007401 int err;
7401 if ((err = ir_eval_math_op(op1_val, resolved_type, op_id, op2_val, resolved_type, out_val))) {
7402 if ((err = ir_eval_math_op(canon_resolved_type, op1_val, op_id, op2_val, out_val))) {
74027403 if (err == ErrorDivByZero) {
74037404 ir_add_error_node(ira, bin_op_instruction->base.source_node,
74047405 buf_sprintf("division by zero is undefined"));
test/cases/typedef.zig created+12
......@@ -0,0 +1,12 @@
1const assert = @import("std").debug.assert;
2
3type int = u8;
4
5fn add(a: int, b: int) -> int {
6 a + b
7}
8fn typedef() {
9 @setFnTest(this);
10
11 assert(add(12, 34) == 46);
12}
test/self_hosted.zig+1
......@@ -29,6 +29,7 @@ const test_switch_prong_err_enum = @import("cases/switch_prong_err_enum.zig");
2929const test_switch_prong_implicit_cast = @import("cases/switch_prong_implicit_cast.zig");
3030const test_this = @import("cases/this.zig");
3131const test_try = @import("cases/try.zig");
32const test_typedef = @import("cases/typedef.zig");
3233const test_undefined = @import("cases/undefined.zig");
3334const test_var_args = @import("cases/var_args.zig");
3435const test_while = @import("cases/while.zig");