about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorJorge Aparicio <japaricious@gmail.com>2017-02-20 14:42:47 -0500
committerJorge Aparicio <japaricious@gmail.com>2017-04-05 13:40:11 -0500
commit4c7e27734031d8b57cb51ad498d7f5111032468d (patch)
tree40b5aa9f7a262e9e2be02eca163c07b9434a808b /src/libsyntax
parent2564711e803f62e04bebf10408cc1c11297c0caf (diff)
downloadrust-4c7e27734031d8b57cb51ad498d7f5111032468d.tar.gz
rust-4c7e27734031d8b57cb51ad498d7f5111032468d.zip
add an #[used] attribute
similar to GCC's __attribute((used))__. This attribute prevents LLVM from
optimizing away a non-exported symbol, within a compilation unit (object file),
when there are no references to it.

This is better explained with an example:

```
#[used]
static LIVE: i32 = 0;

static REFERENCED: i32 = 0;

static DEAD: i32 = 0;

fn internal() {}

pub fn exported() -> &'static i32 {
    &REFERENCED
}
```

Without optimizations, LLVM pretty much preserves all the static variables and
functions within the compilation unit.

```
$ rustc --crate-type=lib --emit=obj symbols.rs && nm -C symbols.o
0000000000000000 t drop::h1be0f8f27a2ba94a
0000000000000000 r symbols::REFERENCED::hb3bdfd46050bc84c
0000000000000000 r symbols::DEAD::hc2ea8f9bd06f380b
0000000000000000 r symbols::LIVE::h0970cf9889edb56e
0000000000000000 T symbols::exported::h6f096c2b1fc292b2
0000000000000000 t symbols::internal::h0ac1aadbc1e3a494
```

With optimizations, LLVM will drop dead code. Here `internal` is dropped because
it's not a exported function/symbol (i.e. not `pub`lic). `DEAD` is dropped for
the same reason. `REFERENCED` is preserved, even though it's not exported,
because it's referenced by the `exported` function. Finally, `LIVE` survives
because of the `#[used]` attribute even though it's not exported or referenced.

```
$ rustc --crate-type=lib -C opt-level=3 --emit=obj symbols.rs && nm -C symbols.o
0000000000000000 r symbols::REFERENCED::hb3bdfd46050bc84c
0000000000000000 r symbols::LIVE::h0970cf9889edb56e
0000000000000000 T symbols::exported::h6f096c2b1fc292b2
```

Note that the linker knows nothing about `#[used]` and will drop `LIVE`
because no other object references to it.

```
$ echo 'fn main() {}' >> symbols.rs
$ rustc symbols.rs && nm -C symbols | grep LIVE
```

At this time, `#[used]` only works on `static` variables.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/feature_gate.rs8
1 files changed, 8 insertions, 0 deletions
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 12d25ca4274..66a813025c4 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -337,11 +337,15 @@ declare_features! (
     // `extern "x86-interrupt" fn()`
     (active, abi_x86_interrupt, "1.17.0", Some(40180)),
 
+
     // Allows the `catch {...}` expression
     (active, catch_expr, "1.17.0", Some(31436)),
 
     // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
     (active, rvalue_static_promotion, "1.15.1", Some(38865)),
+
+    // Used to preserve symbols
+    (active, used, "1.18.0", None),
 );
 
 declare_features! (
@@ -748,6 +752,10 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
                                   "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 in resolve
     ("prelude_import", Whitelisted, Gated(Stability::Unstable,