This commit follows the same logic as:
- https://github.com/rust-lang/compiler-builtins/pull/462
- https://github.com/rust-lang/compiler-builtins/pull/466
I've tested the changes by preparing a simple program:
```rust
fn calc() -> ... {
let x = hint::black_box(4u...); // 4u8, 4u16, 4u32, 4u64, 4u128 + signed
let y = hint::black_box(1u32);
// x >> y
// x << y
}
fn main() -> ! {
let dp = arduino_hal::Peripherals::take().unwrap();
let pins = arduino_hal::pins!(dp);
let mut serial = arduino_hal::default_serial!(dp, pins, 57600);
for b in calc().to_le_bytes() {
_ = ufmt::uwrite!(&mut serial, "{} ", b);
}
_ = ufmt::uwriteln!(&mut serial, "");
loop {
//
}
}
```
... switching types & operators in `calc()`, and observing the results;
what I ended up with was:
```
u32 << u32 - ok
u64 << u32 - ok
u128 << u32 - error (undefined reference to `__ashlti3')
i32 >> u32 - ok
i64 >> u32 - ok
i128 >> u32 - error (undefined reference to `__ashrti3')
u32 >> u32 - ok
u64 >> u32 - ok
u128 >> u32 - error (undefined reference to `__lshrti3')
(where "ok" = compiles and returns correct results)
```
As with multiplication and division, so do in here 128-bit operations
not work, because avr-gcc's standard library doesn't provide them (at
the same time, requiring that specific calling convention, making it
pretty difficult for compiler-builtins to jump in).
I think 128-bit operations non-working on an 8-bit controller is an
acceptable trade-off - 😇 - and so the entire fix in here is
just about skipping those functions.
int_util.c includes stdlib.h if `_WIN32` is defined. When compiling
the UEFI targets with clang they are treated as Windows targets (e.g. if
the Rust target is x86_64-unknown-uefi, the clang target is
x86_64-unknown-windows-gnu). So stdlib.h gets included, even though we
are compilling with `-ffreestanding` and don't want stdlib.h to be
used. That file may not be present, or an incompatible version might be
installed leading to typedef redefinition errors.
The contents of stdlib.h aren't actually needed for these targets anyway
(due to `__STDC_HOSTED__` being 0), so create a minimal stdlib.h in
`build.rs` when `target_os == uefi` and add it to the include path.
The UEFI targets link with `/SAFESEH`. That requires that objects have a
symbol called [`@feat.00`]. Clang adds that symbol for COFF targets if
the input is a C file, but not if the input is an ASM file. That doesn't
prevent compiler_builtins or rustc from building, but using the
resulting rustc to compile something that references one of the objects
lacking `@feat.00` will result in a linker error.
Fix by removing all the `.S` implementations when `target_os == uefi`.
[`@feat.00`]: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#the-sxdata-section