1 // min-llvm-version: 10.0.1
6 #![feature(asm, thread_local)]
8 extern "C" fn f1() -> i32 {
12 // The compiler will generate a shim to hide the caller location parameter.
22 asm!("call {}", sym $func,
24 out("rcx") _, out("rdx") _, out("rdi") _, out("rsi") _,
25 out("r8") _, out("r9") _, out("r10") _, out("r11") _,
26 out("xmm0") _, out("xmm1") _, out("xmm2") _, out("xmm3") _,
27 out("xmm4") _, out("xmm5") _, out("xmm6") _, out("xmm7") _,
28 out("xmm8") _, out("xmm9") _, out("xmm10") _, out("xmm11") _,
29 out("xmm12") _, out("xmm13") _, out("xmm14") _, out("xmm15") _,
36 macro_rules! static_addr {
39 let result: *const u32;
40 // LEA performs a RIP-relative address calculation and returns the address
41 asm!("lea {}, [rip + {}]", out(reg) result, sym $s);
46 macro_rules! static_tls_addr {
49 let result: *const u32;
52 # Load TLS base address
53 mov {out}, qword ptr fs:[0]
54 # Calculate the address of sym in the TLS block. The @tpoff
55 # relocation gives the offset of the symbol from the start
57 lea {out}, [{out} + {sym}@tpoff]
59 out = out(reg) result,
72 assert_eq!(call!(f1), 111);
73 assert_eq!(call!(f2), 222);
74 assert_eq!(static_addr!(S1), &S1 as *const u32);
75 assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
76 std::thread::spawn(|| {
77 assert_eq!(static_addr!(S1), &S1 as *const u32);
78 assert_eq!(static_tls_addr!(S2), &S2 as *const u32);