-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Add cfg(no_128_bit) to core: removes u128/i128 formatting #103126
Conversation
r? @scottmcm (rust-highfive has picked a reviewer for you, use r? to override) |
// fail or panic, but for an application which has specifically | ||
// recompiled core to avoid i128, the former seems unnecessary | ||
// and the latter needlessly harmful. | ||
f.write_str(stringify!($T)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is an i128/u128 impl necessary in the first place?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question; I haven’t tried removing it. I think it’s conventional to provide Debug
for everything public in the standard library; not sure if that could be waived in this case?
I believe u128 is also used in some of the Duration methods before casting to floats. Maybe these methods should be removed too? |
I considered trying to rip it out more thoroughly and produce a core library which cannot use these functions, but that would be quite hard to maintain and test, not least because the operations which compile to these functions are LLVM’s choice and platform-specific. E.g. there doesn’t appear to be one for addition. My understanding is that usage in an inline or generic method is OK because that doesn’t end up in the finished binaries unless used, so the formatting and parsing code (which isn’t inlined) is what matters. |
This comment has been minimized.
This comment has been minimized.
This seems like a policy decision to me, so I'm going to flip it over to |
I've tried measuring the impact of this PR onto the generated libdemo.a file in the added test. For that I've manually applied this PR to my local rustc checkout, and ran the command:
To get the state before the PR, I did:
To turn on optimizations, I added
IIRC kernels usually get deployed without debuginfo, and are usually compiled with optimizations, so the last line is probably the most relevant. 32 kilobytes of savings correspond to about 1.9% relative to the 1696 kb. I've also tried out the already existing floating point number cfg, this time with this patch applied, but not with the flag to turn off 128 bit numbers enabled.
So float parsing/formatting has about 340 kb of savings, or 20% of the 1696 binary. It makes total sense that floats take up more space because their formatting code is way more complicated. As the second difference between floats and 128 bit numbers, floats require the FPU to be around so are an absolute no-no in kernel space. For 128 bit numbers, they shouldn't use any special hardware so should in theory be able to run in the kernel... the reason to avoid them is just the impact on the binary size I think? Not a kernel person, but it seems that the kernel already uses GCC's I think this PR makes sense, even if the impact is rather small compared to turning off float formatting, and 128 bit numbers are "just" integers, so don't require any special hardware outside of CPU, registers and memory. |
Nit: floats can be used where available, but it is still good to be able to remove them when not used (see below).
In general, everything that can reasonably be removed should be so (conditionally depending on the kernel configuration, in many cases), but this does not mean the features are never used by any configuration. In addition, even if the kernel does not use something in any config today, that itself may change over time, e.g. see The road to Zettalinux by willy. When I made the original list long ago, I picked a few "big" things that I could think of, but really, the more that we can configure in/out, the better (just like the kernel itself). I imagined other use cases (i.e. outside the Linux kernel) would also appreciate these options too. For instance, in embedded, constrained devices, every saved text page is welcome, and could open Rust for more use cases. Security-wise, it is also a good idea to avoid dead code. And perhaps in some safety-critical systems it may facilitate the process. For some of these use cases it may be possible to strip things out after compilation, but probably not for all of them, at least as-is/easily (e.g. in the kernel we support external modules, so we export So all effort towards what I called "modularization of |
740cfa7
to
8122fb6
Compare
This comment has been minimized.
This comment has been minimized.
@rustbot ready |
Hey! It looks like you've submitted a new PR for the library teams! If this PR contains changes to any Examples of
|
☔ The latest upstream changes (presumably #108286) made this pull request unmergeable. Please resolve the merge conflicts. |
Ah, so this is waiting on a team decision? I'll add the label. |
@@ -62,6 +62,7 @@ macro_rules! int_impl { | |||
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_str_radix(\"A\", 16), Ok(10));")] | |||
/// ``` | |||
#[stable(feature = "rust1", since = "1.0.0")] | |||
$( #[$intrinsics_cfg] )? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is doing more than just controlling the removal of formatting: this function is about parsing. If not called, the function should not be included by the linker, different to what's happening to stuff called by the fmt machinery that is always included the moment anything that uses the fmt machinery is included.
@@ -166,13 +169,15 @@ nonzero_integers! { | |||
#[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16); | |||
#[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32); | |||
#[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU64(u64); | |||
#[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU128(u128); | |||
#[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] | |||
#[cfg(not(no_128_bit))] NonZeroU128(u128); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, I don't think it should be cfg'd out in this PR.
We discussed this in the libs meeting today and we are not inclined the add more opt-out configuration flags. The current set is already questionable and doesn't have a path to specialization. While I can appreciate the concerns about binary size for the Linux kernel, this is fundamentally a problem caused by the way Linux does dynamic linking of modules, which prevents the linker from eliminating unused symbols. As such, this flag is not useful for the majority of embedded projects which use static linking. The existing @rfcbot fcp close |
Team member @Amanieu has proposed to close this. The next step is review by the rest of the tagged team members: No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
The final comment period, with a disposition to close, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. |
This is the
u128
/i128
equivalent of #86048, which removed floating point formatting from the core library oncfg(no_fp_fmt_parse)
.The purpose of this option is to permit linking with a custom
compiler-builtins
which does not support 128-bit integers. (Or nocompiler-builtins
at all, if some other source ofmemcpy
etc. is available, although this patch alone is not necessarily sufficient for that). This is a situation that the Linux kernel is in; see https://github.com/torvalds/linux/blob/2df76606db9de579bc96725981db4e8daa281993/rust/compiler_builtins.rs#L51-L63 which is a customcompiler-builtins
which just panics on everything. (NB that I am not involved in the Linux kernel efforts myself.)<i128 as Debug>::fmt
is defined to outputi128
, rather than panic as #86048 does on floats. No other formatting is supported.Test for this is by generating a static library linked to
core
but not tocompiler-builtins
and verifying that it does not have any dependencies on 128-bit compiler-rt functions with objdump. Using 128-bit division (etc.) is not forbidden by this patch so user code may still cause calls to these functions; it is up to users to decide what they want to do in this case, as Rust can't know exactly which operations on which architectures will require compiler-builtins. Users will see a linker error if they try operations which do, so I don't believe that to be a soundness issue.Linked issues: Rust-for-Linux/linux#514.