about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-04-26 15:48:58 +0000
committerbors <bors@rust-lang.org>2020-04-26 15:48:58 +0000
commit7f3b3df9e2f2efe3434b4f6fc76462d2c8ad332f (patch)
tree473644e3095ec29d92b0c68880f49599c402cbfa /src
parentec1f28f9614292c36b371d3758afffdd52cb9786 (diff)
parentaa9dc6952235a58d4c37b63bed15992f5225fbf0 (diff)
downloadrust-7f3b3df9e2f2efe3434b4f6fc76462d2c8ad332f.tar.gz
rust-7f3b3df9e2f2efe3434b4f6fc76462d2c8ad332f.zip
Auto merge of #71579 - Dylan-DPC:rollup-h9om2g3, r=Dylan-DPC
Rollup of 5 pull requests

Successful merges:

 - #71490 (Cleanup and document `-C relocation-model`)
 - #71562 (fix more clippy warnings)
 - #71571 (Fix since attribute for nonzero_bitor impl's)
 - #71574 (proc_macro: Fix since attributes for new Span methods)
 - #71575 (Fix stable(since) attribute for BTreeMap::remove_entry)

Failed merges:

r? @ghost
Diffstat (limited to 'src')
-rw-r--r--src/doc/rustc/src/codegen-options/index.md43
-rw-r--r--src/liballoc/collections/binary_heap.rs2
-rw-r--r--src/liballoc/collections/btree/map.rs2
-rw-r--r--src/liballoc/collections/linked_list.rs2
-rw-r--r--src/libcore/num/mod.rs10
-rw-r--r--src/libproc_macro/lib.rs4
-rw-r--r--src/librustc_codegen_llvm/back/write.rs48
-rw-r--r--src/librustc_codegen_llvm/context.rs38
-rw-r--r--src/librustc_codegen_llvm/lib.rs15
-rw-r--r--src/librustc_codegen_llvm/llvm/ffi.rs5
-rw-r--r--src/librustc_codegen_llvm/llvm_util.rs4
-rw-r--r--src/librustc_codegen_ssa/back/link.rs13
-rw-r--r--src/librustc_codegen_ssa/back/write.rs2
-rw-r--r--src/librustc_codegen_ssa/traits/backend.rs4
-rw-r--r--src/librustc_driver/lib.rs6
-rw-r--r--src/librustc_interface/tests.rs4
-rw-r--r--src/librustc_interface/util.rs8
-rw-r--r--src/librustc_metadata/rmeta/decoder/cstore_impl.rs2
-rw-r--r--src/librustc_mir/transform/copy_prop.rs4
-rw-r--r--src/librustc_mir_build/build/expr/as_rvalue.rs2
-rw-r--r--src/librustc_session/config.rs7
-rw-r--r--src/librustc_session/options.rs23
-rw-r--r--src/librustc_session/session.rs6
-rw-r--r--src/librustc_target/spec/aarch64_unknown_none.rs4
-rw-r--r--src/librustc_target/spec/aarch64_unknown_none_softfloat.rs4
-rw-r--r--src/librustc_target/spec/armebv7r_none_eabi.rs5
-rw-r--r--src/librustc_target/spec/armebv7r_none_eabihf.rs5
-rw-r--r--src/librustc_target/spec/armv7a_none_eabi.rs4
-rw-r--r--src/librustc_target/spec/armv7a_none_eabihf.rs4
-rw-r--r--src/librustc_target/spec/armv7r_none_eabi.rs5
-rw-r--r--src/librustc_target/spec/armv7r_none_eabihf.rs5
-rw-r--r--src/librustc_target/spec/hermit_base.rs4
-rw-r--r--src/librustc_target/spec/hermit_kernel_base.rs4
-rw-r--r--src/librustc_target/spec/linux_kernel_base.rs4
-rw-r--r--src/librustc_target/spec/mod.rs60
-rw-r--r--src/librustc_target/spec/msp430_none_elf.rs4
-rw-r--r--src/librustc_target/spec/riscv32i_unknown_none_elf.rs5
-rw-r--r--src/librustc_target/spec/riscv32imac_unknown_none_elf.rs5
-rw-r--r--src/librustc_target/spec/riscv32imc_unknown_none_elf.rs5
-rw-r--r--src/librustc_target/spec/riscv64gc_unknown_none_elf.rs5
-rw-r--r--src/librustc_target/spec/riscv64imac_unknown_none_elf.rs5
-rw-r--r--src/librustc_target/spec/thumb_base.rs4
-rw-r--r--src/librustc_target/spec/wasm32_base.rs4
-rw-r--r--src/libstd/sync/mpsc/stream.rs2
-rw-r--r--src/rustllvm/PassWrapper.cpp21
-rw-r--r--src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile7
-rw-r--r--src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile7
47 files changed, 247 insertions, 189 deletions
diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
index a503679f19b..dc5d797ebbc 100644
--- a/src/doc/rustc/src/codegen-options/index.md
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -319,11 +319,46 @@ to a valid `.profdata` file. See the chapter on
 
 ## relocation-model
 
-This option lets you choose which
-[relocation](https://en.wikipedia.org/wiki/Relocation_\(computing\)) model to
-use.
+This option controls generation of
+[position-independent code (PIC)](https://en.wikipedia.org/wiki/Position-independent_code).
 
-To find the valid options for this flag, run `rustc --print relocation-models`.
+Supported values for this option are:
+
+#### Primary relocation models
+
+- `static` - non-relocatable code, machine instructions may use absolute addressing modes.
+
+- `pic` - fully relocatable position independent code,
+machine instructions need to use relative addressing modes.  
+Equivalent to the "uppercase" `-fPIC` or `-fPIE` options in other compilers,
+depending on the produced crate types.  
+This is the default model for majority of supported targets.
+
+#### Special relocation models
+
+- `dynamic-no-pic` - relocatable external references, non-relocatable code.  
+Only makes sense on Darwin and is rarely used.  
+If StackOverflow tells you to use this as an opt-out of PIC or PIE, don't believe it,
+use `-C relocation-model=static` instead.
+- `ropi`, `rwpi` and `ropi-rwpi` - relocatable code and read-only data, relocatable read-write data,
+and combination of both, respectively.  
+Only makes sense for certain embedded ARM targets.
+- `default` - relocation model default to the current target.  
+Only makes sense as an override for some other explicitly specified relocation model
+previously set on the command line.
+
+Supported values can also be discovered by running `rustc --print relocation-models`.
+
+#### Linking effects
+
+In addition to codegen effects, `relocation-model` has effects during linking.
+
+If the relocation model is `pic` and the current target supports position-independent executables
+(PIE), the linker will be instructed (`-pie`) to produce one.  
+If the target doesn't support both position-independent and statically linked executables,
+then `-C target-feature=+crt-static` "wins" over `-C relocation-model=pic`,
+and the linker is instructed (`-static`) to produce a statically linked
+but not position-independent executable.
 
 ## remark
 
diff --git a/src/liballoc/collections/binary_heap.rs b/src/liballoc/collections/binary_heap.rs
index 8e170d970bc..a3ef9989184 100644
--- a/src/liballoc/collections/binary_heap.rs
+++ b/src/liballoc/collections/binary_heap.rs
@@ -1269,7 +1269,7 @@ impl<'a, T: Ord> Drop for DrainSorted<'a, T> {
 
         impl<'r, 'a, T: Ord> Drop for DropGuard<'r, 'a, T> {
             fn drop(&mut self) {
-                while let Some(_) = self.0.inner.pop() {}
+                while self.0.inner.pop().is_some() {}
             }
         }
 
diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs
index 099687bd6b0..c0b976565e4 100644
--- a/src/liballoc/collections/btree/map.rs
+++ b/src/liballoc/collections/btree/map.rs
@@ -930,7 +930,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// assert_eq!(map.remove_entry(&1), Some((1, "a")));
     /// assert_eq!(map.remove_entry(&1), None);
     /// ```
-    #[stable(feature = "btreemap_remove_entry", since = "1.44.0")]
+    #[stable(feature = "btreemap_remove_entry", since = "1.45.0")]
     pub fn remove_entry<Q: ?Sized>(&mut self, key: &Q) -> Option<(K, V)>
     where
         K: Borrow<Q>,
diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs
index 9dd7fc6d7ee..bfa4045787f 100644
--- a/src/liballoc/collections/linked_list.rs
+++ b/src/liballoc/collections/linked_list.rs
@@ -972,7 +972,7 @@ unsafe impl<#[may_dangle] T> Drop for LinkedList<T> {
             fn drop(&mut self) {
                 // Continue the same loop we do below. This only runs when a destructor has
                 // panicked. If another one panics this will abort.
-                while let Some(_) = self.0.pop_front_node() {}
+                while self.0.pop_front_node().is_some() {}
             }
         }
 
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 0349678b07b..a259e293b0c 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -111,7 +111,7 @@ assert_eq!(size_of::<Option<core::num::", stringify!($Ty), ">>(), size_of::<", s
                 }
             }
 
-            #[stable(feature = "nonzero_bitor", since = "1.43.0")]
+            #[stable(feature = "nonzero_bitor", since = "1.45.0")]
             impl BitOr for $Ty {
                 type Output = Self;
                 #[inline]
@@ -122,7 +122,7 @@ assert_eq!(size_of::<Option<core::num::", stringify!($Ty), ">>(), size_of::<", s
                 }
             }
 
-            #[stable(feature = "nonzero_bitor", since = "1.43.0")]
+            #[stable(feature = "nonzero_bitor", since = "1.45.0")]
             impl BitOr<$Int> for $Ty {
                 type Output = Self;
                 #[inline]
@@ -134,7 +134,7 @@ assert_eq!(size_of::<Option<core::num::", stringify!($Ty), ">>(), size_of::<", s
                 }
             }
 
-            #[stable(feature = "nonzero_bitor", since = "1.43.0")]
+            #[stable(feature = "nonzero_bitor", since = "1.45.0")]
             impl BitOr<$Ty> for $Int {
                 type Output = $Ty;
                 #[inline]
@@ -146,7 +146,7 @@ assert_eq!(size_of::<Option<core::num::", stringify!($Ty), ">>(), size_of::<", s
                 }
             }
 
-            #[stable(feature = "nonzero_bitor", since = "1.43.0")]
+            #[stable(feature = "nonzero_bitor", since = "1.45.0")]
             impl BitOrAssign for $Ty {
                 #[inline]
                 fn bitor_assign(&mut self, rhs: Self) {
@@ -154,7 +154,7 @@ assert_eq!(size_of::<Option<core::num::", stringify!($Ty), ">>(), size_of::<", s
                 }
             }
 
-            #[stable(feature = "nonzero_bitor", since = "1.43.0")]
+            #[stable(feature = "nonzero_bitor", since = "1.45.0")]
             impl BitOrAssign<$Int> for $Ty {
                 #[inline]
                 fn bitor_assign(&mut self, rhs: $Int) {
diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index 5995f64dc78..86e39094935 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -351,14 +351,14 @@ impl Span {
 
     /// Creates a new span with the same line/column information as `self` but
     /// that resolves symbols as though it were at `other`.
-    #[stable(feature = "proc_macro_span_resolved_at", since = "1.43.0")]
+    #[stable(feature = "proc_macro_span_resolved_at", since = "1.45.0")]
     pub fn resolved_at(&self, other: Span) -> Span {
         Span(self.0.resolved_at(other.0))
     }
 
     /// Creates a new span with the same name resolution behavior as `self` but
     /// with the line/column information of `other`.
-    #[stable(feature = "proc_macro_span_located_at", since = "1.43.0")]
+    #[stable(feature = "proc_macro_span_located_at", since = "1.45.0")]
     pub fn located_at(&self, other: Span) -> Span {
         other.resolved_at(*self)
     }
diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index b57ad102d63..bf79c5b593e 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -7,7 +7,7 @@ use crate::back::profiling::{
 use crate::base;
 use crate::common;
 use crate::consts;
-use crate::context::{get_reloc_model, is_pie_binary};
+use crate::context::all_outputs_are_pic_executables;
 use crate::llvm::{self, DiagnosticInfo, PassManager, SMDiagnostic};
 use crate::llvm_util;
 use crate::type_::Type;
@@ -25,6 +25,7 @@ use rustc_middle::bug;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{self, Lto, OutputType, Passes, Sanitizer, SwitchWithOptPath};
 use rustc_session::Session;
+use rustc_target::spec::RelocModel;
 
 use libc::{c_char, c_int, c_uint, c_void, size_t};
 use std::ffi::CString;
@@ -35,16 +36,6 @@ use std::slice;
 use std::str;
 use std::sync::Arc;
 
-pub const RELOC_MODEL_ARGS: [(&str, llvm::RelocMode); 7] = [
-    ("pic", llvm::RelocMode::PIC),
-    ("static", llvm::RelocMode::Static),
-    ("default", llvm::RelocMode::Default),
-    ("dynamic-no-pic", llvm::RelocMode::DynamicNoPic),
-    ("ropi", llvm::RelocMode::ROPI),
-    ("rwpi", llvm::RelocMode::RWPI),
-    ("ropi-rwpi", llvm::RelocMode::ROPI_RWPI),
-];
-
 pub const CODE_GEN_MODEL_ARGS: &[(&str, llvm::CodeModel)] = &[
     ("small", llvm::CodeModel::Small),
     ("kernel", llvm::CodeModel::Kernel),
@@ -84,19 +75,13 @@ pub fn write_output_file(
     }
 }
 
-pub fn create_informational_target_machine(
-    sess: &Session,
-    find_features: bool,
-) -> &'static mut llvm::TargetMachine {
-    target_machine_factory(sess, config::OptLevel::No, find_features)()
+pub fn create_informational_target_machine(sess: &Session) -> &'static mut llvm::TargetMachine {
+    target_machine_factory(sess, config::OptLevel::No)()
         .unwrap_or_else(|err| llvm_err(sess.diagnostic(), &err).raise())
 }
 
-pub fn create_target_machine(
-    tcx: TyCtxt<'_>,
-    find_features: bool,
-) -> &'static mut llvm::TargetMachine {
-    target_machine_factory(&tcx.sess, tcx.backend_optimization_level(LOCAL_CRATE), find_features)()
+pub fn create_target_machine(tcx: TyCtxt<'_>) -> &'static mut llvm::TargetMachine {
+    target_machine_factory(&tcx.sess, tcx.backend_optimization_level(LOCAL_CRATE))()
         .unwrap_or_else(|err| llvm_err(tcx.sess.diagnostic(), &err).raise())
 }
 
@@ -126,15 +111,22 @@ fn to_pass_builder_opt_level(cfg: config::OptLevel) -> llvm::PassBuilderOptLevel
     }
 }
 
-// If find_features is true this won't access `sess.crate_types` by assuming
-// that `is_pie_binary` is false. When we discover LLVM target features
-// `sess.crate_types` is uninitialized so we cannot access it.
+fn to_llvm_relocation_model(relocation_model: RelocModel) -> llvm::RelocModel {
+    match relocation_model {
+        RelocModel::Static => llvm::RelocModel::Static,
+        RelocModel::Pic => llvm::RelocModel::PIC,
+        RelocModel::DynamicNoPic => llvm::RelocModel::DynamicNoPic,
+        RelocModel::Ropi => llvm::RelocModel::ROPI,
+        RelocModel::Rwpi => llvm::RelocModel::RWPI,
+        RelocModel::RopiRwpi => llvm::RelocModel::ROPI_RWPI,
+    }
+}
+
 pub fn target_machine_factory(
     sess: &Session,
     optlvl: config::OptLevel,
-    find_features: bool,
 ) -> Arc<dyn Fn() -> Result<&'static mut llvm::TargetMachine, String> + Send + Sync> {
-    let reloc_model = get_reloc_model(sess);
+    let reloc_model = to_llvm_relocation_model(sess.relocation_model());
 
     let (opt_level, _) = to_llvm_opt_settings(optlvl);
     let use_softfp = sess.opts.cg.soft_float;
@@ -175,7 +167,7 @@ pub fn target_machine_factory(
     let features = features.join(",");
     let features = CString::new(features).unwrap();
     let abi = SmallCStr::new(&sess.target.target.options.llvm_abiname);
-    let is_pie_binary = !find_features && is_pie_binary(sess);
+    let pic_is_pie = all_outputs_are_pic_executables(sess);
     let trap_unreachable = sess.target.target.options.trap_unreachable;
     let emit_stack_size_section = sess.opts.debugging_opts.emit_stack_sizes;
 
@@ -192,7 +184,7 @@ pub fn target_machine_factory(
                 reloc_model,
                 opt_level,
                 use_softfp,
-                is_pie_binary,
+                pic_is_pie,
                 ffunction_sections,
                 fdata_sections,
                 trap_unreachable,
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index d385c073074..df442609052 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -21,7 +21,7 @@ use rustc_session::Session;
 use rustc_span::source_map::{Span, DUMMY_SP};
 use rustc_span::symbol::Symbol;
 use rustc_target::abi::{HasDataLayout, LayoutOf, PointeeInfo, Size, TargetDataLayout, VariantIdx};
-use rustc_target::spec::{HasTargetSpec, Target};
+use rustc_target::spec::{HasTargetSpec, RelocModel, Target};
 
 use std::cell::{Cell, RefCell};
 use std::ffi::CStr;
@@ -87,22 +87,6 @@ pub struct CodegenCx<'ll, 'tcx> {
     local_gen_sym_counter: Cell<usize>,
 }
 
-pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
-    let reloc_model_arg = match sess.opts.cg.relocation_model {
-        Some(ref s) => &s[..],
-        None => &sess.target.target.options.relocation_model[..],
-    };
-
-    match crate::back::write::RELOC_MODEL_ARGS.iter().find(|&&arg| arg.0 == reloc_model_arg) {
-        Some(x) => x.1,
-        _ => {
-            sess.err(&format!("{:?} is not a valid relocation mode", reloc_model_arg));
-            sess.abort_if_errors();
-            bug!();
-        }
-    }
-}
-
 fn get_tls_model(sess: &Session) -> llvm::ThreadLocalMode {
     let tls_model_arg = match sess.opts.debugging_opts.tls_model {
         Some(ref s) => &s[..],
@@ -119,12 +103,14 @@ fn get_tls_model(sess: &Session) -> llvm::ThreadLocalMode {
     }
 }
 
-fn is_any_library(sess: &Session) -> bool {
-    sess.crate_types.borrow().iter().any(|ty| *ty != config::CrateType::Executable)
-}
-
-pub fn is_pie_binary(sess: &Session) -> bool {
-    !is_any_library(sess) && get_reloc_model(sess) == llvm::RelocMode::PIC
+/// PIE is potentially more effective than PIC, but can only be used in executables.
+/// If all our outputs are executables, then we can relax PIC to PIE when producing object code.
+/// If the list of crate types is not yet known we conservatively return `false`.
+pub fn all_outputs_are_pic_executables(sess: &Session) -> bool {
+    sess.relocation_model() == RelocModel::Pic
+        && sess.crate_types.try_get().map_or(false, |crate_types| {
+            crate_types.iter().all(|ty| *ty == config::CrateType::Executable)
+        })
 }
 
 fn strip_function_ptr_alignment(data_layout: String) -> String {
@@ -157,7 +143,7 @@ pub unsafe fn create_module(
 
     // Ensure the data-layout values hardcoded remain the defaults.
     if sess.target.target.options.is_builtin {
-        let tm = crate::back::write::create_informational_target_machine(&tcx.sess, false);
+        let tm = crate::back::write::create_informational_target_machine(tcx.sess);
         llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, tm);
         llvm::LLVMRustDisposeTargetMachine(tm);
 
@@ -200,11 +186,11 @@ pub unsafe fn create_module(
     let llvm_target = SmallCStr::new(&sess.target.target.llvm_target);
     llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
 
-    if get_reloc_model(sess) == llvm::RelocMode::PIC {
+    if sess.relocation_model() == RelocModel::Pic {
         llvm::LLVMRustSetModulePICLevel(llmod);
     }
 
-    if is_pie_binary(sess) {
+    if all_outputs_are_pic_executables(sess) {
         llvm::LLVMRustSetModulePIELevel(llmod);
     }
 
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index 64158679740..330d6ea75d2 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -110,9 +110,8 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
         &self,
         sess: &Session,
         optlvl: OptLevel,
-        find_features: bool,
     ) -> Arc<dyn Fn() -> Result<&'static mut llvm::TargetMachine, String> + Send + Sync> {
-        back::write::target_machine_factory(sess, optlvl, find_features)
+        back::write::target_machine_factory(sess, optlvl)
     }
     fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str {
         llvm_util::target_cpu(sess)
@@ -201,7 +200,9 @@ impl CodegenBackend for LlvmCodegenBackend {
         match req {
             PrintRequest::RelocationModels => {
                 println!("Available relocation models:");
-                for &(name, _) in back::write::RELOC_MODEL_ARGS.iter() {
+                for name in
+                    &["static", "pic", "dynamic-no-pic", "ropi", "rwpi", "ropi-rwpi", "default"]
+                {
                     println!("    {}", name);
                 }
                 println!();
@@ -351,7 +352,7 @@ impl ModuleLlvm {
         unsafe {
             let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
             let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
-            ModuleLlvm { llmod_raw, llcx, tm: create_target_machine(tcx, false) }
+            ModuleLlvm { llmod_raw, llcx, tm: create_target_machine(tcx) }
         }
     }
 
@@ -359,11 +360,7 @@ impl ModuleLlvm {
         unsafe {
             let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
             let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
-            ModuleLlvm {
-                llmod_raw,
-                llcx,
-                tm: create_informational_target_machine(&tcx.sess, false),
-            }
+            ModuleLlvm { llmod_raw, llcx, tm: create_informational_target_machine(tcx.sess) }
         }
     }
 
diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs
index aeb34e5c9c9..fd03812cccd 100644
--- a/src/librustc_codegen_llvm/llvm/ffi.rs
+++ b/src/librustc_codegen_llvm/llvm/ffi.rs
@@ -445,8 +445,7 @@ pub struct SanitizerOptions {
 /// LLVMRelocMode
 #[derive(Copy, Clone, PartialEq)]
 #[repr(C)]
-pub enum RelocMode {
-    Default,
+pub enum RelocModel {
     Static,
     PIC,
     DynamicNoPic,
@@ -1946,7 +1945,7 @@ extern "C" {
         Features: *const c_char,
         Abi: *const c_char,
         Model: CodeModel,
-        Reloc: RelocMode,
+        Reloc: RelocModel,
         Level: CodeGenOptLevel,
         UseSoftFP: bool,
         PositionIndependentExecutable: bool,
diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs
index 6f16b0fb79c..a36e95771e8 100644
--- a/src/librustc_codegen_llvm/llvm_util.rs
+++ b/src/librustc_codegen_llvm/llvm_util.rs
@@ -270,7 +270,7 @@ pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
 }
 
 pub fn target_features(sess: &Session) -> Vec<Symbol> {
-    let target_machine = create_informational_target_machine(sess, true);
+    let target_machine = create_informational_target_machine(sess);
     target_feature_whitelist(sess)
         .iter()
         .filter_map(|&(feature, gate)| {
@@ -322,7 +322,7 @@ pub fn print_passes() {
 
 pub(crate) fn print(req: PrintRequest, sess: &Session) {
     require_inited();
-    let tm = create_informational_target_machine(sess, true);
+    let tm = create_informational_target_machine(sess);
     unsafe {
         match req {
             PrintRequest::TargetCPUs => llvm::LLVMRustPrintTargetCPUs(tm),
diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs
index 8725bfaa025..9d42db8ec42 100644
--- a/src/librustc_codegen_ssa/back/link.rs
+++ b/src/librustc_codegen_ssa/back/link.rs
@@ -12,7 +12,7 @@ use rustc_session::search_paths::PathKind;
 /// need out of the shared crate context before we get rid of it.
 use rustc_session::{filesearch, Session};
 use rustc_span::symbol::Symbol;
-use rustc_target::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelroLevel};
+use rustc_target::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, RelroLevel};
 
 use super::archive::ArchiveBuilder;
 use super::command::Command;
@@ -1352,7 +1352,7 @@ fn add_position_independent_executable_args(
     if sess.target.target.options.position_independent_executables {
         let attr_link_args = &*codegen_results.crate_info.link_args;
         let mut user_defined_link_args = sess.opts.cg.link_args.iter().chain(attr_link_args);
-        if is_pic(sess)
+        if sess.relocation_model() == RelocModel::Pic
             && !sess.crt_static(Some(crate_type))
             && !user_defined_link_args.any(|x| x == "-static")
         {
@@ -1992,12 +1992,3 @@ fn are_upstream_rust_objects_already_included(sess: &Session) -> bool {
         config::Lto::No | config::Lto::ThinLocal => false,
     }
 }
-
-fn is_pic(sess: &Session) -> bool {
-    let reloc_model_arg = match sess.opts.cg.relocation_model {
-        Some(ref s) => &s[..],
-        None => &sess.target.target.options.relocation_model[..],
-    };
-
-    reloc_model_arg == "pic"
-}
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index 37034141bb7..c84f38670f7 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -1037,7 +1037,7 @@ 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, false)),
+        tm_factory: TargetMachineFactory(backend.target_machine_factory(tcx.sess, ol)),
         total_cgus,
         msvc_imps_needed: msvc_imps_needed(tcx),
         target_pointer_width: tcx.sess.target.target.target_pointer_width.clone(),
diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs
index 91be123beb0..6cbb47efa99 100644
--- a/src/librustc_codegen_ssa/traits/backend.rs
+++ b/src/librustc_codegen_ssa/traits/backend.rs
@@ -110,14 +110,10 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se
         tcx: TyCtxt<'_>,
         cgu_name: Symbol,
     ) -> (ModuleCodegen<Self::Module>, u64);
-    // If find_features is true this won't access `sess.crate_types` by assuming
-    // that `is_pie_binary` is false. When we discover LLVM target features
-    // `sess.crate_types` is uninitialized so we cannot access it.
     fn target_machine_factory(
         &self,
         sess: &Session,
         opt_level: config::OptLevel,
-        find_features: bool,
     ) -> Arc<dyn Fn() -> Result<Self::TargetMachine, String> + Send + Sync>;
     fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str;
 }
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index fff86ba8194..913ccf8e680 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -618,15 +618,15 @@ impl RustcDefaultCalls {
     ) -> Compilation {
         let r = matches.opt_strs("Z");
         if r.iter().any(|s| *s == "ls") {
-            match input {
-                &Input::File(ref ifile) => {
+            match *input {
+                Input::File(ref ifile) => {
                     let path = &(*ifile);
                     let mut v = Vec::new();
                     locator::list_file_metadata(&sess.target.target, path, metadata_loader, &mut v)
                         .unwrap();
                     println!("{}", String::from_utf8(v).unwrap());
                 }
-                &Input::Str { .. } => {
+                Input::Str { .. } => {
                     early_error(ErrorOutputType::default(), "cannot list metadata for stdin");
                 }
             }
diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs
index 211850486c0..f0e7581b760 100644
--- a/src/librustc_interface/tests.rs
+++ b/src/librustc_interface/tests.rs
@@ -14,7 +14,7 @@ use rustc_session::{build_session, Session};
 use rustc_span::edition::{Edition, DEFAULT_EDITION};
 use rustc_span::symbol::sym;
 use rustc_span::SourceFileHashAlgorithm;
-use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel};
+use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelocModel, RelroLevel};
 use std::collections::{BTreeMap, BTreeSet};
 use std::iter::FromIterator;
 use std::path::PathBuf;
@@ -430,7 +430,7 @@ fn test_codegen_options_tracking_hash() {
     tracked!(prefer_dynamic, true);
     tracked!(profile_generate, SwitchWithOptPath::Enabled(None));
     tracked!(profile_use, Some(PathBuf::from("abc")));
-    tracked!(relocation_model, Some(String::from("relocation model")));
+    tracked!(relocation_model, Some(RelocModel::Pic));
     tracked!(soft_float, true);
     tracked!(target_cpu, Some(String::from("abc")));
     tracked!(target_feature, String::from("all the features, all of them"));
diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs
index fda01725443..367dc4dee7e 100644
--- a/src/librustc_interface/util.rs
+++ b/src/librustc_interface/util.rs
@@ -625,8 +625,8 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> {
                     | ast::TyKind::Rptr(_, ast::MutTy { ty: ref subty, .. })
                     | ast::TyKind::Paren(ref subty) => involves_impl_trait(subty),
                     ast::TyKind::Tup(ref tys) => any_involves_impl_trait(tys.iter()),
-                    ast::TyKind::Path(_, ref path) => path.segments.iter().any(|seg| {
-                        match seg.args.as_ref().map(|generic_arg| &**generic_arg) {
+                    ast::TyKind::Path(_, ref path) => {
+                        path.segments.iter().any(|seg| match seg.args.as_deref() {
                             None => false,
                             Some(&ast::GenericArgs::AngleBracketed(ref data)) => {
                                 data.args.iter().any(|arg| match arg {
@@ -647,8 +647,8 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> {
                                 any_involves_impl_trait(data.inputs.iter())
                                     || ReplaceBodyWithLoop::should_ignore_fn(&data.output)
                             }
-                        }
-                    }),
+                        })
+                    }
                     _ => false,
                 }
             }
diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
index ecf3825dadb..7d1639cbcf7 100644
--- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
+++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
@@ -431,7 +431,7 @@ impl CStore {
                 ident,
                 id: ast::DUMMY_NODE_ID,
                 span,
-                attrs: attrs.iter().cloned().collect(),
+                attrs: attrs.to_vec(),
                 kind: ast::ItemKind::MacroDef(data.get_macro(id.index, sess)),
                 vis: source_map::respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited),
                 tokens: None,
diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs
index bc1cb52ae85..b9eb58f800e 100644
--- a/src/librustc_mir/transform/copy_prop.rs
+++ b/src/librustc_mir/transform/copy_prop.rs
@@ -246,7 +246,7 @@ impl<'tcx> Action<'tcx> {
     }
 
     fn constant(src_constant: &Constant<'tcx>) -> Option<Action<'tcx>> {
-        Some(Action::PropagateConstant((*src_constant).clone()))
+        Some(Action::PropagateConstant(*src_constant))
     }
 
     fn perform(
@@ -371,7 +371,7 @@ impl<'tcx> MutVisitor<'tcx> for ConstantPropagationVisitor<'tcx> {
             _ => return,
         }
 
-        *operand = Operand::Constant(box self.constant.clone());
+        *operand = Operand::Constant(box self.constant);
         self.uses_replaced += 1
     }
 }
diff --git a/src/librustc_mir_build/build/expr/as_rvalue.rs b/src/librustc_mir_build/build/expr/as_rvalue.rs
index b6f46aab416..38f71135c7d 100644
--- a/src/librustc_mir_build/build/expr/as_rvalue.rs
+++ b/src/librustc_mir_build/build/expr/as_rvalue.rs
@@ -292,7 +292,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             let of_fld = Field::new(1);
 
             let tcx = self.hir.tcx();
-            let val = tcx.mk_place_field(result_value.clone(), val_fld, ty);
+            let val = tcx.mk_place_field(result_value, val_fld, ty);
             let of = tcx.mk_place_field(result_value, of_fld, bool_ty);
 
             let err = AssertKind::Overflow(op);
diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs
index f6d7e091e00..1ab02f84c11 100644
--- a/src/librustc_session/config.rs
+++ b/src/librustc_session/config.rs
@@ -1311,10 +1311,6 @@ fn collect_print_requests(
         prints.push(PrintRequest::TargetFeatures);
         cg.target_feature = String::new();
     }
-    if cg.relocation_model.as_ref().map_or(false, |s| s == "help") {
-        prints.push(PrintRequest::RelocationModels);
-        cg.relocation_model = None;
-    }
     if cg.code_model.as_ref().map_or(false, |s| s == "help") {
         prints.push(PrintRequest::CodeModels);
         cg.code_model = None;
@@ -2005,7 +2001,7 @@ crate mod dep_tracking {
     use crate::utils::NativeLibraryKind;
     use rustc_feature::UnstableFeatures;
     use rustc_span::edition::Edition;
-    use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel, TargetTriple};
+    use rustc_target::spec::{MergeFunctions, PanicStrategy, RelocModel, RelroLevel, TargetTriple};
     use std::collections::hash_map::DefaultHasher;
     use std::collections::BTreeMap;
     use std::hash::Hash;
@@ -2053,6 +2049,7 @@ crate mod dep_tracking {
     impl_dep_tracking_hash_via_hash!(Option<(String, u64)>);
     impl_dep_tracking_hash_via_hash!(Option<Vec<String>>);
     impl_dep_tracking_hash_via_hash!(Option<MergeFunctions>);
+    impl_dep_tracking_hash_via_hash!(Option<RelocModel>);
     impl_dep_tracking_hash_via_hash!(Option<PanicStrategy>);
     impl_dep_tracking_hash_via_hash!(Option<RelroLevel>);
     impl_dep_tracking_hash_via_hash!(Option<lint::Level>);
diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs
index 54b2f2fe470..2279c16748c 100644
--- a/src/librustc_session/options.rs
+++ b/src/librustc_session/options.rs
@@ -6,7 +6,7 @@ use crate::search_paths::SearchPath;
 use crate::utils::NativeLibraryKind;
 
 use rustc_target::spec::TargetTriple;
-use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel};
+use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelocModel, RelroLevel};
 
 use rustc_feature::UnstableFeatures;
 use rustc_span::edition::Edition;
@@ -265,14 +265,13 @@ macro_rules! options {
         pub const parse_merge_functions: &str = "one of: `disabled`, `trampolines`, or `aliases`";
         pub const parse_symbol_mangling_version: &str = "either `legacy` or `v0` (RFC 2603)";
         pub const parse_src_file_hash: &str = "either `md5` or `sha1`";
+        pub const parse_relocation_model: &str =
+            "one of supported relocation models (`rustc --print relocation-models`)";
     }
 
     #[allow(dead_code)]
     mod $mod_set {
-        use super::{$struct_name, Passes, Sanitizer, LtoCli, LinkerPluginLto, SwitchWithOptPath,
-            SymbolManglingVersion, CFGuard, SourceFileHashAlgorithm};
-        use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel};
-        use std::path::PathBuf;
+        use super::*;
         use std::str::FromStr;
 
         // Sometimes different options need to build a common structure.
@@ -598,6 +597,15 @@ macro_rules! options {
             true
         }
 
+        fn parse_relocation_model(slot: &mut Option<RelocModel>, v: Option<&str>) -> bool {
+            match v.and_then(|s| RelocModel::from_str(s).ok()) {
+                Some(relocation_model) => *slot = Some(relocation_model),
+                None if v == Some("default") => *slot = None,
+                _ => return false,
+            }
+            true
+        }
+
         fn parse_symbol_mangling_version(
             slot: &mut SymbolManglingVersion,
             v: Option<&str>,
@@ -697,8 +705,9 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
         "compile the program with profiling instrumentation"),
     profile_use: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
         "use the given `.profdata` file for profile-guided optimization"),
-    relocation_model: Option<String> = (None, parse_opt_string, [TRACKED],
-        "choose the relocation model to use (`rustc --print relocation-models` for details)"),
+    relocation_model: Option<RelocModel> = (None, parse_relocation_model, [TRACKED],
+        "control generation of position-independent code (PIC) \
+        (`rustc --print relocation-models` for details)"),
     remark: Passes = (Passes::Some(Vec::new()), parse_passes, [UNTRACKED],
         "print remarks for these optimization passes (space separated, or \"all\")"),
     rpath: bool = (false, parse_bool, [UNTRACKED],
diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs
index f0bbe1d0a18..226d9392095 100644
--- a/src/librustc_session/session.rs
+++ b/src/librustc_session/session.rs
@@ -22,7 +22,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId, ErrorReported
 use rustc_span::edition::Edition;
 use rustc_span::source_map::{self, FileLoader, MultiSpan, RealFileLoader, SourceMap, Span};
 use rustc_span::SourceFileHashAlgorithm;
-use rustc_target::spec::{PanicStrategy, RelroLevel, Target, TargetTriple};
+use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, Target, TargetTriple};
 
 use std::cell::{self, RefCell};
 use std::env;
@@ -584,6 +584,10 @@ impl Session {
         }
     }
 
+    pub fn relocation_model(&self) -> RelocModel {
+        self.opts.cg.relocation_model.unwrap_or(self.target.target.options.relocation_model)
+    }
+
     pub fn must_not_eliminate_frame_pointers(&self) -> bool {
         // "mcount" function relies on stack pointer.
         // See <https://sourceware.org/binutils/docs/gprof/Implementation.html>.
diff --git a/src/librustc_target/spec/aarch64_unknown_none.rs b/src/librustc_target/spec/aarch64_unknown_none.rs
index 13e62b60ca8..7177c4e251e 100644
--- a/src/librustc_target/spec/aarch64_unknown_none.rs
+++ b/src/librustc_target/spec/aarch64_unknown_none.rs
@@ -6,14 +6,14 @@
 //
 // For example, `-C target-cpu=cortex-a53`.
 
-use super::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions};
+use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
 
 pub fn target() -> Result<Target, String> {
     let opts = TargetOptions {
         linker: Some("rust-lld".to_owned()),
         features: "+strict-align,+neon,+fp-armv8".to_string(),
         executables: true,
-        relocation_model: "static".to_string(),
+        relocation_model: RelocModel::Static,
         disable_redzone: true,
         linker_is_gnu: true,
         max_atomic_width: Some(128),
diff --git a/src/librustc_target/spec/aarch64_unknown_none_softfloat.rs b/src/librustc_target/spec/aarch64_unknown_none_softfloat.rs
index cf46252555c..986300c677d 100644
--- a/src/librustc_target/spec/aarch64_unknown_none_softfloat.rs
+++ b/src/librustc_target/spec/aarch64_unknown_none_softfloat.rs
@@ -6,14 +6,14 @@
 //
 // For example, `-C target-cpu=cortex-a53`.
 
-use super::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions};
+use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
 
 pub fn target() -> Result<Target, String> {
     let opts = TargetOptions {
         linker: Some("rust-lld".to_owned()),
         features: "+strict-align,-neon,-fp-armv8".to_string(),
         executables: true,
-        relocation_model: "static".to_string(),
+        relocation_model: RelocModel::Static,
         disable_redzone: true,
         linker_is_gnu: true,
         max_atomic_width: Some(128),
diff --git a/src/librustc_target/spec/armebv7r_none_eabi.rs b/src/librustc_target/spec/armebv7r_none_eabi.rs
index ebe901e4f27..a1f68f6706a 100644
--- a/src/librustc_target/spec/armebv7r_none_eabi.rs
+++ b/src/librustc_target/spec/armebv7r_none_eabi.rs
@@ -1,6 +1,7 @@
 // Targets the Big endian Cortex-R4/R5 processor (ARMv7-R)
 
-use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
@@ -18,7 +19,7 @@ pub fn target() -> TargetResult {
         options: TargetOptions {
             executables: true,
             linker: Some("rust-lld".to_owned()),
-            relocation_model: "static".to_string(),
+            relocation_model: RelocModel::Static,
             panic_strategy: PanicStrategy::Abort,
             max_atomic_width: Some(32),
             abi_blacklist: super::arm_base::abi_blacklist(),
diff --git a/src/librustc_target/spec/armebv7r_none_eabihf.rs b/src/librustc_target/spec/armebv7r_none_eabihf.rs
index 8652d1051ad..4d81c21f52a 100644
--- a/src/librustc_target/spec/armebv7r_none_eabihf.rs
+++ b/src/librustc_target/spec/armebv7r_none_eabihf.rs
@@ -1,6 +1,7 @@
 // Targets the Cortex-R4F/R5F processor (ARMv7-R)
 
-use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
@@ -18,7 +19,7 @@ pub fn target() -> TargetResult {
         options: TargetOptions {
             executables: true,
             linker: Some("rust-lld".to_owned()),
-            relocation_model: "static".to_string(),
+            relocation_model: RelocModel::Static,
             panic_strategy: PanicStrategy::Abort,
             features: "+vfp3,-d32,-fp16".to_string(),
             max_atomic_width: Some(32),
diff --git a/src/librustc_target/spec/armv7a_none_eabi.rs b/src/librustc_target/spec/armv7a_none_eabi.rs
index 2fbef154f81..09f1494e81c 100644
--- a/src/librustc_target/spec/armv7a_none_eabi.rs
+++ b/src/librustc_target/spec/armv7a_none_eabi.rs
@@ -17,14 +17,14 @@
 // - `relocation-model` set to `static`; also no PIE, no relro and no dynamic
 // linking. rationale: matches `thumb` targets
 
-use super::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions};
+use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
 
 pub fn target() -> Result<Target, String> {
     let opts = TargetOptions {
         linker: Some("rust-lld".to_owned()),
         features: "+v7,+thumb2,+soft-float,-neon,+strict-align".to_string(),
         executables: true,
-        relocation_model: "static".to_string(),
+        relocation_model: RelocModel::Static,
         disable_redzone: true,
         max_atomic_width: Some(64),
         panic_strategy: PanicStrategy::Abort,
diff --git a/src/librustc_target/spec/armv7a_none_eabihf.rs b/src/librustc_target/spec/armv7a_none_eabihf.rs
index f31e68c5bd1..653ca76435b 100644
--- a/src/librustc_target/spec/armv7a_none_eabihf.rs
+++ b/src/librustc_target/spec/armv7a_none_eabihf.rs
@@ -5,14 +5,14 @@
 // changes (list in `armv7a_none_eabi.rs`) to bring it closer to the bare-metal
 // `thumb` & `aarch64` targets.
 
-use super::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions};
+use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
 
 pub fn target() -> Result<Target, String> {
     let opts = TargetOptions {
         linker: Some("rust-lld".to_owned()),
         features: "+v7,+vfp3,-d32,+thumb2,-neon,+strict-align".to_string(),
         executables: true,
-        relocation_model: "static".to_string(),
+        relocation_model: RelocModel::Static,
         disable_redzone: true,
         max_atomic_width: Some(64),
         panic_strategy: PanicStrategy::Abort,
diff --git a/src/librustc_target/spec/armv7r_none_eabi.rs b/src/librustc_target/spec/armv7r_none_eabi.rs
index b7fcda63db0..29dfa170397 100644
--- a/src/librustc_target/spec/armv7r_none_eabi.rs
+++ b/src/librustc_target/spec/armv7r_none_eabi.rs
@@ -1,6 +1,7 @@
 // Targets the Little-endian Cortex-R4/R5 processor (ARMv7-R)
 
-use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
@@ -18,7 +19,7 @@ pub fn target() -> TargetResult {
         options: TargetOptions {
             executables: true,
             linker: Some("rust-lld".to_owned()),
-            relocation_model: "static".to_string(),
+            relocation_model: RelocModel::Static,
             panic_strategy: PanicStrategy::Abort,
             max_atomic_width: Some(32),
             abi_blacklist: super::arm_base::abi_blacklist(),
diff --git a/src/librustc_target/spec/armv7r_none_eabihf.rs b/src/librustc_target/spec/armv7r_none_eabihf.rs
index 340090fd43b..e6b0187c331 100644
--- a/src/librustc_target/spec/armv7r_none_eabihf.rs
+++ b/src/librustc_target/spec/armv7r_none_eabihf.rs
@@ -1,6 +1,7 @@
 // Targets the Little-endian Cortex-R4F/R5F processor (ARMv7-R)
 
-use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
@@ -18,7 +19,7 @@ pub fn target() -> TargetResult {
         options: TargetOptions {
             executables: true,
             linker: Some("rust-lld".to_owned()),
-            relocation_model: "static".to_string(),
+            relocation_model: RelocModel::Static,
             panic_strategy: PanicStrategy::Abort,
             features: "+vfp3,-d32,-fp16".to_string(),
             max_atomic_width: Some(32),
diff --git a/src/librustc_target/spec/hermit_base.rs b/src/librustc_target/spec/hermit_base.rs
index b9f94023e7a..cb12055290e 100644
--- a/src/librustc_target/spec/hermit_base.rs
+++ b/src/librustc_target/spec/hermit_base.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions};
+use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     let mut pre_link_args = LinkArgs::new();
@@ -15,7 +15,7 @@ pub fn opts() -> TargetOptions {
         pre_link_args,
         panic_strategy: PanicStrategy::Abort,
         position_independent_executables: true,
-        relocation_model: "static".to_string(),
+        relocation_model: RelocModel::Static,
         target_family: None,
         tls_model: "initial-exec".to_string(),
         ..Default::default()
diff --git a/src/librustc_target/spec/hermit_kernel_base.rs b/src/librustc_target/spec/hermit_kernel_base.rs
index 1f9b195e2e6..11599fda409 100644
--- a/src/librustc_target/spec/hermit_kernel_base.rs
+++ b/src/librustc_target/spec/hermit_kernel_base.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions};
+use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     let mut pre_link_args = LinkArgs::new();
@@ -16,7 +16,7 @@ pub fn opts() -> TargetOptions {
         pre_link_args,
         panic_strategy: PanicStrategy::Abort,
         position_independent_executables: true,
-        relocation_model: "static".to_string(),
+        relocation_model: RelocModel::Static,
         target_family: None,
         tls_model: "initial-exec".to_string(),
         ..Default::default()
diff --git a/src/librustc_target/spec/linux_kernel_base.rs b/src/librustc_target/spec/linux_kernel_base.rs
index 4a900d1b02c..201d6a0fff9 100644
--- a/src/librustc_target/spec/linux_kernel_base.rs
+++ b/src/librustc_target/spec/linux_kernel_base.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, RelroLevel, TargetOptions};
+use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, RelroLevel, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     let mut pre_link_args = LinkArgs::new();
@@ -16,7 +16,7 @@ pub fn opts() -> TargetOptions {
         position_independent_executables: true,
         needs_plt: true,
         relro_level: RelroLevel::Full,
-        relocation_model: "static".to_string(),
+        relocation_model: RelocModel::Static,
         target_family: Some("unix".to_string()),
         pre_link_args,
 
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index d9040463317..77fc78e8148 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -265,6 +265,46 @@ impl ToJson for MergeFunctions {
     }
 }
 
+#[derive(Clone, Copy, PartialEq, Hash, Debug)]
+pub enum RelocModel {
+    Static,
+    Pic,
+    DynamicNoPic,
+    Ropi,
+    Rwpi,
+    RopiRwpi,
+}
+
+impl FromStr for RelocModel {
+    type Err = ();
+
+    fn from_str(s: &str) -> Result<RelocModel, ()> {
+        Ok(match s {
+            "static" => RelocModel::Static,
+            "pic" => RelocModel::Pic,
+            "dynamic-no-pic" => RelocModel::DynamicNoPic,
+            "ropi" => RelocModel::Ropi,
+            "rwpi" => RelocModel::Rwpi,
+            "ropi-rwpi" => RelocModel::RopiRwpi,
+            _ => return Err(()),
+        })
+    }
+}
+
+impl ToJson for RelocModel {
+    fn to_json(&self) -> Json {
+        match *self {
+            RelocModel::Static => "static",
+            RelocModel::Pic => "pic",
+            RelocModel::DynamicNoPic => "dynamic-no-pic",
+            RelocModel::Ropi => "ropi",
+            RelocModel::Rwpi => "rwpi",
+            RelocModel::RopiRwpi => "ropi-rwpi",
+        }
+        .to_json()
+    }
+}
+
 pub enum LoadTargetError {
     BuiltinTargetNotFound(String),
     Other(String),
@@ -614,8 +654,8 @@ pub struct TargetOptions {
     /// libraries. Defaults to false.
     pub executables: bool,
     /// Relocation model to use in object file. Corresponds to `llc
-    /// -relocation-model=$relocation_model`. Defaults to "pic".
-    pub relocation_model: String,
+    /// -relocation-model=$relocation_model`. Defaults to `Pic`.
+    pub relocation_model: RelocModel,
     /// Code model to use. Corresponds to `llc -code-model=$code_model`.
     pub code_model: Option<String>,
     /// TLS model to use. Options are "global-dynamic" (default), "local-dynamic", "initial-exec"
@@ -821,7 +861,7 @@ impl Default for TargetOptions {
             dynamic_linking: false,
             only_cdylib: false,
             executables: false,
-            relocation_model: "pic".to_string(),
+            relocation_model: RelocModel::Pic,
             code_model: None,
             tls_model: "global-dynamic".to_string(),
             disable_redzone: false,
@@ -1008,6 +1048,18 @@ impl Target {
                     Some(Ok(()))
                 })).unwrap_or(Ok(()))
             } );
+            ($key_name:ident, RelocModel) => ( {
+                let name = (stringify!($key_name)).replace("_", "-");
+                obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+                    match s.parse::<RelocModel>() {
+                        Ok(relocation_model) => base.options.$key_name = relocation_model,
+                        _ => return Some(Err(format!("'{}' is not a valid relocation model. \
+                                                      Run `rustc --print relocation-models` to \
+                                                      see the list of supported values.", s))),
+                    }
+                    Some(Ok(()))
+                })).unwrap_or(Ok(()))
+            } );
             ($key_name:ident, PanicStrategy) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
                 obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
@@ -1146,7 +1198,7 @@ impl Target {
         key!(dynamic_linking, bool);
         key!(only_cdylib, bool);
         key!(executables, bool);
-        key!(relocation_model);
+        key!(relocation_model, RelocModel)?;
         key!(code_model, optional);
         key!(tls_model);
         key!(disable_redzone, bool);
diff --git a/src/librustc_target/spec/msp430_none_elf.rs b/src/librustc_target/spec/msp430_none_elf.rs
index 9a90ac7ccec..c6d0308f8f8 100644
--- a/src/librustc_target/spec/msp430_none_elf.rs
+++ b/src/librustc_target/spec/msp430_none_elf.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
+use crate::spec::{LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
@@ -40,7 +40,7 @@ pub fn target() -> TargetResult {
 
             // Similarly, one almost always never wants to use relocatable
             // code because of the extra costs it involves.
-            relocation_model: "static".to_string(),
+            relocation_model: RelocModel::Static,
 
             // Right now we invoke an external assembler and this isn't
             // compatible with multiple codegen units, and plus we probably
diff --git a/src/librustc_target/spec/riscv32i_unknown_none_elf.rs b/src/librustc_target/spec/riscv32i_unknown_none_elf.rs
index a7020bc8f91..aade1e70823 100644
--- a/src/librustc_target/spec/riscv32i_unknown_none_elf.rs
+++ b/src/librustc_target/spec/riscv32i_unknown_none_elf.rs
@@ -1,4 +1,5 @@
-use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
@@ -21,7 +22,7 @@ pub fn target() -> TargetResult {
             features: String::new(),
             executables: true,
             panic_strategy: PanicStrategy::Abort,
-            relocation_model: "static".to_string(),
+            relocation_model: RelocModel::Static,
             emit_debug_gdb_scripts: false,
             abi_blacklist: super::riscv_base::abi_blacklist(),
             eliminate_frame_pointer: false,
diff --git a/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs b/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs
index 6ec49410aeb..e2990eeb826 100644
--- a/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs
+++ b/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs
@@ -1,4 +1,5 @@
-use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
@@ -21,7 +22,7 @@ pub fn target() -> TargetResult {
             features: "+m,+a,+c".to_string(),
             executables: true,
             panic_strategy: PanicStrategy::Abort,
-            relocation_model: "static".to_string(),
+            relocation_model: RelocModel::Static,
             emit_debug_gdb_scripts: false,
             abi_blacklist: super::riscv_base::abi_blacklist(),
             eliminate_frame_pointer: false,
diff --git a/src/librustc_target/spec/riscv32imc_unknown_none_elf.rs b/src/librustc_target/spec/riscv32imc_unknown_none_elf.rs
index 70346347fb3..55a4d58dfcc 100644
--- a/src/librustc_target/spec/riscv32imc_unknown_none_elf.rs
+++ b/src/librustc_target/spec/riscv32imc_unknown_none_elf.rs
@@ -1,4 +1,5 @@
-use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
@@ -21,7 +22,7 @@ pub fn target() -> TargetResult {
             features: "+m,+c".to_string(),
             executables: true,
             panic_strategy: PanicStrategy::Abort,
-            relocation_model: "static".to_string(),
+            relocation_model: RelocModel::Static,
             emit_debug_gdb_scripts: false,
             abi_blacklist: super::riscv_base::abi_blacklist(),
             eliminate_frame_pointer: false,
diff --git a/src/librustc_target/spec/riscv64gc_unknown_none_elf.rs b/src/librustc_target/spec/riscv64gc_unknown_none_elf.rs
index ca0f3d64d4a..9dbbcb1f4bd 100644
--- a/src/librustc_target/spec/riscv64gc_unknown_none_elf.rs
+++ b/src/librustc_target/spec/riscv64gc_unknown_none_elf.rs
@@ -1,4 +1,5 @@
-use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
@@ -21,7 +22,7 @@ pub fn target() -> TargetResult {
             features: "+m,+a,+f,+d,+c".to_string(),
             executables: true,
             panic_strategy: PanicStrategy::Abort,
-            relocation_model: "static".to_string(),
+            relocation_model: RelocModel::Static,
             code_model: Some("medium".to_string()),
             emit_debug_gdb_scripts: false,
             abi_blacklist: super::riscv_base::abi_blacklist(),
diff --git a/src/librustc_target/spec/riscv64imac_unknown_none_elf.rs b/src/librustc_target/spec/riscv64imac_unknown_none_elf.rs
index 614403fe02a..7e9390561a7 100644
--- a/src/librustc_target/spec/riscv64imac_unknown_none_elf.rs
+++ b/src/librustc_target/spec/riscv64imac_unknown_none_elf.rs
@@ -1,4 +1,5 @@
-use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
+use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
@@ -21,7 +22,7 @@ pub fn target() -> TargetResult {
             features: "+m,+a,+c".to_string(),
             executables: true,
             panic_strategy: PanicStrategy::Abort,
-            relocation_model: "static".to_string(),
+            relocation_model: RelocModel::Static,
             code_model: Some("medium".to_string()),
             emit_debug_gdb_scripts: false,
             abi_blacklist: super::riscv_base::abi_blacklist(),
diff --git a/src/librustc_target/spec/thumb_base.rs b/src/librustc_target/spec/thumb_base.rs
index eca095b5942..646a149a336 100644
--- a/src/librustc_target/spec/thumb_base.rs
+++ b/src/librustc_target/spec/thumb_base.rs
@@ -27,7 +27,7 @@
 // differentiate these targets from our other `arm(v7)-*-*-gnueabi(hf)` targets in the context of
 // build scripts / gcc flags.
 
-use crate::spec::{PanicStrategy, TargetOptions};
+use crate::spec::{PanicStrategy, RelocModel, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     // See rust-lang/rfcs#1645 for a discussion about these defaults
@@ -40,7 +40,7 @@ pub fn opts() -> TargetOptions {
         panic_strategy: PanicStrategy::Abort,
         // Similarly, one almost always never wants to use relocatable code because of the extra
         // costs it involves.
-        relocation_model: "static".to_string(),
+        relocation_model: RelocModel::Static,
         abi_blacklist: super::arm_base::abi_blacklist(),
         // When this section is added a volatile load to its start address is also generated. This
         // volatile load is a footgun as it can end up loading an invalid memory address, depending
diff --git a/src/librustc_target/spec/wasm32_base.rs b/src/librustc_target/spec/wasm32_base.rs
index 47e80e8db19..08bade2abf4 100644
--- a/src/librustc_target/spec/wasm32_base.rs
+++ b/src/librustc_target/spec/wasm32_base.rs
@@ -1,4 +1,4 @@
-use super::{LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions};
+use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, TargetOptions};
 use std::collections::BTreeMap;
 
 pub fn options() -> TargetOptions {
@@ -130,7 +130,7 @@ pub fn options() -> TargetOptions {
         // that eventually we can ship a `pic`-compatible standard library which
         // works with `static` as well (or works with some method of generating
         // non-relative calls and such later on).
-        relocation_model: "static".to_string(),
+        relocation_model: RelocModel::Static,
 
         // When the atomics feature is activated then these two keys matter,
         // otherwise they're basically ignored by the standard library. In this
diff --git a/src/libstd/sync/mpsc/stream.rs b/src/libstd/sync/mpsc/stream.rs
index 26b4faebd86..9f7c1af8951 100644
--- a/src/libstd/sync/mpsc/stream.rs
+++ b/src/libstd/sync/mpsc/stream.rs
@@ -329,7 +329,7 @@ impl<T> Packet<T> {
             );
             cnt != DISCONNECTED && cnt != steals
         } {
-            while let Some(_) = self.queue.pop() {
+            while self.queue.pop().is_some() {
                 steals += 1;
             }
         }
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index b221c17b422..e31dd77d8af 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -346,8 +346,7 @@ static PassBuilder::OptimizationLevel fromRust(LLVMRustPassBuilderOptLevel Level
   }
 }
 
-enum class LLVMRustRelocMode {
-  Default,
+enum class LLVMRustRelocModel {
   Static,
   PIC,
   DynamicNoPic,
@@ -356,21 +355,19 @@ enum class LLVMRustRelocMode {
   ROPIRWPI,
 };
 
-static Optional<Reloc::Model> fromRust(LLVMRustRelocMode RustReloc) {
+static Reloc::Model fromRust(LLVMRustRelocModel RustReloc) {
   switch (RustReloc) {
-  case LLVMRustRelocMode::Default:
-    return None;
-  case LLVMRustRelocMode::Static:
+  case LLVMRustRelocModel::Static:
     return Reloc::Static;
-  case LLVMRustRelocMode::PIC:
+  case LLVMRustRelocModel::PIC:
     return Reloc::PIC_;
-  case LLVMRustRelocMode::DynamicNoPic:
+  case LLVMRustRelocModel::DynamicNoPic:
     return Reloc::DynamicNoPIC;
-  case LLVMRustRelocMode::ROPI:
+  case LLVMRustRelocModel::ROPI:
     return Reloc::ROPI;
-  case LLVMRustRelocMode::RWPI:
+  case LLVMRustRelocModel::RWPI:
     return Reloc::RWPI;
-  case LLVMRustRelocMode::ROPIRWPI:
+  case LLVMRustRelocModel::ROPIRWPI:
     return Reloc::ROPI_RWPI;
   }
   report_fatal_error("Bad RelocModel.");
@@ -440,7 +437,7 @@ extern "C" const char* LLVMRustGetHostCPUName(size_t *len) {
 
 extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
     const char *TripleStr, const char *CPU, const char *Feature,
-    const char *ABIStr, LLVMRustCodeModel RustCM, LLVMRustRelocMode RustReloc,
+    const char *ABIStr, LLVMRustCodeModel RustCM, LLVMRustRelocModel RustReloc,
     LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat,
     bool PositionIndependentExecutable, bool FunctionSections,
     bool DataSections,
diff --git a/src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile b/src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile
index 35317dca1e8..5d46be87eac 100644
--- a/src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile
+++ b/src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile
@@ -11,10 +11,7 @@ LOG := $(TMPDIR)/log.txt
 # are compiled with address sanitizer, and we assert that a fault in the cdylib
 # is correctly detected.
 
-# See comment in sanitizer-address/Makefile for why this is here
-EXTRA_RUSTFLAG=-C relocation-model=dynamic-no-pic
-
 all:
-	$(RUSTC) -g -Z sanitizer=address --crate-type cdylib --target $(TARGET) $(EXTRA_RUSTFLAG) library.rs
-	$(RUSTC) -g -Z sanitizer=address --crate-type bin --target $(TARGET) $(EXTRA_RUSTFLAG) -llibrary program.rs
+	$(RUSTC) -g -Z sanitizer=address --crate-type cdylib --target $(TARGET) library.rs
+	$(RUSTC) -g -Z sanitizer=address --crate-type bin --target $(TARGET) -llibrary program.rs
 	LD_LIBRARY_PATH=$(TMPDIR) $(TMPDIR)/program 2>&1 | $(CGREP) stack-buffer-overflow
diff --git a/src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile b/src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile
index 24d2ebd8f48..f62c3a6654e 100644
--- a/src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile
+++ b/src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile
@@ -11,10 +11,7 @@ LOG := $(TMPDIR)/log.txt
 # are compiled with address sanitizer, and we assert that a fault in the dylib
 # is correctly detected.
 
-# See comment in sanitizer-address/Makefile for why this is here
-EXTRA_RUSTFLAG=-C relocation-model=dynamic-no-pic
-
 all:
-	$(RUSTC) -g -Z sanitizer=address --crate-type dylib --target $(TARGET) $(EXTRA_RUSTFLAG) library.rs
-	$(RUSTC) -g -Z sanitizer=address --crate-type bin --target $(TARGET) $(EXTRA_RUSTFLAG) -llibrary program.rs
+	$(RUSTC) -g -Z sanitizer=address --crate-type dylib --target $(TARGET) library.rs
+	$(RUSTC) -g -Z sanitizer=address --crate-type bin --target $(TARGET) -llibrary program.rs
 	LD_LIBRARY_PATH=$(TMPDIR) $(TMPDIR)/program 2>&1 | $(CGREP) stack-buffer-overflow