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