Skip to content

Commit 43371cf

Browse files
authored
Merge pull request #25965 from alexrp/s390x
`s390x-linux` and general big-endian stuff
2 parents 806470b + abd05b3 commit 43371cf

File tree

29 files changed

+455
-182
lines changed

29 files changed

+455
-182
lines changed

.forgejo/workflows/ci.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,26 @@ jobs:
7373
- name: Build and Test
7474
run: sh ci/riscv64-linux-release.sh
7575
timeout-minutes: 420
76+
s390x-linux-debug:
77+
runs-on: [self-hosted, s390x-linux]
78+
steps:
79+
- name: Checkout
80+
uses: actions/checkout@v4
81+
with:
82+
fetch-depth: 0
83+
- name: Build and Test
84+
run: sh ci/s390x-linux-debug.sh
85+
timeout-minutes: 240
86+
s390x-linux-release:
87+
runs-on: [self-hosted, s390x-linux]
88+
steps:
89+
- name: Checkout
90+
uses: actions/checkout@v4
91+
with:
92+
fetch-depth: 0
93+
- name: Build and Test
94+
run: sh ci/s390x-linux-release.sh
95+
timeout-minutes: 180
7696
x86_64-freebsd-debug:
7797
runs-on: [self-hosted, x86_64-freebsd]
7898
steps:

ci/s390x-linux-debug.sh

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#!/bin/sh
2+
3+
# Requires cmake ninja-build
4+
5+
set -x
6+
set -e
7+
8+
TARGET="s390x-linux-musl"
9+
MCPU="z15"
10+
CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.16.0-dev.1354+94e98bfe8"
11+
PREFIX="$HOME/deps/$CACHE_BASENAME"
12+
ZIG="$PREFIX/bin/zig"
13+
14+
# Override the cache directories because they won't actually help other CI runs
15+
# which will be testing alternate versions of zig, and ultimately would just
16+
# fill up space on the hard drive for no reason.
17+
export ZIG_GLOBAL_CACHE_DIR="$PWD/zig-global-cache"
18+
export ZIG_LOCAL_CACHE_DIR="$PWD/zig-local-cache"
19+
20+
mkdir build-debug
21+
cd build-debug
22+
23+
export CC="$ZIG cc -target $TARGET -mcpu=$MCPU"
24+
export CXX="$ZIG c++ -target $TARGET -mcpu=$MCPU"
25+
26+
cmake .. \
27+
-DCMAKE_INSTALL_PREFIX="stage3-debug" \
28+
-DCMAKE_PREFIX_PATH="$PREFIX" \
29+
-DCMAKE_BUILD_TYPE=Debug \
30+
-DZIG_TARGET_TRIPLE="$TARGET" \
31+
-DZIG_TARGET_MCPU="$MCPU" \
32+
-DZIG_STATIC=ON \
33+
-DZIG_NO_LIB=ON \
34+
-GNinja \
35+
-DCMAKE_C_LINKER_DEPFILE_SUPPORTED=FALSE \
36+
-DCMAKE_CXX_LINKER_DEPFILE_SUPPORTED=FALSE
37+
# https://github.com/ziglang/zig/issues/22213
38+
39+
# Now cmake will use zig as the C/C++ compiler. We reset the environment variables
40+
# so that installation and testing do not get affected by them.
41+
unset CC
42+
unset CXX
43+
44+
ninja install
45+
46+
# No -fqemu and -fwasmtime here as they're covered by the x86_64-linux scripts.
47+
stage3-debug/bin/zig build test docs \
48+
--maxrss 30064771072 \
49+
-Dstatic-llvm \
50+
-Dskip-non-native \
51+
-Dtarget=native-native-musl \
52+
--search-prefix "$PREFIX" \
53+
--zig-lib-dir "$PWD/../lib" \
54+
--test-timeout 4m
55+
56+
stage3-debug/bin/zig build \
57+
--prefix stage4-debug \
58+
-Denable-llvm \
59+
-Dno-lib \
60+
-Dtarget=$TARGET \
61+
-Dcpu=$MCPU \
62+
-Duse-zig-libcxx \
63+
-Dversion-string="$(stage3-debug/bin/zig version)"
64+
65+
stage4-debug/bin/zig test ../test/behavior.zig

ci/s390x-linux-release.sh

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#!/bin/sh
2+
3+
# Requires cmake ninja-build
4+
5+
set -x
6+
set -e
7+
8+
TARGET="s390x-linux-musl"
9+
MCPU="z15"
10+
CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.16.0-dev.1354+94e98bfe8"
11+
PREFIX="$HOME/deps/$CACHE_BASENAME"
12+
ZIG="$PREFIX/bin/zig"
13+
14+
# Override the cache directories because they won't actually help other CI runs
15+
# which will be testing alternate versions of zig, and ultimately would just
16+
# fill up space on the hard drive for no reason.
17+
export ZIG_GLOBAL_CACHE_DIR="$PWD/zig-global-cache"
18+
export ZIG_LOCAL_CACHE_DIR="$PWD/zig-local-cache"
19+
20+
mkdir build-release
21+
cd build-release
22+
23+
export CC="$ZIG cc -target $TARGET -mcpu=$MCPU"
24+
export CXX="$ZIG c++ -target $TARGET -mcpu=$MCPU"
25+
26+
cmake .. \
27+
-DCMAKE_INSTALL_PREFIX="stage3-release" \
28+
-DCMAKE_PREFIX_PATH="$PREFIX" \
29+
-DCMAKE_BUILD_TYPE=Release \
30+
-DZIG_TARGET_TRIPLE="$TARGET" \
31+
-DZIG_TARGET_MCPU="$MCPU" \
32+
-DZIG_STATIC=ON \
33+
-DZIG_NO_LIB=ON \
34+
-GNinja \
35+
-DCMAKE_C_LINKER_DEPFILE_SUPPORTED=FALSE \
36+
-DCMAKE_CXX_LINKER_DEPFILE_SUPPORTED=FALSE
37+
# https://github.com/ziglang/zig/issues/22213
38+
39+
# Now cmake will use zig as the C/C++ compiler. We reset the environment variables
40+
# so that installation and testing do not get affected by them.
41+
unset CC
42+
unset CXX
43+
44+
ninja install
45+
46+
# No -fqemu and -fwasmtime here as they're covered by the x86_64-linux scripts.
47+
stage3-release/bin/zig build test docs \
48+
--maxrss 30064771072 \
49+
-Dstatic-llvm \
50+
-Dskip-non-native \
51+
-Dtarget=native-native-musl \
52+
--search-prefix "$PREFIX" \
53+
--zig-lib-dir "$PWD/../lib" \
54+
--test-timeout 4m
55+
56+
# Ensure that stage3 and stage4 are byte-for-byte identical.
57+
stage3-release/bin/zig build \
58+
--prefix stage4-release \
59+
-Denable-llvm \
60+
-Dno-lib \
61+
-Doptimize=ReleaseFast \
62+
-Dstrip \
63+
-Dtarget=$TARGET \
64+
-Dcpu=$MCPU \
65+
-Duse-zig-libcxx \
66+
-Dversion-string="$(stage3-release/bin/zig version)"
67+
68+
# diff returns an error code if the files differ.
69+
echo "If the following command fails, it means nondeterminism has been"
70+
echo "introduced, making stage3 and stage4 no longer byte-for-byte identical."
71+
diff stage3-release/bin/zig stage4-release/bin/zig

doc/langref/runtime_shrExact_overflow.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ pub fn main() void {
77
const y = @shrExact(x, 2);
88
std.debug.print("value: {}\n", .{y});
99

10-
if ((builtin.cpu.arch.isRISCV() or builtin.cpu.arch.isLoongArch()) and builtin.zig_backend == .stage2_llvm) @panic("https://github.com/ziglang/zig/issues/24304");
10+
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");
1111
}
1212

1313
// exe=fail

doc/langref/test_defining_variadic_function.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ test "defining a variadic function" {
2222
// https://github.com/ziglang/zig/issues/16961
2323
return error.SkipZigTest;
2424
}
25+
if (builtin.cpu.arch == .s390x) {
26+
// https://github.com/ziglang/zig/issues/21350#issuecomment-3543006475
27+
return error.SkipZigTest;
28+
}
2529

2630
try std.testing.expectEqual(@as(c_int, 0), add(0));
2731
try std.testing.expectEqual(@as(c_int, 1), add(1, @as(c_int, 1)));

lib/compiler/aro/aro/Compilation.zig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,11 @@ fn generateSystemDefines(comp: *Compilation, w: *Io.Writer) !void {
774774
try w.print("#define __wasm_{s}__ 1\n", .{feature.name});
775775
}
776776
},
777+
.s390x => {
778+
try define(w, "__s390__");
779+
try define(w, "__s390x__");
780+
try define(w, "__zarch__");
781+
},
777782
else => {},
778783
}
779784

lib/compiler/std-docs.zig

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -348,12 +348,12 @@ fn buildWasmBinary(
348348
result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body);
349349
},
350350
.emit_digest => {
351-
const EmitDigest = std.zig.Server.Message.EmitDigest;
352-
const emit_digest = @as(*align(1) const EmitDigest, @ptrCast(body));
351+
var r: std.Io.Reader = .fixed(body);
352+
const emit_digest = r.takeStruct(std.zig.Server.Message.EmitDigest, .little) catch unreachable;
353353
if (!emit_digest.flags.cache_hit) {
354354
std.log.info("source changes detected; rebuilt wasm component", .{});
355355
}
356-
const digest = body[@sizeOf(EmitDigest)..][0..Cache.bin_digest_len];
356+
const digest = r.takeArray(Cache.bin_digest_len) catch unreachable;
357357
result = .{
358358
.root_dir = Cache.Directory.cwd(),
359359
.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 {
415415
.tag = tag,
416416
.bytes_len = 0,
417417
};
418-
try file.writeAll(std.mem.asBytes(&header));
418+
var w = file.writer(&.{});
419+
w.interface.writeStruct(header, .little) catch |err| switch (err) {
420+
error.WriteFailed => return w.err.?,
421+
};
419422
}
420423

421424
fn openBrowserTab(gpa: Allocator, url: []const u8) !void {

lib/std/Build/Step.zig

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,10 @@ fn sendMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag) !void {
680680
.tag = tag,
681681
.bytes_len = 0,
682682
};
683-
try file.writeAll(std.mem.asBytes(&header));
683+
var w = file.writer(&.{});
684+
w.interface.writeStruct(header, .little) catch |err| switch (err) {
685+
error.WriteFailed => return w.err.?,
686+
};
684687
}
685688

686689
pub fn handleVerbose(

lib/std/Build/Step/CheckObject.zig

Lines changed: 53 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1857,15 +1857,26 @@ const ElfDumper = struct {
18571857

18581858
fn parseAndDumpObject(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
18591859
const gpa = step.owner.allocator;
1860-
var reader: std.Io.Reader = .fixed(bytes);
18611860

1862-
const hdr = try reader.takeStruct(elf.Elf64_Ehdr, .little);
1863-
if (!mem.eql(u8, hdr.e_ident[0..4], "\x7fELF")) {
1864-
return error.InvalidMagicNumber;
1861+
// `std.elf.Header` takes care of endianness issues for us.
1862+
var reader: std.Io.Reader = .fixed(bytes);
1863+
const hdr = try elf.Header.read(&reader);
1864+
1865+
var shdrs = try gpa.alloc(elf.Elf64_Shdr, hdr.shnum);
1866+
defer gpa.free(shdrs);
1867+
{
1868+
var shdr_it = hdr.iterateSectionHeadersBuffer(bytes);
1869+
var shdr_i: usize = 0;
1870+
while (try shdr_it.next()) |shdr| : (shdr_i += 1) shdrs[shdr_i] = shdr;
18651871
}
18661872

1867-
const shdrs = @as([*]align(1) const elf.Elf64_Shdr, @ptrCast(bytes.ptr + hdr.e_shoff))[0..hdr.e_shnum];
1868-
const phdrs = @as([*]align(1) const elf.Elf64_Phdr, @ptrCast(bytes.ptr + hdr.e_phoff))[0..hdr.e_phnum];
1873+
var phdrs = try gpa.alloc(elf.Elf64_Phdr, hdr.shnum);
1874+
defer gpa.free(phdrs);
1875+
{
1876+
var phdr_it = hdr.iterateProgramHeadersBuffer(bytes);
1877+
var phdr_i: usize = 0;
1878+
while (try phdr_it.next()) |phdr| : (phdr_i += 1) phdrs[phdr_i] = phdr;
1879+
}
18691880

18701881
var ctx = ObjectContext{
18711882
.gpa = gpa,
@@ -1875,13 +1886,21 @@ const ElfDumper = struct {
18751886
.phdrs = phdrs,
18761887
.shstrtab = undefined,
18771888
};
1878-
ctx.shstrtab = ctx.getSectionContents(ctx.hdr.e_shstrndx);
1889+
ctx.shstrtab = ctx.getSectionContents(ctx.hdr.shstrndx);
1890+
1891+
defer gpa.free(ctx.symtab.symbols);
1892+
defer gpa.free(ctx.dysymtab.symbols);
1893+
defer gpa.free(ctx.dyns);
18791894

18801895
for (ctx.shdrs, 0..) |shdr, i| switch (shdr.sh_type) {
18811896
elf.SHT_SYMTAB, elf.SHT_DYNSYM => {
18821897
const raw = ctx.getSectionContents(i);
18831898
const nsyms = @divExact(raw.len, @sizeOf(elf.Elf64_Sym));
1884-
const symbols = @as([*]align(1) const elf.Elf64_Sym, @ptrCast(raw.ptr))[0..nsyms];
1899+
const symbols = try gpa.alloc(elf.Elf64_Sym, nsyms);
1900+
1901+
var r: std.Io.Reader = .fixed(raw);
1902+
for (0..nsyms) |si| symbols[si] = r.takeStruct(elf.Elf64_Sym, ctx.hdr.endian) catch unreachable;
1903+
18851904
const strings = ctx.getSectionContents(shdr.sh_link);
18861905

18871906
switch (shdr.sh_type) {
@@ -1900,6 +1919,17 @@ const ElfDumper = struct {
19001919
else => unreachable,
19011920
}
19021921
},
1922+
elf.SHT_DYNAMIC => {
1923+
const raw = ctx.getSectionContents(i);
1924+
const ndyns = @divExact(raw.len, @sizeOf(elf.Elf64_Dyn));
1925+
const dyns = try gpa.alloc(elf.Elf64_Dyn, ndyns);
1926+
1927+
var r: std.Io.Reader = .fixed(raw);
1928+
for (0..ndyns) |si| dyns[si] = r.takeStruct(elf.Elf64_Dyn, ctx.hdr.endian) catch unreachable;
1929+
1930+
ctx.dyns = dyns;
1931+
ctx.dyns_strings = ctx.getSectionContents(shdr.sh_link);
1932+
},
19031933

19041934
else => {},
19051935
};
@@ -1923,9 +1953,9 @@ const ElfDumper = struct {
19231953
try ctx.dumpSymtab(.dysymtab, writer);
19241954
} else return step.fail("no dynamic symbol table found", .{}),
19251955

1926-
.dynamic_section => if (ctx.getSectionByName(".dynamic")) |shndx| {
1927-
try ctx.dumpDynamicSection(shndx, writer);
1928-
} else return step.fail("no .dynamic section found", .{}),
1956+
.dynamic_section => if (ctx.dyns.len > 0) {
1957+
try ctx.dumpDynamicSection(writer);
1958+
} else return step.fail("no dynamic section found", .{}),
19291959

19301960
.dump_section => {
19311961
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 {
19421972
const ObjectContext = struct {
19431973
gpa: Allocator,
19441974
data: []const u8,
1945-
hdr: elf.Elf64_Ehdr,
1946-
shdrs: []align(1) const elf.Elf64_Shdr,
1947-
phdrs: []align(1) const elf.Elf64_Phdr,
1975+
hdr: elf.Header,
1976+
shdrs: []const elf.Elf64_Shdr,
1977+
phdrs: []const elf.Elf64_Phdr,
19481978
shstrtab: []const u8,
19491979
symtab: Symtab = .{},
19501980
dysymtab: Symtab = .{},
1981+
dyns: []const elf.Elf64_Dyn = &.{},
1982+
dyns_strings: []const u8 = &.{},
19511983

19521984
fn dumpHeader(ctx: ObjectContext, writer: anytype) !void {
19531985
try writer.writeAll("header\n");
1954-
try writer.print("type {s}\n", .{@tagName(ctx.hdr.e_type)});
1955-
try writer.print("entry {x}\n", .{ctx.hdr.e_entry});
1986+
try writer.print("type {s}\n", .{@tagName(ctx.hdr.type)});
1987+
try writer.print("entry {x}\n", .{ctx.hdr.entry});
19561988
}
19571989

19581990
fn dumpPhdrs(ctx: ObjectContext, writer: anytype) !void {
@@ -2011,16 +2043,10 @@ const ElfDumper = struct {
20112043
}
20122044
}
20132045

2014-
fn dumpDynamicSection(ctx: ObjectContext, shndx: usize, writer: anytype) !void {
2015-
const shdr = ctx.shdrs[shndx];
2016-
const strtab = ctx.getSectionContents(shdr.sh_link);
2017-
const data = ctx.getSectionContents(shndx);
2018-
const nentries = @divExact(data.len, @sizeOf(elf.Elf64_Dyn));
2019-
const entries = @as([*]align(1) const elf.Elf64_Dyn, @ptrCast(data.ptr))[0..nentries];
2020-
2046+
fn dumpDynamicSection(ctx: ObjectContext, writer: anytype) !void {
20212047
try writer.writeAll(ElfDumper.dynamic_section_label ++ "\n");
20222048

2023-
for (entries) |entry| {
2049+
for (ctx.dyns) |entry| {
20242050
const key = @as(u64, @bitCast(entry.d_tag));
20252051
const value = entry.d_val;
20262052

@@ -2067,7 +2093,7 @@ const ElfDumper = struct {
20672093
elf.DT_RPATH,
20682094
elf.DT_RUNPATH,
20692095
=> {
2070-
const name = getString(strtab, @intCast(value));
2096+
const name = getString(ctx.dyns_strings, @intCast(value));
20712097
try writer.print(" {s}", .{name});
20722098
},
20732099

@@ -2256,8 +2282,8 @@ const ElfDumper = struct {
22562282
};
22572283

22582284
const Symtab = struct {
2259-
symbols: []align(1) const elf.Elf64_Sym = &[0]elf.Elf64_Sym{},
2260-
strings: []const u8 = &[0]u8{},
2285+
symbols: []const elf.Elf64_Sym = &.{},
2286+
strings: []const u8 = &.{},
22612287

22622288
fn get(st: Symtab, index: usize) ?elf.Elf64_Sym {
22632289
if (index >= st.symbols.len) return null;

0 commit comments

Comments
 (0)