Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Zig code compile for riscv64-linux target (with or without glibc) #18815

Closed
wants to merge 3 commits into from

Conversation

rootbeer
Copy link
Contributor

@rootbeer rootbeer commented Feb 4, 2024

(Probably incomplete) patches to make Zig code compile for riscv64-linux target (with or without glibc). Builds on #18803.

With these patches I can compile a glibc-linked hello.zig with (I'm on an x86_64 Linux host):

   zig build-exe hello.zig -lc -target riscv64-linux-gnu.2.38 -mcpu=generic_rv64

or a native Zig binary with:

   zig build-exe hello.zig -target riscv64-linux -mcpu=generic_rv64

But the resulting binary segfaults immediately in my (perhaps broken) qemu setup. I've no experience in riscv64, so this maybe be broken in subtle ways, but perhaps its a useful point for someone with the right hardware to make more progress.

@mikdusan
Copy link
Member

mikdusan commented Feb 4, 2024

But the resulting binary segfaults immediately in my (perhaps broken) qemu setup.

To provide a baseline, on master I can build a riscv64 hello-world and run it w/ qemu:

[master] marcus▸ zig version
0.12.0-dev.2540+776cd673f

[master] marcus▸ cat z0.zig
const std = @import("std");

pub fn main() !void {
    std.log.debug("hello", .{});
}

[master] marcus▸ zig build-exe z0.zig -target riscv64-linux

[master] marcus▸ qemu-riscv64 --version
qemu-riscv64 version 8.2.0
Copyright (c) 2003-2023 Fabrice Bellard and the QEMU Project developers

[master] marcus▸ qemu-riscv64 ./z0
debug: hello

@rootbeer
Copy link
Contributor Author

rootbeer commented Feb 6, 2024

Thanks for the detailed steps for ensuring I've got qemu-riscv64 working. I'm able to run statically linked a "hello world" Zig binary (and even if I use the statically linked Musl C library instead of the Zig library). After some Googling (and hints in some of the other ongoing Zig PRs for riscv64), I can run the dynamic executables by first doing:

patchelf --set-interpreter /lib/ld-linux-riscv64-lp64d.so.1 hello

(To specify the "d" flavor of linker, instead of the Zig default "...lp64.so.1", see #18803 (comment)).

Then

qemu-riscv64 -L /usr/riscv64-linux-gnu/ ./hello

seems to work! (At least for simple hello-world binaries.)

Anyone know how to express to Zig that you want to target the different floating point ABIs? (I believe that is the only source of ABI differentiation that we need to capture for the linker?)

@RossComputerGuy
Copy link
Contributor

@rootbeer I think we'll have to look at the difference features set in target and just "figure it out".

@bjia56
Copy link

bjia56 commented Feb 6, 2024

@rootbeer thanks for looking into updating Target.zig with the new interpreter! I think the logic should mirror the abi checks here:

.riscv64 => {

RossComputerGuy and others added 3 commits February 8, 2024 08:37
Borrow the ucontext layout from Go (probably reasonable?) and fix up
some missing imports for shared structures.

I can compile a glibc-linked hello.zig with:

   zig build-exe hello.zig -lc -target riscv64-linux-gnu.2.38 -mcpu=generic_rv64

or a native Zig binary with:

   zig build-exe hello.zig -target riscv64-linux -mcpu=generic_rv64

But the resulting binary segfaults immediately in my (perhaps broken) qemu
setup.  I've no experience in riscv64, so this maybe be broken in subtle
ways, but perhaps its a useful point for someone with the right hardware
to make more progress.

Builds on ziglang#18803
Riscv64 supports multiple ABIs, depending on how floating-point values are
supported.  Each ABI has its own dynamic linker, so decode the CPU and ABI
features to build the right linker path.
@rootbeer
Copy link
Contributor Author

I've (force) pushed an updated tree that builds the target dynamic linker path based on the CPU/ABI for riscv{32,64} dynamic binaries. With my tree I can use zig to build Zig-source or C-source "hello world" binaries and run them with qemu. The Zig code can be standalone or linked to glibc or musl, and the C-source can be linked to glibc or musl.

AFAICT, I can only target the double-float register ABI with Zig, via the "riscv64-linux-gnu" or "riscv64-linux-musl" targets. I'm not sure if that list of targets needs to be expanded (e.g., with "*-gnueabihf" flavors), or if the -cpu parameter should be changed from the default to exercise the other floating point ABIs.

It also isn't clear to me which variations fp ABIs glibc supports. (I assume Zig wants to support all the variations.)

Finally, I'm "testing" the floating-point ABI by invoking pow and powf via the C library, since they take and return double/float values. Any idea if that is that a sufficient smoke test for getting the ABI linking correct?

@andrewrk
Copy link
Member

andrewrk commented May 9, 2024

Still a draft, has conflicts with master branch, not touched for over 30 days. Feel free to reopen when you have something ready for review.

@andrewrk andrewrk closed this May 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants