diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Sema.zig | 10 | ||||
| -rw-r--r-- | src/value.zig | 33 |
2 files changed, 38 insertions, 5 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 2ab2b76c18..4c3f20f28b 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -6502,13 +6502,13 @@ fn zirShl( if (rhs_val.compareWithZero(.eq)) { return sema.addConstant(lhs_ty, lhs_val); } - const val = try lhs_val.shl(rhs_val, sema.arena); - switch (air_tag) { + const val = switch (air_tag) { .shl_exact => return sema.fail(block, lhs_src, "TODO implement Sema for comptime shl_exact", .{}), - .shl_sat => return sema.fail(block, lhs_src, "TODO implement Sema for comptime shl_sat", .{}), - .shl => {}, + .shl_sat => try lhs_val.shlSat(rhs_val, lhs_ty, sema.arena, sema.mod.getTarget()), + .shl => try lhs_val.shl(rhs_val, sema.arena), else => unreachable, - } + }; + return sema.addConstant(lhs_ty, val); } else rs: { if (maybe_rhs_val) |rhs_val| { diff --git a/src/value.zig b/src/value.zig index 264525a204..127c6c27b4 100644 --- a/src/value.zig +++ b/src/value.zig @@ -2404,6 +2404,39 @@ pub const Value = extern union { } } + pub fn shlSat( + lhs: Value, + rhs: Value, + ty: Type, + arena: *Allocator, + target: Target, + ) !Value { + // TODO is this a performance issue? maybe we should try the operation without + // resorting to BigInt first. + const info = ty.intInfo(target); + + var lhs_space: Value.BigIntSpace = undefined; + const lhs_bigint = lhs.toBigInt(&lhs_space); + const shift = rhs.toUnsignedInt(); + const limbs = try arena.alloc( + std.math.big.Limb, + std.math.big.int.calcTwosCompLimbCount(info.bits), + ); + var result_bigint = BigIntMutable{ + .limbs = limbs, + .positive = undefined, + .len = undefined, + }; + result_bigint.shiftLeftSat(lhs_bigint, shift, info.signedness, info.bits); + const result_limbs = result_bigint.limbs[0..result_bigint.len]; + + if (result_bigint.positive) { + return Value.Tag.int_big_positive.create(arena, result_limbs); + } else { + return Value.Tag.int_big_negative.create(arena, result_limbs); + } + } + pub fn shr(lhs: Value, rhs: Value, allocator: *Allocator) !Value { // TODO is this a performance issue? maybe we should try the operation without // resorting to BigInt first. |
