aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-10-29 17:48:34 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-10-29 17:49:02 -0700
commitd6067db06267e37dec65202667741bc1b63fe980 (patch)
treea693698a60b30a7d0ca2764056858c8b74066cd7 /src
parent5ff01bd820ea08005a422f046ad5bbad663b0dab (diff)
downloadzig-d6067db06267e37dec65202667741bc1b63fe980.tar.gz
zig-d6067db06267e37dec65202667741bc1b63fe980.zip
stage2: implement `@popCount` for non-vectors
Diffstat (limited to 'src')
-rw-r--r--src/Air.zig5
-rw-r--r--src/Liveness.zig1
-rw-r--r--src/Sema.zig26
-rw-r--r--src/arch/aarch64/CodeGen.zig7
-rw-r--r--src/codegen.zig9
-rw-r--r--src/codegen/c.zig1
-rw-r--r--src/codegen/llvm.zig35
-rw-r--r--src/print_air.zig1
-rw-r--r--src/value.zig216
9 files changed, 142 insertions, 159 deletions
diff --git a/src/Air.zig b/src/Air.zig
index d39a78f1ad..9902ccbf56 100644
--- a/src/Air.zig
+++ b/src/Air.zig
@@ -202,6 +202,10 @@ pub const Inst = struct {
/// Result type will always be an unsigned integer big enough to fit the answer.
/// Uses the `ty_op` field.
ctz,
+ /// Count number of 1 bits in an integer according to its representation in twos complement.
+ /// Result type will always be an unsigned integer big enough to fit the answer.
+ /// Uses the `ty_op` field.
+ popcount,
/// `<`. Result type is always bool.
/// Uses the `bin_op` field.
@@ -744,6 +748,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
.get_union_tag,
.clz,
.ctz,
+ .popcount,
=> return air.getRefType(datas[inst].ty_op.ty),
.loop,
diff --git a/src/Liveness.zig b/src/Liveness.zig
index 499500fddb..1210390971 100644
--- a/src/Liveness.zig
+++ b/src/Liveness.zig
@@ -313,6 +313,7 @@ fn analyzeInst(
.get_union_tag,
.clz,
.ctz,
+ .popcount,
=> {
const o = inst_datas[inst].ty_op;
return trackOperands(a, new_set, inst, main_tomb, .{ o.operand, .none, .none });
diff --git a/src/Sema.zig b/src/Sema.zig
index 83b81ef174..0788997576 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -9904,8 +9904,30 @@ fn zirCtz(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
fn zirPopCount(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
- const src = inst_data.src();
- return sema.fail(block, src, "TODO: Sema.zirPopCount", .{});
+ const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
+ const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
+ const operand = sema.resolveInst(inst_data.operand);
+ const operand_ty = sema.typeOf(operand);
+ // TODO implement support for vectors
+ if (operand_ty.zigTypeTag() != .Int) {
+ return sema.fail(block, ty_src, "expected integer type, found '{}'", .{
+ operand_ty,
+ });
+ }
+ const target = sema.mod.getTarget();
+ const bits = operand_ty.intInfo(target).bits;
+ if (bits == 0) return Air.Inst.Ref.zero;
+
+ const result_ty = try Type.smallestUnsignedInt(sema.arena, bits);
+
+ const runtime_src = if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| {
+ if (val.isUndef()) return sema.addConstUndef(result_ty);
+ const result_val = try val.popCount(operand_ty, target, sema.arena);
+ return sema.addConstant(result_ty, result_val);
+ } else operand_src;
+
+ try sema.requireRuntimeBlock(block, runtime_src);
+ return block.addTyOp(.popcount, result_ty, operand);
}
fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig
index 2c6feec70c..9331fb249e 100644
--- a/src/arch/aarch64/CodeGen.zig
+++ b/src/arch/aarch64/CodeGen.zig
@@ -481,6 +481,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.get_union_tag => try self.airGetUnionTag(inst),
.clz => try self.airClz(inst),
.ctz => try self.airCtz(inst),
+ .popcount => try self.airPopcount(inst),
.atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
.atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),
@@ -1138,6 +1139,12 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
}
+fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {
+ const ty_op = self.air.instructions.items(.data)[inst].ty_op;
+ const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airPopcount for {}", .{self.target.cpu.arch});
+ return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
+}
+
fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool {
if (!self.liveness.operandDies(inst, op_index))
return false;
diff --git a/src/codegen.zig b/src/codegen.zig
index 374a9353e1..82aa9430e8 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -836,6 +836,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
.get_union_tag => try self.airGetUnionTag(inst),
.clz => try self.airClz(inst),
.ctz => try self.airCtz(inst),
+ .popcount => try self.airPopcount(inst),
.atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
.atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),
@@ -1610,6 +1611,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
}
+ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {
+ const ty_op = self.air.instructions.items(.data)[inst].ty_op;
+ const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) {
+ else => return self.fail("TODO implement airPopcount for {}", .{self.target.cpu.arch}),
+ };
+ return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
+ }
+
fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool {
if (!self.liveness.operandDies(inst, op_index))
return false;
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 3ab74a85be..8e046264aa 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -1107,6 +1107,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
.get_union_tag => try airGetUnionTag(f, inst),
.clz => try airBuiltinCall(f, inst, "clz"),
.ctz => try airBuiltinCall(f, inst, "ctz"),
+ .popcount => try airBuiltinCall(f, inst, "popcount"),
.int_to_float,
.float_to_int,
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 572e23ff28..683ee9b95b 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -1777,6 +1777,7 @@ pub const FuncGen = struct {
.get_union_tag => try self.airGetUnionTag(inst),
.clz => try self.airClzCtz(inst, "ctlz"),
.ctz => try self.airClzCtz(inst, "cttz"),
+ .popcount => try self.airPopCount(inst, "ctpop"),
.atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
.atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),
@@ -3679,6 +3680,40 @@ pub const FuncGen = struct {
}
}
+ fn airPopCount(self: *FuncGen, inst: Air.Inst.Index, prefix: [*:0]const u8) !?*const llvm.Value {
+ if (self.liveness.isUnused(inst)) return null;
+
+ const ty_op = self.air.instructions.items(.data)[inst].ty_op;
+ const operand_ty = self.air.typeOf(ty_op.operand);
+ const operand = try self.resolveInst(ty_op.operand);
+ const target = self.dg.module.getTarget();
+ const bits = operand_ty.intInfo(target).bits;
+
+ var fn_name_buf: [100]u8 = undefined;
+ const llvm_fn_name = std.fmt.bufPrintZ(&fn_name_buf, "llvm.{s}.i{d}", .{
+ prefix, bits,
+ }) catch unreachable;
+ const fn_val = self.dg.object.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: {
+ const operand_llvm_ty = try self.dg.llvmType(operand_ty);
+ const param_types = [_]*const llvm.Type{operand_llvm_ty};
+ const fn_type = llvm.functionType(operand_llvm_ty, &param_types, param_types.len, .False);
+ break :blk self.dg.object.llvm_module.addFunction(llvm_fn_name, fn_type);
+ };
+
+ const params = [_]*const llvm.Value{operand};
+ const wrong_size_result = self.builder.buildCall(fn_val, &params, params.len, .C, .Auto, "");
+ const result_ty = self.air.typeOfIndex(inst);
+ const result_llvm_ty = try self.dg.llvmType(result_ty);
+ const result_bits = result_ty.intInfo(target).bits;
+ if (bits > result_bits) {
+ return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, "");
+ } else if (bits < result_bits) {
+ return self.builder.buildZExt(wrong_size_result, result_llvm_ty, "");
+ } else {
+ return wrong_size_result;
+ }
+ }
+
fn callFloor(self: *FuncGen, arg: *const llvm.Value, ty: Type) !*const llvm.Value {
return self.callFloatUnary(arg, ty, "floor");
}
diff --git a/src/print_air.zig b/src/print_air.zig
index 17efa8297d..56a73b3fcf 100644
--- a/src/print_air.zig
+++ b/src/print_air.zig
@@ -196,6 +196,7 @@ const Writer = struct {
.get_union_tag,
.clz,
.ctz,
+ .popcount,
=> try w.writeTyOp(s, inst),
.block,
diff --git a/src/value.zig b/src/value.zig
index 382aeeedf7..2e3f1bc4b8 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -1062,14 +1062,7 @@ pub const Value = extern union {
const limbs_buffer = try arena.alloc(std.math.big.Limb, 2);
var bigint = BigIntMutable.init(limbs_buffer, 0);
bigint.readTwosComplement(buffer, int_info.bits, endian, int_info.signedness);
- // TODO if it fits in 64 bits then use one of those tags
-
- const result_limbs = bigint.limbs[0..bigint.len];
- if (bigint.positive) {
- return Value.Tag.int_big_positive.create(arena, result_limbs);
- } else {
- return Value.Tag.int_big_negative.create(arena, result_limbs);
- }
+ return fromBigInt(arena, bigint.toConst());
},
.Float => switch (ty.floatBits(target)) {
16 => return Value.Tag.float_16.create(arena, floatReadFromMemory(f16, target, buffer)),
@@ -1200,16 +1193,34 @@ pub const Value = extern union {
if (x == 0) return 0;
return @intCast(usize, std.math.log2(x) + 1);
},
- .int_i64 => {
- @panic("TODO implement i64 intBitCountTwosComp");
- },
.int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().bitCountTwosComp(),
.int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().bitCountTwosComp(),
- else => unreachable,
+ else => {
+ var buffer: BigIntSpace = undefined;
+ return self.toBigInt(&buffer).bitCountTwosComp();
+ },
}
}
+ pub fn popCount(val: Value, ty: Type, target: Target, arena: *Allocator) !Value {
+ assert(!val.isUndef());
+
+ const info = ty.intInfo(target);
+
+ var buffer: Value.BigIntSpace = undefined;
+ const operand_bigint = val.toBigInt(&buffer);
+
+ 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.popCount(operand_bigint, info.bits);
+
+ return fromBigInt(arena, result_bigint.toConst());
+ }
+
/// Asserts the value is an integer, and the destination type is ComptimeInt or Int.
pub fn intFitsInType(self: Value, ty: Type, target: Target) bool {
switch (self.tag()) {
@@ -1246,7 +1257,8 @@ pub const Value = extern union {
const info = ty.intInfo(target);
if (info.signedness == .unsigned and x < 0)
return false;
- @panic("TODO implement i64 intFitsInType");
+ var buffer: BigIntSpace = undefined;
+ return self.toBigInt(&buffer).fitsInTwosComp(info.signedness, info.bits);
},
.ComptimeInt => return true,
else => unreachable,
@@ -1943,12 +1955,22 @@ pub const Value = extern union {
);
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
result_bigint.addWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);
- const result_limbs = result_bigint.limbs[0..result_bigint.len];
+ return fromBigInt(arena, result_bigint.toConst());
+ }
- if (result_bigint.positive) {
- return Value.Tag.int_big_positive.create(arena, result_limbs);
+ fn fromBigInt(arena: *Allocator, big_int: BigIntConst) !Value {
+ if (big_int.positive) {
+ if (big_int.to(u64)) |x| {
+ return Value.Tag.int_u64.create(arena, x);
+ } else |_| {
+ return Value.Tag.int_big_positive.create(arena, big_int.limbs);
+ }
} else {
- return Value.Tag.int_big_negative.create(arena, result_limbs);
+ if (big_int.to(i64)) |x| {
+ return Value.Tag.int_i64.create(arena, x);
+ } else |_| {
+ return Value.Tag.int_big_negative.create(arena, big_int.limbs);
+ }
}
}
@@ -1975,13 +1997,7 @@ pub const Value = extern union {
);
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
result_bigint.addSat(lhs_bigint, rhs_bigint, 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);
- }
+ return fromBigInt(arena, result_bigint.toConst());
}
/// Supports both floats and ints; handles undefined.
@@ -2010,13 +2026,7 @@ pub const Value = extern union {
);
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
result_bigint.subWrap(lhs_bigint, rhs_bigint, 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);
- }
+ return fromBigInt(arena, result_bigint.toConst());
}
/// Supports integers only; asserts neither operand is undefined.
@@ -2042,13 +2052,7 @@ pub const Value = extern union {
);
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
result_bigint.subSat(lhs_bigint, rhs_bigint, 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);
- }
+ return fromBigInt(arena, result_bigint.toConst());
}
/// Supports both floats and ints; handles undefined.
@@ -2082,13 +2086,7 @@ pub const Value = extern union {
);
defer arena.free(limbs_buffer);
result_bigint.mulWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits, limbs_buffer, arena);
- 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);
- }
+ return fromBigInt(arena, result_bigint.toConst());
}
/// Supports integers only; asserts neither operand is undefined.
@@ -2124,13 +2122,7 @@ pub const Value = extern union {
defer arena.free(limbs_buffer);
result_bigint.mul(lhs_bigint, rhs_bigint, limbs_buffer, arena);
result_bigint.saturate(result_bigint.toConst(), 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);
- }
+ return fromBigInt(arena, result_bigint.toConst());
}
/// Supports both floats and ints; handles undefined.
@@ -2174,13 +2166,7 @@ pub const Value = extern union {
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
result_bigint.bitNotWrap(val_bigint, 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);
- }
+ return fromBigInt(arena, result_bigint.toConst());
}
/// operands must be integers; handles undefined.
@@ -2200,13 +2186,7 @@ pub const Value = extern union {
);
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
result_bigint.bitAnd(lhs_bigint, rhs_bigint);
- 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);
- }
+ return fromBigInt(arena, result_bigint.toConst());
}
/// operands must be integers; handles undefined.
@@ -2239,13 +2219,7 @@ pub const Value = extern union {
);
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
result_bigint.bitOr(lhs_bigint, rhs_bigint);
- 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);
- }
+ return fromBigInt(arena, result_bigint.toConst());
}
/// operands must be integers; handles undefined.
@@ -2265,13 +2239,7 @@ pub const Value = extern union {
);
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
result_bigint.bitXor(lhs_bigint, rhs_bigint);
- 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);
- }
+ return fromBigInt(arena, result_bigint.toConst());
}
pub fn intAdd(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
@@ -2287,13 +2255,7 @@ pub const Value = extern union {
);
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
result_bigint.add(lhs_bigint, rhs_bigint);
- const result_limbs = result_bigint.limbs[0..result_bigint.len];
-
- if (result_bigint.positive) {
- return Value.Tag.int_big_positive.create(allocator, result_limbs);
- } else {
- return Value.Tag.int_big_negative.create(allocator, result_limbs);
- }
+ return fromBigInt(allocator, result_bigint.toConst());
}
pub fn intSub(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
@@ -2309,13 +2271,7 @@ pub const Value = extern union {
);
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
result_bigint.sub(lhs_bigint, rhs_bigint);
- const result_limbs = result_bigint.limbs[0..result_bigint.len];
-
- if (result_bigint.positive) {
- return Value.Tag.int_big_positive.create(allocator, result_limbs);
- } else {
- return Value.Tag.int_big_negative.create(allocator, result_limbs);
- }
+ return fromBigInt(allocator, result_bigint.toConst());
}
pub fn intDiv(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
@@ -2340,13 +2296,7 @@ pub const Value = extern union {
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);
- const result_limbs = result_q.limbs[0..result_q.len];
-
- if (result_q.positive) {
- return Value.Tag.int_big_positive.create(allocator, result_limbs);
- } else {
- return Value.Tag.int_big_negative.create(allocator, result_limbs);
- }
+ return fromBigInt(allocator, result_q.toConst());
}
pub fn intDivFloor(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
@@ -2371,13 +2321,7 @@ pub const Value = extern union {
var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
result_q.divFloor(&result_r, lhs_bigint, rhs_bigint, limbs_buffer);
- const result_limbs = result_q.limbs[0..result_q.len];
-
- if (result_q.positive) {
- return Value.Tag.int_big_positive.create(allocator, result_limbs);
- } else {
- return Value.Tag.int_big_negative.create(allocator, result_limbs);
- }
+ return fromBigInt(allocator, result_q.toConst());
}
pub fn intRem(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
@@ -2404,13 +2348,7 @@ pub const Value = extern union {
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);
- const result_limbs = result_r.limbs[0..result_r.len];
-
- if (result_r.positive) {
- return Value.Tag.int_big_positive.create(allocator, result_limbs);
- } else {
- return Value.Tag.int_big_negative.create(allocator, result_limbs);
- }
+ return fromBigInt(allocator, result_r.toConst());
}
pub fn intMod(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
@@ -2435,13 +2373,7 @@ pub const Value = extern union {
var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
result_q.divFloor(&result_r, lhs_bigint, rhs_bigint, limbs_buffer);
- const result_limbs = result_r.limbs[0..result_r.len];
-
- if (result_r.positive) {
- return Value.Tag.int_big_positive.create(allocator, result_limbs);
- } else {
- return Value.Tag.int_big_negative.create(allocator, result_limbs);
- }
+ return fromBigInt(allocator, result_r.toConst());
}
/// Returns true if the value is a floating point type and is NaN. Returns false otherwise.
@@ -2487,13 +2419,7 @@ pub const Value = extern union {
);
defer allocator.free(limbs_buffer);
result_bigint.mul(lhs_bigint, rhs_bigint, limbs_buffer, allocator);
- const result_limbs = result_bigint.limbs[0..result_bigint.len];
-
- if (result_bigint.positive) {
- return Value.Tag.int_big_positive.create(allocator, result_limbs);
- } else {
- return Value.Tag.int_big_negative.create(allocator, result_limbs);
- }
+ return fromBigInt(allocator, result_bigint.toConst());
}
pub fn intTrunc(val: Value, allocator: *Allocator, signedness: std.builtin.Signedness, bits: u16) !Value {
@@ -2507,13 +2433,7 @@ pub const Value = extern union {
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
result_bigint.truncate(val_bigint, signedness, bits);
- const result_limbs = result_bigint.limbs[0..result_bigint.len];
-
- if (result_bigint.positive) {
- return Value.Tag.int_big_positive.create(allocator, result_limbs);
- } else {
- return Value.Tag.int_big_negative.create(allocator, result_limbs);
- }
+ return fromBigInt(allocator, result_bigint.toConst());
}
pub fn shl(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
@@ -2532,13 +2452,7 @@ pub const Value = extern union {
.len = undefined,
};
result_bigint.shiftLeft(lhs_bigint, shift);
- const result_limbs = result_bigint.limbs[0..result_bigint.len];
-
- if (result_bigint.positive) {
- return Value.Tag.int_big_positive.create(allocator, result_limbs);
- } else {
- return Value.Tag.int_big_negative.create(allocator, result_limbs);
- }
+ return fromBigInt(allocator, result_bigint.toConst());
}
pub fn shlSat(
@@ -2565,13 +2479,7 @@ pub const Value = extern union {
.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);
- }
+ return fromBigInt(arena, result_bigint.toConst());
}
pub fn shr(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
@@ -2590,13 +2498,7 @@ pub const Value = extern union {
.len = undefined,
};
result_bigint.shiftRight(lhs_bigint, shift);
- const result_limbs = result_bigint.limbs[0..result_bigint.len];
-
- if (result_bigint.positive) {
- return Value.Tag.int_big_positive.create(allocator, result_limbs);
- } else {
- return Value.Tag.int_big_negative.create(allocator, result_limbs);
- }
+ return fromBigInt(allocator, result_bigint.toConst());
}
pub fn floatAdd(