diff options
Diffstat (limited to 'compiler/rustc_codegen_ssa/src')
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/link.rs | 215 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/write.rs | 34 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/base.rs | 41 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/lib.rs | 26 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/analyze.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/block.rs | 21 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/constant.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/debuginfo.rs | 109 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/intrinsic.rs | 31 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/mod.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/traits/backend.rs | 4 |
12 files changed, 313 insertions, 183 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 46febf049c3..55fddb38e10 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2,7 +2,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_fs_util::fix_windows_verbatim_for_gcc; use rustc_hir::def_id::CrateNum; -use rustc_middle::middle::cstore::{EncodedMetadata, LibSource, NativeLib}; +use rustc_middle::middle::cstore::{EncodedMetadata, LibSource}; use rustc_middle::middle::dependency_format::Linkage; use rustc_session::config::{self, CFGuard, CrateType, DebugInfo}; use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SanitizerSet}; @@ -21,7 +21,10 @@ use super::archive::ArchiveBuilder; use super::command::Command; use super::linker::{self, Linker}; use super::rpath::{self, RPathConfig}; -use crate::{looks_like_rust_object_file, CodegenResults, CrateInfo, METADATA_FILENAME}; +use crate::{ + looks_like_rust_object_file, CodegenResults, CompiledModule, CrateInfo, NativeLib, + METADATA_FILENAME, +}; use cc::windows_registry; use tempfile::Builder as TempFileBuilder; @@ -96,6 +99,9 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( path.as_ref(), target_cpu, ); + if sess.opts.debugging_opts.split_dwarf == config::SplitDwarfKind::Split { + link_dwarf_object(sess, &out_filename); + } } } if sess.opts.json_artifact_notifications { @@ -107,22 +113,30 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( // Remove the temporary object file and metadata if we aren't saving temps sess.time("link_binary_remove_temps", || { if !sess.opts.cg.save_temps { + let remove_temps_from_module = |module: &CompiledModule| { + if let Some(ref obj) = module.object { + remove(sess, obj); + } + + if let Some(ref obj) = module.dwarf_object { + remove(sess, obj); + } + }; + if sess.opts.output_types.should_codegen() && !preserve_objects_for_their_debuginfo(sess) { - for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) { - remove(sess, obj); + for module in &codegen_results.modules { + remove_temps_from_module(module); } } + if let Some(ref metadata_module) = codegen_results.metadata_module { - if let Some(ref obj) = metadata_module.object { - remove(sess, obj); - } + remove_temps_from_module(metadata_module); } + if let Some(ref allocator_module) = codegen_results.allocator_module { - if let Some(ref obj) = allocator_module.object { - remove(sess, obj); - } + remove_temps_from_module(allocator_module); } } }); @@ -279,12 +293,12 @@ pub fn emit_metadata(sess: &Session, metadata: &EncodedMetadata, tmpdir: &MaybeT out_filename } -// Create an 'rlib' -// -// An rlib in its current incarnation is essentially a renamed .a file. The -// rlib primarily contains the object file of the crate, but it also contains -// all of the object files from native libraries. This is done by unzipping -// native libraries and inserting all of the contents into this archive. +/// Create an 'rlib'. +/// +/// An rlib in its current incarnation is essentially a renamed .a file. The rlib primarily contains +/// the object file of the crate, but it also contains all of the object files from native +/// libraries. This is done by unzipping native libraries and inserting all of the contents into +/// this archive. fn link_rlib<'a, B: ArchiveBuilder<'a>>( sess: &'a Session, codegen_results: &CodegenResults, @@ -379,18 +393,17 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( ab } -// Create a static archive -// -// This is essentially the same thing as an rlib, but it also involves adding -// all of the upstream crates' objects into the archive. This will slurp in -// all of the native libraries of upstream dependencies as well. -// -// Additionally, there's no way for us to link dynamic libraries, so we warn -// about all dynamic library dependencies that they're not linked in. -// -// There's no need to include metadata in a static archive, so ensure to not -// link in the metadata object file (and also don't prepare the archive with a -// metadata file). +/// Create a static archive. +/// +/// This is essentially the same thing as an rlib, but it also involves adding all of the upstream +/// crates' objects into the archive. This will slurp in all of the native libraries of upstream +/// dependencies as well. +/// +/// Additionally, there's no way for us to link dynamic libraries, so we warn about all dynamic +/// library dependencies that they're not linked in. +/// +/// There's no need to include metadata in a static archive, so ensure to not link in the metadata +/// object file (and also don't prepare the archive with a metadata file). fn link_staticlib<'a, B: ArchiveBuilder<'a>>( sess: &'a Session, codegen_results: &CodegenResults, @@ -447,10 +460,73 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>( } } -// Create a dynamic library or executable -// -// This will invoke the system linker/cc to create the resulting file. This -// links to all upstream files as well. +fn escape_stdout_stderr_string(s: &[u8]) -> String { + str::from_utf8(s).map(|s| s.to_owned()).unwrap_or_else(|_| { + let mut x = "Non-UTF-8 output: ".to_string(); + x.extend(s.iter().flat_map(|&b| ascii::escape_default(b)).map(char::from)); + x + }) +} + +const LLVM_DWP_EXECUTABLE: &'static str = "rust-llvm-dwp"; + +/// Invoke `llvm-dwp` (shipped alongside rustc) to link `dwo` files from Split DWARF into a `dwp` +/// file. +fn link_dwarf_object<'a>(sess: &'a Session, executable_out_filename: &Path) { + info!("preparing dwp to {}.dwp", executable_out_filename.to_str().unwrap()); + + let dwp_out_filename = executable_out_filename.with_extension("dwp"); + let mut cmd = Command::new(LLVM_DWP_EXECUTABLE); + cmd.arg("-e"); + cmd.arg(executable_out_filename); + cmd.arg("-o"); + cmd.arg(&dwp_out_filename); + + let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(false); + if let Some(path) = env::var_os("PATH") { + new_path.extend(env::split_paths(&path)); + } + let new_path = env::join_paths(new_path).unwrap(); + cmd.env("PATH", new_path); + + info!("{:?}", &cmd); + match sess.time("run_dwp", || cmd.output()) { + Ok(prog) if !prog.status.success() => { + sess.struct_err(&format!( + "linking dwarf objects with `{}` failed: {}", + LLVM_DWP_EXECUTABLE, prog.status + )) + .note(&format!("{:?}", &cmd)) + .note(&escape_stdout_stderr_string(&prog.stdout)) + .note(&escape_stdout_stderr_string(&prog.stderr)) + .emit(); + info!("linker stderr:\n{}", escape_stdout_stderr_string(&prog.stderr)); + info!("linker stdout:\n{}", escape_stdout_stderr_string(&prog.stdout)); + } + Ok(_) => {} + Err(e) => { + let dwp_not_found = e.kind() == io::ErrorKind::NotFound; + let mut err = if dwp_not_found { + sess.struct_err(&format!("linker `{}` not found", LLVM_DWP_EXECUTABLE)) + } else { + sess.struct_err(&format!("could not exec the linker `{}`", LLVM_DWP_EXECUTABLE)) + }; + + err.note(&e.to_string()); + + if !dwp_not_found { + err.note(&format!("{:?}", &cmd)); + } + + err.emit(); + } + } +} + +/// Create a dynamic library or executable. +/// +/// This will invoke the system linker/cc to create the resulting file. This links to all upstream +/// files as well. fn link_natively<'a, B: ArchiveBuilder<'a>>( sess: &'a Session, crate_type: CrateType, @@ -662,7 +738,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( prog.status )) .note(&format!("{:?}", &cmd)) - .note(&escape_string(&output)) + .note(&escape_stdout_stderr_string(&output)) .emit(); // If MSVC's `link.exe` was expected but the return code @@ -715,8 +791,8 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( sess.abort_if_errors(); } - info!("linker stderr:\n{}", escape_string(&prog.stderr)); - info!("linker stdout:\n{}", escape_string(&prog.stdout)); + info!("linker stderr:\n{}", escape_stdout_stderr_string(&prog.stderr)); + info!("linker stdout:\n{}", escape_stdout_stderr_string(&prog.stdout)); } Err(e) => { let linker_not_found = e.kind() == io::ErrorKind::NotFound; @@ -962,6 +1038,13 @@ fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool { return false; } + // Single mode keeps debuginfo in the same object file, but in such a way that it it skipped + // by the linker - so it's expected that when codegen units are linked together that this + // debuginfo would be lost without keeping around the temps. + if sess.opts.debugging_opts.split_dwarf == config::SplitDwarfKind::Single { + return true; + } + // If we're on OSX then the equivalent of split dwarf is turned on by // default. The final executable won't actually have any debug information // except it'll have pointers to elsewhere. Historically we've always run @@ -1677,17 +1760,15 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( cmd.take_cmd() } -// # Native library linking -// -// User-supplied library search paths (-L on the command line). These are -// the same paths used to find Rust crates, so some of them may have been -// added already by the previous crate linking code. This only allows them -// to be found at compile time so it is still entirely up to outside -// forces to make sure that library can be found at runtime. -// -// Also note that the native libraries linked here are only the ones located -// in the current crate. Upstream crates with native library dependencies -// may have their native library pulled in above. +/// # Native library linking +/// +/// User-supplied library search paths (-L on the command line). These are the same paths used to +/// find Rust crates, so some of them may have been added already by the previous crate linking +/// code. This only allows them to be found at compile time so it is still entirely up to outside +/// forces to make sure that library can be found at runtime. +/// +/// Also note that the native libraries linked here are only the ones located in the current crate. +/// Upstream crates with native library dependencies may have their native library pulled in above. fn add_local_native_libraries( cmd: &mut dyn Linker, sess: &Session, @@ -1727,11 +1808,10 @@ fn add_local_native_libraries( } } -// # Rust Crate linking -// -// Rust crates are not considered at all when creating an rlib output. All -// dependencies will be linked when producing the final output (instead of -// the intermediate rlib version) +/// # Rust Crate linking +/// +/// Rust crates are not considered at all when creating an rlib output. All dependencies will be +/// linked when producing the final output (instead of the intermediate rlib version). fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( cmd: &mut dyn Linker, sess: &'a Session, @@ -1996,24 +2076,21 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( } } -// Link in all of our upstream crates' native dependencies. Remember that -// all of these upstream native dependencies are all non-static -// dependencies. We've got two cases then: -// -// 1. The upstream crate is an rlib. In this case we *must* link in the -// native dependency because the rlib is just an archive. -// -// 2. The upstream crate is a dylib. In order to use the dylib, we have to -// have the dependency present on the system somewhere. Thus, we don't -// gain a whole lot from not linking in the dynamic dependency to this -// crate as well. -// -// The use case for this is a little subtle. In theory the native -// dependencies of a crate are purely an implementation detail of the crate -// itself, but the problem arises with generic and inlined functions. If a -// generic function calls a native function, then the generic function must -// be instantiated in the target crate, meaning that the native symbol must -// also be resolved in the target crate. +/// Link in all of our upstream crates' native dependencies. Remember that all of these upstream +/// native dependencies are all non-static dependencies. We've got two cases then: +/// +/// 1. The upstream crate is an rlib. In this case we *must* link in the native dependency because +/// the rlib is just an archive. +/// +/// 2. The upstream crate is a dylib. In order to use the dylib, we have to have the dependency +/// present on the system somewhere. Thus, we don't gain a whole lot from not linking in the +/// dynamic dependency to this crate as well. +/// +/// The use case for this is a little subtle. In theory the native dependencies of a crate are +/// purely an implementation detail of the crate itself, but the problem arises with generic and +/// inlined functions. If a generic function calls a native function, then the generic function +/// must be instantiated in the target crate, meaning that the native symbol must also be resolved +/// in the target crate. fn add_upstream_native_libraries( cmd: &mut dyn Linker, sess: &Session, diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 7f2bb7b5bcd..c84b87964b8 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -274,17 +274,20 @@ impl ModuleConfig { } } -// HACK(eddyb) work around `#[derive]` producing wrong bounds for `Clone`. -pub struct TargetMachineFactory<B: WriteBackendMethods>( - pub Arc<dyn Fn() -> Result<B::TargetMachine, String> + Send + Sync>, -); - -impl<B: WriteBackendMethods> Clone for TargetMachineFactory<B> { - fn clone(&self) -> Self { - TargetMachineFactory(self.0.clone()) - } +/// Configuration passed to the function returned by the `target_machine_factory`. +pub struct TargetMachineFactoryConfig { + /// Split DWARF is enabled in LLVM by checking that `TM.MCOptions.SplitDwarfFile` isn't empty, + /// so the path to the dwarf object has to be provided when we create the target machine. + /// This can be ignored by backends which do not need it for their Split DWARF support. + pub split_dwarf_file: Option<PathBuf>, } +pub type TargetMachineFactoryFn<B> = Arc< + dyn Fn(TargetMachineFactoryConfig) -> Result<<B as WriteBackendMethods>::TargetMachine, String> + + Send + + Sync, +>; + pub type ExportedSymbols = FxHashMap<CrateNum, Arc<Vec<(String, SymbolExportLevel)>>>; /// Additional resources used by optimize_and_codegen (not module specific) @@ -305,12 +308,13 @@ pub struct CodegenContext<B: WriteBackendMethods> { pub regular_module_config: Arc<ModuleConfig>, pub metadata_module_config: Arc<ModuleConfig>, pub allocator_module_config: Arc<ModuleConfig>, - pub tm_factory: TargetMachineFactory<B>, + pub tm_factory: TargetMachineFactoryFn<B>, pub msvc_imps_needed: bool, pub is_pe_coff: bool, pub target_pointer_width: u32, pub target_arch: String, pub debuginfo: config::DebugInfo, + pub split_dwarf_kind: config::SplitDwarfKind, // Number of cgus excluding the allocator/metadata modules pub total_cgus: usize, @@ -627,6 +631,12 @@ fn produce_final_output_artifacts( } } + if let Some(ref path) = module.dwarf_object { + if !keep_numbered_objects { + remove(sess, path); + } + } + if let Some(ref path) = module.bytecode { if !keep_numbered_bitcode { remove(sess, path); @@ -849,6 +859,7 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>( name: module.name, kind: ModuleKind::Regular, object, + dwarf_object: None, bytecode: None, })) } @@ -1020,13 +1031,14 @@ fn start_executing_work<B: ExtraBackendMethods>( regular_module_config: regular_config, metadata_module_config: metadata_config, allocator_module_config: allocator_config, - tm_factory: TargetMachineFactory(backend.target_machine_factory(tcx.sess, ol)), + tm_factory: backend.target_machine_factory(tcx.sess, ol), total_cgus, msvc_imps_needed: msvc_imps_needed(tcx), is_pe_coff: tcx.sess.target.is_like_windows, target_pointer_width: tcx.sess.target.pointer_width, target_arch: tcx.sess.target.arch.clone(), debuginfo: tcx.sess.opts.debuginfo, + split_dwarf_kind: tcx.sess.opts.debugging_opts.split_dwarf, }; // This is the "main loop" of parallel work happening for parallel codegen. diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 21138f967a2..f47d2ada61a 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -1,18 +1,3 @@ -//! Codegen the completed AST to the LLVM IR. -//! -//! Some functions here, such as `codegen_block` and `codegen_expr`, return a value -- -//! the result of the codegen to LLVM -- while others, such as `codegen_fn` -//! and `mono_item`, are called only for the side effect of adding a -//! particular definition to the LLVM IR output we're producing. -//! -//! Hopefully useful general knowledge about codegen: -//! -//! * There's no way to find out the `Ty` type of a `Value`. Doing so -//! would be "trying to get the eggs out of an omelette" (credit: -//! pcwalton). You can, instead, find out its `llvm::Type` by calling `val_ty`, -//! but one `llvm::Type` corresponds to many `Ty`s; for instance, `tup(int, int, -//! int)` and `rec(x=int, y=int, z=int)` will have the same `llvm::Type`. - use crate::back::write::{ compute_per_cgu_lto_type, start_async_codegen, submit_codegened_module_to_llvm, submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm, ComputedLtoType, OngoingCodegen, @@ -46,7 +31,6 @@ use rustc_session::cgu_reuse_tracker::CguReuse; use rustc_session::config::{self, EntryFnType}; use rustc_session::utils::NativeLibKind; use rustc_session::Session; -use rustc_symbol_mangling::test as symbol_names_test; use rustc_target::abi::{Align, LayoutOf, VariantIdx}; use std::cmp; @@ -486,8 +470,6 @@ pub fn codegen_crate<B: ExtraBackendMethods>( ongoing_codegen.codegen_finished(tcx); - finalize_tcx(tcx); - ongoing_codegen.check_for_errors(tcx.sess); return ongoing_codegen; @@ -688,14 +670,8 @@ pub fn codegen_crate<B: ExtraBackendMethods>( total_codegen_time.into_inner(), ); - rustc_incremental::assert_module_sources::assert_module_sources(tcx); - - symbol_names_test::report_symbol_names(tcx); - ongoing_codegen.check_for_errors(tcx.sess); - finalize_tcx(tcx); - ongoing_codegen.into_inner() } @@ -746,18 +722,6 @@ impl<B: ExtraBackendMethods> Drop for AbortCodegenOnDrop<B> { } } -fn finalize_tcx(tcx: TyCtxt<'_>) { - tcx.sess.time("assert_dep_graph", || rustc_incremental::assert_dep_graph(tcx)); - tcx.sess.time("serialize_dep_graph", || rustc_incremental::save_dep_graph(tcx)); - - // We assume that no queries are run past here. If there are new queries - // after this point, they'll show up as "<unknown>" in self-profiling data. - { - let _prof_timer = tcx.prof.generic_activity("self_profile_alloc_query_strings"); - tcx.alloc_self_profile_query_strings(); - } -} - impl CrateInfo { pub fn new(tcx: TyCtxt<'_>) -> CrateInfo { let mut info = CrateInfo { @@ -766,7 +730,7 @@ impl CrateInfo { profiler_runtime: None, is_no_builtins: Default::default(), native_libraries: Default::default(), - used_libraries: tcx.native_libraries(LOCAL_CRATE), + used_libraries: tcx.native_libraries(LOCAL_CRATE).iter().map(Into::into).collect(), link_args: tcx.link_args(LOCAL_CRATE), crate_name: Default::default(), used_crates_dynamic: cstore::used_crates(tcx, LinkagePreference::RequireDynamic), @@ -787,7 +751,8 @@ impl CrateInfo { info.missing_lang_items.reserve(n_crates); for &cnum in crates.iter() { - info.native_libraries.insert(cnum, tcx.native_libraries(cnum)); + info.native_libraries + .insert(cnum, tcx.native_libraries(cnum).iter().map(Into::into).collect()); info.crate_name.insert(cnum, tcx.crate_name(cnum).to_string()); info.used_crate_source.insert(cnum, tcx.used_crate_source(cnum)); if tcx.is_panic_runtime(cnum) { diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 8ec1eed4404..e27eac3f69b 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -21,15 +21,17 @@ extern crate tracing; #[macro_use] extern crate rustc_middle; +use rustc_ast as ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; use rustc_hir::def_id::CrateNum; use rustc_hir::LangItem; use rustc_middle::dep_graph::WorkProduct; -use rustc_middle::middle::cstore::{CrateSource, LibSource, NativeLib}; +use rustc_middle::middle::cstore::{self, CrateSource, LibSource}; use rustc_middle::middle::dependency_format::Dependencies; use rustc_middle::ty::query::Providers; use rustc_session::config::{OutputFilenames, OutputType, RUST_CGU_EXT}; +use rustc_session::utils::NativeLibKind; use rustc_span::symbol::Symbol; use std::path::{Path, PathBuf}; @@ -64,13 +66,15 @@ impl<M> ModuleCodegen<M> { pub fn into_compiled_module( self, emit_obj: bool, + emit_dwarf_obj: bool, emit_bc: bool, outputs: &OutputFilenames, ) -> CompiledModule { let object = emit_obj.then(|| outputs.temp_path(OutputType::Object, Some(&self.name))); + let dwarf_object = emit_dwarf_obj.then(|| outputs.temp_path_dwo(Some(&self.name))); let bytecode = emit_bc.then(|| outputs.temp_path(OutputType::Bitcode, Some(&self.name))); - CompiledModule { name: self.name.clone(), kind: self.kind, object, bytecode } + CompiledModule { name: self.name.clone(), kind: self.kind, object, dwarf_object, bytecode } } } @@ -79,6 +83,7 @@ pub struct CompiledModule { pub name: String, pub kind: ModuleKind, pub object: Option<PathBuf>, + pub dwarf_object: Option<PathBuf>, pub bytecode: Option<PathBuf>, } @@ -102,6 +107,19 @@ bitflags::bitflags! { } } +#[derive(Clone, Debug, Encodable, Decodable, HashStable)] +pub struct NativeLib { + pub kind: NativeLibKind, + pub name: Option<Symbol>, + pub cfg: Option<ast::MetaItem>, +} + +impl From<&cstore::NativeLib> for NativeLib { + fn from(lib: &cstore::NativeLib) -> Self { + NativeLib { kind: lib.kind, name: lib.name, cfg: lib.cfg.clone() } + } +} + /// Misc info we load from metadata to persist beyond the tcx. /// /// Note: though `CrateNum` is only meaningful within the same tcx, information within `CrateInfo` @@ -116,9 +134,9 @@ pub struct CrateInfo { pub compiler_builtins: Option<CrateNum>, pub profiler_runtime: Option<CrateNum>, pub is_no_builtins: FxHashSet<CrateNum>, - pub native_libraries: FxHashMap<CrateNum, Lrc<Vec<NativeLib>>>, + pub native_libraries: FxHashMap<CrateNum, Vec<NativeLib>>, pub crate_name: FxHashMap<CrateNum, String>, - pub used_libraries: Lrc<Vec<NativeLib>>, + pub used_libraries: Vec<NativeLib>, pub link_args: Lrc<Vec<String>>, pub used_crate_source: FxHashMap<CrateNum, Lrc<CrateSource>>, pub used_crates_static: Vec<(CrateNum, LibSource)>, diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index 44bb0deeae9..57e49ba8d1a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -112,12 +112,12 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { }; // Allow uses of projections that are ZSTs or from scalar fields. - let is_consume = match context { + let is_consume = matches!( + context, PlaceContext::NonMutatingUse( NonMutatingUseContext::Copy | NonMutatingUseContext::Move, - ) => true, - _ => false, - }; + ) + ); if is_consume { let base_ty = mir::Place::ty_from(place_ref.local, proj_base, self.fx.mir, cx.tcx()); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index e59832a8eed..ecac05fd955 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -522,7 +522,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mut bx: Bx, terminator: &mir::Terminator<'tcx>, func: &mir::Operand<'tcx>, - args: &Vec<mir::Operand<'tcx>>, + args: &[mir::Operand<'tcx>], destination: &Option<(mir::Place<'tcx>, mir::BasicBlock)>, cleanup: Option<mir::BasicBlock>, fn_span: Span, @@ -1395,6 +1395,25 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { dst: PlaceRef<'tcx, Bx::Value>, ) { let src = self.codegen_operand(bx, src); + + // Special-case transmutes between scalars as simple bitcasts. + match (&src.layout.abi, &dst.layout.abi) { + (abi::Abi::Scalar(src_scalar), abi::Abi::Scalar(dst_scalar)) => { + // HACK(eddyb) LLVM doesn't like `bitcast`s between pointers and non-pointers. + if (src_scalar.value == abi::Pointer) == (dst_scalar.value == abi::Pointer) { + assert_eq!(src.layout.size, dst.layout.size); + + // NOTE(eddyb) the `from_immediate` and `to_immediate_scalar` + // conversions allow handling `bool`s the same as `u8`s. + let src = bx.from_immediate(src.immediate()); + let src_as_dst = bx.bitcast(src, bx.backend_type(dst.layout)); + Immediate(bx.to_immediate_scalar(src_as_dst, dst_scalar)).store(bx, dst); + return; + } + } + _ => {} + } + let llty = bx.backend_type(src.layout); let cast_ptr = bx.pointercast(dst.llval, bx.type_ptr_to(llty)); let align = src.layout.align.abi.min(dst.align); diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index c8001b8daf0..3a85c268e0e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -11,7 +11,7 @@ use super::FunctionCx; impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn eval_mir_constant_to_operand( - &mut self, + &self, bx: &mut Bx, constant: &mir::Constant<'tcx>, ) -> Result<OperandRef<'tcx, Bx::Value>, ErrorHandled> { @@ -21,7 +21,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } pub fn eval_mir_constant( - &mut self, + &self, constant: &mir::Constant<'tcx>, ) -> Result<ConstValue<'tcx>, ErrorHandled> { match self.monomorphize(constant.literal).val { diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index c4191a4e23d..f1eae605da0 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -8,7 +8,7 @@ use rustc_span::symbol::{kw, Symbol}; use rustc_span::{BytePos, Span}; use rustc_target::abi::{LayoutOf, Size}; -use super::operand::OperandValue; +use super::operand::{OperandRef, OperandValue}; use super::place::PlaceRef; use super::{FunctionCx, LocalRef}; @@ -116,6 +116,24 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { span } + fn spill_operand_to_stack( + operand: &OperandRef<'tcx, Bx::Value>, + name: Option<String>, + bx: &mut Bx, + ) -> PlaceRef<'tcx, Bx::Value> { + // "Spill" the value onto the stack, for debuginfo, + // without forcing non-debuginfo uses of the local + // to also load from the stack every single time. + // FIXME(#68817) use `llvm.dbg.value` instead, + // at least for the cases which LLVM handles correctly. + let spill_slot = PlaceRef::alloca(bx, operand.layout); + if let Some(name) = name { + bx.set_var_name(spill_slot.llval, &(name + ".dbg.spill")); + } + operand.val.store(bx, spill_slot); + spill_slot + } + /// Apply debuginfo and/or name, after creating the `alloca` for a local, /// or initializing the local with an operand (whichever applies). pub fn debug_introduce_local(&self, bx: &mut Bx, local: mir::Local) { @@ -152,7 +170,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // (after #67586 gets fixed). None } else { - let name = kw::Invalid; + let name = kw::Empty; let decl = &self.mir.local_decls[local]; let dbg_var = if full_debug_info { self.adjusted_span_and_dbg_scope(decl.source_info).map( @@ -186,7 +204,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { None } else { Some(match whole_local_var.or(fallback_var) { - Some(var) if var.name != kw::Invalid => var.name.to_string(), + Some(var) if var.name != kw::Empty => var.name.to_string(), _ => format!("{:?}", local), }) }; @@ -226,17 +244,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { return; } - // "Spill" the value onto the stack, for debuginfo, - // without forcing non-debuginfo uses of the local - // to also load from the stack every single time. - // FIXME(#68817) use `llvm.dbg.value` instead, - // at least for the cases which LLVM handles correctly. - let spill_slot = PlaceRef::alloca(bx, operand.layout); - if let Some(name) = name { - bx.set_var_name(spill_slot.llval, &(name + ".dbg.spill")); - } - operand.val.store(bx, spill_slot); - spill_slot + Self::spill_operand_to_stack(operand, name, bx) } LocalRef::Place(place) => *place, @@ -308,6 +316,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { /// Partition all `VarDebugInfo` in `self.mir`, by their base `Local`. pub fn compute_per_local_var_debug_info( &self, + bx: &mut Bx, ) -> Option<IndexVec<mir::Local, Vec<PerLocalVarDebugInfo<'tcx, Bx::DIVariable>>>> { let full_debug_info = self.cx.sess().opts.debuginfo == DebugInfo::Full; @@ -322,31 +331,63 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } else { None }; + let dbg_var = dbg_scope_and_span.map(|(dbg_scope, _, span)| { - let place = var.place; - let var_ty = self.monomorphized_place_ty(place.as_ref()); - let var_kind = if self.mir.local_kind(place.local) == mir::LocalKind::Arg - && place.projection.is_empty() - && var.source_info.scope == mir::OUTERMOST_SOURCE_SCOPE - { - let arg_index = place.local.index() - 1; - - // FIXME(eddyb) shouldn't `ArgumentVariable` indices be - // offset in closures to account for the hidden environment? - // Also, is this `+ 1` needed at all? - VariableKind::ArgumentVariable(arg_index + 1) - } else { - VariableKind::LocalVariable + let (var_ty, var_kind) = match var.value { + mir::VarDebugInfoContents::Place(place) => { + let var_ty = self.monomorphized_place_ty(place.as_ref()); + let var_kind = if self.mir.local_kind(place.local) == mir::LocalKind::Arg + && place.projection.is_empty() + && var.source_info.scope == mir::OUTERMOST_SOURCE_SCOPE + { + let arg_index = place.local.index() - 1; + + // FIXME(eddyb) shouldn't `ArgumentVariable` indices be + // offset in closures to account for the hidden environment? + // Also, is this `+ 1` needed at all? + VariableKind::ArgumentVariable(arg_index + 1) + } else { + VariableKind::LocalVariable + }; + (var_ty, var_kind) + } + mir::VarDebugInfoContents::Const(c) => { + let ty = self.monomorphize(c.literal.ty); + (ty, VariableKind::LocalVariable) + } }; + self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span) }); - per_local[var.place.local].push(PerLocalVarDebugInfo { - name: var.name, - source_info: var.source_info, - dbg_var, - projection: var.place.projection, - }); + match var.value { + mir::VarDebugInfoContents::Place(place) => { + per_local[place.local].push(PerLocalVarDebugInfo { + name: var.name, + source_info: var.source_info, + dbg_var, + projection: place.projection, + }); + } + mir::VarDebugInfoContents::Const(c) => { + if let Some(dbg_var) = dbg_var { + let dbg_loc = match self.dbg_loc(var.source_info) { + Some(dbg_loc) => dbg_loc, + None => continue, + }; + + if let Ok(operand) = self.eval_mir_constant_to_operand(bx, &c) { + let base = Self::spill_operand_to_stack( + &operand, + Some(var.name.to_string()), + bx, + ); + + bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, Size::ZERO, &[]); + } + } + } + } } Some(per_local) } diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 72a64a8c510..80e3ed75b85 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -83,9 +83,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { return; } - sym::unreachable => { - return; - } sym::va_start => bx.va_start(args[0].immediate()), sym::va_end => bx.va_end(args[0].immediate()), sym::size_of_val => { @@ -106,8 +103,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.const_usize(bx.layout_of(tp_ty).align.abi.bytes()) } } - sym::size_of - | sym::pref_align_of + sym::pref_align_of | sym::min_align_of | sym::needs_drop | sym::type_id @@ -119,10 +115,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { .unwrap(); OperandRef::from_const(bx, value, ret_ty).immediate_or_packed_pair(bx) } - // Effectively no-op - sym::forget => { - return; - } sym::offset => { let ptr = args[0].immediate(); let offset = args[1].immediate(); @@ -218,9 +210,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow - | sym::wrapping_add - | sym::wrapping_sub - | sym::wrapping_mul | sym::unchecked_div | sym::unchecked_rem | sym::unchecked_shl @@ -254,9 +243,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { return; } - sym::wrapping_add => bx.add(args[0].immediate(), args[1].immediate()), - sym::wrapping_sub => bx.sub(args[0].immediate(), args[1].immediate()), - sym::wrapping_mul => bx.mul(args[0].immediate(), args[1].immediate()), sym::exact_div => { if signed { bx.exactsdiv(args[0].immediate(), args[1].immediate()) @@ -538,8 +524,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; let ty = substs.type_at(0); - if int_type_width_signed(ty, bx.tcx()).is_some() { - bx.atomic_rmw(atom_op, args[0].immediate(), args[1].immediate(), order) + if int_type_width_signed(ty, bx.tcx()).is_some() + || (ty.is_unsafe_ptr() && op == "xchg") + { + let mut ptr = args[0].immediate(); + let mut val = args[1].immediate(); + if ty.is_unsafe_ptr() { + // Some platforms do not support atomic operations on pointers, + // so we cast to integer first. + let ptr_llty = bx.type_ptr_to(bx.type_isize()); + ptr = bx.pointercast(ptr, ptr_llty); + val = bx.ptrtoint(val, bx.type_isize()); + } + bx.atomic_rmw(atom_op, ptr, val, order) } else { return invalid_monomorphization(ty); } diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 640f805d5e8..285140060be 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -186,7 +186,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( caller_location: None, }; - fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(); + fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut bx); for const_ in &mir.required_consts { if let Err(err) = fx.eval_mir_constant(const_) { diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 2ad470c2693..e3a6cabd600 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -489,6 +489,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Rvalue::Discriminant(ref place) => { let discr_ty = rvalue.ty(self.mir, bx.tcx()); + let discr_ty = self.monomorphize(discr_ty); let discr = self .codegen_place(&mut bx, place.as_ref()) .codegen_get_discr(&mut bx, discr_ty); diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index b9c555c2eb0..f28db2fe84b 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -1,5 +1,6 @@ use super::write::WriteBackendMethods; use super::CodegenObject; +use crate::back::write::TargetMachineFactoryFn; use crate::{CodegenResults, ModuleCodegen}; use rustc_ast::expand::allocator::AllocatorKind; @@ -21,7 +22,6 @@ use rustc_target::spec::Target; pub use rustc_data_structures::sync::MetadataRef; use std::any::Any; -use std::sync::Arc; pub trait BackendTypes { type Value: CodegenObject; @@ -123,7 +123,7 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se &self, sess: &Session, opt_level: config::OptLevel, - ) -> Arc<dyn Fn() -> Result<Self::TargetMachine, String> + Send + Sync>; + ) -> TargetMachineFactoryFn<Self>; fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str; fn tune_cpu<'b>(&self, sess: &'b Session) -> Option<&'b str>; } |
