From 4e2a4e194bb07d08927410012a5a19bbe443c9f2 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 8 Nov 2020 16:32:54 +0100 Subject: [PATCH 1/5] std: Use correct clone() stub The previous clone() definition was written for 32bit PPC targets, trying to execute it on a PPC64 machine lead to countless crashes. Use the clone() definition kindly lifted from Musl libc. --- lib/std/special/c.zig | 89 ++++++++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 40 deletions(-) diff --git a/lib/std/special/c.zig b/lib/std/special/c.zig index 55548e399e..449b70d6b0 100644 --- a/lib/std/special/c.zig +++ b/lib/std/special/c.zig @@ -386,6 +386,11 @@ fn clone() callconv(.Naked) void { ); }, .arm => { + // __clone(func, stack, flags, arg, ptid, tls, ctid) + // r0, r1, r2, r3, +0, +4, +8 + + // syscall(SYS_clone, flags, stack, ptid, tls, ctid) + // r7 r0, r1, r2, r3, r4 asm volatile ( \\ stmfd sp!,{r4,r5,r6,r7} \\ mov r7,#120 @@ -445,6 +450,11 @@ fn clone() callconv(.Naked) void { ); }, .mips, .mipsel => { + // __clone(func, stack, flags, arg, ptid, tls, ctid) + // 3, 4, 5, 6, 7, 8, 9 + + // syscall(SYS_clone, flags, stack, ptid, tls, ctid) + // 2 4, 5, 6, 7, 8 asm volatile ( \\ # Save function pointer and argument pointer on new thread stack \\ and $5, $5, -8 @@ -465,12 +475,14 @@ fn clone() callconv(.Naked) void { \\ addu $sp, $sp, 16 \\ jr $ra \\ subu $2, $0, $2 - \\1: beq $2, $0, 1f + \\1: + \\ beq $2, $0, 1f \\ nop \\ addu $sp, $sp, 16 \\ jr $ra \\ nop - \\1: lw $25, 0($sp) + \\1: + \\ lw $25, 0($sp) \\ lw $4, 4($sp) \\ jalr $25 \\ nop @@ -480,51 +492,48 @@ fn clone() callconv(.Naked) void { ); }, .powerpc64, .powerpc64le => { + // __clone(func, stack, flags, arg, ptid, tls, ctid) + // 3, 4, 5, 6, 7, 8, 9 + + // syscall(SYS_clone, flags, stack, ptid, tls, ctid) + // 0 3, 4, 5, 6, 7 asm volatile ( - \\ # store non-volatile regs r30, r31 on stack in order to put our - \\ # start func and its arg there - \\ stwu 30, -16(1) - \\ stw 31, 4(1) - \\ # save r3 (func) into r30, and r6(arg) into r31 - \\ mr 30, 3 - \\ mr 31, 6 \\ # create initial stack frame for new thread - \\ clrrwi 4, 4, 4 - \\ li 0, 0 - \\ stwu 0, -16(4) - \\ #move c into first arg - \\ mr 3, 5 - \\ mr 5, 7 - \\ mr 6, 8 - \\ mr 7, 9 - \\ # move syscall number into r0 - \\ li 0, 120 + \\ clrrdi 4, 4, 4 + \\ li 0, 0 + \\ stdu 0,-32(4) + \\ + \\ # save fn and arg to child stack + \\ std 3, 8(4) + \\ std 6, 16(4) + \\ + \\ # shuffle args into correct registers and call SYS_clone + \\ mr 3, 5 + \\ #mr 4, 4 + \\ mr 5, 7 + \\ mr 6, 8 + \\ mr 7, 9 + \\ li 0, 120 # SYS_clone = 120 \\ sc - \\ # check for syscall error - \\ bns+ 1f # jump to label 1 if no summary overflow. - \\ #else - \\ neg 3, 3 #negate the result (errno) + \\ + \\ # if error, negate return (errno) + \\ bns+ 1f + \\ neg 3, 3 + \\ \\1: - \\ # compare sc result with 0 + \\ # if we're the parent, return \\ cmpwi cr7, 3, 0 - \\ # if not 0, jump to end - \\ bne cr7, 2f - \\ #else: we're the child - \\ #call funcptr: move arg (d) into r3 - \\ mr 3, 31 - \\ #move r30 (funcptr) into CTR reg - \\ mtctr 30 - \\ # call CTR reg + \\ bnelr cr7 + \\ + \\ # we're the child. call fn(arg) + \\ ld 3, 16(1) + \\ ld 12, 8(1) + \\ mtctr 12 \\ bctrl - \\ # mov SYS_exit into r0 (the exit param is already in r3) - \\ li 0, 1 + \\ + \\ # call SYS_exit. exit code is already in r3 from fn return value + \\ li 0, 1 # SYS_exit = 1 \\ sc - \\2: - \\ # restore stack - \\ lwz 30, 0(1) - \\ lwz 31, 4(1) - \\ addi 1, 1, 16 - \\ blr ); }, .sparcv9 => { From e374ae3598669bf856df9d65e405c398b893e325 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 8 Nov 2020 16:34:44 +0100 Subject: [PATCH 2/5] std: Use newfstatat on PPC64 One more variation in the syscall table, hooray! --- lib/std/os/linux.zig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index d0bc80c645..5299c995a0 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -1098,6 +1098,8 @@ pub fn lstat(pathname: [*:0]const u8, statbuf: *kernel_stat) usize { pub fn fstatat(dirfd: i32, path: [*:0]const u8, stat_buf: *kernel_stat, flags: u32) usize { if (@hasField(SYS, "fstatat64")) { return syscall4(.fstatat64, @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), @ptrToInt(stat_buf), flags); + } else if (@hasField(SYS, "newfstatat")) { + return syscall4(.newfstatat, @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), @ptrToInt(stat_buf), flags); } else { return syscall4(.fstatat, @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), @ptrToInt(stat_buf), flags); } From 9c5eea9f40f7f879de2e645b45f9e58eea316357 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 8 Nov 2020 16:55:11 +0100 Subject: [PATCH 3/5] stage2: Use correct ppc generic feature set --- lib/std/target.zig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/std/target.zig b/lib/std/target.zig index 56390fbce3..9a006a95fa 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -1123,7 +1123,9 @@ pub const Target = struct { .mips, .mipsel => &mips.cpu.mips32, .mips64, .mips64el => &mips.cpu.mips64, .msp430 => &msp430.cpu.generic, - .powerpc, .powerpc64, .powerpc64le => &powerpc.cpu.generic, + .powerpc => &powerpc.cpu.ppc32, + .powerpc64 => &powerpc.cpu.ppc64, + .powerpc64le => &powerpc.cpu.ppc64le, .amdgcn => &amdgpu.cpu.generic, .riscv32 => &riscv.cpu.generic_rv32, .riscv64 => &riscv.cpu.generic_rv64, From f2b4e6b2e7ba9da26f69e2d978978adaf8b3f55a Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 9 Nov 2020 17:24:47 +0100 Subject: [PATCH 4/5] Better coverage in @splat tests Cover more common and uncommon cases. --- test/stage1/behavior/vector.zig | 34 +++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/test/stage1/behavior/vector.zig b/test/stage1/behavior/vector.zig index fb85c116d5..a36463144f 100644 --- a/test/stage1/behavior/vector.zig +++ b/test/stage1/behavior/vector.zig @@ -149,15 +149,33 @@ test "vector casts of sizes not divisable by 8" { test "vector @splat" { const S = struct { + fn testForT(comptime N: comptime_int, v: anytype) void { + const T = @TypeOf(v); + var vec = @splat(N, v); + expectEqual(Vector(N, T), @TypeOf(vec)); + var as_array = @as([N]T, vec); + for (as_array) |elem| expectEqual(v, elem); + } fn doTheTest() void { - var v: u32 = 5; - var x = @splat(4, v); - expect(@TypeOf(x) == Vector(4, u32)); - var array_x: [4]u32 = x; - expect(array_x[0] == 5); - expect(array_x[1] == 5); - expect(array_x[2] == 5); - expect(array_x[3] == 5); + // Splats with multiple-of-8 bit types that fill a 128bit vector. + testForT(16, @as(u8, 0xEE)); + testForT(8, @as(u16, 0xBEEF)); + testForT(4, @as(u32, 0xDEADBEEF)); + testForT(2, @as(u64, 0xCAFEF00DDEADBEEF)); + + testForT(8, @as(f16, 3.1415)); + testForT(4, @as(f32, 3.1415)); + testForT(2, @as(f64, 3.1415)); + + // Same but fill more than 128 bits. + testForT(16 * 2, @as(u8, 0xEE)); + testForT(8 * 2, @as(u16, 0xBEEF)); + testForT(4 * 2, @as(u32, 0xDEADBEEF)); + testForT(2 * 2, @as(u64, 0xCAFEF00DDEADBEEF)); + + testForT(8 * 2, @as(f16, 3.1415)); + testForT(4 * 2, @as(f32, 3.1415)); + testForT(2 * 2, @as(f64, 3.1415)); } }; S.doTheTest(); From 2193bbfd938ef562abdf1c9f1aced9acb24009bd Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 9 Nov 2020 17:26:24 +0100 Subject: [PATCH 5/5] Skip f16 to f128 conversion test for ppc64 As for aarch64 we're waiting for LLVM to emit calls to the specific builtins that implement this conversion. --- test/stage1/behavior/widening.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/test/stage1/behavior/widening.zig b/test/stage1/behavior/widening.zig index 71f8ae482e..2f215ccb11 100644 --- a/test/stage1/behavior/widening.zig +++ b/test/stage1/behavior/widening.zig @@ -31,6 +31,7 @@ test "float widening" { test "float widening f16 to f128" { // TODO https://github.com/ziglang/zig/issues/3282 if (@import("builtin").arch == .aarch64) return error.SkipZigTest; + if (@import("builtin").arch == .powerpc64le) return error.SkipZigTest; var x: f16 = 12.34; var y: f128 = x;