Merge pull request #25965 from alexrp/s390x

`s390x-linux` and general big-endian stuff
This commit is contained in:
Alex Rønne Petersen 2025-11-19 19:52:18 +01:00 committed by GitHub
commit 43371cf388
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 454 additions and 181 deletions

View File

@ -73,6 +73,26 @@ jobs:
- name: Build and Test
run: sh ci/riscv64-linux-release.sh
timeout-minutes: 420
s390x-linux-debug:
runs-on: [self-hosted, s390x-linux]
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Build and Test
run: sh ci/s390x-linux-debug.sh
timeout-minutes: 240
s390x-linux-release:
runs-on: [self-hosted, s390x-linux]
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Build and Test
run: sh ci/s390x-linux-release.sh
timeout-minutes: 180
x86_64-freebsd-debug:
runs-on: [self-hosted, x86_64-freebsd]
steps:

65
ci/s390x-linux-debug.sh Executable file
View File

@ -0,0 +1,65 @@
#!/bin/sh
# Requires cmake ninja-build
set -x
set -e
TARGET="s390x-linux-musl"
MCPU="z15"
CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.16.0-dev.1354+94e98bfe8"
PREFIX="$HOME/deps/$CACHE_BASENAME"
ZIG="$PREFIX/bin/zig"
# Override the cache directories because they won't actually help other CI runs
# which will be testing alternate versions of zig, and ultimately would just
# fill up space on the hard drive for no reason.
export ZIG_GLOBAL_CACHE_DIR="$PWD/zig-global-cache"
export ZIG_LOCAL_CACHE_DIR="$PWD/zig-local-cache"
mkdir build-debug
cd build-debug
export CC="$ZIG cc -target $TARGET -mcpu=$MCPU"
export CXX="$ZIG c++ -target $TARGET -mcpu=$MCPU"
cmake .. \
-DCMAKE_INSTALL_PREFIX="stage3-debug" \
-DCMAKE_PREFIX_PATH="$PREFIX" \
-DCMAKE_BUILD_TYPE=Debug \
-DZIG_TARGET_TRIPLE="$TARGET" \
-DZIG_TARGET_MCPU="$MCPU" \
-DZIG_STATIC=ON \
-DZIG_NO_LIB=ON \
-GNinja \
-DCMAKE_C_LINKER_DEPFILE_SUPPORTED=FALSE \
-DCMAKE_CXX_LINKER_DEPFILE_SUPPORTED=FALSE
# https://github.com/ziglang/zig/issues/22213
# Now cmake will use zig as the C/C++ compiler. We reset the environment variables
# so that installation and testing do not get affected by them.
unset CC
unset CXX
ninja install
# No -fqemu and -fwasmtime here as they're covered by the x86_64-linux scripts.
stage3-debug/bin/zig build test docs \
--maxrss 30064771072 \
-Dstatic-llvm \
-Dskip-non-native \
-Dtarget=native-native-musl \
--search-prefix "$PREFIX" \
--zig-lib-dir "$PWD/../lib" \
--test-timeout 4m
stage3-debug/bin/zig build \
--prefix stage4-debug \
-Denable-llvm \
-Dno-lib \
-Dtarget=$TARGET \
-Dcpu=$MCPU \
-Duse-zig-libcxx \
-Dversion-string="$(stage3-debug/bin/zig version)"
stage4-debug/bin/zig test ../test/behavior.zig

71
ci/s390x-linux-release.sh Executable file
View File

@ -0,0 +1,71 @@
#!/bin/sh
# Requires cmake ninja-build
set -x
set -e
TARGET="s390x-linux-musl"
MCPU="z15"
CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.16.0-dev.1354+94e98bfe8"
PREFIX="$HOME/deps/$CACHE_BASENAME"
ZIG="$PREFIX/bin/zig"
# Override the cache directories because they won't actually help other CI runs
# which will be testing alternate versions of zig, and ultimately would just
# fill up space on the hard drive for no reason.
export ZIG_GLOBAL_CACHE_DIR="$PWD/zig-global-cache"
export ZIG_LOCAL_CACHE_DIR="$PWD/zig-local-cache"
mkdir build-release
cd build-release
export CC="$ZIG cc -target $TARGET -mcpu=$MCPU"
export CXX="$ZIG c++ -target $TARGET -mcpu=$MCPU"
cmake .. \
-DCMAKE_INSTALL_PREFIX="stage3-release" \
-DCMAKE_PREFIX_PATH="$PREFIX" \
-DCMAKE_BUILD_TYPE=Release \
-DZIG_TARGET_TRIPLE="$TARGET" \
-DZIG_TARGET_MCPU="$MCPU" \
-DZIG_STATIC=ON \
-DZIG_NO_LIB=ON \
-GNinja \
-DCMAKE_C_LINKER_DEPFILE_SUPPORTED=FALSE \
-DCMAKE_CXX_LINKER_DEPFILE_SUPPORTED=FALSE
# https://github.com/ziglang/zig/issues/22213
# Now cmake will use zig as the C/C++ compiler. We reset the environment variables
# so that installation and testing do not get affected by them.
unset CC
unset CXX
ninja install
# No -fqemu and -fwasmtime here as they're covered by the x86_64-linux scripts.
stage3-release/bin/zig build test docs \
--maxrss 30064771072 \
-Dstatic-llvm \
-Dskip-non-native \
-Dtarget=native-native-musl \
--search-prefix "$PREFIX" \
--zig-lib-dir "$PWD/../lib" \
--test-timeout 4m
# Ensure that stage3 and stage4 are byte-for-byte identical.
stage3-release/bin/zig build \
--prefix stage4-release \
-Denable-llvm \
-Dno-lib \
-Doptimize=ReleaseFast \
-Dstrip \
-Dtarget=$TARGET \
-Dcpu=$MCPU \
-Duse-zig-libcxx \
-Dversion-string="$(stage3-release/bin/zig version)"
# diff returns an error code if the files differ.
echo "If the following command fails, it means nondeterminism has been"
echo "introduced, making stage3 and stage4 no longer byte-for-byte identical."
diff stage3-release/bin/zig stage4-release/bin/zig

View File

@ -7,7 +7,7 @@ pub fn main() void {
const y = @shrExact(x, 2);
std.debug.print("value: {}\n", .{y});
if ((builtin.cpu.arch.isRISCV() or builtin.cpu.arch.isLoongArch()) and builtin.zig_backend == .stage2_llvm) @panic("https://github.com/ziglang/zig/issues/24304");
if ((builtin.cpu.arch.isRISCV() or builtin.cpu.arch.isLoongArch() or builtin.cpu.arch == .s390x) and builtin.zig_backend == .stage2_llvm) @panic("https://github.com/ziglang/zig/issues/24304");
}
// exe=fail

View File

@ -22,6 +22,10 @@ test "defining a variadic function" {
// https://github.com/ziglang/zig/issues/16961
return error.SkipZigTest;
}
if (builtin.cpu.arch == .s390x) {
// https://github.com/ziglang/zig/issues/21350#issuecomment-3543006475
return error.SkipZigTest;
}
try std.testing.expectEqual(@as(c_int, 0), add(0));
try std.testing.expectEqual(@as(c_int, 1), add(1, @as(c_int, 1)));

View File

@ -774,6 +774,11 @@ fn generateSystemDefines(comp: *Compilation, w: *Io.Writer) !void {
try w.print("#define __wasm_{s}__ 1\n", .{feature.name});
}
},
.s390x => {
try define(w, "__s390__");
try define(w, "__s390x__");
try define(w, "__zarch__");
},
else => {},
}

View File

@ -348,12 +348,12 @@ fn buildWasmBinary(
result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body);
},
.emit_digest => {
const EmitDigest = std.zig.Server.Message.EmitDigest;
const emit_digest = @as(*align(1) const EmitDigest, @ptrCast(body));
var r: std.Io.Reader = .fixed(body);
const emit_digest = r.takeStruct(std.zig.Server.Message.EmitDigest, .little) catch unreachable;
if (!emit_digest.flags.cache_hit) {
std.log.info("source changes detected; rebuilt wasm component", .{});
}
const digest = body[@sizeOf(EmitDigest)..][0..Cache.bin_digest_len];
const digest = r.takeArray(Cache.bin_digest_len) catch unreachable;
result = .{
.root_dir = Cache.Directory.cwd(),
.sub_path = try std.fs.path.join(arena, &.{
@ -415,7 +415,10 @@ fn sendMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag) !void {
.tag = tag,
.bytes_len = 0,
};
try file.writeAll(std.mem.asBytes(&header));
var w = file.writer(&.{});
w.interface.writeStruct(header, .little) catch |err| switch (err) {
error.WriteFailed => return w.err.?,
};
}
fn openBrowserTab(gpa: Allocator, url: []const u8) !void {

View File

@ -680,7 +680,10 @@ fn sendMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag) !void {
.tag = tag,
.bytes_len = 0,
};
try file.writeAll(std.mem.asBytes(&header));
var w = file.writer(&.{});
w.interface.writeStruct(header, .little) catch |err| switch (err) {
error.WriteFailed => return w.err.?,
};
}
pub fn handleVerbose(

View File

@ -1857,15 +1857,26 @@ const ElfDumper = struct {
fn parseAndDumpObject(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
const gpa = step.owner.allocator;
var reader: std.Io.Reader = .fixed(bytes);
const hdr = try reader.takeStruct(elf.Elf64_Ehdr, .little);
if (!mem.eql(u8, hdr.e_ident[0..4], "\x7fELF")) {
return error.InvalidMagicNumber;
// `std.elf.Header` takes care of endianness issues for us.
var reader: std.Io.Reader = .fixed(bytes);
const hdr = try elf.Header.read(&reader);
var shdrs = try gpa.alloc(elf.Elf64_Shdr, hdr.shnum);
defer gpa.free(shdrs);
{
var shdr_it = hdr.iterateSectionHeadersBuffer(bytes);
var shdr_i: usize = 0;
while (try shdr_it.next()) |shdr| : (shdr_i += 1) shdrs[shdr_i] = shdr;
}
const shdrs = @as([*]align(1) const elf.Elf64_Shdr, @ptrCast(bytes.ptr + hdr.e_shoff))[0..hdr.e_shnum];
const phdrs = @as([*]align(1) const elf.Elf64_Phdr, @ptrCast(bytes.ptr + hdr.e_phoff))[0..hdr.e_phnum];
var phdrs = try gpa.alloc(elf.Elf64_Phdr, hdr.shnum);
defer gpa.free(phdrs);
{
var phdr_it = hdr.iterateProgramHeadersBuffer(bytes);
var phdr_i: usize = 0;
while (try phdr_it.next()) |phdr| : (phdr_i += 1) phdrs[phdr_i] = phdr;
}
var ctx = ObjectContext{
.gpa = gpa,
@ -1875,13 +1886,21 @@ const ElfDumper = struct {
.phdrs = phdrs,
.shstrtab = undefined,
};
ctx.shstrtab = ctx.getSectionContents(ctx.hdr.e_shstrndx);
ctx.shstrtab = ctx.getSectionContents(ctx.hdr.shstrndx);
defer gpa.free(ctx.symtab.symbols);
defer gpa.free(ctx.dysymtab.symbols);
defer gpa.free(ctx.dyns);
for (ctx.shdrs, 0..) |shdr, i| switch (shdr.sh_type) {
elf.SHT_SYMTAB, elf.SHT_DYNSYM => {
const raw = ctx.getSectionContents(i);
const nsyms = @divExact(raw.len, @sizeOf(elf.Elf64_Sym));
const symbols = @as([*]align(1) const elf.Elf64_Sym, @ptrCast(raw.ptr))[0..nsyms];
const symbols = try gpa.alloc(elf.Elf64_Sym, nsyms);
var r: std.Io.Reader = .fixed(raw);
for (0..nsyms) |si| symbols[si] = r.takeStruct(elf.Elf64_Sym, ctx.hdr.endian) catch unreachable;
const strings = ctx.getSectionContents(shdr.sh_link);
switch (shdr.sh_type) {
@ -1900,6 +1919,17 @@ const ElfDumper = struct {
else => unreachable,
}
},
elf.SHT_DYNAMIC => {
const raw = ctx.getSectionContents(i);
const ndyns = @divExact(raw.len, @sizeOf(elf.Elf64_Dyn));
const dyns = try gpa.alloc(elf.Elf64_Dyn, ndyns);
var r: std.Io.Reader = .fixed(raw);
for (0..ndyns) |si| dyns[si] = r.takeStruct(elf.Elf64_Dyn, ctx.hdr.endian) catch unreachable;
ctx.dyns = dyns;
ctx.dyns_strings = ctx.getSectionContents(shdr.sh_link);
},
else => {},
};
@ -1923,9 +1953,9 @@ const ElfDumper = struct {
try ctx.dumpSymtab(.dysymtab, writer);
} else return step.fail("no dynamic symbol table found", .{}),
.dynamic_section => if (ctx.getSectionByName(".dynamic")) |shndx| {
try ctx.dumpDynamicSection(shndx, writer);
} else return step.fail("no .dynamic section found", .{}),
.dynamic_section => if (ctx.dyns.len > 0) {
try ctx.dumpDynamicSection(writer);
} else return step.fail("no dynamic section found", .{}),
.dump_section => {
const name = mem.sliceTo(@as([*:0]const u8, @ptrCast(check.data.items.ptr + check.payload.dump_section)), 0);
@ -1942,17 +1972,19 @@ const ElfDumper = struct {
const ObjectContext = struct {
gpa: Allocator,
data: []const u8,
hdr: elf.Elf64_Ehdr,
shdrs: []align(1) const elf.Elf64_Shdr,
phdrs: []align(1) const elf.Elf64_Phdr,
hdr: elf.Header,
shdrs: []const elf.Elf64_Shdr,
phdrs: []const elf.Elf64_Phdr,
shstrtab: []const u8,
symtab: Symtab = .{},
dysymtab: Symtab = .{},
dyns: []const elf.Elf64_Dyn = &.{},
dyns_strings: []const u8 = &.{},
fn dumpHeader(ctx: ObjectContext, writer: anytype) !void {
try writer.writeAll("header\n");
try writer.print("type {s}\n", .{@tagName(ctx.hdr.e_type)});
try writer.print("entry {x}\n", .{ctx.hdr.e_entry});
try writer.print("type {s}\n", .{@tagName(ctx.hdr.type)});
try writer.print("entry {x}\n", .{ctx.hdr.entry});
}
fn dumpPhdrs(ctx: ObjectContext, writer: anytype) !void {
@ -2011,16 +2043,10 @@ const ElfDumper = struct {
}
}
fn dumpDynamicSection(ctx: ObjectContext, shndx: usize, writer: anytype) !void {
const shdr = ctx.shdrs[shndx];
const strtab = ctx.getSectionContents(shdr.sh_link);
const data = ctx.getSectionContents(shndx);
const nentries = @divExact(data.len, @sizeOf(elf.Elf64_Dyn));
const entries = @as([*]align(1) const elf.Elf64_Dyn, @ptrCast(data.ptr))[0..nentries];
fn dumpDynamicSection(ctx: ObjectContext, writer: anytype) !void {
try writer.writeAll(ElfDumper.dynamic_section_label ++ "\n");
for (entries) |entry| {
for (ctx.dyns) |entry| {
const key = @as(u64, @bitCast(entry.d_tag));
const value = entry.d_val;
@ -2067,7 +2093,7 @@ const ElfDumper = struct {
elf.DT_RPATH,
elf.DT_RUNPATH,
=> {
const name = getString(strtab, @intCast(value));
const name = getString(ctx.dyns_strings, @intCast(value));
try writer.print(" {s}", .{name});
},
@ -2256,8 +2282,8 @@ const ElfDumper = struct {
};
const Symtab = struct {
symbols: []align(1) const elf.Elf64_Sym = &[0]elf.Elf64_Sym{},
strings: []const u8 = &[0]u8{},
symbols: []const elf.Elf64_Sym = &.{},
strings: []const u8 = &.{},
fn get(st: Symtab, index: usize) ?elf.Elf64_Sym {
if (index >= st.symbols.len) return null;

View File

@ -1927,6 +1927,7 @@ fn pollZigTest(
.ns_elapsed = if (timer) |*t| t.read() else 0,
} };
const body = stdout.take(header.bytes_len) catch unreachable;
var body_r: std.Io.Reader = .fixed(body);
switch (header.tag) {
.zig_version => {
if (!std.mem.eql(u8, builtin.zig_version_string, body)) return run.step.fail(
@ -1942,29 +1943,23 @@ fn pollZigTest(
// restart the test runner).
assert(opt_metadata.* == null);
const TmHdr = std.zig.Server.Message.TestMetadata;
const tm_hdr: *align(1) const TmHdr = @ptrCast(body);
const tm_hdr = body_r.takeStruct(std.zig.Server.Message.TestMetadata, .little) catch unreachable;
results.test_count = tm_hdr.tests_len;
const names_bytes = body[@sizeOf(TmHdr)..][0 .. results.test_count * @sizeOf(u32)];
const expected_panic_msgs_bytes = body[@sizeOf(TmHdr) + names_bytes.len ..][0 .. results.test_count * @sizeOf(u32)];
const string_bytes = body[@sizeOf(TmHdr) + names_bytes.len + expected_panic_msgs_bytes.len ..][0..tm_hdr.string_bytes_len];
const names = try arena.alloc(u32, results.test_count);
for (names) |*dest| dest.* = body_r.takeInt(u32, .little) catch unreachable;
const names = std.mem.bytesAsSlice(u32, names_bytes);
const expected_panic_msgs = std.mem.bytesAsSlice(u32, expected_panic_msgs_bytes);
const expected_panic_msgs = try arena.alloc(u32, results.test_count);
for (expected_panic_msgs) |*dest| dest.* = body_r.takeInt(u32, .little) catch unreachable;
const names_aligned = try arena.alloc(u32, names.len);
for (names_aligned, names) |*dest, src| dest.* = src;
const expected_panic_msgs_aligned = try arena.alloc(u32, expected_panic_msgs.len);
for (expected_panic_msgs_aligned, expected_panic_msgs) |*dest, src| dest.* = src;
const string_bytes = body_r.take(tm_hdr.string_bytes_len) catch unreachable;
options.progress_node.setEstimatedTotalItems(names.len);
opt_metadata.* = .{
.string_bytes = try arena.dupe(u8, string_bytes),
.ns_per_test = try arena.alloc(u64, results.test_count),
.names = names_aligned,
.expected_panic_msgs = expected_panic_msgs_aligned,
.names = names,
.expected_panic_msgs = expected_panic_msgs,
.next_index = 0,
.prog_node = options.progress_node,
};
@ -1983,8 +1978,7 @@ fn pollZigTest(
assert(fuzz_context == null);
const md = &opt_metadata.*.?;
const TrHdr = std.zig.Server.Message.TestResults;
const tr_hdr: *align(1) const TrHdr = @ptrCast(body);
const tr_hdr = body_r.takeStruct(std.zig.Server.Message.TestResults, .little) catch unreachable;
assert(tr_hdr.index == active_test_index);
switch (tr_hdr.flags.status) {
@ -2026,18 +2020,21 @@ fn pollZigTest(
requestNextTest(child.stdin.?, md, &sub_prog_node) catch |err| return .{ .write_failed = err };
},
.coverage_id => {
const fuzz = fuzz_context.?.fuzz;
const msg_ptr: *align(1) const [4]u64 = @ptrCast(body);
coverage_id = msg_ptr[0];
coverage_id = body_r.takeInt(u64, .little) catch unreachable;
const cumulative_runs = body_r.takeInt(u64, .little) catch unreachable;
const cumulative_unique = body_r.takeInt(u64, .little) catch unreachable;
const cumulative_coverage = body_r.takeInt(u64, .little) catch unreachable;
{
const fuzz = fuzz_context.?.fuzz;
fuzz.queue_mutex.lock();
defer fuzz.queue_mutex.unlock();
try fuzz.msg_queue.append(fuzz.gpa, .{ .coverage = .{
.id = coverage_id.?,
.cumulative = .{
.runs = msg_ptr[1],
.unique = msg_ptr[2],
.coverage = msg_ptr[3],
.runs = cumulative_runs,
.unique = cumulative_unique,
.coverage = cumulative_coverage,
},
.run = run,
} });
@ -2046,8 +2043,7 @@ fn pollZigTest(
},
.fuzz_start_addr => {
const fuzz = fuzz_context.?.fuzz;
const msg_ptr: *align(1) const u64 = @ptrCast(body);
const addr = msg_ptr.*;
const addr = body_r.takeInt(u64, .little) catch unreachable;
{
fuzz.queue_mutex.lock();
defer fuzz.queue_mutex.unlock();
@ -2116,7 +2112,10 @@ fn sendMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag) !void {
.tag = tag,
.bytes_len = 0,
};
try file.writeAll(@ptrCast(&header));
var w = file.writer(&.{});
w.interface.writeStruct(header, .little) catch |err| switch (err) {
error.WriteFailed => return w.err.?,
};
}
fn sendRunTestMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag, index: u32) !void {
@ -2124,8 +2123,13 @@ fn sendRunTestMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag, index:
.tag = tag,
.bytes_len = 4,
};
const full_msg = std.mem.asBytes(&header) ++ std.mem.asBytes(&index);
try file.writeAll(full_msg);
var w = file.writer(&.{});
w.interface.writeStruct(header, .little) catch |err| switch (err) {
error.WriteFailed => return w.err.?,
};
w.interface.writeInt(u32, index, .little) catch |err| switch (err) {
error.WriteFailed => return w.err.?,
};
}
fn sendRunFuzzTestMessage(
@ -2138,10 +2142,19 @@ fn sendRunFuzzTestMessage(
.tag = .start_fuzzing,
.bytes_len = 4 + 1 + 8,
};
const full_msg = std.mem.asBytes(&header) ++ std.mem.asBytes(&index) ++
std.mem.asBytes(&kind) ++ std.mem.asBytes(&amount_or_instance);
try file.writeAll(full_msg);
var w = file.writer(&.{});
w.interface.writeStruct(header, .little) catch |err| switch (err) {
error.WriteFailed => return w.err.?,
};
w.interface.writeInt(u32, index, .little) catch |err| switch (err) {
error.WriteFailed => return w.err.?,
};
w.interface.writeByte(@intFromEnum(kind)) catch |err| switch (err) {
error.WriteFailed => return w.err.?,
};
w.interface.writeInt(u64, amount_or_instance, .little) catch |err| switch (err) {
error.WriteFailed => return w.err.?,
};
}
fn evalGeneric(run: *Run, child: *std.process.Child) !EvalGenericResult {

View File

@ -4488,6 +4488,8 @@ test "copy_cqes with wrapping sq.cqes buffer" {
}
test "bind/listen/connect" {
if (builtin.cpu.arch == .s390x) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/25956
var ring = IoUring.init(4, 0) catch |err| switch (err) {
error.SystemOutdated => return error.SkipZigTest,
error.PermissionDenied => return error.SkipZigTest,

View File

@ -238,26 +238,34 @@ pub fn serveErrorBundle(s: *Server, error_bundle: std.zig.ErrorBundle) !void {
try s.out.flush();
}
pub fn allocErrorBundle(allocator: std.mem.Allocator, body: []const u8) !std.zig.ErrorBundle {
const eb_hdr = @as(*align(1) const OutMessage.ErrorBundle, @ptrCast(body));
const extra_bytes =
body[@sizeOf(OutMessage.ErrorBundle)..][0 .. @sizeOf(u32) * eb_hdr.extra_len];
const string_bytes =
body[@sizeOf(OutMessage.ErrorBundle) + extra_bytes.len ..][0..eb_hdr.string_bytes_len];
const unaligned_extra: []align(1) const u32 = @ptrCast(extra_bytes);
pub fn allocErrorBundle(gpa: std.mem.Allocator, body: []const u8) error{ OutOfMemory, EndOfStream }!std.zig.ErrorBundle {
var r: Reader = .fixed(body);
const hdr = r.takeStruct(OutMessage.ErrorBundle, .little) catch |err| switch (err) {
error.EndOfStream => |e| return e,
error.ReadFailed => unreachable,
};
var error_bundle: std.zig.ErrorBundle = .{
var eb: std.zig.ErrorBundle = .{
.string_bytes = &.{},
.extra = &.{},
};
errdefer error_bundle.deinit(allocator);
errdefer eb.deinit(gpa);
error_bundle.string_bytes = try allocator.dupe(u8, string_bytes);
const extra = try allocator.alloc(u32, unaligned_extra.len);
@memcpy(extra, unaligned_extra);
error_bundle.extra = extra;
const extra = try gpa.alloc(u32, hdr.extra_len);
eb.extra = extra;
const string_bytes = try gpa.alloc(u8, hdr.string_bytes_len);
eb.string_bytes = string_bytes;
return error_bundle;
r.readSliceEndian(u32, extra, .little) catch |err| switch (err) {
error.EndOfStream => |e| return e,
error.ReadFailed => unreachable,
};
r.readSliceAll(string_bytes) catch |err| switch (err) {
error.EndOfStream => |e| return e,
error.ReadFailed => unreachable,
};
return eb;
}
pub const TestMetadata = struct {

View File

@ -3129,6 +3129,7 @@ test "std.zon free on error" {
test "std.zon vector" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/15330
if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .s390x) return error.SkipZigTest; // github.com/ziglang/zig/issues/25957
const gpa = std.testing.allocator;

View File

@ -5084,16 +5084,32 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal
} else operand;
const local = try f.allocLocal(null, dest_ty);
try w.writeAll("memcpy(&");
try f.writeCValue(w, local, .Other);
try w.writeAll(", &");
try f.writeCValue(w, operand_lval, .Other);
try w.writeAll(", sizeof(");
try f.renderType(
w,
if (dest_ty.abiSize(zcu) <= operand_ty.abiSize(zcu)) dest_ty else operand_ty,
);
try w.writeAll("));");
// On big-endian targets, copying ABI integers with padding bits is awkward, because the padding bits are at the low bytes of the value.
// We need to offset the source or destination pointer appropriately and copy the right number of bytes.
if (target.cpu.arch.endian() == .big and dest_ty.isAbiInt(zcu) and !operand_ty.isAbiInt(zcu)) {
// e.g. [10]u8 -> u80. We need to offset the destination so that we copy to the least significant bits of the integer.
const offset = dest_ty.abiSize(zcu) - operand_ty.abiSize(zcu);
try w.writeAll("memcpy((char *)&");
try f.writeCValue(w, local, .Other);
try w.print(" + {d}, &", .{offset});
try f.writeCValue(w, operand_lval, .Other);
try w.print(", {d});", .{operand_ty.abiSize(zcu)});
} else if (target.cpu.arch.endian() == .big and operand_ty.isAbiInt(zcu) and !dest_ty.isAbiInt(zcu)) {
// e.g. u80 -> [10]u8. We need to offset the source so that we copy from the least significant bits of the integer.
const offset = operand_ty.abiSize(zcu) - dest_ty.abiSize(zcu);
try w.writeAll("memcpy(&");
try f.writeCValue(w, local, .Other);
try w.writeAll(", (const char *)&");
try f.writeCValue(w, operand_lval, .Other);
try w.print(" + {d}, {d});", .{ offset, dest_ty.abiSize(zcu) });
} else {
try w.writeAll("memcpy(&");
try f.writeCValue(w, local, .Other);
try w.writeAll(", &");
try f.writeCValue(w, operand_lval, .Other);
try w.print(", {d});", .{@min(dest_ty.abiSize(zcu), operand_ty.abiSize(zcu))});
}
try f.object.newline();
// Ensure padding bits have the expected value.

View File

@ -3651,35 +3651,22 @@ pub const Object = struct {
.opt => {}, // pointer like optional expected
else => unreachable,
}
const bits = ty.bitSize(zcu);
const bytes: usize = @intCast(std.mem.alignForward(u64, bits, 8) / 8);
var stack = std.heap.stackFallback(32, o.gpa);
const allocator = stack.get();
const limbs = try allocator.alloc(
std.math.big.Limb,
std.mem.alignForward(usize, bytes, @sizeOf(std.math.big.Limb)) /
@sizeOf(std.math.big.Limb),
);
const bits: usize = @intCast(ty.bitSize(zcu));
const buffer = try allocator.alloc(u8, (bits + 7) / 8);
defer allocator.free(buffer);
const limbs = try allocator.alloc(std.math.big.Limb, std.math.big.int.calcTwosCompLimbCount(bits));
defer allocator.free(limbs);
@memset(limbs, 0);
val.writeToPackedMemory(ty, pt, std.mem.sliceAsBytes(limbs)[0..bytes], 0) catch unreachable;
val.writeToPackedMemory(ty, pt, buffer, 0) catch unreachable;
if (builtin.target.cpu.arch.endian() == .little) {
if (target.cpu.arch.endian() == .big)
std.mem.reverse(u8, std.mem.sliceAsBytes(limbs)[0..bytes]);
} else if (target.cpu.arch.endian() == .little) {
for (limbs) |*limb| {
limb.* = std.mem.nativeToLittle(usize, limb.*);
}
}
var big: std.math.big.int.Mutable = .init(limbs, 0);
big.readTwosComplement(buffer, bits, target.cpu.arch.endian(), .unsigned);
return o.builder.bigIntConst(llvm_int_ty, .{
.limbs = limbs,
.positive = true,
});
return o.builder.bigIntConst(llvm_int_ty, big.toConst());
}
fn lowerValue(o: *Object, pt: Zcu.PerThread, arg_val: InternPool.Index) Error!Builder.Constant {

View File

@ -1,3 +1,4 @@
const builtin = @import("builtin");
const std = @import("std");
const assert = std.debug.assert;
@ -255,6 +256,7 @@ pub fn hasNewLinkerSupport(ofmt: std.Target.ObjectFormat, backend: std.builtin.C
/// debug mode. A given target should only return true here if it is passing greater
/// than or equal to the number of behavior tests as the respective LLVM backend.
pub fn selfHostedBackendIsAsRobustAsLlvm(target: *const std.Target) bool {
if (comptime builtin.cpu.arch.endian() == .big) return false; // https://github.com/ziglang/zig/issues/25961
if (target.cpu.arch.isSpirV()) return true;
if (target.cpu.arch == .x86_64 and target.ptrBitWidth() == 64) {
if (target.os.tag == .illumos) {

View File

@ -28,6 +28,8 @@
#define zig_arm
#elif defined(__hexagon__)
#define zig_hexagon
#elif defined(__kvx__)
#define zig_kvx
#elif defined(__loongarch32)
#define zig_loongarch32
#define zig_loongarch
@ -383,7 +385,7 @@
#define zig_trap() __asm__ volatile("udf #0xfdee")
#elif defined(zig_hexagon)
#define zig_trap() __asm__ volatile("r27:26 = memd(#0xbadc0fee)")
#elif defined(zig_loongarch) || defined(zig_powerpc)
#elif defined(zig_kvx) || defined(zig_loongarch) || defined(zig_powerpc)
#define zig_trap() __asm__ volatile(".word 0x0")
#elif defined(zig_mips)
#define zig_trap() __asm__ volatile(".word 0x3d")
@ -419,7 +421,7 @@
#define zig_breakpoint() __asm__ volatile("brk #0xf000")
#elif defined(zig_hexagon)
#define zig_breakpoint() __asm__ volatile("brkpt")
#elif defined(zig_loongarch)
#elif defined(zig_kvx) || defined(zig_loongarch)
#define zig_breakpoint() __asm__ volatile("break 0x0")
#elif defined(zig_mips)
#define zig_breakpoint() __asm__ volatile("break")

Binary file not shown.

View File

@ -77,6 +77,10 @@ static void assert_or_panic(bool ok) {
# define ZIG_NO_COMPLEX
#endif
#ifdef __s390x__
# define ZIG_NO_COMPLEX
#endif
#ifdef __x86_64__
#define ZIG_NO_RAW_F16
#endif
@ -2728,7 +2732,7 @@ void run_c_tests(void) {
}
#endif
#if !defined(ZIG_PPC32) && !defined(__hexagon__)
#if !defined(ZIG_PPC32) && !defined(__hexagon__) && !defined(__s390x__)
{
struct Struct_u64_u64 s = zig_ret_struct_u64_u64();
assert_or_panic(s.a == 1);
@ -2807,7 +2811,7 @@ void run_c_tests(void) {
#if !defined __i386__ && !defined __arm__ && !defined __aarch64__ && \
!defined __powerpc__ && !defined ZIG_RISCV64 && !defined(__loongarch__) && \
!defined(__mips64__) && !defined(__hexagon__)
!defined(__mips64__) && !defined(__hexagon__) && !defined(__s390x__)
{
struct SmallStructInts s = {1, 2, 3, 4};
zig_small_struct_ints(s);
@ -2816,7 +2820,7 @@ void run_c_tests(void) {
#if !defined __arm__ && !defined __aarch64__ && \
!defined __powerpc__ && !defined ZIG_RISCV64 && !defined(__loongarch__) && \
!defined(__mips64__) && !defined(__hexagon__)
!defined(__mips64__) && !defined(__hexagon__) && !defined(__s390x__)
{
struct MedStructInts s = {1, 2, 3};
zig_med_struct_ints(s);
@ -2843,7 +2847,7 @@ void run_c_tests(void) {
#if !defined __i386__ && !defined __arm__ && \
!defined ZIG_PPC32 && !defined _ARCH_PPC64 && !defined(__loongarch__) && \
!defined(__mips64__) && !defined(__hexagon__)
!defined(__mips64__) && !defined(__hexagon__) && !defined(__s390x__)
{
struct SplitStructInts s = {1234, 100, 1337};
zig_split_struct_ints(s);
@ -2851,7 +2855,7 @@ void run_c_tests(void) {
#endif
#if !defined __arm__ && !defined ZIG_PPC32 && !defined _ARCH_PPC64 && !defined(__loongarch__) && \
!defined(__mips64__) && !defined(__hexagon__)
!defined(__mips64__) && !defined(__hexagon__) && !defined(__s390x__)
{
struct MedStructMixed s = {1234, 100.0f, 1337.0f};
zig_med_struct_mixed(s);
@ -2860,14 +2864,15 @@ void run_c_tests(void) {
#if !defined __i386__ && !defined __arm__ && \
!defined ZIG_PPC32 && !defined _ARCH_PPC64 && !defined(__loongarch__) && \
!defined(__mips64__) && !defined(__hexagon__)
!defined(__mips64__) && !defined(__hexagon__) && !defined(__s390x__)
{
struct SplitStructMixed s = {1234, 100, 1337.0f};
zig_split_struct_mixed(s);
}
#endif
#if !defined(__powerpc__) && !defined(__loongarch__) && !defined(__mips64__) && !defined(__hexagon__)
#if !defined(__powerpc__) && !defined(__loongarch__) && !defined(__mips64__) && !defined(__hexagon__) && \
!defined(__s390x__)
{
struct BigStruct s = {30, 31, 32, 33, 34};
struct BigStruct res = zig_big_struct_both(s);
@ -2880,7 +2885,7 @@ void run_c_tests(void) {
#endif
#if !defined ZIG_PPC32 && !defined _ARCH_PPC64 && !defined(__loongarch__) && !defined(__mips64__) && \
!defined(__hexagon__)
!defined(__hexagon__) && !defined(__s390x__)
{
struct Rect r1 = {1, 21, 16, 4};
struct Rect r2 = {178, 189, 21, 15};
@ -2888,7 +2893,8 @@ void run_c_tests(void) {
}
#endif
#if !defined ZIG_PPC32 && !defined(__loongarch__) && !defined(__mips64__) && !defined(__hexagon__)
#if !defined ZIG_PPC32 && !defined(__loongarch__) && !defined(__mips64__) && !defined(__hexagon__) && \
!defined(__s390x__)
{
struct FloatRect r1 = {1, 21, 16, 4};
struct FloatRect r2 = {178, 189, 21, 15};

View File

@ -12,7 +12,8 @@ const expect = std.testing.expect;
const expectEqual = std.testing.expectEqual;
const have_i128 = builtin.cpu.arch != .x86 and !builtin.cpu.arch.isArm() and
!builtin.cpu.arch.isMIPS() and !builtin.cpu.arch.isPowerPC32() and builtin.cpu.arch != .riscv32 and
builtin.cpu.arch != .hexagon;
builtin.cpu.arch != .hexagon and
builtin.cpu.arch != .s390x; // https://github.com/llvm/llvm-project/issues/168460
const have_f128 = builtin.cpu.arch.isWasm() or (builtin.cpu.arch.isX86() and !builtin.os.tag.isDarwin());
const have_f80 = builtin.cpu.arch.isX86();
@ -185,7 +186,8 @@ extern fn c_cmultd(a: ComplexDouble, b: ComplexDouble) ComplexDouble;
const complex_abi_compatible = builtin.cpu.arch != .x86 and !builtin.cpu.arch.isMIPS() and
!builtin.cpu.arch.isArm() and !builtin.cpu.arch.isPowerPC32() and !builtin.cpu.arch.isRISCV() and
builtin.cpu.arch != .hexagon;
builtin.cpu.arch != .hexagon and
builtin.cpu.arch != .s390x;
test "C ABI complex float" {
if (!complex_abi_compatible) return error.SkipZigTest;
@ -329,6 +331,7 @@ test "C ABI struct u64 u64" {
if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
const s = c_ret_struct_u64_u64();
try expect(s.a == 21);
@ -363,6 +366,7 @@ extern fn c_struct_f32(Struct_f32) void;
test "C ABI struct f32" {
if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
const s = c_ret_struct_f32();
try expect(s.a == 2.5);
@ -390,6 +394,7 @@ test "C ABI struct f64" {
if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
if (builtin.cpu.arch == .riscv32) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
const s = c_ret_struct_f64();
try expect(s.a == 2.5);
@ -421,6 +426,7 @@ test "C ABI struct {f32,f32} f32" {
if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
const s = c_ret_struct_f32f32_f32();
try expect(s.a.b == 1.0);
@ -454,6 +460,7 @@ test "C ABI struct f32 {f32,f32}" {
if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
const s = c_ret_struct_f32_f32f32();
try expect(s.a == 1.0);
@ -491,6 +498,7 @@ test "C ABI struct{u32,union{u32,struct{u32,u32}}}" {
if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
const s = c_ret_struct_u32_union_u32_u32u32();
try expect(s.a == 1);
@ -511,6 +519,7 @@ test "C ABI struct i32 i32" {
if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
if (builtin.cpu.arch == .riscv32) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
const s: Struct_i32_i32 = .{
.a = 1,
@ -543,6 +552,7 @@ test "C ABI big struct" {
if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
const s = BigStruct{
.a = 1,
@ -571,6 +581,7 @@ test "C ABI big union" {
if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
const x = BigUnion{
.a = BigStruct{
@ -606,6 +617,7 @@ test "C ABI medium struct of ints and floats" {
if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
const s = MedStructMixed{
.a = 1234,
@ -641,6 +653,7 @@ test "C ABI small struct of ints" {
if (builtin.cpu.arch == .aarch64_be) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
const s = SmallStructInts{
.a = 1,
@ -676,6 +689,7 @@ test "C ABI medium struct of ints" {
if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
const s = MedStructInts{
.x = 1,
@ -756,6 +770,7 @@ test "C ABI split struct of ints" {
if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
const s = SplitStructInt{
.a = 1234,
@ -785,6 +800,7 @@ test "C ABI split struct of ints and floats" {
if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
const s = SplitStructMixed{
.a = 1234,
@ -814,6 +830,7 @@ test "C ABI sret and byval together" {
if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
const s = BigStruct{
.a = 1,
@ -868,6 +885,7 @@ test "C ABI structs of floats as parameter" {
if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
const v3 = Vector3{
.x = 3.0,
@ -910,6 +928,7 @@ test "C ABI structs of ints as multiple parameters" {
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
const r1 = Rect{
.left = 1,
@ -949,6 +968,7 @@ test "C ABI structs of floats as multiple parameters" {
if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
const r1 = FloatRect{
.left = 1,
@ -1064,6 +1084,7 @@ test "Struct with array as padding." {
if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
c_struct_with_array(.{ .a = 1, .padding = undefined, .b = 2 });
@ -1091,6 +1112,7 @@ test "Float array like struct" {
if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
c_float_array_struct(.{
.origin = .{
@ -1119,6 +1141,7 @@ test "small simd vector" {
if (builtin.cpu.arch == .x86) return error.SkipZigTest;
if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
c_small_vec(.{ 1, 2 });
@ -1136,6 +1159,7 @@ test "medium simd vector" {
if (builtin.zig_backend == .stage2_x86_64 and !comptime builtin.cpu.has(.x86, .avx)) return error.SkipZigTest;
if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
c_medium_vec(.{ 1, 2, 3, 4 });
@ -1184,6 +1208,7 @@ extern fn c_ret_vector_4_float() Vector4Float;
test "float simd vectors" {
if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
{
c_vector_2_float(.{ 1.0, 2.0 });
@ -5469,6 +5494,7 @@ test "C ABI pointer sized float struct" {
if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
c_ptr_size_float_struct(.{ .x = 1, .y = 2 });
@ -5493,6 +5519,7 @@ test "DC: Zig passes to C" {
if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
try expectOk(c_assert_DC(.{ .v1 = -0.25, .v2 = 15 }));
}
test "DC: Zig returns to C" {
@ -5500,6 +5527,7 @@ test "DC: Zig returns to C" {
if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
try expectOk(c_assert_ret_DC());
}
test "DC: C passes to Zig" {
@ -5508,6 +5536,7 @@ test "DC: C passes to Zig" {
if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
try expectOk(c_send_DC());
}
test "DC: C returns to Zig" {
@ -5515,6 +5544,7 @@ test "DC: C returns to Zig" {
if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
try expectEqual(DC{ .v1 = -0.25, .v2 = 15 }, c_ret_DC());
}
@ -5542,12 +5572,14 @@ test "CFF: Zig passes to C" {
if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
try expectOk(c_assert_CFF(.{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 }));
}
test "CFF: Zig returns to C" {
if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
try expectOk(c_assert_ret_CFF());
}
test "CFF: C passes to Zig" {
@ -5558,6 +5590,7 @@ test "CFF: C passes to Zig" {
if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
try expectOk(c_send_CFF());
}
@ -5567,6 +5600,7 @@ test "CFF: C returns to Zig" {
if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
try expectEqual(CFF{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 }, c_ret_CFF());
}
pub extern fn c_assert_CFF(lv: CFF) c_int;
@ -5593,12 +5627,14 @@ test "PD: Zig passes to C" {
if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
try expectOk(c_assert_PD(.{ .v1 = null, .v2 = 0.5 }));
}
test "PD: Zig returns to C" {
if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
try expectOk(c_assert_ret_PD());
}
test "PD: C passes to Zig" {
@ -5606,12 +5642,14 @@ test "PD: C passes to Zig" {
if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
try expectOk(c_send_PD());
}
test "PD: C returns to Zig" {
if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest;
if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
try expectEqual(PD{ .v1 = null, .v2 = 0.5 }, c_ret_PD());
}
pub extern fn c_assert_PD(lv: PD) c_int;
@ -5645,6 +5683,7 @@ extern fn c_modify_by_ref_param(ByRef) ByRef;
test "C function modifies by ref param" {
if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
const res = c_modify_by_ref_param(.{ .val = 1, .arr = undefined });
try expect(res.val == 42);
@ -5669,6 +5708,7 @@ test "C function that takes byval struct called via function pointer" {
if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
var fn_ptr = &c_func_ptr_byval;
_ = &fn_ptr;
@ -5701,6 +5741,7 @@ test "f16 struct" {
if (builtin.target.cpu.arch.isMIPS64()) return error.SkipZigTest;
if (builtin.target.cpu.arch.isPowerPC32()) return error.SkipZigTest;
if (builtin.cpu.arch.isArm() and builtin.mode != .Debug) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
const a = c_f16_struct(.{ .a = 12 });
try expect(a.a == 34);
@ -5810,6 +5851,7 @@ test "Stdcall ABI structs" {
if (builtin.cpu.arch == .aarch64_be) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
const res = stdcall_coord2(
.{ .x = 0x1111, .y = 0x2222 },
@ -5825,6 +5867,7 @@ test "Stdcall ABI big union" {
if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
const x = BigUnion{
.a = BigStruct{
@ -5899,6 +5942,7 @@ test "byval tail callsite attribute" {
if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest;
if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest;
if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
if (builtin.cpu.arch == .s390x) return error.SkipZigTest;
// Originally reported at https://github.com/ziglang/zig/issues/16290
// the bug was that the extern function had the byval attribute, but

View File

@ -437,6 +437,7 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext) void {
.{ .aarch64, .linux },
.{ .loongarch64, .linux },
.{ .riscv64, .linux },
.{ .s390x, .linux },
.{ .x86_64, .windows },
.{ .x86, .windows },
.{ .x86_64, .macos },

View File

@ -5,6 +5,9 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {
// https://github.com/ziglang/zig/issues/25323
if (builtin.os.tag == .freebsd) return elf_step;
// https://github.com/ziglang/zig/issues/25961
if (comptime builtin.cpu.arch.endian() == .big) return elf_step;
const default_target = b.resolveTargetQuery(.{
.cpu_arch = .x86_64, // TODO relax this once ELF linker is able to handle other archs
.os_tag = .linux,

View File

@ -6,6 +6,9 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {
// https://github.com/ziglang/zig/issues/25323
if (builtin.os.tag == .freebsd) return macho_step;
// https://github.com/ziglang/zig/issues/25961
if (comptime builtin.cpu.arch.endian() == .big) return macho_step;
const x86_64_target = b.resolveTargetQuery(.{
.cpu_arch = .x86_64,
.os_tag = .macos,

View File

@ -39,6 +39,7 @@ pub fn addCase(self: *ErrorTrace, case: Case) void {
}
fn shouldTestNonLlvm(target: *const std.Target) bool {
if (comptime builtin.cpu.arch.endian() == .big) return false; // https://github.com/ziglang/zig/issues/25961
return switch (target.cpu.arch) {
.x86_64 => switch (target.ofmt) {
.elf => !target.os.tag.isBSD() and target.os.tag != .illumos,

View File

@ -44,12 +44,15 @@ fn addCaseTarget(
target: *const std.Build.ResolvedTarget,
triple: ?[]const u8,
) void {
const both_backends = switch (target.result.cpu.arch) {
.x86_64 => switch (target.result.ofmt) {
.elf => !target.result.os.tag.isBSD() and target.result.os.tag != .illumos,
const both_backends = b: {
if (comptime builtin.cpu.arch.endian() == .big) break :b false; // https://github.com/ziglang/zig/issues/25961
break :b switch (target.result.cpu.arch) {
.x86_64 => switch (target.result.ofmt) {
.elf => !target.result.os.tag.isBSD() and target.result.os.tag != .illumos,
else => false,
},
else => false,
},
else => false,
};
};
const both_pie = switch (target.result.os.tag) {
.fuchsia, .openbsd => false,

View File

@ -25,30 +25,5 @@ int main (int argc, char *argv[])
if (!ok) abort();
// Test some basic arithmetic from compiler-rt
{
double complex z = 0.0 + I * 4.0;
double complex w = 0.0 + I * 16.0;
double complex product = z * w;
double complex quotient = z / w;
if (!(creal(product) == -64.0)) abort();
if (!(cimag(product) == 0.0)) abort();
if (!(creal(quotient) == 0.25)) abort();
if (!(cimag(quotient) == 0.0)) abort();
}
{
float complex z = 4.0 + I * 4.0;
float complex w = 2.0 - I * 2.0;
float complex product = z * w;
float complex quotient = z / w;
if (!(creal(product) == 16.0)) abort();
if (!(cimag(product) == 0.0)) abort();
if (!(creal(quotient) == 0.0)) abort();
if (!(cimag(quotient) == 2.0)) abort();
}
return EXIT_SUCCESS;
}

View File

@ -141,12 +141,14 @@ pub fn build(b: *std.Build) void {
check.checkInDynamicSymtab();
check.checkExact("0 0 UND FUNC GLOBAL DEFAULT powf");
// An atexit local symbol is defined, and depends on undefined dynamic
// __cxa_atexit.
check.checkInSymtab();
check.checkContains("FUNC LOCAL HIDDEN atexit");
check.checkInDynamicSymtab();
check.checkExact("0 0 UND FUNC GLOBAL DEFAULT __cxa_atexit");
if (target.result.cpu.arch != .s390x) {
// An atexit local symbol is defined, and depends on undefined dynamic
// __cxa_atexit.
check.checkInSymtab();
check.checkContains("FUNC LOCAL HIDDEN atexit");
check.checkInDynamicSymtab();
check.checkExact("0 0 UND FUNC GLOBAL DEFAULT __cxa_atexit");
}
test_step.dependOn(&check.step);
}
@ -250,12 +252,14 @@ pub fn build(b: *std.Build) void {
check.checkInDynamicSymtab();
check.checkExact("0 0 UND FUNC GLOBAL DEFAULT exit");
// An atexit local symbol is defined, and depends on undefined dynamic
// __cxa_atexit.
check.checkInSymtab();
check.checkContains("FUNC LOCAL HIDDEN atexit");
check.checkInDynamicSymtab();
check.checkExact("0 0 UND FUNC GLOBAL DEFAULT __cxa_atexit");
if (target.result.cpu.arch != .s390x) {
// An atexit local symbol is defined, and depends on undefined dynamic
// __cxa_atexit.
check.checkInSymtab();
check.checkContains("FUNC LOCAL HIDDEN atexit");
check.checkInDynamicSymtab();
check.checkExact("0 0 UND FUNC GLOBAL DEFAULT __cxa_atexit");
}
test_step.dependOn(&check.step);
}

View File

@ -1756,14 +1756,13 @@ const c_abi_targets = blk: {
},
},
// Clang explodes when parsing `cfuncs.c`.
// .{
// .target = .{
// .cpu_arch = .s390x,
// .os_tag = .linux,
// .abi = .musl,
// },
// },
.{
.target = .{
.cpu_arch = .s390x,
.os_tag = .linux,
.abi = .musl,
},
},
.{
.target = std.Target.Query.parse(.{
@ -2500,6 +2499,7 @@ fn addOneModuleTest(
}
pub fn wouldUseLlvm(use_llvm: ?bool, query: std.Target.Query, optimize_mode: OptimizeMode) bool {
if (comptime builtin.cpu.arch.endian() == .big) return true; // https://github.com/ziglang/zig/issues/25961
if (use_llvm) |x| return x;
if (query.ofmt == .c) return false;
switch (optimize_mode) {

View File

@ -290,9 +290,8 @@ const Eval = struct {
return;
},
.emit_digest => {
const EbpHdr = std.zig.Server.Message.EmitDigest;
const ebp_hdr = @as(*align(1) const EbpHdr, @ptrCast(body));
_ = ebp_hdr;
var r: std.Io.Reader = .fixed(body);
_ = r.takeStruct(std.zig.Server.Message.EmitDigest, .little) catch unreachable;
if (stderr.bufferedLen() > 0) {
const stderr_data = try poller.toOwnedSlice(.stderr);
if (eval.allow_stderr) {
@ -307,7 +306,7 @@ const Eval = struct {
// This message indicates the end of the update.
}
const digest = body[@sizeOf(EbpHdr)..][0..Cache.bin_digest_len];
const digest = r.takeArray(Cache.bin_digest_len) catch unreachable;
const result_dir = ".local-cache" ++ std.fs.path.sep_str ++ "o" ++ std.fs.path.sep_str ++ Cache.binToHex(digest.*);
const bin_name = try std.zig.EmitArtifact.bin.cacheName(arena, .{
@ -519,7 +518,10 @@ const Eval = struct {
.tag = .update,
.bytes_len = 0,
};
try eval.child.stdin.?.writeAll(std.mem.asBytes(&header));
var w = eval.child.stdin.?.writer(&.{});
w.interface.writeStruct(header, .little) catch |err| switch (err) {
error.WriteFailed => return w.err.?,
};
}
fn end(eval: *Eval, poller: *Poller) !void {
@ -836,9 +838,12 @@ fn requestExit(child: *std.process.Child, eval: *Eval) void {
.tag = .exit,
.bytes_len = 0,
};
child.stdin.?.writeAll(std.mem.asBytes(&header)) catch |err| switch (err) {
error.BrokenPipe => {},
else => eval.fatal("failed to send exit: {s}", .{@errorName(err)}),
var w = eval.child.stdin.?.writer(&.{});
w.interface.writeStruct(header, .little) catch |err| switch (err) {
error.WriteFailed => switch (w.err.?) {
error.BrokenPipe => {},
else => |e| eval.fatal("failed to send exit: {s}", .{@errorName(e)}),
},
};
// Send EOF to stdin.