@@ -78,6 +78,7 @@ post_hoc_blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *LabeledBlock) = .{},
78
78
err: ?*Module.ErrorMsg = null,
79
79
80
80
const std = @import("std");
81
+ const math = std.math;
81
82
const mem = std.mem;
82
83
const Allocator = std.mem.Allocator;
83
84
const assert = std.debug.assert;
@@ -11824,7 +11825,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
11824
11825
return sema.failWithDivideByZero(block, rhs_src);
11825
11826
}
11826
11827
if (maybe_lhs_val) |lhs_val| {
11827
- const rem_result = try lhs_val .intRem(rhs_val , resolved_type, sema.arena, target );
11828
+ const rem_result = try sema .intRem(block , resolved_type, lhs_val, lhs_src, rhs_val, rhs_src );
11828
11829
// If this answer could possibly be different by doing `intMod`,
11829
11830
// we must emit a compile error. Otherwise, it's OK.
11830
11831
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.
11886
11887
return block.addBinOp(air_tag, casted_lhs, casted_rhs);
11887
11888
}
11888
11889
11890
+ fn intRem(
11891
+ sema: *Sema,
11892
+ block: *Block,
11893
+ ty: Type,
11894
+ lhs: Value,
11895
+ lhs_src: LazySrcLoc,
11896
+ rhs: Value,
11897
+ rhs_src: LazySrcLoc,
11898
+ ) CompileError!Value {
11899
+ if (ty.zigTypeTag() == .Vector) {
11900
+ const result_data = try sema.arena.alloc(Value, ty.vectorLen());
11901
+ for (result_data) |*scalar, i| {
11902
+ scalar.* = try sema.intRemScalar(block, lhs.indexVectorlike(i), lhs_src, rhs.indexVectorlike(i), rhs_src);
11903
+ }
11904
+ return Value.Tag.aggregate.create(sema.arena, result_data);
11905
+ }
11906
+ return sema.intRemScalar(block, lhs, lhs_src, rhs, rhs_src);
11907
+ }
11908
+
11909
+ fn intRemScalar(
11910
+ sema: *Sema,
11911
+ block: *Block,
11912
+ lhs: Value,
11913
+ lhs_src: LazySrcLoc,
11914
+ rhs: Value,
11915
+ rhs_src: LazySrcLoc,
11916
+ ) CompileError!Value {
11917
+ const target = sema.mod.getTarget();
11918
+ // TODO is this a performance issue? maybe we should try the operation without
11919
+ // resorting to BigInt first.
11920
+ var lhs_space: Value.BigIntSpace = undefined;
11921
+ var rhs_space: Value.BigIntSpace = undefined;
11922
+ const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, target, sema.kit(block, lhs_src));
11923
+ const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, target, sema.kit(block, rhs_src));
11924
+ const limbs_q = try sema.arena.alloc(
11925
+ math.big.Limb,
11926
+ lhs_bigint.limbs.len,
11927
+ );
11928
+ const limbs_r = try sema.arena.alloc(
11929
+ math.big.Limb,
11930
+ // TODO: consider reworking Sema to re-use Values rather than
11931
+ // always producing new Value objects.
11932
+ rhs_bigint.limbs.len,
11933
+ );
11934
+ const limbs_buffer = try sema.arena.alloc(
11935
+ math.big.Limb,
11936
+ math.big.int.calcDivLimbsBufferLen(lhs_bigint.limbs.len, rhs_bigint.limbs.len),
11937
+ );
11938
+ var result_q = math.big.int.Mutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
11939
+ var result_r = math.big.int.Mutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
11940
+ result_q.divTrunc(&result_r, lhs_bigint, rhs_bigint, limbs_buffer);
11941
+ return Value.fromBigInt(sema.arena, result_r.toConst());
11942
+ }
11943
+
11889
11944
fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
11890
11945
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
11891
11946
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
12050
12105
if (maybe_lhs_val) |lhs_val| {
12051
12106
return sema.addConstant(
12052
12107
resolved_type,
12053
- try lhs_val .intRem(rhs_val , resolved_type, sema.arena, target ),
12108
+ try sema .intRem(block , resolved_type, lhs_val, lhs_src, rhs_val, rhs_src ),
12054
12109
);
12055
12110
}
12056
12111
break :rs lhs_src;
0 commit comments