-
Notifications
You must be signed in to change notification settings - Fork 71
AVR support #406
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
When I build the sysroot in release mode, dev is not affected, I get the following crash from libgccjit...
The error happens at |
Thanks for reporting this. Do I need to use your for to reproduce this error? |
I think so, the error appeared in an RTL combine pass and it mentions an AVR source. Also you might need the {
"arch": "avr",
"atomic-cas": false,
"cpu": "atmega328p",
"data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8",
"eh-frame-header": false,
"exe-suffix": ".elf",
"executables": true,
"late-link-args": {
"gcc": [
"-lc",
"-lgcc"
]
},
"linker": "avr-gcc",
"linker-flavor": "gcc",
"linker-is-gnu": true,
"llvm-target": "avr-unknown-unknown",
"max-atomic-width": 0,
"no-default-libraries": false,
"pre-link-args": {
"gcc": [
"-Os",
"-mmcu=atmega328p",
"-Wl,--as-needed"
]
},
"relocation-model": "static",
"target-c-int-width": "16",
"target-endian": "little",
"target-pointer-width": "16"
} And then compile with:
If we cannot find anything then we can create a GCC Bugzilla ticket. |
Thanks. In the mean time, if you could find a small reproducer (small |
Here's a reproducer with an adapted #![no_std]
#![no_main]
#![feature(maybe_uninit_slice)]
use core::{
fmt,
hint,
mem::MaybeUninit,
panic,
ptr,
slice,
str,
};
static DEC_DIGITS_LUT: &[u8; 200] = b"0001020304050607080910111213141516171819\
2021222324252627282930313233343536373839\
4041424344454647484950515253545556575859\
6061626364656667686970717273747576777879\
8081828384858687888990919293949596979899";
pub fn fmt_u32(mut n: u32, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// 2^128 is about 3*10^38, so 39 gives an extra byte of space
let mut buf = [MaybeUninit::<u8>::uninit(); 39];
let mut curr = buf.len();
let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf);
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
// SAFETY: Since `d1` and `d2` are always less than or equal to `198`, we
// can copy from `lut_ptr[d1..d1 + 1]` and `lut_ptr[d2..d2 + 1]`. To show
// that it's OK to copy into `buf_ptr`, notice that at the beginning
// `curr == buf.len() == 39 > log(n)` since `n < 2^128 < 10^39`, and at
// each step this is kept the same as `n` is divided. Since `n` is always
// non-negative, this means that `curr > 0` so `buf_ptr[curr..curr + 1]`
// is safe to access.
unsafe {
// need at least 16 bits for the 4-characters-at-a-time to work.
assert!(core::mem::size_of::<u32>() >= 2);
// eagerly decode 4 characters at a time
while n >= 10000 {
let rem = (n % 10000) as usize;
n /= 10000;
let d1 = (rem / 100) << 1;
let d2 = (rem % 100) << 1;
curr -= 4;
// We are allowed to copy to `buf_ptr[curr..curr + 3]` here since
// otherwise `curr < 0`. But then `n` was originally at least `10000^10`
// which is `10^40 > 2^128 > n`.
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
ptr::copy_nonoverlapping(lut_ptr.add(d2), buf_ptr.add(curr + 2), 2);
}
// if we reach here numbers are <= 9999, so at most 4 chars long
let mut n = n as usize; // possibly reduce 64bit math
// decode 2 more chars, if > 2 chars
if n >= 100 {
let d1 = (n % 100) << 1;
n /= 100;
curr -= 2;
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
}
// decode last 1 or 2 chars
if n < 10 {
curr -= 1;
*buf_ptr.add(curr) = (n as u8) + b'0';
} else {
let d1 = n << 1;
curr -= 2;
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
}
}
// SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid
// UTF-8 since `DEC_DIGITS_LUT` is
let buf_slice = unsafe {
str::from_utf8_unchecked(
slice::from_raw_parts(buf_ptr.add(curr), buf.len() - curr))
};
f.pad_integral(is_nonnegative, "", buf_slice)
}
struct Qux(pub u32);
impl fmt::Debug for Qux {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_u32(self.0, true, f)
}
}
#[export_name = "main"]
fn main() {
panic!("{:?}", Qux(0));
}
#[panic_handler]
pub fn panic(_info: &panic::PanicInfo) -> ! {
unsafe { hint::unreachable_unchecked() }
} |
Thanks! I'll look at that in the coming weeks. |
I've found the source of the errors, it happens at those |
Ok, from what I've found the bug appears when rustc_codegen_gcc/src/builder.rs Lines 1079 to 1088 in 70586a2
We can see two things here, one is that the destination pointer gets casted into Either this ICE is produced by the lack of align handling, otherwise done at compile and run time whe |
You could try casting the pointers like it is done for Otherwise, I might be able to take a look in a couple of weeks. |
Also, maybe I could be able to help sooner if you post the lines around 2705 in the file |
The file in my clone has that length too, I haven't modified it, what happens is that it gets processed by an utility, When a function that uses |
I've noticed that the type gets downcasted from pub fn fmt_u32(mut n: u32, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// 2^128 is about 3*10^38, so 39 gives an extra byte of space
let mut buf = [MaybeUninit::<u8>::uninit(); 39];
let mut curr = buf.len();
let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf);
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
unsafe {
while n >= 100 {
let d1 = (n % 7) as usize;
n /= 7;
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
}
}
let buf_slice = unsafe {
str::from_utf8_unchecked(
slice::from_raw_parts(buf_ptr.add(curr), buf.len() - curr))
};
f.pad_integral(is_nonnegative, "", buf_slice)
} The issue pops up with the loop. while n >= 100 {
let d1 = (n % 7) as usize;
n /= 7;
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
} Observe that the number that is used to divide In conclusion, this is likely to be a bug with GCC so we might have to workaround it. |
Found a fix to the issue, it was an upstream bug with how |
I'm in the process of rebasing my GCC fork. Hopefully, this should finish soon. |
The rebase is done. Can you please test to see if the issue is fixed? |
It worked, thanks for the rebase. |
Volatile loads and stores was implemented in #572 and rust-lang/gcc@50d1270, please tell me if that works for you. |
This is mainly motivated due to size issues when using LLVM when AVR is targeted.
I have partial support for it in my forks (gcc, gccjit.rs, rustc_codegen_gcc, but there are a few features needed and some issues to be addressed.
Features needed:
-m
) in libgccjit.sysroot
should only depend oncore
andalloc
for AVR.Issues to be fixed:
atmega328p
, fails with an error message.$GCC_EXEC_PATH
needs to be set for it to pickdevice-specs
at the correct location (lib/gcc/avr/<gcc version>
).avr-objcopy -O ihex
are way bigger than C.The text was updated successfully, but these errors were encountered: