-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Enable function-sections for ARM Thumb targets #37580
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @arielb1 (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
@japaric do you remember if this was intentionally omitted, or perhaps just an accident? |
Ah to clarify this looks good to me, thanks! Just want to understand if we intentionally omitted this or not. |
It was never brought up during the RFC. GCC says:
But, AFAICT, this seems to already be the case today. As in each functions gets its own text.$name section. @JinShil Do you have any measurements of how this affect binary size? |
/// Emit each function in its own section. Defaults to true.
pub function_sections: bool, |
Ah, that would explain my confusion for why functions would today be in their own sections. In that sense, @JinShil I'm curious what prompted this PR? Were the function sections not working for you? |
I'm seeing a lot of dead code in my binary after including formatted IO from core. Analyzing the binary with |
@JinShil How can you tell it's dead code? I'd like to know. And I'd like to know why Using formatting (e.g. I feel that the formatting machinery hasn't been optimized for code size. I'm going to blame the use trait objects and For the record, this is what Some numbers:
NOTE: Everything (including core) was compiled with opt-level=3 + LTO. opt-level=s and opt-level=z make only a small difference: just ~200 bytes smaller at most. Fun stuff:
I have no idea why those strings are in there. (Sorry for the rant) |
@japaric Yes that's exactly what I'm seeing, which led me to blame the lack of an explicit 'function_sections =true' in the target definition. I would expect those strings to be put in their own section and removed with '--gc-sections'. |
@japaric FWIW println has quite a bit of machinery:
The That's at least what's happening! |
@japaric But I guess the point you're making is that the code isn't actually dead. That may be true. I'm on the road for the next 48 hours, but when I get back I'll do a more thorough analysis. I obviously should have looked a little deeper before submitting thus PR. |
Could you say more about this? Are these strings not supposed to be in the I'm wondering if I'm doing something silly in my linker script that's preventing this stuff from being GCed away. I'll double check.
Have a safe trip!
👍 @alexcrichton I should have been more explicit. This is bare metal /
These are not present in my example.
I'm not unwrapping in my macro but simply ignoring the error because my
This is part I find odd. I'm compiling everything (including
Right, but I'm wondering how much optimizations trait objects are actually preventing; it seems they are forcing the compiler to not use inlining at all so the compiler "can't see" that the error path is never used in this particular case and drop branches, etc. There are probably tradeoffs in larger code bases that use different kinds of formatting. Some numbers on trait objects vs generics would be nice, specially now that we have opt-levels |
So after looking carefully, those function names that appear in the
What's left to test is (a) check if we can eliminate some |
That's actually due to the |
I was able to get back to this today. The following code... // compile with --emit obj and analyize with arm-none-eabi-objdump -s object_file.0.o
#![feature(no_core)]
#![feature(lang_items)]
#![no_core]
#![no_main]
//---------- Minimal Runtime ------------
#[lang = "sized"]
pub trait Sized { }
#[lang = "sync"]
pub trait Sync { }
#[lang = "copy"]
pub trait Copy { }
impl Sync for &'static str { }
//---------- Program Code ---------------
#[allow(dead_code)]
static READ_ONLY_STRING: &'static str = "This is a readonly string";
#[no_mangle]
#[allow(dead_code)]
pub fn function1() { }
#[no_mangle]
#[allow(dead_code)]
pub fn function2() { } ... produces the following object file.
So, it does look like the compiler is doing the right thing. You can see However, after linking, the final binary contains only a
It was this result that led me to believe that TL;DR |
Aha! Disregard me then!
Oh we print backtraces for both panic=abort and panic=unwind, compiling with panic=abort just removes the unwinding infrastructure for panics, not the backtrace portion.
It's true, yeah, and I'd love to dive more into the
I'd recommend (a) first as I suspect that will get us 99% of the way there. Option (b) may not be backwards compatible, unfortunately. |
I've open rust-embedded/wg#18 to work on this out of tree. Possibly experimenting with an implementation (different fmt traits?) that don't involve trait objects just to get an idea of how much it helps (if at all). |
For the ARM thumb targets, I think users would want
function-sections
enabled more often then not, given the importance of code size for these targets.Due to #26338 there doesn't appear to be a way to pass
-function-sections
and-data-sections
on the command line forrustc
.