Open pingiun opened 4 years ago
The good news here is that the next step is the fun part: making the zig standard library support powerpc64le-linux
Here is an incomplete diff for ppc64le. I had access to a decent POWER machine for a bit and tried to get this working. I lost access to the machine and my VM is too painfully slow to continue on this. Hopefully someone else can use this as a base. There was still one error when trying to build zig with this patch (and the missing files mentioned below). Zig0 would build and was usable for small examples but it couldn't quite build a full zig.
P.S. I forgot to save the os.zig files to go with this (ie. lib/std/os/linux/powerpc64le.zig and lib/std/os/bits/linux/powerpc64le.zig) but they should be pretty easy to recreate from the musl ppc64le sources.
diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig
index a6d010e26..a854552b6 100644
--- a/lib/std/os/bits/linux.zig
+++ b/lib/std/os/bits/linux.zig
@@ -15,6 +15,7 @@ pub usingnamespace switch (builtin.arch) {
.arm => @import("linux/arm-eabi.zig"),
.riscv64 => @import("linux/riscv64.zig"),
.mipsel => @import("linux/mipsel.zig"),
+ .powerpc64le => @import("linux/powerpc64le.zig"),
else => struct {},
};
@@ -1026,12 +1027,13 @@ pub fn CPU_COUNT(set: cpu_set_t) cpu_count_t {
pub const MINSIGSTKSZ = switch (builtin.arch) {
.i386, .x86_64, .arm, .mipsel => 2048,
+ .powerpc64le => 4096,
.aarch64 => 5120,
else => @compileError("MINSIGSTKSZ not defined for this architecture"),
};
pub const SIGSTKSZ = switch (builtin.arch) {
.i386, .x86_64, .arm, .mipsel => 8192,
- .aarch64 => 16384,
+ .aarch64, .powerpc64le => 16384,
else => @compileError("SIGSTKSZ not defined for this architecture"),
};
diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig
index 51649941c..67c4daafd 100644
--- a/lib/std/os/linux.zig
+++ b/lib/std/os/linux.zig
@@ -20,6 +20,7 @@ pub usingnamespace switch (builtin.arch) {
.arm => @import("linux/arm-eabi.zig"),
.riscv64 => @import("linux/riscv64.zig"),
.mipsel => @import("linux/mipsel.zig"),
+ .powerpc64le => @import("linux/powerpc64le.zig"),
else => struct {},
};
pub usingnamespace @import("bits.zig");
diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig
index efb1e5fe0..9c13d1282 100644
--- a/lib/std/os/linux/tls.zig
+++ b/lib/std/os/linux/tls.zig
@@ -47,7 +47,7 @@ const TLSVariant = enum {
};
const tls_variant = switch (builtin.arch) {
- .arm, .armeb, .aarch64, .aarch64_be, .riscv32, .riscv64, .mipsel => TLSVariant.VariantI,
+ .arm, .armeb, .aarch64, .aarch64_be, .riscv32, .riscv64, .mipsel, .powerpc64le => TLSVariant.Va
riantI,
.x86_64, .i386 => TLSVariant.VariantII,
else => @compileError("undefined tls_variant for this architecture"),
};
@@ -83,12 +83,12 @@ comptime {
// make the generated code more efficient
const tls_tp_offset = switch (builtin.arch) {
- .mipsel => 0x7000,
+ .mipsel, .powerpc64le => 0x7000,
else => 0,
};
const tls_dtv_offset = switch (builtin.arch) {
- .mipsel => 0x8000,
+ .mipsel, .powerpc64le => 0x8000,
.riscv32, .riscv64 => 0x800,
else => 0,
};
@@ -167,6 +167,19 @@ pub fn setThreadPointer(addr: usize) void {
const rc = std.os.linux.syscall1(std.os.linux.SYS_set_thread_area, addr);
assert(rc == 0);
},
+ .powerpc64le => {
+ asm volatile (
+// This small snippet doesn't seem to be necessary? Just the last three lines? Not totally sure.
+// \\ stw 3, -12(1)
+// \\ addi 3, 1, -12
+// \\ mr 2,3
+// \\ mr 13,3
+// \\ li 3,0
+// \\ blr
+ \\ mr 13, %[addr]
+ :
+ : [addr] "r" (addr)
+ );
+ },
else => @compileError("Unsupported architecture"),
}
}
diff --git a/lib/std/special/c.zig b/lib/std/special/c.zig
index 0895b1e6f..0c1e55ebc 100644
--- a/lib/std/special/c.zig
+++ b/lib/std/special/c.zig
@@ -391,10 +391,80 @@ nakedcc fn clone() void {
\\ syscall
);
},
+ .powerpc64le => {
+ asm volatile (
+ \\ clrrdi 4,4,4
+ \\ li 0,0
+ \\ stdu 0,-32(4)
+ \\ std 3,8(4)
+ \\ std 6,16(4)
+ \\ mr 3,5
+ \\ mr 4,4
+ \\ mr 5,7
+ \\ mr 6,8
+ \\ mr 7,9
+ \\ li 0,120
+ \\ sc
+ \\ bns+ 1f
+ \\ neg 3,3
+ \\1:
+ \\ cmpwi cr7,3,0
+ \\ bnelr cr7
+ \\ ld 3,16(1)
+ \\ ld 12, 8(1)
+ \\ mtctr 12
+ \\ bctrl
+ \\ li 0,1
+ \\ sc
+ );
+ },
else => @compileError("Implement clone() for this arch."),
}
}
+// This is the valgrind implementation, which seems a little more
+// robust. I am not totally sure it is compatible with musl however! Test??
+ // \\ stdu 1,-64(1)
+ // \\ std 29,40(1)
+ // \\ std 30,48(1)
+ // \\ std 31,56(1)
+ // \\ mr 30,3
+ // \\ mr 31,6
+ // \\ rldicr 4,4,0,59
+ // \\ li 0,0
+ // \\ stdu 0,-32(4)
+ // \\ mr 29,4
+ // \\ li 0,120
+ // \\ mr 3,5
+ // \\ mr 5,8
+ // \\ mr 6,13
+ // \\ mr 7,7
+ // \\ mr 8,8
+ // \\ mr 9,9
+ // \\ sc
+ // \\ mfcr 4
+ // \\ sldi 4,4,32
+ // \\ sldi 3,3,32
+ // \\ sldi 3,3,32
+ // \\ or 3,3,4
+ // \\ cmpwi 3,0
+ // \\ bne 1f
+ // \\ mr 1,29
+ // \\ ld 30,0(30)
+ // \\ mtctr 30
+ // \\ mr 3,31
+ // \\ bctrl
+ // \\ li 0,1
+ // \\ sc
+ // \\ .long 0
+ // \\1:
+ // \\ ld 29,40(1)
+ // \\ ld 30,48(1)
+ // \\ ld 31,56(1)
+ // \\ addi 1,1,64
+ // \\ blr
+
+
const math = std.math;
export fn fmodf(x: f32, y: f32) f32 {
diff --git a/lib/std/start.zig b/lib/std/start.zig
index 3c4644994..6a90f91e0 100644
--- a/lib/std/start.zig
+++ b/lib/std/start.zig
@@ -120,6 +120,11 @@ nakedcc fn _start() noreturn {
: [argc] "=r" (-> [*]usize)
);
},
+ .powerpc64le => {
+ starting_stack_ptr = asm volatile ("mr %[argc], 1"
+ : [argc] "=r" (-> [*]usize)
+ );
+ },
else => @compileError("unsupported arch"),
}
// If LLVM inlines stack variables into _start, they will overwrite
@@ -143,6 +148,10 @@ fn posixCallMainAndExit() noreturn {
if (builtin.os == builtin.Os.freebsd) {
@setAlignStack(16);
}
+ switch (builtin.arch) {
+ .powerpc64le => @setAlignStack(16),
+ else => {},
+ }
const argc = starting_stack_ptr[0];
const argv = @ptrCast([*][*:0]u8, starting_stack_ptr + 1);
diff --git a/src/os.cpp b/src/os.cpp
index f6a0b4fbd..e652a6787 100644
--- a/src/os.cpp
+++ b/src/os.cpp
@@ -2128,6 +2128,9 @@ const char *possible_ld_names[] = {
"ld-musl-armhf.so.1",
"ld-linux.so.3",
"ld-musl-arm.so.1",
+#elif defined(ZIG_ARCH_PPC64LE)
+ "ld-linux-ppc64le.so.2",
+ "ld-musl-ppc64le.so.1",
#endif
NULL,
};
diff --git a/src/os.hpp b/src/os.hpp
index ac8c55946..833fa45a9 100644
--- a/src/os.hpp
+++ b/src/os.hpp
@@ -39,6 +39,8 @@
#define ZIG_ARCH_ARM64
#elif defined(__ARM_EABI__)
#define ZIG_ARCH_ARM
+#elif defined(__ppc64le__)
+#define ZIG_ARCH_PPC64LE
#else
#define ZIG_ARCH_UNKNOWN
#endif
diff --git a/src/target.cpp b/src/target.cpp
index 82d5467e2..c11d87729 100644
--- a/src/target.cpp
+++ b/src/target.cpp
@@ -1459,6 +1459,10 @@ const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) {
case ZigLLVM_mipsel:
return "sp";
+ case ZigLLVM_ppc:
+ case ZigLLVM_ppc64:
+ return "r1";
+
case ZigLLVM_wasm32:
case ZigLLVM_wasm64:
return nullptr; // known to be not available
@@ -1497,8 +1501,6 @@ const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) {
case ZigLLVM_tce:
case ZigLLVM_tcele:
case ZigLLVM_xcore:
- case ZigLLVM_ppc:
- case ZigLLVM_ppc64:
zig_panic("TODO populate this table with stack pointer register name for this CPU archi
tecture");
}
zig_unreachable();
Want to take this upstream? Send pull request to ziglang/zig
I can, but I wouldn't be able to test the patch with zig 0.6 on ppc hardware, so a PR might not run properly.
You can still test cross compiling with this bootstrap repository, it's just that the diff needs to go upstream, since this repository copies zig from there.
This is the output when cross-compiling from x86_64-gentoo-linux-musl
host:
[ 91%] Built target LLVMAVRCodeGen
[ 92%] Built target LLVMARMCodeGen
[ 96%] Built target LLVMAMDGPUCodeGen
[ 97%] Built target LLVMAArch64CodeGen
[ 97%] Building CXX object lib/ExecutionEngine/Orc/CMakeFiles/LLVMOrcJIT.dir/CompileUtils.cpp.o
zig: warning: argument unused during compilation: '-mred-zone' [-Wunused-command-line-argument]
[ 97%] Building CXX object lib/ExecutionEngine/Orc/CMakeFiles/LLVMOrcJIT.dir/Core.cpp.o
zig: warning: argument unused during compilation: '-mred-zone' [-Wunused-command-line-argument]
[ 97%] Building CXX object lib/ExecutionEngine/Orc/CMakeFiles/LLVMOrcJIT.dir/DebugObjectManagerPlugin.cpp.o
zig: warning: argument unused during compilation: '-mred-zone' [-Wunused-command-line-argument]
[ 97%] Building CXX object lib/ExecutionEngine/Orc/CMakeFiles/LLVMOrcJIT.dir/DebuggerSupportPlugin.cpp.o
zig: warning: argument unused during compilation: '-mred-zone' [-Wunused-command-line-argument]
[ 97%] Linking CXX executable ../../../../../bin/clang-ast-dump
LLD Link... ld.lld: error: undefined symbol: __floatditf
>>> referenced by LockFileManager.cpp
>>> LockFileManager.cpp.o:(llvm::LockFileManager::waitForUnlock(unsigned int)) in archive ../../../../../lib/libLLVMSupport.a
>>> did you mean: __floattitf
>>> defined in: /home/user/.cache/zig/o/3c99341f972f013c322b509c22aa92b9/libcompiler_rt.a(/home/user/.cache/zig/o/3c99341f972f013c322b509c22aa92b9/compiler_rt.o)
make[2]: *** [tools/clang/lib/Tooling/DumpTool/CMakeFiles/clang-ast-dump.dir/build.make:155: bin/clang-ast-dump] Error 1
make[1]: *** [CMakeFiles/Makefile2:30653: tools/clang/lib/Tooling/DumpTool/CMakeFiles/clang-ast-dump.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....
[ 97%] Building CXX object lib/ExecutionEngine/Orc/CMakeFiles/LLVMOrcJIT.dir/DebugUtils.cpp.o
zig: warning: argument unused during compilation: '-mred-zone' [-Wunused-command-line-argument]
[ 97%] Building CXX object lib/ExecutionEngine/Orc/CMakeFiles/LLVMOrcJIT.dir/EPCDynamicLibrarySearchGenerator.cpp.o
zig: warning: argument unused during compilation: '-mred-zone' [-Wunused-command-line-argument]
[ 97%] Building CXX object lib/ExecutionEngine/Orc/CMakeFiles/LLVMOrcJIT.dir/EPCDebugObjectRegistrar.cpp.o
zig: warning: argument unused during compilation: '-mred-zone' [-Wunused-command-line-argument]
[ 97%] Building CXX object lib/ExecutionEngine/Orc/CMakeFiles/LLVMOrcJIT.dir/EPCEHFrameRegistrar.cpp.o
On a debian powerpc64le virtual machine, Zig release 0.6.0:
Behavior tests: