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
1663516635 IrInstGen *casted_op2;
1663616636 IrBinOp op_id = bin_op_instruction->op_id;
1663716637 if (op1->value->type->id == ZigTypeIdComptimeInt) {
16638 // comptime_int has no finite bit width
1663816639 casted_op2 = op2;
1663916640
1664016641 if (op_id == IrBinOpBitShiftLeftLossy) {
1664116642 op_id = IrBinOpBitShiftLeftExact;
1664216643 }
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) {
1664516656 Buf *val_buf = buf_alloc();
16646 bigint_append_buf(val_buf, &casted_op2->value->data.x_bigint, 10);
16647 ir_add_error(ira, &casted_op2->base, buf_sprintf("shift by negative value %s", buf_ptr(val_buf)));
16657 bigint_append_buf(val_buf, &op2_val->data.x_bigint, 10);
16658 ir_add_error(ira, &casted_op2->base,
16659 buf_sprintf("shift by negative value %s", buf_ptr(val_buf)));
1664816660 return ira->codegen->invalid_inst_gen;
1664916661 }
1665016662 } else {
16651 assert(op1->value->type->data.integral.bit_count > 0);
16663 const unsigned bit_count = op1->value->type->data.integral.bit_count;
1665216664 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
1665516667 casted_op2 = ir_implicit_cast(ira, op2, shift_amt_type);
1665616668 if (type_is_invalid(casted_op2->value->type))
1665716669 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)) {
1666016673 ZigValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad);
1666116674 if (op2_val == nullptr)
1666216675 return ira->codegen->invalid_inst_gen;
1666316676
1666416677 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
1666716680 if (bigint_cmp(&op2_val->data.x_bigint, &bit_count_value) != CmpLT) {
1666816681 ErrorMsg* msg = ir_add_error(ira,
......@@ -16670,14 +16683,23 @@ static IrInstGen *ir_analyze_bit_shift(IrAnalyze *ira, IrInstSrcBinOp *bin_op_in
1667016683 buf_sprintf("RHS of shift is too large for LHS type"));
1667116684 add_error_note(ira->codegen, msg, op1->base.source_node,
1667216685 buf_sprintf("type %s has only %u bits",
16673 buf_ptr(&op1->value->type->name),
16674 op1->value->type->data.integral.bit_count));
16686 buf_ptr(&op1->value->type->name), bit_count));
1667516687
1667616688 return ira->codegen->invalid_inst_gen;
1667716689 }
1667816690 }
1667916691 }
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
1668116703 if (instr_is_comptime(op1) && instr_is_comptime(casted_op2)) {
1668216704 ZigValue *op1_val = ir_resolve_const(ira, op1, UndefBad);
1668316705 if (op1_val == nullptr)
......@@ -16688,12 +16710,6 @@ static IrInstGen *ir_analyze_bit_shift(IrAnalyze *ira, IrInstSrcBinOp *bin_op_in
1668816710 return ira->codegen->invalid_inst_gen;
1668916711
1669016712 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);
1669716713 }
1669816714
1669916715 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 {
453453 expect(shifted == 0b00101101);
454454}
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
456475test "comptime_int addition" {
457476 comptime {
458477 expect(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950);