]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_codegen_cranelift/src/atomic_shim.rs
Rollup merge of #79379 - GuillaumeGomez:no-js-not-hidden, r=Nemo157
[rust.git] / compiler / rustc_codegen_cranelift / src / atomic_shim.rs
1 //! Atomic intrinsics are implemented using a global lock for now, as Cranelift doesn't support
2 //! atomic operations yet.
3
4 // FIXME implement atomic instructions in Cranelift.
5
6 use crate::prelude::*;
7
8 #[cfg(all(feature = "jit", unix))]
9 #[no_mangle]
10 static mut __cg_clif_global_atomic_mutex: libc::pthread_mutex_t = libc::PTHREAD_MUTEX_INITIALIZER;
11
12 pub(crate) fn init_global_lock(
13     module: &mut impl Module,
14     bcx: &mut FunctionBuilder<'_>,
15     use_jit: bool,
16 ) {
17     if use_jit {
18         // When using JIT, dylibs won't find the __cg_clif_global_atomic_mutex data object defined here,
19         // so instead we define it in the cg_clif dylib.
20
21         return;
22     }
23
24     let mut data_ctx = DataContext::new();
25     data_ctx.define_zeroinit(1024); // 1024 bytes should be big enough on all platforms.
26     data_ctx.set_align(16);
27     let atomic_mutex = module
28         .declare_data(
29             "__cg_clif_global_atomic_mutex",
30             Linkage::Export,
31             true,
32             false,
33         )
34         .unwrap();
35     module.define_data(atomic_mutex, &data_ctx).unwrap();
36
37     let pthread_mutex_init = module
38         .declare_function(
39             "pthread_mutex_init",
40             Linkage::Import,
41             &cranelift_codegen::ir::Signature {
42                 call_conv: module.target_config().default_call_conv,
43                 params: vec![
44                     AbiParam::new(
45                         module.target_config().pointer_type(), /* *mut pthread_mutex_t */
46                     ),
47                     AbiParam::new(
48                         module.target_config().pointer_type(), /* *const pthread_mutex_attr_t */
49                     ),
50                 ],
51                 returns: vec![AbiParam::new(types::I32 /* c_int */)],
52             },
53         )
54         .unwrap();
55
56     let pthread_mutex_init = module.declare_func_in_func(pthread_mutex_init, bcx.func);
57
58     let atomic_mutex = module.declare_data_in_func(atomic_mutex, bcx.func);
59     let atomic_mutex = bcx
60         .ins()
61         .global_value(module.target_config().pointer_type(), atomic_mutex);
62
63     let nullptr = bcx.ins().iconst(module.target_config().pointer_type(), 0);
64
65     bcx.ins().call(pthread_mutex_init, &[atomic_mutex, nullptr]);
66 }
67
68 pub(crate) fn init_global_lock_constructor(
69     module: &mut impl Module,
70     constructor_name: &str,
71 ) -> FuncId {
72     let sig = Signature::new(CallConv::SystemV);
73     let init_func_id = module
74         .declare_function(constructor_name, Linkage::Export, &sig)
75         .unwrap();
76
77     let mut ctx = Context::new();
78     ctx.func = Function::with_name_signature(ExternalName::user(0, 0), sig);
79     {
80         let mut func_ctx = FunctionBuilderContext::new();
81         let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
82
83         let block = bcx.create_block();
84         bcx.switch_to_block(block);
85
86         crate::atomic_shim::init_global_lock(module, &mut bcx, false);
87
88         bcx.ins().return_(&[]);
89         bcx.seal_all_blocks();
90         bcx.finalize();
91     }
92     module
93         .define_function(
94             init_func_id,
95             &mut ctx,
96             &mut cranelift_codegen::binemit::NullTrapSink {},
97         )
98         .unwrap();
99
100     init_func_id
101 }
102
103 pub(crate) fn lock_global_lock(fx: &mut FunctionCx<'_, '_, impl Module>) {
104     let atomic_mutex = fx
105         .cx
106         .module
107         .declare_data(
108             "__cg_clif_global_atomic_mutex",
109             Linkage::Import,
110             true,
111             false,
112         )
113         .unwrap();
114
115     let pthread_mutex_lock = fx
116         .cx
117         .module
118         .declare_function(
119             "pthread_mutex_lock",
120             Linkage::Import,
121             &cranelift_codegen::ir::Signature {
122                 call_conv: fx.cx.module.target_config().default_call_conv,
123                 params: vec![AbiParam::new(
124                     fx.cx.module.target_config().pointer_type(), /* *mut pthread_mutex_t */
125                 )],
126                 returns: vec![AbiParam::new(types::I32 /* c_int */)],
127             },
128         )
129         .unwrap();
130
131     let pthread_mutex_lock = fx
132         .cx
133         .module
134         .declare_func_in_func(pthread_mutex_lock, fx.bcx.func);
135
136     let atomic_mutex = fx.cx.module.declare_data_in_func(atomic_mutex, fx.bcx.func);
137     let atomic_mutex = fx
138         .bcx
139         .ins()
140         .global_value(fx.cx.module.target_config().pointer_type(), atomic_mutex);
141
142     fx.bcx.ins().call(pthread_mutex_lock, &[atomic_mutex]);
143 }
144
145 pub(crate) fn unlock_global_lock(fx: &mut FunctionCx<'_, '_, impl Module>) {
146     let atomic_mutex = fx
147         .cx
148         .module
149         .declare_data(
150             "__cg_clif_global_atomic_mutex",
151             Linkage::Import,
152             true,
153             false,
154         )
155         .unwrap();
156
157     let pthread_mutex_unlock = fx
158         .cx
159         .module
160         .declare_function(
161             "pthread_mutex_unlock",
162             Linkage::Import,
163             &cranelift_codegen::ir::Signature {
164                 call_conv: fx.cx.module.target_config().default_call_conv,
165                 params: vec![AbiParam::new(
166                     fx.cx.module.target_config().pointer_type(), /* *mut pthread_mutex_t */
167                 )],
168                 returns: vec![AbiParam::new(types::I32 /* c_int */)],
169             },
170         )
171         .unwrap();
172
173     let pthread_mutex_unlock = fx
174         .cx
175         .module
176         .declare_func_in_func(pthread_mutex_unlock, fx.bcx.func);
177
178     let atomic_mutex = fx.cx.module.declare_data_in_func(atomic_mutex, fx.bcx.func);
179     let atomic_mutex = fx
180         .bcx
181         .ins()
182         .global_value(fx.cx.module.target_config().pointer_type(), atomic_mutex);
183
184     fx.bcx.ins().call(pthread_mutex_unlock, &[atomic_mutex]);
185 }