]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #55593 - nikic:remove-llvm-4-checks, r=rkruppe
authorbors <bors@rust-lang.org>
Mon, 5 Nov 2018 01:41:55 +0000 (01:41 +0000)
committerbors <bors@rust-lang.org>
Mon, 5 Nov 2018 01:41:55 +0000 (01:41 +0000)
Remove checks for LLVM < 4.0

While we still have to support LLVM 4.0 for Emscripten, we can drop checks for LLVM >= 4.0 and < 4.0.

1  2 
src/librustc_codegen_llvm/back/write.rs
src/librustc_codegen_llvm/base.rs

index a88ce69604b356fb90d5f85df4edf349e4739827,dabfa4c540b19589f5c4bfc5aef25b2e34182cf6..d04e80195f054afcb155a8823a099767c11e0e94
  
  use attributes;
  use back::bytecode::{self, RLIB_BYTECODE_EXTENSION};
- use back::lto::{self, ModuleBuffer, ThinBuffer, SerializedModule};
+ use back::lto::{self, ThinBuffer, SerializedModule};
  use back::link::{self, get_linker, remove};
 -use back::command::Command;
 -use back::linker::LinkerInfo;
 -use back::symbol_export::ExportedSymbols;
  use base;
  use consts;
  use memmap;
@@@ -35,9 -38,6 +35,9 @@@ use rustc::util::common::{time_ext, tim
  use rustc_fs_util::{path2cstr, link_or_copy};
  use rustc_data_structures::small_c_str::SmallCStr;
  use rustc_data_structures::svh::Svh;
 +use rustc_codegen_utils::command::Command;
 +use rustc_codegen_utils::linker::LinkerInfo;
 +use rustc_codegen_utils::symbol_export::ExportedSymbols;
  use errors::{self, Handler, Level, DiagnosticBuilder, FatalError, DiagnosticId};
  use errors::emitter::{Emitter};
  use syntax::attr;
@@@ -564,8 -564,8 +564,8 @@@ unsafe fn optimize(cgcx: &CodegenContex
              // Some options cause LLVM bitcode to be emitted, which uses ThinLTOBuffers, so we need
              // to make sure we run LLVM's NameAnonGlobals pass when emitting bitcode; otherwise
              // we'll get errors in LLVM.
-             let using_thin_buffers = llvm::LLVMRustThinLTOAvailable() && (config.emit_bc
-                 || config.obj_is_bitcode || config.emit_bc_compressed || config.embed_bitcode);
+             let using_thin_buffers = config.emit_bc || config.obj_is_bitcode
+                 || config.emit_bc_compressed || config.embed_bitcode;
              let mut have_name_anon_globals_pass = false;
              if !config.no_prepopulate_passes {
                  llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
@@@ -729,15 -729,8 +729,8 @@@ unsafe fn codegen(cgcx: &CodegenContext
  
  
          if write_bc || config.emit_bc_compressed || config.embed_bitcode {
-             let thin;
-             let old;
-             let data = if llvm::LLVMRustThinLTOAvailable() {
-                 thin = ThinBuffer::new(llmod);
-                 thin.data()
-             } else {
-                 old = ModuleBuffer::new(llmod);
-                 old.data()
-             };
+             let thin = ThinBuffer::new(llmod);
+             let data = thin.data();
              timeline.record("make-bc");
  
              if write_bc {
@@@ -1385,12 -1378,8 +1378,8 @@@ fn execute_optimize_work_item(cgcx: &Co
          // builds we don't actually want to LTO the allocator modules if
          // it shows up. This is due to various linker shenanigans that
          // we'll encounter later.
-         //
-         // Additionally here's where we also factor in the current LLVM
-         // version. If it doesn't support ThinLTO we skip this.
          Lto::ThinLocal => {
-             module.kind != ModuleKind::Allocator &&
-                 unsafe { llvm::LLVMRustThinLTOAvailable() }
+             module.kind != ModuleKind::Allocator
          }
      };
  
@@@ -1508,7 -1497,6 +1497,7 @@@ enum Message 
      },
      CodegenComplete,
      CodegenItem,
 +    CodegenAborted,
  }
  
  struct Diagnostic {
@@@ -1789,7 -1777,6 +1778,7 @@@ fn start_executing_work(tcx: TyCtxt
          let mut needs_lto = Vec::new();
          let mut lto_import_only_modules = Vec::new();
          let mut started_lto = false;
 +        let mut codegen_aborted = false;
  
          // This flag tracks whether all items have gone through codegens
          let mut codegen_done = false;
          let mut llvm_start_time = None;
  
          // Run the message loop while there's still anything that needs message
 -        // processing:
 +        // processing. Note that as soon as codegen is aborted we simply want to
 +        // wait for all existing work to finish, so many of the conditions here
 +        // only apply if codegen hasn't been aborted as they represent pending
 +        // work to be done.
          while !codegen_done ||
 -              work_items.len() > 0 ||
                running > 0 ||
 -              needs_lto.len() > 0 ||
 -              lto_import_only_modules.len() > 0 ||
 -              main_thread_worker_state != MainThreadWorkerState::Idle {
 +              (!codegen_aborted && (
 +                  work_items.len() > 0 ||
 +                  needs_lto.len() > 0 ||
 +                  lto_import_only_modules.len() > 0 ||
 +                  main_thread_worker_state != MainThreadWorkerState::Idle
 +              ))
 +        {
  
              // While there are still CGUs to be codegened, the coordinator has
              // to decide how to utilize the compiler processes implicit Token:
                          spawn_work(cgcx, item);
                      }
                  }
 +            } else if codegen_aborted {
 +                // don't queue up any more work if codegen was aborted, we're
 +                // just waiting for our existing children to finish
              } else {
                  // If we've finished everything related to normal codegen
                  // then it must be the case that we've got some LTO work to do.
  
              // Spin up what work we can, only doing this while we've got available
              // parallelism slots and work left to spawn.
 -            while work_items.len() > 0 && running < tokens.len() {
 +            while !codegen_aborted && work_items.len() > 0 && running < tokens.len() {
                  let (item, _) = work_items.pop().unwrap();
  
                  maybe_start_llvm_timer(cgcx.config(item.module_kind()),
                      if !cgcx.opts.debugging_opts.no_parallel_llvm {
                          helper.request_token();
                      }
 +                    assert!(!codegen_aborted);
                      assert_eq!(main_thread_worker_state,
                                 MainThreadWorkerState::Codegenning);
                      main_thread_worker_state = MainThreadWorkerState::Idle;
  
                  Message::CodegenComplete => {
                      codegen_done = true;
 +                    assert!(!codegen_aborted);
                      assert_eq!(main_thread_worker_state,
                                 MainThreadWorkerState::Codegenning);
                      main_thread_worker_state = MainThreadWorkerState::Idle;
                  }
  
 +                // If codegen is aborted that means translation was aborted due
 +                // to some normal-ish compiler error. In this situation we want
 +                // to exit as soon as possible, but we want to make sure all
 +                // existing work has finished. Flag codegen as being done, and
 +                // then conditions above will ensure no more work is spawned but
 +                // we'll keep executing this loop until `running` hits 0.
 +                Message::CodegenAborted => {
 +                    assert!(!codegen_aborted);
 +                    codegen_done = true;
 +                    codegen_aborted = true;
 +                    assert_eq!(main_thread_worker_state,
 +                               MainThreadWorkerState::Codegenning);
 +                }
 +
                  // If a thread exits successfully then we drop a token associated
                  // with that worker and update our `running` count. We may later
                  // re-acquire a token to continue running more work. We may also not
@@@ -2473,19 -2435,6 +2462,19 @@@ impl OngoingCodegen 
          drop(self.coordinator_send.send(Box::new(Message::CodegenComplete)));
      }
  
 +    /// Consume this context indicating that codegen was entirely aborted, and
 +    /// we need to exit as quickly as possible.
 +    ///
 +    /// This method blocks the current thread until all worker threads have
 +    /// finished, and all worker threads should have exited or be real close to
 +    /// exiting at this point.
 +    pub fn codegen_aborted(self) {
 +        // Signal to the coordinator it should spawn no more work and start
 +        // shutdown.
 +        drop(self.coordinator_send.send(Box::new(Message::CodegenAborted)));
 +        drop(self.future.join());
 +    }
 +
      pub fn check_for_errors(&self, sess: &Session) {
          self.shared_emitter_main.check(sess, false);
      }
      }
  }
  
 +// impl Drop for OngoingCodegen {
 +//     fn drop(&mut self) {
 +//     }
 +// }
 +
  pub(crate) fn submit_codegened_module_to_llvm(tcx: TyCtxt,
                                                module: ModuleCodegen,
                                                cost: u64) {
index 9736994fc07555ac4d93d30adfc780d19730c3d6,ecdff946bf3857fc4568e6accf6d1d5ac0c9a8ab..fb33fe85b005441782f340c8f880a687273bbf3e
@@@ -54,6 -54,7 +54,6 @@@ use attributes
  use builder::{Builder, MemFlags};
  use callee;
  use common::{C_bool, C_bytes_in_context, C_i32, C_usize};
 -use rustc_mir::monomorphize::collector::{self, MonoItemCollectionMode};
  use rustc_mir::monomorphize::item::DefPathBasedNames;
  use common::{C_struct_in_context, C_array, val_ty};
  use consts;
@@@ -63,24 -64,24 +63,24 @@@ use declare
  use meth;
  use mir;
  use monomorphize::Instance;
 -use monomorphize::partitioning::{self, PartitioningStrategy, CodegenUnit, CodegenUnitExt};
 +use monomorphize::partitioning::{CodegenUnit, CodegenUnitExt};
  use rustc_codegen_utils::symbol_names_test;
  use time_graph;
 -use mono_item::{MonoItem, BaseMonoItemExt, MonoItemExt};
 +use mono_item::{MonoItem, MonoItemExt};
  use type_::Type;
  use type_of::LayoutLlvmExt;
 -use rustc::util::nodemap::{FxHashMap, DefIdSet};
 +use rustc::util::nodemap::FxHashMap;
  use CrateInfo;
  use rustc_data_structures::small_c_str::SmallCStr;
  use rustc_data_structures::sync::Lrc;
  
  use std::any::Any;
 +use std::cmp;
  use std::ffi::CString;
 -use std::sync::Arc;
 -use std::time::{Instant, Duration};
  use std::i32;
 -use std::cmp;
 +use std::ops::{Deref, DerefMut};
  use std::sync::mpsc;
 +use std::time::{Instant, Duration};
  use syntax_pos::Span;
  use syntax_pos::symbol::InternedString;
  use syntax::attr;
@@@ -556,7 -557,7 +556,7 @@@ fn maybe_create_entry_wrapper(cx: &Code
          // regions must appear in the argument
          // listing.
          let main_ret_ty = cx.tcx.erase_regions(
 -            &main_ret_ty.no_late_bound_regions().unwrap(),
 +            &main_ret_ty.no_bound_vars().unwrap(),
          );
  
          if declare::get_defined_value(cx, "main").is_some() {
@@@ -737,19 -738,6 +737,6 @@@ pub fn codegen_crate<'a, 'tcx>(tcx: TyC
  {
      check_for_rustc_errors_attr(tcx);
  
-     if let Some(true) = tcx.sess.opts.debugging_opts.thinlto {
-         if unsafe { !llvm::LLVMRustThinLTOAvailable() } {
-             tcx.sess.fatal("this compiler's LLVM does not support ThinLTO");
-         }
-     }
-     if (tcx.sess.opts.debugging_opts.pgo_gen.is_some() ||
-         !tcx.sess.opts.debugging_opts.pgo_use.is_empty()) &&
-         unsafe { !llvm::LLVMRustPGOAvailable() }
-     {
-         tcx.sess.fatal("this compiler's LLVM does not support PGO");
-     }
      let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
  
      // Codegen the metadata.
          metadata,
          rx,
          codegen_units.len());
 +    let ongoing_codegen = AbortCodegenOnDrop(Some(ongoing_codegen));
  
      // Codegen an allocator shim, if necessary.
      //
      ongoing_codegen.check_for_errors(tcx.sess);
  
      assert_and_save_dep_graph(tcx);
 -    ongoing_codegen
 +    ongoing_codegen.into_inner()
  }
  
 -fn assert_and_save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
 -    time(tcx.sess,
 -         "assert dep graph",
 -         || rustc_incremental::assert_dep_graph(tcx));
 -
 -    time(tcx.sess,
 -         "serialize dep graph",
 -         || rustc_incremental::save_dep_graph(tcx));
 +/// A curious wrapper structure whose only purpose is to call `codegen_aborted`
 +/// when it's dropped abnormally.
 +///
 +/// In the process of working on rust-lang/rust#55238 a mysterious segfault was
 +/// stumbled upon. The segfault was never reproduced locally, but it was
 +/// suspected to be releated to the fact that codegen worker threads were
 +/// sticking around by the time the main thread was exiting, causing issues.
 +///
 +/// This structure is an attempt to fix that issue where the `codegen_aborted`
 +/// message will block until all workers have finished. This should ensure that
 +/// even if the main codegen thread panics we'll wait for pending work to
 +/// complete before returning from the main thread, hopefully avoiding
 +/// segfaults.
 +///
 +/// If you see this comment in the code, then it means that this workaround
 +/// worked! We may yet one day track down the mysterious cause of that
 +/// segfault...
 +struct AbortCodegenOnDrop(Option<OngoingCodegen>);
 +
 +impl AbortCodegenOnDrop {
 +    fn into_inner(mut self) -> OngoingCodegen {
 +        self.0.take().unwrap()
 +    }
  }
  
 -fn collect_and_partition_mono_items<'a, 'tcx>(
 -    tcx: TyCtxt<'a, 'tcx, 'tcx>,
 -    cnum: CrateNum,
 -) -> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>)
 -{
 -    assert_eq!(cnum, LOCAL_CRATE);
 -
 -    let collection_mode = match tcx.sess.opts.debugging_opts.print_mono_items {
 -        Some(ref s) => {
 -            let mode_string = s.to_lowercase();
 -            let mode_string = mode_string.trim();
 -            if mode_string == "eager" {
 -                MonoItemCollectionMode::Eager
 -            } else {
 -                if mode_string != "lazy" {
 -                    let message = format!("Unknown codegen-item collection mode '{}'. \
 -                                           Falling back to 'lazy' mode.",
 -                                          mode_string);
 -                    tcx.sess.warn(&message);
 -                }
 -
 -                MonoItemCollectionMode::Lazy
 -            }
 -        }
 -        None => {
 -            if tcx.sess.opts.cg.link_dead_code {
 -                MonoItemCollectionMode::Eager
 -            } else {
 -                MonoItemCollectionMode::Lazy
 -            }
 -        }
 -    };
 -
 -    let (items, inlining_map) =
 -        time(tcx.sess, "monomorphization collection", || {
 -            collector::collect_crate_mono_items(tcx, collection_mode)
 -    });
 -
 -    tcx.sess.abort_if_errors();
 -
 -    ::rustc_mir::monomorphize::assert_symbols_are_distinct(tcx, items.iter());
 -
 -    let strategy = if tcx.sess.opts.incremental.is_some() {
 -        PartitioningStrategy::PerModule
 -    } else {
 -        PartitioningStrategy::FixedUnitCount(tcx.sess.codegen_units())
 -    };
 -
 -    let codegen_units = time(tcx.sess, "codegen unit partitioning", || {
 -        partitioning::partition(tcx,
 -                                items.iter().cloned(),
 -                                strategy,
 -                                &inlining_map)
 -            .into_iter()
 -            .map(Arc::new)
 -            .collect::<Vec<_>>()
 -    });
 -
 -    let mono_items: DefIdSet = items.iter().filter_map(|mono_item| {
 -        match *mono_item {
 -            MonoItem::Fn(ref instance) => Some(instance.def_id()),
 -            MonoItem::Static(def_id) => Some(def_id),
 -            _ => None,
 -        }
 -    }).collect();
 -
 -    if tcx.sess.opts.debugging_opts.print_mono_items.is_some() {
 -        let mut item_to_cgus: FxHashMap<_, Vec<_>> = Default::default();
 -
 -        for cgu in &codegen_units {
 -            for (&mono_item, &linkage) in cgu.items() {
 -                item_to_cgus.entry(mono_item)
 -                            .or_default()
 -                            .push((cgu.name().clone(), linkage));
 -            }
 -        }
 +impl Deref for AbortCodegenOnDrop {
 +    type Target = OngoingCodegen;
  
 -        let mut item_keys: Vec<_> = items
 -            .iter()
 -            .map(|i| {
 -                let mut output = i.to_string(tcx);
 -                output.push_str(" @@");
 -                let mut empty = Vec::new();
 -                let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
 -                cgus.as_mut_slice().sort_by_key(|&(ref name, _)| name.clone());
 -                cgus.dedup();
 -                for &(ref cgu_name, (linkage, _)) in cgus.iter() {
 -                    output.push_str(" ");
 -                    output.push_str(&cgu_name.as_str());
 -
 -                    let linkage_abbrev = match linkage {
 -                        Linkage::External => "External",
 -                        Linkage::AvailableExternally => "Available",
 -                        Linkage::LinkOnceAny => "OnceAny",
 -                        Linkage::LinkOnceODR => "OnceODR",
 -                        Linkage::WeakAny => "WeakAny",
 -                        Linkage::WeakODR => "WeakODR",
 -                        Linkage::Appending => "Appending",
 -                        Linkage::Internal => "Internal",
 -                        Linkage::Private => "Private",
 -                        Linkage::ExternalWeak => "ExternalWeak",
 -                        Linkage::Common => "Common",
 -                    };
 -
 -                    output.push_str("[");
 -                    output.push_str(linkage_abbrev);
 -                    output.push_str("]");
 -                }
 -                output
 -            })
 -            .collect();
 +    fn deref(&self) -> &OngoingCodegen {
 +        self.0.as_ref().unwrap()
 +    }
 +}
  
 -        item_keys.sort();
 +impl DerefMut for AbortCodegenOnDrop {
 +    fn deref_mut(&mut self) -> &mut OngoingCodegen {
 +        self.0.as_mut().unwrap()
 +    }
 +}
  
 -        for item in item_keys {
 -            println!("MONO_ITEM {}", item);
 +impl Drop for AbortCodegenOnDrop {
 +    fn drop(&mut self) {
 +        if let Some(codegen) = self.0.take() {
 +            codegen.codegen_aborted();
          }
      }
 +}
  
 -    (Arc::new(mono_items), Arc::new(codegen_units))
 +fn assert_and_save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
 +    time(tcx.sess,
 +         "assert dep graph",
 +         || rustc_incremental::assert_dep_graph(tcx));
 +
 +    time(tcx.sess,
 +         "serialize dep graph",
 +         || rustc_incremental::save_dep_graph(tcx));
  }
  
  impl CrateInfo {
      }
  }
  
 -fn is_codegened_item(tcx: TyCtxt, id: DefId) -> bool {
 -    let (all_mono_items, _) =
 -        tcx.collect_and_partition_mono_items(LOCAL_CRATE);
 -    all_mono_items.contains(&id)
 -}
 -
  fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                    cgu_name: InternedString)
                                    -> Stats {
      }
  }
  
 -pub fn provide(providers: &mut Providers) {
 -    providers.collect_and_partition_mono_items =
 -        collect_and_partition_mono_items;
 -
 -    providers.is_codegened_item = is_codegened_item;
 -
 -    providers.codegen_unit = |tcx, name| {
 -        let (_, all) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
 -        all.iter()
 -            .find(|cgu| *cgu.name() == name)
 -            .cloned()
 -            .unwrap_or_else(|| panic!("failed to find cgu with name {:?}", name))
 -    };
 -
 -    provide_extern(providers);
 -}
 -
 -pub fn provide_extern(providers: &mut Providers) {
 +pub fn provide_both(providers: &mut Providers) {
      providers.dllimport_foreign_items = |tcx, krate| {
          let module_map = tcx.foreign_modules(krate);
          let module_map = module_map.iter()