Rust-GCC / Rust-GCC/gccrs

Wrong argument register is used

Open
#3,880 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
2.9k
Forks
231
Avg merge
19h 55m
Merged PRs (30d)
67

Description

On a mips-elf target, (what I hope) equivalent C and Rust code produce different results, namely, the Rust version is trying to take the first argument from the second argument register

Build setup

FROM ubuntu:noble

ENV RUSTUP_HOME=/usr/local/rustup \
    CARGO_HOME=/usr/local/cargo \
    PATH=/usr/local/cargo/bin:$PATH \
    RUST_VERSION=nightly-2025-06-28-x86_64-unknown-linux-gnu \
    CCACHE_DIR=/w/ccache CC="ccache gcc" CXX="ccache g++"

RUN <<EOF
apt-get update
apt-get install -y build-essential libgmp-dev libmpfr-dev libmpc-dev libncurses5-dev flex bison autogen dejagnu git ccache wget

ccache --set-config max_size=0

# stolen from rust docker
wget https://static.rust-lang.org/rustup/archive/1.28.2/x86_64-unknown-linux-gnu/rustup-init
chmod +x ./rustup-init
./rustup-init -y --no-modify-path --profile complete --default-toolchain $RUST_VERSION --default-host x86_64-unknown-linux-gnu
chmod -R a+w $RUSTUP_HOME $CARGO_HOME
EOF

Compile binutils 2.44 with ./configure --disable-werror --target=mips-elf and install
Compile gccrs fcc21680857077d01a0d6b9336eea3999da351d1 with ../gccrs/configure --enable-languages=rust --disable-shared --disable-nls --target=mips-elf : (reconfigured) ../gccrs/configure --enable-languages=rust --disable-shared --disable-threads --disable-libmudflap --disable-libssp --disable-libstdcxx --disable-nls --disable-libgcc --disable-libgomp --disable-libatomic --target=mips-elf --without-headers and install

Compiling with -frust-incomplete-and-experimental-compiler-do-not-use -O2 -S

void start(unsigned char *ptr) {
    void call_with_a0(unsigned char *ptr);

    call_with_a0(ptr);
}
#[no_mangle]
pub extern "C" fn start(ptr: *mut u8) {
    extern "C" {
        fn call_with_a0(ptr: *mut u8);
    }

    unsafe {
        call_with_a0(ptr);
    }
}
Full output assembly

	.file	1 "a0.c"
	.section .mdebug.abi32
	.previous
	.nan	legacy
	.module	fp=32
	.module	nooddspreg
	.module	arch=mips1
	.text
	.align	2
	.globl	start
	.set	nomips16
	.set	nomicromips
	.ent	start
	.type	start, @function
start:
	.frame	$sp,0,$31		# vars= 0, regs= 0/0, args= 0, gp= 0
	.mask	0x00000000,0
	.fmask	0x00000000,0
	.set	noreorder
	.set	nomacro
	j	call_with_a0
	nop

	.set	macro
	.set	reorder
	.end	start
	.size	start, .-start
	.ident	"GCC: (GNU) 16.0.0 20250604 (experimental)"
	.file	1 "a0.rs"
	.section .mdebug.abi32
	.previous
	.nan	legacy
	.module	fp=32
	.module	nooddspreg
	.module	arch=mips1
	.text
	.align	2
	.globl	start
$LFB0 = .
	.cfi_startproc
	.set	nomips16
	.set	nomicromips
	.ent	start
	.type	start, @function
start:
	.frame	$sp,24,$31		# vars= 0, regs= 1/0, args= 16, gp= 0
	.mask	0x80000000,-4
	.fmask	0x00000000,0
	.set	noreorder
	.set	nomacro
	addiu	$sp,$sp,-24
	.cfi_def_cfa_offset 24
	sw	$4,24($sp)
	sw	$31,20($sp)
	.cfi_offset 31, -4
	jal	call_with_a0
	move	$4,$5                                                   # <---- notable: move $a0, $a1 ..?

	lw	$31,20($sp)
	lw	$2,24($sp)
	jr	$31
	addiu	$sp,$sp,24

	.cfi_def_cfa_offset 0
	.cfi_restore 31
	.set	macro
	.set	reorder
	.end	start
	.cfi_endproc
$LFE0:
	.size	start, .-start
	.ident	"GCC: (GNU) 16.0.0 20250604 (experimental)"

diff --git a/c.s b/r.s
index f27ce13..350c65d 100644
--- a/c.s
+++ b/r.s
@@ -1,4 +1,4 @@
-	.file	1 "a0.c"
+	.file	1 "a0.rs"
 	.section .mdebug.abi32
 	.previous
 	.nan	legacy
@@ -8,21 +8,37 @@
 	.text
 	.align	2
 	.globl	start
+$LFB0 = .
+	.cfi_startproc
 	.set	nomips16
 	.set	nomicromips
 	.ent	start
 	.type	start, @function
 start:
-	.frame	$sp,0,$31		# vars= 0, regs= 0/0, args= 0, gp= 0
-	.mask	0x00000000,0
+	.frame	$sp,24,$31		# vars= 0, regs= 1/0, args= 16, gp= 0
+	.mask	0x80000000,-4
 	.fmask	0x00000000,0
 	.set	noreorder
 	.set	nomacro
-	j	call_with_a0
-	nop
+	addiu	$sp,$sp,-24
+	.cfi_def_cfa_offset 24
+	sw	$4,24($sp)
+	sw	$31,20($sp)
+	.cfi_offset 31, -4
+	jal	call_with_a0
+	move	$4,$5                                                   # <---- notable: move $a0, $a1 ..?
 
+	lw	$31,20($sp)
+	lw	$2,24($sp)
+	jr	$31
+	addiu	$sp,$sp,24
+
+	.cfi_def_cfa_offset 0
+	.cfi_restore 31
 	.set	macro
 	.set	reorder
 	.end	start
+	.cfi_endproc
+$LFE0:
 	.size	start, .-start
 	.ident	"GCC: (GNU) 16.0.0 20250604 (experimental)"

EDIT 1: Switch target from mips-unknown-netbsd to mips-elf, same results

EDIT 2: Remove c_void, use u8 pointers

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the reduced C and Rust examples with gccrs on the mips-elf target using the shown build and compiler flags. Compare the generated a0.c and a0.rs assembly, focusing on the call to call_with_a0 and its argument registers. Done means the Rust output passes the pointer in the same register as the equivalent C output.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.