aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIsaac Freund <mail@isaacfreund.com>2022-08-10 13:21:47 +0200
committerIsaac Freund <mail@isaacfreund.com>2022-08-10 14:48:27 +0200
commitbb1c3e8b7e2be201221e14719d2d39e6298cc66c (patch)
treed4d5800c280beea171fdb4028553a7107aa21891 /src
parent49a270b2038709a6a0c1f4de604696278769257b (diff)
downloadzig-bb1c3e8b7e2be201221e14719d2d39e6298cc66c.tar.gz
zig-bb1c3e8b7e2be201221e14719d2d39e6298cc66c.zip
stage2: Handle lazy values for the % operator
Diffstat (limited to 'src')
-rw-r--r--src/Sema.zig59
-rw-r--r--src/value.zig38
2 files changed, 57 insertions, 40 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index acdce0e9b0..6d95b46c7c 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -78,6 +78,7 @@ post_hoc_blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *LabeledBlock) = .{},
err: ?*Module.ErrorMsg = null,
const std = @import("std");
+const math = std.math;
const mem = std.mem;
const Allocator = std.mem.Allocator;
const assert = std.debug.assert;
@@ -11824,7 +11825,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
return sema.failWithDivideByZero(block, rhs_src);
}
if (maybe_lhs_val) |lhs_val| {
- const rem_result = try lhs_val.intRem(rhs_val, resolved_type, sema.arena, target);
+ const rem_result = try sema.intRem(block, resolved_type, lhs_val, lhs_src, rhs_val, rhs_src);
// If this answer could possibly be different by doing `intMod`,
// we must emit a compile error. Otherwise, it's OK.
if ((try rhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) != (try lhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) and
@@ -11886,6 +11887,60 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
return block.addBinOp(air_tag, casted_lhs, casted_rhs);
}
+fn intRem(
+ sema: *Sema,
+ block: *Block,
+ ty: Type,
+ lhs: Value,
+ lhs_src: LazySrcLoc,
+ rhs: Value,
+ rhs_src: LazySrcLoc,
+) CompileError!Value {
+ if (ty.zigTypeTag() == .Vector) {
+ const result_data = try sema.arena.alloc(Value, ty.vectorLen());
+ for (result_data) |*scalar, i| {
+ scalar.* = try sema.intRemScalar(block, lhs.indexVectorlike(i), lhs_src, rhs.indexVectorlike(i), rhs_src);
+ }
+ return Value.Tag.aggregate.create(sema.arena, result_data);
+ }
+ return sema.intRemScalar(block, lhs, lhs_src, rhs, rhs_src);
+}
+
+fn intRemScalar(
+ sema: *Sema,
+ block: *Block,
+ lhs: Value,
+ lhs_src: LazySrcLoc,
+ rhs: Value,
+ rhs_src: LazySrcLoc,
+) CompileError!Value {
+ const target = sema.mod.getTarget();
+ // TODO is this a performance issue? maybe we should try the operation without
+ // resorting to BigInt first.
+ var lhs_space: Value.BigIntSpace = undefined;
+ var rhs_space: Value.BigIntSpace = undefined;
+ const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, target, sema.kit(block, lhs_src));
+ const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, target, sema.kit(block, rhs_src));
+ const limbs_q = try sema.arena.alloc(
+ math.big.Limb,
+ lhs_bigint.limbs.len,
+ );
+ const limbs_r = try sema.arena.alloc(
+ math.big.Limb,
+ // TODO: consider reworking Sema to re-use Values rather than
+ // always producing new Value objects.
+ rhs_bigint.limbs.len,
+ );
+ const limbs_buffer = try sema.arena.alloc(
+ math.big.Limb,
+ math.big.int.calcDivLimbsBufferLen(lhs_bigint.limbs.len, rhs_bigint.limbs.len),
+ );
+ var result_q = math.big.int.Mutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
+ var result_r = math.big.int.Mutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
+ result_q.divTrunc(&result_r, lhs_bigint, rhs_bigint, limbs_buffer);
+ return Value.fromBigInt(sema.arena, result_r.toConst());
+}
+
fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
@@ -12050,7 +12105,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
if (maybe_lhs_val) |lhs_val| {
return sema.addConstant(
resolved_type,
- try lhs_val.intRem(rhs_val, resolved_type, sema.arena, target),
+ try sema.intRem(block, resolved_type, lhs_val, lhs_src, rhs_val, rhs_src),
);
}
break :rs lhs_src;
diff --git a/src/value.zig b/src/value.zig
index 3994040ba6..f156651eaa 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -3472,44 +3472,6 @@ pub const Value = extern union {
return fromBigInt(allocator, result_q.toConst());
}
- pub fn intRem(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, target: Target) !Value {
- if (ty.zigTypeTag() == .Vector) {
- const result_data = try allocator.alloc(Value, ty.vectorLen());
- for (result_data) |*scalar, i| {
- scalar.* = try intRemScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), allocator, target);
- }
- return Value.Tag.aggregate.create(allocator, result_data);
- }
- return intRemScalar(lhs, rhs, allocator, target);
- }
-
- pub fn intRemScalar(lhs: Value, rhs: Value, allocator: Allocator, target: Target) !Value {
- // TODO is this a performance issue? maybe we should try the operation without
- // resorting to BigInt first.
- var lhs_space: Value.BigIntSpace = undefined;
- var rhs_space: Value.BigIntSpace = undefined;
- const lhs_bigint = lhs.toBigInt(&lhs_space, target);
- const rhs_bigint = rhs.toBigInt(&rhs_space, target);
- const limbs_q = try allocator.alloc(
- std.math.big.Limb,
- lhs_bigint.limbs.len,
- );
- const limbs_r = try allocator.alloc(
- std.math.big.Limb,
- // TODO: consider reworking Sema to re-use Values rather than
- // always producing new Value objects.
- rhs_bigint.limbs.len,
- );
- const limbs_buffer = try allocator.alloc(
- std.math.big.Limb,
- std.math.big.int.calcDivLimbsBufferLen(lhs_bigint.limbs.len, rhs_bigint.limbs.len),
- );
- var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
- var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
- result_q.divTrunc(&result_r, lhs_bigint, rhs_bigint, limbs_buffer);
- return fromBigInt(allocator, result_r.toConst());
- }
-
pub fn intMod(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, target: Target) !Value {
if (ty.zigTypeTag() == .Vector) {
const result_data = try allocator.alloc(Value, ty.vectorLen());