Repository navigation
ice Can't change TLS data object to normal or in the opposite way #1691
Copy link
Copy link
Closed
Description
#![feature(thread_local)]
#[no_mangle]
static EXPORTED: u64 = 0;
extern "C" {
#[thread_local]
#[link_name = "EXPORTED"]
static C: u64;
}
fn thread_local_ptr<T>(key: &'static std::thread::LocalKey<T>) -> *const T {
key.with(|local| core::ptr::from_ref(local))
}
fn main() {
unsafe { C };
}warning: function `thread_local_ptr` is never used
--> a.rs:9:4
|
9 | fn thread_local_ptr<T>(key: &'static std::thread::LocalKey<T>) -> *const T {
| ^^^^^^^^^^^^^^^^
|
= note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default
thread 'rustc' (1825008) panicked at /rust/deps/cranelift-module-0.134.0/src/module.rs:411:9:
assertion `left == right` failed: Can't change TLS data object to normal or in the opposite way
left: false
right: true
stack backtrace:
0: 0x7f25e6492846 - <<std[5a41d20a063701f0]::sys::backtrace::BacktraceLock>::print::DisplayBacktrace as core[cb6dd95fb6db39b2]::fmt::Display>::fmt
1: 0x7f25e6a0ad23 - core[cb6dd95fb6db39b2]::fmt::write
2: 0x7f25e64a7ccc - <std[5a41d20a063701f0]::sys::stdio::unix::Stderr as core[cb6dd95fb6db39b2]::io::write::Write>::write_fmt
3: 0x7f25e6465c9a - std[5a41d20a063701f0]::panicking::default_hook::{closure#0}
4: 0x7f25e6486af3 - std[5a41d20a063701f0]::panicking::default_hook
5: 0x7f25e54085da - std[5a41d20a063701f0]::panicking::update_hook::<alloc[7eac85f6001fa66c]::boxed::Box<rustc_driver_impl[be15a1de4f8adf7c]::install_ice_hook::{closure#1}>>::{closure#0}
6: 0x7f25e6486f92 - std[5a41d20a063701f0]::panicking::panic_with_hook
7: 0x7f25e6465d52 - std[5a41d20a063701f0]::panicking::panic_handler::{closure#0}
8: 0x7f25e645cc39 - std[5a41d20a063701f0]::sys::backtrace::__rust_end_short_backtrace::<std[5a41d20a063701f0]::panicking::panic_handler::{closure#0}, !>
9: 0x7f25e646775d - __rustc[d7d9a081177ff67c]::rust_begin_unwind
10: 0x7f25e316f23c - core[cb6dd95fb6db39b2]::panicking::panic_fmt
11: 0x7f25e4d8f703 - core[cb6dd95fb6db39b2]::panicking::assert_failed_inner
12: 0x7f25d357bde9 - core[cb6dd95fb6db39b2]::panicking::assert_failed::<bool, bool>
13: 0x7f25d357d2b8 - <cranelift_module[2eb1bc0d7108a86c]::module::ModuleDeclarations>::declare_data
14: 0x7f25d353ac23 - <cranelift_object[bb96b36a0857ccef]::backend::ObjectModule as cranelift_module[2eb1bc0d7108a86c]::module::Module>::declare_data
15: 0x7f25d34ecee9 - rustc_codegen_cranelift[24e9fc91d79ce9ea]::constant::data_id_for_static
16: 0x7f25d34df2f2 - rustc_codegen_cranelift[24e9fc91d79ce9ea]::base::codegen_fn_body
17: 0x7f25d350627c - rustc_codegen_cranelift[24e9fc91d79ce9ea]::driver::aot::codegen_cgu
18: 0x7f25d34aa42e - <rustc_codegen_cranelift[24e9fc91d79ce9ea]::driver::aot::AotDriver as rustc_codegen_ssa[a93c6d9b7850f4fb]::traits::backend::ExtraBackendMethods>::compile_codegen_unit::{closure#0}
19: 0x7f25d35143fe - <rustc_codegen_cranelift[24e9fc91d79ce9ea]::driver::aot::AotDriver as rustc_codegen_ssa[a93c6d9b7850f4fb]::traits::backend::ExtraBackendMethods>::compile_codegen_unit
20: 0x7f25d3479882 - rustc_codegen_ssa[a93c6d9b7850f4fb]::base::codegen_crate::<rustc_codegen_cranelift[24e9fc91d79ce9ea]::driver::aot::AotDriver, rustc_codegen_cranelift[24e9fc91d79ce9ea]::driver::aot::AotModule>
21: 0x7f25d35233cf - <rustc_codegen_cranelift[24e9fc91d79ce9ea]::CraneliftCodegenBackend as rustc_codegen_ssa[a93c6d9b7850f4fb]::traits::backend::CodegenBackend>::codegen_crate
22: 0x7f25e7c879cc - <rustc_interface[727e6560ae5ab0f8]::queries::Linker>::codegen_and_build_linker
23: 0x7f25e7c7f395 - rustc_interface[727e6560ae5ab0f8]::interface::run_compiler::<(), rustc_driver_impl[be15a1de4f8adf7c]::run_compiler::{closure#0}>::{closure#2}
24: 0x7f25e7cae7a4 - std[5a41d20a063701f0]::sys::backtrace::__rust_begin_short_backtrace::<rustc_interface[727e6560ae5ab0f8]::util::run_in_thread_with_globals<rustc_interface[727e6560ae5ab0f8]::util::run_in_thread_pool_with_globals<rustc_interface[727e6560ae5ab0f8]::interface::run_compiler<(), rustc_driver_impl[be15a1de4f8adf7c]::run_compiler::{closure#0}>::{closure#2}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>
25: 0x7f25e7cae56d - <std[5a41d20a063701f0]::thread::lifecycle::spawn_unchecked<rustc_interface[727e6560ae5ab0f8]::util::run_in_thread_with_globals<rustc_interface[727e6560ae5ab0f8]::util::run_in_thread_pool_with_globals<rustc_interface[727e6560ae5ab0f8]::interface::run_compiler<(), rustc_driver_impl[be15a1de4f8adf7c]::run_compiler::{closure#0}>::{closure#2}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>::{closure#1} as core[cb6dd95fb6db39b2]::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
26: 0x7f25e7cab807 - <std[5a41d20a063701f0]::sys::thread::unix::Thread>::new::thread_start
27: 0x7f25e1297739 - <unknown>
28: 0x7f25e131bedc - <unknown>
29: 0x0 - <unknown>
error: the compiler unexpectedly panicked. This is a bug
note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md
note: please make sure that you have updated to the latest nightly
note: please attach the file at `/tmp/cr/rustc-ice-2026-08-15T09_56_24-1824987.txt` to your bug report
note: rustc 1.99.0-nightly (d453bdd8f 2026-08-14) running on x86_64-unknown-linux-gnu
note: compiler flags: -Z codegen-backend=cranelift
query stack during panic:
end of query stack
stmt _1 = &/*tls*/ C
fn main() -> () {
let mut _0: ();
let mut _1: *const u64;
let mut _2: *const ();
let mut _3: usize;
let mut _4: usize;
let mut _5: usize;
let mut _6: bool;
let mut _7: *const ();
let mut _8: usize;
let mut _9: bool;
let mut _10: bool;
let mut _11: bool;
let mut _12: bool;
bb0: {
_1 = &/*tls*/ C;
_2 = copy _1 as *const () (PtrToPtr);
_3 = copy _2 as usize (Transmute);
_4 = Sub(const <u64 as std::mem::SizedTypeProperties>::ALIGN, const 1_usize);
_5 = BitAnd(copy _3, copy _4);
_6 = Eq(copy _5, const 0_usize);
assert(copy _6, "misaligned pointer dereference: address must be a multiple of {} but is {}", const <u64 as std::mem::SizedTypeProperties>::ALIGN, copy _3) -> [success: bb1, unwind unreachable];
}
bb1: {
_7 = copy _1 as *const () (PtrToPtr);
_8 = copy _7 as usize (Transmute);
_9 = Ne(const <u64 as std::mem::SizedTypeProperties>::SIZE, const 0_usize);
_10 = Eq(copy _8, const 0_usize);
_11 = BitAnd(copy _10, copy _9);
_12 = Not(copy _11);
assert(copy _12, "null pointer dereference occurred") -> [success: bb2, unwind unreachable];
}
bb2: {
return;
}
}
warning: 1 warning emitted
rustc 1.99.0-nightly (d453bdd8f 2026-08-14)
binary: rustc
commit-hash: d453bdd8f092d099bc336f0bda4163f809ad18e0
commit-date: 2026-08-14
host: x86_64-unknown-linux-gnu
release: 1.99.0-nightly
LLVM version: 23.1.0
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
pantha704 commentedon Oct 16, 2026
Hi! Picked this up — reproduced on current
main(cranelift-module 0.135.0), while the LLVM backend compiles and runs the same program fine.Root cause.
constant::data_id_for_staticdeclares the symbolEXPORTEDtwice in one module: once for the definedstatic EXPORTED(non-TLS) and once for the foreign#[thread_local]C(TLS, vialink_name).cranelift_module::DataDeclaration::mergeasserts when a repeated declaration changes the TLS flag (cranelift-module/src/module.rs:411).What LLVM does with the same program (
--emit=llvm-ir): both declarations collapse into a single global —@EXPORTED = thread_local constant [8 x i8] c"*\00..."— the definition merges into the thread-local declaration, the initializer is kept, and accesses go through@llvm.threadlocal.address. At runtime both&EXPORTEDand&Cobserve the same TLS object.Why it's not a one-liner for cg_clif. A
DataId's TLS flag is fixed atdeclare_datatime and cranelift-module asserts before we can react, so making it compile like LLVM requires the TLS-ness to be known at the first declaration. Options I can see:ThreadLocalRefuses of foreign statics, and declare any static whose symbol name is in that set withtls = truefrom the start (needs a spot to stash the name set fordata_id_for_static).Do you have a preference? If (1), I can prototype the pre-scan; happy to hear too if you'd rather this be fixed in cranelift-module instead.