Skip to content

Cross language plugin LTO panics #16

Closed
@pquux

Description

@pquux

Cross language Link Time Optimization (LTO) is a nice feature where instead of compiling binary object files, we have clang create llvm bitcode which we link together and optimize when we generate an output binary. This is particularly useful for rust FFI cases, where we can compile a legacy C application and perform LTO when linking it with rust, thus hopefully removing some of the FFI overhead on hot codepaths.

More info can be found here and here

#[macro_use]
extern crate ctor;

use std::collections::HashMap;

#[ctor]
/// This is an immutable static, evaluated at init time
static STATIC_CTOR: HashMap<u32, &'static str> = {
    let mut m = HashMap::new();
    m.insert(0, "foo");
    m.insert(1, "bar");
    m.insert(2, "baz");
    m
};

fn main() {
    println!("{:x} -> {}", 1, STATIC_CTOR.get(&1).unwrap());
}

You can compile with:

$ RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang-8 -Clink-arg=-fuse-ld=lld-8" cargo run --release
   Compiling proc-macro2 v0.4.27
   Compiling unicode-xid v0.1.0
   Compiling syn v0.15.31
   Compiling quote v0.6.12
   Compiling ctor v0.1.9
   Compiling ctor-opt v0.1.0 (/home/x/ctor-opt)
    Finished release [optimized] target(s) in 51.82s
     Running `target/release/ctor-opt`
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/libcore/option.rs:347:21
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
             at src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:39
   1: std::sys_common::backtrace::_print
             at src/libstd/sys_common/backtrace.rs:71
   2: std::panicking::default_hook::{{closure}}
             at src/libstd/sys_common/backtrace.rs:59
             at src/libstd/panicking.rs:197
   3: std::panicking::default_hook
             at src/libstd/panicking.rs:211
   4: std::panicking::rust_panic_with_hook
             at src/libstd/panicking.rs:474
   5: std::panicking::continue_panic_fmt
             at src/libstd/panicking.rs:381
   6: rust_begin_unwind
             at src/libstd/panicking.rs:308
   7: core::panicking::panic_fmt
             at src/libcore/panicking.rs:85
   8: core::panicking::panic
             at src/libcore/panicking.rs:49
   9: ctor_opt::main
  10: std::rt::lang_start::{{closure}}
  11: std::panicking::try::do_call
             at src/libstd/rt.rs:49
             at src/libstd/panicking.rs:293
  12: __rust_maybe_catch_panic
             at src/libpanic_unwind/lib.rs:85
  13: std::rt::lang_start_internal
             at src/libstd/panicking.rs:272
             at src/libstd/panic.rs:388
             at src/libstd/rt.rs:48
  14: main
  15: __libc_start_main
  16: _start

This was tested on debian sid with rust nightly, clang-8 and lld-8 packages installed. Note that the clang and lld version unfortunately do need to match the rust llvm version.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions