diff --git a/.forgejo/workflows/ci.yaml b/.forgejo/workflows/ci.yaml index 7a6ed634f7e9af5fb36727df0077e52e32430a22..1c2ac7d24281de9b72fa0d357b4ab1e0b4a747e0 100644 --- a/.forgejo/workflows/ci.yaml +++ b/.forgejo/workflows/ci.yaml @@ -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: diff --git a/ci/s390x-linux-debug.sh b/ci/s390x-linux-debug.sh new file mode 100755 index 0000000000000000000000000000000000000000..ce5057634f6b9a630354e1c7d20becb767f23232 --- /dev/null +++ b/ci/s390x-linux-debug.sh @@ -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 diff --git a/ci/s390x-linux-release.sh b/ci/s390x-linux-release.sh new file mode 100755 index 0000000000000000000000000000000000000000..e474b89ffe12a10ef7217d2452446ed353b6ec4e --- /dev/null +++ b/ci/s390x-linux-release.sh @@ -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 diff --git a/doc/langref/runtime_shrExact_overflow.zig b/doc/langref/runtime_shrExact_overflow.zig index 98da0dde1191d434baa623c998bbeced7a7cb518..32cfc33ca2decbe246369effda9308b029d99d07 100644 --- a/doc/langref/runtime_shrExact_overflow.zig +++ b/doc/langref/runtime_shrExact_overflow.zig @@ -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 diff --git a/doc/langref/test_defining_variadic_function.zig b/doc/langref/test_defining_variadic_function.zig index 732531197199f568e870b5314b0a088e199c52c5..40ec7029b21813fa7dd109c64cb8fdedd2ee4e89 100644 --- a/doc/langref/test_defining_variadic_function.zig +++ b/doc/langref/test_defining_variadic_function.zig @@ -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))); diff --git a/lib/compiler/aro/aro/Compilation.zig b/lib/compiler/aro/aro/Compilation.zig index 0ec314ba83bbbb51d1c98679571dc7b9a6e1b038..222bede46cc2f6a62031a4c0da32fc184081d357 100644 --- a/lib/compiler/aro/aro/Compilation.zig +++ b/lib/compiler/aro/aro/Compilation.zig @@ -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 => {}, } diff --git a/lib/compiler/std-docs.zig b/lib/compiler/std-docs.zig index f560e05ccaa319fe7a06fd4a2ebfce77201d799a..bad2de0ee7b264a805aa087f4bf6f41c06162419 100644 --- a/lib/compiler/std-docs.zig +++ b/lib/compiler/std-docs.zig @@ -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 { diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig index f4387a2480c5f7c26aa64838119daba3b325eca7..8ee686e44e2cc663fc7e7c0a9075ef5455a421e0 100644 --- a/lib/std/Build/Step.zig +++ b/lib/std/Build/Step.zig @@ -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( diff --git a/lib/std/Build/Step/CheckObject.zig b/lib/std/Build/Step/CheckObject.zig index 56be318a84b209fea0712f6cd32a4421633bc01a..d9935d4f3df355a8414b6e3201dae68791bb2335 100644 --- a/lib/std/Build/Step/CheckObject.zig +++ b/lib/std/Build/Step/CheckObject.zig @@ -1857,15 +1857,26 @@ const ElfDumper = struct { fn parseAndDumpObject(step: *Step, check: Check, bytes: []const u8) ![]const u8 { const gpa = step.owner.allocator; + + // `std.elf.Header` takes care of endianness issues for us. var reader: std.Io.Reader = .fixed(bytes); + const hdr = try elf.Header.read(&reader); - const hdr = try reader.takeStruct(elf.Elf64_Ehdr, .little); - if (!mem.eql(u8, hdr.e_ident[0..4], "\x7fELF")) { - return error.InvalidMagicNumber; + 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; diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index 4d1852e2e1fdc2fab588dbeceed9916c2cc3f51c..52a690ef94a7a29f242967871017f09febbe6ce0 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -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 { diff --git a/lib/std/os/linux/IoUring.zig b/lib/std/os/linux/IoUring.zig index 54b4a5bd386d93d73831148f61bf52ac70937719..f5f68a0ebecfd4872423d99e853f80d440264424 100644 --- a/lib/std/os/linux/IoUring.zig +++ b/lib/std/os/linux/IoUring.zig @@ -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, diff --git a/lib/std/zig/Server.zig b/lib/std/zig/Server.zig index ffc596e8dc89d6846dd396b306e2cdecde74407a..a1166f7aa7518c01edce089dfffa93dfc4a1e899 100644 --- a/lib/std/zig/Server.zig +++ b/lib/std/zig/Server.zig @@ -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 { diff --git a/lib/std/zon/parse.zig b/lib/std/zon/parse.zig index a3d0b69251631f9e77d0d488db879a9343628491..5c1621adcf78cc8eea503a3c990167cebafc455b 100644 --- a/lib/std/zon/parse.zig +++ b/lib/std/zon/parse.zig @@ -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; diff --git a/src/codegen/c.zig b/src/codegen/c.zig index c4b909d4a93aee9b153b557efc2fd20f48916f34..91614bf2df197aded488b49caca3ca8cd4227e63 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -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. diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 450e446d8a31f15a1c06f91c10f87999d73284d3..8d51fea0c3aaa2869ba69a01eb45a28481e5bcc9 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -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 { diff --git a/src/target.zig b/src/target.zig index a721b0bf65654fc793dd26ae94f7687baa7c9f1f..7e50589ab87d61e3d4c0b0257f5971f727f16e8a 100644 --- a/src/target.zig +++ b/src/target.zig @@ -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) { diff --git a/stage1/zig.h b/stage1/zig.h index baae5926101bfa6d5a7713a560652402463dc39a..7a7a22b17ba14ff003c3b64964f61a88bafb76f7 100644 --- a/stage1/zig.h +++ b/stage1/zig.h @@ -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") diff --git a/stage1/zig1.wasm b/stage1/zig1.wasm index 1660c5a9266d1ffca3acc88ae559218d3b2ad078..40c744b1fa0be38a70b77a3f94a13e422e744a83 100644 Binary files a/stage1/zig1.wasm and b/stage1/zig1.wasm differ diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c index c191dd5e0ef8c290d29c6c373448db4034538786..940ddac9d21eae4b15063a2a9512c089b5770b72 100644 --- a/test/c_abi/cfuncs.c +++ b/test/c_abi/cfuncs.c @@ -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}; diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig index 8316847743e5ebd382b5c4bb4604062a66e79bc7..10cdab85b748395e17aed89208f169aa75355df9 100644 --- a/test/c_abi/main.zig +++ b/test/c_abi/main.zig @@ -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 diff --git a/test/error_traces.zig b/test/error_traces.zig index da40c1eaa6b5ba0b55672afaa287e2b49fce0589..62daf1c94fa04e301a9b65daf9e67ee9c379df98 100644 --- a/test/error_traces.zig +++ b/test/error_traces.zig @@ -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 }, diff --git a/test/link/elf.zig b/test/link/elf.zig index 7e4897ae2f976dc6eb35ca16b2daeeb2ac4643b7..824fc76e9279ae8182fd3818efe33cfa4c780f94 100644 --- a/test/link/elf.zig +++ b/test/link/elf.zig @@ -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, diff --git a/test/link/macho.zig b/test/link/macho.zig index fdc585b29989186e71cf888a537e5e121b18265d..4fc0cad0eedb0feb667fc2e25a26b73177c5aab8 100644 --- a/test/link/macho.zig +++ b/test/link/macho.zig @@ -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, diff --git a/test/src/ErrorTrace.zig b/test/src/ErrorTrace.zig index bd3febef0e7a2047c4419df2bff0f375c27e0382..f6f80f8b138d2f7a663b4fe1d5d8d58bc8ef43de 100644 --- a/test/src/ErrorTrace.zig +++ b/test/src/ErrorTrace.zig @@ -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, diff --git a/test/src/StackTrace.zig b/test/src/StackTrace.zig index 8b2d514010fc98df8e128bc3af7981056255298a..57e29dd8000ab3f892ab354ee2ea2dbed251f943 100644 --- a/test/src/StackTrace.zig +++ b/test/src/StackTrace.zig @@ -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, diff --git a/test/standalone/c_compiler/test.c b/test/standalone/c_compiler/test.c index 3beb1aa2fffba81cad8160ec67e414ab9ab2fa1a..ad3f48ccf9c1485ae8f8fb99490dd97457a219b5 100644 --- a/test/standalone/c_compiler/test.c +++ b/test/standalone/c_compiler/test.c @@ -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; } diff --git a/test/standalone/glibc_compat/build.zig b/test/standalone/glibc_compat/build.zig index 6c2c924cae0a40f93a7ad81f4fa2bbbc54539186..277bbb035d754cfd95e5e1d2c0b31f4debff252e 100644 --- a/test/standalone/glibc_compat/build.zig +++ b/test/standalone/glibc_compat/build.zig @@ -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); } diff --git a/test/tests.zig b/test/tests.zig index 1f9db5f2ddbe5419975e86526879e386a0449f47..4ea42c2eb563cb37e10a157a5d56f36b883c494c 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -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) { diff --git a/tools/incr-check.zig b/tools/incr-check.zig index 6d3a38760f0051af00f413a0ca67bce5e5232e58..7f3bf75686ebbcfde5421c8947fe5170c2a941ea 100644 --- a/tools/incr-check.zig +++ b/tools/incr-check.zig @@ -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.