|
| 1 | +# `virtual-function-elimination` |
| 2 | + |
| 3 | +This option controls whether LLVM runs the Virtual Function Elimination (VFE) |
| 4 | +optimization. This optimization in only available with LTO, so this flag can |
| 5 | +only be passed if [`-Clto`][Clto] is also passed. |
| 6 | + |
| 7 | +VFE makes it possible to remove functions from vtables that are never |
| 8 | +dynamically called by the rest of the code. Without this flag, LLVM makes the |
| 9 | +really conservative assumption, that if any function in a vtable is called, no |
| 10 | +function that is referenced by this vtable can be removed. With this flag |
| 11 | +additional information are given to LLVM, so that it can determine which |
| 12 | +functions are actually called and remove the unused functions. |
| 13 | + |
| 14 | +## Limitations |
| 15 | + |
| 16 | +At the time of writing this flag may remove vtable functions too eagerly. One |
| 17 | +such example is in this code: |
| 18 | + |
| 19 | +```rust |
| 20 | +trait Foo { fn foo(&self) { println!("foo") } } |
| 21 | + |
| 22 | +impl Foo for usize {} |
| 23 | + |
| 24 | +pub struct FooBox(Box<dyn Foo>); |
| 25 | + |
| 26 | +pub fn make_foo() -> FooBox { FooBox(Box::new(0)) } |
| 27 | + |
| 28 | +#[inline] |
| 29 | +pub fn f(a: FooBox) { a.0.foo() } |
| 30 | +``` |
| 31 | + |
| 32 | +In the above code the `Foo` trait is private, so an assumption is made that its |
| 33 | +functions can only be seen/called from the current crate and can therefore get |
| 34 | +optimized out, if unused. However, with `make_foo` you can produce a wrapped |
| 35 | +`dyn Foo` type outside of the current crate, which can then be used in `f`. Due |
| 36 | +to inlining of `f`, `Foo::foo` can then be called from a foreign crate. This can |
| 37 | +lead to miscompilations. |
| 38 | + |
| 39 | +[Clto]: https://doc.rust-lang.org/rustc/codegen-options/index.html#lto |
0 commit comments