-
Notifications
You must be signed in to change notification settings - Fork 243
Open
Labels
compiler-bugNot a bug in avr-hal, but a bug in the rust compiler/LLVMNot a bug in avr-hal, but a bug in the rust compiler/LLVM
Description
Somewhat related to Rahix/avr-device#190
and rust-lang/rust#141260 (@LuigiPiucco )
I discovered this in a normal avr-device program: https://github.com/tomtor/avr-modern-rust
and rewrote it to a minimal program to demonstrate the issue:
#![no_std]
#![no_main]
// const IO: u16 = 0x1; // this value generated bad code
const IO: u16 = 0x2; // this value generates good code
const VPORTA: *mut u8 = (IO) as *mut u8;
const LED: u8 = 0b1000_0000; // PA7
pub fn high_vp(b: u8) {
unsafe {
*VPORTA = *VPORTA | b;
}
}
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
loop {}
}
// the body of the next function is nonsense and irrelevant, we just need some code which is not inlined
pub fn nil(a: u16) {
let mut i: u16 = 0;
while i < 100 {
high_vp(LED);
nil(a - 1);
i += 1;
}
}
#[avr_device::entry]
//#[cortex_m_rt::entry]
fn main() -> ! {
let mut counter: u16 = 0;
loop {
counter += 1;
// The following line produces incorrect code: !!!
high_vp(LED);
nil((counter & 0xf) + IO);
}
}
this generates the following excellent code:
00000094 <_ZN15avr_modern_demo20__avr_device_rt_main17h009e886c0b40ab89E>:
94: 0f 93 push r16
96: 1f 93 push r17
98: 80 e0 ldi r24, 0x00 ; 0
9a: 90 e0 ldi r25, 0x00 ; 0
9c: 17 9a sbi 0x02, 7 ; 2
9e: 01 96 adiw r24, 0x01 ; 1
a0: 8c 01 movw r16, r24
a2: 8f 70 andi r24, 0x0F ; 15
a4: 90 70 andi r25, 0x00 ; 0
a6: 02 96 adiw r24, 0x02 ; 2
a8: 0e 94 2b 00 call 0x56 ; 0x56 <_ZN15avr_modern_demo3nil17h6637efea0a821bd7E>
ac: c8 01 movw r24, r16
ae: f6 cf rjmp .-20 ; 0x9c <_ZN15avr_modern_demo20__avr_device_rt_main17h009e886c0b40ab89E+0x8>
however, if we use 0x1 instead of 0x2 we get:
00000096 <_ZN15avr_modern_demo20__avr_device_rt_main17h009e886c0b40ab89E>:
96: 0f 93 push r16
98: 1f 93 push r17
9a: a0 e0 ldi r26, 0x00 ; 0
9c: b0 e0 ldi r27, 0x00 ; 0
9e: 8d 91 ld r24, X+
a0: 80 68 ori r24, 0x80 ; 128
a2: 8d 01 movw r16, r26
a4: af 70 andi r26, 0x0F ; 15
a6: b0 70 andi r27, 0x00 ; 0
a8: 8d 93 st X+, r24
aa: cd 01 movw r24, r26
ac: 0e 94 2b 00 call 0x56 ; 0x56 <_ZN15avr_modern_demo3nil17h6637efea0a821bd7E>
b0: d8 01 movw r26, r16
b2: f5 cf rjmp .-22 ; 0x9e <_ZN15avr_modern_demo20__avr_device_rt_main17h009e886c0b40ab89E+0x8>
The varying argument to nil() is used to store the new contents at 0x1 which is only correct for the first iteration of the loop!
Metadata
Metadata
Assignees
Labels
compiler-bugNot a bug in avr-hal, but a bug in the rust compiler/LLVMNot a bug in avr-hal, but a bug in the rust compiler/LLVM