Skip to content

Commit adb21b5

Browse files
committed
Document some safety constraints and use more safe wrappers
1 parent 2776bdf commit adb21b5

File tree

11 files changed

+118
-128
lines changed

11 files changed

+118
-128
lines changed

compiler/rustc_codegen_llvm/src/allocator.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,13 @@ pub(crate) unsafe fn codegen(
8181
llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
8282
let val = tcx.sess.opts.unstable_opts.oom.should_panic();
8383
let llval = llvm::LLVMConstInt(i8, val as u64, False);
84-
llvm::LLVMSetInitializer(ll_g, llval);
84+
llvm::set_initializer(ll_g, llval);
8585

8686
let name = NO_ALLOC_SHIM_IS_UNSTABLE;
8787
let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_c_char_ptr(), name.len(), i8);
8888
llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
8989
let llval = llvm::LLVMConstInt(i8, 0, False);
90-
llvm::LLVMSetInitializer(ll_g, llval);
90+
llvm::set_initializer(ll_g, llval);
9191
}
9292

9393
if tcx.sess.opts.debuginfo != DebugInfo::None {

compiler/rustc_codegen_llvm/src/back/archive.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_codegen_ssa::back::archive::{
1111
use rustc_session::Session;
1212

1313
use crate::llvm::archive_ro::{ArchiveRO, Child};
14-
use crate::llvm::{self, ArchiveKind};
14+
use crate::llvm::{self, ArchiveKind, last_error};
1515

1616
/// Helper for adding many files to an archive.
1717
#[must_use = "must call build() to finish building the archive"]
@@ -169,6 +169,8 @@ impl<'a> LlvmArchiveBuilder<'a> {
169169
.unwrap_or_else(|kind| self.sess.dcx().emit_fatal(UnknownArchiveKind { kind }));
170170

171171
let mut additions = mem::take(&mut self.additions);
172+
// Values in the `members` list below will contain pointers to the strings allocated here.
173+
// So they need to get dropped after all elements of `members` get freed.
172174
let mut strings = Vec::new();
173175
let mut members = Vec::new();
174176

@@ -229,12 +231,7 @@ impl<'a> LlvmArchiveBuilder<'a> {
229231
self.sess.target.arch == "arm64ec",
230232
);
231233
let ret = if r.into_result().is_err() {
232-
let err = llvm::LLVMRustGetLastError();
233-
let msg = if err.is_null() {
234-
"failed to write archive".into()
235-
} else {
236-
String::from_utf8_lossy(CStr::from_ptr(err).to_bytes())
237-
};
234+
let msg = last_error().unwrap_or_else(|| "failed to write archive".into());
238235
Err(io::Error::new(io::ErrorKind::Other, msg))
239236
} else {
240237
Ok(!members.is_empty())

compiler/rustc_codegen_llvm/src/back/write.rs

+96-105
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,11 @@ pub(crate) fn llvm_err<'a>(dcx: DiagCtxtHandle<'_>, err: LlvmError<'a>) -> Fatal
5151
}
5252
}
5353

54-
fn write_output_file<'ll>(
54+
// SAFETY: the pass manager must come from the closure argument of `with_codegen`.
55+
unsafe fn write_output_file<'ll>(
5556
dcx: DiagCtxtHandle<'_>,
5657
target: &'ll llvm::TargetMachine,
57-
pm: &llvm::PassManager<'ll>,
58+
pm: *mut llvm::PassManager<'ll>,
5859
m: &'ll llvm::Module,
5960
output: &Path,
6061
dwo_output: Option<&Path>,
@@ -63,39 +64,39 @@ fn write_output_file<'ll>(
6364
verify_llvm_ir: bool,
6465
) -> Result<(), FatalError> {
6566
debug!("write_output_file output={:?} dwo_output={:?}", output, dwo_output);
66-
unsafe {
67-
let output_c = path_to_c_string(output);
68-
let dwo_output_c;
69-
let dwo_output_ptr = if let Some(dwo_output) = dwo_output {
70-
dwo_output_c = path_to_c_string(dwo_output);
71-
dwo_output_c.as_ptr()
72-
} else {
73-
std::ptr::null()
74-
};
75-
let result = llvm::LLVMRustWriteOutputFile(
67+
let output_c = path_to_c_string(output);
68+
let dwo_output_c;
69+
let dwo_output_ptr = if let Some(dwo_output) = dwo_output {
70+
dwo_output_c = path_to_c_string(dwo_output);
71+
dwo_output_c.as_ptr()
72+
} else {
73+
std::ptr::null()
74+
};
75+
let result = unsafe {
76+
llvm::LLVMRustWriteOutputFile(
7677
target,
7778
pm,
7879
m,
7980
output_c.as_ptr(),
8081
dwo_output_ptr,
8182
file_type,
8283
verify_llvm_ir,
83-
);
84+
)
85+
};
8486

85-
// Record artifact sizes for self-profiling
86-
if result == llvm::LLVMRustResult::Success {
87-
let artifact_kind = match file_type {
88-
llvm::FileType::ObjectFile => "object_file",
89-
llvm::FileType::AssemblyFile => "assembly_file",
90-
};
91-
record_artifact_size(self_profiler_ref, artifact_kind, output);
92-
if let Some(dwo_file) = dwo_output {
93-
record_artifact_size(self_profiler_ref, "dwo_file", dwo_file);
94-
}
87+
// Record artifact sizes for self-profiling
88+
if result == llvm::LLVMRustResult::Success {
89+
let artifact_kind = match file_type {
90+
llvm::FileType::ObjectFile => "object_file",
91+
llvm::FileType::AssemblyFile => "assembly_file",
92+
};
93+
record_artifact_size(self_profiler_ref, artifact_kind, output);
94+
if let Some(dwo_file) = dwo_output {
95+
record_artifact_size(self_profiler_ref, "dwo_file", dwo_file);
9596
}
96-
97-
result.into_result().map_err(|()| llvm_err(dcx, LlvmError::WriteOutput { path: output }))
9897
}
98+
99+
result.into_result().map_err(|()| llvm_err(dcx, LlvmError::WriteOutput { path: output }))
99100
}
100101

101102
pub(crate) fn create_informational_target_machine(
@@ -325,13 +326,17 @@ pub(crate) fn save_temp_bitcode(
325326
if !cgcx.save_temps {
326327
return;
327328
}
329+
let ext = format!("{name}.bc");
330+
let cgu = Some(&module.name[..]);
331+
let path = cgcx.output_filenames.temp_path_ext(&ext, cgu);
332+
write_bitcode_to_file(module, &path)
333+
}
334+
335+
fn write_bitcode_to_file(module: &ModuleCodegen<ModuleLlvm>, path: &Path) {
328336
unsafe {
329-
let ext = format!("{name}.bc");
330-
let cgu = Some(&module.name[..]);
331-
let path = cgcx.output_filenames.temp_path_ext(&ext, cgu);
332-
let cstr = path_to_c_string(&path);
337+
let path = path_to_c_string(&path);
333338
let llmod = module.module_llvm.llmod();
334-
llvm::LLVMWriteBitcodeToFile(llmod, cstr.as_ptr());
339+
llvm::LLVMWriteBitcodeToFile(llmod, path.as_ptr());
335340
}
336341
}
337342

@@ -661,7 +666,6 @@ pub(crate) unsafe fn optimize(
661666
) -> Result<(), FatalError> {
662667
let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_optimize", &*module.name);
663668

664-
let llmod = module.module_llvm.llmod();
665669
let llcx = &*module.module_llvm.llcx;
666670
let _handlers = DiagnosticHandlers::new(cgcx, dcx, llcx, module, CodegenDiagnosticsStage::Opt);
667671

@@ -670,8 +674,7 @@ pub(crate) unsafe fn optimize(
670674

671675
if config.emit_no_opt_bc {
672676
let out = cgcx.output_filenames.temp_path_ext("no-opt.bc", module_name);
673-
let out = path_to_c_string(&out);
674-
unsafe { llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()) };
677+
write_bitcode_to_file(module, &out)
675678
}
676679

677680
// FIXME(ZuseZ4): support SanitizeHWAddress and prevent illegal/unsupported opts
@@ -748,18 +751,18 @@ pub(crate) unsafe fn codegen(
748751
// files for an LLVM module.
749752
//
750753
// Apparently each of these pass managers is a one-shot kind of
751-
// thing, so we create a new one for each type of output. The
752-
// pass manager passed to the closure should be ensured to not
753-
// escape the closure itself, and the manager should only be
754-
// used once.
755-
unsafe fn with_codegen<'ll, F, R>(
754+
// thing, so we create a new one for each type of output.
755+
// The pass manager must be consumed by `LLVMRustWriteOutputFile`,
756+
// which also takes care of freeing its memory. For details of why it's
757+
// this way, see the C++ code of `LLVMRustWriteOutputFile`
758+
fn with_codegen<'ll, F, R>(
756759
tm: &'ll llvm::TargetMachine,
757760
llmod: &'ll llvm::Module,
758761
no_builtins: bool,
759762
f: F,
760763
) -> R
761764
where
762-
F: FnOnce(&'ll mut PassManager<'ll>) -> R,
765+
F: FnOnce(*mut PassManager<'ll>) -> R,
763766
{
764767
unsafe {
765768
let cpm = llvm::LLVMCreatePassManager();
@@ -890,21 +893,19 @@ pub(crate) unsafe fn codegen(
890893
} else {
891894
llmod
892895
};
893-
unsafe {
894-
with_codegen(tm, llmod, config.no_builtins, |cpm| {
895-
write_output_file(
896-
dcx,
897-
tm,
898-
cpm,
899-
llmod,
900-
&path,
901-
None,
902-
llvm::FileType::AssemblyFile,
903-
&cgcx.prof,
904-
config.verify_llvm_ir,
905-
)
906-
})?;
907-
}
896+
with_codegen(tm, llmod, config.no_builtins, |cpm| unsafe {
897+
write_output_file(
898+
dcx,
899+
tm,
900+
cpm,
901+
llmod,
902+
&path,
903+
None,
904+
llvm::FileType::AssemblyFile,
905+
&cgcx.prof,
906+
config.verify_llvm_ir,
907+
)
908+
})?;
908909
}
909910

910911
match config.emit_obj {
@@ -928,21 +929,19 @@ pub(crate) unsafe fn codegen(
928929
(_, SplitDwarfKind::Split) => Some(dwo_out.as_path()),
929930
};
930931

931-
unsafe {
932-
with_codegen(tm, llmod, config.no_builtins, |cpm| {
933-
write_output_file(
934-
dcx,
935-
tm,
936-
cpm,
937-
llmod,
938-
&obj_out,
939-
dwo_out,
940-
llvm::FileType::ObjectFile,
941-
&cgcx.prof,
942-
config.verify_llvm_ir,
943-
)
944-
})?;
945-
}
932+
with_codegen(tm, llmod, config.no_builtins, |cpm| unsafe {
933+
write_output_file(
934+
dcx,
935+
tm,
936+
cpm,
937+
llmod,
938+
&obj_out,
939+
dwo_out,
940+
llvm::FileType::ObjectFile,
941+
&cgcx.prof,
942+
config.verify_llvm_ir,
943+
)
944+
})?;
946945
}
947946

948947
EmitObj::Bitcode => {
@@ -1069,24 +1068,18 @@ unsafe fn embed_bitcode(
10691068
{
10701069
// We don't need custom section flags, create LLVM globals.
10711070
let llconst = common::bytes_in_context(llcx, bitcode);
1072-
let llglobal = llvm::LLVMAddGlobal(
1073-
llmod,
1074-
common::val_ty(llconst),
1075-
c"rustc.embedded.module".as_ptr(),
1076-
);
1077-
llvm::LLVMSetInitializer(llglobal, llconst);
1071+
let llglobal =
1072+
llvm::add_global(llmod, common::val_ty(llconst), c"rustc.embedded.module");
1073+
llvm::set_initializer(llglobal, llconst);
10781074

10791075
llvm::set_section(llglobal, bitcode_section_name(cgcx));
10801076
llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
10811077
llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
10821078

10831079
let llconst = common::bytes_in_context(llcx, cmdline.as_bytes());
1084-
let llglobal = llvm::LLVMAddGlobal(
1085-
llmod,
1086-
common::val_ty(llconst),
1087-
c"rustc.embedded.cmdline".as_ptr(),
1088-
);
1089-
llvm::LLVMSetInitializer(llglobal, llconst);
1080+
let llglobal =
1081+
llvm::add_global(llmod, common::val_ty(llconst), c"rustc.embedded.cmdline");
1082+
llvm::set_initializer(llglobal, llconst);
10901083
let section = if cgcx.target_is_like_osx {
10911084
c"__LLVM,__cmdline"
10921085
} else if cgcx.target_is_like_aix {
@@ -1126,31 +1119,29 @@ fn create_msvc_imps(
11261119
// underscores added in front).
11271120
let prefix = if cgcx.target_arch == "x86" { "\x01__imp__" } else { "\x01__imp_" };
11281121

1129-
unsafe {
1130-
let ptr_ty = Type::ptr_llcx(llcx);
1131-
let globals = base::iter_globals(llmod)
1132-
.filter(|&val| {
1133-
llvm::get_linkage(val) == llvm::Linkage::ExternalLinkage
1134-
&& llvm::LLVMIsDeclaration(val) == 0
1135-
})
1136-
.filter_map(|val| {
1137-
// Exclude some symbols that we know are not Rust symbols.
1138-
let name = llvm::get_value_name(val);
1139-
if ignored(name) { None } else { Some((val, name)) }
1140-
})
1141-
.map(move |(val, name)| {
1142-
let mut imp_name = prefix.as_bytes().to_vec();
1143-
imp_name.extend(name);
1144-
let imp_name = CString::new(imp_name).unwrap();
1145-
(imp_name, val)
1146-
})
1147-
.collect::<Vec<_>>();
1122+
let ptr_ty = Type::ptr_llcx(llcx);
1123+
let globals = base::iter_globals(llmod)
1124+
.filter(|&val| {
1125+
llvm::get_linkage(val) == llvm::Linkage::ExternalLinkage && llvm::is_declaration(val)
1126+
})
1127+
.filter_map(|val| {
1128+
// Exclude some symbols that we know are not Rust symbols.
1129+
let name = llvm::get_value_name(val);
1130+
if ignored(name) { None } else { Some((val, name)) }
1131+
})
1132+
.map(move |(val, name)| {
1133+
let mut imp_name = prefix.as_bytes().to_vec();
1134+
imp_name.extend(name);
1135+
let imp_name = CString::new(imp_name).unwrap();
1136+
(imp_name, val)
1137+
})
1138+
.collect::<Vec<_>>();
11481139

1149-
for (imp_name, val) in globals {
1150-
let imp = llvm::LLVMAddGlobal(llmod, ptr_ty, imp_name.as_ptr());
1151-
llvm::LLVMSetInitializer(imp, val);
1152-
llvm::set_linkage(imp, llvm::Linkage::ExternalLinkage);
1153-
}
1140+
for (imp_name, val) in globals {
1141+
let imp = llvm::add_global(llmod, ptr_ty, &imp_name);
1142+
1143+
llvm::set_initializer(imp, val);
1144+
llvm::set_linkage(imp, llvm::Linkage::ExternalLinkage);
11541145
}
11551146

11561147
// Use this function to exclude certain symbols from `__imp` generation.

compiler/rustc_codegen_llvm/src/common.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,8 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
215215
let g = self.define_global(&sym, self.val_ty(sc)).unwrap_or_else(|| {
216216
bug!("symbol `{}` is already defined", sym);
217217
});
218+
llvm::set_initializer(g, sc);
218219
unsafe {
219-
llvm::LLVMSetInitializer(g, sc);
220220
llvm::LLVMSetGlobalConstant(g, True);
221221
llvm::LLVMSetUnnamedAddress(g, llvm::UnnamedAddr::Global);
222222
}

compiler/rustc_codegen_llvm/src/consts.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ fn check_and_apply_linkage<'ll, 'tcx>(
191191
})
192192
});
193193
llvm::set_linkage(g2, llvm::Linkage::InternalLinkage);
194-
unsafe { llvm::LLVMSetInitializer(g2, g1) };
194+
llvm::set_initializer(g2, g1);
195195
g2
196196
} else if cx.tcx.sess.target.arch == "x86"
197197
&& common::is_mingw_gnu_toolchain(&cx.tcx.sess.target)
@@ -227,7 +227,7 @@ impl<'ll> CodegenCx<'ll, '_> {
227227
}
228228
_ => self.define_private_global(self.val_ty(cv)),
229229
};
230-
unsafe { llvm::LLVMSetInitializer(gv, cv) };
230+
llvm::set_initializer(gv, cv);
231231
set_global_alignment(self, gv, align);
232232
llvm::SetUnnamedAddress(gv, llvm::UnnamedAddr::Global);
233233
gv
@@ -416,7 +416,7 @@ impl<'ll> CodegenCx<'ll, '_> {
416416
new_g
417417
};
418418
set_global_alignment(self, g, alloc.align);
419-
llvm::LLVMSetInitializer(g, v);
419+
llvm::set_initializer(g, v);
420420

421421
if self.should_assume_dso_local(g, true) {
422422
llvm::LLVMRustSetDSOLocal(g, true);

compiler/rustc_codegen_llvm/src/context.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -593,12 +593,10 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
593593
pub(crate) fn create_used_variable_impl(&self, name: &'static CStr, values: &[&'ll Value]) {
594594
let array = self.const_array(self.type_ptr(), values);
595595

596-
unsafe {
597-
let g = llvm::LLVMAddGlobal(self.llmod, self.val_ty(array), name.as_ptr());
598-
llvm::LLVMSetInitializer(g, array);
599-
llvm::set_linkage(g, llvm::Linkage::AppendingLinkage);
600-
llvm::set_section(g, c"llvm.metadata");
601-
}
596+
let g = llvm::add_global(self.llmod, self.val_ty(array), name);
597+
llvm::set_initializer(g, array);
598+
llvm::set_linkage(g, llvm::Linkage::AppendingLinkage);
599+
llvm::set_section(g, c"llvm.metadata");
602600
}
603601

604602
pub(crate) fn get_metadata_value(&self, metadata: &'ll Metadata) -> &'ll Value {

0 commit comments

Comments
 (0)