]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_codegen_cranelift/src/atomic_shim.rs
New upstream version 1.50.0+dfsg1
[rustc.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 }