1
Fork 0

Fix unsafe_op_in_unsafe_fn in compiler

This commit is contained in:
Michael Goulet 2024-07-14 14:27:57 -04:00
parent 71eb49c318
commit 28503d69ac
15 changed files with 386 additions and 311 deletions

View file

@ -727,7 +727,7 @@ pub unsafe fn optimize_thin_module(
// into that context. One day, however, we may do this for upstream
// crates but for locally codegened modules we may be able to reuse
// that LLVM Context and Module.
let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
let llcx = unsafe { llvm::LLVMRustContextCreate(cgcx.fewer_names) };
let llmod_raw = parse_module(llcx, module_name, thin_module.data(), dcx)? as *const _;
let mut module = ModuleCodegen {
module_llvm: ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) },
@ -750,7 +750,9 @@ pub unsafe fn optimize_thin_module(
{
let _timer =
cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_rename", thin_module.name());
if !llvm::LLVMRustPrepareThinLTORename(thin_module.shared.data.0, llmod, target) {
if unsafe {
!llvm::LLVMRustPrepareThinLTORename(thin_module.shared.data.0, llmod, target)
} {
return Err(write::llvm_err(dcx, LlvmError::PrepareThinLtoModule));
}
save_temp_bitcode(cgcx, &module, "thin-lto-after-rename");
@ -760,7 +762,8 @@ pub unsafe fn optimize_thin_module(
let _timer = cgcx
.prof
.generic_activity_with_arg("LLVM_thin_lto_resolve_weak", thin_module.name());
if !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) {
if unsafe { !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) }
{
return Err(write::llvm_err(dcx, LlvmError::PrepareThinLtoModule));
}
save_temp_bitcode(cgcx, &module, "thin-lto-after-resolve");
@ -770,7 +773,8 @@ pub unsafe fn optimize_thin_module(
let _timer = cgcx
.prof
.generic_activity_with_arg("LLVM_thin_lto_internalize", thin_module.name());
if !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) {
if unsafe { !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) }
{
return Err(write::llvm_err(dcx, LlvmError::PrepareThinLtoModule));
}
save_temp_bitcode(cgcx, &module, "thin-lto-after-internalize");
@ -779,7 +783,9 @@ pub unsafe fn optimize_thin_module(
{
let _timer =
cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_import", thin_module.name());
if !llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod, target) {
if unsafe {
!llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod, target)
} {
return Err(write::llvm_err(dcx, LlvmError::PrepareThinLtoModule));
}
save_temp_bitcode(cgcx, &module, "thin-lto-after-import");

View file

@ -46,13 +46,15 @@ pub unsafe extern "C" fn selfprofile_before_pass_callback(
pass_name: *const c_char,
ir_name: *const c_char,
) {
let llvm_self_profiler = &mut *(llvm_self_profiler as *mut LlvmSelfProfiler<'_>);
let pass_name = CStr::from_ptr(pass_name).to_str().expect("valid UTF-8");
let ir_name = CStr::from_ptr(ir_name).to_str().expect("valid UTF-8");
llvm_self_profiler.before_pass_callback(pass_name, ir_name);
unsafe {
let llvm_self_profiler = &mut *(llvm_self_profiler as *mut LlvmSelfProfiler<'_>);
let pass_name = CStr::from_ptr(pass_name).to_str().expect("valid UTF-8");
let ir_name = CStr::from_ptr(ir_name).to_str().expect("valid UTF-8");
llvm_self_profiler.before_pass_callback(pass_name, ir_name);
}
}
pub unsafe extern "C" fn selfprofile_after_pass_callback(llvm_self_profiler: *mut c_void) {
let llvm_self_profiler = &mut *(llvm_self_profiler as *mut LlvmSelfProfiler<'_>);
let llvm_self_profiler = unsafe { &mut *(llvm_self_profiler as *mut LlvmSelfProfiler<'_>) };
llvm_self_profiler.after_pass_callback();
}

View file

@ -428,9 +428,10 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void
if user.is_null() {
return;
}
let (cgcx, dcx) = *(user as *const (&CodegenContext<LlvmCodegenBackend>, DiagCtxtHandle<'_>));
let (cgcx, dcx) =
unsafe { *(user as *const (&CodegenContext<LlvmCodegenBackend>, DiagCtxtHandle<'_>)) };
match llvm::diagnostic::Diagnostic::unpack(info) {
match unsafe { llvm::diagnostic::Diagnostic::unpack(info) } {
llvm::diagnostic::InlineAsm(inline) => {
report_inline_asm(cgcx, inline.message, inline.level, inline.cookie, inline.source);
}
@ -454,14 +455,14 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void
});
}
llvm::diagnostic::PGO(diagnostic_ref) | llvm::diagnostic::Linker(diagnostic_ref) => {
let message = llvm::build_string(|s| {
let message = llvm::build_string(|s| unsafe {
llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s)
})
.expect("non-UTF8 diagnostic");
dcx.emit_warn(FromLlvmDiag { message });
}
llvm::diagnostic::Unsupported(diagnostic_ref) => {
let message = llvm::build_string(|s| {
let message = llvm::build_string(|s| unsafe {
llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s)
})
.expect("non-UTF8 diagnostic");
@ -564,37 +565,39 @@ pub(crate) unsafe fn llvm_optimize(
let llvm_plugins = config.llvm_plugins.join(",");
let result = llvm::LLVMRustOptimize(
module.module_llvm.llmod(),
&*module.module_llvm.tm,
to_pass_builder_opt_level(opt_level),
opt_stage,
cgcx.opts.cg.linker_plugin_lto.enabled(),
config.no_prepopulate_passes,
config.verify_llvm_ir,
using_thin_buffers,
config.merge_functions,
unroll_loops,
config.vectorize_slp,
config.vectorize_loop,
config.no_builtins,
config.emit_lifetime_markers,
sanitizer_options.as_ref(),
pgo_gen_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
pgo_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
config.instrument_coverage,
instr_profile_output_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
config.instrument_gcov,
pgo_sample_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
config.debug_info_for_profiling,
llvm_selfprofiler,
selfprofile_before_pass_callback,
selfprofile_after_pass_callback,
extra_passes.as_ptr().cast(),
extra_passes.len(),
llvm_plugins.as_ptr().cast(),
llvm_plugins.len(),
);
let result = unsafe {
llvm::LLVMRustOptimize(
module.module_llvm.llmod(),
&*module.module_llvm.tm,
to_pass_builder_opt_level(opt_level),
opt_stage,
cgcx.opts.cg.linker_plugin_lto.enabled(),
config.no_prepopulate_passes,
config.verify_llvm_ir,
using_thin_buffers,
config.merge_functions,
unroll_loops,
config.vectorize_slp,
config.vectorize_loop,
config.no_builtins,
config.emit_lifetime_markers,
sanitizer_options.as_ref(),
pgo_gen_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
pgo_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
config.instrument_coverage,
instr_profile_output_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
config.instrument_gcov,
pgo_sample_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
config.debug_info_for_profiling,
llvm_selfprofiler,
selfprofile_before_pass_callback,
selfprofile_after_pass_callback,
extra_passes.as_ptr().cast(),
extra_passes.len(),
llvm_plugins.as_ptr().cast(),
llvm_plugins.len(),
)
};
result.into_result().map_err(|()| llvm_err(dcx, LlvmError::RunLlvmPasses))
}
@ -617,7 +620,7 @@ pub(crate) unsafe fn optimize(
if config.emit_no_opt_bc {
let out = cgcx.output_filenames.temp_path_ext("no-opt.bc", module_name);
let out = path_to_c_string(&out);
llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
unsafe { llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()) };
}
if let Some(opt_level) = config.opt_level {
@ -627,7 +630,7 @@ pub(crate) unsafe fn optimize(
_ if cgcx.opts.cg.linker_plugin_lto.enabled() => llvm::OptStage::PreLinkThinLTO,
_ => llvm::OptStage::PreLinkNoLTO,
};
return llvm_optimize(cgcx, dcx, module, config, opt_level, opt_stage);
return unsafe { llvm_optimize(cgcx, dcx, module, config, opt_level, opt_stage) };
}
Ok(())
}
@ -692,10 +695,12 @@ pub(crate) unsafe fn codegen(
where
F: FnOnce(&'ll mut PassManager<'ll>) -> R,
{
let cpm = llvm::LLVMCreatePassManager();
llvm::LLVMAddAnalysisPasses(tm, cpm);
llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
f(cpm)
unsafe {
let cpm = llvm::LLVMCreatePassManager();
llvm::LLVMAddAnalysisPasses(tm, cpm);
llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
f(cpm)
}
}
// Two things to note:
@ -757,7 +762,9 @@ pub(crate) unsafe fn codegen(
let _timer = cgcx
.prof
.generic_activity_with_arg("LLVM_module_codegen_embed_bitcode", &*module.name);
embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data);
unsafe {
embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data);
}
}
}
@ -793,7 +800,8 @@ pub(crate) unsafe fn codegen(
cursor.position() as size_t
}
let result = llvm::LLVMRustPrintModule(llmod, out_c.as_ptr(), demangle_callback);
let result =
unsafe { llvm::LLVMRustPrintModule(llmod, out_c.as_ptr(), demangle_callback) };
if result == llvm::LLVMRustResult::Success {
record_artifact_size(&cgcx.prof, "llvm_ir", &out);
@ -812,22 +820,24 @@ pub(crate) unsafe fn codegen(
// binaries. So we must clone the module to produce the asm output
// if we are also producing object code.
let llmod = if let EmitObj::ObjectCode(_) = config.emit_obj {
llvm::LLVMCloneModule(llmod)
unsafe { llvm::LLVMCloneModule(llmod) }
} else {
llmod
};
with_codegen(tm, llmod, config.no_builtins, |cpm| {
write_output_file(
dcx,
tm,
cpm,
llmod,
&path,
None,
llvm::FileType::AssemblyFile,
&cgcx.prof,
)
})?;
unsafe {
with_codegen(tm, llmod, config.no_builtins, |cpm| {
write_output_file(
dcx,
tm,
cpm,
llmod,
&path,
None,
llvm::FileType::AssemblyFile,
&cgcx.prof,
)
})?;
}
}
match config.emit_obj {
@ -851,18 +861,20 @@ pub(crate) unsafe fn codegen(
(_, SplitDwarfKind::Split) => Some(dwo_out.as_path()),
};
with_codegen(tm, llmod, config.no_builtins, |cpm| {
write_output_file(
dcx,
tm,
cpm,
llmod,
&obj_out,
dwo_out,
llvm::FileType::ObjectFile,
&cgcx.prof,
)
})?;
unsafe {
with_codegen(tm, llmod, config.no_builtins, |cpm| {
write_output_file(
dcx,
tm,
cpm,
llmod,
&obj_out,
dwo_out,
llvm::FileType::ObjectFile,
&cgcx.prof,
)
})?;
}
}
EmitObj::Bitcode => {
@ -1013,44 +1025,46 @@ unsafe fn embed_bitcode(
// reason (see issue #90326 for historical background).
let is_aix = target_is_aix(cgcx);
let is_apple = target_is_apple(cgcx);
if is_apple || is_aix || cgcx.opts.target_triple.triple().starts_with("wasm") {
// We don't need custom section flags, create LLVM globals.
let llconst = common::bytes_in_context(llcx, bitcode);
let llglobal = llvm::LLVMAddGlobal(
llmod,
common::val_ty(llconst),
c"rustc.embedded.module".as_ptr().cast(),
);
llvm::LLVMSetInitializer(llglobal, llconst);
unsafe {
if is_apple || is_aix || cgcx.opts.target_triple.triple().starts_with("wasm") {
// We don't need custom section flags, create LLVM globals.
let llconst = common::bytes_in_context(llcx, bitcode);
let llglobal = llvm::LLVMAddGlobal(
llmod,
common::val_ty(llconst),
c"rustc.embedded.module".as_ptr().cast(),
);
llvm::LLVMSetInitializer(llglobal, llconst);
let section = bitcode_section_name(cgcx);
llvm::LLVMSetSection(llglobal, section.as_ptr().cast());
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
let section = bitcode_section_name(cgcx);
llvm::LLVMSetSection(llglobal, section.as_ptr().cast());
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
let llconst = common::bytes_in_context(llcx, cmdline.as_bytes());
let llglobal = llvm::LLVMAddGlobal(
llmod,
common::val_ty(llconst),
c"rustc.embedded.cmdline".as_ptr().cast(),
);
llvm::LLVMSetInitializer(llglobal, llconst);
let section = if is_apple {
c"__LLVM,__cmdline"
} else if is_aix {
c".info"
let llconst = common::bytes_in_context(llcx, cmdline.as_bytes());
let llglobal = llvm::LLVMAddGlobal(
llmod,
common::val_ty(llconst),
c"rustc.embedded.cmdline".as_ptr().cast(),
);
llvm::LLVMSetInitializer(llglobal, llconst);
let section = if is_apple {
c"__LLVM,__cmdline"
} else if is_aix {
c".info"
} else {
c".llvmcmd"
};
llvm::LLVMSetSection(llglobal, section.as_ptr().cast());
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
} else {
c".llvmcmd"
};
llvm::LLVMSetSection(llglobal, section.as_ptr().cast());
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
} else {
// We need custom section flags, so emit module-level inline assembly.
let section_flags = if cgcx.is_pe_coff { "n" } else { "e" };
let asm = create_section_with_flags_asm(".llvmbc", section_flags, bitcode);
llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len());
let asm = create_section_with_flags_asm(".llvmcmd", section_flags, cmdline.as_bytes());
llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len());
// We need custom section flags, so emit module-level inline assembly.
let section_flags = if cgcx.is_pe_coff { "n" } else { "e" };
let asm = create_section_with_flags_asm(".llvmbc", section_flags, bitcode);
llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len());
let asm = create_section_with_flags_asm(".llvmcmd", section_flags, cmdline.as_bytes());
llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len());
}
}
}