Skip to content

Please add instructions on how to add an architecture #173

@glaubitz

Description

@glaubitz

We're in the process on adding support for new architectures to the Rust compiler with the help of rustc_codegen_gcc.

As a first candidate, we want to get the m68k architecture working which has an LLVM backend which is not 100% feature-complete and has some issues when trying to build the Rust compiler for m68k. Thus, we want to give it a try with rustc_codegen_gcc.

Now, to get the backend working, we need to add m68k support in rustix and linux-raw-sys. While I have experience adding architecture support to the libc crate, I'm not sure how to add architecture support to these two crates. It seems that one has to run bindgen to generate the bindings, but there doesn't seem to be any easy to follow manual for it.

Could you please add instructions on how to add a new architecture so that new contributors don't have to figure this out by trial and error?

Activity

antoyo

antoyo commented on Nov 4, 2025

@antoyo

I believe I found it (to be confirmed by someone who knows this project).
In this match, we need:

        "m68k" => &["m68k"],

However, when trying to generate the bindings, it panics with:

thread 'main' (82788) panicked at /home/user/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bindgen-0.72.1/codegen/mod.rs:946:25:
assertion `left == right` failed: Target platform requires `--no-size_t-is-usize`. The alignment of `size_t` (2) does not match the target pointer size (4)
  left: 2
 right: 4
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

I guess I might need to set the alignment to 4 for m68k somewhere.

pekkarr

pekkarr commented on Nov 4, 2025

@pekkarr

I'm able to generate bindings for m68k using the regular LLVM-based rustc with these changes:

diff --git a/gen/modules/general.h b/gen/modules/general.h
index bf163a36d4d2..4c9f81677497 100644
--- a/gen/modules/general.h
+++ b/gen/modules/general.h
@@ -229,7 +229,7 @@ struct user_desc {
 // that its fourth argument be the size of the kernel's internal `sigset_t`
 // type. So we define our own.

-#if defined(__i386__) || defined(__x86_64__) || defined(__s390x__) || defined(__arm__) || defined(__loongarch__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__s390x__) || defined(__arm__) || defined(__loongarch__) || defined(__m68k__)
 #define _NSIG 64
 #endif

diff --git a/gen/src/main.rs b/gen/src/main.rs
index 3e67b701bdb9..86e97618a50c 100644
--- a/gen/src/main.rs
+++ b/gen/src/main.rs
@@ -292,13 +292,14 @@ fn rust_arches(linux_arch: &str) -> &[&str] {
         // hexagon gets build errors; disable it for now
         "hexagon" => &[],
         "loongarch" => &["loongarch64"],
+        "m68k" => &["m68k"],
         "mips" => &["mips", "mips64", "mips32r6", "mips64r6"],
         "powerpc" => &["powerpc", "powerpc64"],
         "riscv" => &["riscv32", "riscv64"],
         "s390" => &["s390x"],
         "sparc" => &["sparc", "sparc64"],
         "x86" => &["x86", "x86_64", "x32"],
-        "alpha" | "cris" | "h8300" | "m68k" | "microblaze" | "mn10300" | "score" | "blackfin"
+        "alpha" | "cris" | "h8300" | "microblaze" | "mn10300" | "score" | "blackfin"
         | "frv" | "ia64" | "m32r" | "m68knommu" | "parisc" | "sh" | "um" | "xtensa"
         | "unicore32" | "c6x" | "nios2" | "openrisc" | "arc" | "nds32" | "metag" | "tile" => &[],
         _ => panic!("unrecognized arch: {}", linux_arch),
diff --git a/src/lib.rs b/src/lib.rs
index 8ba26751deff..716e36a92f5e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -27,6 +27,7 @@ pub mod ctypes {
     pub type c_char = c_uchar;
     #[cfg(any(
         target_arch = "loongarch64",
+        target_arch = "m68k",
         target_arch = "mips",
         target_arch = "mips64",
         target_arch = "mips32r6",
antoyo

antoyo commented on Nov 4, 2025

@antoyo

I'm able to generate bindings for m68k using the regular LLVM-based rustc with these changes:

I still get the same panic as above with these changes.
Do you use rust stable version 1.91?
Which command do you run to generate the bindings?
I tried:

cd gen
cargo run --release

Thanks for your help.

pekkarr

pekkarr commented on Nov 4, 2025

@pekkarr

I'm using stable rustc 1.91.0 (installed with rustup) on Debian testing, with libclang-19-dev 1:19.1.7-7 (which is used by bindgen). I used those same commands.

I tried it now on Arch Linux and I actually got the same alignment panic. Maybe Debian patches their clang to change the alignment on m68k?

pekkarr

pekkarr commented on Nov 4, 2025

@pekkarr

It looks like size_t (which is unsigned int on m68k) alignment was changed recently in clang to 2 bytes to match what GCC does. Debian is just using an old version of clang.

glaubitz

glaubitz commented on Nov 4, 2025

@glaubitz
Author

It looks like size_t (which is unsigned int on m68k) alignment was changed recently in clang to 2 bytes to match what GCC does. Debian is just using an old version of clang.

This is actually a more complicated story. The official SysV ABI for m68k requires a default alignment of 4 bytes and that is actually used on NetBSD ELF as well as Amiga Unix.

However, one of the Linux/m68k maintainers back in the days decided not to switch the default alignment on m68k for Linux from 2 to 4 bytes when the switch was made from a.out to ELF.

I am planning to eventually switch Debian/m68k to 4 bytes alignment and so does Gentoo, but there are still some tests to be done.

See this wiki page for more information.

antoyo

antoyo commented on Nov 4, 2025

@antoyo

@pekkarr: Thanks. I managed to generate the code for m68k, but I noticed a few modules are not generated (the content is only /* automatically generated by rust-bindgen 0.72.1 */).
It seems it was the same issue for sparc.

Here are the logs for m68k (it looks normal to me):

Generating all bindings for Linux v6.17 architecture m68k
Generating bindings for auxvec on Linux v6.17 architecture m68k
Generating bindings for bootparam on Linux v6.17 architecture m68k
Generating bindings for btrfs on Linux v6.17 architecture m68k
Generating bindings for elf_uapi on Linux v6.17 architecture m68k
Generating bindings for errno on Linux v6.17 architecture m68k
Generating bindings for general on Linux v6.17 architecture m68k
clang diag: modules/general.h:156:9: warning: 'EPOLLIN' macro redefined [-Wmacro-redefined]
clang diag: modules/general.h:157:9: warning: 'EPOLLPRI' macro redefined [-Wmacro-redefined]
clang diag: modules/general.h:158:9: warning: 'EPOLLOUT' macro redefined [-Wmacro-redefined]
clang diag: modules/general.h:159:9: warning: 'EPOLLERR' macro redefined [-Wmacro-redefined]
clang diag: modules/general.h:160:9: warning: 'EPOLLHUP' macro redefined [-Wmacro-redefined]
clang diag: modules/general.h:161:9: warning: 'EPOLLNVAL' macro redefined [-Wmacro-redefined]
clang diag: modules/general.h:162:9: warning: 'EPOLLRDNORM' macro redefined [-Wmacro-redefined]
clang diag: modules/general.h:163:9: warning: 'EPOLLRDBAND' macro redefined [-Wmacro-redefined]
clang diag: modules/general.h:164:9: warning: 'EPOLLWRNORM' macro redefined [-Wmacro-redefined]
clang diag: modules/general.h:165:9: warning: 'EPOLLWRBAND' macro redefined [-Wmacro-redefined]
clang diag: modules/general.h:166:9: warning: 'EPOLLMSG' macro redefined [-Wmacro-redefined]
clang diag: modules/general.h:167:9: warning: 'EPOLLRDHUP' macro redefined [-Wmacro-redefined]
clang diag: modules/general.h:168:9: warning: 'EPOLLEXCLUSIVE' macro redefined [-Wmacro-redefined]
clang diag: modules/general.h:169:9: warning: 'EPOLLWAKEUP' macro redefined [-Wmacro-redefined]
clang diag: modules/general.h:170:9: warning: 'EPOLLONESHOT' macro redefined [-Wmacro-redefined]
clang diag: modules/general.h:171:9: warning: 'EPOLLET' macro redefined [-Wmacro-redefined]
clang diag: modules/general.h:199:9: warning: 'UFFD_API' macro redefined [-Wmacro-redefined]
clang diag: modules/general.h:201:9: warning: 'UFFDIO_REGISTER_MODE_MISSING' macro redefined [-Wmacro-redefined]
clang diag: modules/general.h:202:9: warning: 'UFFDIO_REGISTER_MODE_WP' macro redefined [-Wmacro-redefined]
clang diag: modules/general.h:203:9: warning: 'UFFDIO_REGISTER_MODE_MINOR' macro redefined [-Wmacro-redefined]
clang diag: modules/general.h:205:9: warning: 'UFFDIO_COPY_MODE_DONTWAKE' macro redefined [-Wmacro-redefined]
clang diag: modules/general.h:206:9: warning: 'UFFDIO_COPY_MODE_WP' macro redefined [-Wmacro-redefined]
clang diag: modules/general.h:208:9: warning: 'UFFDIO_ZEROPAGE_MODE_DONTWAKE' macro redefined [-Wmacro-redefined]
Generating bindings for if_arp on Linux v6.17 architecture m68k
Generating bindings for if_ether on Linux v6.17 architecture m68k
Generating bindings for if_packet on Linux v6.17 architecture m68k
Generating bindings for if_tun on Linux v6.17 architecture m68k
Generating bindings for image on Linux v6.17 architecture m68k
Generating bindings for io_uring on Linux v6.17 architecture m68k
Generating bindings for ioctl on Linux v6.17 architecture m68k
Generating bindings for landlock on Linux v6.17 architecture m68k
Generating bindings for loop_device on Linux v6.17 architecture m68k
Generating bindings for mempolicy on Linux v6.17 architecture m68k
Generating bindings for net on Linux v6.17 architecture m68k
Generating bindings for netlink on Linux v6.17 architecture m68k
Generating bindings for prctl on Linux v6.17 architecture m68k
Generating bindings for ptrace on Linux v6.17 architecture m68k
Generating bindings for system on Linux v6.17 architecture m68k
Generating bindings for xdp on Linux v6.17 architecture m68k

I applied a similar fix in my rustix fork to handle m68k.

pekkarr

pekkarr commented on Nov 5, 2025

@pekkarr

I noticed a few modules are not generated

Right. For bootparam and image that's probably fine, since those are generated only for a select few architectures.

For ioctl, I got things to work with these changes:

diff --git a/gen/ioctl/generate.sh b/gen/ioctl/generate.sh
index 6b7ee52..4869a36 100755
--- a/gen/ioctl/generate.sh
+++ b/gen/ioctl/generate.sh
@@ -65,6 +65,10 @@ cat loongarch-ioctls.txt >> "$out"
 # qemu-csky -L /usr/csky-linux-gnuabiv2 ./main.exe >> "$out"
 cat csky-ioctls.txt >> "$out"

+m68k-linux-gnu-gcc -Iinclude -c list.c $cflags
+m68k-linux-gnu-gcc main.c list.o -o main.exe $cflags
+qemu-m68k -L /usr/m68k-linux-gnu ./main.exe >> "$out"
+
 # Add any extra custom definitions at the end.
 echo "#include \"ioctl-addendum.h\"" >> "$out"

diff --git a/gen/ioctl/list.c b/gen/ioctl/list.c
index 0a1e767..c702926 100644
--- a/gen/ioctl/list.c
+++ b/gen/ioctl/list.c
@@ -96,7 +96,7 @@ struct sockaddr {
 #include <linux/joystick.h>
 #include <linux/kd.h>
 #include <linux/kcov.h>
-#if !defined(__arm__) && !defined(__loongarch__) && !defined(__powerpc64__) && !defined(__riscv) && !defined(__csky__)// various errors
+#if !defined(__arm__) && !defined(__loongarch__) && !defined(__powerpc64__) && !defined(__riscv) && !defined(__csky__) && !defined(__m68k__) // various errors
 #include <linux/kvm.h>
 #endif
 #include <linux/lirc.h>
diff --git a/gen/ioctl/main.c b/gen/ioctl/main.c
index 6b1111f..484484d 100644
--- a/gen/ioctl/main.c
+++ b/gen/ioctl/main.c
@@ -49,6 +49,8 @@ int main(void) {
     printf("#ifdef __loongarch__\n");
 #elif defined(__csky__)
     printf("#ifdef __csky__\n");
+#elif defined(__m68k__)
+    printf("#ifdef __m68k__\n");
 #else
 #error "unimplemented architecture"
 #endif

(If you're using Linux kernel >= 6.13 you also need to remove one reiserfs include and ioctl from gen/ioctl/list.c, since reiserfs was removed from the kernel. For some reason the ioctl generation uses system-wide installed Linux headers instead of fresh git ones like the other modules.)

And then run cd gen/ioctl && ./generate.sh (which requires GCC cross-compilers for several architectures installed) and then regenerate the bindings as before.

Anyways, I think the alignment panic is a bug in bindgen. Based on the code comments, the issue and the commit that introduced this check, the idea is to check that size_t is the same type as uintptr_t so that size_t can be mapped to usize in Rust. However, the code checks that size_t alignment is equal to pointer size, not pointer alignment. I don't think this is required, it should be enough that size_t has the same size and alignment as a pointer (which is true for m68k).

antoyo

antoyo commented on Nov 5, 2025

@antoyo

@pekkarr: Thanks for the info.

What would be the way forward to add support for m68k here?
Would the first step be fixing the panic in bindgen?

pekkarr

pekkarr commented on Nov 5, 2025

@pekkarr

If @sunfishcode agrees that we can add an architecture that's only usable with rustc_codegen_gcc, I can make a pull request for linux-raw-sys.

I think that the bindgen panic is not critical to fix for this, since it can be worked around by using an older libclang (like on Debian) and bindgen is only used when pre-generating the bindings, so users of linux-raw-sys aren't affected. However, fixing the check in bindgen would be important for other Rust libraries that generate C bindings at build time, since that won't work on m68k if the C headers use size_t.

antoyo

antoyo commented on Nov 5, 2025

@antoyo

If @sunfishcode agrees that we can add an architecture that's only usable with rustc_codegen_gcc, I can make a pull request for linux-raw-sys.

I'm not sure if that's what you mean here, but the Rust compiler already has tier-3 support for m68k.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @antoyo@glaubitz@pekkarr

        Issue actions

          Please add instructions on how to add an architecture · Issue #173 · sunfishcode/linux-raw-sys