]> git.lizzy.rs Git - rust.git/blob - src/test/ui/asm/sym.rs
Auto merge of #86155 - alexcrichton:abort-on-unwind, r=nikomatsakis
[rust.git] / src / test / ui / asm / sym.rs
1 // min-llvm-version: 10.0.1
2 // only-x86_64
3 // only-linux
4 // run-pass
5
6 #![feature(asm, thread_local)]
7
8 extern "C" fn f1() -> i32 {
9     111
10 }
11
12 // The compiler will generate a shim to hide the caller location parameter.
13 #[track_caller]
14 fn f2() -> i32 {
15     222
16 }
17
18 macro_rules! call {
19     ($func:path) => {
20         unsafe {
21             let result: i32;
22             asm!("call {}", sym $func,
23                 out("rax") result,
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") _,
30             );
31             result
32         }
33     }
34 }
35
36 macro_rules! static_addr {
37     ($s:expr) => {
38         unsafe {
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);
42             result
43         }
44     }
45 }
46 macro_rules! static_tls_addr {
47     ($s:expr) => {
48         unsafe {
49             let result: *const u32;
50             asm!(
51                 "
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
56                     # of the TLS block.
57                     lea {out}, [{out} + {sym}@tpoff]
58                 ",
59                 out = out(reg) result,
60                 sym = sym $s
61             );
62             result
63         }
64     }
65 }
66
67 static S1: u32 = 111;
68 #[thread_local]
69 static S2: u32 = 222;
70
71 fn main() {
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);
79     }).join().unwrap();
80 }