aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.zig11
-rw-r--r--lib/compiler/aro/aro/target.zig6
-rw-r--r--lib/compiler_rt/int_from_float.zig6
-rw-r--r--lib/compiler_rt/int_from_float_test.zig40
-rw-r--r--lib/std/Build/Cache.zig20
-rw-r--r--lib/std/Target.zig4
-rw-r--r--lib/std/Target/Query.zig2
-rw-r--r--lib/std/Thread.zig31
-rw-r--r--lib/std/array_list.zig132
-rw-r--r--lib/std/c.zig1012
-rw-r--r--lib/std/c/serenity.zig75
-rw-r--r--lib/std/crypto/Certificate.zig3
-rw-r--r--lib/std/crypto/Certificate/Bundle.zig16
-rw-r--r--lib/std/fs.zig8
-rw-r--r--lib/std/fs/get_app_data_dir.zig2
-rw-r--r--lib/std/fs/test.zig103
-rw-r--r--lib/std/io/test.zig16
-rw-r--r--lib/std/mem/Allocator.zig3
-rw-r--r--lib/std/multi_array_list.zig4
-rw-r--r--lib/std/os.zig3
-rw-r--r--lib/std/os/uefi.zig3
-rw-r--r--lib/std/os/uefi/status.zig46
-rw-r--r--lib/std/posix/test.zig343
-rw-r--r--lib/std/process.zig1
-rw-r--r--lib/std/time/epoch.zig15
-rw-r--r--lib/std/zig/system.zig4
-rw-r--r--lib/std/zig/target.zig11
-rw-r--r--src/Compilation.zig53
-rw-r--r--src/Package/Fetch.zig11
-rw-r--r--src/Sema.zig25
-rw-r--r--src/Value.zig2
-rw-r--r--src/Zcu.zig5
-rw-r--r--src/arch/x86_64/CodeGen.zig775
-rw-r--r--src/arch/x86_64/abi.zig8
-rw-r--r--src/codegen/llvm.zig612
-rw-r--r--src/link/Dwarf.zig59
-rw-r--r--src/main.zig2
-rw-r--r--test/behavior/floatop.zig133
-rw-r--r--test/behavior/select.zig20
-rw-r--r--test/behavior/this.zig10
-rw-r--r--test/cases/compile_errors/union_field_ordered_differently_than_enum.zig27
-rw-r--r--test/link/elf.zig3
-rw-r--r--test/tests.zig8
43 files changed, 2427 insertions, 1246 deletions
diff --git a/build.zig b/build.zig
index 9a52a35275..15762f0ae8 100644
--- a/build.zig
+++ b/build.zig
@@ -257,13 +257,10 @@ pub fn build(b: *std.Build) !void {
var code: u8 = undefined;
const git_describe_untrimmed = b.runAllowFail(&[_][]const u8{
"git",
- "-C",
- b.build_root.path orelse ".",
- "describe",
- "--match",
- "*.*.*",
- "--tags",
- "--abbrev=9",
+ "-C", b.build_root.path orelse ".", // affects the --git-dir argument
+ "--git-dir", ".git", // affected by the -C argument
+ "describe", "--match", "*.*.*", //
+ "--tags", "--abbrev=9",
}, &code, .Ignore) catch {
break :v version_string;
};
diff --git a/lib/compiler/aro/aro/target.zig b/lib/compiler/aro/aro/target.zig
index 7495eb5d9a..bea982daa2 100644
--- a/lib/compiler/aro/aro/target.zig
+++ b/lib/compiler/aro/aro/target.zig
@@ -204,7 +204,7 @@ pub fn unnamedFieldAffectsAlignment(target: std.Target) bool {
},
.armeb => {
if (std.Target.arm.featureSetHas(target.cpu.features, .has_v7)) {
- if (std.Target.Abi.default(target.cpu.arch, target.os) == .eabi) return true;
+ if (std.Target.Abi.default(target.cpu.arch, target.os.tag) == .eabi) return true;
}
},
.arm => return true,
@@ -716,7 +716,7 @@ test "alignment functions - smoke test" {
const x86 = std.Target.Cpu.Arch.x86_64;
target.os = std.Target.Os.Tag.defaultVersionRange(.linux, x86, .none);
target.cpu = std.Target.Cpu.baseline(x86, target.os);
- target.abi = std.Target.Abi.default(x86, target.os);
+ target.abi = std.Target.Abi.default(x86, target.os.tag);
try std.testing.expect(isTlsSupported(target));
try std.testing.expect(!ignoreNonZeroSizedBitfieldTypeAlignment(target));
@@ -729,7 +729,7 @@ test "alignment functions - smoke test" {
const arm = std.Target.Cpu.Arch.arm;
target.os = std.Target.Os.Tag.defaultVersionRange(.ios, arm, .none);
target.cpu = std.Target.Cpu.baseline(arm, target.os);
- target.abi = std.Target.Abi.default(arm, target.os);
+ target.abi = std.Target.Abi.default(arm, target.os.tag);
try std.testing.expect(!isTlsSupported(target));
try std.testing.expect(ignoreNonZeroSizedBitfieldTypeAlignment(target));
diff --git a/lib/compiler_rt/int_from_float.zig b/lib/compiler_rt/int_from_float.zig
index 7bbcd90893..0c2c73bb42 100644
--- a/lib/compiler_rt/int_from_float.zig
+++ b/lib/compiler_rt/int_from_float.zig
@@ -72,10 +72,12 @@ pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, resul
} });
const parts = math.frexp(a);
- const exponent = @max(parts.exponent - significand_bits, 0);
+ const significand_bits_adjusted_to_handle_smin = @as(i32, significand_bits) +
+ @intFromBool(signedness == .signed and parts.exponent == 32 * result.len);
+ const exponent = @max(parts.exponent - significand_bits_adjusted_to_handle_smin, 0);
const int: I = @intFromFloat(switch (exponent) {
0 => a,
- else => math.ldexp(parts.significand, significand_bits),
+ else => math.ldexp(parts.significand, significand_bits_adjusted_to_handle_smin),
});
switch (signedness) {
.signed => {
diff --git a/lib/compiler_rt/int_from_float_test.zig b/lib/compiler_rt/int_from_float_test.zig
index e10ed1ec00..5305ecf2a0 100644
--- a/lib/compiler_rt/int_from_float_test.zig
+++ b/lib/compiler_rt/int_from_float_test.zig
@@ -24,6 +24,8 @@ const __fixdfdi = @import("fixdfdi.zig").__fixdfdi;
const __fixunsdfdi = @import("fixunsdfdi.zig").__fixunsdfdi;
const __fixdfti = @import("fixdfti.zig").__fixdfti;
const __fixunsdfti = @import("fixunsdfti.zig").__fixunsdfti;
+const __fixdfei = @import("fixdfei.zig").__fixdfei;
+const __fixunsdfei = @import("fixunsdfei.zig").__fixunsdfei;
// Conversion from f128
const __fixtfsi = @import("fixtfsi.zig").__fixtfsi;
@@ -681,6 +683,44 @@ test "fixunsdfti" {
try test__fixunsdfti(-0x1.FFFFFFFFFFFFEp+62, 0);
}
+fn test_fixdfei(comptime T: type, expected: T, a: f64) !void {
+ const int = @typeInfo(T).int;
+ var expected_buf: [@divExact(int.bits, 32)]u32 = undefined;
+ std.mem.writeInt(T, std.mem.asBytes(&expected_buf), expected, endian);
+ var actual_buf: [@divExact(int.bits, 32)]u32 = undefined;
+ _ = switch (int.signedness) {
+ .signed => __fixdfei,
+ .unsigned => __fixunsdfei,
+ }(&actual_buf, int.bits, a);
+ try testing.expect(std.mem.eql(u32, &expected_buf, &actual_buf));
+}
+
+test "fixdfei" {
+ try test_fixdfei(i256, -1 << 255, -0x1p255);
+ try test_fixdfei(i256, -1 << 127, -0x1p127);
+ try test_fixdfei(i256, -1 << 100, -0x1p100);
+ try test_fixdfei(i256, -1 << 50, -0x1p50);
+ try test_fixdfei(i256, -1 << 1, -0x1p1);
+ try test_fixdfei(i256, -1 << 0, -0x1p0);
+ try test_fixdfei(i256, 0, 0);
+ try test_fixdfei(i256, 1 << 0, 0x1p0);
+ try test_fixdfei(i256, 1 << 1, 0x1p1);
+ try test_fixdfei(i256, 1 << 50, 0x1p50);
+ try test_fixdfei(i256, 1 << 100, 0x1p100);
+ try test_fixdfei(i256, 1 << 127, 0x1p127);
+ try test_fixdfei(i256, 1 << 254, 0x1p254);
+}
+
+test "fixundfei" {
+ try test_fixdfei(u256, 0, 0);
+ try test_fixdfei(u256, 1 << 0, 0x1p0);
+ try test_fixdfei(u256, 1 << 1, 0x1p1);
+ try test_fixdfei(u256, 1 << 50, 0x1p50);
+ try test_fixdfei(u256, 1 << 100, 0x1p100);
+ try test_fixdfei(u256, 1 << 127, 0x1p127);
+ try test_fixdfei(u256, 1 << 255, 0x1p255);
+}
+
fn test__fixtfsi(a: f128, expected: i32) !void {
const x = __fixtfsi(a);
try testing.expect(x == expected);
diff --git a/lib/std/Build/Cache.zig b/lib/std/Build/Cache.zig
index 24edee37a8..932ec00517 100644
--- a/lib/std/Build/Cache.zig
+++ b/lib/std/Build/Cache.zig
@@ -1254,11 +1254,6 @@ fn testGetCurrentFileTimestamp(dir: fs.Dir) !i128 {
}
test "cache file and then recall it" {
- if (builtin.os.tag == .wasi) {
- // https://github.com/ziglang/zig/issues/5437
- return error.SkipZigTest;
- }
-
var tmp = testing.tmpDir(.{});
defer tmp.cleanup();
@@ -1320,11 +1315,6 @@ test "cache file and then recall it" {
}
test "check that changing a file makes cache fail" {
- if (builtin.os.tag == .wasi) {
- // https://github.com/ziglang/zig/issues/5437
- return error.SkipZigTest;
- }
-
var tmp = testing.tmpDir(.{});
defer tmp.cleanup();
@@ -1394,11 +1384,6 @@ test "check that changing a file makes cache fail" {
}
test "no file inputs" {
- if (builtin.os.tag == .wasi) {
- // https://github.com/ziglang/zig/issues/5437
- return error.SkipZigTest;
- }
-
var tmp = testing.tmpDir(.{});
defer tmp.cleanup();
@@ -1442,11 +1427,6 @@ test "no file inputs" {
}
test "Manifest with files added after initial hash work" {
- if (builtin.os.tag == .wasi) {
- // https://github.com/ziglang/zig/issues/5437
- return error.SkipZigTest;
- }
-
var tmp = testing.tmpDir(.{});
defer tmp.cleanup();
diff --git a/lib/std/Target.zig b/lib/std/Target.zig
index 8e78e4dc29..79a78a41df 100644
--- a/lib/std/Target.zig
+++ b/lib/std/Target.zig
@@ -803,8 +803,8 @@ pub const Abi = enum {
// - raygeneration
// - vertex
- pub fn default(arch: Cpu.Arch, os: Os) Abi {
- return switch (os.tag) {
+ pub fn default(arch: Cpu.Arch, os_tag: Os.Tag) Abi {
+ return switch (os_tag) {
.freestanding, .other => switch (arch) {
// Soft float is usually a sane default for freestanding.
.arm,
diff --git a/lib/std/Target/Query.zig b/lib/std/Target/Query.zig
index 2d5c734108..cf53a8175b 100644
--- a/lib/std/Target/Query.zig
+++ b/lib/std/Target/Query.zig
@@ -102,7 +102,7 @@ pub fn fromTarget(target: Target) Query {
.os_version_min = undefined,
.os_version_max = undefined,
.abi = target.abi,
- .glibc_version = target.os.versionRange().gnuLibCVersion(),
+ .glibc_version = if (target.abi.isGnu()) target.os.versionRange().gnuLibCVersion() else null,
.android_api_level = if (target.abi.isAndroid()) target.os.version_range.linux.android else null,
};
result.updateOsVersionRange(target.os);
diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig
index 27b2b11c4a..fe3bf0fcea 100644
--- a/lib/std/Thread.zig
+++ b/lib/std/Thread.zig
@@ -122,6 +122,8 @@ pub const max_name_len = switch (native_os) {
.openbsd => 23,
.dragonfly => 1023,
.solaris, .illumos => 31,
+ // https://github.com/SerenityOS/serenity/blob/6b4c300353da49d3508b5442cf61da70bd04d757/Kernel/Tasks/Thread.h#L102
+ .serenity => 63,
else => 0,
};
@@ -201,6 +203,15 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void {
else => |e| return posix.unexpectedErrno(e),
}
},
+ .serenity => if (use_pthreads) {
+ const err = std.c.pthread_setname_np(self.getHandle(), name_with_terminator.ptr);
+ switch (@as(posix.E, @enumFromInt(err))) {
+ .SUCCESS => return,
+ .NAMETOOLONG => unreachable,
+ .SRCH => unreachable,
+ else => |e| return posix.unexpectedErrno(e),
+ }
+ },
.netbsd, .solaris, .illumos => if (use_pthreads) {
const err = std.c.pthread_setname_np(self.getHandle(), name_with_terminator.ptr, null);
switch (@as(posix.E, @enumFromInt(err))) {
@@ -302,6 +313,16 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co
else => |e| return posix.unexpectedErrno(e),
}
},
+ .serenity => if (use_pthreads) {
+ const err = std.c.pthread_getname_np(self.getHandle(), buffer.ptr, max_name_len + 1);
+ switch (@as(posix.E, @enumFromInt(err))) {
+ .SUCCESS => return,
+ .NAMETOOLONG => unreachable,
+ .SRCH => unreachable,
+ .FAULT => unreachable,
+ else => |e| return posix.unexpectedErrno(e),
+ }
+ },
.netbsd, .solaris, .illumos => if (use_pthreads) {
const err = std.c.pthread_getname_np(self.getHandle(), buffer.ptr, max_name_len + 1);
switch (@as(posix.E, @enumFromInt(err))) {
@@ -342,6 +363,7 @@ pub const Id = switch (native_os) {
.openbsd,
.haiku,
.wasi,
+ .serenity,
=> u32,
.macos, .ios, .watchos, .tvos, .visionos => u64,
.windows => windows.DWORD,
@@ -692,6 +714,9 @@ const PosixThreadImpl = struct {
.haiku => {
return @as(u32, @bitCast(c.find_thread(null)));
},
+ .serenity => {
+ return @as(u32, @bitCast(c.pthread_self()));
+ },
else => {
return @intFromPtr(c.pthread_self());
},
@@ -713,11 +738,11 @@ const PosixThreadImpl = struct {
};
return @as(usize, @intCast(count));
},
- .solaris, .illumos => {
+ .solaris, .illumos, .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.
- const rc = c.sysconf(std.c._SC.NPROCESSORS_ONLN);
+ // cpu. (solaris, illumos)
+ const rc = c.sysconf(@intFromEnum(std.c._SC.NPROCESSORS_ONLN));
return switch (posix.errno(rc)) {
.SUCCESS => @as(usize, @intCast(rc)),
else => |err| posix.unexpectedErrno(err),
diff --git a/lib/std/array_list.zig b/lib/std/array_list.zig
index 7849e98b42..bedba88a73 100644
--- a/lib/std/array_list.zig
+++ b/lib/std/array_list.zig
@@ -50,19 +50,19 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
}
/// Deinitialize with `deinit` or use `toOwnedSlice`.
- pub fn init(allocator: Allocator) Self {
+ pub fn init(gpa: Allocator) Self {
return Self{
.items = &[_]T{},
.capacity = 0,
- .allocator = allocator,
+ .allocator = gpa,
};
}
/// Initialize with capacity to hold `num` elements.
/// The resulting capacity will equal `num` exactly.
/// Deinitialize with `deinit` or use `toOwnedSlice`.
- pub fn initCapacity(allocator: Allocator, num: usize) Allocator.Error!Self {
- var self = Self.init(allocator);
+ pub fn initCapacity(gpa: Allocator, num: usize) Allocator.Error!Self {
+ var self = Self.init(gpa);
try self.ensureTotalCapacityPrecise(num);
return self;
}
@@ -75,24 +75,24 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
}
/// ArrayList takes ownership of the passed in slice. The slice must have been
- /// allocated with `allocator`.
+ /// allocated with `gpa`.
/// Deinitialize with `deinit` or use `toOwnedSlice`.
- pub fn fromOwnedSlice(allocator: Allocator, slice: Slice) Self {
+ pub fn fromOwnedSlice(gpa: Allocator, slice: Slice) Self {
return Self{
.items = slice,
.capacity = slice.len,
- .allocator = allocator,
+ .allocator = gpa,
};
}
/// ArrayList takes ownership of the passed in slice. The slice must have been
- /// allocated with `allocator`.
+ /// allocated with `gpa`.
/// Deinitialize with `deinit` or use `toOwnedSlice`.
- pub fn fromOwnedSliceSentinel(allocator: Allocator, comptime sentinel: T, slice: [:sentinel]T) Self {
+ pub fn fromOwnedSliceSentinel(gpa: Allocator, comptime sentinel: T, slice: [:sentinel]T) Self {
return Self{
.items = slice,
.capacity = slice.len + 1,
- .allocator = allocator,
+ .allocator = gpa,
};
}
@@ -646,9 +646,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
/// Initialize with capacity to hold `num` elements.
/// The resulting capacity will equal `num` exactly.
/// Deinitialize with `deinit` or use `toOwnedSlice`.
- pub fn initCapacity(allocator: Allocator, num: usize) Allocator.Error!Self {
+ pub fn initCapacity(gpa: Allocator, num: usize) Allocator.Error!Self {
var self = Self{};
- try self.ensureTotalCapacityPrecise(allocator, num);
+ try self.ensureTotalCapacityPrecise(gpa, num);
return self;
}
@@ -664,19 +664,18 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
}
/// Release all allocated memory.
- pub fn deinit(self: *Self, allocator: Allocator) void {
- allocator.free(self.allocatedSlice());
+ pub fn deinit(self: *Self, gpa: Allocator) void {
+ gpa.free(self.allocatedSlice());
self.* = undefined;
}
/// Convert this list into an analogous memory-managed one.
/// The returned list has ownership of the underlying memory.
- pub fn toManaged(self: *Self, allocator: Allocator) ArrayListAligned(T, alignment) {
- return .{ .items = self.items, .capacity = self.capacity, .allocator = allocator };
+ pub fn toManaged(self: *Self, gpa: Allocator) ArrayListAligned(T, alignment) {
+ return .{ .items = self.items, .capacity = self.capacity, .allocator = gpa };
}
- /// ArrayListUnmanaged takes ownership of the passed in slice. The slice must have been
- /// allocated with `allocator`.
+ /// ArrayListUnmanaged takes ownership of the passed in slice.
/// Deinitialize with `deinit` or use `toOwnedSlice`.
pub fn fromOwnedSlice(slice: Slice) Self {
return Self{
@@ -685,8 +684,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
};
}
- /// ArrayListUnmanaged takes ownership of the passed in slice. The slice must have been
- /// allocated with `allocator`.
+ /// ArrayListUnmanaged takes ownership of the passed in slice.
/// Deinitialize with `deinit` or use `toOwnedSlice`.
pub fn fromOwnedSliceSentinel(comptime sentinel: T, slice: [:sentinel]T) Self {
return Self{
@@ -697,31 +695,31 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
/// The caller owns the returned memory. Empties this ArrayList.
/// Its capacity is cleared, making deinit() safe but unnecessary to call.
- pub fn toOwnedSlice(self: *Self, allocator: Allocator) Allocator.Error!Slice {
+ pub fn toOwnedSlice(self: *Self, gpa: Allocator) Allocator.Error!Slice {
const old_memory = self.allocatedSlice();
- if (allocator.remap(old_memory, self.items.len)) |new_items| {
+ if (gpa.remap(old_memory, self.items.len)) |new_items| {
self.* = .empty;
return new_items;
}
- const new_memory = try allocator.alignedAlloc(T, alignment, self.items.len);
+ const new_memory = try gpa.alignedAlloc(T, alignment, self.items.len);
@memcpy(new_memory, self.items);
- self.clearAndFree(allocator);
+ self.clearAndFree(gpa);
return new_memory;
}
/// The caller owns the returned memory. ArrayList becomes empty.
- pub fn toOwnedSliceSentinel(self: *Self, allocator: Allocator, comptime sentinel: T) Allocator.Error!SentinelSlice(sentinel) {
+ pub fn toOwnedSliceSentinel(self: *Self, gpa: Allocator, comptime sentinel: T) Allocator.Error!SentinelSlice(sentinel) {
// This addition can never overflow because `self.items` can never occupy the whole address space
- try self.ensureTotalCapacityPrecise(allocator, self.items.len + 1);
+ try self.ensureTotalCapacityPrecise(gpa, self.items.len + 1);
self.appendAssumeCapacity(sentinel);
- const result = try self.toOwnedSlice(allocator);
+ const result = try self.toOwnedSlice(gpa);
return result[0 .. result.len - 1 :sentinel];
}
/// Creates a copy of this ArrayList.
- pub fn clone(self: Self, allocator: Allocator) Allocator.Error!Self {
- var cloned = try Self.initCapacity(allocator, self.capacity);
+ pub fn clone(self: Self, gpa: Allocator) Allocator.Error!Self {
+ var cloned = try Self.initCapacity(gpa, self.capacity);
cloned.appendSliceAssumeCapacity(self.items);
return cloned;
}
@@ -731,8 +729,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
/// This operation is O(N).
/// Invalidates element pointers if additional memory is needed.
/// Asserts that the index is in bounds or equal to the length.
- pub fn insert(self: *Self, allocator: Allocator, i: usize, item: T) Allocator.Error!void {
- const dst = try self.addManyAt(allocator, i, 1);
+ pub fn insert(self: *Self, gpa: Allocator, i: usize, item: T) Allocator.Error!void {
+ const dst = try self.addManyAt(gpa, i, 1);
dst[0] = item;
}
@@ -759,11 +757,11 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
/// Asserts that the index is in bounds or equal to the length.
pub fn addManyAt(
self: *Self,
- allocator: Allocator,
+ gpa: Allocator,
index: usize,
count: usize,
) Allocator.Error![]T {
- var managed = self.toManaged(allocator);
+ var managed = self.toManaged(gpa);
defer self.* = managed.moveToUnmanaged();
return managed.addManyAt(index, count);
}
@@ -795,12 +793,12 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
/// Asserts that the index is in bounds or equal to the length.
pub fn insertSlice(
self: *Self,
- allocator: Allocator,
+ gpa: Allocator,
index: usize,
items: []const T,
) Allocator.Error!void {
const dst = try self.addManyAt(
- allocator,
+ gpa,
index,
items.len,
);
@@ -812,7 +810,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
/// Asserts that the range is in bounds.
pub fn replaceRange(
self: *Self,
- allocator: Allocator,
+ gpa: Allocator,
start: usize,
len: usize,
new_items: []const T,
@@ -823,7 +821,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
const first = new_items[0..range.len];
const rest = new_items[range.len..];
@memcpy(range[0..first.len], first);
- try self.insertSlice(allocator, after_range, rest);
+ try self.insertSlice(gpa, after_range, rest);
} else {
self.replaceRangeAssumeCapacity(start, len, new_items);
}
@@ -859,8 +857,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
/// Extend the list by 1 element. Allocates more memory as necessary.
/// Invalidates element pointers if additional memory is needed.
- pub fn append(self: *Self, allocator: Allocator, item: T) Allocator.Error!void {
- const new_item_ptr = try self.addOne(allocator);
+ pub fn append(self: *Self, gpa: Allocator, item: T) Allocator.Error!void {
+ const new_item_ptr = try self.addOne(gpa);
new_item_ptr.* = item;
}
@@ -899,8 +897,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
/// Append the slice of items to the list. Allocates more
/// memory as necessary.
/// Invalidates element pointers if additional memory is needed.
- pub fn appendSlice(self: *Self, allocator: Allocator, items: []const T) Allocator.Error!void {
- try self.ensureUnusedCapacity(allocator, items.len);
+ pub fn appendSlice(self: *Self, gpa: Allocator, items: []const T) Allocator.Error!void {
+ try self.ensureUnusedCapacity(gpa, items.len);
self.appendSliceAssumeCapacity(items);
}
@@ -918,8 +916,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
/// memory as necessary. Only call this function if a call to `appendSlice` instead would
/// be a compile error.
/// Invalidates element pointers if additional memory is needed.
- pub fn appendUnalignedSlice(self: *Self, allocator: Allocator, items: []align(1) const T) Allocator.Error!void {
- try self.ensureUnusedCapacity(allocator, items.len);
+ pub fn appendUnalignedSlice(self: *Self, gpa: Allocator, items: []align(1) const T) Allocator.Error!void {
+ try self.ensureUnusedCapacity(gpa, items.len);
self.appendUnalignedSliceAssumeCapacity(items);
}
@@ -947,8 +945,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
std.io.Writer(WriterContext, Allocator.Error, appendWrite);
/// Initializes a Writer which will append to the list.
- pub fn writer(self: *Self, allocator: Allocator) Writer {
- return .{ .context = .{ .self = self, .allocator = allocator } };
+ pub fn writer(self: *Self, gpa: Allocator) Writer {
+ return .{ .context = .{ .self = self, .allocator = gpa } };
}
/// Same as `append` except it returns the number of bytes written,
@@ -983,9 +981,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
/// Invalidates element pointers if additional memory is needed.
/// The function is inline so that a comptime-known `value` parameter will
/// have a more optimal memset codegen in case it has a repeated byte pattern.
- pub inline fn appendNTimes(self: *Self, allocator: Allocator, value: T, n: usize) Allocator.Error!void {
+ pub inline fn appendNTimes(self: *Self, gpa: Allocator, value: T, n: usize) Allocator.Error!void {
const old_len = self.items.len;
- try self.resize(allocator, try addOrOom(old_len, n));
+ try self.resize(gpa, try addOrOom(old_len, n));
@memset(self.items[old_len..self.items.len], value);
}
@@ -1004,15 +1002,15 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
/// Adjust the list length to `new_len`.
/// Additional elements contain the value `undefined`.
/// Invalidates element pointers if additional memory is needed.
- pub fn resize(self: *Self, allocator: Allocator, new_len: usize) Allocator.Error!void {
- try self.ensureTotalCapacity(allocator, new_len);
+ pub fn resize(self: *Self, gpa: Allocator, new_len: usize) Allocator.Error!void {
+ try self.ensureTotalCapacity(gpa, new_len);
self.items.len = new_len;
}
/// Reduce allocated capacity to `new_len`.
/// May invalidate element pointers.
/// Asserts that the new length is less than or equal to the previous length.
- pub fn shrinkAndFree(self: *Self, allocator: Allocator, new_len: usize) void {
+ pub fn shrinkAndFree(self: *Self, gpa: Allocator, new_len: usize) void {
assert(new_len <= self.items.len);
if (@sizeOf(T) == 0) {
@@ -1021,13 +1019,13 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
}
const old_memory = self.allocatedSlice();
- if (allocator.remap(old_memory, new_len)) |new_items| {
+ if (gpa.remap(old_memory, new_len)) |new_items| {
self.capacity = new_items.len;
self.items = new_items;
return;
}
- const new_memory = allocator.alignedAlloc(T, alignment, new_len) catch |e| switch (e) {
+ const new_memory = gpa.alignedAlloc(T, alignment, new_len) catch |e| switch (e) {
error.OutOfMemory => {
// No problem, capacity is still correct then.
self.items.len = new_len;
@@ -1036,7 +1034,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
};
@memcpy(new_memory, self.items[0..new_len]);
- allocator.free(old_memory);
+ gpa.free(old_memory);
self.items = new_memory;
self.capacity = new_memory.len;
}
@@ -1056,8 +1054,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
}
/// Invalidates all element pointers.
- pub fn clearAndFree(self: *Self, allocator: Allocator) void {
- allocator.free(self.allocatedSlice());
+ pub fn clearAndFree(self: *Self, gpa: Allocator) void {
+ gpa.free(self.allocatedSlice());
self.items.len = 0;
self.capacity = 0;
}
@@ -1073,7 +1071,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
/// If the current capacity is less than `new_capacity`, this function will
/// modify the array so that it can hold exactly `new_capacity` items.
/// Invalidates element pointers if additional memory is needed.
- pub fn ensureTotalCapacityPrecise(self: *Self, allocator: Allocator, new_capacity: usize) Allocator.Error!void {
+ pub fn ensureTotalCapacityPrecise(self: *Self, gpa: Allocator, new_capacity: usize) Allocator.Error!void {
if (@sizeOf(T) == 0) {
self.capacity = math.maxInt(usize);
return;
@@ -1087,13 +1085,13 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
// the allocator implementation would pointlessly copy our
// extra capacity.
const old_memory = self.allocatedSlice();
- if (allocator.remap(old_memory, new_capacity)) |new_memory| {
+ if (gpa.remap(old_memory, new_capacity)) |new_memory| {
self.items.ptr = new_memory.ptr;
self.capacity = new_memory.len;
} else {
- const new_memory = try allocator.alignedAlloc(T, alignment, new_capacity);
+ const new_memory = try gpa.alignedAlloc(T, alignment, new_capacity);
@memcpy(new_memory[0..self.items.len], self.items);
- allocator.free(old_memory);
+ gpa.free(old_memory);
self.items.ptr = new_memory.ptr;
self.capacity = new_memory.len;
}
@@ -1103,10 +1101,10 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
/// Invalidates element pointers if additional memory is needed.
pub fn ensureUnusedCapacity(
self: *Self,
- allocator: Allocator,
+ gpa: Allocator,
additional_count: usize,
) Allocator.Error!void {
- return self.ensureTotalCapacity(allocator, try addOrOom(self.items.len, additional_count));
+ return self.ensureTotalCapacity(gpa, try addOrOom(self.items.len, additional_count));
}
/// Increases the array's length to match the full capacity that is already allocated.
@@ -1118,10 +1116,10 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
/// Increase length by 1, returning pointer to the new item.
/// The returned element pointer becomes invalid when the list is resized.
- pub fn addOne(self: *Self, allocator: Allocator) Allocator.Error!*T {
+ pub fn addOne(self: *Self, gpa: Allocator) Allocator.Error!*T {
// This can never overflow because `self.items` can never occupy the whole address space
const newlen = self.items.len + 1;
- try self.ensureTotalCapacity(allocator, newlen);
+ try self.ensureTotalCapacity(gpa, newlen);
return self.addOneAssumeCapacity();
}
@@ -1139,9 +1137,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
/// Resize the array, adding `n` new elements, which have `undefined` values.
/// The return value is an array pointing to the newly allocated elements.
/// The returned pointer becomes invalid when the list is resized.
- pub fn addManyAsArray(self: *Self, allocator: Allocator, comptime n: usize) Allocator.Error!*[n]T {
+ pub fn addManyAsArray(self: *Self, gpa: Allocator, comptime n: usize) Allocator.Error!*[n]T {
const prev_len = self.items.len;
- try self.resize(allocator, try addOrOom(self.items.len, n));
+ try self.resize(gpa, try addOrOom(self.items.len, n));
return self.items[prev_len..][0..n];
}
@@ -1161,9 +1159,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
/// The return value is a slice pointing to the newly allocated elements.
/// The returned pointer becomes invalid when the list is resized.
/// Resizes list if `self.capacity` is not large enough.
- pub fn addManyAsSlice(self: *Self, allocator: Allocator, n: usize) Allocator.Error![]T {
+ pub fn addManyAsSlice(self: *Self, gpa: Allocator, n: usize) Allocator.Error![]T {
const prev_len = self.items.len;
- try self.resize(allocator, try addOrOom(self.items.len, n));
+ try self.resize(gpa, try addOrOom(self.items.len, n));
return self.items[prev_len..][0..n];
}
diff --git a/lib/std/c.zig b/lib/std/c.zig
index 9b7d36cb32..53cd75f789 100644
--- a/lib/std/c.zig
+++ b/lib/std/c.zig
@@ -19,6 +19,7 @@ const netbsd = @import("c/netbsd.zig");
const dragonfly = @import("c/dragonfly.zig");
const haiku = @import("c/haiku.zig");
const openbsd = @import("c/openbsd.zig");
+const serenity = @import("c/serenity.zig");
// These constants are shared among all operating systems even when not linking
// libc.
@@ -75,12 +76,14 @@ pub const ino_t = switch (native_os) {
.wasi => wasi.inode_t,
.windows => windows.LARGE_INTEGER,
.haiku => i64,
+ // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L38
else => u64,
};
pub const off_t = switch (native_os) {
.linux => linux.off_t,
.emscripten => emscripten.off_t,
+ // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L39
else => i64,
};
@@ -105,7 +108,8 @@ pub const timespec = switch (native_os) {
@as(wasi.timestamp_t, @intCast(ts.nsec));
}
},
- .windows => extern struct {
+ // https://github.com/SerenityOS/serenity/blob/0a78056453578c18e0a04a0b45ebfb1c96d59005/Kernel/API/POSIX/time.h#L17-L20
+ .windows, .serenity => extern struct {
sec: time_t,
nsec: c_long,
},
@@ -129,7 +133,8 @@ pub const dev_t = switch (native_os) {
.emscripten => emscripten.dev_t,
.wasi => wasi.device_t,
.openbsd, .haiku, .solaris, .illumos, .macos, .ios, .tvos, .watchos, .visionos => i32,
- .netbsd, .freebsd => u64,
+ // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L43
+ .netbsd, .freebsd, .serenity => u64,
else => void,
};
@@ -137,7 +142,8 @@ pub const mode_t = switch (native_os) {
.linux => linux.mode_t,
.emscripten => emscripten.mode_t,
.openbsd, .haiku, .netbsd, .solaris, .illumos, .wasi, .windows => u32,
- .freebsd, .macos, .ios, .tvos, .watchos, .visionos, .dragonfly => u16,
+ // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L44
+ .freebsd, .macos, .ios, .tvos, .watchos, .visionos, .dragonfly, .serenity => u16,
else => u0,
};
@@ -145,7 +151,8 @@ pub const nlink_t = switch (native_os) {
.linux => linux.nlink_t,
.emscripten => emscripten.nlink_t,
.wasi => c_ulonglong,
- .freebsd => u64,
+ // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L45
+ .freebsd, .serenity => u64,
.openbsd, .netbsd, .solaris, .illumos => u32,
.haiku => i32,
else => void,
@@ -154,12 +161,14 @@ pub const nlink_t = switch (native_os) {
pub const uid_t = switch (native_os) {
.linux => linux.uid_t,
.emscripten => emscripten.uid_t,
+ // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L28
else => u32,
};
pub const gid_t = switch (native_os) {
.linux => linux.gid_t,
.emscripten => emscripten.gid_t,
+ // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L29
else => u32,
};
@@ -167,11 +176,14 @@ pub const blksize_t = switch (native_os) {
.linux => linux.blksize_t,
.emscripten => emscripten.blksize_t,
.wasi => c_long,
+ // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L42
+ .serenity => u64,
else => i32,
};
pub const passwd = switch (native_os) {
- .linux => extern struct {
+ // https://github.com/SerenityOS/serenity/blob/7442cfb5072b74a62c0e061e6e9ff44fda08780d/Userland/Libraries/LibC/pwd.h#L15-L23
+ .linux, .serenity => extern struct {
name: ?[*:0]const u8, // username
passwd: ?[*:0]const u8, // user password
uid: uid_t, // user ID
@@ -199,6 +211,8 @@ pub const blkcnt_t = switch (native_os) {
.linux => linux.blkcnt_t,
.emscripten => emscripten.blkcnt_t,
.wasi => c_longlong,
+ // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L41
+ .serenity => u64,
else => i64,
};
@@ -206,6 +220,7 @@ pub const fd_t = switch (native_os) {
.linux => linux.fd_t,
.wasi => wasi.fd_t,
.windows => windows.HANDLE,
+ .serenity => c_int,
else => i32,
};
@@ -309,6 +324,14 @@ pub const clockid_t = switch (native_os) {
MONOTONIC = 3,
THREAD_CPUTIME_ID = 4,
},
+ // https://github.com/SerenityOS/serenity/blob/0a78056453578c18e0a04a0b45ebfb1c96d59005/Kernel/API/POSIX/time.h#L24-L36
+ .serenity => enum(c_int) {
+ REALTIME = 0,
+ MONOTONIC = 1,
+ MONOTONIC_RAW = 2,
+ REALTIME_COARSE = 3,
+ MONOTONIC_COARSE = 4,
+ },
else => void,
};
pub const CPU_COUNT = switch (native_os) {
@@ -681,6 +704,93 @@ pub const E = switch (native_os) {
.dragonfly => dragonfly.E,
.haiku => haiku.E,
.openbsd => openbsd.E,
+ // https://github.com/SerenityOS/serenity/blob/dd59fe35c7e5bbaf6b6b3acb3f9edc56619d4b66/Kernel/API/POSIX/errno.h
+ .serenity => enum(c_int) {
+ SUCCESS = 0,
+ PERM = 1,
+ NOENT = 2,
+ SRCH = 3,
+ INTR = 4,
+ IO = 5,
+ NXIO = 6,
+ @"2BIG" = 7,
+ NOEXEC = 8,
+ BADF = 9,
+ CHILD = 10,
+ AGAIN = 11,
+ NOMEM = 12,
+ ACCES = 13,
+ FAULT = 14,
+ NOTBLK = 15,
+ BUSY = 16,
+ EXIST = 17,
+ XDEV = 18,
+ NODEV = 19,
+ NOTDIR = 20,
+ ISDIR = 21,
+ INVAL = 22,
+ NFILE = 23,
+ MFILE = 24,
+ NOTTY = 25,
+ TXTBSY = 26,
+ FBIG = 27,
+ NOSPC = 28,
+ SPIPE = 29,
+ ROFS = 30,
+ MLINK = 31,
+ PIPE = 32,
+ RANGE = 33,
+ NAMETOOLONG = 34,
+ LOOP = 35,
+ OVERFLOW = 36,
+ OPNOTSUPP = 37,
+ NOSYS = 38,
+ NOTIMPL = 39,
+ AFNOSUPPORT = 40,
+ NOTSOCK = 41,
+ ADDRINUSE = 42,
+ NOTEMPTY = 43,
+ DOM = 44,
+ CONNREFUSED = 45,
+ HOSTDOWN = 46,
+ ADDRNOTAVAIL = 47,
+ ISCONN = 48,
+ CONNABORTED = 49,
+ ALREADY = 50,
+ CONNRESET = 51,
+ DESTADDRREQ = 52,
+ HOSTUNREACH = 53,
+ ILSEQ = 54,
+ MSGSIZE = 55,
+ NETDOWN = 56,
+ NETUNREACH = 57,
+ NETRESET = 58,
+ NOBUFS = 59,
+ NOLCK = 60,
+ NOMSG = 61,
+ NOPROTOOPT = 62,
+ NOTCONN = 63,
+ SHUTDOWN = 64,
+ TOOMANYREFS = 65,
+ SOCKTNOSUPPORT = 66,
+ PROTONOSUPPORT = 67,
+ DEADLK = 68,
+ TIMEDOUT = 69,
+ PROTOTYPE = 70,
+ INPROGRESS = 71,
+ NOTHREAD = 72,
+ PROTO = 73,
+ NOTSUP = 74,
+ PFNOSUPPORT = 75,
+ DIRINTOSELF = 76,
+ DQUOT = 77,
+ NOTRECOVERABLE = 78,
+ CANCELED = 79,
+ PROMISEVIOLATION = 80,
+ STALE = 81,
+ SRCNOTFOUND = 82,
+ _,
+ },
else => void,
};
pub const Elf_Symndx = switch (native_os) {
@@ -1054,6 +1164,24 @@ pub const F = switch (native_os) {
pub const UNLCK = 2;
pub const WRLCK = 3;
},
+ .serenity => struct {
+ // https://github.com/SerenityOS/serenity/blob/2808b0376406a40e31293bb3bcb9170374e90506/Kernel/API/POSIX/fcntl.h#L15-L24
+ pub const DUPFD = 0;
+ pub const GETFD = 1;
+ pub const SETFD = 2;
+ pub const GETFL = 3;
+ pub const SETFL = 4;
+ pub const ISTTY = 5;
+ pub const GETLK = 6;
+ pub const SETLK = 7;
+ pub const SETLKW = 8;
+ pub const DUPFD_CLOEXEC = 9;
+
+ // https://github.com/SerenityOS/serenity/blob/2808b0376406a40e31293bb3bcb9170374e90506/Kernel/API/POSIX/fcntl.h#L45-L47
+ pub const RDLCK = 0;
+ pub const WRLCK = 1;
+ pub const UNLCK = 2;
+ },
else => void,
};
pub const FD_CLOEXEC = switch (native_os) {
@@ -1129,18 +1257,29 @@ pub const Flock = switch (native_os) {
len: off_t,
pid: pid_t,
},
+ // https://github.com/SerenityOS/serenity/blob/2808b0376406a40e31293bb3bcb9170374e90506/Kernel/API/POSIX/fcntl.h#L54-L60
+ .serenity => extern struct {
+ type: c_short,
+ whence: c_short,
+ start: off_t,
+ len: off_t,
+ pid: pid_t,
+ },
else => void,
};
pub const HOST_NAME_MAX = switch (native_os) {
.linux => linux.HOST_NAME_MAX,
.macos, .ios, .tvos, .watchos, .visionos => 72,
.openbsd, .haiku, .dragonfly, .netbsd, .solaris, .illumos, .freebsd => 255,
+ // https://github.com/SerenityOS/serenity/blob/c87557e9c1865fa1a6440de34ff6ce6fc858a2b7/Kernel/API/POSIX/sys/limits.h#L22
+ .serenity => 64,
else => {},
};
pub const IOV_MAX = switch (native_os) {
.linux => linux.IOV_MAX,
.emscripten => emscripten.IOV_MAX,
- .openbsd, .haiku, .solaris, .illumos, .wasi => 1024,
+ // https://github.com/SerenityOS/serenity/blob/098af0f846a87b651731780ff48420205fd33754/Kernel/API/POSIX/sys/uio.h#L16
+ .openbsd, .haiku, .solaris, .illumos, .wasi, .serenity => 1024,
.macos, .ios, .tvos, .watchos, .visionos => 16,
.dragonfly, .netbsd, .freebsd => KERN.IOV_MAX,
else => {},
@@ -1425,6 +1564,16 @@ pub const MADV = switch (native_os) {
pub const INVAL = 10;
pub const SETMAP = 11;
},
+ // https://github.com/SerenityOS/serenity/blob/6d59d4d3d9e76e39112842ec487840828f1c9bfe/Kernel/API/POSIX/sys/mman.h#L35-L41
+ .serenity => struct {
+ pub const NORMAL = 0x0;
+ pub const SET_VOLATILE = 0x1;
+ pub const SET_NONVOLATILE = 0x2;
+ pub const DONTNEED = 0x3;
+ pub const WILLNEED = 0x4;
+ pub const SEQUENTIAL = 0x5;
+ pub const RANDOM = 0x6;
+ },
else => void,
};
pub const MSF = switch (native_os) {
@@ -1444,6 +1593,12 @@ pub const MSF = switch (native_os) {
pub const INVALIDATE = 2;
pub const SYNC = 4;
},
+ // https://github.com/SerenityOS/serenity/blob/6d59d4d3d9e76e39112842ec487840828f1c9bfe/Kernel/API/POSIX/sys/mman.h#L50-L52
+ .serenity => struct {
+ pub const SYNC = 1;
+ pub const ASYNC = 2;
+ pub const INVALIDATE = 4;
+ },
else => void,
};
pub const MMAP2_UNIT = switch (native_os) {
@@ -1456,7 +1611,8 @@ pub const NAME_MAX = switch (native_os) {
// Haiku's headers make this 256, to contain room for the terminating null
// character, but POSIX definition says that NAME_MAX does not include the
// terminating null.
- .haiku, .openbsd, .dragonfly, .netbsd, .solaris, .illumos, .freebsd, .macos, .ios, .tvos, .watchos, .visionos => 255,
+ // https://github.com/SerenityOS/serenity/blob/c87557e9c1865fa1a6440de34ff6ce6fc858a2b7/Kernel/API/POSIX/sys/limits.h#L20
+ .haiku, .openbsd, .dragonfly, .netbsd, .solaris, .illumos, .freebsd, .macos, .ios, .tvos, .watchos, .visionos, .serenity => 255,
else => {},
};
pub const PATH_MAX = switch (native_os) {
@@ -1464,7 +1620,7 @@ pub const PATH_MAX = switch (native_os) {
.emscripten => emscripten.PATH_MAX,
.wasi => 4096,
.windows => 260,
- .openbsd, .haiku, .dragonfly, .netbsd, .solaris, .illumos, .freebsd, .macos, .ios, .tvos, .watchos, .visionos => 1024,
+ .openbsd, .haiku, .dragonfly, .netbsd, .solaris, .illumos, .freebsd, .macos, .ios, .tvos, .watchos, .visionos, .serenity => 1024,
else => {},
};
@@ -1597,6 +1753,19 @@ pub const POLL = switch (native_os) {
pub const RDBAND = 0x0080;
pub const WRBAND = 0x0100;
},
+ // https://github.com/SerenityOS/serenity/blob/265764ff2fec038855193296588a887fc322d76a/Kernel/API/POSIX/poll.h#L15-L24
+ .serenity => struct {
+ pub const IN = 0x0001;
+ pub const PRI = 0x0002;
+ pub const OUT = 0x0004;
+ pub const ERR = 0x0008;
+ pub const HUP = 0x0010;
+ pub const NVAL = 0x0020;
+ pub const RDNORM = IN;
+ pub const WRNORM = OUT;
+ pub const WRBAND = 0x1000;
+ pub const RDHUP = 0x2000;
+ },
else => void,
};
@@ -1604,7 +1773,8 @@ pub const POLL = switch (native_os) {
pub const PROT = switch (native_os) {
.linux => linux.PROT,
.emscripten => emscripten.PROT,
- .openbsd, .haiku, .dragonfly, .netbsd, .solaris, .illumos, .freebsd, .windows => struct {
+ // https://github.com/SerenityOS/serenity/blob/6d59d4d3d9e76e39112842ec487840828f1c9bfe/Kernel/API/POSIX/sys/mman.h#L28-L31
+ .openbsd, .haiku, .dragonfly, .netbsd, .solaris, .illumos, .freebsd, .windows, .serenity => struct {
/// page can not be accessed
pub const NONE = 0x0;
/// page can be read
@@ -1719,7 +1889,8 @@ pub const REG = switch (native_os) {
pub const RLIM = switch (native_os) {
.linux => linux.RLIM,
.emscripten => emscripten.RLIM,
- .openbsd, .haiku, .dragonfly, .netbsd, .freebsd, .macos, .ios, .tvos, .watchos, .visionos => struct {
+ // https://github.com/SerenityOS/serenity/blob/aae106e37b48f2158e68902293df1e4bf7b80c0f/Userland/Libraries/LibC/sys/resource.h#L52
+ .openbsd, .haiku, .dragonfly, .netbsd, .freebsd, .macos, .ios, .tvos, .watchos, .visionos, .serenity => struct {
/// No limit
pub const INFINITY: rlim_t = (1 << 63) - 1;
@@ -2174,6 +2345,66 @@ pub const S = switch (native_os) {
return m & IFMT == IFSOCK;
}
},
+ // https://github.com/SerenityOS/serenity/blob/ec492a1a0819e6239ea44156825c4ee7234ca3db/Kernel/API/POSIX/sys/stat.h#L16-L51
+ .serenity => struct {
+ pub const IFMT = 0o170000;
+ pub const IFDIR = 0o040000;
+ pub const IFCHR = 0o020000;
+ pub const IFBLK = 0o060000;
+ pub const IFREG = 0o100000;
+ pub const IFIFO = 0o010000;
+ pub const IFLNK = 0o120000;
+ pub const IFSOCK = 0o140000;
+
+ pub const ISUID = 0o4000;
+ pub const ISGID = 0o2000;
+ pub const ISVTX = 0o1000;
+ pub const IRUSR = 0o400;
+ pub const IWUSR = 0o200;
+ pub const IXUSR = 0o100;
+ pub const IREAD = IRUSR;
+ pub const IWRITE = IWUSR;
+ pub const IEXEC = IXUSR;
+ pub const IRGRP = 0o040;
+ pub const IWGRP = 0o020;
+ pub const IXGRP = 0o010;
+ pub const IROTH = 0o004;
+ pub const IWOTH = 0o002;
+ pub const IXOTH = 0o001;
+
+ pub const IRWXU = IRUSR | IWUSR | IXUSR;
+
+ pub const IRWXG = IRWXU >> 3;
+ pub const IRWXO = IRWXG >> 3;
+
+ pub fn ISDIR(m: u32) bool {
+ return m & IFMT == IFDIR;
+ }
+
+ pub fn ISCHR(m: u32) bool {
+ return m & IFMT == IFCHR;
+ }
+
+ pub fn ISBLK(m: u32) bool {
+ return m & IFMT == IFBLK;
+ }
+
+ pub fn ISREG(m: u32) bool {
+ return m & IFMT == IFREG;
+ }
+
+ pub fn ISFIFO(m: u32) bool {
+ return m & IFMT == IFIFO;
+ }
+
+ pub fn ISLNK(m: u32) bool {
+ return m & IFMT == IFLNK;
+ }
+
+ pub fn ISSOCK(m: u32) bool {
+ return m & IFMT == IFSOCK;
+ }
+ },
else => void,
};
pub const SA = switch (native_os) {
@@ -2254,6 +2485,18 @@ pub const SA = switch (native_os) {
pub const NOCLDWAIT = 0x0020;
pub const SIGINFO = 0x0040;
},
+ // https://github.com/SerenityOS/serenity/blob/ec492a1a0819e6239ea44156825c4ee7234ca3db/Kernel/API/POSIX/signal.h#L65-L71
+ .serenity => struct {
+ pub const NOCLDSTOP = 1;
+ pub const NOCLDWAIT = 2;
+ pub const SIGINFO = 4;
+ pub const ONSTACK = 0x08000000;
+ pub const RESTART = 0x10000000;
+ pub const NODEFER = 0x40000000;
+ pub const RESETHAND = 0x80000000;
+ pub const NOMASK = NODEFER;
+ pub const ONESHOT = RESETHAND;
+ },
else => void,
};
pub const sigval_t = switch (native_os) {
@@ -2269,7 +2512,10 @@ pub const SC = switch (native_os) {
else => void,
};
-pub const _SC = switch (native_os) {
+pub const _SC = if (builtin.abi.isAndroid()) enum(c_int) {
+ PAGESIZE = 39,
+ NPROCESSORS_ONLN = 97,
+} else switch (native_os) {
.driverkit, .ios, .macos, .tvos, .visionos, .watchos => enum(c_int) {
PAGESIZE = 29,
},
@@ -2298,6 +2544,24 @@ pub const _SC = switch (native_os) {
PAGESIZE = 11,
NPROCESSORS_ONLN = 15,
},
+ // https://github.com/SerenityOS/serenity/blob/1dfc9e2df39dd23f1de92530677c845aae4345f2/Kernel/API/POSIX/unistd.h#L36-L52
+ .serenity => enum(c_int) {
+ MONOTONIC_CLOCK = 0,
+ NPROCESSORS_CONF = 1,
+ NPROCESSORS_ONLN = 2,
+ OPEN_MAX = 3,
+ HOST_NAME_MAX = 4,
+ TTY_NAME_MAX = 5,
+ PAGESIZE = 6,
+ GETPW_R_SIZE_MAX = 7,
+ GETGR_R_SIZE_MAX = 8,
+ CLK_TCK = 9,
+ SYMLOOP_MAX = 10,
+ MAPPED_FILES = 11,
+ ARG_MAX = 12,
+ IOV_MAX = 13,
+ PHYS_PAGES = 14,
+ },
else => void,
};
@@ -2309,7 +2573,8 @@ pub const SEEK = switch (native_os) {
pub const CUR: wasi.whence_t = .CUR;
pub const END: wasi.whence_t = .END;
},
- .openbsd, .haiku, .netbsd, .freebsd, .macos, .ios, .tvos, .watchos, .visionos, .windows => struct {
+ // https://github.com/SerenityOS/serenity/blob/808ce594db1f2190e5212a250e900bde2ffe710b/Kernel/API/POSIX/stdio.h#L15-L17
+ .openbsd, .haiku, .netbsd, .freebsd, .macos, .ios, .tvos, .watchos, .visionos, .windows, .serenity => struct {
pub const SET = 0;
pub const CUR = 1;
pub const END = 2;
@@ -2326,6 +2591,7 @@ pub const SEEK = switch (native_os) {
pub const SHUT = switch (native_os) {
.linux => linux.SHUT,
.emscripten => emscripten.SHUT,
+ // https://github.com/SerenityOS/serenity/blob/ac44ec5ebc707f9dd0c3d4759a1e17e91db5d74f/Kernel/API/POSIX/sys/socket.h#L40-L42
else => struct {
pub const RD = 0;
pub const WR = 1;
@@ -2785,6 +3051,42 @@ pub const SIG = switch (native_os) {
pub const UNBLOCK = 2;
pub const SETMASK = 3;
},
+ // https://github.com/SerenityOS/serenity/blob/046c23f567a17758d762a33bdf04bacbfd088f9f/Kernel/API/POSIX/signal_numbers.h
+ .serenity => struct {
+ pub const INVAL = 0;
+ pub const HUP = 1;
+ pub const INT = 2;
+ pub const QUIT = 3;
+ pub const ILL = 4;
+ pub const TRAP = 5;
+ pub const ABRT = 6;
+ pub const BUS = 7;
+ pub const FPE = 8;
+ pub const KILL = 9;
+ pub const USR1 = 10;
+ pub const SEGV = 11;
+ pub const USR2 = 12;
+ pub const PIPE = 13;
+ pub const ALRM = 14;
+ pub const TERM = 15;
+ pub const STKFLT = 16;
+ pub const CHLD = 17;
+ pub const CONT = 18;
+ pub const STOP = 19;
+ pub const TSTP = 20;
+ pub const TTIN = 21;
+ pub const TTOU = 22;
+ pub const URG = 23;
+ pub const XCPU = 24;
+ pub const XFSZ = 25;
+ pub const VTALRM = 26;
+ pub const PROF = 27;
+ pub const WINCH = 28;
+ pub const IO = 29;
+ pub const INFO = 30;
+ pub const SYS = 31;
+ pub const CANCEL = 32;
+ },
else => void,
};
@@ -2792,6 +3094,8 @@ pub const SIOCGIFINDEX = switch (native_os) {
.linux => linux.SIOCGIFINDEX,
.emscripten => emscripten.SIOCGIFINDEX,
.solaris, .illumos => solaris.SIOCGLIFINDEX,
+ // https://github.com/SerenityOS/serenity/blob/cb10f70394fb7e9cfc77f827adb2e46d199bc3a5/Kernel/API/Ioctl.h#L118
+ .serenity => 34,
else => void,
};
@@ -2936,6 +3240,18 @@ pub const Sigaction = switch (native_os) {
/// signal options
flags: c_uint,
},
+ // https://github.com/SerenityOS/serenity/blob/ec492a1a0819e6239ea44156825c4ee7234ca3db/Kernel/API/POSIX/signal.h#L39-L46
+ .serenity => extern struct {
+ pub const handler_fn = *align(1) const fn (c_int) callconv(.c) void;
+ pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.c) void;
+
+ handler: extern union {
+ handler: ?handler_fn,
+ sigaction: ?sigaction_fn,
+ },
+ mask: sigset_t,
+ flags: c_int,
+ },
else => void,
};
pub const T = switch (native_os) {
@@ -3311,6 +3627,22 @@ pub const T = switch (native_os) {
pub const IOCGDRAINWAIT = 0x40047456;
pub const IOCISPTMASTER = 0x20007455;
},
+ // https://github.com/SerenityOS/serenity/blob/cb10f70394fb7e9cfc77f827adb2e46d199bc3a5/Kernel/API/Ioctl.h#L84-L96
+ .serenity => struct {
+ pub const IOCGPGRP = 0;
+ pub const IOCSPGRP = 1;
+ pub const CGETS = 2;
+ pub const CSETS = 3;
+ pub const CSETSW = 4;
+ pub const CSETSF = 5;
+ pub const CFLSH = 6;
+ pub const IOCGWINSZ = 7;
+ pub const IOCSCTTY = 8;
+ pub const IOCSTI = 9;
+ pub const IOCNOTTY = 10;
+ pub const IOCSWINSZ = 11;
+ pub const IOCGPTN = 12;
+ },
else => void,
};
pub const IOCPARM_MASK = switch (native_os) {
@@ -3546,6 +3878,43 @@ pub const W = switch (native_os) {
return (((s) & 0o177) != 0o177) and (((s) & 0o177) != 0);
}
},
+ // https://github.com/SerenityOS/serenity/blob/ec492a1a0819e6239ea44156825c4ee7234ca3db/Kernel/API/POSIX/sys/wait.h
+ .serenity => struct {
+ pub const NOHANG = 1;
+ pub const UNTRACED = 2;
+ pub const STOPPED = UNTRACED;
+ pub const EXITED = 4;
+ pub const CONTINUED = 8;
+ pub const NOWAIT = 0x1000000;
+
+ pub fn EXITSTATUS(s: u32) u8 {
+ return @intCast((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 (((s & 0x7f) + 1) >> 1) > 0;
+ }
+
+ pub fn IFCONTINUED(s: u32) bool {
+ return s == 0xffff;
+ }
+ },
else => void,
};
pub const clock_t = switch (native_os) {
@@ -3556,6 +3925,8 @@ pub const clock_t = switch (native_os) {
.openbsd, .solaris, .illumos => i64,
.netbsd => u32,
.haiku => i32,
+ // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L50
+ .serenity => u64,
else => void,
};
pub const cpu_set_t = switch (native_os) {
@@ -3568,7 +3939,7 @@ pub const dl_phdr_info = switch (native_os) {
.emscripten => emscripten.dl_phdr_info,
.freebsd => extern struct {
/// Module relocation base.
- addr: if (builtin.target.ptrBitWidth() == 32) std.elf.Elf32_Addr else std.elf.Elf64_Addr,
+ addr: std.elf.Addr,
/// Module name.
name: ?[*:0]const u8,
/// Pointer to module's phdr.
@@ -3592,11 +3963,12 @@ pub const dl_phdr_info = switch (native_os) {
/// Incremented when an object is unmapped from the process.
subs: u64,
},
- .openbsd, .haiku, .dragonfly, .netbsd => extern struct {
+ // https://github.com/SerenityOS/serenity/blob/45d81dceed81df0c8ef75b440b20cc0938195faa/Userland/Libraries/LibC/link.h#L15-L20
+ .openbsd, .haiku, .dragonfly, .netbsd, .serenity => extern struct {
addr: usize,
name: ?[*:0]const u8,
phdr: [*]std.elf.Phdr,
- phnum: u16,
+ phnum: std.elf.Half,
},
else => void,
};
@@ -3608,6 +3980,26 @@ pub const ifreq = switch (native_os) {
.linux => linux.ifreq,
.emscripten => emscripten.ifreq,
.solaris, .illumos => lifreq,
+ // https://github.com/SerenityOS/serenity/blob/9882848e0bf783dfc8e8a6d887a848d70d9c58f4/Kernel/API/POSIX/net/if.h#L49-L82
+ .serenity => extern struct {
+ // Not actually in a union, but the stdlib expects one for ifreq
+ ifrn: extern union {
+ name: [IFNAMESIZE]u8,
+ },
+ ifru: extern union {
+ addr: sockaddr,
+ dstaddr: sockaddr,
+ broadaddr: sockaddr,
+ netmask: sockaddr,
+ hwaddr: sockaddr,
+ flags: c_short,
+ metric: c_int,
+ vnetid: i64,
+ media: u64,
+ data: ?*anyopaque,
+ index: c_uint,
+ },
+ },
else => void,
};
pub const itimerspec = switch (native_os) {
@@ -3650,6 +4042,16 @@ pub const msghdr = switch (native_os) {
/// flags on received message
flags: i32,
},
+ // https://github.com/SerenityOS/serenity/blob/ac44ec5ebc707f9dd0c3d4759a1e17e91db5d74f/Kernel/API/POSIX/sys/socket.h#L74-L82
+ .serenity => extern struct {
+ name: ?*anyopaque,
+ namelen: socklen_t,
+ iov: [*]iovec,
+ iovlen: c_int,
+ control: ?*anyopaque,
+ controllen: socklen_t,
+ flags: c_int,
+ },
else => void,
};
pub const msghdr_const = switch (native_os) {
@@ -3684,6 +4086,15 @@ pub const msghdr_const = switch (native_os) {
/// flags on received message
flags: i32,
},
+ .serenity => extern struct {
+ name: ?*const anyopaque,
+ namelen: socklen_t,
+ iov: [*]const iovec,
+ iovlen: c_int,
+ control: ?*const anyopaque,
+ controllen: socklen_t,
+ flags: c_int,
+ },
else => void,
};
pub const nfds_t = switch (native_os) {
@@ -3692,6 +4103,8 @@ pub const nfds_t = switch (native_os) {
.haiku, .solaris, .illumos, .wasi => usize,
.windows => c_ulong,
.openbsd, .dragonfly, .netbsd, .freebsd, .macos, .ios, .tvos, .watchos, .visionos => u32,
+ // https://github.com/SerenityOS/serenity/blob/265764ff2fec038855193296588a887fc322d76a/Kernel/API/POSIX/poll.h#L32
+ .serenity => c_uint,
else => void,
};
pub const perf_event_attr = switch (native_os) {
@@ -3702,12 +4115,20 @@ pub const pid_t = switch (native_os) {
.linux => linux.pid_t,
.emscripten => emscripten.pid_t,
.windows => windows.HANDLE,
+ // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L31-L32
+ .serenity => c_int,
else => i32,
};
pub const pollfd = switch (native_os) {
.linux => linux.pollfd,
.emscripten => emscripten.pollfd,
.windows => ws2_32.pollfd,
+ // https://github.com/SerenityOS/serenity/blob/265764ff2fec038855193296588a887fc322d76a/Kernel/API/POSIX/poll.h#L26-L30
+ .serenity => extern struct {
+ fd: fd_t,
+ events: c_short,
+ revents: c_short,
+ },
else => extern struct {
fd: fd_t,
events: i16,
@@ -3719,11 +4140,14 @@ pub const rlim_t = switch (native_os) {
.emscripten => emscripten.rlim_t,
.openbsd, .netbsd, .solaris, .illumos, .macos, .ios, .tvos, .watchos, .visionos => u64,
.haiku, .dragonfly, .freebsd => i64,
+ // https://github.com/SerenityOS/serenity/blob/aae106e37b48f2158e68902293df1e4bf7b80c0f/Userland/Libraries/LibC/sys/resource.h#L54
+ .serenity => usize,
else => void,
};
pub const rlimit = switch (native_os) {
.linux, .emscripten => linux.rlimit,
.windows => void,
+ // https://github.com/SerenityOS/serenity/blob/aae106e37b48f2158e68902293df1e4bf7b80c0f/Userland/Libraries/LibC/sys/resource.h#L56-L59
else => extern struct {
/// Soft limit
cur: rlim_t,
@@ -3825,6 +4249,17 @@ pub const rlimit_resource = switch (native_os) {
NOVMON = 7,
_,
},
+ // https://github.com/SerenityOS/serenity/blob/aae106e37b48f2158e68902293df1e4bf7b80c0f/Userland/Libraries/LibC/sys/resource.h#L42-L48
+ .serenity => enum(c_int) {
+ CORE = 1,
+ CPU = 2,
+ DATA = 3,
+ FSIZE = 4,
+ NOFILE = 5,
+ STACK = 6,
+ AS = 7,
+ _,
+ },
else => void,
};
pub const rusage = switch (native_os) {
@@ -3873,6 +4308,28 @@ pub const rusage = switch (native_os) {
pub const CHILDREN = -1;
pub const THREAD = 1;
},
+ // https://github.com/SerenityOS/serenity/blob/aae106e37b48f2158e68902293df1e4bf7b80c0f/Userland/Libraries/LibC/sys/resource.h#L18-L38
+ .serenity => extern struct {
+ utime: timeval,
+ stime: timeval,
+ maxrss: c_long,
+ ixrss: c_long,
+ idrss: c_long,
+ isrss: c_long,
+ minflt: c_long,
+ majflt: c_long,
+ nswap: c_long,
+ inblock: c_long,
+ oublock: c_long,
+ msgsnd: c_long,
+ msgrcv: c_long,
+ nsignals: c_long,
+ nvcsw: c_long,
+ nivcsw: c_long,
+
+ pub const SELF = 1;
+ pub const CHILDREN = 2;
+ },
else => void,
};
@@ -4050,12 +4507,25 @@ pub const siginfo_t = switch (native_os) {
assert(@sizeOf(@This()) == 136);
}
},
+ // https://github.com/SerenityOS/serenity/blob/ec492a1a0819e6239ea44156825c4ee7234ca3db/Kernel/API/POSIX/signal.h#L27-L37
+ .serenity => extern struct {
+ signo: c_int,
+ code: c_int,
+ errno: c_int,
+ pid: pid_t,
+ uid: uid_t,
+ addr: ?*anyopaque,
+ status: c_int,
+ band: c_int,
+ value: sigval,
+ },
else => void,
};
pub const sigset_t = switch (native_os) {
.linux => linux.sigset_t,
.emscripten => emscripten.sigset_t,
- .openbsd, .macos, .ios, .tvos, .watchos, .visionos => u32,
+ // https://github.com/SerenityOS/serenity/blob/ec492a1a0819e6239ea44156825c4ee7234ca3db/Kernel/API/POSIX/signal.h#L19
+ .openbsd, .macos, .ios, .tvos, .watchos, .visionos, .serenity => u32,
.dragonfly, .netbsd, .solaris, .illumos, .freebsd => extern struct {
__bits: [SIG.WORDS]u32,
},
@@ -4075,7 +4545,8 @@ pub const filled_sigset = switch (native_os) {
};
pub const sigval = switch (native_os) {
.linux => linux.sigval,
- .openbsd, .dragonfly, .freebsd => extern union {
+ // https://github.com/SerenityOS/serenity/blob/ec492a1a0819e6239ea44156825c4ee7234ca3db/Kernel/API/POSIX/signal.h#L22-L25
+ .openbsd, .dragonfly, .freebsd, .serenity => extern union {
int: c_int,
ptr: ?*anyopaque,
},
@@ -4144,7 +4615,8 @@ pub const addrinfo = if (builtin.abi.isAndroid()) extern struct {
addr: ?*sockaddr,
next: ?*addrinfo,
},
- .openbsd => extern struct {
+ // https://github.com/SerenityOS/serenity/blob/d510d2aeb2facbd8f6c383d70fd1b033e1fee5dd/Userland/Libraries/LibC/netdb.h#L66-L75
+ .openbsd, .serenity => extern struct {
flags: AI,
family: c_int,
socktype: c_int,
@@ -4460,11 +4932,41 @@ pub const sockaddr = switch (native_os) {
path: [104]u8,
};
},
+ // https://github.com/SerenityOS/serenity/blob/ac44ec5ebc707f9dd0c3d4759a1e17e91db5d74f/Kernel/API/POSIX/sys/socket.h#L110-L114
+ .serenity => extern struct {
+ family: sa_family_t,
+ data: [26]u8,
+
+ // https://github.com/SerenityOS/serenity/blob/ec492a1a0819e6239ea44156825c4ee7234ca3db/Kernel/API/POSIX/netinet/in.h
+ const in_addr = u32;
+ const in6_addr = [16]u8;
+ pub const in = extern struct {
+ family: sa_family_t = AF.INET,
+ port: in_port_t,
+ addr: in_addr,
+ zero: [8]u8 = @splat(0),
+ };
+ pub const in6 = extern struct {
+ family: sa_family_t = AF.INET6,
+ port: in_port_t,
+ flowinfo: u32,
+ addr: in6_addr,
+ scope_id: u32,
+ };
+
+ // https://github.com/SerenityOS/serenity/blob/b92e6b02e53b2927732f31b1442cad420b62d1ef/Kernel/API/POSIX/sys/un.h
+ const UNIX_PATH_MAX = 108;
+ pub const un = extern struct {
+ family: sa_family_t = AF.LOCAL,
+ path: [UNIX_PATH_MAX]u8,
+ };
+ },
else => void,
};
pub const socklen_t = switch (native_os) {
.linux, .emscripten => linux.socklen_t,
.windows => ws2_32.socklen_t,
+ // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L57
else => u32,
};
pub const in_port_t = u16;
@@ -4472,7 +4974,8 @@ pub const sa_family_t = switch (native_os) {
.linux, .emscripten => linux.sa_family_t,
.windows => ws2_32.ADDRESS_FAMILY,
.openbsd, .haiku, .dragonfly, .netbsd, .freebsd, .macos, .ios, .tvos, .watchos, .visionos => u8,
- .solaris, .illumos => u16,
+ // https://github.com/SerenityOS/serenity/blob/ac44ec5ebc707f9dd0c3d4759a1e17e91db5d74f/Kernel/API/POSIX/sys/socket.h#L66
+ .solaris, .illumos, .serenity => u16,
else => void,
};
pub const AF = if (builtin.abi.isAndroid()) struct {
@@ -4751,6 +5254,15 @@ pub const AF = if (builtin.abi.isAndroid()) struct {
pub const ISDN = 26;
pub const MAX = 36;
},
+ // https://github.com/SerenityOS/serenity/blob/ac44ec5ebc707f9dd0c3d4759a1e17e91db5d74f/Kernel/API/POSIX/sys/socket.h#L17-L22
+ .serenity => struct {
+ pub const UNSPEC = 0;
+ pub const LOCAL = 1;
+ pub const UNIX = LOCAL;
+ pub const INET = 2;
+ pub const INET6 = 3;
+ pub const MAX = 4;
+ },
else => void,
};
pub const PF = if (builtin.abi.isAndroid()) struct {
@@ -5020,11 +5532,21 @@ pub const PF = if (builtin.abi.isAndroid()) struct {
pub const ISDN = AF.ISDN;
pub const MAX = AF.MAX;
},
+ // https://github.com/SerenityOS/serenity/blob/ac44ec5ebc707f9dd0c3d4759a1e17e91db5d74f/Kernel/API/POSIX/sys/socket.h#L24-L29
+ .serenity => struct {
+ pub const LOCAL = AF.LOCAL;
+ pub const UNIX = AF.LOCAL;
+ pub const INET = AF.INET;
+ pub const INET6 = AF.INET6;
+ pub const UNSPEC = AF.UNSPEC;
+ pub const MAX = AF.MAX;
+ },
else => void,
};
pub const DT = switch (native_os) {
.linux => linux.DT,
- .netbsd, .freebsd, .macos, .ios, .tvos, .watchos, .visionos => struct {
+ // https://github.com/SerenityOS/serenity/blob/1262a7d1424d0d2e89d80644409721cbf056ab17/Kernel/API/POSIX/dirent.h#L16-L35
+ .netbsd, .freebsd, .openbsd, .macos, .ios, .tvos, .watchos, .visionos, .serenity => struct {
pub const UNKNOWN = 0;
pub const FIFO = 1;
pub const CHR = 2;
@@ -5047,17 +5569,6 @@ pub const DT = switch (native_os) {
pub const WHT = 14;
pub const DBF = 15;
},
- .openbsd => struct {
- pub const UNKNOWN = 0;
- pub const FIFO = 1;
- pub const CHR = 2;
- pub const DIR = 4;
- pub const BLK = 6;
- pub const REG = 8;
- pub const LNK = 10;
- pub const SOCK = 12;
- pub const WHT = 14; // XXX
- },
else => void,
};
pub const MSG = switch (native_os) {
@@ -5078,6 +5589,18 @@ pub const MSG = switch (native_os) {
pub const EOF = 0x0400;
pub const NOSIGNAL = 0x0800;
},
+ // https://github.com/SerenityOS/serenity/blob/ac44ec5ebc707f9dd0c3d4759a1e17e91db5d74f/Kernel/API/POSIX/sys/socket.h#L56-L64
+ .serenity => struct {
+ pub const TRUNC = 0x1;
+ pub const CTRUNC = 0x2;
+ pub const PEEK = 0x4;
+ pub const OOB = 0x8;
+ pub const DONTROUTE = 0x10;
+ pub const WAITALL = 0x20;
+ pub const DONTWAIT = 0x40;
+ pub const NOSIGNAL = 0x80;
+ pub const EOR = 0x100;
+ },
else => void,
};
pub const SOCK = switch (native_os) {
@@ -5168,6 +5691,17 @@ pub const SOCK = switch (native_os) {
pub const CLOEXEC = 0x8000;
pub const NONBLOCK = 0x4000;
},
+ // https://github.com/SerenityOS/serenity/blob/ac44ec5ebc707f9dd0c3d4759a1e17e91db5d74f/Kernel/API/POSIX/sys/socket.h#L31-L38
+ .serenity => struct {
+ pub const STREAM = 1;
+ pub const DGRAM = 2;
+ pub const RAW = 3;
+ pub const RDM = 4;
+ pub const SEQPACKET = 5;
+
+ pub const NONBLOCK = 0o4000;
+ pub const CLOEXEC = 0o2000000;
+ },
else => void,
};
pub const TCP = switch (native_os) {
@@ -5175,6 +5709,11 @@ pub const TCP = switch (native_os) {
.linux => linux.TCP,
.emscripten => emscripten.TCP,
.windows => ws2_32.TCP,
+ // https://github.com/SerenityOS/serenity/blob/61ac554a3403838f79ca746bd1c65ded6f97d124/Kernel/API/POSIX/netinet/tcp.h#L13-L14
+ .serenity => struct {
+ pub const NODELAY = 10;
+ pub const MAXSEG = 11;
+ },
else => void,
};
pub const IPPROTO = switch (native_os) {
@@ -5759,6 +6298,20 @@ pub const IPPROTO = switch (native_os) {
/// raw IP packet
pub const RAW = 255;
},
+ // https://github.com/SerenityOS/serenity/blob/ac44ec5ebc707f9dd0c3d4759a1e17e91db5d74f/Kernel/API/POSIX/sys/socket.h#L44-L54
+ .serenity => struct {
+ pub const IP = 0;
+ pub const ICMP = 1;
+ pub const IGMP = 2;
+ pub const IPIP = 4;
+ pub const TCP = 6;
+ pub const UDP = 17;
+ pub const IPV6 = 41;
+ pub const ESP = 50;
+ pub const AH = 51;
+ pub const ICMPV6 = 58;
+ pub const RAW = 255;
+ },
else => void,
};
pub const SOL = switch (native_os) {
@@ -5774,6 +6327,10 @@ pub const SOL = switch (native_os) {
pub const PACKET = 0xfffd;
pub const FILTER = 0xfffc;
},
+ // https://github.com/SerenityOS/serenity/blob/ac44ec5ebc707f9dd0c3d4759a1e17e91db5d74f/Kernel/API/POSIX/sys/socket.h#L127
+ .serenity => struct {
+ pub const SOCKET = 1;
+ },
else => void,
};
pub const SO = switch (native_os) {
@@ -5991,12 +6548,35 @@ pub const SO = switch (native_os) {
pub const DOMAIN = 0x1024;
pub const PROTOCOL = 0x1025;
},
+ // https://github.com/SerenityOS/serenity/blob/ac44ec5ebc707f9dd0c3d4759a1e17e91db5d74f/Kernel/API/POSIX/sys/socket.h#L130-L150
+ .serenity => struct {
+ pub const RCVTIMEO = 0;
+ pub const SNDTIMEO = 1;
+ pub const TYPE = 2;
+ pub const ERROR = 3;
+ pub const PEERCRED = 4;
+ pub const RCVBUF = 5;
+ pub const SNDBUF = 6;
+ pub const DEBUG = 7;
+ pub const REUSEADDR = 8;
+ pub const BINDTODEVICE = 9;
+ pub const KEEPALIVE = 10;
+ pub const TIMESTAMP = 11;
+ pub const BROADCAST = 12;
+ pub const LINGER = 13;
+ pub const ACCEPTCONN = 14;
+ pub const DONTROUTE = 15;
+ pub const OOBINLINE = 16;
+ pub const SNDLOWAT = 17;
+ pub const RCVLOWAT = 18;
+ },
else => void,
};
pub const SOMAXCONN = switch (native_os) {
.linux => linux.SOMAXCONN,
.windows => ws2_32.SOMAXCONN,
- .solaris, .illumos => 128,
+ // https://github.com/SerenityOS/serenity/blob/ac44ec5ebc707f9dd0c3d4759a1e17e91db5d74f/Kernel/API/POSIX/sys/socket.h#L128
+ .solaris, .illumos, .serenity => 128,
.openbsd => 28,
else => void,
};
@@ -6004,7 +6584,8 @@ pub const IFNAMESIZE = switch (native_os) {
.linux => linux.IFNAMESIZE,
.emscripten => emscripten.IFNAMESIZE,
.windows => 30,
- .openbsd, .dragonfly, .netbsd, .freebsd, .macos, .ios, .tvos, .watchos, .visionos => 16,
+ // https://github.com/SerenityOS/serenity/blob/9882848e0bf783dfc8e8a6d887a848d70d9c58f4/Kernel/API/POSIX/net/if.h#L50
+ .openbsd, .dragonfly, .netbsd, .freebsd, .macos, .ios, .tvos, .watchos, .visionos, .serenity => 16,
.solaris, .illumos => 32,
else => void,
};
@@ -6020,6 +6601,12 @@ pub const stack_t = switch (native_os) {
/// SS_DISABLE and/or SS_ONSTACK.
flags: i32,
},
+ // https://github.com/SerenityOS/serenity/blob/ec492a1a0819e6239ea44156825c4ee7234ca3db/Kernel/API/POSIX/signal.h#L48-L52
+ .serenity => extern struct {
+ sp: *anyopaque,
+ flags: c_int,
+ size: usize,
+ },
else => extern struct {
sp: [*]u8,
size: isize,
@@ -6030,10 +6617,12 @@ pub const time_t = switch (native_os) {
.linux => linux.time_t,
.emscripten => emscripten.time_t,
.haiku, .dragonfly => isize,
+ // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L47
else => i64,
};
pub const suseconds_t = switch (native_os) {
- .solaris, .illumos => i64,
+ // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L49
+ .solaris, .illumos, .serenity => i64,
.freebsd, .dragonfly => c_long,
.netbsd => c_int,
.haiku => i32,
@@ -6051,7 +6640,8 @@ pub const timeval = switch (native_os) {
sec: c_long,
usec: i32,
},
- .dragonfly, .netbsd, .freebsd, .solaris, .illumos => extern struct {
+ // https://github.com/SerenityOS/serenity/blob/6b6eca0631c893c5f8cfb8274cdfe18e2d0637c0/Kernel/API/POSIX/sys/time.h#L15-L18
+ .dragonfly, .netbsd, .freebsd, .solaris, .illumos, .serenity => extern struct {
/// seconds
sec: time_t,
/// microseconds
@@ -6070,6 +6660,11 @@ pub const timezone = switch (native_os) {
minuteswest: i32,
dsttime: i32,
},
+ // https://github.com/SerenityOS/serenity/blob/ba776390b5878ec0be1a9e595a3471a6cfe0a0cf/Userland/Libraries/LibC/sys/time.h#L19-L22
+ .serenity => extern struct {
+ minuteswest: c_int,
+ dsttime: c_int,
+ },
else => void,
};
@@ -6127,7 +6722,8 @@ pub const ucontext_t = switch (native_os) {
arg: ?*void,
_spare: [4]c_int,
},
- .haiku => extern struct {
+ // https://github.com/SerenityOS/serenity/blob/87eac0e424cff4a1f941fb704b9362a08654c24d/Kernel/API/POSIX/ucontext.h#L19-L24
+ .haiku, .serenity => extern struct {
link: ?*ucontext_t,
sigmask: sigset_t,
stack: stack_t,
@@ -6222,6 +6818,47 @@ pub const mcontext_t = switch (native_os) {
},
.dragonfly => dragonfly.mcontext_t,
.haiku => haiku.mcontext_t,
+ .serenity => switch (native_arch) {
+ // https://github.com/SerenityOS/serenity/blob/200e91cd7f1ec5453799a2720d4dc114a59cc289/Kernel/Arch/aarch64/mcontext.h#L15-L19
+ .aarch64 => extern struct {
+ x: [31]u64,
+ sp: u64,
+ pc: u64,
+ },
+ // https://github.com/SerenityOS/serenity/blob/66f8d0f031ef25c409dbb4fecaa454800fecae0f/Kernel/Arch/riscv64/mcontext.h#L15-L18
+ .riscv64 => extern struct {
+ x: [31]u64,
+ pc: u64,
+ },
+ // https://github.com/SerenityOS/serenity/blob/7b9ea3efdec9f86a1042893e8107d0b23aad8727/Kernel/Arch/x86_64/mcontext.h#L15-L40
+ .x86_64 => extern struct {
+ rax: u64,
+ rcx: u64,
+ rdx: u64,
+ rbx: u64,
+ rsp: u64,
+ rbp: u64,
+ rsi: u64,
+ rdi: u64,
+ rip: u64,
+ r8: u64,
+ r9: u64,
+ r10: u64,
+ r11: u64,
+ r12: u64,
+ r13: u64,
+ r14: u64,
+ r15: u64,
+ rflags: u64,
+ cs: u32,
+ ss: u32,
+ ds: u32,
+ es: u32,
+ fs: u32,
+ gs: u32,
+ },
+ else => struct {},
+ },
else => void,
};
@@ -6247,6 +6884,16 @@ pub const utsname = switch (native_os) {
version: [256:0]u8,
machine: [256:0]u8,
},
+ // https://github.com/SerenityOS/serenity/blob/d794ed1de7a46482272683f8dc4c858806390f29/Kernel/API/POSIX/sys/utsname.h#L17-L23
+ .serenity => extern struct {
+ sysname: [UTSNAME_ENTRY_LEN:0]u8,
+ nodename: [UTSNAME_ENTRY_LEN:0]u8,
+ release: [UTSNAME_ENTRY_LEN:0]u8,
+ version: [UTSNAME_ENTRY_LEN:0]u8,
+ machine: [UTSNAME_ENTRY_LEN:0]u8,
+
+ const UTSNAME_ENTRY_LEN = 65;
+ },
else => void,
};
pub const PR = switch (native_os) {
@@ -6265,6 +6912,8 @@ pub const _errno = switch (native_os) {
.solaris, .illumos => private.___errno,
.openbsd, .netbsd => private.__errno,
.haiku => haiku._errnop,
+ // https://github.com/SerenityOS/serenity/blob/a353ceecf13b6f156a078e32f1ddf1d21366934c/Userland/Libraries/LibC/errno.h#L33
+ .serenity => private.__errno_location,
else => {},
};
@@ -6340,6 +6989,16 @@ pub const RTLD = switch (native_os) {
FIRST: bool = false,
_: u23 = 0,
},
+ // https://github.com/SerenityOS/serenity/blob/36a26d7fa80bc9c72b19442912d8967f448368ff/Userland/Libraries/LibC/dlfcn.h#L13-L17
+ .serenity => packed struct(c_int) {
+ DEFAULT: bool = false,
+ _1: u1,
+ LAZY: bool = false,
+ NOW: bool = false,
+ GLOBAL: bool = false,
+ LOCAL: bool = false,
+ _: std.meta.Int(.unsigned, @bitSizeOf(c_int) - 6) = 0,
+ },
else => void,
};
@@ -6413,11 +7072,20 @@ pub const dirent = switch (native_os) {
_: u32 align(1) = 0,
name: [MAXNAMLEN:0]u8,
},
+ // https://github.com/SerenityOS/serenity/blob/abc150085f532f123b598949218893cb272ccc4c/Userland/Libraries/LibC/dirent.h#L14-L20
+ .serenity => extern struct {
+ ino: ino_t,
+ off: off_t,
+ reclen: c_ushort,
+ type: u8,
+ name: [256:0]u8,
+ },
else => void,
};
pub const MAXNAMLEN = switch (native_os) {
.netbsd, .solaris, .illumos => 511,
- .haiku => NAME_MAX,
+ // https://github.com/SerenityOS/serenity/blob/1262a7d1424d0d2e89d80644409721cbf056ab17/Kernel/API/POSIX/dirent.h#L37
+ .haiku, .serenity => NAME_MAX,
.openbsd => 255,
else => {},
};
@@ -6499,6 +7167,17 @@ pub const AI = if (builtin.abi.isAndroid()) packed struct(u32) {
_: u19 = 0,
},
.windows => ws2_32.AI,
+ // https://github.com/SerenityOS/serenity/blob/d510d2aeb2facbd8f6c383d70fd1b033e1fee5dd/Userland/Libraries/LibC/netdb.h#L90-L96
+ .serenity => packed struct(c_int) {
+ PASSIVE: bool = false,
+ CANONNAME: bool = false,
+ NUMERICHOST: bool = false,
+ NUMERICSERV: bool = false,
+ V4MAPPED: bool = false,
+ ALL: bool = false,
+ ADDRCONFIG: bool = false,
+ _: std.meta.Int(.unsigned, @bitSizeOf(c_int) - 7) = 0,
+ },
else => void,
};
@@ -6523,6 +7202,15 @@ pub const NI = switch (native_os) {
NUMERICSCOPE: bool = false,
_: u25 = 0,
},
+ // https://github.com/SerenityOS/serenity/blob/d510d2aeb2facbd8f6c383d70fd1b033e1fee5dd/Userland/Libraries/LibC/netdb.h#L101-L105
+ .serenity => packed struct(c_int) {
+ NUMERICHOST: bool = false,
+ NUMERICSERV: bool = false,
+ NAMEREQD: bool = false,
+ NOFQDN: bool = false,
+ DGRAM: bool = false,
+ _: std.meta.Int(.unsigned, @bitSizeOf(c_int) - 5) = 0,
+ },
else => void,
};
@@ -6675,6 +7363,22 @@ pub const EAI = if (builtin.abi.isAndroid()) enum(c_int) {
OVERFLOW = -14,
_,
},
+ // https://github.com/SerenityOS/serenity/blob/d510d2aeb2facbd8f6c383d70fd1b033e1fee5dd/Userland/Libraries/LibC/netdb.h#L77-L88
+ .serenity => enum(c_int) {
+ ADDRFAMILY = 1,
+ AGAIN = 2,
+ BADFLAGS = 3,
+ FAIL = 4,
+ FAMILY = 5,
+ MEMORY = 6,
+ NODATA = 7,
+ NONAME = 8,
+ SERVICE = 9,
+ SOCKTYPE = 10,
+ SYSTEM = 11,
+ OVERFLOW = 12,
+ _,
+ },
else => void,
};
@@ -7097,6 +7801,34 @@ pub const Stat = switch (native_os) {
return self.birthtim;
}
},
+ // https://github.com/SerenityOS/serenity/blob/ec492a1a0819e6239ea44156825c4ee7234ca3db/Kernel/API/POSIX/sys/stat.h#L53-L67
+ .serenity => extern 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;
+ }
+ },
else => void,
};
@@ -7159,6 +7891,13 @@ pub const pthread_mutex_t = switch (native_os) {
.emscripten => extern struct {
data: [24]u8 align(4) = [_]u8{0} ** 24,
},
+ // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L68-L73
+ .serenity => extern struct {
+ lock: u32 = 0,
+ owner: pthread_t = 0,
+ level: c_int = 0,
+ type: c_int = 0,
+ },
else => void,
};
@@ -7201,6 +7940,12 @@ pub const pthread_cond_t = switch (native_os) {
.fuchsia, .emscripten => extern struct {
data: [48]u8 align(@alignOf(usize)) = [_]u8{0} ** 48,
},
+ // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L80-L84
+ .serenity => extern struct {
+ mutex: ?*pthread_mutex_t = null,
+ value: u32 = 0,
+ clockid: clockid_t = .REALTIME_COARSE,
+ },
else => void,
};
@@ -7258,6 +8003,10 @@ pub const pthread_rwlock_t = switch (native_os) {
.emscripten => extern struct {
size: [32]u8 align(4) = [_]u8{0} ** 32,
},
+ // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L86
+ .serenity => extern struct {
+ inner: u64 = 0,
+ },
else => void,
};
@@ -7270,7 +8019,8 @@ pub const pthread_attr_t = switch (native_os) {
__sig: c_long,
__opaque: [56]u8,
},
- .freebsd => extern struct {
+ // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L75
+ .freebsd, .openbsd, .serenity => extern struct {
inner: ?*anyopaque = null,
},
.solaris, .illumos => extern struct {
@@ -7288,16 +8038,14 @@ pub const pthread_attr_t = switch (native_os) {
guard_size: i32,
stack_address: ?*anyopaque,
},
- .openbsd => extern struct {
- inner: ?*anyopaque = null,
- },
else => void,
};
pub const pthread_key_t = switch (native_os) {
.linux, .emscripten => c_uint,
.macos, .ios, .tvos, .watchos, .visionos => c_ulong,
- .openbsd, .solaris, .illumos => c_int,
+ // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L65
+ .openbsd, .solaris, .illumos, .serenity => c_int,
else => void,
};
@@ -7353,6 +8101,12 @@ pub const sem_t = switch (native_os) {
},
padding: [2]i32,
},
+ // https://github.com/SerenityOS/serenity/blob/aae106e37b48f2158e68902293df1e4bf7b80c0f/Userland/Libraries/LibC/semaphore.h#L23-L27
+ .serenity => extern struct {
+ magic: u32,
+ value: u32,
+ flags: u8,
+ },
else => void,
};
@@ -7556,6 +8310,13 @@ pub const AT = switch (native_os) {
/// file.
pub const FDCWD: fd_t = if (builtin.link_libc) -2 else 3;
},
+ // https://github.com/SerenityOS/serenity/blob/2808b0376406a40e31293bb3bcb9170374e90506/Kernel/API/POSIX/fcntl.h#L49-L52
+ .serenity => struct {
+ pub const FDCWD = -100;
+ pub const SYMLINK_NOFOLLOW = 0x100;
+ pub const REMOVEDIR = 0x200;
+ pub const EACCESS = 0x400;
+ },
else => void,
};
@@ -7771,6 +8532,23 @@ pub const O = switch (native_os) {
TMPFILE: bool = false,
_: u9 = 0,
},
+ // https://github.com/SerenityOS/serenity/blob/2808b0376406a40e31293bb3bcb9170374e90506/Kernel/API/POSIX/fcntl.h#L28-L43
+ .serenity => packed struct(c_int) {
+ ACCMODE: std.posix.ACCMODE = .RDONLY,
+ EXEC: bool = false,
+ CREAT: bool = false,
+ EXCL: bool = false,
+ NOCTTY: bool = false,
+ TRUNC: bool = false,
+ APPEND: bool = false,
+ NONBLOCK: bool = false,
+ DIRECTORY: bool = false,
+ NOFOLLOW: bool = false,
+ CLOEXEC: bool = false,
+ DIRECT: bool = false,
+ SYNC: bool = false,
+ _: std.meta.Int(.unsigned, @bitSizeOf(c_int) - 14) = 0,
+ },
else => void,
};
@@ -7910,6 +8688,21 @@ pub const MAP = switch (native_os) {
@"32BIT": bool = false,
_: u12 = 0,
},
+ // https://github.com/SerenityOS/serenity/blob/6d59d4d3d9e76e39112842ec487840828f1c9bfe/Kernel/API/POSIX/sys/mman.h#L16-L26
+ .serenity => packed struct(c_int) {
+ FILE: bool = false,
+ SHARED: bool = false,
+ PRIVATE: bool = false,
+ _3: u2 = 0,
+ FIXED: bool = false,
+ ANONYMOUS: bool = false,
+ STACK: bool = false,
+ NORESERVE: bool = false,
+ RANDOMIZED: bool = false,
+ PURGEABLE: bool = false,
+ FIXED_NOREPLACE: bool = false,
+ _: std.meta.Int(.unsigned, @bitSizeOf(c_int) - 12) = 0,
+ },
else => void,
};
@@ -8020,6 +8813,27 @@ pub const V = switch (native_os) {
LNEXT,
EOL2,
},
+ // https://github.com/SerenityOS/serenity/blob/d277cdfd4c7ed21d5248a83217ae03b9f890c3c8/Kernel/API/POSIX/termios.h#L32-L49
+ .serenity => enum {
+ INTR,
+ QUIT,
+ ERASE,
+ KILL,
+ EOF,
+ TIME,
+ MIN,
+ SWTC,
+ START,
+ STOP,
+ SUSP,
+ EOL,
+ REPRINT,
+ DISCARD,
+ WERASE,
+ LNEXT,
+ EOL2,
+ INFO,
+ },
else => void,
};
@@ -8028,7 +8842,8 @@ pub const NCCS = switch (native_os) {
.macos, .ios, .tvos, .watchos, .visionos, .freebsd, .netbsd, .openbsd, .dragonfly => 20,
.haiku => 11,
.solaris, .illumos => 19,
- .emscripten, .wasi => 32,
+ // https://github.com/SerenityOS/serenity/blob/d277cdfd4c7ed21d5248a83217ae03b9f890c3c8/Kernel/API/POSIX/termios.h#L15
+ .emscripten, .wasi, .serenity => 32,
else => void,
};
@@ -8043,7 +8858,8 @@ pub const termios = switch (native_os) {
ispeed: speed_t align(8),
ospeed: speed_t,
},
- .freebsd, .netbsd, .dragonfly, .openbsd => extern struct {
+ // https://github.com/SerenityOS/serenity/blob/d277cdfd4c7ed21d5248a83217ae03b9f890c3c8/Kernel/API/POSIX/termios.h#L21-L29
+ .freebsd, .netbsd, .dragonfly, .openbsd, .serenity => extern struct {
iflag: tc_iflag_t,
oflag: tc_oflag_t,
cflag: tc_cflag_t,
@@ -8171,7 +8987,8 @@ pub const tc_iflag_t = switch (native_os) {
DOSMODE: bool = false,
_: u16 = 0,
},
- .emscripten, .wasi => packed struct(u32) {
+ // https://github.com/SerenityOS/serenity/blob/d277cdfd4c7ed21d5248a83217ae03b9f890c3c8/Kernel/API/POSIX/termios.h#L52-L66
+ .emscripten, .wasi, .serenity => packed struct(u32) {
IGNBRK: bool = false,
BRKINT: bool = false,
IGNPAR: bool = false,
@@ -8263,7 +9080,8 @@ pub const tc_oflag_t = switch (native_os) {
WRAP: bool = false,
_: u14 = 0,
},
- .haiku, .wasi, .emscripten => packed struct(u32) {
+ // https://github.com/SerenityOS/serenity/blob/d277cdfd4c7ed21d5248a83217ae03b9f890c3c8/Kernel/API/POSIX/termios.h#L69-L97
+ .haiku, .wasi, .emscripten, .serenity => packed struct(u32) {
OPOST: bool = false,
OLCUC: bool = false,
ONLCR: bool = false,
@@ -8422,6 +9240,19 @@ pub const tc_cflag_t = switch (native_os) {
CLOCAL: bool = false,
_: u20 = 0,
},
+ // https://github.com/SerenityOS/serenity/blob/d277cdfd4c7ed21d5248a83217ae03b9f890c3c8/Kernel/API/POSIX/termios.h#L131-L141
+ .serenity => packed struct(u32) {
+ _0: u4 = 0,
+ CSIZE: CSIZE = .CS5,
+ CSTOPB: bool = false,
+ CREAD: bool = false,
+ PARENB: bool = false,
+ PARODD: bool = false,
+ HUPCL: bool = false,
+ CLOCAL: bool = false,
+ CBAUDEX: bool = false,
+ _: u19 = 0,
+ },
else => void,
};
@@ -8548,6 +9379,27 @@ pub const tc_lflag_t = switch (native_os) {
IEXTEN: bool = false,
_: u16 = 0,
},
+ // https://github.com/SerenityOS/serenity/blob/d277cdfd4c7ed21d5248a83217ae03b9f890c3c8/Kernel/API/POSIX/termios.h#L168-L189
+ .serenity => packed struct(u32) {
+ ISIG: bool = false,
+ ICANON: bool = false,
+ XCASE: bool = false,
+ ECHO: bool = false,
+ ECHOE: bool = false,
+ ECHOK: bool = false,
+ ECHONL: bool = false,
+ NOFLSH: bool = false,
+ TOSTOP: bool = false,
+ ECHOCTL: bool = false,
+ ECHOPRT: bool = false,
+ ECHOKE: bool = false,
+ FLUSHO: bool = false,
+ PENDIN: bool = false,
+ _14: u6 = 0,
+ IEXTEN: bool = false,
+ EXTPROC: bool = false,
+ _: u15 = 0,
+ },
else => void,
};
@@ -8696,7 +9548,8 @@ pub const speed_t = switch (native_os) {
B3500000 = 30,
B4000000 = 31,
},
- .emscripten, .wasi => enum(u32) {
+ // https://github.com/SerenityOS/serenity/blob/d277cdfd4c7ed21d5248a83217ae03b9f890c3c8/Kernel/API/POSIX/termios.h#L111-L159
+ .emscripten, .wasi, .serenity => enum(u32) {
B0 = 0o0000000,
B50 = 0o0000001,
B75 = 0o0000002,
@@ -8735,7 +9588,11 @@ pub const speed_t = switch (native_os) {
pub const whence_t = if (native_os == .wasi) std.os.wasi.whence_t else c_int;
-pub const sig_atomic_t = c_int;
+pub const sig_atomic_t = switch (native_os) {
+ // https://github.com/SerenityOS/serenity/blob/ec492a1a0819e6239ea44156825c4ee7234ca3db/Kernel/API/POSIX/signal.h#L20
+ .serenity => u32,
+ else => c_int,
+};
/// maximum signal number + 1
pub const NSIG = switch (native_os) {
@@ -8744,7 +9601,8 @@ pub const NSIG = switch (native_os) {
.haiku => 65,
.netbsd, .freebsd => 32,
.solaris, .illumos => 75,
- .openbsd => 33,
+ // https://github.com/SerenityOS/serenity/blob/046c23f567a17758d762a33bdf04bacbfd088f9f/Kernel/API/POSIX/signal_numbers.h#L42
+ .openbsd, .serenity => 33,
else => {},
};
@@ -8758,6 +9616,8 @@ pub const MINSIGSTKSZ = switch (native_os) {
.solaris, .illumos => 2048,
.haiku, .netbsd => 8192,
.openbsd => 1 << openbsd.MAX_PAGE_SHIFT,
+ // https://github.com/SerenityOS/serenity/blob/ec492a1a0819e6239ea44156825c4ee7234ca3db/Kernel/API/POSIX/signal.h#L58
+ .serenity => 4096,
else => {},
};
pub const SIGSTKSZ = switch (native_os) {
@@ -8766,6 +9626,8 @@ pub const SIGSTKSZ = switch (native_os) {
.solaris, .illumos => 8192,
.haiku => 16384,
.openbsd => MINSIGSTKSZ + (1 << openbsd.MAX_PAGE_SHIFT) * 4,
+ // https://github.com/SerenityOS/serenity/blob/ec492a1a0819e6239ea44156825c4ee7234ca3db/Kernel/API/POSIX/signal.h#L59
+ .serenity => 32768,
else => {},
};
pub const SS = switch (native_os) {
@@ -8774,7 +9636,8 @@ pub const SS = switch (native_os) {
pub const ONSTACK = 1;
pub const DISABLE = 4;
},
- .haiku, .solaris, .illumos => struct {
+ // https://github.com/SerenityOS/serenity/blob/ec492a1a0819e6239ea44156825c4ee7234ca3db/Kernel/API/POSIX/signal.h#L54-L55
+ .haiku, .solaris, .illumos, .serenity => struct {
pub const ONSTACK = 0x1;
pub const DISABLE = 0x2;
},
@@ -9267,6 +10130,12 @@ pub const NOTE = switch (native_os) {
else => void,
};
+pub const FUTEX = switch (native_os) {
+ .openbsd => openbsd.FUTEX,
+ .serenity => serenity.FUTEX,
+ else => void,
+};
+
// Unix-like systems
pub const DIR = opaque {};
pub extern "c" fn opendir(pathname: [*:0]const u8) ?*DIR;
@@ -9327,7 +10196,7 @@ pub extern "c" fn sendfile64(out_fd: fd_t, in_fd: fd_t, offset: ?*i64, count: us
pub extern "c" fn setrlimit64(resource: rlimit_resource, rlim: *const rlimit) c_int;
pub const arc4random_buf = switch (native_os) {
- .dragonfly, .netbsd, .freebsd, .solaris, .openbsd, .macos, .ios, .tvos, .watchos, .visionos => private.arc4random_buf,
+ .dragonfly, .netbsd, .freebsd, .solaris, .openbsd, .macos, .ios, .tvos, .watchos, .visionos, .serenity => private.arc4random_buf,
else => {},
};
pub const getentropy = switch (native_os) {
@@ -9395,7 +10264,7 @@ pub const sigaltstack = switch (native_os) {
pub extern "c" fn memfd_create(name: [*:0]const u8, flags: c_uint) c_int;
pub const pipe2 = switch (native_os) {
- .dragonfly, .emscripten, .netbsd, .freebsd, .solaris, .illumos, .openbsd, .linux => private.pipe2,
+ .dragonfly, .emscripten, .netbsd, .freebsd, .solaris, .illumos, .openbsd, .linux, .serenity => private.pipe2,
else => {},
};
pub const copy_file_range = switch (native_os) {
@@ -9501,15 +10370,15 @@ pub const _msize = switch (native_os) {
else => {},
};
pub const malloc_size = switch (native_os) {
- .macos, .ios, .tvos, .watchos, .visionos => private.malloc_size,
+ .macos, .ios, .tvos, .watchos, .visionos, .serenity => private.malloc_size,
else => {},
};
pub const malloc_usable_size = switch (native_os) {
- .freebsd, .linux => private.malloc_usable_size,
+ .freebsd, .linux, .serenity => private.malloc_usable_size,
else => {},
};
pub const posix_memalign = switch (native_os) {
- .dragonfly, .netbsd, .freebsd, .solaris, .openbsd, .linux, .macos, .ios, .tvos, .watchos, .visionos => private.posix_memalign,
+ .dragonfly, .netbsd, .freebsd, .solaris, .openbsd, .linux, .macos, .ios, .tvos, .watchos, .visionos, .serenity => private.posix_memalign,
else => {},
};
pub const sysconf = switch (native_os) {
@@ -9532,6 +10401,12 @@ pub const flock = switch (native_os) {
else => private.flock,
};
+pub const futex = switch (native_os) {
+ .openbsd => openbsd.futex,
+ .serenity => serenity.futex,
+ else => {},
+};
+
pub extern "c" var environ: [*:null]?[*:0]u8;
pub extern "c" fn fopen(noalias filename: [*:0]const u8, noalias modes: [*:0]const u8) ?*FILE;
@@ -9582,6 +10457,7 @@ pub const fork = switch (native_os) {
.watchos,
.visionos,
.haiku,
+ .serenity,
=> private.fork,
else => {},
};
@@ -9825,7 +10701,11 @@ pub extern "c" fn pthread_rwlock_tryrdlock(rwl: *pthread_rwlock_t) callconv(.c)
pub extern "c" fn pthread_rwlock_trywrlock(rwl: *pthread_rwlock_t) callconv(.c) E;
pub extern "c" fn pthread_rwlock_unlock(rwl: *pthread_rwlock_t) callconv(.c) E;
-pub const pthread_t = *opaque {};
+pub const pthread_t = switch (native_os) {
+ // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L64
+ .serenity => c_int,
+ else => *opaque {},
+};
pub const FILE = opaque {};
pub extern "c" fn dlopen(path: ?[*:0]const u8, mode: RTLD) ?*anyopaque;
@@ -9958,7 +10838,6 @@ pub const thread_id = haiku.thread_id;
pub const AUTH = openbsd.AUTH;
pub const BI = openbsd.BI;
-pub const FUTEX = openbsd.FUTEX;
pub const HW = openbsd.HW;
pub const PTHREAD_STACK_MIN = openbsd.PTHREAD_STACK_MIN;
pub const TCFLUSH = openbsd.TCFLUSH;
@@ -9999,7 +10878,6 @@ pub const bcrypt_checkpass = openbsd.bcrypt_checkpass;
pub const bcrypt_gensalt = openbsd.bcrypt_gensalt;
pub const bcrypt_newhash = openbsd.bcrypt_newhash;
pub const endpwent = openbsd.endpwent;
-pub const futex = openbsd.futex;
pub const getpwent = openbsd.getpwent;
pub const getpwnam_r = openbsd.getpwnam_r;
pub const getpwnam_shadow = openbsd.getpwnam_shadow;
@@ -10226,6 +11104,24 @@ pub const lwp_gettid = dragonfly.lwp_gettid;
pub const umtx_sleep = dragonfly.umtx_sleep;
pub const umtx_wakeup = dragonfly.umtx_wakeup;
+pub const PERF_EVENT = serenity.PERF_EVENT;
+pub const disown = serenity.disown;
+pub const profiling_enable = serenity.profiling_enable;
+pub const profiling_disable = serenity.profiling_disable;
+pub const profiling_free_buffer = serenity.profiling_free_buffer;
+pub const futex_wait = serenity.futex_wait;
+pub const futex_wake = serenity.futex_wake;
+pub const purge = serenity.purge;
+pub const perf_event = serenity.perf_event;
+pub const perf_register_string = serenity.perf_register_string;
+pub const get_stack_bounds = serenity.get_stack_bounds;
+pub const anon_create = serenity.anon_create;
+pub const serenity_readlink = serenity.serenity_readlink;
+pub const serenity_open = serenity.serenity_open;
+pub const getkeymap = serenity.getkeymap;
+pub const setkeymap = serenity.setkeymap;
+pub const internet_checksum = serenity.internet_checksum;
+
/// External definitions shared by two or more operating systems.
const private = struct {
extern "c" fn close(fd: fd_t) c_int;
diff --git a/lib/std/c/serenity.zig b/lib/std/c/serenity.zig
new file mode 100644
index 0000000000..e64bef98a7
--- /dev/null
+++ b/lib/std/c/serenity.zig
@@ -0,0 +1,75 @@
+const std = @import("../std.zig");
+const assert = std.debug.assert;
+const builtin = @import("builtin");
+const O = std.c.O;
+const clockid_t = std.c.clockid_t;
+const pid_t = std.c.pid_t;
+const timespec = std.c.timespec;
+
+comptime {
+ assert(builtin.os.tag == .serenity); // Prevent access of std.c symbols on wrong OS.
+}
+
+// https://github.com/SerenityOS/serenity/blob/ec492a1a0819e6239ea44156825c4ee7234ca3db/Kernel/API/POSIX/futex.h#L46-L53
+pub const FUTEX = struct {
+ pub const WAIT = 1;
+ pub const WAKE = 2;
+ pub const REQUEUE = 3;
+ pub const CMP_REQUEUE = 4;
+ pub const WAKE_OP = 5;
+ pub const WAIT_BITSET = 9;
+ pub const WAKE_BITSET = 10;
+
+ pub const CLOCK_REALTIME = 1 << 8;
+ pub const PRIVATE_FLAG = 1 << 9;
+};
+
+// https://github.com/SerenityOS/serenity/blob/54e79aa1d90bbcb69014255a59afb085802719d3/Kernel/API/POSIX/serenity.h#L18-L36
+pub const PERF_EVENT = packed struct(c_int) {
+ SAMPLE: bool = false,
+ MALLOC: bool = false,
+ FREE: bool = false,
+ MMAP: bool = false,
+ MUNMAP: bool = false,
+ PROCESS_CREATE: bool = false,
+ PROCESS_EXEC: bool = false,
+ PROCESS_EXIT: bool = false,
+ THREAD_CREATE: bool = false,
+ THREAD_EXIT: bool = false,
+ CONTEXT_SWITCH: bool = false,
+ KMALLOC: bool = false,
+ KFREE: bool = false,
+ PAGE_FAULT: bool = false,
+ SYSCALL: bool = false,
+ SIGNPOST: bool = false,
+ FILESYSTEM: bool = false,
+};
+
+// https://github.com/SerenityOS/serenity/blob/abc150085f532f123b598949218893cb272ccc4c/Userland/Libraries/LibC/serenity.h
+
+pub extern "c" fn disown(pid: pid_t) c_int;
+
+pub extern "c" fn profiling_enable(pid: pid_t, event_mask: PERF_EVENT) c_int;
+pub extern "c" fn profiling_disable(pid: pid_t) c_int;
+pub extern "c" fn profiling_free_buffer(pid: pid_t) c_int;
+
+pub extern "c" fn futex(userspace_address: *u32, futex_op: c_int, value: u32, timeout: *const timespec, userspace_address2: *u32, value3: u32) c_int;
+pub extern "c" fn futex_wait(userspace_address: *u32, value: u32, abstime: *const timespec, clockid: clockid_t, process_shared: c_int) c_int;
+pub extern "c" fn futex_wake(userspace_address: *u32, count: u32, process_shared: c_int) c_int;
+
+pub extern "c" fn purge(mode: c_int) c_int;
+
+pub extern "c" fn perf_event(type: PERF_EVENT, arg1: usize, arg2: usize) c_int;
+pub extern "c" fn perf_register_string(string: [*]const u8, string_length: usize) c_int;
+
+pub extern "c" fn get_stack_bounds(user_stack_base: *usize, user_stack_size: *usize) c_int;
+
+pub extern "c" fn anon_create(size: usize, options: O) c_int;
+
+pub extern "c" fn serenity_readlink(path: [*]const u8, path_length: usize, buffer: [*]u8, buffer_size: usize) c_int;
+pub extern "c" fn serenity_open(path: [*]const u8, path_length: usize, options: c_int, ...) c_int;
+
+pub extern "c" fn getkeymap(name_buffer: [*]u8, name_buffer_size: usize, map: [*]u32, shift_map: [*]u32, alt_map: [*]u32, altgr_map: [*]u32, shift_altgr_map: [*]u32) c_int;
+pub extern "c" fn setkeymap(name: [*]const u8, map: [*]const u32, shift_map: [*]const u32, alt_map: [*]const u32, altgr_map: [*]const u32, shift_altgr_map: [*]const u32) c_int;
+
+pub extern "c" fn internet_checksum(ptr: *const anyopaque, count: usize) u16;
diff --git a/lib/std/crypto/Certificate.zig b/lib/std/crypto/Certificate.zig
index 9ca6aa5e48..c89141ec7d 100644
--- a/lib/std/crypto/Certificate.zig
+++ b/lib/std/crypto/Certificate.zig
@@ -607,11 +607,10 @@ const Date = struct {
}
{
- const is_leap = std.time.epoch.isLeapYear(date.year);
var month: u4 = 1;
while (month < date.month) : (month += 1) {
const days: u64 = std.time.epoch.getDaysInMonth(
- @as(std.time.epoch.YearLeapKind, @enumFromInt(@intFromBool(is_leap))),
+ date.year,
@as(std.time.epoch.Month, @enumFromInt(month)),
);
sec += days * std.time.epoch.secs_per_day;
diff --git a/lib/std/crypto/Certificate/Bundle.zig b/lib/std/crypto/Certificate/Bundle.zig
index 627cd4172b..a74eb44a91 100644
--- a/lib/std/crypto/Certificate/Bundle.zig
+++ b/lib/std/crypto/Certificate/Bundle.zig
@@ -50,7 +50,7 @@ pub fn deinit(cb: *Bundle, gpa: Allocator) void {
cb.* = undefined;
}
-pub const RescanError = RescanLinuxError || RescanMacError || RescanBSDError || RescanWindowsError;
+pub const RescanError = RescanLinuxError || RescanMacError || RescanWithPathError || RescanWindowsError;
/// Clears the set of certificates and then scans the host operating system
/// file system standard locations for certificates.
@@ -60,10 +60,12 @@ pub fn rescan(cb: *Bundle, gpa: Allocator) RescanError!void {
switch (builtin.os.tag) {
.linux => return rescanLinux(cb, gpa),
.macos => return rescanMac(cb, gpa),
- .freebsd, .openbsd => return rescanBSD(cb, gpa, "/etc/ssl/cert.pem"),
- .netbsd => return rescanBSD(cb, gpa, "/etc/openssl/certs/ca-certificates.crt"),
- .dragonfly => return rescanBSD(cb, gpa, "/usr/local/etc/ssl/cert.pem"),
- .solaris, .illumos => return rescanBSD(cb, gpa, "/etc/ssl/cacert.pem"),
+ .freebsd, .openbsd => return rescanWithPath(cb, gpa, "/etc/ssl/cert.pem"),
+ .netbsd => return rescanWithPath(cb, gpa, "/etc/openssl/certs/ca-certificates.crt"),
+ .dragonfly => return rescanWithPath(cb, gpa, "/usr/local/etc/ssl/cert.pem"),
+ .solaris, .illumos => return rescanWithPath(cb, gpa, "/etc/ssl/cacert.pem"),
+ // https://github.com/SerenityOS/serenity/blob/222acc9d389bc6b490d4c39539761b043a4bfcb0/Ports/ca-certificates/package.sh#L19
+ .serenity => return rescanWithPath(cb, gpa, "/etc/ssl/certs/ca-certificates.crt"),
.windows => return rescanWindows(cb, gpa),
else => {},
}
@@ -116,9 +118,9 @@ fn rescanLinux(cb: *Bundle, gpa: Allocator) RescanLinuxError!void {
cb.bytes.shrinkAndFree(gpa, cb.bytes.items.len);
}
-const RescanBSDError = AddCertsFromFilePathError;
+const RescanWithPathError = AddCertsFromFilePathError;
-fn rescanBSD(cb: *Bundle, gpa: Allocator, cert_file_path: []const u8) RescanBSDError!void {
+fn rescanWithPath(cb: *Bundle, gpa: Allocator, cert_file_path: []const u8) RescanWithPathError!void {
cb.bytes.clearRetainingCapacity();
cb.map.clearRetainingCapacity();
try addCertsFromFilePathAbsolute(cb, gpa, cert_file_path);
diff --git a/lib/std/fs.zig b/lib/std/fs.zig
index 99936e9abd..fc2da3de72 100644
--- a/lib/std/fs.zig
+++ b/lib/std/fs.zig
@@ -52,7 +52,7 @@ pub const MAX_PATH_BYTES = @compileError("deprecated; renamed to max_path_bytes"
/// * On other platforms, `[]u8` file paths are opaque sequences of bytes with
/// no particular encoding.
pub const max_path_bytes = switch (native_os) {
- .linux, .macos, .ios, .freebsd, .openbsd, .netbsd, .dragonfly, .haiku, .solaris, .illumos, .plan9, .emscripten, .wasi => posix.PATH_MAX,
+ .linux, .macos, .ios, .freebsd, .openbsd, .netbsd, .dragonfly, .haiku, .solaris, .illumos, .plan9, .emscripten, .wasi, .serenity => posix.PATH_MAX,
// Each WTF-16LE code unit may be expanded to 3 WTF-8 bytes.
// If it would require 4 WTF-8 bytes, then there would be a surrogate
// pair in the WTF-16LE, and we (over)account 3 bytes for it that way.
@@ -73,7 +73,7 @@ pub const max_path_bytes = switch (native_os) {
/// On WASI, file name components are encoded as valid UTF-8.
/// On other platforms, `[]u8` components are an opaque sequence of bytes with no particular encoding.
pub const max_name_bytes = switch (native_os) {
- .linux, .macos, .ios, .freebsd, .openbsd, .netbsd, .dragonfly, .solaris, .illumos => posix.NAME_MAX,
+ .linux, .macos, .ios, .freebsd, .openbsd, .netbsd, .dragonfly, .solaris, .illumos, .serenity => posix.NAME_MAX,
// Haiku's NAME_MAX includes the null terminator, so subtract one.
.haiku => posix.NAME_MAX - 1,
// Each WTF-16LE character may be expanded to 3 WTF-8 bytes.
@@ -466,7 +466,7 @@ pub fn symLinkAbsoluteZ(
pub const OpenSelfExeError = posix.OpenError || SelfExePathError || posix.FlockError;
pub fn openSelfExe(flags: File.OpenFlags) OpenSelfExeError!File {
- if (native_os == .linux) {
+ if (native_os == .linux or native_os == .serenity) {
return openFileAbsoluteZ("/proc/self/exe", flags);
}
if (native_os == .windows) {
@@ -572,7 +572,7 @@ pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 {
return result;
}
switch (native_os) {
- .linux => return posix.readlinkZ("/proc/self/exe", out_buffer) catch |err| switch (err) {
+ .linux, .serenity => return posix.readlinkZ("/proc/self/exe", out_buffer) catch |err| switch (err) {
error.InvalidUtf8 => unreachable, // WASI-only
error.InvalidWtf8 => unreachable, // Windows-only
error.UnsupportedReparsePointType => unreachable, // Windows-only
diff --git a/lib/std/fs/get_app_data_dir.zig b/lib/std/fs/get_app_data_dir.zig
index cce99ea8cc..a256758a07 100644
--- a/lib/std/fs/get_app_data_dir.zig
+++ b/lib/std/fs/get_app_data_dir.zig
@@ -30,7 +30,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, .illumos => {
+ .linux, .freebsd, .netbsd, .dragonfly, .openbsd, .solaris, .illumos, .serenity => {
if (posix.getenv("XDG_DATA_HOME")) |xdg| {
if (xdg.len > 0) {
return fs.path.join(allocator, &[_][]const u8{ xdg, appname });
diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig
index 98fef1b2ce..546435f4ab 100644
--- a/lib/std/fs/test.zig
+++ b/lib/std/fs/test.zig
@@ -320,14 +320,8 @@ test "accessAbsolute" {
var tmp = tmpDir(.{});
defer tmp.cleanup();
- var arena = ArenaAllocator.init(testing.allocator);
- defer arena.deinit();
- const allocator = arena.allocator();
-
- const base_path = blk: {
- const relative_path = try fs.path.join(allocator, &.{ ".zig-cache", "tmp", tmp.sub_path[0..] });
- break :blk try fs.realpathAlloc(allocator, relative_path);
- };
+ const base_path = try tmp.dir.realpathAlloc(testing.allocator, ".");
+ defer testing.allocator.free(base_path);
try fs.accessAbsolute(base_path, .{});
}
@@ -338,25 +332,52 @@ test "openDirAbsolute" {
var tmp = tmpDir(.{});
defer tmp.cleanup();
+ const tmp_ino = (try tmp.dir.stat()).inode;
+
try tmp.dir.makeDir("subdir");
- var arena = ArenaAllocator.init(testing.allocator);
- defer arena.deinit();
- const allocator = arena.allocator();
+ const sub_path = try tmp.dir.realpathAlloc(testing.allocator, "subdir");
+ defer testing.allocator.free(sub_path);
- const base_path = blk: {
- const relative_path = try fs.path.join(allocator, &.{ ".zig-cache", "tmp", tmp.sub_path[0..], "subdir" });
- break :blk try fs.realpathAlloc(allocator, relative_path);
- };
+ // Can open sub_path
+ var tmp_sub = try fs.openDirAbsolute(sub_path, .{});
+ defer tmp_sub.close();
+
+ const sub_ino = (try tmp_sub.stat()).inode;
{
- var dir = try fs.openDirAbsolute(base_path, .{});
+ // Can open sub_path + ".."
+ const dir_path = try fs.path.join(testing.allocator, &.{ sub_path, ".." });
+ defer testing.allocator.free(dir_path);
+
+ var dir = try fs.openDirAbsolute(dir_path, .{});
defer dir.close();
+
+ const ino = (try dir.stat()).inode;
+ try testing.expectEqual(tmp_ino, ino);
}
- for ([_][]const u8{ ".", ".." }) |sub_path| {
- const dir_path = try fs.path.join(allocator, &.{ base_path, sub_path });
+ {
+ // Can open sub_path + "."
+ const dir_path = try fs.path.join(testing.allocator, &.{ sub_path, "." });
+ defer testing.allocator.free(dir_path);
+
var dir = try fs.openDirAbsolute(dir_path, .{});
defer dir.close();
+
+ const ino = (try dir.stat()).inode;
+ try testing.expectEqual(sub_ino, ino);
+ }
+
+ {
+ // Can open subdir + "..", with some extra "."
+ const dir_path = try fs.path.join(testing.allocator, &.{ sub_path, ".", "..", "." });
+ defer testing.allocator.free(dir_path);
+
+ var dir = try fs.openDirAbsolute(dir_path, .{});
+ defer dir.close();
+
+ const ino = (try dir.stat()).inode;
+ try testing.expectEqual(tmp_ino, ino);
}
}
@@ -409,10 +430,7 @@ test "readLinkAbsolute" {
defer arena.deinit();
const allocator = arena.allocator();
- const base_path = blk: {
- const relative_path = try fs.path.join(allocator, &.{ ".zig-cache", "tmp", tmp.sub_path[0..] });
- break :blk try fs.realpathAlloc(allocator, relative_path);
- };
+ const base_path = try tmp.dir.realpathAlloc(allocator, ".");
{
const target_path = try fs.path.join(allocator, &.{ base_path, "file.txt" });
@@ -748,7 +766,6 @@ test "directory operations on files" {
test "file operations on directories" {
// TODO: fix this test on FreeBSD. https://github.com/ziglang/zig/issues/1759
if (native_os == .freebsd) return error.SkipZigTest;
- if (native_os == .wasi and builtin.link_libc) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/20747
try testWithAllSupportedPathTypes(struct {
fn impl(ctx: *TestContext) !void {
@@ -759,18 +776,30 @@ test "file operations on directories" {
try testing.expectError(error.IsDir, ctx.dir.createFile(test_dir_name, .{}));
try testing.expectError(error.IsDir, ctx.dir.deleteFile(test_dir_name));
switch (native_os) {
- // no error when reading a directory.
- .dragonfly, .netbsd => {},
- // Currently, WASI will return error.Unexpected (via ENOTCAPABLE) when attempting fd_read on a directory handle.
- // TODO: Re-enable on WASI once https://github.com/bytecodealliance/wasmtime/issues/1935 is resolved.
- .wasi => {},
+ .dragonfly, .netbsd => {
+ // no error when reading a directory. See https://github.com/ziglang/zig/issues/5732
+ const buf = try ctx.dir.readFileAlloc(testing.allocator, test_dir_name, std.math.maxInt(usize));
+ testing.allocator.free(buf);
+ },
+ .wasi => {
+ // WASI return EBADF, which gets mapped to NotOpenForReading.
+ // See https://github.com/bytecodealliance/wasmtime/issues/1935
+ try testing.expectError(error.NotOpenForReading, ctx.dir.readFileAlloc(testing.allocator, test_dir_name, std.math.maxInt(usize)));
+ },
else => {
try testing.expectError(error.IsDir, ctx.dir.readFileAlloc(testing.allocator, test_dir_name, std.math.maxInt(usize)));
},
}
- // Note: The `.mode = .read_write` is necessary to ensure the error occurs on all platforms.
- // TODO: Add a read-only test as well, see https://github.com/ziglang/zig/issues/5732
- try testing.expectError(error.IsDir, ctx.dir.openFile(test_dir_name, .{ .mode = .read_write }));
+
+ if (native_os == .wasi and builtin.link_libc) {
+ // wasmtime unexpectedly succeeds here, see https://github.com/ziglang/zig/issues/20747
+ const handle = try ctx.dir.openFile(test_dir_name, .{ .mode = .read_write });
+ handle.close();
+ } else {
+ // Note: The `.mode = .read_write` is necessary to ensure the error occurs on all platforms.
+ // TODO: Add a read-only test as well, see https://github.com/ziglang/zig/issues/5732
+ try testing.expectError(error.IsDir, ctx.dir.openFile(test_dir_name, .{ .mode = .read_write }));
+ }
if (ctx.path_type == .absolute and comptime PathType.absolute.isSupported(builtin.os)) {
try testing.expectError(error.IsDir, fs.createFileAbsolute(test_dir_name, .{}));
@@ -993,10 +1022,7 @@ test "renameAbsolute" {
defer arena.deinit();
const allocator = arena.allocator();
- const base_path = blk: {
- const relative_path = try fs.path.join(allocator, &.{ ".zig-cache", "tmp", tmp_dir.sub_path[0..] });
- break :blk try fs.realpathAlloc(allocator, relative_path);
- };
+ const base_path = try tmp_dir.dir.realpathAlloc(allocator, ".");
try testing.expectError(error.FileNotFound, fs.renameAbsolute(
try fs.path.join(allocator, &.{ base_path, "missing_file_name" }),
@@ -1386,7 +1412,6 @@ test "sendfile" {
defer tmp.cleanup();
try tmp.dir.makePath("os_test_tmp");
- defer tmp.dir.deleteTree("os_test_tmp") catch {};
var dir = try tmp.dir.openDir("os_test_tmp", .{});
defer dir.close();
@@ -1451,7 +1476,6 @@ test "copyRangeAll" {
defer tmp.cleanup();
try tmp.dir.makePath("os_test_tmp");
- defer tmp.dir.deleteTree("os_test_tmp") catch {};
var dir = try tmp.dir.openDir("os_test_tmp", .{});
defer dir.close();
@@ -1800,10 +1824,7 @@ test "'.' and '..' in absolute functions" {
defer arena.deinit();
const allocator = arena.allocator();
- const base_path = blk: {
- const relative_path = try fs.path.join(allocator, &.{ ".zig-cache", "tmp", tmp.sub_path[0..] });
- break :blk try fs.realpathAlloc(allocator, relative_path);
- };
+ const base_path = try tmp.dir.realpathAlloc(allocator, ".");
const subdir_path = try fs.path.join(allocator, &.{ base_path, "./subdir" });
try fs.makeDirAbsolute(subdir_path);
diff --git a/lib/std/io/test.zig b/lib/std/io/test.zig
index 6505fcd4fa..523b25c9c8 100644
--- a/lib/std/io/test.zig
+++ b/lib/std/io/test.zig
@@ -108,10 +108,7 @@ test "File seek ops" {
const tmp_file_name = "temp_test_file.txt";
var file = try tmp.dir.createFile(tmp_file_name, .{});
- defer {
- file.close();
- tmp.dir.deleteFile(tmp_file_name) catch {};
- }
+ defer file.close();
try file.writeAll(&([_]u8{0x55} ** 8192));
@@ -135,10 +132,7 @@ test "setEndPos" {
const tmp_file_name = "temp_test_file.txt";
var file = try tmp.dir.createFile(tmp_file_name, .{});
- defer {
- file.close();
- tmp.dir.deleteFile(tmp_file_name) catch {};
- }
+ defer file.close();
// Verify that the file size changes and the file offset is not moved
try std.testing.expect((try file.getEndPos()) == 0);
@@ -161,10 +155,8 @@ test "updateTimes" {
const tmp_file_name = "just_a_temporary_file.txt";
var file = try tmp.dir.createFile(tmp_file_name, .{ .read = true });
- defer {
- file.close();
- tmp.dir.deleteFile(tmp_file_name) catch {};
- }
+ defer file.close();
+
const stat_old = try file.stat();
// Set atime and mtime to 5s before
try file.updateTimes(
diff --git a/lib/std/mem/Allocator.zig b/lib/std/mem/Allocator.zig
index 1ad9533116..8ca7ed669b 100644
--- a/lib/std/mem/Allocator.zig
+++ b/lib/std/mem/Allocator.zig
@@ -308,7 +308,8 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
/// In such case, it is more efficient for the caller to perform those
/// operations.
///
-/// `allocation` may be an empty slice, in which case a new allocation is made.
+/// `allocation` may be an empty slice, in which case `null` is returned,
+/// unless `new_len` is also 0, in which case `allocation` is returned.
///
/// `new_len` may be zero, in which case the allocation is freed.
pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: {
diff --git a/lib/std/multi_array_list.zig b/lib/std/multi_array_list.zig
index 7d68322c90..0df825187b 100644
--- a/lib/std/multi_array_list.zig
+++ b/lib/std/multi_array_list.zig
@@ -248,8 +248,8 @@ pub fn MultiArrayList(comptime T: type) type {
/// Extend the list by 1 element, returning the newly reserved
/// index with uninitialized data.
/// Allocates more memory as necesasry.
- pub fn addOne(self: *Self, allocator: Allocator) Allocator.Error!usize {
- try self.ensureUnusedCapacity(allocator, 1);
+ pub fn addOne(self: *Self, gpa: Allocator) Allocator.Error!usize {
+ try self.ensureUnusedCapacity(gpa, 1);
return self.addOneAssumeCapacity();
}
diff --git a/lib/std/os.zig b/lib/std/os.zig
index 80f45dd59d..45568caf3c 100644
--- a/lib/std/os.zig
+++ b/lib/std/os.zig
@@ -82,6 +82,7 @@ pub fn isGetFdPathSupportedOnTarget(os: std.Target.Os) bool {
.solaris,
.illumos,
.freebsd,
+ .serenity,
=> true,
.dragonfly => os.version_range.semver.max.order(.{ .major = 6, .minor = 0, .patch = 0 }) != .lt,
@@ -127,7 +128,7 @@ pub fn getFdPath(fd: std.posix.fd_t, out_buffer: *[max_path_bytes]u8) std.posix.
const len = mem.indexOfScalar(u8, out_buffer[0..], 0) orelse max_path_bytes;
return out_buffer[0..len];
},
- .linux => {
+ .linux, .serenity => {
var procfs_buf: ["/proc/self/fd/-2147483648\x00".len]u8 = undefined;
const proc_path = std.fmt.bufPrintZ(procfs_buf[0..], "/proc/self/fd/{d}", .{fd}) catch unreachable;
diff --git a/lib/std/os/uefi.zig b/lib/std/os/uefi.zig
index f7e51c63aa..9674e704dc 100644
--- a/lib/std/os/uefi.zig
+++ b/lib/std/os/uefi.zig
@@ -141,11 +141,10 @@ pub const Time = extern struct {
pub const unspecified_timezone: i16 = 0x7ff;
fn daysInYear(year: u16, max_month: u4) u9 {
- const leap_year: std.time.epoch.YearLeapKind = if (std.time.epoch.isLeapYear(year)) .leap else .not_leap;
var days: u9 = 0;
var month: u4 = 0;
while (month < max_month) : (month += 1) {
- days += std.time.epoch.getDaysInMonth(leap_year, @enumFromInt(month + 1));
+ days += std.time.epoch.getDaysInMonth(year, @enumFromInt(month + 1));
}
return days;
}
diff --git a/lib/std/os/uefi/status.zig b/lib/std/os/uefi/status.zig
index 5c86520194..2e17ef64c9 100644
--- a/lib/std/os/uefi/status.zig
+++ b/lib/std/os/uefi/status.zig
@@ -231,11 +231,57 @@ pub const Status = enum(usize) {
else => {},
}
}
+
+ pub fn fromError(e: Error) Status {
+ return switch (e) {
+ Error.Aborted => .aborted,
+ Error.AccessDenied => .access_denied,
+ Error.AlreadyStarted => .already_started,
+ Error.BadBufferSize => .bad_buffer_size,
+ Error.BufferTooSmall => .buffer_too_small,
+ Error.CompromisedData => .compromised_data,
+ Error.ConnectionFin => .connection_fin,
+ Error.ConnectionRefused => .connection_refused,
+ Error.ConnectionReset => .connection_reset,
+ Error.CrcError => .crc_error,
+ Error.DeviceError => .device_error,
+ Error.EndOfFile => .end_of_file,
+ Error.EndOfMedia => .end_of_media,
+ Error.HostUnreachable => .host_unreachable,
+ Error.HttpError => .http_error,
+ Error.IcmpError => .icmp_error,
+ Error.IncompatibleVersion => .incompatible_version,
+ Error.InvalidLanguage => .invalid_language,
+ Error.InvalidParameter => .invalid_parameter,
+ Error.IpAddressConflict => .ip_address_conflict,
+ Error.LoadError => .load_error,
+ Error.MediaChanged => .media_changed,
+ Error.NetworkUnreachable => .network_unreachable,
+ Error.NoMapping => .no_mapping,
+ Error.NoMedia => .no_media,
+ Error.NoResponse => .no_response,
+ Error.NotFound => .not_found,
+ Error.NotReady => .not_ready,
+ Error.NotStarted => .not_started,
+ Error.OutOfResources => .out_of_resources,
+ Error.PortUnreachable => .port_unreachable,
+ Error.ProtocolError => .protocol_error,
+ Error.ProtocolUnreachable => .protocol_unreachable,
+ Error.SecurityViolation => .security_violation,
+ Error.TftpError => .tftp_error,
+ Error.Timeout => .timeout,
+ Error.Unsupported => .unsupported,
+ Error.VolumeCorrupted => .volume_corrupted,
+ Error.VolumeFull => .volume_full,
+ Error.WriteProtected => .write_protected,
+ };
+ }
};
test "status" {
var st: Status = .device_error;
try testing.expectError(error.DeviceError, st.err());
+ try testing.expectEqual(st, Status.fromError(st.err()));
st = .success;
try st.err();
diff --git a/lib/std/posix/test.zig b/lib/std/posix/test.zig
index 29756cae69..9678bfb261 100644
--- a/lib/std/posix/test.zig
+++ b/lib/std/posix/test.zig
@@ -8,7 +8,6 @@ const io = std.io;
const fs = std.fs;
const mem = std.mem;
const elf = std.elf;
-const File = std.fs.File;
const Thread = std.Thread;
const linux = std.os.linux;
@@ -19,8 +18,6 @@ const AtomicRmwOp = std.builtin.AtomicRmwOp;
const AtomicOrder = std.builtin.AtomicOrder;
const native_os = builtin.target.os.tag;
const tmpDir = std.testing.tmpDir;
-const Dir = std.fs.Dir;
-const ArenaAllocator = std.heap.ArenaAllocator;
// https://github.com/ziglang/zig/issues/20288
test "WTF-8 to WTF-16 conversion buffer overflows" {
@@ -115,50 +112,62 @@ test "open smoke test" {
var tmp = tmpDir(.{});
defer tmp.cleanup();
- // Get base abs path
- var arena = ArenaAllocator.init(testing.allocator);
- defer arena.deinit();
- const allocator = arena.allocator();
+ const base_path = try tmp.dir.realpathAlloc(a, ".");
+ defer a.free(base_path);
- const base_path = blk: {
- const relative_path = try fs.path.join(allocator, &[_][]const u8{ ".zig-cache", "tmp", tmp.sub_path[0..] });
- break :blk try fs.realpathAlloc(allocator, relative_path);
- };
-
- var file_path: []u8 = undefined;
- var fd: posix.fd_t = undefined;
const mode: posix.mode_t = if (native_os == .windows) 0 else 0o666;
- // Create some file using `open`.
- file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" });
- fd = try posix.open(file_path, .{ .ACCMODE = .RDWR, .CREAT = true, .EXCL = true }, mode);
- posix.close(fd);
+ {
+ // Create some file using `open`.
+ const file_path = try fs.path.join(a, &.{ base_path, "some_file" });
+ defer a.free(file_path);
+ const fd = try posix.open(file_path, .{ .ACCMODE = .RDWR, .CREAT = true, .EXCL = true }, mode);
+ posix.close(fd);
+ }
- // Try this again with the same flags. This op should fail with error.PathAlreadyExists.
- file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" });
- try expectError(error.PathAlreadyExists, posix.open(file_path, .{ .ACCMODE = .RDWR, .CREAT = true, .EXCL = true }, mode));
+ {
+ // Try this again with the same flags. This op should fail with error.PathAlreadyExists.
+ const file_path = try fs.path.join(a, &.{ base_path, "some_file" });
+ defer a.free(file_path);
+ try expectError(error.PathAlreadyExists, posix.open(file_path, .{ .ACCMODE = .RDWR, .CREAT = true, .EXCL = true }, mode));
+ }
- // Try opening without `EXCL` flag.
- file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" });
- fd = try posix.open(file_path, .{ .ACCMODE = .RDWR, .CREAT = true }, mode);
- posix.close(fd);
+ {
+ // Try opening without `EXCL` flag.
+ const file_path = try fs.path.join(a, &.{ base_path, "some_file" });
+ defer a.free(file_path);
+ const fd = try posix.open(file_path, .{ .ACCMODE = .RDWR, .CREAT = true }, mode);
+ posix.close(fd);
+ }
- // Try opening as a directory which should fail.
- file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" });
- try expectError(error.NotDir, posix.open(file_path, .{ .ACCMODE = .RDWR, .DIRECTORY = true }, mode));
+ {
+ // Try opening as a directory which should fail.
+ const file_path = try fs.path.join(a, &.{ base_path, "some_file" });
+ defer a.free(file_path);
+ try expectError(error.NotDir, posix.open(file_path, .{ .ACCMODE = .RDWR, .DIRECTORY = true }, mode));
+ }
- // Create some directory
- file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_dir" });
- try posix.mkdir(file_path, mode);
+ {
+ // Create some directory
+ const file_path = try fs.path.join(a, &.{ base_path, "some_dir" });
+ defer a.free(file_path);
+ try posix.mkdir(file_path, mode);
+ }
- // Open dir using `open`
- file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_dir" });
- fd = try posix.open(file_path, .{ .ACCMODE = .RDONLY, .DIRECTORY = true }, mode);
- posix.close(fd);
+ {
+ // Open dir using `open`
+ const file_path = try fs.path.join(a, &.{ base_path, "some_dir" });
+ defer a.free(file_path);
+ const fd = try posix.open(file_path, .{ .ACCMODE = .RDONLY, .DIRECTORY = true }, mode);
+ posix.close(fd);
+ }
- // Try opening as file which should fail.
- file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_dir" });
- try expectError(error.IsDir, posix.open(file_path, .{ .ACCMODE = .RDWR }, mode));
+ {
+ // Try opening as file which should fail.
+ const file_path = try fs.path.join(a, &.{ base_path, "some_dir" });
+ defer a.free(file_path);
+ try expectError(error.IsDir, posix.open(file_path, .{ .ACCMODE = .RDWR }, mode));
+ }
}
test "openat smoke test" {
@@ -705,8 +714,6 @@ test "mmap" {
try testing.expectEqual(i, try stream.readInt(u32, .little));
}
}
-
- try tmp.dir.deleteFile(test_out_file);
}
test "getenv" {
@@ -732,10 +739,7 @@ test "fcntl" {
const test_out_file = "os_tmp_test";
const file = try tmp.dir.createFile(test_out_file, .{});
- defer {
- file.close();
- tmp.dir.deleteFile(test_out_file) catch {};
- }
+ defer file.close();
// Note: The test assumes createFile opens the file with CLOEXEC
{
@@ -771,10 +775,7 @@ test "sync" {
const test_out_file = "os_tmp_test";
const file = try tmp.dir.createFile(test_out_file, .{});
- defer {
- file.close();
- tmp.dir.deleteFile(test_out_file) catch {};
- }
+ defer file.close();
posix.sync();
try posix.syncfs(file.handle);
@@ -791,10 +792,7 @@ test "fsync" {
const test_out_file = "os_tmp_test";
const file = try tmp.dir.createFile(test_out_file, .{});
- defer {
- file.close();
- tmp.dir.deleteFile(test_out_file) catch {};
- }
+ defer file.close();
try posix.fsync(file.handle);
try posix.fdatasync(file.handle);
@@ -1041,54 +1039,65 @@ test "rename smoke test" {
var tmp = tmpDir(.{});
defer tmp.cleanup();
- // Get base abs path
- var arena = ArenaAllocator.init(testing.allocator);
- defer arena.deinit();
- const allocator = arena.allocator();
-
- const base_path = blk: {
- const relative_path = try fs.path.join(allocator, &[_][]const u8{ ".zig-cache", "tmp", tmp.sub_path[0..] });
- break :blk try fs.realpathAlloc(allocator, relative_path);
- };
+ const base_path = try tmp.dir.realpathAlloc(a, ".");
+ defer a.free(base_path);
- var file_path: []u8 = undefined;
- var fd: posix.fd_t = undefined;
const mode: posix.mode_t = if (native_os == .windows) 0 else 0o666;
- // Create some file using `open`.
- file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" });
- fd = try posix.open(file_path, .{ .ACCMODE = .RDWR, .CREAT = true, .EXCL = true }, mode);
- posix.close(fd);
-
- // Rename the file
- var new_file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_other_file" });
- try posix.rename(file_path, new_file_path);
-
- // Try opening renamed file
- file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_other_file" });
- fd = try posix.open(file_path, .{ .ACCMODE = .RDWR }, mode);
- posix.close(fd);
+ {
+ // Create some file using `open`.
+ const file_path = try fs.path.join(a, &.{ base_path, "some_file" });
+ defer a.free(file_path);
+ const fd = try posix.open(file_path, .{ .ACCMODE = .RDWR, .CREAT = true, .EXCL = true }, mode);
+ posix.close(fd);
+
+ // Rename the file
+ const new_file_path = try fs.path.join(a, &.{ base_path, "some_other_file" });
+ defer a.free(new_file_path);
+ try posix.rename(file_path, new_file_path);
+ }
- // Try opening original file - should fail with error.FileNotFound
- file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" });
- try expectError(error.FileNotFound, posix.open(file_path, .{ .ACCMODE = .RDWR }, mode));
+ {
+ // Try opening renamed file
+ const file_path = try fs.path.join(a, &.{ base_path, "some_other_file" });
+ defer a.free(file_path);
+ const fd = try posix.open(file_path, .{ .ACCMODE = .RDWR }, mode);
+ posix.close(fd);
+ }
- // Create some directory
- file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_dir" });
- try posix.mkdir(file_path, mode);
+ {
+ // Try opening original file - should fail with error.FileNotFound
+ const file_path = try fs.path.join(a, &.{ base_path, "some_file" });
+ defer a.free(file_path);
+ try expectError(error.FileNotFound, posix.open(file_path, .{ .ACCMODE = .RDWR }, mode));
+ }
- // Rename the directory
- new_file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_other_dir" });
- try posix.rename(file_path, new_file_path);
+ {
+ // Create some directory
+ const file_path = try fs.path.join(a, &.{ base_path, "some_dir" });
+ defer a.free(file_path);
+ try posix.mkdir(file_path, mode);
+
+ // Rename the directory
+ const new_file_path = try fs.path.join(a, &.{ base_path, "some_other_dir" });
+ defer a.free(new_file_path);
+ try posix.rename(file_path, new_file_path);
+ }
- // Try opening renamed directory
- file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_other_dir" });
- fd = try posix.open(file_path, .{ .ACCMODE = .RDONLY, .DIRECTORY = true }, mode);
- posix.close(fd);
+ {
+ // Try opening renamed directory
+ const file_path = try fs.path.join(a, &.{ base_path, "some_other_dir" });
+ defer a.free(file_path);
+ const fd = try posix.open(file_path, .{ .ACCMODE = .RDONLY, .DIRECTORY = true }, mode);
+ posix.close(fd);
+ }
- // Try opening original directory - should fail with error.FileNotFound
- file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_dir" });
- try expectError(error.FileNotFound, posix.open(file_path, .{ .ACCMODE = .RDONLY, .DIRECTORY = true }, mode));
+ {
+ // Try opening original directory - should fail with error.FileNotFound
+ const file_path = try fs.path.join(a, &.{ base_path, "some_dir" });
+ defer a.free(file_path);
+ try expectError(error.FileNotFound, posix.open(file_path, .{ .ACCMODE = .RDONLY, .DIRECTORY = true }, mode));
+ }
}
test "access smoke test" {
@@ -1098,44 +1107,50 @@ test "access smoke test" {
var tmp = tmpDir(.{});
defer tmp.cleanup();
- // Get base abs path
- var arena = ArenaAllocator.init(testing.allocator);
- defer arena.deinit();
- const allocator = arena.allocator();
-
- const base_path = blk: {
- const relative_path = try fs.path.join(allocator, &[_][]const u8{ ".zig-cache", "tmp", tmp.sub_path[0..] });
- break :blk try fs.realpathAlloc(allocator, relative_path);
- };
+ const base_path = try tmp.dir.realpathAlloc(a, ".");
+ defer a.free(base_path);
- var file_path: []u8 = undefined;
- var fd: posix.fd_t = undefined;
const mode: posix.mode_t = if (native_os == .windows) 0 else 0o666;
+ {
+ // Create some file using `open`.
+ const file_path = try fs.path.join(a, &.{ base_path, "some_file" });
+ defer a.free(file_path);
+ const fd = try posix.open(file_path, .{ .ACCMODE = .RDWR, .CREAT = true, .EXCL = true }, mode);
+ posix.close(fd);
+ }
- // Create some file using `open`.
- file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" });
- fd = try posix.open(file_path, .{ .ACCMODE = .RDWR, .CREAT = true, .EXCL = true }, mode);
- posix.close(fd);
+ {
+ // Try to access() the file
+ const file_path = try fs.path.join(a, &.{ base_path, "some_file" });
+ defer a.free(file_path);
+ if (native_os == .windows) {
+ try posix.access(file_path, posix.F_OK);
+ } else {
+ try posix.access(file_path, posix.F_OK | posix.W_OK | posix.R_OK);
+ }
+ }
- // Try to access() the file
- file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" });
- if (native_os == .windows) {
- try posix.access(file_path, posix.F_OK);
- } else {
- try posix.access(file_path, posix.F_OK | posix.W_OK | posix.R_OK);
+ {
+ // Try to access() a non-existent file - should fail with error.FileNotFound
+ const file_path = try fs.path.join(a, &.{ base_path, "some_other_file" });
+ defer a.free(file_path);
+ try expectError(error.FileNotFound, posix.access(file_path, posix.F_OK));
}
- // Try to access() a non-existent file - should fail with error.FileNotFound
- file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_other_file" });
- try expectError(error.FileNotFound, posix.access(file_path, posix.F_OK));
+ {
+ // Create some directory
+ const file_path = try fs.path.join(a, &.{ base_path, "some_dir" });
+ defer a.free(file_path);
+ try posix.mkdir(file_path, mode);
+ }
- // Create some directory
- file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_dir" });
- try posix.mkdir(file_path, mode);
+ {
+ // Try to access() the directory
+ const file_path = try fs.path.join(a, &.{ base_path, "some_dir" });
+ defer a.free(file_path);
- // Try to access() the directory
- file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_dir" });
- try posix.access(file_path, posix.F_OK);
+ try posix.access(file_path, posix.F_OK);
+ }
}
test "timerfd" {
@@ -1167,103 +1182,59 @@ test "isatty" {
}
test "read with empty buffer" {
- if (native_os == .wasi) return error.SkipZigTest;
-
var tmp = tmpDir(.{});
defer tmp.cleanup();
- var arena = ArenaAllocator.init(testing.allocator);
- defer arena.deinit();
- const allocator = arena.allocator();
-
- // Get base abs path
- const base_path = blk: {
- const relative_path = try fs.path.join(allocator, &[_][]const u8{ ".zig-cache", "tmp", tmp.sub_path[0..] });
- break :blk try fs.realpathAlloc(allocator, relative_path);
- };
-
- const file_path: []u8 = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" });
- var file = try fs.cwd().createFile(file_path, .{ .read = true });
+ var file = try tmp.dir.createFile("read_empty", .{ .read = true });
defer file.close();
- const bytes = try allocator.alloc(u8, 0);
+ const bytes = try a.alloc(u8, 0);
+ defer a.free(bytes);
- _ = try posix.read(file.handle, bytes);
+ const rc = try posix.read(file.handle, bytes);
+ try expectEqual(rc, 0);
}
test "pread with empty buffer" {
- if (native_os == .wasi) return error.SkipZigTest;
-
var tmp = tmpDir(.{});
defer tmp.cleanup();
- var arena = ArenaAllocator.init(testing.allocator);
- defer arena.deinit();
- const allocator = arena.allocator();
-
- // Get base abs path
- const base_path = blk: {
- const relative_path = try fs.path.join(allocator, &[_][]const u8{ ".zig-cache", "tmp", tmp.sub_path[0..] });
- break :blk try fs.realpathAlloc(allocator, relative_path);
- };
-
- const file_path: []u8 = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" });
- var file = try fs.cwd().createFile(file_path, .{ .read = true });
+ var file = try tmp.dir.createFile("pread_empty", .{ .read = true });
defer file.close();
- const bytes = try allocator.alloc(u8, 0);
+ const bytes = try a.alloc(u8, 0);
+ defer a.free(bytes);
- _ = try posix.pread(file.handle, bytes, 0);
+ const rc = try posix.pread(file.handle, bytes, 0);
+ try expectEqual(rc, 0);
}
test "write with empty buffer" {
- if (native_os == .wasi) return error.SkipZigTest;
-
var tmp = tmpDir(.{});
defer tmp.cleanup();
- var arena = ArenaAllocator.init(testing.allocator);
- defer arena.deinit();
- const allocator = arena.allocator();
-
- // Get base abs path
- const base_path = blk: {
- const relative_path = try fs.path.join(allocator, &[_][]const u8{ ".zig-cache", "tmp", tmp.sub_path[0..] });
- break :blk try fs.realpathAlloc(allocator, relative_path);
- };
-
- const file_path: []u8 = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" });
- var file = try fs.cwd().createFile(file_path, .{});
+ var file = try tmp.dir.createFile("write_empty", .{});
defer file.close();
- const bytes = try allocator.alloc(u8, 0);
+ const bytes = try a.alloc(u8, 0);
+ defer a.free(bytes);
- _ = try posix.write(file.handle, bytes);
+ const rc = try posix.write(file.handle, bytes);
+ try expectEqual(rc, 0);
}
test "pwrite with empty buffer" {
- if (native_os == .wasi) return error.SkipZigTest;
-
var tmp = tmpDir(.{});
defer tmp.cleanup();
- var arena = ArenaAllocator.init(testing.allocator);
- defer arena.deinit();
- const allocator = arena.allocator();
-
- // Get base abs path
- const base_path = blk: {
- const relative_path = try fs.path.join(allocator, &[_][]const u8{ ".zig-cache", "tmp", tmp.sub_path[0..] });
- break :blk try fs.realpathAlloc(allocator, relative_path);
- };
-
- const file_path: []u8 = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" });
- var file = try fs.cwd().createFile(file_path, .{});
+ var file = try tmp.dir.createFile("pwrite_empty", .{});
defer file.close();
- const bytes = try allocator.alloc(u8, 0);
+ const bytes = try a.alloc(u8, 0);
+ defer a.free(bytes);
- _ = try posix.pwrite(file.handle, bytes, 0);
+ const rc = try posix.pwrite(file.handle, bytes, 0);
+ try expectEqual(rc, 0);
}
fn expectMode(dir: posix.fd_t, file: []const u8, mode: posix.mode_t) !void {
diff --git a/lib/std/process.zig b/lib/std/process.zig
index dd08e88af2..b734276444 100644
--- a/lib/std/process.zig
+++ b/lib/std/process.zig
@@ -1539,6 +1539,7 @@ pub fn getUserInfo(name: []const u8) !UserInfo {
.haiku,
.solaris,
.illumos,
+ .serenity,
=> posixGetUserInfo(name),
else => @compileError("Unsupported OS"),
};
diff --git a/lib/std/time/epoch.zig b/lib/std/time/epoch.zig
index b409d3e9eb..fa7499aec7 100644
--- a/lib/std/time/epoch.zig
+++ b/lib/std/time/epoch.zig
@@ -64,8 +64,6 @@ pub fn getDaysInYear(year: Year) u9 {
return if (isLeapYear(year)) 366 else 365;
}
-pub const YearLeapKind = enum(u1) { not_leap, leap };
-
pub const Month = enum(u4) {
jan = 1,
feb,
@@ -87,13 +85,13 @@ pub const Month = enum(u4) {
}
};
-/// Get the number of days in the given month
-pub fn getDaysInMonth(leap_year: YearLeapKind, month: Month) u5 {
+/// Get the number of days in the given month and year
+pub fn getDaysInMonth(year: Year, month: Month) u5 {
return switch (month) {
.jan => 31,
- .feb => @as(u5, switch (leap_year) {
- .leap => 29,
- .not_leap => 28,
+ .feb => @as(u5, switch (isLeapYear(year)) {
+ true => 29,
+ false => 28,
}),
.mar => 31,
.apr => 30,
@@ -116,9 +114,8 @@ pub const YearAndDay = struct {
pub fn calculateMonthDay(self: YearAndDay) MonthAndDay {
var month: Month = .jan;
var days_left = self.day;
- const leap_kind: YearLeapKind = if (isLeapYear(self.year)) .leap else .not_leap;
while (true) {
- const days_in_month = getDaysInMonth(leap_kind, month);
+ const days_in_month = getDaysInMonth(self.year, month);
if (days_left < days_in_month)
break;
days_left -= days_in_month;
diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig
index 84f9cf7330..a4b16d6c46 100644
--- a/lib/std/zig/system.zig
+++ b/lib/std/zig/system.zig
@@ -539,7 +539,7 @@ pub fn abiAndDynamicLinkerFromFile(
var result: Target = .{
.cpu = cpu,
.os = os,
- .abi = query.abi orelse Target.Abi.default(cpu.arch, os),
+ .abi = query.abi orelse Target.Abi.default(cpu.arch, os.tag),
.ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch),
.dynamic_linker = query.dynamic_linker,
};
@@ -1213,7 +1213,7 @@ fn detectAbiAndDynamicLinker(
}
fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, query: Target.Query) Target {
- const abi = query.abi orelse Target.Abi.default(cpu.arch, os);
+ const abi = query.abi orelse Target.Abi.default(cpu.arch, os.tag);
return .{
.cpu = cpu,
.os = os,
diff --git a/lib/std/zig/target.zig b/lib/std/zig/target.zig
index f4c6ae6885..ee46288903 100644
--- a/lib/std/zig/target.zig
+++ b/lib/std/zig/target.zig
@@ -318,6 +318,17 @@ pub fn isLibCLibName(target: std.Target, name: []const u8) bool {
return true;
}
+ if (target.os.tag == .serenity) {
+ if (eqlIgnoreCase(ignore_case, name, "dl"))
+ return true;
+ if (eqlIgnoreCase(ignore_case, name, "m"))
+ return true;
+ if (eqlIgnoreCase(ignore_case, name, "pthread"))
+ return true;
+ if (eqlIgnoreCase(ignore_case, name, "ssp"))
+ return true;
+ }
+
return false;
}
diff --git a/src/Compilation.zig b/src/Compilation.zig
index 12221ba3dc..51f6293fc8 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -2261,7 +2261,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
zcu.compile_log_text.shrinkAndFree(gpa, 0);
- zcu.skip_analysis_errors = false;
+ zcu.skip_analysis_this_update = false;
// Make sure std.zig is inside the import_table. We unconditionally need
// it for start.zig.
@@ -2336,6 +2336,17 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
const pt: Zcu.PerThread = .activate(zcu, .main);
defer pt.deactivate();
+ if (!zcu.skip_analysis_this_update) {
+ if (comp.config.is_test) {
+ // The `test_functions` decl has been intentionally postponed until now,
+ // at which point we must populate it with the list of test functions that
+ // have been discovered and not filtered out.
+ try pt.populateTestFunctions(main_progress_node);
+ }
+
+ try pt.processExports();
+ }
+
if (build_options.enable_debug_extensions and comp.verbose_intern_pool) {
std.debug.print("intern pool stats for '{s}':\n", .{
comp.root_name,
@@ -2350,15 +2361,6 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
});
zcu.intern_pool.dumpGenericInstances(gpa);
}
-
- if (comp.config.is_test) {
- // The `test_functions` decl has been intentionally postponed until now,
- // at which point we must populate it with the list of test functions that
- // have been discovered and not filtered out.
- try pt.populateTestFunctions(main_progress_node);
- }
-
- try pt.processExports();
}
if (anyErrors(comp)) {
@@ -3310,7 +3312,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
}
}
}
- if (zcu.skip_analysis_errors) break :zcu_errors;
+ if (zcu.skip_analysis_this_update) break :zcu_errors;
var sorted_failed_analysis: std.AutoArrayHashMapUnmanaged(InternPool.AnalUnit, *Zcu.ErrorMsg).DataList.Slice = s: {
const SortOrder = struct {
zcu: *Zcu,
@@ -3446,7 +3448,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
try comp.link_diags.addMessagesToBundle(&bundle, comp.bin_file);
if (comp.zcu) |zcu| {
- if (!zcu.skip_analysis_errors and bundle.root_list.items.len == 0 and zcu.compile_log_sources.count() != 0) {
+ if (!zcu.skip_analysis_this_update and bundle.root_list.items.len == 0 and zcu.compile_log_sources.count() != 0) {
const values = zcu.compile_log_sources.values();
// First one will be the error; subsequent ones will be notes.
const src_loc = values[0].src();
@@ -3957,7 +3959,7 @@ fn performAllTheWorkInner(
// However, this means our analysis data is invalid, so we want to omit all analysis errors.
assert(zcu.failed_files.count() > 0); // we will get an error
- zcu.skip_analysis_errors = true;
+ zcu.skip_analysis_this_update = true;
return;
}
@@ -5631,7 +5633,10 @@ pub fn addCCArgs(
}
if (target_util.llvmMachineAbi(target)) |mabi| {
- try argv.append(try std.fmt.allocPrint(arena, "-mabi={s}", .{mabi}));
+ // Clang's integrated Arm assembler doesn't support `-mabi` yet...
+ if (!(target.cpu.arch.isArm() and (ext == .assembly or ext == .assembly_with_cpp))) {
+ try argv.append(try std.fmt.allocPrint(arena, "-mabi={s}", .{mabi}));
+ }
}
// We might want to support -mfloat-abi=softfp for Arm and CSKY here in the future.
@@ -6026,17 +6031,19 @@ pub fn addCCArgs(
// function was called.
try argv.append("-fno-sanitize=function");
- // It's recommended to use the minimal runtime in production environments
- // due to the security implications of the full runtime. The minimal runtime
- // doesn't provide much benefit over simply trapping.
if (mod.optimize_mode == .ReleaseSafe) {
+ // It's recommended to use the minimal runtime in production
+ // environments due to the security implications of the full runtime.
+ // The minimal runtime doesn't provide much benefit over simply
+ // trapping, however, so we do that instead.
try argv.append("-fsanitize-trap=undefined");
- }
-
- // This is necessary because, by default, Clang instructs LLVM to embed a COFF link
- // dependency on `libclang_rt.ubsan_standalone.a` when the UBSan runtime is used.
- if (target.os.tag == .windows) {
- try argv.append("-fno-rtlib-defaultlib");
+ } else {
+ // This is necessary because, by default, Clang instructs LLVM to embed
+ // a COFF link dependency on `libclang_rt.ubsan_standalone.a` when the
+ // UBSan runtime is used.
+ if (target.os.tag == .windows) {
+ try argv.append("-fno-rtlib-defaultlib");
+ }
}
}
}
diff --git a/src/Package/Fetch.zig b/src/Package/Fetch.zig
index 61a01e3ab3..bb70518910 100644
--- a/src/Package/Fetch.zig
+++ b/src/Package/Fetch.zig
@@ -1850,7 +1850,11 @@ const FileHeader = struct {
return magic_number == std.macho.MH_MAGIC or
magic_number == std.macho.MH_MAGIC_64 or
magic_number == std.macho.FAT_MAGIC or
- magic_number == std.macho.FAT_MAGIC_64;
+ magic_number == std.macho.FAT_MAGIC_64 or
+ magic_number == std.macho.MH_CIGAM or
+ magic_number == std.macho.MH_CIGAM_64 or
+ magic_number == std.macho.FAT_CIGAM or
+ magic_number == std.macho.FAT_CIGAM_64;
}
pub fn isExecutable(self: *FileHeader) bool {
@@ -1875,6 +1879,11 @@ test FileHeader {
h.bytes_read = 0;
h.update(&macho64_magic_bytes);
try std.testing.expect(h.isExecutable());
+
+ const macho64_cigam_bytes = [_]u8{ 0xFE, 0xED, 0xFA, 0xCF };
+ h.bytes_read = 0;
+ h.update(&macho64_cigam_bytes);
+ try std.testing.expect(h.isExecutable());
}
// Result of the `unpackResource` operation. Enables collecting errors from
diff --git a/src/Sema.zig b/src/Sema.zig
index 1ef3834b61..8368ca3515 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -17860,11 +17860,18 @@ fn zirThis(
const zcu = pt.zcu;
const namespace = pt.zcu.namespacePtr(block.namespace);
- const new_ty = try pt.ensureTypeUpToDate(namespace.owner_type);
-
- switch (pt.zcu.intern_pool.indexToKey(new_ty)) {
- .struct_type, .union_type => try sema.declareDependency(.{ .interned = new_ty }),
+ switch (pt.zcu.intern_pool.indexToKey(namespace.owner_type)) {
+ .opaque_type => {
+ // Opaque types are never outdated since they don't undergo type resolution, so nothing to do!
+ return Air.internedToRef(namespace.owner_type);
+ },
+ .struct_type, .union_type => {
+ const new_ty = try pt.ensureTypeUpToDate(namespace.owner_type);
+ try sema.declareDependency(.{ .interned = new_ty });
+ return Air.internedToRef(new_ty);
+ },
.enum_type => {
+ const new_ty = try pt.ensureTypeUpToDate(namespace.owner_type);
try sema.declareDependency(.{ .interned = new_ty });
// Since this is an enum, it has to be resolved immediately.
// `ensureTypeUpToDate` has resolved the new type if necessary.
@@ -17873,11 +17880,10 @@ fn zirThis(
if (zcu.failed_analysis.contains(ty_unit) or zcu.transitive_failed_analysis.contains(ty_unit)) {
return error.AnalysisFail;
}
+ return Air.internedToRef(new_ty);
},
- .opaque_type => {},
else => unreachable,
}
- return Air.internedToRef(new_ty);
}
fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
@@ -36742,7 +36748,7 @@ fn unionFields(
if (enum_index != field_i) {
const msg = msg: {
const enum_field_src: LazySrcLoc = .{
- .base_node_inst = tag_info.zir_index.unwrap().?,
+ .base_node_inst = Type.fromInterned(tag_ty).typeDeclInstAllowGeneratedTag(zcu).?,
.offset = .{ .container_field_name = enum_index },
};
const msg = try sema.errMsg(name_src, "union field '{}' ordered differently than corresponding enum field", .{
@@ -38052,6 +38058,11 @@ fn compareScalar(
const pt = sema.pt;
const coerced_lhs = try pt.getCoerced(lhs, ty);
const coerced_rhs = try pt.getCoerced(rhs, ty);
+
+ // Equality comparisons of signed zero and NaN need to use floating point semantics
+ if (coerced_lhs.isFloat(pt.zcu) or coerced_rhs.isFloat(pt.zcu))
+ return Value.compareHeteroSema(coerced_lhs, op, coerced_rhs, pt);
+
switch (op) {
.eq => return sema.valuesEqual(coerced_lhs, coerced_rhs, ty),
.neq => return !(try sema.valuesEqual(coerced_lhs, coerced_rhs, ty)),
diff --git a/src/Value.zig b/src/Value.zig
index be2c73c3e9..40e5331c4e 100644
--- a/src/Value.zig
+++ b/src/Value.zig
@@ -1132,6 +1132,8 @@ pub fn compareHeteroAdvanced(
else => {},
}
}
+
+ if (lhs.isNan(zcu) or rhs.isNan(zcu)) return op == .neq;
return (try orderAdvanced(lhs, rhs, strat, zcu, tid)).compare(op);
}
diff --git a/src/Zcu.zig b/src/Zcu.zig
index 30bb6e5b3c..28b7ba1b65 100644
--- a/src/Zcu.zig
+++ b/src/Zcu.zig
@@ -181,7 +181,10 @@ analysis_roots: std.BoundedArray(*Package.Module, 4) = .{},
/// Allocated into `gpa`.
resolved_references: ?std.AutoHashMapUnmanaged(AnalUnit, ?ResolvedReference) = null,
-skip_analysis_errors: bool = false,
+/// If `true`, then semantic analysis must not occur on this update due to AstGen errors.
+/// Essentially the entire pipeline after AstGen, including Sema, codegen, and link, is skipped.
+/// Reset to `false` at the start of each update in `Compilation.update`.
+skip_analysis_this_update: bool = false,
stage1_flags: packed struct {
have_winmain: bool = false,
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig
index 4af9b01257..2a9e25500c 100644
--- a/src/arch/x86_64/CodeGen.zig
+++ b/src/arch/x86_64/CodeGen.zig
@@ -2437,7 +2437,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
try cg.airArg(inst);
- try cg.resetTemps();
+ try cg.resetTemps(@enumFromInt(0));
cg.checkInvariantsAfterAirInst();
},
else => break,
@@ -2477,7 +2477,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.shuffle => try cg.airShuffle(inst),
.reduce => try cg.airReduce(inst),
.reduce_optimized => try cg.airReduce(inst),
- .aggregate_init => try cg.airAggregateInit(inst),
// zig fmt: on
.arg => if (cg.debug_output != .none) {
@@ -80843,6 +80842,74 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
for (ops[1..]) |op| try op.die(cg);
try res[0].finish(inst, &.{ty_op.operand}, ops[0..1], cg);
},
+ .aggregate_init => |air_tag| if (use_old) try cg.airAggregateInit(inst) else fallback: {
+ const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
+ const agg_ty = ty_pl.ty.toType();
+ if ((agg_ty.isVector(zcu) and agg_ty.childType(zcu).toIntern() == .bool_type) or
+ (agg_ty.zigTypeTag(zcu) == .@"struct" and agg_ty.containerLayout(zcu) == .@"packed")) break :fallback try cg.airAggregateInit(inst);
+ var res = try cg.tempAllocMem(agg_ty);
+ const reset_index = cg.next_temp_index;
+ var bt = cg.liveness.iterateBigTomb(inst);
+ switch (ip.indexToKey(agg_ty.toIntern())) {
+ inline .array_type, .vector_type => |sequence_type| {
+ const elems: []const Air.Inst.Ref = @ptrCast(cg.air.extra[ty_pl.payload..][0..@intCast(sequence_type.len)]);
+ const elem_size = Type.fromInterned(sequence_type.child).abiSize(zcu);
+ var elem_disp: u31 = 0;
+ for (elems) |elem_ref| {
+ var elem = try cg.tempFromOperand(elem_ref, bt.feed());
+ try res.write(&elem, .{ .disp = elem_disp }, cg);
+ try elem.die(cg);
+ try cg.resetTemps(reset_index);
+ elem_disp += @intCast(elem_size);
+ }
+ if (@hasField(@TypeOf(sequence_type), "sentinel") and sequence_type.sentinel != .none) {
+ var sentinel = try cg.tempFromValue(.fromInterned(sequence_type.sentinel));
+ try res.write(&sentinel, .{ .disp = elem_disp }, cg);
+ try sentinel.die(cg);
+ }
+ },
+ .struct_type => {
+ const loaded_struct = ip.loadStructType(agg_ty.toIntern());
+ const elems: []const Air.Inst.Ref = @ptrCast(cg.air.extra[ty_pl.payload..][0..loaded_struct.field_types.len]);
+ switch (loaded_struct.layout) {
+ .auto, .@"extern" => {
+ for (elems, 0..) |elem_ref, field_index| {
+ const elem_dies = bt.feed();
+ if (loaded_struct.fieldIsComptime(ip, field_index)) continue;
+ var elem = try cg.tempFromOperand(elem_ref, elem_dies);
+ try res.write(&elem, .{ .disp = @intCast(loaded_struct.offsets.get(ip)[field_index]) }, cg);
+ try elem.die(cg);
+ try cg.resetTemps(reset_index);
+ }
+ },
+ .@"packed" => return cg.fail("failed to select {s} {}", .{
+ @tagName(air_tag),
+ agg_ty.fmt(pt),
+ }),
+ }
+ },
+ .tuple_type => |tuple_type| {
+ const elems: []const Air.Inst.Ref = @ptrCast(cg.air.extra[ty_pl.payload..][0..tuple_type.types.len]);
+ var elem_disp: u31 = 0;
+ for (elems, 0..) |elem_ref, field_index| {
+ const elem_dies = bt.feed();
+ if (tuple_type.values.get(ip)[field_index] != .none) continue;
+ const field_type = Type.fromInterned(tuple_type.types.get(ip)[field_index]);
+ elem_disp = @intCast(field_type.abiAlignment(zcu).forward(elem_disp));
+ var elem = try cg.tempFromOperand(elem_ref, elem_dies);
+ try res.write(&elem, .{ .disp = elem_disp }, cg);
+ try elem.die(cg);
+ try cg.resetTemps(reset_index);
+ elem_disp += @intCast(field_type.abiSize(zcu));
+ }
+ },
+ else => return cg.fail("failed to select {s} {}", .{
+ @tagName(air_tag),
+ agg_ty.fmt(pt),
+ }),
+ }
+ try res.finish(inst, &.{}, &.{}, cg);
+ },
.union_init => if (use_old) try cg.airUnionInit(inst) else {
const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
const extra = cg.air.extraData(Air.UnionInit, ty_pl.payload).data;
@@ -82199,14 +82266,14 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.c_va_start => try cg.airVaStart(inst),
.work_item_id, .work_group_size, .work_group_id => unreachable,
}
- try cg.resetTemps();
+ try cg.resetTemps(@enumFromInt(0));
cg.checkInvariantsAfterAirInst();
}
verbose_tracking_log.debug("{}", .{cg.fmtTracking()});
}
-fn genLazy(self: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
- const pt = self.pt;
+fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
+ const pt = cg.pt;
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
switch (ip.indexToKey(lazy_sym.ty)) {
@@ -82215,97 +82282,98 @@ fn genLazy(self: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
wip_mir_log.debug("{}.@tagName:", .{enum_ty.fmt(pt)});
const param_regs = abi.getCAbiIntParamRegs(.auto);
- const param_locks = self.register_manager.lockRegsAssumeUnused(2, param_regs[0..2].*);
- defer for (param_locks) |lock| self.register_manager.unlockReg(lock);
+ const param_locks = cg.register_manager.lockRegsAssumeUnused(2, param_regs[0..2].*);
+ defer for (param_locks) |lock| cg.register_manager.unlockReg(lock);
const ret_mcv: MCValue = .{ .register_pair = param_regs[0..2].* };
- const enum_mcv: MCValue = .{ .register = param_regs[0] };
+ var enum_temp = try cg.tempInit(enum_ty, .{ .register = param_regs[0] });
- const data_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
- const data_lock = self.register_manager.lockRegAssumeUnused(data_reg);
- defer self.register_manager.unlockReg(data_lock);
- try self.genLazySymbolRef(.lea, data_reg, .{ .kind = .const_data, .ty = lazy_sym.ty });
+ const data_reg = try cg.register_manager.allocReg(null, abi.RegisterClass.gp);
+ const data_lock = cg.register_manager.lockRegAssumeUnused(data_reg);
+ defer cg.register_manager.unlockReg(data_lock);
+ try cg.genLazySymbolRef(.lea, data_reg, .{ .kind = .const_data, .ty = lazy_sym.ty });
var data_off: i32 = 0;
+ const reset_index = cg.next_temp_index;
const tag_names = ip.loadEnumType(lazy_sym.ty).names;
for (0..tag_names.len) |tag_index| {
- var enum_temp = try self.tempInit(enum_ty, enum_mcv);
-
const tag_name_len = tag_names.get(ip)[tag_index].length(ip);
- var tag_temp = try self.tempFromValue(try pt.enumValueFieldIndex(enum_ty, @intCast(tag_index)));
- const cc_temp = enum_temp.cmpInts(.neq, &tag_temp, self) catch |err| switch (err) {
+ var tag_temp = try cg.tempFromValue(try pt.enumValueFieldIndex(enum_ty, @intCast(tag_index)));
+ const cc_temp = enum_temp.cmpInts(.neq, &tag_temp, cg) catch |err| switch (err) {
error.SelectFailed => unreachable,
else => |e| return e,
};
- try enum_temp.die(self);
- try tag_temp.die(self);
- const skip_reloc = try self.asmJccReloc(cc_temp.tracking(self).short.eflags, undefined);
- try cc_temp.die(self);
- try self.resetTemps();
+ try tag_temp.die(cg);
+ const skip_reloc = try cg.asmJccReloc(cc_temp.tracking(cg).short.eflags, undefined);
+ try cc_temp.die(cg);
+ try cg.resetTemps(reset_index);
- try self.genSetReg(
+ try cg.genSetReg(
ret_mcv.register_pair[0],
.usize,
.{ .register_offset = .{ .reg = data_reg, .off = data_off } },
.{},
);
- try self.genSetReg(ret_mcv.register_pair[1], .usize, .{ .immediate = tag_name_len }, .{});
- try self.asmOpOnly(.{ ._, .ret });
+ try cg.genSetReg(ret_mcv.register_pair[1], .usize, .{ .immediate = tag_name_len }, .{});
+ try cg.asmOpOnly(.{ ._, .ret });
- self.performReloc(skip_reloc);
+ cg.performReloc(skip_reloc);
data_off += @intCast(tag_name_len + 1);
}
+ try enum_temp.die(cg);
- try self.genSetReg(ret_mcv.register_pair[0], .usize, .{ .immediate = 0 }, .{});
- try self.asmOpOnly(.{ ._, .ret });
+ try cg.genSetReg(ret_mcv.register_pair[0], .usize, .{ .immediate = 0 }, .{});
+ try cg.asmOpOnly(.{ ._, .ret });
},
.error_set_type => |error_set_type| {
const err_ty: Type = .fromInterned(lazy_sym.ty);
wip_mir_log.debug("{}.@errorCast:", .{err_ty.fmt(pt)});
const param_regs = abi.getCAbiIntParamRegs(.auto);
- const param_locks = self.register_manager.lockRegsAssumeUnused(2, param_regs[0..2].*);
- defer for (param_locks) |lock| self.register_manager.unlockReg(lock);
+ const param_locks = cg.register_manager.lockRegsAssumeUnused(2, param_regs[0..2].*);
+ defer for (param_locks) |lock| cg.register_manager.unlockReg(lock);
const ret_mcv: MCValue = .{ .register = param_regs[0] };
const err_mcv: MCValue = .{ .register = param_regs[0] };
+ var err_temp = try cg.tempInit(err_ty, err_mcv);
const ExpectedContents = [32]Mir.Inst.Index;
var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) =
- std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
+ std.heap.stackFallback(@sizeOf(ExpectedContents), cg.gpa);
const allocator = stack.get();
const relocs = try allocator.alloc(Mir.Inst.Index, error_set_type.names.len);
defer allocator.free(relocs);
+ const reset_index = cg.next_temp_index;
for (0.., relocs) |tag_index, *reloc| {
- var err_temp = try self.tempInit(err_ty, err_mcv);
-
- var tag_temp = try self.tempInit(.anyerror, .{
+ var tag_temp = try cg.tempInit(.anyerror, .{
.immediate = ip.getErrorValueIfExists(error_set_type.names.get(ip)[tag_index]).?,
});
- const cc_temp = err_temp.cmpInts(.eq, &tag_temp, self) catch |err| switch (err) {
+ const cc_temp = err_temp.cmpInts(.eq, &tag_temp, cg) catch |err| switch (err) {
error.SelectFailed => unreachable,
else => |e| return e,
};
- try err_temp.die(self);
- try tag_temp.die(self);
- reloc.* = try self.asmJccReloc(cc_temp.tracking(self).short.eflags, undefined);
- try cc_temp.die(self);
- try self.resetTemps();
+ try tag_temp.die(cg);
+ reloc.* = try cg.asmJccReloc(cc_temp.tracking(cg).short.eflags, undefined);
+ try cc_temp.die(cg);
+ try cg.resetTemps(reset_index);
}
+ try err_temp.die(cg);
- try self.genCopy(.usize, ret_mcv, .{ .immediate = 0 }, .{});
- for (relocs) |reloc| self.performReloc(reloc);
+ try cg.genCopy(.usize, ret_mcv, .{ .immediate = 0 }, .{});
+ for (relocs) |reloc| cg.performReloc(reloc);
assert(ret_mcv.register == err_mcv.register);
- try self.asmOpOnly(.{ ._, .ret });
+ try cg.asmOpOnly(.{ ._, .ret });
},
- else => return self.fail(
+ else => return cg.fail(
"TODO implement {s} for {}",
.{ @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt) },
),
}
+ try cg.resetTemps(@enumFromInt(0));
+ cg.checkInvariantsAfterAirInst();
}
fn getValue(self: *CodeGen, value: MCValue, inst: ?Air.Inst.Index) !void {
@@ -93621,17 +93689,17 @@ fn lowerBlock(self: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index
}
fn lowerSwitchBr(
- self: *CodeGen,
+ cg: *CodeGen,
inst: Air.Inst.Index,
switch_br: Air.UnwrappedSwitch,
condition: MCValue,
condition_dies: bool,
is_loop: bool,
) !void {
- const zcu = self.pt.zcu;
- const condition_ty = self.typeOf(switch_br.operand);
- const condition_int_info = self.intInfo(condition_ty).?;
- const condition_int_ty = try self.pt.intType(condition_int_info.signedness, condition_int_info.bits);
+ const zcu = cg.pt.zcu;
+ const condition_ty = cg.typeOf(switch_br.operand);
+ const condition_int_info = cg.intInfo(condition_ty).?;
+ const condition_int_ty = try cg.pt.intType(condition_int_info.signedness, condition_int_info.bits);
const ExpectedContents = extern struct {
liveness_deaths: [1 << 8 | 1]Air.Inst.Index,
@@ -93639,15 +93707,15 @@ fn lowerSwitchBr(
relocs: [1 << 6]Mir.Inst.Index,
};
var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) =
- std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
+ std.heap.stackFallback(@sizeOf(ExpectedContents), cg.gpa);
const allocator = stack.get();
- const state = try self.saveState();
+ const state = try cg.saveState();
- const liveness = try self.liveness.getSwitchBr(allocator, inst, switch_br.cases_len + 1);
+ const liveness = try cg.liveness.getSwitchBr(allocator, inst, switch_br.cases_len + 1);
defer allocator.free(liveness.deaths);
- if (!self.mod.pic and self.target.ofmt == .elf) table: {
+ if (!cg.mod.pic and cg.target.ofmt == .elf) table: {
var prong_items: u32 = 0;
var min: ?Value = null;
var max: ?Value = null;
@@ -93690,41 +93758,41 @@ fn lowerSwitchBr(
if (prong_items < table_len >> 2) break :table; // no more than 75% waste
const condition_index = if (condition_dies and condition.isModifiable()) condition else condition_index: {
- const condition_index = try self.allocTempRegOrMem(condition_ty, true);
- try self.genCopy(condition_ty, condition_index, condition, .{});
+ const condition_index = try cg.allocTempRegOrMem(condition_ty, true);
+ try cg.genCopy(condition_ty, condition_index, condition, .{});
break :condition_index condition_index;
};
- try self.spillEflagsIfOccupied();
- if (min.?.orderAgainstZero(zcu).compare(.neq)) try self.genBinOpMir(
+ try cg.spillEflagsIfOccupied();
+ if (min.?.orderAgainstZero(zcu).compare(.neq)) try cg.genBinOpMir(
.{ ._, .sub },
condition_ty,
condition_index,
.{ .air_ref = Air.internedToRef(min.?.toIntern()) },
);
const else_reloc = if (switch_br.else_body_len > 0) else_reloc: {
- var cond_temp = try self.tempInit(condition_ty, condition_index);
- var table_max_temp = try self.tempFromValue(try self.pt.intValue(condition_int_ty, table_len - 1));
- const cc_temp = cond_temp.cmpInts(.gt, &table_max_temp, self) catch |err| switch (err) {
+ var cond_temp = try cg.tempInit(condition_ty, condition_index);
+ var table_max_temp = try cg.tempFromValue(try cg.pt.intValue(condition_int_ty, table_len - 1));
+ const cc_temp = cond_temp.cmpInts(.gt, &table_max_temp, cg) catch |err| switch (err) {
error.SelectFailed => unreachable,
else => |e| return e,
};
- try cond_temp.die(self);
- try table_max_temp.die(self);
- const else_reloc = try self.asmJccReloc(cc_temp.tracking(self).short.eflags, undefined);
- try cc_temp.die(self);
+ try cond_temp.die(cg);
+ try table_max_temp.die(cg);
+ const else_reloc = try cg.asmJccReloc(cc_temp.tracking(cg).short.eflags, undefined);
+ try cc_temp.die(cg);
break :else_reloc else_reloc;
} else undefined;
- const table_start: u31 = @intCast(self.mir_table.items.len);
+ const table_start: u31 = @intCast(cg.mir_table.items.len);
{
const condition_index_reg = if (condition_index.isRegister())
condition_index.getReg().?
else
- try self.copyToTmpRegister(.usize, condition_index);
- const condition_index_lock = self.register_manager.lockReg(condition_index_reg);
- defer if (condition_index_lock) |lock| self.register_manager.unlockReg(lock);
- try self.truncateRegister(condition_ty, condition_index_reg);
- const ptr_size = @divExact(self.target.ptrBitWidth(), 8);
- try self.asmMemory(.{ ._mp, .j }, .{
+ try cg.copyToTmpRegister(.usize, condition_index);
+ const condition_index_lock = cg.register_manager.lockReg(condition_index_reg);
+ defer if (condition_index_lock) |lock| cg.register_manager.unlockReg(lock);
+ try cg.truncateRegister(condition_ty, condition_index_reg);
+ const ptr_size = @divExact(cg.target.ptrBitWidth(), 8);
+ try cg.asmMemory(.{ ._mp, .j }, .{
.base = .table,
.mod = .{ .rm = .{
.size = .ptr,
@@ -93735,32 +93803,32 @@ fn lowerSwitchBr(
});
}
const else_reloc_marker: u32 = 0;
- assert(self.mir_instructions.len > else_reloc_marker);
- try self.mir_table.appendNTimes(self.gpa, else_reloc_marker, table_len);
- if (is_loop) try self.loop_switches.putNoClobber(self.gpa, inst, .{
+ assert(cg.mir_instructions.len > else_reloc_marker);
+ try cg.mir_table.appendNTimes(cg.gpa, else_reloc_marker, table_len);
+ if (is_loop) try cg.loop_switches.putNoClobber(cg.gpa, inst, .{
.start = table_start,
.len = table_len,
.min = min.?,
.else_relocs = if (switch_br.else_body_len > 0) .{ .forward = .empty } else .@"unreachable",
});
defer if (is_loop) {
- var loop_switch_data = self.loop_switches.fetchRemove(inst).?.value;
+ var loop_switch_data = cg.loop_switches.fetchRemove(inst).?.value;
switch (loop_switch_data.else_relocs) {
.@"unreachable", .backward => {},
- .forward => |*else_relocs| else_relocs.deinit(self.gpa),
+ .forward => |*else_relocs| else_relocs.deinit(cg.gpa),
}
};
var cases_it = switch_br.iterateCases();
while (cases_it.next()) |case| {
{
- const table = self.mir_table.items[table_start..][0..table_len];
+ const table = cg.mir_table.items[table_start..][0..table_len];
for (case.items) |item| {
const val = Value.fromInterned(item.toInterned().?);
var val_space: Value.BigIntSpace = undefined;
const val_bigint = val.toBigInt(&val_space, zcu);
var index_bigint: std.math.big.int.Mutable = .{ .limbs = limbs, .positive = undefined, .len = undefined };
index_bigint.sub(val_bigint, min_bigint);
- table[index_bigint.toConst().to(u10) catch unreachable] = @intCast(self.mir_instructions.len);
+ table[index_bigint.toConst().to(u10) catch unreachable] = @intCast(cg.mir_instructions.len);
}
for (case.ranges) |range| {
var low_space: Value.BigIntSpace = undefined;
@@ -93772,14 +93840,14 @@ fn lowerSwitchBr(
const start = index_bigint.toConst().to(u10) catch unreachable;
index_bigint.sub(high_bigint, min_bigint);
const end = @as(u11, index_bigint.toConst().to(u10) catch unreachable) + 1;
- @memset(table[start..end], @intCast(self.mir_instructions.len));
+ @memset(table[start..end], @intCast(cg.mir_instructions.len));
}
}
- for (liveness.deaths[case.idx]) |operand| try self.processDeath(operand);
+ for (liveness.deaths[case.idx]) |operand| try cg.processDeath(operand);
- try self.genBodyBlock(case.body);
- try self.restoreState(state, &.{}, .{
+ try cg.genBodyBlock(case.body);
+ try cg.restoreState(state, &.{}, .{
.emit_instructions = false,
.update_tracking = true,
.resurrect = true,
@@ -93790,21 +93858,21 @@ fn lowerSwitchBr(
const else_body = cases_it.elseBody();
const else_deaths = liveness.deaths.len - 1;
- for (liveness.deaths[else_deaths]) |operand| try self.processDeath(operand);
+ for (liveness.deaths[else_deaths]) |operand| try cg.processDeath(operand);
- self.performReloc(else_reloc);
+ cg.performReloc(else_reloc);
if (is_loop) {
- const loop_switch_data = self.loop_switches.getPtr(inst).?;
- for (loop_switch_data.else_relocs.forward.items) |reloc| self.performReloc(reloc);
- loop_switch_data.else_relocs.forward.deinit(self.gpa);
- loop_switch_data.else_relocs = .{ .backward = @intCast(self.mir_instructions.len) };
+ const loop_switch_data = cg.loop_switches.getPtr(inst).?;
+ for (loop_switch_data.else_relocs.forward.items) |reloc| cg.performReloc(reloc);
+ loop_switch_data.else_relocs.forward.deinit(cg.gpa);
+ loop_switch_data.else_relocs = .{ .backward = @intCast(cg.mir_instructions.len) };
}
- for (self.mir_table.items[table_start..][0..table_len]) |*entry| if (entry.* == else_reloc_marker) {
- entry.* = @intCast(self.mir_instructions.len);
+ for (cg.mir_table.items[table_start..][0..table_len]) |*entry| if (entry.* == else_reloc_marker) {
+ entry.* = @intCast(cg.mir_instructions.len);
};
- try self.genBodyBlock(else_body);
- try self.restoreState(state, &.{}, .{
+ try cg.genBodyBlock(else_body);
+ try cg.restoreState(state, &.{}, .{
.emit_instructions = false,
.update_tracking = true,
.resurrect = true,
@@ -93819,9 +93887,12 @@ fn lowerSwitchBr(
const relocs = try allocator.alloc(Mir.Inst.Index, case.items.len + case.ranges.len);
defer allocator.free(relocs);
- try self.spillEflagsIfOccupied();
+ var cond_temp = try cg.tempInit(condition_ty, condition);
+ const reset_index = cg.next_temp_index;
+
+ try cg.spillEflagsIfOccupied();
for (case.items, relocs[0..case.items.len]) |item, *reloc| {
- const item_mcv = try self.resolveInst(item);
+ const item_mcv = try cg.resolveInst(item);
const cc: Condition = switch (condition) {
.eflags => |cc| switch (item_mcv.immediate) {
0 => cc.negate(),
@@ -93829,27 +93900,24 @@ fn lowerSwitchBr(
else => unreachable,
},
else => cc: {
- var cond_temp = try self.tempInit(condition_ty, condition);
- var item_temp = try self.tempInit(condition_ty, item_mcv);
- const cc_temp = cond_temp.cmpInts(.eq, &item_temp, self) catch |err| switch (err) {
+ var item_temp = try cg.tempInit(condition_ty, item_mcv);
+ const cc_temp = cond_temp.cmpInts(.eq, &item_temp, cg) catch |err| switch (err) {
error.SelectFailed => unreachable,
else => |e| return e,
};
- try cond_temp.die(self);
- try item_temp.die(self);
- const cc = cc_temp.tracking(self).short.eflags;
- try cc_temp.die(self);
- try self.resetTemps();
+ try item_temp.die(cg);
+ const cc = cc_temp.tracking(cg).short.eflags;
+ try cc_temp.die(cg);
+ try cg.resetTemps(reset_index);
break :cc cc;
},
};
- reloc.* = try self.asmJccReloc(cc, undefined);
+ reloc.* = try cg.asmJccReloc(cc, undefined);
}
for (case.ranges, relocs[case.items.len..]) |range, *reloc| {
- var cond_temp = try self.tempInit(condition_ty, condition);
- const min_mcv = try self.resolveInst(range[0]);
- const max_mcv = try self.resolveInst(range[1]);
+ const min_mcv = try cg.resolveInst(range[0]);
+ const max_mcv = try cg.resolveInst(range[1]);
// `null` means always false.
const lt_min = cc: switch (condition) {
.eflags => |cc| switch (min_mcv.immediate) {
@@ -93858,19 +93926,19 @@ fn lowerSwitchBr(
else => unreachable,
},
else => {
- var min_temp = try self.tempInit(condition_ty, min_mcv);
- const cc_temp = cond_temp.cmpInts(.lt, &min_temp, self) catch |err| switch (err) {
+ var min_temp = try cg.tempInit(condition_ty, min_mcv);
+ const cc_temp = cond_temp.cmpInts(.lt, &min_temp, cg) catch |err| switch (err) {
error.SelectFailed => unreachable,
else => |e| return e,
};
- try min_temp.die(self);
- const cc = cc_temp.tracking(self).short.eflags;
- try cc_temp.die(self);
+ try min_temp.die(cg);
+ const cc = cc_temp.tracking(cg).short.eflags;
+ try cc_temp.die(cg);
break :cc cc;
},
};
const lt_min_reloc = if (lt_min) |cc| r: {
- break :r try self.asmJccReloc(cc, undefined);
+ break :r try cg.asmJccReloc(cc, undefined);
} else null;
// `null` means always true.
const lte_max = switch (condition) {
@@ -93880,38 +93948,41 @@ fn lowerSwitchBr(
else => unreachable,
},
else => cc: {
- var max_temp = try self.tempInit(condition_ty, max_mcv);
- const cc_temp = cond_temp.cmpInts(.lte, &max_temp, self) catch |err| switch (err) {
+ var max_temp = try cg.tempInit(condition_ty, max_mcv);
+ const cc_temp = cond_temp.cmpInts(.lte, &max_temp, cg) catch |err| switch (err) {
error.SelectFailed => unreachable,
else => |e| return e,
};
- try max_temp.die(self);
- const cc = cc_temp.tracking(self).short.eflags;
- try cc_temp.die(self);
+ try max_temp.die(cg);
+ const cc = cc_temp.tracking(cg).short.eflags;
+ try cc_temp.die(cg);
break :cc cc;
},
};
- try cond_temp.die(self);
- try self.resetTemps();
+ try cg.resetTemps(reset_index);
// "Success" case is in `reloc`....
if (lte_max) |cc| {
- reloc.* = try self.asmJccReloc(cc, undefined);
+ reloc.* = try cg.asmJccReloc(cc, undefined);
} else {
- reloc.* = try self.asmJmpReloc(undefined);
+ reloc.* = try cg.asmJmpReloc(undefined);
}
// ...and "fail" case falls through to next checks.
- if (lt_min_reloc) |r| self.performReloc(r);
+ if (lt_min_reloc) |r| cg.performReloc(r);
}
+ try cond_temp.die(cg);
+ try cg.resetTemps(@enumFromInt(0));
+ cg.checkInvariantsAfterAirInst();
+
// The jump to skip this case if the conditions all failed.
- const skip_case_reloc = try self.asmJmpReloc(undefined);
+ const skip_case_reloc = try cg.asmJmpReloc(undefined);
- for (liveness.deaths[case.idx]) |operand| try self.processDeath(operand);
+ for (liveness.deaths[case.idx]) |operand| try cg.processDeath(operand);
// Relocate all success cases to the body we're about to generate.
- for (relocs) |reloc| self.performReloc(reloc);
- try self.genBodyBlock(case.body);
- try self.restoreState(state, &.{}, .{
+ for (relocs) |reloc| cg.performReloc(reloc);
+ try cg.genBodyBlock(case.body);
+ try cg.restoreState(state, &.{}, .{
.emit_instructions = false,
.update_tracking = true,
.resurrect = true,
@@ -93919,16 +93990,16 @@ fn lowerSwitchBr(
});
// Relocate the "skip" branch to fall through to the next case.
- self.performReloc(skip_case_reloc);
+ cg.performReloc(skip_case_reloc);
}
if (switch_br.else_body_len > 0) {
const else_body = cases_it.elseBody();
const else_deaths = liveness.deaths.len - 1;
- for (liveness.deaths[else_deaths]) |operand| try self.processDeath(operand);
+ for (liveness.deaths[else_deaths]) |operand| try cg.processDeath(operand);
- try self.genBodyBlock(else_body);
- try self.restoreState(state, &.{}, .{
+ try cg.genBodyBlock(else_body);
+ try cg.restoreState(state, &.{}, .{
.emit_instructions = false,
.update_tracking = true,
.resurrect = true,
@@ -95003,7 +95074,7 @@ fn moveStrategy(cg: *CodeGen, ty: Type, class: Register.Class, aligned: bool) !M
.mmx => {},
.sse => switch (ty.zigTypeTag(zcu)) {
else => {
- const classes = std.mem.sliceTo(&abi.classifySystemV(ty, zcu, cg.target.*, .other), .none);
+ const classes = std.mem.sliceTo(&abi.classifySystemV(ty, zcu, cg.target, .other), .none);
assert(std.mem.indexOfNone(abi.Class, classes, &.{
.integer, .sse, .sseup, .memory, .float, .float_combine,
}) == null);
@@ -97909,16 +97980,150 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
switch (pred_mcv) {
.register => |pred_reg| switch (pred_reg.class()) {
.general_purpose => {},
- .sse => if (need_xmm0 and pred_reg.id() != comptime Register.xmm0.id()) {
- try self.register_manager.getKnownReg(.xmm0, null);
- try self.genSetReg(.xmm0, pred_ty, pred_mcv, .{});
- break :mask .xmm0;
- } else break :mask if (has_blend)
- pred_reg
+ .sse => if (elem_ty.toIntern() == .bool_type)
+ if (need_xmm0 and pred_reg.id() != comptime Register.xmm0.id()) {
+ try self.register_manager.getKnownReg(.xmm0, null);
+ try self.genSetReg(.xmm0, pred_ty, pred_mcv, .{});
+ break :mask .xmm0;
+ } else break :mask if (has_blend)
+ pred_reg
+ else
+ try self.copyToTmpRegister(pred_ty, pred_mcv)
else
- try self.copyToTmpRegister(pred_ty, pred_mcv),
+ return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)}),
else => unreachable,
},
+ .register_mask => |pred_reg_mask| {
+ if (pred_reg_mask.info.scalar.bitSize(self.target) != 8 * elem_abi_size)
+ return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)});
+
+ const mask_reg: Register = if (need_xmm0 and pred_reg_mask.reg.id() != comptime Register.xmm0.id()) mask_reg: {
+ try self.register_manager.getKnownReg(.xmm0, null);
+ try self.genSetReg(.xmm0, ty, .{ .register = pred_reg_mask.reg }, .{});
+ break :mask_reg .xmm0;
+ } else pred_reg_mask.reg;
+ const mask_alias = registerAlias(mask_reg, abi_size);
+ const mask_lock = self.register_manager.lockRegAssumeUnused(mask_reg);
+ defer self.register_manager.unlockReg(mask_lock);
+
+ const lhs_mcv = try self.resolveInst(extra.lhs);
+ const lhs_lock = switch (lhs_mcv) {
+ .register => |lhs_reg| self.register_manager.lockRegAssumeUnused(lhs_reg),
+ else => null,
+ };
+ defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);
+
+ const rhs_mcv = try self.resolveInst(extra.rhs);
+ const rhs_lock = switch (rhs_mcv) {
+ .register => |rhs_reg| self.register_manager.lockReg(rhs_reg),
+ else => null,
+ };
+ defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
+
+ const order = has_blend != pred_reg_mask.info.inverted;
+ const reuse_mcv, const other_mcv = if (order)
+ .{ rhs_mcv, lhs_mcv }
+ else
+ .{ lhs_mcv, rhs_mcv };
+ const dst_mcv: MCValue = if (reuse_mcv.isRegister() and self.reuseOperand(
+ inst,
+ if (order) extra.rhs else extra.lhs,
+ @intFromBool(order),
+ reuse_mcv,
+ )) reuse_mcv else if (has_avx)
+ .{ .register = try self.register_manager.allocReg(inst, abi.RegisterClass.sse) }
+ else
+ try self.copyToRegisterWithInstTracking(inst, ty, reuse_mcv);
+ const dst_reg = dst_mcv.getReg().?;
+ const dst_alias = registerAlias(dst_reg, abi_size);
+ const dst_lock = self.register_manager.lockReg(dst_reg);
+ defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
+
+ const mir_tag = @as(?Mir.Inst.FixedTag, if ((pred_reg_mask.info.kind == .all and
+ elem_ty.toIntern() != .f32_type and elem_ty.toIntern() != .f64_type) or pred_reg_mask.info.scalar == .byte)
+ if (has_avx)
+ .{ .vp_b, .blendv }
+ else if (has_blend)
+ .{ .p_b, .blendv }
+ else if (pred_reg_mask.info.kind == .all)
+ .{ .p_, undefined }
+ else
+ null
+ else if ((pred_reg_mask.info.kind == .all and (elem_ty.toIntern() != .f64_type or !self.hasFeature(.sse2))) or
+ pred_reg_mask.info.scalar == .dword)
+ if (has_avx)
+ .{ .v_ps, .blendv }
+ else if (has_blend)
+ .{ ._ps, .blendv }
+ else if (pred_reg_mask.info.kind == .all)
+ .{ ._ps, undefined }
+ else
+ null
+ else if (pred_reg_mask.info.kind == .all or pred_reg_mask.info.scalar == .qword)
+ if (has_avx)
+ .{ .v_pd, .blendv }
+ else if (has_blend)
+ .{ ._pd, .blendv }
+ else if (pred_reg_mask.info.kind == .all)
+ .{ ._pd, undefined }
+ else
+ null
+ else
+ null) orelse return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)});
+ if (has_avx) {
+ const rhs_alias = if (reuse_mcv.isRegister())
+ registerAlias(reuse_mcv.getReg().?, abi_size)
+ else rhs: {
+ try self.genSetReg(dst_reg, ty, reuse_mcv, .{});
+ break :rhs dst_alias;
+ };
+ if (other_mcv.isBase()) try self.asmRegisterRegisterMemoryRegister(
+ mir_tag,
+ dst_alias,
+ rhs_alias,
+ try other_mcv.mem(self, .{ .size = self.memSize(ty) }),
+ mask_alias,
+ ) else try self.asmRegisterRegisterRegisterRegister(
+ mir_tag,
+ dst_alias,
+ rhs_alias,
+ registerAlias(if (other_mcv.isRegister())
+ other_mcv.getReg().?
+ else
+ try self.copyToTmpRegister(ty, other_mcv), abi_size),
+ mask_alias,
+ );
+ } else if (has_blend) if (other_mcv.isBase()) try self.asmRegisterMemoryRegister(
+ mir_tag,
+ dst_alias,
+ try other_mcv.mem(self, .{ .size = self.memSize(ty) }),
+ mask_alias,
+ ) else try self.asmRegisterRegisterRegister(
+ mir_tag,
+ dst_alias,
+ registerAlias(if (other_mcv.isRegister())
+ other_mcv.getReg().?
+ else
+ try self.copyToTmpRegister(ty, other_mcv), abi_size),
+ mask_alias,
+ ) else {
+ try self.asmRegisterRegister(.{ mir_tag[0], .@"and" }, dst_alias, mask_alias);
+ if (other_mcv.isBase()) try self.asmRegisterMemory(
+ .{ mir_tag[0], .andn },
+ mask_alias,
+ try other_mcv.mem(self, .{ .size = .fromSize(abi_size) }),
+ ) else try self.asmRegisterRegister(
+ .{ mir_tag[0], .andn },
+ mask_alias,
+ if (other_mcv.isRegister())
+ other_mcv.getReg().?
+ else
+ try self.copyToTmpRegister(ty, other_mcv),
+ );
+ try self.asmRegisterRegister(.{ mir_tag[0], .@"or" }, dst_alias, mask_alias);
+ }
+ break :result dst_mcv;
+ },
else => {},
}
const mask_reg: Register = if (need_xmm0) mask_reg: {
@@ -98121,7 +98326,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
const dst_lock = self.register_manager.lockReg(dst_reg);
defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
- const mir_tag = @as(?Mir.Inst.FixedTag, switch (ty.childType(zcu).zigTypeTag(zcu)) {
+ const mir_tag = @as(?Mir.Inst.FixedTag, switch (elem_ty.zigTypeTag(zcu)) {
else => null,
.int => switch (abi_size) {
0 => unreachable,
@@ -98137,7 +98342,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
null,
else => null,
},
- .float => switch (ty.childType(zcu).floatBits(self.target.*)) {
+ .float => switch (elem_ty.floatBits(self.target.*)) {
else => unreachable,
16, 80, 128 => null,
32 => switch (vec_len) {
@@ -98191,30 +98396,20 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
try self.copyToTmpRegister(ty, lhs_mcv), abi_size),
mask_alias,
) else {
- const mir_fixes = @as(?Mir.Inst.Fixes, switch (elem_ty.zigTypeTag(zcu)) {
- else => null,
- .int => .p_,
- .float => switch (elem_ty.floatBits(self.target.*)) {
- 32 => ._ps,
- 64 => ._pd,
- 16, 80, 128 => null,
- else => unreachable,
- },
- }) orelse return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)});
- try self.asmRegisterRegister(.{ mir_fixes, .@"and" }, dst_alias, mask_alias);
+ try self.asmRegisterRegister(.{ mir_tag[0], .@"and" }, dst_alias, mask_alias);
if (rhs_mcv.isBase()) try self.asmRegisterMemory(
- .{ mir_fixes, .andn },
+ .{ mir_tag[0], .andn },
mask_alias,
try rhs_mcv.mem(self, .{ .size = .fromSize(abi_size) }),
) else try self.asmRegisterRegister(
- .{ mir_fixes, .andn },
+ .{ mir_tag[0], .andn },
mask_alias,
if (rhs_mcv.isRegister())
rhs_mcv.getReg().?
else
try self.copyToTmpRegister(ty, rhs_mcv),
);
- try self.asmRegisterRegister(.{ mir_fixes, .@"or" }, dst_alias, mask_alias);
+ try self.asmRegisterRegister(.{ mir_tag[0], .@"or" }, dst_alias, mask_alias);
}
break :result dst_mcv;
};
@@ -99635,7 +99830,7 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void {
const overflow_arg_area: MCValue = .{ .indirect = .{ .reg = ptr_arg_list_reg, .off = 8 } };
const reg_save_area: MCValue = .{ .indirect = .{ .reg = ptr_arg_list_reg, .off = 16 } };
- const classes = std.mem.sliceTo(&abi.classifySystemV(promote_ty, zcu, self.target.*, .arg), .none);
+ const classes = std.mem.sliceTo(&abi.classifySystemV(promote_ty, zcu, self.target, .arg), .none);
switch (classes[0]) {
.integer => {
assert(classes.len == 1);
@@ -99980,7 +100175,7 @@ fn resolveCallingConventionValues(
var ret_tracking_i: usize = 0;
const classes = switch (cc) {
- .x86_64_sysv => std.mem.sliceTo(&abi.classifySystemV(ret_ty, zcu, self.target.*, .ret), .none),
+ .x86_64_sysv => std.mem.sliceTo(&abi.classifySystemV(ret_ty, zcu, self.target, .ret), .none),
.x86_64_win => &.{abi.classifyWindows(ret_ty, zcu)},
else => unreachable,
};
@@ -100069,7 +100264,7 @@ fn resolveCallingConventionValues(
var arg_mcv_i: usize = 0;
const classes = switch (cc) {
- .x86_64_sysv => std.mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target.*, .arg), .none),
+ .x86_64_sysv => std.mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target, .arg), .none),
.x86_64_win => &.{abi.classifyWindows(ty, zcu)},
else => unreachable,
};
@@ -100373,7 +100568,7 @@ fn splitType(self: *CodeGen, comptime parts_len: usize, ty: Type) ![parts_len]Ty
error.DivisionByZero => unreachable,
error.UnexpectedRemainder => {},
};
- const classes = std.mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target.*, .other), .none);
+ const classes = std.mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target, .other), .none);
if (classes.len == parts_len) for (&parts, classes, 0..) |*part, class, part_i| {
part.* = switch (class) {
.integer => if (part_i < parts_len - 1)
@@ -100753,11 +100948,11 @@ const Temp = struct {
const new_temp_index = cg.next_temp_index;
cg.temp_type[@intFromEnum(new_temp_index)] = .usize;
cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1);
- switch (temp.tracking(cg).short) {
- else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),
+ const mcv = temp.tracking(cg).short;
+ switch (mcv) {
+ else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),
.register => |reg| {
- const new_reg =
- try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
+ const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });
try cg.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{
.base = .{ .reg = reg.to64() },
@@ -100765,33 +100960,22 @@ const Temp = struct {
});
},
.register_offset => |reg_off| {
- const new_reg =
- try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
+ const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });
try cg.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{
.base = .{ .reg = reg_off.reg.to64() },
.mod = .{ .rm = .{ .disp = reg_off.off + off } },
});
},
+ .load_symbol, .load_frame => {
+ const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
+ new_temp_index.tracking(cg).* = .init(.{ .register_offset = .{ .reg = new_reg, .off = off } });
+ try cg.genSetReg(new_reg, .usize, mcv, .{});
+ },
.lea_symbol => |sym_off| new_temp_index.tracking(cg).* = .init(.{ .lea_symbol = .{
.sym_index = sym_off.sym_index,
.off = sym_off.off + off,
} }),
- .load_frame => |frame_addr| {
- const new_reg =
- try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
- new_temp_index.tracking(cg).* = .init(.{ .register_offset = .{
- .reg = new_reg,
- .off = off,
- } });
- try cg.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{
- .base = .{ .frame = frame_addr.index },
- .mod = .{ .rm = .{
- .size = .qword,
- .disp = frame_addr.off,
- } },
- });
- },
.lea_frame => |frame_addr| new_temp_index.tracking(cg).* = .init(.{ .lea_frame = .{
.index = frame_addr.index,
.off = frame_addr.off + off,
@@ -101108,7 +101292,8 @@ const Temp = struct {
=> return temp.toRegClass(true, .general_purpose, cg),
.lea_symbol => |sym_off| {
const off = sym_off.off;
- if (off == 0) return false;
+ // hack around linker relocation bugs
+ if (false and off == 0) return false;
try temp.toOffset(-off, cg);
while (try temp.toRegClass(true, .general_purpose, cg)) {}
try temp.toOffset(off, cg);
@@ -101339,6 +101524,7 @@ const Temp = struct {
const val_mcv = val.tracking(cg).short;
switch (val_mcv) {
else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),
+ .none => {},
.undef => if (opts.safe) {
var dst_ptr = try cg.tempInit(.usize, dst.tracking(cg).short.address().offset(opts.disp));
var pat = try cg.tempInit(.u8, .{ .immediate = 0xaa });
@@ -101371,19 +101557,19 @@ const Temp = struct {
.disp = opts.disp,
}),
),
- .register => |val_reg| try dst.writeRegs(opts.disp, val_ty, &.{registerAlias(
+ .register => |val_reg| try dst.writeReg(opts.disp, val_ty, registerAlias(
val_reg,
@intCast(val_ty.abiSize(cg.pt.zcu)),
- )}, cg),
+ ), cg),
inline .register_pair,
.register_triple,
.register_quadruple,
=> |val_regs| try dst.writeRegs(opts.disp, val_ty, &val_regs, cg),
.register_offset => |val_reg_off| switch (val_reg_off.off) {
- 0 => try dst.writeRegs(opts.disp, val_ty, &.{registerAlias(
+ 0 => try dst.writeReg(opts.disp, val_ty, registerAlias(
val_reg_off.reg,
@intCast(val_ty.abiSize(cg.pt.zcu)),
- )}, cg),
+ ), cg),
else => continue :val_to_gpr,
},
.register_overflow => |val_reg_ov| {
@@ -101401,7 +101587,7 @@ const Temp = struct {
else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, val_ty.fmt(cg.pt) }),
});
const first_size: u31 = @intCast(first_ty.abiSize(cg.pt.zcu));
- try dst.writeRegs(opts.disp, first_ty, &.{registerAlias(val_reg_ov.reg, first_size)}, cg);
+ try dst.writeReg(opts.disp, first_ty, registerAlias(val_reg_ov.reg, first_size), cg);
try cg.asmSetccMemory(
val_reg_ov.eflags,
try dst.tracking(cg).short.mem(cg, .{
@@ -101492,42 +101678,76 @@ const Temp = struct {
}));
}
+ fn writeReg(dst: Temp, disp: i32, src_ty: Type, src_reg: Register, cg: *CodeGen) InnerError!void {
+ const src_abi_size: u31 = @intCast(src_ty.abiSize(cg.pt.zcu));
+ const src_rc = src_reg.class();
+ if (src_rc == .x87 or std.math.isPowerOfTwo(src_abi_size)) {
+ const strat = try cg.moveStrategy(src_ty, src_rc, false);
+ try strat.write(cg, try dst.tracking(cg).short.mem(cg, .{
+ .size = .fromBitSize(@min(8 * src_abi_size, src_reg.bitSize())),
+ .disp = disp,
+ }), registerAlias(src_reg, src_abi_size));
+ } else {
+ const frame_size = std.math.ceilPowerOfTwoAssert(u32, src_abi_size);
+ const frame_index = try cg.allocFrameIndex(.init(.{
+ .size = frame_size,
+ .alignment = .fromNonzeroByteUnits(frame_size),
+ }));
+ const strat = try cg.moveStrategy(src_ty, src_rc, true);
+ try strat.write(cg, .{
+ .base = .{ .frame = frame_index },
+ .mod = .{ .rm = .{ .size = .fromSize(frame_size) } },
+ }, registerAlias(src_reg, frame_size));
+ var dst_ptr = try cg.tempInit(.usize, dst.tracking(cg).short.address());
+ try dst_ptr.toOffset(disp, cg);
+ var src_ptr = try cg.tempInit(.usize, .{ .lea_frame = .{ .index = frame_index } });
+ var len = try cg.tempInit(.usize, .{ .immediate = src_abi_size });
+ try dst_ptr.memcpy(&src_ptr, &len, cg);
+ try dst_ptr.die(cg);
+ try src_ptr.die(cg);
+ try len.die(cg);
+ }
+ }
+
fn writeRegs(dst: Temp, disp: i32, src_ty: Type, src_regs: []const Register, cg: *CodeGen) InnerError!void {
+ const zcu = cg.pt.zcu;
+ const classes = std.mem.sliceTo(&abi.classifySystemV(src_ty, zcu, cg.target, .other), .none);
+ var next_class_index: u4 = 0;
var part_disp = disp;
- var src_abi_size: u32 = @intCast(src_ty.abiSize(cg.pt.zcu));
+ var remaining_abi_size = src_ty.abiSize(zcu);
for (src_regs) |src_reg| {
- const src_rc = src_reg.class();
- const part_bit_size = @min(8 * src_abi_size, src_reg.bitSize());
- const part_size = @divExact(part_bit_size, 8);
- if (src_rc == .x87 or std.math.isPowerOfTwo(part_size)) {
- const strat = try cg.moveStrategy(src_ty, src_rc, false);
- try strat.write(cg, try dst.tracking(cg).short.mem(cg, .{
- .size = .fromBitSize(part_bit_size),
- .disp = part_disp,
- }), registerAlias(src_reg, part_size));
- } else {
- const frame_size = std.math.ceilPowerOfTwoAssert(u32, part_size);
- const frame_index = try cg.allocFrameIndex(.init(.{
- .size = frame_size,
- .alignment = .fromNonzeroByteUnits(frame_size),
- }));
- const strat = try cg.moveStrategy(src_ty, src_rc, true);
- try strat.write(cg, .{
- .base = .{ .frame = frame_index },
- .mod = .{ .rm = .{ .size = .fromSize(frame_size) } },
- }, registerAlias(src_reg, frame_size));
- var dst_ptr = try cg.tempInit(.usize, dst.tracking(cg).short.address());
- try dst_ptr.toOffset(part_disp, cg);
- var src_ptr = try cg.tempInit(.usize, .{ .lea_frame = .{ .index = frame_index } });
- var len = try cg.tempInit(.usize, .{ .immediate = src_abi_size });
- try dst_ptr.memcpy(&src_ptr, &len, cg);
- try dst_ptr.die(cg);
- try src_ptr.die(cg);
- try len.die(cg);
- }
+ const class_index = next_class_index;
+ const class = classes[class_index];
+ next_class_index = @intCast(switch (class) {
+ .integer, .memory, .float, .float_combine => class_index + 1,
+ .sse => std.mem.indexOfNonePos(abi.Class, classes, class_index + 1, &.{.sseup}) orelse classes.len,
+ .x87 => std.mem.indexOfNonePos(abi.Class, classes, class_index + 1, &.{.x87up}) orelse classes.len,
+ .sseup, .x87up, .complex_x87, .none, .win_i128, .integer_per_element => unreachable,
+ });
+ const part_size = switch (class) {
+ .integer, .sse, .memory => @min(8 * @as(u7, next_class_index - class_index), remaining_abi_size),
+ .x87 => 16,
+ .float => 4,
+ .float_combine => 8,
+ .sseup, .x87up, .complex_x87, .none, .win_i128, .integer_per_element => unreachable,
+ };
+ try dst.writeReg(part_disp, switch (class) {
+ .integer => .u64,
+ .sse => switch (part_size) {
+ else => unreachable,
+ 8 => .f64,
+ 16 => .vector_2_f64,
+ 32 => .vector_4_f64,
+ },
+ .x87 => .f80,
+ .float => .f32,
+ .float_combine => .vector_2_f32,
+ .sseup, .x87up, .complex_x87, .memory, .none, .win_i128, .integer_per_element => unreachable,
+ }, src_reg, cg);
part_disp += part_size;
- src_abi_size -= part_size;
+ remaining_abi_size -= part_size;
}
+ assert(next_class_index == classes.len);
}
fn memcpy(dst: *Temp, src: *Temp, len: *Temp, cg: *CodeGen) InnerError!void {
@@ -105786,9 +106006,9 @@ const Temp = struct {
};
};
-fn resetTemps(cg: *CodeGen) InnerError!void {
+fn resetTemps(cg: *CodeGen, from_index: Temp.Index) InnerError!void {
var any_valid = false;
- for (0..@intFromEnum(cg.next_temp_index)) |temp_index| {
+ for (@intFromEnum(from_index)..@intFromEnum(cg.next_temp_index)) |temp_index| {
const temp: Temp.Index = @enumFromInt(temp_index);
if (temp.isValid(cg)) {
any_valid = true;
@@ -105800,7 +106020,7 @@ fn resetTemps(cg: *CodeGen) InnerError!void {
cg.temp_type[temp_index] = undefined;
}
if (any_valid) return cg.fail("failed to kill all temps", .{});
- cg.next_temp_index = @enumFromInt(0);
+ cg.next_temp_index = from_index;
}
fn reuseTemp(
@@ -105889,70 +106109,75 @@ fn tempMemFromValue(cg: *CodeGen, value: Value) InnerError!Temp {
return cg.tempInit(value.typeOf(cg.pt.zcu), try cg.lowerUav(value));
}
-fn tempFromOperand(
- cg: *CodeGen,
- inst: Air.Inst.Index,
- op_index: Liveness.OperandInt,
- op_ref: Air.Inst.Ref,
- ignore_death: bool,
-) InnerError!Temp {
+fn tempFromOperand(cg: *CodeGen, op_ref: Air.Inst.Ref, op_dies: bool) InnerError!Temp {
const zcu = cg.pt.zcu;
const ip = &zcu.intern_pool;
- if (ignore_death or !cg.liveness.operandDies(inst, op_index)) {
- if (op_ref.toIndex()) |op_inst| return .{ .index = op_inst };
- const val = op_ref.toInterned().?;
- const gop = try cg.const_tracking.getOrPut(cg.gpa, val);
- if (!gop.found_existing) gop.value_ptr.* = .init(init: {
- const const_mcv = try cg.genTypedValue(.fromInterned(val));
- switch (const_mcv) {
- .lea_tlv => |tlv_sym| switch (cg.bin_file.tag) {
- .elf, .macho => {
- if (cg.mod.pic) {
- try cg.spillRegisters(&.{ .rdi, .rax });
- } else {
- try cg.spillRegisters(&.{.rax});
- }
- const frame_index = try cg.allocFrameIndex(.init(.{
- .size = 8,
- .alignment = .@"8",
- }));
- try cg.genSetMem(
- .{ .frame = frame_index },
- 0,
- .usize,
- .{ .lea_symbol = .{ .sym_index = tlv_sym } },
- .{},
- );
- break :init .{ .load_frame = .{ .index = frame_index } };
- },
- else => break :init const_mcv,
+ if (op_dies) {
+ const temp_index = cg.next_temp_index;
+ const temp: Temp = .{ .index = temp_index.toIndex() };
+ const op_inst = op_ref.toIndex().?;
+ const tracking = cg.getResolvedInstValue(op_inst);
+ temp_index.tracking(cg).* = tracking.*;
+ if (!cg.reuseTemp(temp.index, op_inst, tracking)) return .{ .index = op_ref.toIndex().? };
+ cg.temp_type[@intFromEnum(temp_index)] = cg.typeOf(op_ref);
+ cg.next_temp_index = @enumFromInt(@intFromEnum(temp_index) + 1);
+ return temp;
+ }
+
+ if (op_ref.toIndex()) |op_inst| return .{ .index = op_inst };
+ const val = op_ref.toInterned().?;
+ const gop = try cg.const_tracking.getOrPut(cg.gpa, val);
+ if (!gop.found_existing) gop.value_ptr.* = .init(init: {
+ const const_mcv = try cg.genTypedValue(.fromInterned(val));
+ switch (const_mcv) {
+ .lea_tlv => |tlv_sym| switch (cg.bin_file.tag) {
+ .elf, .macho => {
+ if (cg.mod.pic) {
+ try cg.spillRegisters(&.{ .rdi, .rax });
+ } else {
+ try cg.spillRegisters(&.{.rax});
+ }
+ const frame_index = try cg.allocFrameIndex(.init(.{
+ .size = 8,
+ .alignment = .@"8",
+ }));
+ try cg.genSetMem(
+ .{ .frame = frame_index },
+ 0,
+ .usize,
+ .{ .lea_symbol = .{ .sym_index = tlv_sym } },
+ .{},
+ );
+ break :init .{ .load_frame = .{ .index = frame_index } };
},
else => break :init const_mcv,
- }
- });
- return cg.tempInit(.fromInterned(ip.typeOf(val)), gop.value_ptr.short);
- }
+ },
+ else => break :init const_mcv,
+ }
+ });
+ return cg.tempInit(.fromInterned(ip.typeOf(val)), gop.value_ptr.short);
+}
- const temp_index = cg.next_temp_index;
- const temp: Temp = .{ .index = temp_index.toIndex() };
- const op_inst = op_ref.toIndex().?;
- const tracking = cg.getResolvedInstValue(op_inst);
- temp_index.tracking(cg).* = tracking.*;
- if (!cg.reuseTemp(temp.index, op_inst, tracking)) return .{ .index = op_ref.toIndex().? };
- cg.temp_type[@intFromEnum(temp_index)] = cg.typeOf(op_ref);
- cg.next_temp_index = @enumFromInt(@intFromEnum(temp_index) + 1);
- return temp;
+fn tempsFromOperandsInner(
+ cg: *CodeGen,
+ inst: Air.Inst.Index,
+ op_temps: []Temp,
+ op_refs: []const Air.Inst.Ref,
+) InnerError!void {
+ for (op_temps, 0.., op_refs) |*op_temp, op_index, op_ref| op_temp.* = try cg.tempFromOperand(op_ref, for (op_refs[0..op_index]) |prev_op_ref| {
+ if (op_ref == prev_op_ref) break false;
+ } else cg.liveness.operandDies(inst, @intCast(op_index)));
}
-inline fn tempsFromOperands(cg: *CodeGen, inst: Air.Inst.Index, op_refs: anytype) InnerError![op_refs.len]Temp {
- var temps: [op_refs.len]Temp = undefined;
- inline for (&temps, 0.., op_refs) |*temp, op_index, op_ref| {
- temp.* = try cg.tempFromOperand(inst, op_index, op_ref, inline for (0..op_index) |prev_op_index| {
- if (op_ref == op_refs[prev_op_index]) break true;
- } else false);
- }
- return temps;
+inline fn tempsFromOperands(
+ cg: *CodeGen,
+ inst: Air.Inst.Index,
+ op_refs: anytype,
+) InnerError![op_refs.len]Temp {
+ var op_temps: [op_refs.len]Temp = undefined;
+ try cg.tempsFromOperandsInner(inst, &op_temps, &op_refs);
+ return op_temps;
}
const Operand = union(enum) {
diff --git a/src/arch/x86_64/abi.zig b/src/arch/x86_64/abi.zig
index 2ac3402fd8..6d11a44c2a 100644
--- a/src/arch/x86_64/abi.zig
+++ b/src/arch/x86_64/abi.zig
@@ -100,7 +100,7 @@ pub const Context = enum { ret, arg, field, other };
/// There are a maximum of 8 possible return slots. Returned values are in
/// the beginning of the array; unused slots are filled with .none.
-pub fn classifySystemV(ty: Type, zcu: *Zcu, target: std.Target, ctx: Context) [8]Class {
+pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Context) [8]Class {
const memory_class = [_]Class{
.memory, .none, .none, .none,
.none, .none, .none, .none,
@@ -148,7 +148,7 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: std.Target, ctx: Context) [8
result[0] = .integer;
return result;
},
- .float => switch (ty.floatBits(target)) {
+ .float => switch (ty.floatBits(target.*)) {
16 => {
if (ctx == .field) {
result[0] = .memory;
@@ -330,7 +330,7 @@ fn classifySystemVStruct(
starting_byte_offset: u64,
loaded_struct: InternPool.LoadedStructType,
zcu: *Zcu,
- target: std.Target,
+ target: *const std.Target,
) u64 {
const ip = &zcu.intern_pool;
var byte_offset = starting_byte_offset;
@@ -379,7 +379,7 @@ fn classifySystemVUnion(
starting_byte_offset: u64,
loaded_union: InternPool.LoadedUnionType,
zcu: *Zcu,
- target: std.Target,
+ target: *const std.Target,
) u64 {
const ip = &zcu.intern_pool;
for (0..loaded_union.field_types.len) |field_index| {
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index e82d75311e..f8aeface59 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -100,7 +100,6 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 {
.kalimba,
.propeller,
=> unreachable, // Gated by hasLlvmSupport().
-
};
try llvm_triple.appendSlice(llvm_arch);
@@ -309,467 +308,154 @@ pub fn supportsTailCall(target: std.Target) bool {
}
}
-const DataLayoutBuilder = struct {
- target: std.Target,
+pub fn dataLayout(target: std.Target) []const u8 {
+ // These data layouts should match Clang.
+ return switch (target.cpu.arch) {
+ .arc => "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-f32:32:32-i64:32-f64:32-a:0:32-n32",
+ .xcore => "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:32-f64:32-a:0:32-n32",
+ .hexagon => "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048",
+ .lanai => "E-m:e-p:32:32-i64:64-a:0:32-n32-S64",
+ .aarch64 => if (target.ofmt == .macho)
+ if (target.os.tag == .windows)
+ "e-m:o-i64:64-i128:128-n32:64-S128-Fn32"
+ else if (target.abi == .ilp32)
+ "e-m:o-p:32:32-i64:64-i128:128-n32:64-S128-Fn32"
+ else
+ "e-m:o-i64:64-i128:128-n32:64-S128-Fn32"
+ else if (target.os.tag == .windows)
+ "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32"
+ else
+ "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32",
+ .aarch64_be => "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32",
+ .arm => if (target.ofmt == .macho)
+ "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
+ else
+ "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
+ .armeb, .thumbeb => if (target.ofmt == .macho)
+ "E-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
+ else
+ "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
+ .thumb => if (target.ofmt == .macho)
+ "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
+ else if (target.os.tag == .windows)
+ "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
+ else
+ "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
+ .avr => "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8",
+ .bpfeb => "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
+ .bpfel => "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
+ .msp430 => "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16",
+ .mips => "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64",
+ .mipsel => "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64",
+ .mips64 => switch (target.abi) {
+ .gnuabin32, .muslabin32 => "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S128",
+ else => "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128",
+ },
+ .mips64el => switch (target.abi) {
+ .gnuabin32, .muslabin32 => "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S128",
+ else => "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128",
+ },
+ .m68k => "E-m:e-p:32:16:32-i8:8:8-i16:16:16-i32:16:32-n8:16:32-a:0:16-S16",
+ .powerpc => if (target.os.tag == .aix)
+ "E-m:a-p:32:32-Fi32-i64:64-n32"
+ else
+ "E-m:e-p:32:32-Fn32-i64:64-n32",
+ .powerpcle => "e-m:e-p:32:32-Fn32-i64:64-n32",
+ .powerpc64 => switch (target.os.tag) {
+ .aix => "E-m:a-Fi64-i64:64-n32:64-S128-v256:256:256-v512:512:512",
+ .linux => if (target.abi.isMusl())
+ "E-m:e-Fn32-i64:64-n32:64-S128-v256:256:256-v512:512:512"
+ else
+ "E-m:e-Fi64-i64:64-n32:64-S128-v256:256:256-v512:512:512",
+ .ps3 => "E-m:e-p:32:32-Fi64-i64:64-n32:64",
+ else => if (target.os.tag == .openbsd or
+ (target.os.tag == .freebsd and target.os.version_range.semver.isAtLeast(.{ .major = 13, .minor = 0, .patch = 0 }) orelse false))
+ "E-m:e-Fn32-i64:64-n32:64"
+ else
+ "E-m:e-Fi64-i64:64-n32:64",
+ },
+ .powerpc64le => if (target.os.tag == .linux)
+ "e-m:e-Fn32-i64:64-n32:64-S128-v256:256:256-v512:512:512"
+ else
+ "e-m:e-Fn32-i64:64-n32:64",
+ .nvptx => "e-p:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64",
+ .nvptx64 => "e-i64:64-i128:128-v16:16-v32:32-n16:32:64",
+ .amdgcn => "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9",
+ .riscv32 => if (std.Target.riscv.featureSetHas(target.cpu.features, .e))
+ "e-m:e-p:32:32-i64:64-n32-S32"
+ else
+ "e-m:e-p:32:32-i64:64-n32-S128",
+ .riscv64 => if (std.Target.riscv.featureSetHas(target.cpu.features, .e))
+ "e-m:e-p:64:64-i64:64-i128:128-n32:64-S64"
+ else
+ "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
+ .sparc => "E-m:e-p:32:32-i64:64-f128:64-n32-S64",
+ .sparc64 => "E-m:e-i64:64-n32:64-S128",
+ .s390x => if (target.os.tag == .zos)
+ "E-m:l-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64"
+ else
+ "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64",
+ .x86 => switch (target.os.tag) {
+ .elfiamcu => "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:32-f64:32-f128:32-n8:16:32-a:0:32-S32",
+ .windows => switch (target.abi) {
+ .cygnus => "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32",
+ .gnu => if (target.ofmt == .coff)
+ "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"
+ else
+ "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32",
+ else => blk: {
+ const msvc = switch (target.abi) {
+ .none, .msvc => true,
+ else => false,
+ };
- pub fn format(
- self: DataLayoutBuilder,
- comptime _: []const u8,
- _: std.fmt.FormatOptions,
- writer: anytype,
- ) @TypeOf(writer).Error!void {
- try writer.writeByte(switch (self.target.cpu.arch.endian()) {
- .little => 'e',
- .big => 'E',
- });
- switch (self.target.cpu.arch) {
- .amdgcn,
- .nvptx,
- .nvptx64,
- => {},
- .avr => try writer.writeAll("-P1"),
- else => try writer.print("-m:{c}", .{@as(u8, switch (self.target.cpu.arch) {
- .mips, .mipsel => 'm', // Mips mangling: Private symbols get a $ prefix.
- else => switch (self.target.ofmt) {
- .elf => 'e', // ELF mangling: Private symbols get a `.L` prefix.
- //.goff => 'l', // GOFF mangling: Private symbols get a `@` prefix.
- .macho => 'o', // Mach-O mangling: Private symbols get `L` prefix.
- // Other symbols get a `_` prefix.
- .coff => switch (self.target.os.tag) {
- .uefi, .windows => switch (self.target.cpu.arch) {
- .x86 => 'x', // Windows x86 COFF mangling: Private symbols get the usual
- // prefix. Regular C symbols get a `_` prefix. Functions with `__stdcall`,
- //`__fastcall`, and `__vectorcall` have custom mangling that appends `@N`
- // where N is the number of bytes used to pass parameters. C++ symbols
- // starting with `?` are not mangled in any way.
- else => 'w', // Windows COFF mangling: Similar to x, except that normal C
- // symbols do not receive a `_` prefix.
- },
- else => 'e',
- },
- //.xcoff => 'a', // XCOFF mangling: Private symbols get a `L..` prefix.
- else => 'e',
- },
- })}),
- }
- const stack_abi = self.target.stackAlignment() * 8;
- if (self.target.cpu.arch == .csky) try writer.print("-S{d}", .{stack_abi});
- var any_non_integral = false;
- const ptr_bit_width = self.target.ptrBitWidth();
- var default_info = struct { size: u16, abi: u16, pref: u16, idx: u16 }{
- .size = 64,
- .abi = 64,
- .pref = 64,
- .idx = 64,
- };
- const addr_space_info = llvmAddrSpaceInfo(self.target);
- for (addr_space_info, 0..) |info, i| {
- assert((info.llvm == .default) == (i == 0));
- if (info.non_integral) {
- assert(info.llvm != .default);
- any_non_integral = true;
- }
- const size = info.size orelse ptr_bit_width;
- const abi = info.abi orelse ptr_bit_width;
- const pref = info.pref orelse abi;
- const idx = info.idx orelse size;
- const matches_default =
- size == default_info.size and
- abi == default_info.abi and
- pref == default_info.pref and
- idx == default_info.idx;
- if (info.llvm == .default) default_info = .{
- .size = size,
- .abi = abi,
- .pref = pref,
- .idx = idx,
- };
- if (!info.force_in_data_layout and matches_default and
- self.target.cpu.arch != .riscv64 and
- self.target.cpu.arch != .loongarch64 and
- !(self.target.cpu.arch == .aarch64 and
- (self.target.os.tag == .uefi or self.target.os.tag == .windows)) and
- self.target.cpu.arch != .bpfeb and self.target.cpu.arch != .bpfel) continue;
- try writer.writeAll("-p");
- if (info.llvm != .default) try writer.print("{d}", .{@intFromEnum(info.llvm)});
- try writer.print(":{d}:{d}", .{ size, abi });
- if (pref != abi or idx != size or self.target.cpu.arch == .hexagon) {
- try writer.print(":{d}", .{pref});
- if (idx != size) try writer.print(":{d}", .{idx});
- }
- }
- if (self.target.cpu.arch.isArm())
- try writer.writeAll("-Fi8") // for thumb interwork
- else if (self.target.cpu.arch == .powerpc64 and
- self.target.os.tag != .freebsd and
- self.target.os.tag != .openbsd and
- !self.target.abi.isMusl())
- try writer.writeAll("-Fi64")
- else if (self.target.cpu.arch.isPowerPC() and self.target.os.tag == .aix)
- try writer.writeAll(if (self.target.cpu.arch.isPowerPC64()) "-Fi64" else "-Fi32")
- else if (self.target.cpu.arch.isPowerPC())
- try writer.writeAll("-Fn32");
- if (self.target.cpu.arch != .hexagon) {
- if (self.target.cpu.arch == .arc or self.target.cpu.arch == .s390x)
- try self.typeAlignment(.integer, 1, 8, 8, false, writer);
- try self.typeAlignment(.integer, 8, 8, 8, false, writer);
- try self.typeAlignment(.integer, 16, 16, 16, false, writer);
- try self.typeAlignment(.integer, 32, 32, 32, false, writer);
- if (self.target.cpu.arch == .arc)
- try self.typeAlignment(.float, 32, 32, 32, false, writer);
- try self.typeAlignment(.integer, 64, 32, 64, false, writer);
- try self.typeAlignment(.integer, 128, 32, 64, false, writer);
- if (backendSupportsF16(self.target))
- try self.typeAlignment(.float, 16, 16, 16, false, writer);
- if (self.target.cpu.arch != .arc)
- try self.typeAlignment(.float, 32, 32, 32, false, writer);
- try self.typeAlignment(.float, 64, 64, 64, false, writer);
- if (self.target.cpu.arch.isX86()) try self.typeAlignment(.float, 80, 0, 0, false, writer);
- try self.typeAlignment(.float, 128, 128, 128, false, writer);
- }
- switch (self.target.cpu.arch) {
- .amdgcn => {
- try self.typeAlignment(.vector, 16, 16, 16, false, writer);
- try self.typeAlignment(.vector, 24, 32, 32, false, writer);
- try self.typeAlignment(.vector, 32, 32, 32, false, writer);
- try self.typeAlignment(.vector, 48, 64, 64, false, writer);
- try self.typeAlignment(.vector, 96, 128, 128, false, writer);
- try self.typeAlignment(.vector, 192, 256, 256, false, writer);
- try self.typeAlignment(.vector, 256, 256, 256, false, writer);
- try self.typeAlignment(.vector, 512, 512, 512, false, writer);
- try self.typeAlignment(.vector, 1024, 1024, 1024, false, writer);
- try self.typeAlignment(.vector, 2048, 2048, 2048, false, writer);
- },
- .ve => {},
- else => {
- try self.typeAlignment(.vector, 16, 32, 32, false, writer);
- try self.typeAlignment(.vector, 32, 32, 32, false, writer);
- try self.typeAlignment(.vector, 64, 64, 64, false, writer);
- try self.typeAlignment(.vector, 128, 128, 128, true, writer);
- },
- }
- const swap_agg_nat = switch (self.target.cpu.arch) {
- .x86, .x86_64 => switch (self.target.os.tag) {
- .uefi, .windows => true,
- else => false,
- },
- .avr, .m68k => true,
- else => false,
- };
- if (!swap_agg_nat) try self.typeAlignment(.aggregate, 0, 0, 64, false, writer);
- if (self.target.cpu.arch == .csky) try writer.writeAll("-Fi32");
- for (@as([]const u24, switch (self.target.cpu.arch) {
- .avr => &.{8},
- .msp430 => &.{ 8, 16 },
- .arc,
- .arm,
- .armeb,
- .csky,
- .loongarch32,
- .mips,
- .mipsel,
- .powerpc,
- .powerpcle,
- .riscv32,
- .sparc,
- .thumb,
- .thumbeb,
- .xtensa,
- => &.{32},
- .aarch64,
- .aarch64_be,
- .amdgcn,
- .bpfeb,
- .bpfel,
- .loongarch64,
- .mips64,
- .mips64el,
- .powerpc64,
- .powerpc64le,
- .riscv64,
- .s390x,
- .sparc64,
- .ve,
- .wasm32,
- .wasm64,
- => &.{ 32, 64 },
- .hexagon => &.{ 16, 32 },
- .m68k,
- .x86,
- => &.{ 8, 16, 32 },
- .nvptx,
- .nvptx64,
- => &.{ 16, 32, 64 },
- .x86_64 => &.{ 8, 16, 32, 64 },
- else => &.{},
- }), 0..) |natural, index| switch (index) {
- 0 => try writer.print("-n{d}", .{natural}),
- else => try writer.print(":{d}", .{natural}),
- };
- if (swap_agg_nat) try self.typeAlignment(.aggregate, 0, 0, 64, false, writer);
- if (self.target.cpu.arch == .hexagon) {
- try self.typeAlignment(.integer, 64, 64, 64, true, writer);
- try self.typeAlignment(.integer, 32, 32, 32, true, writer);
- try self.typeAlignment(.integer, 16, 16, 16, true, writer);
- try self.typeAlignment(.integer, 1, 8, 8, true, writer);
- try self.typeAlignment(.float, 32, 32, 32, true, writer);
- try self.typeAlignment(.float, 64, 64, 64, true, writer);
- }
- if (stack_abi != ptr_bit_width or self.target.cpu.arch == .msp430 or
- self.target.os.tag == .uefi or self.target.os.tag == .windows or
- self.target.cpu.arch == .riscv32)
- try writer.print("-S{d}", .{stack_abi});
- if (self.target.cpu.arch.isAARCH64())
- try writer.writeAll("-Fn32");
- switch (self.target.cpu.arch) {
- .hexagon, .ve => {
- try self.typeAlignment(.vector, 32, 128, 128, true, writer);
- try self.typeAlignment(.vector, 64, 128, 128, true, writer);
- try self.typeAlignment(.vector, 128, 128, 128, true, writer);
- },
- else => {},
- }
- if (self.target.cpu.arch != .amdgcn) {
- try self.typeAlignment(.vector, 256, 128, 128, true, writer);
- try self.typeAlignment(.vector, 512, 128, 128, true, writer);
- try self.typeAlignment(.vector, 1024, 128, 128, true, writer);
- try self.typeAlignment(.vector, 2048, 128, 128, true, writer);
- try self.typeAlignment(.vector, 4096, 128, 128, true, writer);
- try self.typeAlignment(.vector, 8192, 128, 128, true, writer);
- try self.typeAlignment(.vector, 16384, 128, 128, true, writer);
- }
- const alloca_addr_space = llvmAllocaAddressSpace(self.target);
- if (alloca_addr_space != .default) try writer.print("-A{d}", .{@intFromEnum(alloca_addr_space)});
- const global_addr_space = llvmDefaultGlobalAddressSpace(self.target);
- if (global_addr_space != .default) try writer.print("-G{d}", .{@intFromEnum(global_addr_space)});
- if (any_non_integral) {
- try writer.writeAll("-ni");
- for (addr_space_info) |info| if (info.non_integral)
- try writer.print(":{d}", .{@intFromEnum(info.llvm)});
- }
- }
-
- fn typeAlignment(
- self: DataLayoutBuilder,
- kind: enum { integer, vector, float, aggregate },
- size: u24,
- default_abi: u24,
- default_pref: u24,
- default_force_pref: bool,
- writer: anytype,
- ) @TypeOf(writer).Error!void {
- var abi = default_abi;
- var pref = default_pref;
- var force_abi = false;
- var force_pref = default_force_pref;
- if (kind == .float and size == 80) {
- abi = 128;
- pref = 128;
- }
- for (@as([]const std.Target.CType, switch (kind) {
- .integer => &.{ .char, .short, .int, .long, .longlong },
- .float => &.{ .float, .double, .longdouble },
- .vector, .aggregate => &.{},
- })) |cty| {
- if (self.target.cTypeBitSize(cty) != size) continue;
- abi = self.target.cTypeAlignment(cty) * 8;
- pref = self.target.cTypePreferredAlignment(cty) * 8;
- break;
- }
- switch (kind) {
- .integer => {
- if (self.target.ptrBitWidth() <= 16 and size >= 128) return;
- abi = @min(abi, Type.maxIntAlignment(self.target) * 8);
- switch (self.target.cpu.arch) {
- .aarch64,
- .aarch64_be,
- => if (size == 128) {
- abi = size;
- pref = size;
- } else switch (self.target.os.tag) {
- .macos, .ios, .watchos, .tvos, .visionos => {},
- .uefi, .windows => {
- pref = size;
- force_abi = size >= 32;
- },
- else => pref = @max(pref, 32),
- },
- .arc => if (size <= 64) {
- abi = @min((std.math.divCeil(u24, size, 8) catch unreachable) * 8, 32);
- pref = 32;
- force_abi = true;
- force_pref = size <= 32;
- },
- .bpfeb,
- .bpfel,
- .nvptx,
- .nvptx64,
- .riscv64,
- => if (size == 128) {
- abi = size;
- pref = size;
- },
- .csky => if (size == 32 or size == 64) {
- abi = 32;
- pref = 32;
- force_abi = true;
- force_pref = true;
- },
- .hexagon => force_abi = true,
- .m68k => if (size <= 32) {
- abi = @min(size, 16);
- pref = size;
- force_abi = true;
- force_pref = true;
- } else if (size == 64) {
- abi = 32;
- pref = size;
- },
- .mips,
- .mipsel,
- .mips64,
- .mips64el,
- => pref = @max(pref, 32),
- .s390x => pref = @max(pref, 16),
- .ve => if (size == 64) {
- abi = size;
- pref = size;
- },
- .xtensa => if (size <= 64) {
- pref = @max(size, 32);
- abi = size;
- force_abi = size == 64;
- },
- .x86 => switch (size) {
- 128 => {
- abi = size;
- pref = size;
- },
- else => {},
- },
- .x86_64 => switch (size) {
- 64, 128 => {
- abi = size;
- pref = size;
- },
- else => {},
- },
- .loongarch64 => switch (size) {
- 128 => {
- abi = size;
- pref = size;
- force_abi = true;
- },
- else => {},
- },
- else => {},
- }
- },
- .vector => if (self.target.cpu.arch.isArm()) {
- switch (size) {
- 128 => abi = 64,
- else => {},
- }
- } else if ((self.target.cpu.arch.isPowerPC64() and self.target.os.tag == .linux and
- (size == 256 or size == 512)) or
- (self.target.cpu.arch.isNvptx() and (size == 16 or size == 32)))
- {
- force_abi = true;
- abi = size;
- pref = size;
- } else if (self.target.cpu.arch == .amdgcn and size <= 2048) {
- force_abi = true;
- } else if (self.target.cpu.arch == .csky and (size == 64 or size == 128)) {
- abi = 32;
- pref = 32;
- force_pref = true;
- } else if (self.target.cpu.arch == .hexagon and
- ((size >= 32 and size <= 64) or (size >= 512 and size <= 2048)))
- {
- abi = size;
- pref = size;
- force_pref = true;
- } else if (self.target.cpu.arch == .s390x and size == 128) {
- abi = 64;
- pref = 64;
- force_pref = false;
- } else if (self.target.cpu.arch == .ve and (size >= 64 and size <= 16384)) {
- abi = 64;
- pref = 64;
- force_abi = true;
- force_pref = true;
- },
- .float => switch (self.target.cpu.arch) {
- .amdgcn => if (size == 128) {
- abi = size;
- pref = size;
- },
- .arc => if (size == 32 or size == 64) {
- abi = 32;
- pref = 32;
- force_abi = true;
- force_pref = size == 32;
- },
- .avr, .msp430, .sparc64 => if (size != 32 and size != 64) return,
- .csky => if (size == 32 or size == 64) {
- abi = 32;
- pref = 32;
- force_abi = true;
- force_pref = true;
- },
- .hexagon => if (size == 32 or size == 64) {
- force_abi = true;
- },
- .ve, .xtensa => if (size == 64) {
- abi = size;
- pref = size;
- },
- .wasm32, .wasm64 => if (self.target.os.tag == .emscripten and size == 128) {
- abi = 64;
- pref = 64;
- },
- else => {},
- },
- .aggregate => if (self.target.os.tag == .uefi or self.target.os.tag == .windows or
- self.target.cpu.arch.isArm())
- {
- pref = @min(pref, self.target.ptrBitWidth());
- } else switch (self.target.cpu.arch) {
- .arc, .csky => {
- abi = 0;
- pref = 32;
- },
- .hexagon => {
- abi = 0;
- pref = 0;
- },
- .m68k => {
- abi = 0;
- pref = 16;
- },
- .msp430 => {
- abi = 8;
- pref = 8;
- },
- .s390x => {
- abi = 8;
- pref = 16;
+ break :blk if (target.ofmt == .coff)
+ if (msvc)
+ "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32"
+ else
+ "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"
+ else if (msvc)
+ "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32"
+ else
+ "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32";
},
- else => {},
},
- }
- if (kind != .vector and self.target.cpu.arch == .avr) {
- force_abi = true;
- abi = 8;
- pref = 8;
- }
- if (!force_abi and abi == default_abi and pref == default_pref) return;
- try writer.print("-{c}", .{@tagName(kind)[0]});
- if (size != 0) try writer.print("{d}", .{size});
- try writer.print(":{d}", .{abi});
- if (pref != abi or force_pref) try writer.print(":{d}", .{pref});
- }
-};
+ else => if (target.ofmt == .macho)
+ "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128"
+ else
+ "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128",
+ },
+ .x86_64 => if (target.os.tag.isDarwin() or target.ofmt == .macho)
+ "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+ else switch (target.abi) {
+ .gnux32, .muslx32 => "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
+ else => if (target.os.tag == .windows and target.ofmt == .coff)
+ "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+ else
+ "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
+ },
+ .spirv => "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1",
+ .spirv32 => "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1",
+ .spirv64 => "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1",
+ .wasm32 => if (target.os.tag == .emscripten)
+ "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-f128:64-n32:64-S128-ni:1:10:20"
+ else
+ "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20",
+ .wasm64 => if (target.os.tag == .emscripten)
+ "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-f128:64-n32:64-S128-ni:1:10:20"
+ else
+ "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20",
+ .ve => "e-m:e-i64:64-n32:64-S128-v64:64:64-v128:64:64-v256:64:64-v512:64:64-v1024:64:64-v2048:64:64-v4096:64:64-v8192:64:64-v16384:64:64",
+ .csky => "e-m:e-S32-p:32:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:32-v128:32:32-a:0:32-Fi32-n32",
+ .loongarch32 => "e-m:e-p:32:32-i64:64-n32-S128",
+ .loongarch64 => "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
+ .xtensa => "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32",
+
+ .kalimba,
+ .propeller,
+ => unreachable, // Gated by hasLlvmSupport().
+ };
+}
pub const Object = struct {
gpa: Allocator,
@@ -856,7 +542,7 @@ pub const Object = struct {
});
errdefer builder.deinit();
- builder.data_layout = try builder.fmt("{}", .{DataLayoutBuilder{ .target = target }});
+ builder.data_layout = try builder.string(dataLayout(target));
const debug_compile_unit, const debug_enums_fwd_ref, const debug_globals_fwd_ref =
if (!builder.strip) debug_info: {
@@ -12071,7 +11757,7 @@ fn firstParamSRet(fn_info: InternPool.Key.FuncType, zcu: *Zcu, target: std.Targe
}
fn firstParamSRetSystemV(ty: Type, zcu: *Zcu, target: std.Target) bool {
- const class = x86_64_abi.classifySystemV(ty, zcu, target, .ret);
+ const class = x86_64_abi.classifySystemV(ty, zcu, &target, .ret);
if (class[0] == .memory) return true;
if (class[0] == .x87 and class[2] != .none) return true;
return false;
@@ -12181,7 +11867,7 @@ fn lowerSystemVFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.E
return o.lowerType(return_type);
}
const target = zcu.getTarget();
- const classes = x86_64_abi.classifySystemV(return_type, zcu, target, .ret);
+ const classes = x86_64_abi.classifySystemV(return_type, zcu, &target, .ret);
if (classes[0] == .memory) return .void;
var types_index: u32 = 0;
var types_buffer: [8]Builder.Type = undefined;
@@ -12459,7 +12145,7 @@ const ParamTypeIterator = struct {
const zcu = it.object.pt.zcu;
const ip = &zcu.intern_pool;
const target = zcu.getTarget();
- const classes = x86_64_abi.classifySystemV(ty, zcu, target, .arg);
+ const classes = x86_64_abi.classifySystemV(ty, zcu, &target, .arg);
if (classes[0] == .memory) {
it.zig_index += 1;
it.llvm_index += 1;
diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig
index 1b3dcfe8b5..a657667f15 100644
--- a/src/link/Dwarf.zig
+++ b/src/link/Dwarf.zig
@@ -2008,9 +2008,9 @@ pub const WipNav = struct {
.decl_const_runtime_bits,
.decl_const_comptime_state,
.decl_const_runtime_bits_comptime_state,
- .decl_empty_func,
+ .decl_nullary_func,
.decl_func,
- .decl_empty_func_generic,
+ .decl_nullary_func_generic,
.decl_func_generic,
=> false,
.generic_decl_var,
@@ -2626,8 +2626,8 @@ pub fn finishWipNavFunc(
abbrev_code_buf,
try dwarf.refAbbrevCode(switch (abbrev_code) {
else => unreachable,
- .decl_func => .decl_empty_func,
- .decl_instance_func => .decl_instance_empty_func,
+ .decl_func => .decl_nullary_func,
+ .decl_instance_func => .decl_instance_nullary_func,
}),
);
}
@@ -3012,29 +3012,34 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
if (nav_gop.found_existing) switch (try dwarf.debug_info.declAbbrevCode(wip_nav.unit, nav_gop.value_ptr.*)) {
.null => {},
else => unreachable,
- .decl_empty_func, .decl_func, .decl_instance_empty_func, .decl_instance_func => return,
- .decl_empty_func_generic,
+ .decl_nullary_func, .decl_func, .decl_instance_nullary_func, .decl_instance_func => return,
+ .decl_nullary_func_generic,
.decl_func_generic,
- .decl_instance_empty_func_generic,
+ .decl_instance_nullary_func_generic,
.decl_instance_func_generic,
=> dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear(),
} else nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit);
wip_nav.entry = nav_gop.value_ptr.*;
const func_type = ip.indexToKey(func.ty).func_type;
+ const is_nullary = !func_type.is_var_args and for (0..func_type.param_types.len) |param_index| {
+ if (!func_type.paramIsComptime(std.math.cast(u5, param_index) orelse break false)) break false;
+ } else true;
const diw = wip_nav.debug_info.writer(dwarf.gpa);
- try wip_nav.declCommon(if (func_type.param_types.len > 0 or func_type.is_var_args) .{
- .decl = .decl_func_generic,
+ try wip_nav.declCommon(if (is_nullary) .{
+ .decl = .decl_nullary_func_generic,
.generic_decl = .generic_decl_func,
- .decl_instance = .decl_instance_func_generic,
+ .decl_instance = .decl_instance_nullary_func_generic,
} else .{
- .decl = .decl_empty_func_generic,
+ .decl = .decl_func_generic,
.generic_decl = .generic_decl_func,
- .decl_instance = .decl_instance_empty_func_generic,
+ .decl_instance = .decl_instance_func_generic,
}, &nav, inst_info.file, &decl);
try wip_nav.refType(.fromInterned(func_type.return_type));
- if (func_type.param_types.len > 0 or func_type.is_var_args) {
+ if (!is_nullary) {
for (0..func_type.param_types.len) |param_index| {
+ if (std.math.cast(u5, param_index)) |small_param_index|
+ if (func_type.paramIsComptime(small_param_index)) continue;
try wip_nav.abbrevCode(.func_type_param);
try wip_nav.refType(.fromInterned(func_type.param_types.get(ip)[param_index]));
}
@@ -3568,12 +3573,14 @@ fn updateLazyType(
};
try diw.writeByte(@intFromEnum(cc));
try wip_nav.refType(.fromInterned(func_type.return_type));
- for (0..func_type.param_types.len) |param_index| {
- try wip_nav.abbrevCode(.func_type_param);
- try wip_nav.refType(.fromInterned(func_type.param_types.get(ip)[param_index]));
+ if (!is_nullary) {
+ for (0..func_type.param_types.len) |param_index| {
+ try wip_nav.abbrevCode(.func_type_param);
+ try wip_nav.refType(.fromInterned(func_type.param_types.get(ip)[param_index]));
+ }
+ if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args);
+ try uleb128(diw, @intFromEnum(AbbrevCode.null));
}
- if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args);
- if (!is_nullary) try uleb128(diw, @intFromEnum(AbbrevCode.null));
},
.error_set_type => |error_set_type| {
try wip_nav.abbrevCode(if (error_set_type.names.len == 0) .generated_empty_enum_type else .generated_enum_type);
@@ -4787,9 +4794,9 @@ const AbbrevCode = enum {
decl_const_runtime_bits,
decl_const_comptime_state,
decl_const_runtime_bits_comptime_state,
- decl_empty_func,
+ decl_nullary_func,
decl_func,
- decl_empty_func_generic,
+ decl_nullary_func_generic,
decl_func_generic,
generic_decl_var,
generic_decl_const,
@@ -4806,9 +4813,9 @@ const AbbrevCode = enum {
decl_instance_const_runtime_bits,
decl_instance_const_comptime_state,
decl_instance_const_runtime_bits_comptime_state,
- decl_instance_empty_func,
+ decl_instance_nullary_func,
decl_instance_func,
- decl_instance_empty_func_generic,
+ decl_instance_nullary_func_generic,
decl_instance_func_generic,
// the rest are unrestricted other than empty variants must not be longer
// than the non-empty variant, and so should appear first
@@ -5019,7 +5026,7 @@ const AbbrevCode = enum {
.{ .ZIG_comptime_value, .ref_addr },
},
},
- .decl_empty_func = .{
+ .decl_nullary_func = .{
.tag = .subprogram,
.attrs = decl_abbrev_common_attrs ++ .{
.{ .linkage_name, .strp },
@@ -5044,7 +5051,7 @@ const AbbrevCode = enum {
.{ .noreturn, .flag },
},
},
- .decl_empty_func_generic = .{
+ .decl_nullary_func_generic = .{
.tag = .subprogram,
.attrs = decl_abbrev_common_attrs ++ .{
.{ .type, .ref_addr },
@@ -5167,7 +5174,7 @@ const AbbrevCode = enum {
.{ .ZIG_comptime_value, .ref_addr },
},
},
- .decl_instance_empty_func = .{
+ .decl_instance_nullary_func = .{
.tag = .subprogram,
.attrs = decl_instance_abbrev_common_attrs ++ .{
.{ .linkage_name, .strp },
@@ -5192,7 +5199,7 @@ const AbbrevCode = enum {
.{ .noreturn, .flag },
},
},
- .decl_instance_empty_func_generic = .{
+ .decl_instance_nullary_func_generic = .{
.tag = .subprogram,
.attrs = decl_instance_abbrev_common_attrs ++ .{
.{ .type, .ref_addr },
diff --git a/src/main.zig b/src/main.zig
index bc8fc930f5..356808804a 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -39,7 +39,7 @@ test {
_ = Package;
}
-const thread_stack_size = 32 << 20;
+const thread_stack_size = 50 << 20;
pub const std_options: std.Options = .{
.wasiCwd = wasi_cwd,
diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig
index f2fa2f4b0a..4b11f61f19 100644
--- a/test/behavior/floatop.zig
+++ b/test/behavior/floatop.zig
@@ -132,13 +132,20 @@ test "cmp f16" {
try comptime testCmp(f16);
}
-test "cmp f32/f64" {
+test "cmp f32" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234
+ if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
try testCmp(f32);
try comptime testCmp(f32);
+}
+
+test "cmp f64" {
+ if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
+ if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234
+
try testCmp(f64);
try comptime testCmp(f64);
}
@@ -224,6 +231,98 @@ fn testCmp(comptime T: type) !void {
}
}
+test "vector cmp f16" {
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+
+ try testCmpVector(f16);
+ try comptime testCmpVector(f16);
+}
+
+test "vector cmp f32" {
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+
+ try testCmpVector(f32);
+ try comptime testCmpVector(f32);
+}
+
+test "vector cmp f64" {
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+
+ try testCmpVector(f64);
+ try comptime testCmpVector(f64);
+}
+
+test "vector cmp f128" {
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
+ if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
+ if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
+
+ try testCmpVector(f128);
+ try comptime testCmpVector(f128);
+}
+
+test "vector cmp f80/c_longdouble" {
+ if (true) return error.SkipZigTest;
+
+ try testCmpVector(f80);
+ try comptime testCmpVector(f80);
+ try testCmpVector(c_longdouble);
+ try comptime testCmpVector(c_longdouble);
+}
+fn testCmpVector(comptime T: type) !void {
+ var edges = [_]T{
+ -math.inf(T),
+ -math.floatMax(T),
+ -math.floatMin(T),
+ -math.floatTrueMin(T),
+ -0.0,
+ math.nan(T),
+ 0.0,
+ math.floatTrueMin(T),
+ math.floatMin(T),
+ math.floatMax(T),
+ math.inf(T),
+ };
+ _ = &edges;
+ for (edges, 0..) |rhs, rhs_i| {
+ const rhs_v: @Vector(4, T) = .{ rhs, rhs, rhs, rhs };
+ for (edges, 0..) |lhs, lhs_i| {
+ const no_nan = lhs_i != 5 and rhs_i != 5;
+ const lhs_order = if (lhs_i < 5) lhs_i else lhs_i - 2;
+ const rhs_order = if (rhs_i < 5) rhs_i else rhs_i - 2;
+ const lhs_v: @Vector(4, T) = .{ lhs, lhs, lhs, lhs };
+ try expect(@reduce(.And, (lhs_v == rhs_v)) == (no_nan and lhs_order == rhs_order));
+ try expect(@reduce(.And, (lhs_v != rhs_v)) == !(no_nan and lhs_order == rhs_order));
+ try expect(@reduce(.And, (lhs_v < rhs_v)) == (no_nan and lhs_order < rhs_order));
+ try expect(@reduce(.And, (lhs_v > rhs_v)) == (no_nan and lhs_order > rhs_order));
+ try expect(@reduce(.And, (lhs_v <= rhs_v)) == (no_nan and lhs_order <= rhs_order));
+ try expect(@reduce(.And, (lhs_v >= rhs_v)) == (no_nan and lhs_order >= rhs_order));
+ }
+ }
+}
+
test "different sized float comparisons" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
@@ -1703,3 +1802,33 @@ test "optimized float mode" {
try expect(S.optimized(small) == small);
try expect(S.strict(small) == tiny);
}
+
+fn MakeType(comptime x: anytype) type {
+ return struct {
+ fn get() @TypeOf(x) {
+ return x;
+ }
+ };
+}
+
+const nan_a: f32 = @bitCast(@as(u32, 0xffc00000));
+const nan_b: f32 = @bitCast(@as(u32, 0xffe00000));
+
+fn testMemoization() !void {
+ try expect(MakeType(nan_a) == MakeType(nan_a));
+ try expect(MakeType(nan_b) == MakeType(nan_b));
+ try expect(MakeType(nan_a) != MakeType(nan_b));
+}
+
+fn testVectorMemoization(comptime T: type) !void {
+ const nan_a_v: T = @splat(nan_a);
+ const nan_b_v: T = @splat(nan_b);
+ try expect(MakeType(nan_a_v) == MakeType(nan_a_v));
+ try expect(MakeType(nan_b_v) == MakeType(nan_b_v));
+ try expect(MakeType(nan_a_v) != MakeType(nan_b_v));
+}
+
+test "comptime calls are only memoized when float arguments are bit-for-bit equal" {
+ try comptime testMemoization();
+ try comptime testVectorMemoization(@Vector(4, f32));
+}
diff --git a/test/behavior/select.zig b/test/behavior/select.zig
index f551ff9533..604227b17f 100644
--- a/test/behavior/select.zig
+++ b/test/behavior/select.zig
@@ -66,3 +66,23 @@ fn selectArrays() !void {
const xyz = @select(f32, x, y, z);
try expect(mem.eql(f32, &@as([4]f32, xyz), &[4]f32{ 0.0, 312.1, -145.9, -3381.233 }));
}
+
+test "@select compare result" {
+ if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
+
+ const S = struct {
+ fn min(comptime V: type, lhs: V, rhs: V) V {
+ return @select(@typeInfo(V).vector.child, lhs < rhs, lhs, rhs);
+ }
+
+ fn doTheTest() !void {
+ try expect(@reduce(.And, min(@Vector(4, f32), .{ -1, 2, -3, 4 }, .{ 1, -2, 3, -4 }) == @Vector(4, f32){ -1, -2, -3, -4 }));
+ try expect(@reduce(.And, min(@Vector(2, f64), .{ -1, 2 }, .{ 1, -2 }) == @Vector(2, f64){ -1, -2 }));
+ }
+ };
+
+ try S.doTheTest();
+ try comptime S.doTheTest();
+}
diff --git a/test/behavior/this.zig b/test/behavior/this.zig
index 3f8fe13316..9f10348b46 100644
--- a/test/behavior/this.zig
+++ b/test/behavior/this.zig
@@ -1,4 +1,5 @@
-const expect = @import("std").testing.expect;
+const std = @import("std");
+const expect = std.testing.expect;
const builtin = @import("builtin");
const module = @This();
@@ -55,3 +56,10 @@ test "this used as optional function parameter" {
global.enter = prev;
global.enter(null);
}
+
+test "@This() in opaque" {
+ const T = opaque {
+ const Self = @This();
+ };
+ comptime std.debug.assert(T.Self == T);
+}
diff --git a/test/cases/compile_errors/union_field_ordered_differently_than_enum.zig b/test/cases/compile_errors/union_field_ordered_differently_than_enum.zig
new file mode 100644
index 0000000000..5c86fb4080
--- /dev/null
+++ b/test/cases/compile_errors/union_field_ordered_differently_than_enum.zig
@@ -0,0 +1,27 @@
+const Tag = enum { a, b };
+
+const Union = union(Tag) {
+ b,
+ a,
+};
+
+const BaseUnion = union(enum) {
+ a,
+ b,
+};
+
+const GeneratedTagUnion = union(@typeInfo(BaseUnion).@"union".tag_type.?) {
+ b,
+ a,
+};
+
+export fn entry() usize {
+ return @sizeOf(Union) + @sizeOf(GeneratedTagUnion);
+}
+
+// error
+//
+// :4:5: error: union field 'b' ordered differently than corresponding enum field
+// :1:23: note: enum field here
+// :14:5: error: union field 'b' ordered differently than corresponding enum field
+// :10:5: note: enum field here
diff --git a/test/link/elf.zig b/test/link/elf.zig
index 1afe1777d3..92b857a565 100644
--- a/test/link/elf.zig
+++ b/test/link/elf.zig
@@ -114,7 +114,8 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {
elf_step.dependOn(testLargeBss(b, .{ .target = gnu_target }));
elf_step.dependOn(testLinkOrder(b, .{ .target = gnu_target }));
elf_step.dependOn(testLdScript(b, .{ .target = gnu_target }));
- elf_step.dependOn(testLdScriptPathError(b, .{ .target = gnu_target }));
+ // https://github.com/ziglang/zig/issues/23125
+ // elf_step.dependOn(testLdScriptPathError(b, .{ .target = gnu_target }));
elf_step.dependOn(testLdScriptAllowUndefinedVersion(b, .{ .target = gnu_target, .use_lld = true }));
elf_step.dependOn(testLdScriptDisallowUndefinedVersion(b, .{ .target = gnu_target, .use_lld = true }));
// https://github.com/ziglang/zig/issues/17451
diff --git a/test/tests.zig b/test/tests.zig
index 7ef5a33a03..28c6fbc67e 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -1430,14 +1430,6 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
test_target.use_llvm == false and mem.eql(u8, options.name, "compiler-rt"))
continue;
- // TODO get compiler-rt tests passing for wasm32-wasi
- // currently causes "LLVM ERROR: Unable to expand fixed point multiplication."
- if (target.cpu.arch == .wasm32 and target.os.tag == .wasi and
- mem.eql(u8, options.name, "compiler-rt"))
- {
- continue;
- }
-
// TODO get universal-libc tests passing for other self-hosted backends.
if (target.cpu.arch != .x86_64 and
test_target.use_llvm == false and mem.eql(u8, options.name, "universal-libc"))