1
0
mirror of https://github.com/SerenityOS/serenity synced 2024-07-09 13:50:46 +00:00

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.
This commit is contained in:
sin-ack 2022-09-25 11:19:54 +00:00 committed by Andrew Kaster
parent 27da878bb7
commit cda5a530e6
19 changed files with 1533 additions and 0 deletions

View File

@ -273,6 +273,7 @@ This list is also available at [ports.serenityos.net](https://ports.serenityos.n
| [`xash3d-fwgs`](xash3d-fwgs/) | Xash3D FWGS game engine | 2022.07.14 | https://github.com/FWGS/xash3d-fwgs |
| [`xz`](xz/) | xz | 5.2.5 | https://tukaani.org/xz/ |
| [`yasm`](yasm/) | Yasm Modular Assembler | 1.3.0 | https://yasm.tortall.net/ |
| [`zig`](zig/) | Zig programming language | 0.11.0-dev.670+f7fea080b | https://ziglang.org/ |
| [`zlib`](zlib/) | zlib | 1.2.13 | https://www.zlib.net/ |
| [`zsh`](zsh/) | Z Shell (Zsh) | 5.8.1 | https://www.zsh.org |
| [`zstd`](zstd/) | Zstandard | 1.5.2 | https://facebook.github.io/zstd/ |

1
Ports/zig/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
!scripts/*

27
Ports/zig/package.sh Executable file
View File

@ -0,0 +1,27 @@
#!/usr/bin/env -S bash ../.port_include.sh
port='zig'
version='0.11.0-dev.670+f7fea080b'
files='https://github.com/ziglang/zig-bootstrap/archive/b9a466fd23d7777e1b3b87d49074ce66370fb7b3.tar.gz zig-bootstrap-b9a466f.tar.gz 84cf91d727c53ef49220ea6b2864dae3bd48e5e5a73be95bf3672c38a72b0946'
auth_type='sha256'
workdir='zig-bootstrap-b9a466fd23d7777e1b3b87d49074ce66370fb7b3'
post_fetch() {
run mkdir -p out
run cp -r "${PORT_META_DIR}/scripts" out/
}
build() {
host_env
cd "${workdir}"
./build "${SERENITY_ARCH}-serenity-none" "native"
}
install() {
zig_install_dir="${workdir}/out/zig-${SERENITY_ARCH}-serenity-none-native"
mkdir -p "${DESTDIR}/usr/local/bin/."
mkdir -p "${DESTDIR}/usr/local/lib/."
cp -rv "${zig_install_dir}/bin/"* "${DESTDIR}/usr/local/bin/"
cp -rv "${zig_install_dir}/lib/"* "${DESTDIR}/usr/local/lib/"
}

View File

@ -0,0 +1 @@
../../../Toolchain/Patches/llvm/0001-Support-Add-support-for-building-LLVM-on-SerenityOS.patch

View File

@ -0,0 +1 @@
../../../Toolchain/Patches/llvm/0002-Triple-Add-triple-for-SerenityOS.patch

View File

@ -0,0 +1 @@
../../../Toolchain/Patches/llvm/0003-Driver-Add-support-for-SerenityOS.patch

View File

@ -0,0 +1 @@
../../../Toolchain/Patches/llvm/0004-Driver-Default-to-ftls-model-initial-exec-on-Serenit.patch

View File

@ -0,0 +1,121 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: sin-ack <sin-ack@protonmail.com>
Date: Tue, 27 Sep 2022 00:08:46 +0000
Subject: [PATCH] Add support for SerenityOS
This commit teaches libc++ about what features are available in our
LibC, namely:
* We do not have locale support, so no-op shims should be used in place
of the C locale API.
* The number of errno constants defined by us is given by the value of
the `ELAST` macro.
* Multithreading is implemented though the pthread library.
* Use libc++'s builtin character type table instead of the one provided
by LibC as there's a lot of extra porting work to convince the rest of
locale.cpp to use our character type table properly.
This commit is an adaptation of the LLVM patch by Daniel Bertalan to fit
the layout of the zig-bootstrap project.
Co-Authored-By: Daniel Bertalan <dani@danielbertalan.dev>
---
zig/lib/libcxx/include/__config | 5 ++--
zig/lib/libcxx/include/__locale | 2 ++
.../include/__support/serenity/xlocale.h | 24 +++++++++++++++++++
zig/lib/libcxx/include/locale | 2 +-
zig/lib/libcxx/src/include/config_elast.h | 2 ++
5 files changed, 32 insertions(+), 3 deletions(-)
create mode 100644 zig/lib/libcxx/include/__support/serenity/xlocale.h
diff --git a/zig/lib/libcxx/include/__config b/zig/lib/libcxx/include/__config
index d9a47343dad1faf52826abbcd6da7578cec9932a..74a8970eddfaec23f421c3edbe974f77ad055e27 100644
--- a/zig/lib/libcxx/include/__config
+++ b/zig/lib/libcxx/include/__config
@@ -910,7 +910,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
defined(__sun__) || \
defined(__MVS__) || \
defined(_AIX) || \
- defined(__EMSCRIPTEN__)
+ defined(__EMSCRIPTEN__) || \
+ defined(__serenity__)
// clang-format on
# define _LIBCPP_HAS_THREAD_API_PTHREAD
# elif defined(__Fuchsia__)
@@ -988,7 +989,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
# endif
# if defined(__BIONIC__) || defined(__NuttX__) || defined(__Fuchsia__) || defined(__wasi__) || \
- defined(_LIBCPP_HAS_MUSL_LIBC) || defined(__OpenBSD__)
+ defined(_LIBCPP_HAS_MUSL_LIBC) || defined(__OpenBSD__) || defined(__serenity__)
# define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
# endif
diff --git a/zig/lib/libcxx/include/__locale b/zig/lib/libcxx/include/__locale
index 40f9a3ff57c22635254be654227333b2a10eca6a..1c499c078b44a49abead17ce566801b4c34733f3 100644
--- a/zig/lib/libcxx/include/__locale
+++ b/zig/lib/libcxx/include/__locale
@@ -42,6 +42,8 @@
# include <__support/musl/xlocale.h>
#elif defined(_LIBCPP_HAS_MUSL_LIBC)
# include <__support/musl/xlocale.h>
+#elif defined(__serenity__)
+# include <__support/serenity/xlocale.h>
#endif
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
diff --git a/zig/lib/libcxx/include/__support/serenity/xlocale.h b/zig/lib/libcxx/include/__support/serenity/xlocale.h
new file mode 100644
index 0000000000000000000000000000000000000000..0f939d2f6989e2ad617145308d079776fe87b6ce
--- /dev/null
+++ b/zig/lib/libcxx/include/__support/serenity/xlocale.h
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_SUPPORT_SERENITY_XLOCALE_H
+#define _LIBCPP_SUPPORT_SERENITY_XLOCALE_H
+
+#if defined(__serenity__)
+
+#include <cstdlib>
+#include <clocale>
+#include <cwctype>
+#include <ctype.h>
+#include <__support/xlocale/__nop_locale_mgmt.h>
+#include <__support/xlocale/__posix_l_fallback.h>
+#include <__support/xlocale/__strtonum_fallback.h>
+
+#endif // __serenity__
+
+#endif
diff --git a/zig/lib/libcxx/include/locale b/zig/lib/libcxx/include/locale
index b01c66d0430f66ee74118e73296780bb864e920b..da29b7d00c709788facb049f417b6d5ccb5b70e1 100644
--- a/zig/lib/libcxx/include/locale
+++ b/zig/lib/libcxx/include/locale
@@ -217,7 +217,7 @@ template <class charT> class messages_byname;
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
// Most unix variants have catopen. These are the specific ones that don't.
-# if !defined(__BIONIC__) && !defined(_NEWLIB_VERSION) && !defined(__EMSCRIPTEN__)
+# if !defined(__BIONIC__) && !defined(_NEWLIB_VERSION) && !defined(__EMSCRIPTEN__) && !defined(__serenity__)
# define _LIBCPP_HAS_CATOPEN 1
# include <nl_types.h>
# endif
diff --git a/zig/lib/libcxx/src/include/config_elast.h b/zig/lib/libcxx/src/include/config_elast.h
index bef26ec5019eccab758733eb85a1f8a6fc404968..fbb2899b1939a2f9ce7a39337c99e48c7749f7f2 100644
--- a/zig/lib/libcxx/src/include/config_elast.h
+++ b/zig/lib/libcxx/src/include/config_elast.h
@@ -35,6 +35,8 @@
#define _LIBCPP_ELAST 4095
#elif defined(__APPLE__)
// No _LIBCPP_ELAST needed on Apple
+#elif defined(__serenity__)
+// No _LIBCPP_ELAST needed on SerenityOS
#elif defined(__sun__)
#define _LIBCPP_ELAST ESTALE
#elif defined(__MVS__)

View File

@ -0,0 +1 @@
../../../Toolchain/Patches/llvm/0007-cmake-Allow-undefined-symbols-on-SerenityOS.patch

View File

@ -0,0 +1 @@
../../../Toolchain/Patches/llvm/0008-cmake-Support-building-shared-libLLVM-and-libClang-f.patch

View File

@ -0,0 +1 @@
../../../Toolchain/Patches/llvm/0010-Add-SerenityOS-to-config.guess.patch

View File

@ -0,0 +1 @@
../../../Toolchain/Patches/llvm/0011-llvm-Prevent-the-use-of-POSIX-shm-on-SerenityOS.patch

View File

@ -0,0 +1,94 @@
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);

View File

@ -0,0 +1,215 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: sin-ack <sin-ack@users.noreply.github.com>
Date: Sun, 11 Dec 2022 17:18:09 +0000
Subject: [PATCH] Add SerenityOS target
Named "serenity" within the code to match what LLVM says.
---
zig/lib/std/target.zig | 6 ++++++
zig/lib/std/zig/CrossTarget.zig | 2 ++
zig/src/codegen/llvm.zig | 2 ++
zig/src/codegen/llvm/bindings.zig | 1 +
zig/src/libc_installation.zig | 6 +++++-
zig/src/link/Elf.zig | 9 +++++++++
zig/src/target.zig | 5 ++++-
zig/src/type.zig | 1 +
zig/src/zig_llvm.h | 3 ++-
9 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/zig/lib/std/target.zig b/zig/lib/std/target.zig
index 49a7bd1c7dd1334067ed3b867f5ada7b99538355..af7b14be8e01509280d59b0196ff3a3040a48bf6 100644
--- a/zig/lib/std/target.zig
+++ b/zig/lib/std/target.zig
@@ -60,6 +60,7 @@ pub const Target = struct {
glsl450,
vulkan,
plan9,
+ serenity,
other,
pub fn isDarwin(tag: Tag) bool {
@@ -267,6 +268,7 @@ pub const Target = struct {
.glsl450, // TODO: GLSL versions
.vulkan,
.plan9,
+ .serenity,
.other,
=> return .{ .none = {} },
@@ -410,6 +412,7 @@ pub const Target = struct {
.openbsd,
.haiku,
.solaris,
+ .serenity,
=> true,
.linux,
@@ -563,6 +566,7 @@ pub const Target = struct {
.watchos,
.driverkit,
.shadermodel,
+ .serenity,
=> return .none,
}
}
@@ -1740,6 +1744,8 @@ pub const Target = struct {
// TODO revisit when multi-arch for Haiku is available
.haiku => return copy(&result, "/system/runtime_loader"),
+ .serenity => return copy(&result, "/usr/lib/Loader.so"),
+
// TODO go over each item in this list and either move it to the above list, or
// implement the standard dynamic linker path code for it.
.ananas,
diff --git a/zig/lib/std/zig/CrossTarget.zig b/zig/lib/std/zig/CrossTarget.zig
index aad0cb42f252d04b858133ba6ec598aa043f1c1c..a401ba49ee7afde0279c537a890cd33d3fe4815e 100644
--- a/zig/lib/std/zig/CrossTarget.zig
+++ b/zig/lib/std/zig/CrossTarget.zig
@@ -137,6 +137,7 @@ fn updateOsVersionRange(self: *CrossTarget, os: Target.Os) void {
.glsl450,
.vulkan,
.plan9,
+ .serenity,
.other,
=> {
self.os_version_min = .{ .none = {} };
@@ -693,6 +694,7 @@ fn parseOs(result: *CrossTarget, diags: *ParseOptions.Diagnostics, text: []const
.plan9,
.driverkit,
.shadermodel,
+ .serenity,
.other,
=> return error.InvalidOperatingSystemVersion,
diff --git a/zig/src/codegen/llvm.zig b/zig/src/codegen/llvm.zig
index e3ae805402e063341519ebeb7ee62c8717e45697..ba4f2c0840f15b7776f4d8768d3a525551069484 100644
--- a/zig/src/codegen/llvm.zig
+++ b/zig/src/codegen/llvm.zig
@@ -143,6 +143,7 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![:0]u8 {
.watchos => "watchos",
.driverkit => "driverkit",
.shadermodel => "shadermodel",
+ .serenity => "serenity",
.opencl,
.glsl450,
.vulkan,
@@ -246,6 +247,7 @@ pub fn targetOs(os_tag: std.Target.Os.Tag) llvm.OSType {
.emscripten => .Emscripten,
.driverkit => .DriverKit,
.shadermodel => .ShaderModel,
+ .serenity => .Serenity,
};
}
diff --git a/zig/src/codegen/llvm/bindings.zig b/zig/src/codegen/llvm/bindings.zig
index 90d0f51c7b36f7f3df19594933034f483a24c757..f11d1a6743493e18d5b4c2c6f19356d249f88cba 100644
--- a/zig/src/codegen/llvm/bindings.zig
+++ b/zig/src/codegen/llvm/bindings.zig
@@ -1287,6 +1287,7 @@ pub const OSType = enum(c_int) {
WASI,
Emscripten,
ShaderModel,
+ Serenity,
};
pub const ArchType = enum(c_int) {
diff --git a/zig/src/libc_installation.zig b/zig/src/libc_installation.zig
index 0a50f970123fbf2298cdf3666a1e7d6a59130e20..af50f4ebfaa783328513d9d9086cdfa9aee83b76 100644
--- a/zig/src/libc_installation.zig
+++ b/zig/src/libc_installation.zig
@@ -8,6 +8,7 @@ const build_options = @import("build_options");
const is_darwin = builtin.target.isDarwin();
const is_windows = builtin.target.os.tag == .windows;
const is_haiku = builtin.target.os.tag == .haiku;
+const is_serenity = builtin.target.os.tag == .serenity;
const log = std.log.scoped(.libc_installation);
@@ -205,6 +206,9 @@ pub const LibCInstallation = struct {
try self.findNativeIncludeDirPosix(args);
try self.findNativeCrtBeginDirHaiku(args);
self.crt_dir = try args.allocator.dupeZ(u8, "/system/develop/lib");
+ } else if (is_serenity) {
+ try self.findNativeIncludeDirPosix(args);
+ self.crt_dir = try args.allocator.dupeZ(u8, "/usr/lib");
} else if (std.process.can_spawn) {
try self.findNativeIncludeDirPosix(args);
switch (builtin.target.os.tag) {
@@ -308,7 +312,7 @@ pub const LibCInstallation = struct {
const include_dir_example_file = if (is_haiku) "posix/stdlib.h" else "stdlib.h";
const sys_include_dir_example_file = if (is_windows)
"sys\\types.h"
- else if (is_haiku)
+ else if (is_haiku or is_serenity)
"errno.h"
else
"sys/errno.h";
diff --git a/zig/src/link/Elf.zig b/zig/src/link/Elf.zig
index ebb1cbdfb8efc867d34e0315256e6efa4c90a035..46c61a10fefd8aa2efe43c023e261e97197dc4b3 100644
--- a/zig/src/link/Elf.zig
+++ b/zig/src/link/Elf.zig
@@ -3152,6 +3152,15 @@ const CsuObjects = struct {
.static_pie => result.set( "rcrt0.o", null, "crtbegin.o", "crtend.o", null ),
// zig fmt: on
},
+ .serenity => switch (mode) {
+ // zig fmt: off
+ .dynamic_lib => result.set( "crt0_shared.o", "crti.o", null, null, "crtn.o" ),
+ .dynamic_exe,
+ .dynamic_pie,
+ .static_exe,
+ .static_pie => result.set( "crt0.o", "crti.o", null, null, "crtn.o" ),
+ // zig fmt: on
+ },
.haiku => switch (mode) {
// zig fmt: off
.dynamic_lib => result.set( null, "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ),
diff --git a/zig/src/target.zig b/zig/src/target.zig
index 836791a1d1d7c69655d056b39ed58f2399ed12f4..02c9a23d9ac0dfa870defba94c8b302a5dab7927 100644
--- a/zig/src/target.zig
+++ b/zig/src/target.zig
@@ -187,7 +187,7 @@ pub fn libcNeedsLibUnwind(target: std.Target) bool {
}
pub fn requiresPIE(target: std.Target) bool {
- return target.isAndroid() or target.isDarwin() or target.os.tag == .openbsd;
+ return target.isAndroid() or target.isDarwin() or target.os.tag == .openbsd or target.os.tag == .serenity;
}
/// This function returns whether non-pic code is completely invalid on the given target.
@@ -472,6 +472,9 @@ pub fn libcFullLinkFlags(target: std.Target) []const []const u8 {
"-lpthread",
"-lc",
},
+ .serenity => &[_][]const u8{
+ "-lc",
+ },
else => switch (target.abi) {
.android => &[_][]const u8{
"-lm",
diff --git a/zig/src/type.zig b/zig/src/type.zig
index 1aefa8f7a1c77ddf58b1cb7271b57db6618704fb..13f8dc1879ed37e0452c78c698b72fcb3b955ec2 100644
--- a/zig/src/type.zig
+++ b/zig/src/type.zig
@@ -6772,6 +6772,7 @@ pub const CType = enum {
.ananas,
.fuchsia,
.minix,
+ .serenity,
=> switch (target.cpu.arch) {
.msp430 => switch (self) {
.short, .ushort, .int, .uint => return 16,
diff --git a/zig/src/zig_llvm.h b/zig/src/zig_llvm.h
index 7f9bd0a1619d30239a1ab92c3b9675d8c1bdb987..dc1561421fa0afedf892ddbdf698b57aeb83af72 100644
--- a/zig/src/zig_llvm.h
+++ b/zig/src/zig_llvm.h
@@ -468,7 +468,8 @@ enum ZigLLVM_OSType {
ZigLLVM_WASI, // Experimental WebAssembly OS
ZigLLVM_Emscripten,
ZigLLVM_ShaderModel, // DirectX ShaderModel
- ZigLLVM_LastOSType = ZigLLVM_ShaderModel
+ ZigLLVM_Serenity, // Well hello friends! :^)
+ ZigLLVM_LastOSType = ZigLLVM_Serenity
};
// Synchronize with target.cpp::abi_list

View File

@ -0,0 +1,616 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: sin-ack <sin-ack@users.noreply.github.com>
Date: Sun, 30 Oct 2022 19:30:50 +0000
Subject: [PATCH] Implement SerenityOS support in std
---
zig/lib/std/Thread.zig | 2 +-
zig/lib/std/c.zig | 1 +
zig/lib/std/c/serenity.zig | 396 +++++++++++++++++++++++++++
zig/lib/std/c/serenity/constants.zig | 6 +
zig/lib/std/debug.zig | 3 +-
zig/lib/std/fs.zig | 72 ++++-
zig/lib/std/fs/get_app_data_dir.zig | 2 +-
zig/lib/std/os.zig | 3 +-
8 files changed, 479 insertions(+), 6 deletions(-)
create mode 100644 zig/lib/std/c/serenity.zig
create mode 100644 zig/lib/std/c/serenity/constants.zig
diff --git a/zig/lib/std/Thread.zig b/zig/lib/std/Thread.zig
index e2e17a29259e1e2cf323ad90451f6fe7906e12a9..125e63bfd138a5a08653f4c815846c42e8eca3c5 100644
--- a/zig/lib/std/Thread.zig
+++ b/zig/lib/std/Thread.zig
@@ -617,7 +617,7 @@ const PosixThreadImpl = struct {
};
return @intCast(usize, count);
},
- .solaris => {
+ .solaris, .serenity => {
// The "proper" way to get the cpu count would be to query
// /dev/kstat via ioctls, and traverse a linked list for each
// cpu.
diff --git a/zig/lib/std/c.zig b/zig/lib/std/c.zig
index 5f03f1c61902a191de87b49f0dcbdfec4a872d34..92c4bfcccb6bf45fcd8df748d346c8ec0dc84208 100644
--- a/zig/lib/std/c.zig
+++ b/zig/lib/std/c.zig
@@ -54,6 +54,7 @@ pub usingnamespace switch (builtin.os.tag) {
.minix => @import("c/minix.zig"),
.emscripten => @import("c/emscripten.zig"),
.wasi => @import("c/wasi.zig"),
+ .serenity => @import("c/serenity.zig"),
else => struct {},
};
diff --git a/zig/lib/std/c/serenity.zig b/zig/lib/std/c/serenity.zig
new file mode 100644
index 0000000000000000000000000000000000000000..057813c1b13fcedc87271003220c42da7ef36e0e
--- /dev/null
+++ b/zig/lib/std/c/serenity.zig
@@ -0,0 +1,396 @@
+pub const std = @import("std");
+pub const SerenityConstants = @import("serenity/constants.zig");
+
+pub const fd_t = c_int;
+pub const dev_t = u32;
+pub const ino_t = u64;
+pub const off_t = i64;
+pub const nlink_t = u32;
+
+pub const E = enum(i32) {
+ SUCCESS = SerenityConstants.ESUCCESS,
+ PERM = SerenityConstants.EPERM,
+ NOENT = SerenityConstants.ENOENT,
+ SRCH = SerenityConstants.ESRCH,
+ INTR = SerenityConstants.EINTR,
+ IO = SerenityConstants.EIO,
+ NXIO = SerenityConstants.ENXIO,
+ @"2BIG" = SerenityConstants.E2BIG,
+ NOEXEC = SerenityConstants.ENOEXEC,
+ BADF = SerenityConstants.EBADF,
+ CHILD = SerenityConstants.ECHILD,
+ AGAIN = SerenityConstants.EAGAIN,
+ NOMEM = SerenityConstants.ENOMEM,
+ ACCES = SerenityConstants.EACCES,
+ FAULT = SerenityConstants.EFAULT,
+ NOTBLK = SerenityConstants.ENOTBLK,
+ BUSY = SerenityConstants.EBUSY,
+ EXIST = SerenityConstants.EEXIST,
+ XDEV = SerenityConstants.EXDEV,
+ NODEV = SerenityConstants.ENODEV,
+ NOTDIR = SerenityConstants.ENOTDIR,
+ ISDIR = SerenityConstants.EISDIR,
+ INVAL = SerenityConstants.EINVAL,
+ NFILE = SerenityConstants.ENFILE,
+ MFILE = SerenityConstants.EMFILE,
+ NOTTY = SerenityConstants.ENOTTY,
+ TXTBSY = SerenityConstants.ETXTBSY,
+ FBIG = SerenityConstants.EFBIG,
+ NOSPC = SerenityConstants.ENOSPC,
+ SPIPE = SerenityConstants.ESPIPE,
+ ROFS = SerenityConstants.EROFS,
+ MLINK = SerenityConstants.EMLINK,
+ PIPE = SerenityConstants.EPIPE,
+ RANGE = SerenityConstants.ERANGE,
+ NAMETOOLONG = SerenityConstants.ENAMETOOLONG,
+ LOOP = SerenityConstants.ELOOP,
+ OVERFLOW = SerenityConstants.EOVERFLOW,
+ OPNOTSUPP = SerenityConstants.EOPNOTSUPP,
+ NOSYS = SerenityConstants.ENOSYS,
+ NOTIMPL = SerenityConstants.ENOTIMPL,
+ AFNOSUPPORT = SerenityConstants.EAFNOSUPPORT,
+ NOTSOCK = SerenityConstants.ENOTSOCK,
+ ADDRINUSE = SerenityConstants.EADDRINUSE,
+ NOTEMPTY = SerenityConstants.ENOTEMPTY,
+ DOM = SerenityConstants.EDOM,
+ CONNREFUSED = SerenityConstants.ECONNREFUSED,
+ HOSTDOWN = SerenityConstants.EHOSTDOWN,
+ ADDRNOTAVAIL = SerenityConstants.EADDRNOTAVAIL,
+ ISCONN = SerenityConstants.EISCONN,
+ CONNABORTED = SerenityConstants.ECONNABORTED,
+ ALREADY = SerenityConstants.EALREADY,
+ CONNRESET = SerenityConstants.ECONNRESET,
+ DESTADDRREQ = SerenityConstants.EDESTADDRREQ,
+ HOSTUNREACH = SerenityConstants.EHOSTUNREACH,
+ ILSEQ = SerenityConstants.EILSEQ,
+ MSGSIZE = SerenityConstants.EMSGSIZE,
+ NETDOWN = SerenityConstants.ENETDOWN,
+ NETUNREACH = SerenityConstants.ENETUNREACH,
+ NETRESET = SerenityConstants.ENETRESET,
+ NOBUFS = SerenityConstants.ENOBUFS,
+ NOLCK = SerenityConstants.ENOLCK,
+ NOMSG = SerenityConstants.ENOMSG,
+ NOPROTOOPT = SerenityConstants.ENOPROTOOPT,
+ NOTCONN = SerenityConstants.ENOTCONN,
+ SHUTDOWN = SerenityConstants.ESHUTDOWN,
+ TOOMANYREFS = SerenityConstants.ETOOMANYREFS,
+ SOCKTNOSUPPORT = SerenityConstants.ESOCKTNOSUPPORT,
+ PROTONOSUPPORT = SerenityConstants.EPROTONOSUPPORT,
+ DEADLK = SerenityConstants.EDEADLK,
+ TIMEDOUT = SerenityConstants.ETIMEDOUT,
+ PROTOTYPE = SerenityConstants.EPROTOTYPE,
+ INPROGRESS = SerenityConstants.EINPROGRESS,
+ NOTHREAD = SerenityConstants.ENOTHREAD,
+ PROTO = SerenityConstants.EPROTO,
+ NOTSUP = SerenityConstants.ENOTSUP,
+ PFNOSUPPORT = SerenityConstants.EPFNOSUPPORT,
+ DIRINTOSELF = SerenityConstants.EDIRINTOSELF,
+ DQUOT = SerenityConstants.EDQUOT,
+ NOTRECOVERABLE = SerenityConstants.ENOTRECOVERABLE,
+ CANCELED = SerenityConstants.ECANCELED,
+ PROMISEVIOLATION = SerenityConstants.EPROMISEVIOLATION,
+ STALE = SerenityConstants.ESTALE,
+};
+
+pub const PATH_MAX = SerenityConstants.PATH_MAX;
+
+pub const time_t = i64;
+pub const timespec = struct {
+ tv_sec: time_t,
+ tv_nsec: c_long,
+};
+
+pub const mode_t = u16;
+
+pub const AT = struct {
+ pub const FDCWD = SerenityConstants.AT_FDCWD;
+ pub const SYMLINK_NOFOLLOW = SerenityConstants.AT_SYMLINK_NOFOLLOW;
+ pub const REMOVEDIR = SerenityConstants.AT_REMOVEDIR;
+};
+
+pub const _errno = struct {
+ extern "c" fn __errno_location() *c_int;
+}.__errno_location;
+
+pub const pthread_attr_t = *anyopaque;
+
+pub const LOCK = struct {
+ pub const SH = SerenityConstants.LOCK_SH;
+ pub const EX = SerenityConstants.LOCK_EX;
+ pub const UN = SerenityConstants.LOCK_UN;
+ pub const NB = SerenityConstants.LOCK_NB;
+};
+
+pub const STDIN_FILENO = SerenityConstants.STDIN_FILENO;
+pub const STDOUT_FILENO = SerenityConstants.STDOUT_FILENO;
+pub const STDERR_FILENO = SerenityConstants.STDERR_FILENO;
+
+pub const F = struct {
+ pub const DUPFD = SerenityConstants.F_DUPFD;
+ pub const GETFD = SerenityConstants.F_GETFD;
+ pub const SETFD = SerenityConstants.F_SETFD;
+ pub const GETFL = SerenityConstants.F_GETFL;
+ pub const SETFL = SerenityConstants.F_SETFL;
+ pub const ISTTY = SerenityConstants.F_ISTTY;
+ pub const GETLK = SerenityConstants.F_GETLK;
+ pub const SETLK = SerenityConstants.F_SETLK;
+ pub const SETLKW = SerenityConstants.F_SETLKW;
+};
+
+pub const FD_CLOEXEC = SerenityConstants.FD_CLOEXEC;
+
+pub const O = struct {
+ pub const RDONLY = SerenityConstants.O_RDONLY;
+ pub const WRONLY = SerenityConstants.O_WRONLY;
+ pub const RDWR = SerenityConstants.O_RDWR;
+ pub const ACCMODE = SerenityConstants.O_ACCMODE;
+ pub const EXEC = SerenityConstants.O_EXEC;
+ pub const CREAT = SerenityConstants.O_CREAT;
+ pub const EXCL = SerenityConstants.O_EXCL;
+ pub const NOCTTY = SerenityConstants.O_NOCTTY;
+ pub const TRUNC = SerenityConstants.O_TRUNC;
+ pub const APPEND = SerenityConstants.O_APPEND;
+ pub const NONBLOCK = SerenityConstants.O_NONBLOCK;
+ pub const DIRECTORY = SerenityConstants.O_DIRECTORY;
+ pub const NOFOLLOW = SerenityConstants.O_NOFOLLOW;
+ pub const CLOEXEC = SerenityConstants.O_CLOEXEC;
+ pub const DIRECT = SerenityConstants.O_DIRECT;
+ pub const SYNC = SerenityConstants.O_SYNC;
+};
+
+pub const R_OK = SerenityConstants.R_OK;
+pub const W_OK = SerenityConstants.W_OK;
+pub const X_OK = SerenityConstants.X_OK;
+pub const F_OK = SerenityConstants.F_OK;
+
+pub const CLOCK = struct {
+ pub const REALTIME = SerenityConstants.CLOCK_REALTIME;
+ pub const MONOTONIC = SerenityConstants.CLOCK_MONOTONIC;
+ pub const MONOTONIC_RAW = SerenityConstants.CLOCK_MONOTONIC_RAW;
+ pub const REALTIME_COARSE = SerenityConstants.CLOCK_REALTIME_COARSE;
+ pub const MONOTONIC_COARSE = SerenityConstants.CLOCK_MONOTONIC_COARSE;
+};
+
+pub const IOV_MAX = SerenityConstants.IOV_MAX;
+
+pub const pthread_mutex_t = struct {
+ lock: u32 = 0,
+ owner: ?std.c.pthread_t = null,
+ level: c_int = 0,
+ type: c_int = 0, // __PTHREAD_MUTEX_NORMAL
+};
+
+pub const pthread_cond_t = struct {
+ mutex: ?*pthread_mutex_t = null,
+ value: u32 = 0,
+ clockid: c_int = CLOCK.MONOTONIC_COARSE, // clockid_t
+};
+
+pub const uid_t = u32;
+pub const gid_t = u32;
+
+pub const blksize_t = u32;
+pub const blkcnt_t = u32;
+
+pub const Stat = struct {
+ dev: dev_t,
+ ino: ino_t,
+ mode: mode_t,
+ nlink: nlink_t,
+ uid: uid_t,
+ gid: gid_t,
+ rdev: dev_t,
+ size: off_t,
+ blksize: blksize_t,
+ blocks: blkcnt_t,
+ atim: timespec,
+ mtim: timespec,
+ ctim: timespec,
+
+ pub fn atime(self: @This()) timespec {
+ return self.atim;
+ }
+ pub fn mtime(self: @This()) timespec {
+ return self.mtim;
+ }
+ pub fn ctime(self: @This()) timespec {
+ return self.ctim;
+ }
+};
+
+pub const pid_t = c_int;
+
+pub const S = struct {
+ pub const IFMT = SerenityConstants.S_IFMT;
+ pub const IFDIR = SerenityConstants.S_IFDIR;
+ pub const IFCHR = SerenityConstants.S_IFCHR;
+ pub const IFBLK = SerenityConstants.S_IFBLK;
+ pub const IFREG = SerenityConstants.S_IFREG;
+ pub const IFIFO = SerenityConstants.S_IFIFO;
+ pub const IFLNK = SerenityConstants.S_IFLNK;
+ pub const IFSOCK = SerenityConstants.S_IFSOCK;
+
+ pub const ISUID = SerenityConstants.S_ISUID;
+ pub const ISGID = SerenityConstants.S_ISGID;
+ pub const ISVTX = SerenityConstants.S_ISVTX;
+ pub const IRUSR = SerenityConstants.S_IRUSR;
+ pub const IWUSR = SerenityConstants.S_IWUSR;
+ pub const IXUSR = SerenityConstants.S_IXUSR;
+ pub const IREAD = SerenityConstants.S_IREAD;
+ pub const IWRITE = SerenityConstants.S_IWRITE;
+ pub const IEXEC = SerenityConstants.S_IEXEC;
+ pub const IRGRP = SerenityConstants.S_IRGRP;
+ pub const IWGRP = SerenityConstants.S_IWGRP;
+ pub const IXGRP = SerenityConstants.S_IXGRP;
+ pub const IROTH = SerenityConstants.S_IROTH;
+ pub const IWOTH = SerenityConstants.S_IWOTH;
+ pub const IXOTH = SerenityConstants.S_IXOTH;
+
+ pub const IRWXU = SerenityConstants.S_IRWXU;
+
+ pub const IRWXG = SerenityConstants.S_IRWXG;
+ pub const IRWXO = SerenityConstants.S_IRWXO;
+
+ pub fn ISREG(m: u32) bool {
+ return m & IFMT == IFREG;
+ }
+
+ pub fn ISLNK(m: u32) bool {
+ return m & IFMT == IFLNK;
+ }
+
+ pub fn ISBLK(m: u32) bool {
+ return m & IFMT == IFBLK;
+ }
+
+ pub fn ISDIR(m: u32) bool {
+ return m & IFMT == IFDIR;
+ }
+
+ pub fn ISCHR(m: u32) bool {
+ return m & IFMT == IFCHR;
+ }
+
+ pub fn ISFIFO(m: u32) bool {
+ return m & IFMT == IFIFO;
+ }
+
+ pub fn ISSOCK(m: u32) bool {
+ return m & IFMT == IFSOCK;
+ }
+};
+
+pub const SEEK = struct {
+ pub const SET = SerenityConstants.SEEK_SET;
+ pub const CUR = SerenityConstants.SEEK_CUR;
+ pub const END = SerenityConstants.SEEK_END;
+};
+
+pub const POLL = struct {
+ pub const IN = SerenityConstants.POLLIN;
+ pub const RDNORM = SerenityConstants.POLLRDNORM;
+ pub const PRI = SerenityConstants.POLLPRI;
+ pub const OUT = SerenityConstants.POLLOUT;
+ pub const WRNORM = SerenityConstants.POLLWRNORM;
+ pub const ERR = SerenityConstants.POLLERR;
+ pub const HUP = SerenityConstants.POLLHUP;
+ pub const NVAL = SerenityConstants.POLLNVAL;
+ pub const WRBAND = SerenityConstants.POLLWRBAND;
+ pub const RDHUP = SerenityConstants.POLLRDHUP;
+};
+
+pub const pollfd = struct {
+ fd: c_int,
+ events: c_short,
+ revents: c_short,
+};
+
+pub const nfds_t = c_uint;
+
+pub const W = struct {
+ pub const NOHANG = SerenityConstants.WNOHANG;
+ pub const UNTRACED = SerenityConstants.WUNTRACED;
+ pub const STOPPED = SerenityConstants.WSTOPPED;
+ pub const EXITED = SerenityConstants.WEXITED;
+ pub const CONTINUED = SerenityConstants.WCONTINUED;
+ pub const NOWAIT = SerenityConstants.WNOWAIT;
+
+ pub fn EXITSTATUS(s: u32) u8 {
+ return @intCast(u8, (s & 0xff00) >> 8);
+ }
+
+ pub fn STOPSIG(s: u32) u32 {
+ return EXITSTATUS(s);
+ }
+
+ pub fn TERMSIG(s: u32) u32 {
+ return s & 0x7f;
+ }
+
+ pub fn IFEXITED(s: u32) bool {
+ return TERMSIG(s) == 0;
+ }
+
+ pub fn IFSTOPPED(s: u32) bool {
+ return (s & 0xff) == 0x7f;
+ }
+
+ pub fn IFSIGNALED(s: u32) bool {
+ return (@intCast(u8, (s & 0x7f) + 1) >> 1) > 0;
+ }
+
+ pub fn IFCONTINUED(s: u32) bool {
+ return s == 0xffff;
+ }
+};
+
+pub const dirent = extern struct {
+ d_ino: ino_t,
+ d_off: off_t,
+ d_reclen: c_ushort,
+ d_type: u8,
+ d_name: [256]u8,
+};
+pub extern "c" fn readdir_r(dir: *std.c.DIR, entry: *dirent, result: *?*dirent) i32;
+
+pub const PROT = struct {
+ pub const READ = SerenityConstants.PROT_READ;
+ pub const WRITE = SerenityConstants.PROT_WRITE;
+ pub const EXEC = SerenityConstants.PROT_EXEC;
+ pub const NONE = SerenityConstants.PROT_NONE;
+};
+
+pub const MAP = struct {
+ pub const FILE = SerenityConstants.MAP_FILE;
+ pub const SHARED = SerenityConstants.MAP_SHARED;
+ pub const PRIVATE = SerenityConstants.MAP_PRIVATE;
+ pub const FIXED = SerenityConstants.MAP_FIXED;
+ pub const ANONYMOUS = SerenityConstants.MAP_ANONYMOUS;
+ pub const ANON = SerenityConstants.MAP_ANON;
+ pub const STACK = SerenityConstants.MAP_STACK;
+ pub const NORESERVE = SerenityConstants.MAP_NORESERVE;
+ pub const RANDOMIZED = SerenityConstants.MAP_RANDOMIZED;
+ pub const PURGEABLE = SerenityConstants.MAP_PURGEABLE;
+ pub const FIXED_NOREPLACE = SerenityConstants.MAP_FIXED_NOREPLACE;
+ pub const FAILED = @intToPtr(*anyopaque, @bitCast(usize, @as(isize, -1)));
+};
+
+pub const MSF = struct {
+ pub const SYNC = SerenityConstants.MS_SYNC;
+ pub const ASYNC = SerenityConstants.MS_ASYNC;
+ pub const INVALIDATE = SerenityConstants.MS_INVALIDATE;
+};
+
+pub extern "c" fn sysconf(sc: c_int) c_long;
+pub const _SC = struct {
+ pub const NPROCESSORS_ONLN = SerenityConstants._SC_NPROCESSORS_ONLN;
+};
+
+pub const dl_phdr_info = extern struct {
+ dlpi_addr: std.elf.Addr,
+ dlpi_name: ?[*:0]const u8,
+ dlpi_phdr: [*]std.elf.Phdr,
+ dlpi_phnum: std.elf.Half,
+};
+pub const dl_iterate_phdr_callback = *const fn (info: *dl_phdr_info, size: usize, data: ?*anyopaque) callconv(.C) c_int;
+pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*anyopaque) c_int;
diff --git a/zig/lib/std/c/serenity/constants.zig b/zig/lib/std/c/serenity/constants.zig
new file mode 100644
index 0000000000000000000000000000000000000000..94d7b1c091f7affb5c968738a8719cbbe526650b
--- /dev/null
+++ b/zig/lib/std/c/serenity/constants.zig
@@ -0,0 +1,6 @@
+comptime {
+ @compileError(
+ "A Zig compilation targeting SerenityOS can only be done by installing the SerenityOS Zig port. " ++
+ "This file is replaced by the actual POSIX constants during the port build process.",
+ );
+}
diff --git a/zig/lib/std/debug.zig b/zig/lib/std/debug.zig
index 90ceff3df157f3d94feddceae12de59fc2e3581d..5c25a8c9cebcb0cce01b229808ea67c57c968d5e 100644
--- a/zig/lib/std/debug.zig
+++ b/zig/lib/std/debug.zig
@@ -812,6 +812,7 @@ pub fn openSelfDebugInfo(allocator: mem.Allocator) anyerror!DebugInfo {
.macos,
.windows,
.solaris,
+ .serenity,
=> return DebugInfo.init(allocator),
else => return error.UnsupportedDebugInfo,
}
@@ -1761,7 +1762,7 @@ pub const ModuleDebugInfo = switch (native_os) {
};
}
},
- .linux, .netbsd, .freebsd, .dragonfly, .openbsd, .haiku, .solaris => struct {
+ .linux, .netbsd, .freebsd, .dragonfly, .openbsd, .haiku, .solaris, .serenity => struct {
base_address: usize,
dwarf: DW.DwarfInfo,
mapped_memory: []align(mem.page_size) const u8,
diff --git a/zig/lib/std/fs.zig b/zig/lib/std/fs.zig
index e253aaff9e9505182db90c8fa08aa931dca8a0ba..cebf86fc05164ff311731deb4c75730d4dc84d27 100644
--- a/zig/lib/std/fs.zig
+++ b/zig/lib/std/fs.zig
@@ -34,7 +34,7 @@ pub const Watch = @import("fs/watch.zig").Watch;
/// fit into a UTF-8 encoded array of this length.
/// The byte count includes room for a null sentinel byte.
pub const MAX_PATH_BYTES = switch (builtin.os.tag) {
- .linux, .macos, .ios, .freebsd, .netbsd, .dragonfly, .openbsd, .haiku, .solaris => os.PATH_MAX,
+ .linux, .macos, .ios, .freebsd, .netbsd, .dragonfly, .openbsd, .haiku, .solaris, .serenity => os.PATH_MAX,
// Each UTF-16LE character may be expanded to 3 UTF-8 bytes.
// If it would require 4 UTF-8 bytes, then there would be a surrogate
// pair in the UTF-16LE, and we (over)account 3 bytes for it that way.
@@ -521,6 +521,69 @@ pub const IterableDir = struct {
self.first_iter = true;
}
},
+ .serenity => struct {
+ dir: Dir,
+ dir_ptr: *os.system.DIR,
+
+ const Self = @This();
+
+ pub const Error = IteratorError;
+
+ pub fn next(self: *Self) Error!?Entry {
+ const errno_location = os.system._errno();
+ start_over: while (true) {
+ // HACK: readdir_r currently doesn't work properly on
+ // SerenityOS. Until it does, we need to rely on
+ // readdir which has legacy errno behavior.
+ const saved_errno = errno_location.*;
+ errno_location.* = 0;
+ const entry = os.system.readdir(self.dir_ptr);
+ if (entry == null) {
+ if (errno_location.* != 0) {
+ switch (os.errno(-1)) {
+ .OVERFLOW => unreachable,
+ .BADF => unreachable,
+ .NOENT => unreachable,
+ else => |err| return os.unexpectedErrno(err),
+ }
+ }
+
+ // No error, just end of directory.
+ errno_location.* = saved_errno;
+ return null;
+ }
+
+ const name = mem.sliceTo(@ptrCast([*:0]u8, &entry.?.d_name), 0);
+ if (mem.eql(u8, name, ".") or mem.eql(u8, name, ".."))
+ continue :start_over;
+
+ const stat_info = os.fstatat(
+ self.dir.fd,
+ name,
+ os.AT.SYMLINK_NOFOLLOW,
+ ) catch |err| switch (err) {
+ error.NameTooLong => unreachable,
+ error.SymLinkLoop => unreachable,
+ error.FileNotFound => unreachable, // lost the race
+ else => |e| return e,
+ };
+ const entry_kind = switch (stat_info.mode & os.S.IFMT) {
+ os.S.IFIFO => Entry.Kind.NamedPipe,
+ os.S.IFCHR => Entry.Kind.CharacterDevice,
+ os.S.IFDIR => Entry.Kind.Directory,
+ os.S.IFBLK => Entry.Kind.BlockDevice,
+ os.S.IFREG => Entry.Kind.File,
+ os.S.IFLNK => Entry.Kind.SymLink,
+ os.S.IFSOCK => Entry.Kind.UnixDomainSocket,
+ else => Entry.Kind.Unknown,
+ };
+ return Entry{
+ .name = name,
+ .kind = entry_kind,
+ };
+ }
+ }
+ },
.haiku => struct {
dir: Dir,
buf: [1024]u8, // TODO align(@alignOf(os.dirent64)),
@@ -906,6 +969,11 @@ pub const IterableDir = struct {
.buf = undefined,
.first_iter = first_iter_start_value,
},
+ .serenity => return Iterator{
+ .dir = self.dir,
+ // FIXME: Very small chance this may fail.
+ .dir_ptr = os.system.fdopendir(self.dir.fd).?,
+ },
.windows => return Iterator{
.dir = self.dir,
.index = 0,
@@ -2941,7 +3009,7 @@ pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 {
return out_buffer[0..real_path.len];
}
switch (builtin.os.tag) {
- .linux => return os.readlinkZ("/proc/self/exe", out_buffer),
+ .linux, .serenity => return os.readlinkZ("/proc/self/exe", out_buffer),
.solaris => return os.readlinkZ("/proc/self/path/a.out", out_buffer),
.freebsd, .dragonfly => {
var mib = [4]c_int{ os.CTL.KERN, os.KERN.PROC, os.KERN.PROC_PATHNAME, -1 };
diff --git a/zig/lib/std/fs/get_app_data_dir.zig b/zig/lib/std/fs/get_app_data_dir.zig
index 4f7ba9af623841cc8be7b6c48d55037f689fec8d..5a5b4de8aefe6962979a9a65f937cc35c78d7631 100644
--- a/zig/lib/std/fs/get_app_data_dir.zig
+++ b/zig/lib/std/fs/get_app_data_dir.zig
@@ -44,7 +44,7 @@ pub fn getAppDataDir(allocator: mem.Allocator, appname: []const u8) GetAppDataDi
};
return fs.path.join(allocator, &[_][]const u8{ home_dir, "Library", "Application Support", appname });
},
- .linux, .freebsd, .netbsd, .dragonfly, .openbsd, .solaris => {
+ .linux, .freebsd, .netbsd, .dragonfly, .openbsd, .solaris, .serenity => {
if (os.getenv("XDG_DATA_HOME")) |xdg| {
return fs.path.join(allocator, &[_][]const u8{ xdg, appname });
}
diff --git a/zig/lib/std/os.zig b/zig/lib/std/os.zig
index f13ee03a967df2899aed1b935dd12975f5d07332..b1c174b774b40553c455d768c11ec6c752796a06 100644
--- a/zig/lib/std/os.zig
+++ b/zig/lib/std/os.zig
@@ -36,6 +36,7 @@ pub const haiku = std.c;
pub const netbsd = std.c;
pub const openbsd = std.c;
pub const solaris = std.c;
+pub const serenity = std.c;
pub const linux = @import("os/linux.zig");
pub const plan9 = @import("os/plan9.zig");
pub const uefi = @import("os/uefi.zig");
@@ -5112,7 +5113,7 @@ pub fn getFdPath(fd: fd_t, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
const len = mem.indexOfScalar(u8, out_buffer[0..], @as(u8, 0)) orelse MAX_PATH_BYTES;
return out_buffer[0..len];
},
- .linux => {
+ .linux, .serenity => {
var procfs_buf: ["/proc/self/fd/-2147483648".len:0]u8 = undefined;
const proc_path = std.fmt.bufPrint(procfs_buf[0..], "/proc/self/fd/{d}\x00", .{fd}) catch unreachable;

View File

@ -0,0 +1,98 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: sin-ack <sin-ack@users.noreply.github.com>
Date: Sun, 11 Dec 2022 17:22:27 +0000
Subject: [PATCH] build: Adjust build process for SerenityOS
---
build | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 52 insertions(+), 1 deletion(-)
diff --git a/build b/build
index 5db75471ba94da22550136754c5ae71a56b4527c..2e757e44e852e41bd998ff70c2a9992b69d2910f 100755
--- a/build
+++ b/build
@@ -17,6 +17,7 @@ case $TARGET_OS_CMAKE in
freebsd) TARGET_OS_CMAKE="FreeBSD";;
windows) TARGET_OS_CMAKE="Windows";;
linux) TARGET_OS_CMAKE="Linux";;
+ serenity) TARGET_OS_CMAKE="Serenity";;
native) TARGET_OS_CMAKE="";;
esac
@@ -62,10 +63,58 @@ cmake "$ROOTDIR/zig" \
-DCMAKE_BUILD_TYPE=Release \
-DZIG_VERSION="$ZIG_VERSION"
cmake --build . --target install
+
+# Create a libc installation file so Zig knows where to look for headers and
+# libraries while compiling for the Serenity target.
+cat <<EOF > "$ROOTDIR/out/libc_installation.txt"
+include_dir=$SERENITY_INSTALL_ROOT/usr/include
+sys_include_dir=$SERENITY_INSTALL_ROOT/usr/include
+crt_dir=$SERENITY_INSTALL_ROOT/usr/lib
+msvc_lib_dir=
+kernel32_lib_dir=
+gcc_dir=
+EOF
+
+export ZIG_LIBC="$ROOTDIR/out/libc_installation.txt"
+
+# Create a CMakeToolchain.txt file to tell CMake about the SerenityOS platform.
+# Adapted from Toolchain/CMake/GNUToolchain.txt.in, with the tool settings
+# removed as zig-bootstrap overrides them manually with the cmake command.
+cat <<EOF > "$ROOTDIR/out/CMakeToolchain.txt"
+if (\${CMAKE_VERSION} VERSION_LESS "3.25.0")
+ list(APPEND CMAKE_MODULE_PATH "$SERENITY_SOURCE_DIR/Toolchain/CMake")
+endif()
+
+set(CMAKE_SYSTEM_NAME SerenityOS)
+set(CMAKE_SYSTEM_PROCESSOR "$SERENITY_ARCH")
+
+set(CMAKE_C_COMPILER_WORKS TRUE)
+set(CMAKE_CXX_COMPILER_WORKS TRUE)
+
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH)
+EOF
+
# Now we have Zig as a cross compiler.
ZIG="$ROOTDIR/out/host/bin/zig"
+# Create a serenity/constants.zig file. This package will overwrite the
+# constants.zig file in the upstream Zig in order to provide values for POSIX
+# constants.
+$ZIG run "$ROOTDIR/out/scripts/generate-serenity-constants.zig" \
+ -D__serenity__ \
+ -I"$SERENITY_INSTALL_ROOT/usr/include" \
+ > "$ROOTDIR/zig/lib/std/c/serenity/constants.zig"
+# HACK: Also copy this file over to the host Zig compiler in the prefix. It has
+# to be done this way because we can't generate the constants until we
+# have a Zig compiler, and by the time the host Zig compiler is built
+# the standard library sources have been copied into the prefix already.
+cp "$ROOTDIR/zig/lib/std/c/serenity/constants.zig" \
+ "$ROOTDIR/out/host/lib/zig/std/c/serenity/constants.zig"
+
# First cross compile zlib for the target, as we need the LLVM linked into
# the final zig binary to have zlib support enabled.
mkdir -p "$ROOTDIR/out/build-zlib-$TARGET-$MCPU"
@@ -81,7 +130,8 @@ cmake "$ROOTDIR/zlib" \
-DCMAKE_ASM_COMPILER="$ZIG;cc;-fno-sanitize=all;-s;-target;$TARGET;-mcpu=$MCPU" \
-DCMAKE_RC_COMPILER="$ROOTDIR/out/host/bin/llvm-rc" \
-DCMAKE_AR="$ROOTDIR/out/host/bin/llvm-ar" \
- -DCMAKE_RANLIB="$ROOTDIR/out/host/bin/llvm-ranlib"
+ -DCMAKE_RANLIB="$ROOTDIR/out/host/bin/llvm-ranlib" \
+ -DCMAKE_TOOLCHAIN_FILE="$ROOTDIR/out/CMakeToolchain.txt"
cmake --build . --target install
# Same deal for zstd.
@@ -144,6 +194,7 @@ cmake "$ROOTDIR/llvm" \
-DCMAKE_RC_COMPILER="$ROOTDIR/out/host/bin/llvm-rc" \
-DCMAKE_AR="$ROOTDIR/out/host/bin/llvm-ar" \
-DCMAKE_RANLIB="$ROOTDIR/out/host/bin/llvm-ranlib" \
+ -DCMAKE_TOOLCHAIN_FILE="$ROOTDIR/out/CMakeToolchain.txt" \
-DLLVM_ENABLE_BACKTRACES=OFF \
-DLLVM_ENABLE_BINDINGS=OFF \
-DLLVM_ENABLE_CRASH_OVERRIDES=OFF \

109
Ports/zig/patches/ReadMe.md Normal file
View File

@ -0,0 +1,109 @@
# Patches for zig on SerenityOS
## `0001-Add-support-for-building-LLVM-on-SerenityOS.patch`
Add support for building LLVM on SerenityOS
Adds SerenityOS `#ifdef`s for platform-specific code.
We stub out wait4, as SerenityOS doesn't support querying a child
process's resource usage information.
## `0002-Add-triple-for-SerenityOS.patch`
Add triple for SerenityOS
## `0003-Add-support-for-SerenityOS.patch`
Add support for SerenityOS
Adds support for the `$arch-pc-serenity` target to the Clang front end.
This makes the compiler look for libraries and headers in the right
places, and enables some security mitigations like stack-smashing
protection and position-independent code by default.
## `0004-Default-to-ftls-model-initial-exec-on-SerenityOS.patch`
Default to -ftls-model=initial-exec on SerenityOS
This is a hack to make Clang use the initial-exec TLS model instead of
the default local-exec when building code for Serenity.
This patch should be removed when we implement proper TLS support.
## `0005-Add-support-for-SerenityOS.patch`
Add support for SerenityOS
This commit teaches libc++ about what features are available in our
LibC, namely:
* We do not have locale support, so no-op shims should be used in place
of the C locale API.
* The number of errno constants defined by us is given by the value of
the `ELAST` macro.
* Multithreading is implemented though the pthread library.
* Use libc++'s builtin character type table instead of the one provided
by LibC as there's a lot of extra porting work to convince the rest of
locale.cpp to use our character type table properly.
This commit is an adaptation of the LLVM patch by Daniel Bertalan to fit
the layout of the zig-bootstrap project.
## `0006-Allow-undefined-symbols-on-SerenityOS.patch`
Allow undefined symbols on SerenityOS
Allow undefined symbols in LLVM libraries, which is needed because only
stubs are available for SerenityOS libraries when libc++ and libunwind
are built.
## `0007-Support-building-shared-libLLVM-and-libClang-for-Ser.patch`
Support building shared libLLVM and libClang for SerenityOS
This patch tells CMake that the --whole-archive linker option should be
used for specifying the archives whose members will constitute these
shared libraries.
Symbol versioning is disabled, as the SerenityOS loader doesn't support
it, and the ELF sections that store version data would just waste space.
## `0008-Add-SerenityOS-to-config.guess.patch`
Add SerenityOS to config.guess
## `0009-Prevent-the-use-of-POSIX-shm-on-SerenityOS.patch`
Prevent the use of POSIX shm on SerenityOS
POSIX shm is not supported by SerenityOS yet, so this causes a
compilation error.
## `0010-llvm-Implement-bigint-to-LLVM-int-for-32-bit-compile.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.
## `0011-Add-SerenityOS-target.patch`
Add SerenityOS target
Named "serenity" within the code to match what LLVM says.
## `0012-Implement-SerenityOS-support-in-std.patch`
Implement SerenityOS support in std
## `0013-build-Adjust-build-process-for-SerenityOS.patch`
build: Adjust build process for SerenityOS

View File

@ -0,0 +1,193 @@
AT_FDCWD
AT_REMOVEDIR
AT_SYMLINK_NOFOLLOW
CLOCK_MONOTONIC
CLOCK_MONOTONIC_COARSE
CLOCK_MONOTONIC_RAW
CLOCK_REALTIME
CLOCK_REALTIME_COARSE
E2BIG
EACCES
EADDRINUSE
EADDRNOTAVAIL
EAFNOSUPPORT
EAGAIN
EALREADY
EBADF
EBUSY
ECANCELED
ECHILD
ECONNABORTED
ECONNREFUSED
ECONNRESET
EDEADLK
EDESTADDRREQ
EDIRINTOSELF
EDOM
EDQUOT
EEXIST
EFAULT
EFBIG
EHOSTDOWN
EHOSTUNREACH
EILSEQ
EINPROGRESS
EINTR
EINVAL
EIO
EISCONN
EISDIR
ELOOP
EMFILE
EMLINK
EMSGSIZE
ENAMETOOLONG
ENETDOWN
ENETRESET
ENETUNREACH
ENFILE
ENOBUFS
ENODEV
ENOENT
ENOEXEC
ENOLCK
ENOMEM
ENOMSG
ENOPROTOOPT
ENOSPC
ENOSYS
ENOTBLK
ENOTCONN
ENOTDIR
ENOTEMPTY
ENOTHREAD
ENOTIMPL
ENOTRECOVERABLE
ENOTSOCK
ENOTSUP
ENOTTY
ENXIO
EOPNOTSUPP
EOVERFLOW
EPERM
EPFNOSUPPORT
EPIPE
EPROMISEVIOLATION
EPROTO
EPROTONOSUPPORT
EPROTOTYPE
ERANGE
EROFS
ESHUTDOWN
ESOCKTNOSUPPORT
ESPIPE
ESRCH
ESTALE
ESUCCESS
ETIMEDOUT
ETOOMANYREFS
ETXTBSY
EXDEV
FD_CLOEXEC
F_DUPFD
F_GETFD
F_GETFL
F_GETLK
F_ISTTY
F_OK
F_SETFD
F_SETFL
F_SETLK
F_SETLKW
IOV_MAX
LOCK_EX
LOCK_NB
LOCK_SH
LOCK_UN
MAP_ANON
MAP_ANONYMOUS
MAP_FILE
MAP_FIXED
MAP_FIXED_NOREPLACE
MAP_NORESERVE
MAP_PRIVATE
MAP_PURGEABLE
MAP_RANDOMIZED
MAP_SHARED
MAP_STACK
MS_ASYNC
MS_INVALIDATE
MS_SYNC
O_ACCMODE
O_APPEND
O_CLOEXEC
O_CREAT
O_DIRECT
O_DIRECTORY
O_EXCL
O_EXEC
O_NOCTTY
O_NOFOLLOW
O_NONBLOCK
O_RDONLY
O_RDWR
O_SYNC
O_TRUNC
O_WRONLY
PATH_MAX
POLLERR
POLLHUP
POLLIN
POLLNVAL
POLLOUT
POLLPRI
POLLRDHUP
POLLRDNORM
POLLWRBAND
POLLWRNORM
PROT_EXEC
PROT_NONE
PROT_READ
PROT_WRITE
R_OK
SEEK_CUR
SEEK_END
SEEK_SET
STDERR_FILENO
STDIN_FILENO
STDOUT_FILENO
S_IEXEC
S_IFBLK
S_IFCHR
S_IFDIR
S_IFIFO
S_IFLNK
S_IFMT
S_IFREG
S_IFSOCK
S_IREAD
S_IRGRP
S_IROTH
S_IRUSR
S_IRWXG
S_IRWXO
S_IRWXU
S_ISGID
S_ISUID
S_ISVTX
S_IWGRP
S_IWOTH
S_IWRITE
S_IWUSR
S_IXGRP
S_IXOTH
S_IXUSR
WCONTINUED
WEXITED
WNOHANG
WNOWAIT
WSTOPPED
WUNTRACED
W_OK
X_OK
_SC_NPROCESSORS_ONLN

View File

@ -0,0 +1,50 @@
const std = @import("std");
const SerenityIncludes = @cImport({
@cInclude("bits/pthread_integration.h");
@cInclude("dirent.h");
@cInclude("errno_codes.h");
@cInclude("fcntl.h");
@cInclude("limits.h");
@cInclude("link.h");
@cInclude("poll.h");
@cInclude("semaphore.h");
@cInclude("stdio.h");
@cInclude("sys/file.h");
@cInclude("sys/mman.h");
@cInclude("sys/stat.h");
@cInclude("sys/types.h");
@cInclude("sys/uio.h");
@cInclude("sys/wait.h");
@cInclude("time.h");
@cInclude("unistd.h");
});
const constant_file = @embedFile("./constants.txt");
const constants = blk: {
@setEvalBranchQuota(10000);
var constant_list: []const []const u8 = &.{};
var constant_iterator = std.mem.tokenize(u8, constant_file, "\n");
while (constant_iterator.next()) |constant| {
constant_list = constant_list ++ &[_][]const u8{constant};
}
break :blk constant_list;
};
pub fn main() !void {
const writer = std.io.getStdOut().writer();
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
inline for (constants) |constant| {
const value = @field(SerenityIncludes, constant);
const decl = try std.fmt.allocPrint(allocator, "pub const " ++ constant ++ " = {d};\n", .{value});
defer allocator.free(decl);
try writer.writeAll(decl);
}
}