Skip to content

RefCell::borrow_mut codegen broken on ARM #40738

@krdln

Description

@krdln

I was trying to compile some programs on my armv7l machine and noticed that most programs using regex crate do panic. I've managed to narrow down the issue to a RefCell::borrow_mut call.

Test program:

use std::cell::RefCell;
fn main() {
    let cell = RefCell::new(1);
    cell.borrow_mut();
    cell.borrow_mut();
}

Versions of Rust tested (installed using rustup, the exact toolchain is nightly-armv7-unknown-linux-gnueabihf, etc.):

> rustc +stable --version
rustc 1.16.0 (30cf806ef 2017-03-10)
> rustc +beta --version
rustc 1.17.0-beta.2 (b7c276653 2017-03-20)
> rustc +nightly --version
rustc 1.17.0-nightly (cab4bff3d 2017-03-21)

This program works correctly on stable, but on beta and nightly fails with the following backtrace:

thread 'main' panicked at 'already borrowed: BorrowMutError', /checkout/src/libcore/result.rs:859
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
stack backtrace:
   0: <core::result::Result<T, E>>::expect
             at /checkout/src/libcore/result.rs:761
   1: <core::cell::RefCell<T>>::borrow_mut
             at /checkout/src/libcore/cell.rs:736
   2: bm_test::main
             at ./bm_test.rs:5

What's quite interesting is that the error is not present when cross-compiling from x86-64 to arm.

I've checked the generated assembly, and found a suspicious difference. For this function:

pub fn bm_once(cell: &RefCell<i32>) {
    cell.borrow_mut();
}

the generated assembly on stable (rustc -O) (or when cross-compiling using any version) is:

	.section	.text._ZN9borrowmut7bm_once17h7c1ef392d62ede16E,"ax",%progbits
	.globl	borrowmut::bm_once
	.p2align	2
	.type	borrowmut::bm_once,%function
borrowmut::bm_once:
	.fnstart
	ldr	r1, [r0]
	cmp	r1, #0
	moveq	r1, #0     // on beta: mvneq r1, #0
	streq	r1, [r0]
	bxeq	lr
	.save	{r11, lr}
	push	{r11, lr}
	bl	core::result::unwrap_failed
.Lfunc_end2:
	.size	borrowmut::bm_once, .Lfunc_end2-borrowmut::bm_once
	.fnend

The wrong assembly for beta and nightly differs only by one instruction – mvneq instead of moveq.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions