From 76d85de22359d7a924b84dde6830650e92e44b89 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 23 Apr 2020 21:10:01 +0300 Subject: [PATCH] codegen_llvm: Simplify logic for relaxing PIC into PIE --- src/librustc_codegen_llvm/back/write.rs | 24 +++++++--------------- src/librustc_codegen_llvm/context.rs | 13 ++++++++---- src/librustc_codegen_llvm/lib.rs | 11 +++------- src/librustc_codegen_llvm/llvm_util.rs | 4 ++-- src/librustc_codegen_ssa/back/write.rs | 2 +- src/librustc_codegen_ssa/traits/backend.rs | 4 ---- 6 files changed, 22 insertions(+), 36 deletions(-) diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 8fa577d87129..bf79c5b593e4 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::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; @@ -75,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()) } @@ -128,13 +122,9 @@ fn to_llvm_relocation_model(relocation_model: RelocModel) -> llvm::RelocModel { } } -// 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. pub fn target_machine_factory( sess: &Session, optlvl: config::OptLevel, - find_features: bool, ) -> Arc Result<&'static mut llvm::TargetMachine, String> + Send + Sync> { let reloc_model = to_llvm_relocation_model(sess.relocation_model()); @@ -177,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; @@ -194,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 f614df6045c5..df442609052b 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -103,9 +103,14 @@ fn get_tls_model(sess: &Session) -> llvm::ThreadLocalMode { } } -pub fn is_pie_binary(sess: &Session) -> bool { +/// 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.borrow().iter().any(|ty| *ty != config::CrateType::Executable) + && 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 { @@ -138,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); @@ -185,7 +190,7 @@ pub unsafe fn create_module( 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 9d6f21508411..330d6ea75d27 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 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) @@ -353,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) } } } @@ -361,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_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index 6f16b0fb79c3..a36e95771e8b 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 { - 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/write.rs b/src/librustc_codegen_ssa/back/write.rs index 37034141bb77..c84f38670f77 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( 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 91be123beb0b..6cbb47efa99f 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, 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 Result + Send + Sync>; fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str; }