提交 7ee72070 编写于 作者: B bors

Auto merge of #51363 - japaric:stable-used, r=cramertj

stabilize #[used]

closes #40289

RFC for stabilization: rust-lang/rfcs#2386

r? @Centril

Where should this be documented? Currently the documentation is in the unstable book
# `used`
The tracking issue for this feature
is: [40289](https://github.com/rust-lang/rust/issues/40289).
------------------------
The `#[used]` attribute can be applied to `static` variables to prevent the Rust
compiler from optimizing them away even if they appear to be unused by the crate
(appear to be "dead code").
``` rust
#![feature(used)]
#[used]
static FOO: i32 = 1;
static BAR: i32 = 2;
fn main() {}
```
If you compile this program into an object file, you'll see that `FOO` makes it
to the object file but `BAR` doesn't. Neither static variable is used by the
program.
``` text
$ rustc -C opt-level=3 --emit=obj used.rs
$ nm -C used.o
0000000000000000 T main
U std::rt::lang_start
0000000000000000 r used::FOO
0000000000000000 t used::main
```
Note that the *linker* knows nothing about the `#[used]` attribute and will
remove `#[used]` symbols if they are not referenced by other parts of the
program:
``` text
$ rustc -C opt-level=3 used.rs
$ nm -C used | grep FOO
```
"This doesn't sound too useful then!" you may think but keep reading.
To preserve the symbols all the way to the final binary, you'll need the
cooperation of the linker. Here's one example:
The ELF standard defines two special sections, `.init_array` and
`.pre_init_array`, that may contain function pointers which will be executed
*before* the `main` function is invoked. The linker will preserve symbols placed
in these sections (at least when linking programs that target the `*-*-linux-*`
targets).
``` rust,ignore
#![feature(used)]
extern "C" fn before_main() {
println!("Hello, world!");
}
#[link_section = ".init_array"]
#[used]
static INIT_ARRAY: [extern "C" fn(); 1] = [before_main];
fn main() {}
```
So, `#[used]` and `#[link_section]` can be combined to obtain "life before
main".
``` text
$ rustc -C opt-level=3 before-main.rs
$ ./before-main
Hello, world!
```
Another example: ARM Cortex-M microcontrollers need their reset handler, a
pointer to the function that will executed right after the microcontroller is
turned on, to be placed near the start of their FLASH memory to boot properly.
This condition can be met using `#[used]` and `#[link_section]` plus a linker
script.
``` rust,ignore
#![feature(panic_handler)]
#![feature(used)]
#![no_main]
#![no_std]
use core::panic::PanicInfo;
extern "C" fn reset_handler() -> ! {
loop {}
}
#[link_section = ".reset_handler"]
#[used]
static RESET_HANDLER: extern "C" fn() -> ! = reset_handler;
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
loop {}
}
```
``` text
MEMORY
{
FLASH : ORIGIN = 0x08000000, LENGTH = 128K
RAM : ORIGIN = 0x20000000, LENGTH = 20K
}
SECTIONS
{
.text ORIGIN(FLASH) :
{
/* Vector table */
LONG(ORIGIN(RAM) + LENGTH(RAM)); /* initial SP value */
KEEP(*(.reset_handler));
/* Omitted: The rest of the vector table */
*(.text.*);
} > FLASH
/DISCARD/ :
{
/* Unused unwinding stuff */
*(.ARM.exidx.*)
}
}
```
``` text
$ xargo rustc --target thumbv7m-none-eabi --release -- \
-C link-arg=-Tlink.x -C link-arg=-nostartfiles
$ arm-none-eabi-objdump -Cd target/thumbv7m-none-eabi/release/app
./target/thumbv7m-none-eabi/release/app: file format elf32-littlearm
Disassembly of section .text:
08000000 <app::RESET_HANDLER-0x4>:
8000000: 20005000 .word 0x20005000
08000004 <app::RESET_HANDLER>:
8000004: 08000009 ....
08000008 <app::reset_handler>:
8000008: e7fe b.n 8000008 <app::reset_handler>
```
......@@ -307,7 +307,7 @@
#![feature(doc_cfg)]
#![feature(doc_masked)]
#![feature(doc_spotlight)]
#![cfg_attr(windows, feature(used))]
#![cfg_attr(all(windows, stage0), feature(used))]
#![feature(doc_alias)]
#![feature(doc_keyword)]
#![feature(panic_info_message)]
......
......@@ -349,9 +349,6 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
// Allows the `try {...}` expression
(active, try_blocks, "1.29.0", Some(31436), None),
// Used to preserve symbols (see llvm.used)
(active, used, "1.18.0", Some(40289), None),
// Allows module-level inline assembly by way of global_asm!()
(active, global_asm, "1.18.0", Some(35119), None),
......@@ -677,6 +674,9 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
// Allows all literals in attribute lists and values of key-value pairs.
(accepted, attr_literals, "1.30.0", Some(34981), None),
(accepted, panic_handler, "1.30.0", Some(44489), None),
// Used to preserve symbols (see llvm.used)
(accepted, used, "1.30.0", Some(40289), None),
);
// If you change this, please modify src/doc/unstable-book as well. You must
......@@ -1071,10 +1071,7 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
"unwind_attributes",
"#[unwind] is experimental",
cfg_fn!(unwind_attributes))),
("used", Whitelisted, Gated(
Stability::Unstable, "used",
"the `#[used]` attribute is an experimental feature",
cfg_fn!(used))),
("used", Whitelisted, Ungated),
// used in resolve
("prelude_import", Whitelisted, Gated(Stability::Unstable,
......
......@@ -9,7 +9,6 @@
// except according to those terms.
#![crate_type = "lib"]
#![feature(used)]
#[used]
static FOO: u32 = 0;
......
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
......@@ -15,6 +15,5 @@
#[used]
fn foo() {}
//~^^ ERROR the `#[used]` attribute is an experimental feature
fn main() {}
error[E0658]: the `#[used]` attribute is an experimental feature (see issue #40289)
error: attribute must be applied to a `static` variable
--> $DIR/feature-gate-linker-flavor.rs:16:1
|
LL | #[used]
| ^^^^^^^
|
= help: add #![feature(used)] to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[used]
fn foo() {}
//~^^ ERROR the `#[used]` attribute is an experimental feature
fn main() {}
error[E0658]: the `#[used]` attribute is an experimental feature (see issue #40289)
--> $DIR/feature-gate-used.rs:11:1
|
LL | #[used]
| ^^^^^^^
|
= help: add #![feature(used)] to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.
......@@ -10,7 +10,6 @@
// run-pass
#![deny(dead_code)]
#![feature(used)]
#[used]
static FOO: u32 = 0;
......
......@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(used)]
#[used]
static FOO: u32 = 0; // OK
......
error: attribute must be applied to a `static` variable
--> $DIR/used.rs:16:1
--> $DIR/used.rs:14:1
|
LL | #[used] //~ ERROR attribute must be applied to a `static` variable
| ^^^^^^^
error: attribute must be applied to a `static` variable
--> $DIR/used.rs:19:1
--> $DIR/used.rs:17:1
|
LL | #[used] //~ ERROR attribute must be applied to a `static` variable
| ^^^^^^^
error: attribute must be applied to a `static` variable
--> $DIR/used.rs:22:1
--> $DIR/used.rs:20:1
|
LL | #[used] //~ ERROR attribute must be applied to a `static` variable
| ^^^^^^^
error: attribute must be applied to a `static` variable
--> $DIR/used.rs:25:1
--> $DIR/used.rs:23:1
|
LL | #[used] //~ ERROR attribute must be applied to a `static` variable
| ^^^^^^^
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册