6 #![feature(thread_local, asm_sym)]
10 extern "C" fn f1() -> i32 {
14 // The compiler will generate a shim to hide the caller location parameter.
24 asm!("bl {}", sym $func,
26 out("x20") _, out("x21") _, out("x22") _,
27 out("x23") _, out("x24") _, out("x25") _,
28 out("x26") _, out("x27") _, out("x28") _,
35 macro_rules! static_addr {
38 let result: *const u32;
40 // ADRP gives the address of a 4KB page from a PC-relative address
42 // We then add the remaining lower 12 bits
43 "add {out}, {out}, #:lo12:{sym}",
44 out = out(reg) result,
50 macro_rules! static_tls_addr {
53 let result: *const u32;
55 // Load the thread pointer register
56 "mrs {out}, TPIDR_EL0",
57 // Add the top 12 bits of the symbol's offset
58 "add {out}, {out}, :tprel_hi12:{sym}",
59 // And the bottom 12 bits
60 "add {out}, {out}, :tprel_lo12_nc:{sym}",
61 out = out(reg) result,
74 assert_eq!(call!(f1), 111);
75 assert_eq!(call!(f2), 222);
76 assert_eq!(static_addr!(S1), &S1 as *const u32);
77 assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
78 std::thread::spawn(|| {
79 assert_eq!(static_addr!(S1), &S1 as *const u32);
80 assert_eq!(static_tls_addr!(S2), &S2 as *const u32);