authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-03-10 23:04:49+01:00
committergravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-03-10 23:04:49+01:00
log4ab13a359dfb14c93869e7f88320ec2aa438da9c
tree6c84c14ea57024aa5a6a8d29306c800b3bed76fb
parent300fceac6eca99fd858678b03a47357e72856e10

ir: Fix shift code for u0 operands


2 files changed, 50 insertions(+), 15 deletions(-)

src/ir.cpp+31-15
...@@ -16635,34 +16635,47 @@ static IrInstGen *ir_analyze_bit_shift(IrAnalyze *ira, IrInstSrcBinOp *bin_op_in...@@ -16635,34 +16635,47 @@ static IrInstGen *ir_analyze_bit_shift(IrAnalyze *ira, IrInstSrcBinOp *bin_op_in
16635 IrInstGen *casted_op2;16635 IrInstGen *casted_op2;
16636 IrBinOp op_id = bin_op_instruction->op_id;16636 IrBinOp op_id = bin_op_instruction->op_id;
16637 if (op1->value->type->id == ZigTypeIdComptimeInt) {16637 if (op1->value->type->id == ZigTypeIdComptimeInt) {
16638 // comptime_int has no finite bit width
16638 casted_op2 = op2;16639 casted_op2 = op2;
1663916640
16640 if (op_id == IrBinOpBitShiftLeftLossy) {16641 if (op_id == IrBinOpBitShiftLeftLossy) {
16641 op_id = IrBinOpBitShiftLeftExact;16642 op_id = IrBinOpBitShiftLeftExact;
16642 }16643 }
1664316644
16644 if (casted_op2->value->data.x_bigint.is_negative) {16645 if (!instr_is_comptime(op2)) {
16646 ir_add_error(ira, &bin_op_instruction->base.base,
16647 buf_sprintf("LHS of shift must be an integer type, or RHS must be compile-time known"));
16648 return ira->codegen->invalid_inst_gen;
16649 }
16650
16651 ZigValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad);
16652 if (op2_val == nullptr)
16653 return ira->codegen->invalid_inst_gen;
16654
16655 if (op2_val->data.x_bigint.is_negative) {
16645 Buf *val_buf = buf_alloc();16656 Buf *val_buf = buf_alloc();
16646 bigint_append_buf(val_buf, &casted_op2->value->data.x_bigint, 10);16657 bigint_append_buf(val_buf, &op2_val->data.x_bigint, 10);
16647 ir_add_error(ira, &casted_op2->base, buf_sprintf("shift by negative value %s", buf_ptr(val_buf)));16658 ir_add_error(ira, &casted_op2->base,
16659 buf_sprintf("shift by negative value %s", buf_ptr(val_buf)));
16648 return ira->codegen->invalid_inst_gen;16660 return ira->codegen->invalid_inst_gen;
16649 }16661 }
16650 } else {16662 } else {
16651 assert(op1->value->type->data.integral.bit_count > 0);16663 const unsigned bit_count = op1->value->type->data.integral.bit_count;
16652 ZigType *shift_amt_type = get_smallest_unsigned_int_type(ira->codegen,16664 ZigType *shift_amt_type = get_smallest_unsigned_int_type(ira->codegen,
16653 op1->value->type->data.integral.bit_count - 1);16665 bit_count > 0 ? bit_count - 1 : 0);
1665416666
16655 casted_op2 = ir_implicit_cast(ira, op2, shift_amt_type);16667 casted_op2 = ir_implicit_cast(ira, op2, shift_amt_type);
16656 if (type_is_invalid(casted_op2->value->type))16668 if (type_is_invalid(casted_op2->value->type))
16657 return ira->codegen->invalid_inst_gen;16669 return ira->codegen->invalid_inst_gen;
1665816670
16659 if (instr_is_comptime(casted_op2)) {16671 // This check is only valid iff op1 has at least one bit
16672 if (bit_count > 0 && instr_is_comptime(casted_op2)) {
16660 ZigValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad);16673 ZigValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad);
16661 if (op2_val == nullptr)16674 if (op2_val == nullptr)
16662 return ira->codegen->invalid_inst_gen;16675 return ira->codegen->invalid_inst_gen;
1666316676
16664 BigInt bit_count_value = {0};16677 BigInt bit_count_value = {0};
16665 bigint_init_unsigned(&bit_count_value, op1->value->type->data.integral.bit_count);16678 bigint_init_unsigned(&bit_count_value, bit_count);
1666616679
16667 if (bigint_cmp(&op2_val->data.x_bigint, &bit_count_value) != CmpLT) {16680 if (bigint_cmp(&op2_val->data.x_bigint, &bit_count_value) != CmpLT) {
16668 ErrorMsg* msg = ir_add_error(ira,16681 ErrorMsg* msg = ir_add_error(ira,
...@@ -16670,14 +16683,23 @@ static IrInstGen *ir_analyze_bit_shift(IrAnalyze *ira, IrInstSrcBinOp *bin_op_in...@@ -16670,14 +16683,23 @@ static IrInstGen *ir_analyze_bit_shift(IrAnalyze *ira, IrInstSrcBinOp *bin_op_in
16670 buf_sprintf("RHS of shift is too large for LHS type"));16683 buf_sprintf("RHS of shift is too large for LHS type"));
16671 add_error_note(ira->codegen, msg, op1->base.source_node,16684 add_error_note(ira->codegen, msg, op1->base.source_node,
16672 buf_sprintf("type %s has only %u bits",16685 buf_sprintf("type %s has only %u bits",
16673 buf_ptr(&op1->value->type->name),16686 buf_ptr(&op1->value->type->name), bit_count));
16674 op1->value->type->data.integral.bit_count));
1667516687
16676 return ira->codegen->invalid_inst_gen;16688 return ira->codegen->invalid_inst_gen;
16677 }16689 }
16678 }16690 }
16679 }16691 }
1668016692
16693 // Fast path for zero RHS
16694 if (instr_is_comptime(casted_op2)) {
16695 ZigValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad);
16696 if (op2_val == nullptr)
16697 return ira->codegen->invalid_inst_gen;
16698
16699 if (bigint_cmp_zero(&op2_val->data.x_bigint) == CmpEQ)
16700 return ir_analyze_cast(ira, &bin_op_instruction->base.base, op1->value->type, op1);
16701 }
16702
16681 if (instr_is_comptime(op1) && instr_is_comptime(casted_op2)) {16703 if (instr_is_comptime(op1) && instr_is_comptime(casted_op2)) {
16682 ZigValue *op1_val = ir_resolve_const(ira, op1, UndefBad);16704 ZigValue *op1_val = ir_resolve_const(ira, op1, UndefBad);
16683 if (op1_val == nullptr)16705 if (op1_val == nullptr)
...@@ -16688,12 +16710,6 @@ static IrInstGen *ir_analyze_bit_shift(IrAnalyze *ira, IrInstSrcBinOp *bin_op_in...@@ -16688,12 +16710,6 @@ static IrInstGen *ir_analyze_bit_shift(IrAnalyze *ira, IrInstSrcBinOp *bin_op_in
16688 return ira->codegen->invalid_inst_gen;16710 return ira->codegen->invalid_inst_gen;
1668916711
16690 return ir_analyze_math_op(ira, &bin_op_instruction->base.base, op1->value->type, op1_val, op_id, op2_val);16712 return ir_analyze_math_op(ira, &bin_op_instruction->base.base, op1->value->type, op1_val, op_id, op2_val);
16691 } else if (op1->value->type->id == ZigTypeIdComptimeInt) {
16692 ir_add_error(ira, &bin_op_instruction->base.base,
16693 buf_sprintf("LHS of shift must be an integer type, or RHS must be compile-time known"));
16694 return ira->codegen->invalid_inst_gen;
16695 } else if (instr_is_comptime(casted_op2) && bigint_cmp_zero(&casted_op2->value->data.x_bigint) == CmpEQ) {
16696 return ir_build_cast(ira, &bin_op_instruction->base.base, op1->value->type, op1, CastOpNoop);
16697 }16713 }
1669816714
16699 return ir_build_bin_op_gen(ira, &bin_op_instruction->base.base, op1->value->type,16715 return ir_build_bin_op_gen(ira, &bin_op_instruction->base.base, op1->value->type,
test/stage1/behavior/math.zig+19
...@@ -453,6 +453,25 @@ fn testShrExact(x: u8) void {...@@ -453,6 +453,25 @@ fn testShrExact(x: u8) void {
453 expect(shifted == 0b00101101);453 expect(shifted == 0b00101101);
454}454}
455455
456test "shift left/right on u0 operand" {
457 const S = struct {
458 fn doTheTest() void {
459 var x: u0 = 0;
460 var y: u0 = 0;
461 expectEqual(@as(u0, 0), x << 0);
462 expectEqual(@as(u0, 0), x >> 0);
463 expectEqual(@as(u0, 0), x << y);
464 expectEqual(@as(u0, 0), x >> y);
465 expectEqual(@as(u0, 0), @shlExact(x, 0));
466 expectEqual(@as(u0, 0), @shrExact(x, 0));
467 expectEqual(@as(u0, 0), @shlExact(x, y));
468 expectEqual(@as(u0, 0), @shrExact(x, y));
469 }
470 };
471 S.doTheTest();
472 comptime S.doTheTest();
473}
474
456test "comptime_int addition" {475test "comptime_int addition" {
457 comptime {476 comptime {
458 expect(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950);477 expect(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950);