]>
Commit | Line | Data |
---|---|---|
f9f354fc | 1 | // only-x86_64 |
f035d41b | 2 | // only-linux |
5e7ed085 | 3 | // needs-asm-support |
f9f354fc XL |
4 | // run-pass |
5 | ||
2b03887a | 6 | #![feature(thread_local)] |
a2a8927a XL |
7 | |
8 | use std::arch::asm; | |
f9f354fc XL |
9 | |
10 | extern "C" fn f1() -> i32 { | |
11 | 111 | |
12 | } | |
13 | ||
14 | // The compiler will generate a shim to hide the caller location parameter. | |
15 | #[track_caller] | |
16 | fn f2() -> i32 { | |
17 | 222 | |
18 | } | |
19 | ||
20 | macro_rules! call { | |
f035d41b | 21 | ($func:path) => { |
f9f354fc | 22 | unsafe { |
f035d41b | 23 | let result: i32; |
f9f354fc XL |
24 | asm!("call {}", sym $func, |
25 | out("rax") result, | |
26 | out("rcx") _, out("rdx") _, out("rdi") _, out("rsi") _, | |
27 | out("r8") _, out("r9") _, out("r10") _, out("r11") _, | |
28 | out("xmm0") _, out("xmm1") _, out("xmm2") _, out("xmm3") _, | |
29 | out("xmm4") _, out("xmm5") _, out("xmm6") _, out("xmm7") _, | |
30 | out("xmm8") _, out("xmm9") _, out("xmm10") _, out("xmm11") _, | |
31 | out("xmm12") _, out("xmm13") _, out("xmm14") _, out("xmm15") _, | |
32 | ); | |
f035d41b | 33 | result |
f9f354fc | 34 | } |
f035d41b | 35 | } |
f9f354fc XL |
36 | } |
37 | ||
f035d41b XL |
38 | macro_rules! static_addr { |
39 | ($s:expr) => { | |
40 | unsafe { | |
41 | let result: *const u32; | |
42 | // LEA performs a RIP-relative address calculation and returns the address | |
43 | asm!("lea {}, [rip + {}]", out(reg) result, sym $s); | |
44 | result | |
45 | } | |
46 | } | |
47 | } | |
48 | macro_rules! static_tls_addr { | |
49 | ($s:expr) => { | |
50 | unsafe { | |
51 | let result: *const u32; | |
52 | asm!( | |
53 | " | |
54 | # Load TLS base address | |
55 | mov {out}, qword ptr fs:[0] | |
56 | # Calculate the address of sym in the TLS block. The @tpoff | |
57 | # relocation gives the offset of the symbol from the start | |
58 | # of the TLS block. | |
59 | lea {out}, [{out} + {sym}@tpoff] | |
60 | ", | |
61 | out = out(reg) result, | |
62 | sym = sym $s | |
63 | ); | |
64 | result | |
65 | } | |
66 | } | |
67 | } | |
68 | ||
69 | static S1: u32 = 111; | |
70 | #[thread_local] | |
71 | static S2: u32 = 222; | |
72 | ||
f9f354fc XL |
73 | fn main() { |
74 | assert_eq!(call!(f1), 111); | |
75 | assert_eq!(call!(f2), 222); | |
f035d41b XL |
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); | |
3c0e092e XL |
81 | }) |
82 | .join() | |
83 | .unwrap(); | |
f9f354fc | 84 | } |