Skip to content

Commit ccfd1b9

Browse files
committed
Initialize the atomic mutex in a constructor for proc macros
1 parent e87651c commit ccfd1b9

File tree

3 files changed

+91
-5
lines changed

3 files changed

+91
-5
lines changed

src/atomic_shim.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::prelude::*;
1010
pub static mut __cg_clif_global_atomic_mutex: libc::pthread_mutex_t = libc::PTHREAD_MUTEX_INITIALIZER;
1111

1212
pub(crate) fn init_global_lock(module: &mut Module<impl Backend>, bcx: &mut FunctionBuilder<'_>) {
13-
if std::env::var("CG_CLIF_JIT").is_ok () {
13+
if std::env::var("CG_CLIF_JIT").is_ok() {
1414
// When using JIT, dylibs won't find the __cg_clif_global_atomic_mutex data object defined here,
1515
// so instead define it in the cg_clif dylib.
1616

@@ -47,6 +47,39 @@ pub(crate) fn init_global_lock(module: &mut Module<impl Backend>, bcx: &mut Func
4747
bcx.ins().call(pthread_mutex_init, &[atomic_mutex, nullptr]);
4848
}
4949

50+
pub(crate) fn init_global_lock_constructor(
51+
module: &mut Module<impl Backend>,
52+
constructor_name: &str
53+
) -> FuncId {
54+
let sig = Signature::new(CallConv::SystemV);
55+
let init_func_id = module
56+
.declare_function(constructor_name, Linkage::Export, &sig)
57+
.unwrap();
58+
59+
let mut ctx = Context::new();
60+
ctx.func = Function::with_name_signature(ExternalName::user(0, 0), sig);
61+
{
62+
let mut func_ctx = FunctionBuilderContext::new();
63+
let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
64+
65+
let block = bcx.create_block();
66+
bcx.switch_to_block(block);
67+
68+
crate::atomic_shim::init_global_lock(module, &mut bcx);
69+
70+
bcx.ins().return_(&[]);
71+
bcx.seal_all_blocks();
72+
bcx.finalize();
73+
}
74+
module.define_function(
75+
init_func_id,
76+
&mut ctx,
77+
&mut cranelift_codegen::binemit::NullTrapSink {},
78+
).unwrap();
79+
80+
init_func_id
81+
}
82+
5083
pub(crate) fn lock_global_lock(fx: &mut FunctionCx<'_, '_, impl Backend>) {
5184
let atomic_mutex = fx.module.declare_data(
5285
"__cg_clif_global_atomic_mutex",

src/backend.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,32 @@ impl WriteDebugInfo for ObjectProduct {
9797
}
9898
}
9999

100+
// FIXME remove once atomic instructions are implemented in Cranelift.
101+
pub(crate) trait AddConstructor {
102+
fn add_constructor(&mut self, func_id: FuncId);
103+
}
104+
105+
impl AddConstructor for ObjectProduct {
106+
fn add_constructor(&mut self, func_id: FuncId) {
107+
let symbol = self.function_symbol(func_id);
108+
let segment = self.object.segment_name(object::write::StandardSegment::Data);
109+
let init_array_section = self.object.add_section(segment.to_vec(), b".init_array".to_vec(), SectionKind::Data);
110+
self.object.append_section_data(
111+
init_array_section,
112+
&std::iter::repeat(0).take(8 /*FIXME pointer size*/).collect::<Vec<u8>>(),
113+
8,
114+
);
115+
self.object.add_relocation(init_array_section, object::write::Relocation {
116+
offset: 0,
117+
size: 64, // FIXME pointer size
118+
kind: RelocationKind::Absolute,
119+
encoding: RelocationEncoding::Generic,
120+
symbol,
121+
addend: 0,
122+
}).unwrap();
123+
}
124+
}
125+
100126
pub(crate) trait Emit {
101127
fn emit(self) -> Vec<u8>;
102128
}
@@ -140,7 +166,7 @@ pub(crate) fn with_object(sess: &Session, name: &str, f: impl FnOnce(&mut Object
140166
metadata_object.write().unwrap()
141167
}
142168

143-
pub(crate) type Backend = impl cranelift_module::Backend<Product: Emit + WriteDebugInfo>;
169+
pub(crate) type Backend = impl cranelift_module::Backend<Product: AddConstructor + Emit + WriteDebugInfo>;
144170

145171
pub(crate) fn make_module(sess: &Session, name: String) -> Module<Backend> {
146172
let module: Module<ObjectBackend> = Module::new(

src/driver/aot.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
1111

1212
use crate::prelude::*;
1313

14-
use crate::backend::{Emit, WriteDebugInfo};
14+
use crate::backend::{AddConstructor, Emit, WriteDebugInfo};
1515

1616
fn new_module(tcx: TyCtxt<'_>, name: String) -> Module<crate::backend::Backend> {
1717
let module = crate::backend::make_module(tcx.sess, name);
@@ -35,8 +35,9 @@ fn emit_module<B: Backend>(
3535
mut module: Module<B>,
3636
debug: Option<DebugContext<'_>>,
3737
unwind_context: UnwindContext<'_>,
38+
map_product: impl FnOnce(B::Product) -> B::Product,
3839
) -> ModuleCodegenResult
39-
where B::Product: Emit + WriteDebugInfo,
40+
where B::Product: AddConstructor + Emit + WriteDebugInfo,
4041
{
4142
module.finalize_definitions();
4243
let mut product = module.finish();
@@ -47,6 +48,8 @@ fn emit_module<B: Backend>(
4748

4849
unwind_context.emit(&mut product);
4950

51+
let product = map_product(product);
52+
5053
let tmp_file = tcx
5154
.output_filenames(LOCAL_CRATE)
5255
.temp_path(OutputType::Object, Some(&name));
@@ -110,7 +113,23 @@ fn module_codegen(tcx: TyCtxt<'_>, cgu_name: rustc_span::Symbol) -> ModuleCodege
110113
let cgu = tcx.codegen_unit(cgu_name);
111114
let mono_items = cgu.items_in_deterministic_order(tcx);
112115

113-
let module = new_module(tcx, cgu_name.as_str().to_string());
116+
let mut module = new_module(tcx, cgu_name.as_str().to_string());
117+
118+
// Initialize the global atomic mutex using a constructor for proc-macros.
119+
// FIXME implement atomic instructions in Cranelift.
120+
let mut init_atomics_mutex_from_constructor = None;
121+
if tcx.sess.crate_types().contains(&rustc_session::config::CrateType::ProcMacro) {
122+
if mono_items.iter().any(|(mono_item, _)| {
123+
match mono_item {
124+
rustc_middle::mir::mono::MonoItem::Static(def_id) => {
125+
tcx.symbol_name(Instance::mono(tcx, *def_id)).name.as_str().contains("__rustc_proc_macro_decls_")
126+
}
127+
_ => false,
128+
}
129+
}) {
130+
init_atomics_mutex_from_constructor = Some(crate::atomic_shim::init_global_lock_constructor(&mut module, &format!("{}_init_atomics_mutex", cgu_name.as_str())));
131+
}
132+
}
114133

115134
let mut cx = crate::CodegenCx::new(tcx, module, tcx.sess.opts.debuginfo != DebugInfo::None);
116135
super::codegen_mono_items(&mut cx, mono_items);
@@ -124,6 +143,13 @@ fn module_codegen(tcx: TyCtxt<'_>, cgu_name: rustc_span::Symbol) -> ModuleCodege
124143
module,
125144
debug,
126145
unwind_context,
146+
|mut product| {
147+
if let Some(func_id) = init_atomics_mutex_from_constructor {
148+
product.add_constructor(func_id);
149+
}
150+
151+
product
152+
}
127153
);
128154

129155
codegen_global_asm(tcx, &cgu.name().as_str(), &global_asm);
@@ -196,6 +222,7 @@ pub(super) fn run_aot(
196222
allocator_module,
197223
None,
198224
allocator_unwind_context,
225+
|product| product,
199226
);
200227
if let Some((id, product)) = work_product {
201228
work_products.insert(id, product);

0 commit comments

Comments
 (0)