Skip to content
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

Pre-RFC: Rust version of __attribute(used)__ (GCC) or llvm.used (LLVM). #1002

Closed
dpc opened this issue Mar 22, 2015 · 23 comments
Closed

Pre-RFC: Rust version of __attribute(used)__ (GCC) or llvm.used (LLVM). #1002

dpc opened this issue Mar 22, 2015 · 23 comments
Labels
T-lang Relevant to the language team, which will review and decide on the RFC.

Comments

@dpc
Copy link

dpc commented Mar 22, 2015

There come times when rust symbols are referenced only by external assembler, sometimes in not-trivial way. It seems rustc is eager to remove them (even making them public does not help).

In clang and gcc there are ways to prevent it: __attribute__((used)) and llvm.used

It seems there is currently no way to force rust to retain a symbol? Can it be added?

@dpc
Copy link
Author

dpc commented May 8, 2015

Please??? :D

@frehberg
Copy link

I need this feature as well. Is there any way to achieve this with latest rust-release? Do you know about #1459

@KalitaAlexey
Copy link

@frehberg Do you talk about function? You can use pub and it won't be removed.

@strega-nil
Copy link

@KalitaAlexey I don't believe statics are afforded the same protection.

@eddyb
Copy link
Member

eddyb commented Aug 12, 2016

@ubsan Anything exported can't ever be removed, so all you have to do is make it reachable from outside the crate. I'm not sure, but #[no_mangle] is likely to force export.

@strega-nil
Copy link

@eddyb Then I'm not sure what the point of llvm.used is?

@eddyb
Copy link
Member

eddyb commented Aug 12, 2016

@ubsan It probably works on internal/private items, to keep them alive despite them not being exported.

@strega-nil
Copy link

@eddyb ... weird.

@dpc
Copy link
Author

dpc commented Aug 12, 2016

I don't think people understand this topic fully.

First in embedded system, there are tricks, like creating an array of things, by just putting them in the same executable section. This symbols will not referenced anywhere explicitly. But they must keep being in the section.

Second it's not about symbols between crates/libraries. It's about LTO removing stuff during final linking optimization. These symbols are not referenced anywhere explicitly so optimizer can remove them. The code, at runtime will go from the start to the section to the end, read the memory in the given section and do something with all the symbols bytes there.

To be able to do that, the symbols need to be marked as used, otherwise LTO will remove them. That is the purpose of __attribute(used)__ (GCC) or llvm.used, and AFAIK, other tricks will not work.

@strega-nil
Copy link

@dpc Ah, 'k, that makes sense.

@eddyb
Copy link
Member

eddyb commented Aug 12, 2016

@dpc You can't use noop volatile assembly capturing the address of the global?

@dpc
Copy link
Author

dpc commented Aug 13, 2016

@eddyb: Nothing will reference that noop volatile assembly and LTO will remove that, and then the thing it referenced. :)

@strega-nil
Copy link

@dpc I don't believe volatile assembly can be removed, although I may be wrong.

@dpc
Copy link
Author

dpc commented Aug 13, 2016

The volatile prevents moves of memory accesses between before and after the volatile, removal of the asm code itself (ensuring it's side effects will take place, even if it return values are not used), and makes sure it will not be duplicated (no more than one-time side effects) - at least that was the guarantee in C, IIRC, similiar guarantees of access to volatile variables . However having volatile asm does not prevent dead code elimination on LTO to just strip the whole function altogether when linkers thinks the code/data is just never reached.

@eddyb
Copy link
Member

eddyb commented Aug 13, 2016

@dpc Whereas llvm.used will work even from dead code, or something?

@dpc
Copy link
Author

dpc commented Aug 14, 2016

@eddyb Yes. The llvm.used is specifically meant to make a piece of data/code appear used for purpose of dead code elimination.

@eddyb
Copy link
Member

eddyb commented Aug 14, 2016

Oh, I wish someone had linked to the documentation for llvm.used - it's not an intrinsic function you call, but a global variable listing all of the functions/globals in the LLVM module you want to keep.

@frehberg
Copy link

My use case is: I want to place a buildtag string onto the main-stack of the process, so it will appear in any core-dumps and can be extracted from core-dump. So far un-used string variables within main() are eliminated, so I have got to println it to keep it on the stack (any hint helpful). Code might look like:

fn main() {
let buildtag = concat!("Tag", "=", "2016-WK16-BLD5");
println!("{}", buildtag);

Any idea, how I could get away with the println but keep the variable buildtag on the stack?

@eddyb
Copy link
Member

eddyb commented Aug 14, 2016

@frehberg Since you have non-dead code that you use the value from, you could use inline assembly to force LLVM to keep a variable alive. Alternatively, a noop C function via FFI.

@JinShil
Copy link
Contributor

JinShil commented Oct 23, 2016

I am in need of this feature as well. As @dpc mentioned I need this for my embedded systems. I've tried the workarounds in this comment, but none worked. Do the powers that be understand the use case here?

@japaric
Copy link
Member

japaric commented Feb 20, 2017

I've send a PR implementing this in rust-lang/rust#39987. I'd like to hear about what use cases people have in mind for this (apart from the one mentioned in the PR description). Please leave a comment on that PR.

frewsxcv added a commit to frewsxcv/rust that referenced this issue Mar 9, 2017
[RFC] #[used] attribute

(For an explanation of what this feature does, read the commit message)

I'd like to propose landing this as an experimental feature (experimental as in:
no clear stabilization path -- like `asm!`, `#[linkage]`) as it's low
maintenance (I think) and relevant to the "Usage in resource-constrained
environments" exploration area.

The main use case I see is running code before `main`. This could be used, for
instance, to cheaply initialize an allocator before `main` where the alternative
is to use `lazy_static` to initialize the allocator on its first use which it's
more expensive (atomics) and doesn't work on ARM Cortex-M0 microcontrollers (no
`AtomicUsize` on that platform)

Here's a `std` example of that:

``` rust

unsafe extern "C" fn before_main_1() {
    println!("Hello");
}

unsafe extern "C" fn before_main_2() {
    println!("World");
}

static INIT_ARRAY: [unsafe extern "C" fn(); 2] = [before_main_1, before_main_2];

fn main() {
    println!("Goodbye");
}
```

```
$ rustc -C lto -C opt-level=3 before_main.rs
$ ./before_main
Hello
World
Goodbye
```

In general, this pattern could be used to let *dependencies* run code before
`main` (which sounds like it could go very wrong in some cases). There are
probably other use cases; I hope that the people I have cc-ed can comment on
those.

Note that I'm personally unsure if the above pattern is something we want to
promote / allow and that's why I'm proposing this feature as experimental. If
this leads to more footguns than benefits then we can just axe the feature.

cc @nikomatsakis ^ I know you have some thoughts on having a process for
experimental features though I'm fine with writing an RFC before landing this.

- `dead_code` lint will have to be updated to special case `#[used]` symbols.

- Should we extend `#[used]` to work on non-generic functions?

cc rust-lang/rfcs#1002
cc rust-lang/rfcs#1459
cc @dpc @JinShil
frewsxcv added a commit to frewsxcv/rust that referenced this issue Apr 6, 2017
[RFC] #[used] attribute

(For an explanation of what this feature does, read the commit message)

I'd like to propose landing this as an experimental feature (experimental as in:
no clear stabilization path -- like `asm!`, `#[linkage]`) as it's low
maintenance (I think) and relevant to the "Usage in resource-constrained
environments" exploration area.

The main use case I see is running code before `main`. This could be used, for
instance, to cheaply initialize an allocator before `main` where the alternative
is to use `lazy_static` to initialize the allocator on its first use which it's
more expensive (atomics) and doesn't work on ARM Cortex-M0 microcontrollers (no
`AtomicUsize` on that platform)

Here's a `std` example of that:

``` rust

unsafe extern "C" fn before_main_1() {
    println!("Hello");
}

unsafe extern "C" fn before_main_2() {
    println!("World");
}

static INIT_ARRAY: [unsafe extern "C" fn(); 2] = [before_main_1, before_main_2];

fn main() {
    println!("Goodbye");
}
```

```
$ rustc -C lto -C opt-level=3 before_main.rs
$ ./before_main
Hello
World
Goodbye
```

In general, this pattern could be used to let *dependencies* run code before
`main` (which sounds like it could go very wrong in some cases). There are
probably other use cases; I hope that the people I have cc-ed can comment on
those.

Note that I'm personally unsure if the above pattern is something we want to
promote / allow and that's why I'm proposing this feature as experimental. If
this leads to more footguns than benefits then we can just axe the feature.

cc @nikomatsakis ^ I know you have some thoughts on having a process for
experimental features though I'm fine with writing an RFC before landing this.

- `dead_code` lint will have to be updated to special case `#[used]` symbols.

- Should we extend `#[used]` to work on non-generic functions?

cc rust-lang/rfcs#1002
cc rust-lang/rfcs#1459
cc @dpc @JinShil
frewsxcv added a commit to frewsxcv/rust that referenced this issue Apr 6, 2017
(For an explanation of what this feature does, read the commit message)

I'd like to propose landing this as an experimental feature (experimental as in:
no clear stabilization path -- like `asm!`, `#[linkage]`) as it's low
maintenance (I think) and relevant to the "Usage in resource-constrained
environments" exploration area.

The main use case I see is running code before `main`. This could be used, for
instance, to cheaply initialize an allocator before `main` where the alternative
is to use `lazy_static` to initialize the allocator on its first use which it's
more expensive (atomics) and doesn't work on ARM Cortex-M0 microcontrollers (no
`AtomicUsize` on that platform)

Here's a `std` example of that:

``` rust

unsafe extern "C" fn before_main_1() {
    println!("Hello");
}

unsafe extern "C" fn before_main_2() {
    println!("World");
}

static INIT_ARRAY: [unsafe extern "C" fn(); 2] = [before_main_1, before_main_2];

fn main() {
    println!("Goodbye");
}
```

```
$ rustc -C lto -C opt-level=3 before_main.rs
$ ./before_main
Hello
World
Goodbye
```

In general, this pattern could be used to let *dependencies* run code before
`main` (which sounds like it could go very wrong in some cases). There are
probably other use cases; I hope that the people I have cc-ed can comment on
those.

Note that I'm personally unsure if the above pattern is something we want to
promote / allow and that's why I'm proposing this feature as experimental. If
this leads to more footguns than benefits then we can just axe the feature.

cc @nikomatsakis ^ I know you have some thoughts on having a process for
experimental features though I'm fine with writing an RFC before landing this.

- `dead_code` lint will have to be updated to special case `#[used]` symbols.

- Should we extend `#[used]` to work on non-generic functions?

cc rust-lang/rfcs#1002
cc rust-lang/rfcs#1459
cc @dpc @JinShil
frewsxcv added a commit to frewsxcv/rust that referenced this issue Apr 7, 2017
(For an explanation of what this feature does, read the commit message)

I'd like to propose landing this as an experimental feature (experimental as in:
no clear stabilization path -- like `asm!`, `#[linkage]`) as it's low
maintenance (I think) and relevant to the "Usage in resource-constrained
environments" exploration area.

The main use case I see is running code before `main`. This could be used, for
instance, to cheaply initialize an allocator before `main` where the alternative
is to use `lazy_static` to initialize the allocator on its first use which it's
more expensive (atomics) and doesn't work on ARM Cortex-M0 microcontrollers (no
`AtomicUsize` on that platform)

Here's a `std` example of that:

``` rust

unsafe extern "C" fn before_main_1() {
    println!("Hello");
}

unsafe extern "C" fn before_main_2() {
    println!("World");
}

static INIT_ARRAY: [unsafe extern "C" fn(); 2] = [before_main_1, before_main_2];

fn main() {
    println!("Goodbye");
}
```

```
$ rustc -C lto -C opt-level=3 before_main.rs
$ ./before_main
Hello
World
Goodbye
```

In general, this pattern could be used to let *dependencies* run code before
`main` (which sounds like it could go very wrong in some cases). There are
probably other use cases; I hope that the people I have cc-ed can comment on
those.

Note that I'm personally unsure if the above pattern is something we want to
promote / allow and that's why I'm proposing this feature as experimental. If
this leads to more footguns than benefits then we can just axe the feature.

cc @nikomatsakis ^ I know you have some thoughts on having a process for
experimental features though I'm fine with writing an RFC before landing this.

- `dead_code` lint will have to be updated to special case `#[used]` symbols.

- Should we extend `#[used]` to work on non-generic functions?

cc rust-lang/rfcs#1002
cc rust-lang/rfcs#1459
cc @dpc @JinShil
bors added a commit to rust-lang/rust that referenced this issue Apr 7, 2017
#[used] attribute

(For an explanation of what this feature does, read the commit message)

I'd like to propose landing this as an experimental feature (experimental as in:
no clear stabilization path -- like `asm!`, `#[linkage]`) as it's low
maintenance (I think) and relevant to the "Usage in resource-constrained
environments" exploration area.

The main use case I see is running code before `main`. This could be used, for
instance, to cheaply initialize an allocator before `main` where the alternative
is to use `lazy_static` to initialize the allocator on its first use which it's
more expensive (atomics) and doesn't work on ARM Cortex-M0 microcontrollers (no
`AtomicUsize` on that platform)

Here's a `std` example of that:

``` rust

unsafe extern "C" fn before_main_1() {
    println!("Hello");
}

unsafe extern "C" fn before_main_2() {
    println!("World");
}

#[link_section = ".init_arary"]
#[used]
static INIT_ARRAY: [unsafe extern "C" fn(); 2] = [before_main_1, before_main_2];

fn main() {
    println!("Goodbye");
}
```

```
$ rustc -C lto -C opt-level=3 before_main.rs
$ ./before_main
Hello
World
Goodbye
```

In general, this pattern could be used to let *dependencies* run code before
`main` (which sounds like it could go very wrong in some cases). There are
probably other use cases; I hope that the people I have cc-ed can comment on
those.

Note that I'm personally unsure if the above pattern is something we want to
promote / allow and that's why I'm proposing this feature as experimental. If
this leads to more footguns than benefits then we can just axe the feature.

cc @nikomatsakis ^ I know you have some thoughts on having a process for
experimental features though I'm fine with writing an RFC before landing this.

- `dead_code` lint will have to be updated to special case `#[used]` symbols.

- Should we extend `#[used]` to work on non-generic functions?

cc rust-lang/rfcs#1002
cc rust-lang/rfcs#1459
cc @dpc @JinShil
@mjbshaw
Copy link
Contributor

mjbshaw commented Dec 21, 2017

Thanks @japaric for implementing this!

I'd love to see this feature stabilized, as #[used] is the only feature in my code that's requiring me to use the nightly toolchain instead of stable. Have there been any updates or discussions on stabilizing this? Should a previous RFC attempt be revived?

@Centril Centril added the T-lang Relevant to the language team, which will review and decide on the RFC. label Feb 23, 2018
@Centril
Copy link
Contributor

Centril commented Oct 7, 2018

#[used] is now stabilized. Closing therefore as completed.

@Centril Centril closed this as completed Oct 7, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-lang Relevant to the language team, which will review and decide on the RFC.
Projects
None yet
Development

No branches or pull requests

9 participants