ladybird/Ports/zig/patches/0010-llvm-Implement-bigint-to-LLVM-int-for-32-bit-compile.patch
sin-ack cda5a530e6 Ports: Add zig port :^)
:yakkie:

The build process for the Zig compiler is more involved than most of
the other ports, because the Zig compiler is mostly self-hosting. In
order to build it, the zig-bootstrap build system is used, which does
the following:

1) Build LLVM for the host OS;
2) Build Zig for the host OS with the SerenityOS target enabled;
3) Build zlib, zstd and LLVM for SerenityOS using `zig cc` as the C/C++
   compiler;
4) Build Zig for SerenityOS using the host Zig.

A few hacks are required in order to tell `zig cc` and zig about what
Serenity's libc looks like in the build process, but other than that
it's fairly straightforward. All of the patches that are included with
this commit are Zig-upstream ready once the LLVM patches are upstreamed.
2022-12-11 19:55:37 -07:00

95 lines
5.0 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: sin-ack <sin-ack@users.noreply.github.com>
Date: Sat, 1 Oct 2022 20:05:58 +0000
Subject: [PATCH] llvm: Implement bigint-to-LLVM int for 32-bit compiler builds
The conversion to DoubleLimb is necessary due to LLVM only accepting
64-bit limbs for big integers. Since we need some space to store it, we
also have to allocate. This is an unfortunate penalty that 32-bit
compiler builds have to take.
---
zig/lib/std/math/big/int.zig | 21 +++++++++++++++++++++
zig/src/codegen/llvm.zig | 28 ++++++++++++++++++++++++++--
2 files changed, 47 insertions(+), 2 deletions(-)
diff --git a/zig/lib/std/math/big/int.zig b/zig/lib/std/math/big/int.zig
index 534e8a570d675aba91f8623a08859aa2d7d533fd..30db3f36df0311faef1eaba3d69a9785d9e50296 100644
--- a/zig/lib/std/math/big/int.zig
+++ b/zig/lib/std/math/big/int.zig
@@ -1899,6 +1899,27 @@ pub const Const = struct {
};
}
+ /// Convert each limb to a DoubleLimb and write it to `double_limbs`.
+ /// Return the slice of limbs that was used.
+ /// Asserts `double_limbs` is big enough to store the value.
+ pub fn toDoubleLimb(self: Const, double_limbs: []DoubleLimb) ![]DoubleLimb {
+ // TODO: Add tests (and check if this works on big-endian)!
+ assert(double_limbs.len >= (try std.math.divCeil(usize, self.limbs.len, 2)));
+
+ var i: usize = 0;
+ var double_limb_i: usize = 0;
+ while (i < self.limbs.len) : ({
+ i += 2;
+ double_limb_i += 1;
+ }) {
+ const most_significant: Limb = if (i + 1 == self.limbs.len) 0 else self.limbs[i + 1];
+ const least_significant = self.limbs[i];
+ double_limbs[double_limb_i] = @intCast(DoubleLimb, least_significant) | (@intCast(DoubleLimb, most_significant) << @bitSizeOf(Limb));
+ }
+
+ return double_limbs[0..double_limb_i];
+ }
+
pub fn dump(self: Const) void {
for (self.limbs[0..self.limbs.len]) |limb| {
std.debug.print("{x} ", .{limb});
diff --git a/zig/src/codegen/llvm.zig b/zig/src/codegen/llvm.zig
index 4115a4870ea3f8731b929afd65f5111bee1f2983..e3ae805402e063341519ebeb7ee62c8717e45697 100644
--- a/zig/src/codegen/llvm.zig
+++ b/zig/src/codegen/llvm.zig
@@ -3241,8 +3241,20 @@ pub const DeclGen = struct {
@intCast(c_uint, bigint.limbs.len),
bigint.limbs.ptr,
);
+ } else {
+ // Because LLVM only accepts 64-bit limbs for constIntOfArbitraryPrecision, we must convert to double-limb here (and allocate to do so).
+ // You (yes, you!) can fix this by making LLVM accept 32-bit limbs for creating an integer of arbitrary precision.
+ const double_limb_count = math.divCeil(usize, bigint.limbs.len, 2) catch return Error.CodegenFail;
+ var double_limb_space = try dg.gpa.alloc(math.big.DoubleLimb, double_limb_count);
+ defer dg.gpa.free(double_limb_space);
+
+ _ = bigint.toDoubleLimb(double_limb_space) catch return Error.CodegenFail;
+
+ break :v llvm_type.constIntOfArbitraryPrecision(
+ @intCast(c_uint, double_limb_count),
+ double_limb_space.ptr,
+ );
}
- @panic("TODO implement bigint to llvm int for 32-bit compiler builds");
};
if (!bigint.positive) {
return llvm.constNeg(unsigned_val);
@@ -3269,8 +3281,20 @@ pub const DeclGen = struct {
@intCast(c_uint, bigint.limbs.len),
bigint.limbs.ptr,
);
+ } else {
+ // Because LLVM only accepts 64-bit limbs for constIntOfArbitraryPrecision, we must convert to double-limb here (and allocate to do so).
+ // You (yes, you!) can fix this by making LLVM accept 32-bit limbs for creating an integer of arbitrary precision.
+ const double_limb_count = math.divCeil(usize, bigint.limbs.len, 2) catch return Error.CodegenFail;
+ var double_limb_space = try dg.gpa.alloc(math.big.DoubleLimb, double_limb_count);
+ defer dg.gpa.free(double_limb_space);
+
+ _ = bigint.toDoubleLimb(double_limb_space) catch return Error.CodegenFail;
+
+ break :v llvm_type.constIntOfArbitraryPrecision(
+ @intCast(c_uint, double_limb_count),
+ double_limb_space.ptr,
+ );
}
- @panic("TODO implement bigint to llvm int for 32-bit compiler builds");
};
if (!bigint.positive) {
return llvm.constNeg(unsigned_val);