Skip to content

Incorrect relative jump (rjmp) code generation in latest nightly release for AVR toolchain #129301

Description

I've already asked this question on stack exchange where you can see more details.

I tried the following code:

#![no_std]
#![no_main]
#![feature(asm_experimental_arch)]

use core::{arch::asm, hint::black_box, panic::PanicInfo};

use avrd::atmega328p;

#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
    loop {}
}

#[inline(never)]
fn delay(x: u32) {
    for _ in 0..x {
        unsafe {
            asm!("nop");
        }
    }
}

unsafe fn write_reg(reg: *mut u8, val: u8, mask: u8) {
    let reg_val = reg.read_volatile();
    reg.write_volatile((reg_val & !mask) | (val & mask));
}

#[no_mangle]
extern "C" fn main() -> ! {
    const LED_BUILTIN: u8 = 5;
    unsafe {
        let portB_data_direction = atmega328p::DDRB;
        // set it to output mode
        write_reg(portB_data_direction, 1 << LED_BUILTIN, 1 << LED_BUILTIN);
        let portB = atmega328p::PORTB;
        // switch it on, hopefully..
        loop {
            write_reg(portB, 1 << LED_BUILTIN, 1 << LED_BUILTIN);
            delay(500_0000);
            write_reg(portB, 0, 1 << LED_BUILTIN);
            delay(500_0000);
        }
    }
}

The RUSTFLAGS="--emit asm" output is also correct, but the machine code generated is faulty. For now I've switched to nightly-2023-12-11, which seems to work just fine.

For the disassembly of both the --emit asm and the final binary, you can refer to the stack exchange post.
Here's a minimal example that doesn't work on nightly (but works on nightly-2023-12-11):

#![no_std]
#![no_main]

use core::{hint::black_box, panic::PanicInfo};

use avrd::atmega328p;

#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
    loop {}
}

#[no_mangle]
extern "C" fn main() -> ! {
    const LED_BUILTIN: u8 = 5;
    unsafe {
        let portB_data_direction = atmega328p::DDRB;
        // set it to output mode
        *portB_data_direction |= 1 << LED_BUILTIN;
        let portB = atmega328p::PORTB;

        loop {
            *portB ^= 1 << LED_BUILTIN;
            for i in 0..500_000 {
                black_box(i);
            }
            *portB ^= 1 << LED_BUILTIN;
            for i in 0..500_000 {
                black_box(i);
            }
        }
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

Labels

A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.A-codegenArea: Code generationArea: Code generationA-inline-assemblyArea: Inline assembly (`asm!(…)`)Area: Inline assembly (`asm!(…)`)C-bugCategory: This is a bug.Category: This is a bug.E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.Call for participation: An issue has been fixed and does not reproduce, but no test has been added.F-asm`#![feature(asm)]` (not `llvm_asm`)`#![feature(asm)]` (not `llvm_asm`)I-miscompileIssue: Correct Rust code lowers to incorrect machine codeIssue: Correct Rust code lowers to incorrect machine codeO-AVRTarget: AVR processors (ATtiny, ATmega, etc.)Target: AVR processors (ATtiny, ATmega, etc.)T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions