1 // min-llvm-version: 12.0.1
7 #![feature(thread_local, asm_sym)]
11 extern "C" fn f1() -> i32 {
15 // The compiler will generate a shim to hide the caller location parameter.
25 asm!("call {}", sym $func,
27 out("rcx") _, out("rdx") _, out("rdi") _, out("rsi") _,
28 out("r8") _, out("r9") _, out("r10") _, out("r11") _,
29 out("xmm0") _, out("xmm1") _, out("xmm2") _, out("xmm3") _,
30 out("xmm4") _, out("xmm5") _, out("xmm6") _, out("xmm7") _,
31 out("xmm8") _, out("xmm9") _, out("xmm10") _, out("xmm11") _,
32 out("xmm12") _, out("xmm13") _, out("xmm14") _, out("xmm15") _,
39 macro_rules! static_addr {
42 let result: *const u32;
43 // LEA performs a RIP-relative address calculation and returns the address
44 asm!("lea {}, [rip + {}]", out(reg) result, sym $s);
49 macro_rules! static_tls_addr {
52 let result: *const u32;
55 # Load TLS base address
56 mov {out}, qword ptr fs:[0]
57 # Calculate the address of sym in the TLS block. The @tpoff
58 # relocation gives the offset of the symbol from the start
60 lea {out}, [{out} + {sym}@tpoff]
62 out = out(reg) result,
75 assert_eq!(call!(f1), 111);
76 assert_eq!(call!(f2), 222);
77 assert_eq!(static_addr!(S1), &S1 as *const u32);
78 assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
79 std::thread::spawn(|| {
80 assert_eq!(static_addr!(S1), &S1 as *const u32);
81 assert_eq!(static_tls_addr!(S2), &S2 as *const u32);