From 37b015fb912676e05625c974ed4d62136b98e3cb Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 31 Oct 2017 17:45:19 +0000 Subject: [PATCH 1/4] Fix error message for invalid code/reloc models --- src/librustc_back/target/mod.rs | 6 ++++++ src/librustc_trans/back/write.rs | 4 +--- src/librustc_trans/context.rs | 4 +--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index a56d067815819..8fd4aad89c643 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -311,6 +311,9 @@ pub struct TargetOptions { pub relocation_model: String, /// Code model to use. Corresponds to `llc -code-model=$code_model`. Defaults to "default". pub code_model: String, + /// TLS model to use. Options are "global-dynamic" (default), "local-dynamic", "initial-exec" + /// and "local-exec". This is similar to the -ftls-model option in GCC/Clang. + pub tls_model: String, /// Do not emit code that uses the "red zone", if the ABI has one. Defaults to false. pub disable_redzone: bool, /// Eliminate frame pointers from stack frames if possible. Defaults to true. @@ -450,6 +453,7 @@ impl Default for TargetOptions { executables: false, relocation_model: "pic".to_string(), code_model: "default".to_string(), + tls_model: "global-dynamic".to_string(), disable_redzone: false, eliminate_frame_pointer: true, function_sections: true, @@ -696,6 +700,7 @@ impl Target { key!(executables, bool); key!(relocation_model); key!(code_model); + key!(tls_model); key!(disable_redzone, bool); key!(eliminate_frame_pointer, bool); key!(function_sections, bool); @@ -888,6 +893,7 @@ impl ToJson for Target { target_option_val!(executables); target_option_val!(relocation_model); target_option_val!(code_model); + target_option_val!(tls_model); target_option_val!(disable_redzone); target_option_val!(eliminate_frame_pointer); target_option_val!(function_sections); diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 5550ab9fa55e6..6153d3dcdbba2 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -173,9 +173,7 @@ pub fn target_machine_factory(sess: &Session) Some(x) => x.1, _ => { sess.err(&format!("{:?} is not a valid code model", - sess.opts - .cg - .code_model)); + code_model_arg)); sess.abort_if_errors(); bug!(); } diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 9df057c77a95d..cd9cb8c0df531 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -159,9 +159,7 @@ pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode { Some(x) => x.1, _ => { sess.err(&format!("{:?} is not a valid relocation mode", - sess.opts - .cg - .code_model)); + reloc_model_arg)); sess.abort_if_errors(); bug!(); } From b233a6e0968c48719c066b8ba4d247925071f680 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 31 Oct 2017 18:24:04 +0000 Subject: [PATCH 2/4] Add support for specifying the TLS model --- src/librustc/session/config.rs | 14 +++++++++++++- src/librustc_driver/lib.rs | 8 ++++++++ src/librustc_llvm/ffi.rs | 12 ++++++++++++ src/librustc_llvm/lib.rs | 5 +++++ src/librustc_trans/back/write.rs | 7 +++++++ src/librustc_trans/consts.rs | 10 +++++----- src/librustc_trans/context.rs | 18 ++++++++++++++++++ 7 files changed, 68 insertions(+), 6 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 0f8312abc3f9f..d1d04e883b8fd 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -368,6 +368,7 @@ pub enum PrintRequest { TargetFeatures, RelocationModels, CodeModels, + TlsModels, TargetSpec, NativeStaticLibs, } @@ -910,6 +911,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, "choose the relocation model to use (rustc --print relocation-models for details)"), code_model: Option = (None, parse_opt_string, [TRACKED], "choose the code model to use (rustc --print code-models for details)"), + tls_model: Option = (None, parse_opt_string, [TRACKED], + "choose the TLS model to use (rustc --print tls-models for details)"), metadata: Vec = (Vec::new(), parse_list, [TRACKED], "metadata to mangle symbol names with"), extra_filename: String = ("".to_string(), parse_string, [UNTRACKED], @@ -1330,7 +1333,7 @@ pub fn rustc_short_optgroups() -> Vec { print on stdout", "[crate-name|file-names|sysroot|cfg|target-list|\ target-cpus|target-features|relocation-models|\ - code-models|target-spec-json|native-static-libs]"), + code-models|tls-models|target-spec-json|native-static-libs]"), opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"), opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"), opt::opt_s("o", "", "Write output to ", "FILENAME"), @@ -1573,6 +1576,10 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) prints.push(PrintRequest::CodeModels); cg.code_model = None; } + if cg.tls_model.as_ref().map_or(false, |s| s == "help") { + prints.push(PrintRequest::TlsModels); + cg.tls_model = None; + } let cg = cg; @@ -1672,6 +1679,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) "target-features" => PrintRequest::TargetFeatures, "relocation-models" => PrintRequest::RelocationModels, "code-models" => PrintRequest::CodeModels, + "tls-models" => PrintRequest::TlsModels, "native-static-libs" => PrintRequest::NativeStaticLibs, "target-spec-json" => { if nightly_options::is_unstable_enabled(matches) { @@ -2514,6 +2522,10 @@ mod tests { opts.cg.code_model = Some(String::from("code model")); assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + opts = reference.clone(); + opts.cg.tls_model = Some(String::from("tls model")); + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + opts = reference.clone(); opts.cg.metadata = vec![String::from("A"), String::from("B")]; assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index fc503f4eb4be1..c5cce70c94566 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -177,6 +177,7 @@ mod rustc_trans { pub mod write { pub const RELOC_MODEL_ARGS: [(&'static str, ()); 0] = []; pub const CODE_GEN_MODEL_ARGS: [(&'static str, ()); 0] = []; + pub const TLS_MODEL_ARGS: [(&'static str, ()); 0] = []; } } } @@ -797,6 +798,13 @@ impl RustcDefaultCalls { } println!(""); } + PrintRequest::TlsModels => { + println!("Available TLS models:"); + for &(name, _) in rustc_trans::back::write::TLS_MODEL_ARGS.iter(){ + println!(" {}", name); + } + println!(""); + } PrintRequest::TargetCPUs | PrintRequest::TargetFeatures => { rustc_trans::print(*req, sess); } diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs index 3399bf2acd891..ac0e4dde0c102 100644 --- a/src/librustc_llvm/ffi.rs +++ b/src/librustc_llvm/ffi.rs @@ -359,6 +359,17 @@ pub struct ThinLTOModule { pub len: usize, } +/// LLVMThreadLocalMode +#[derive(Copy, Clone)] +#[repr(C)] +pub enum ThreadLocalMode { + NotThreadLocal, + GeneralDynamic, + LocalDynamic, + InitialExec, + LocalExec +} + // Opaque pointer types #[allow(missing_copy_implementations)] pub enum Module_opaque {} @@ -709,6 +720,7 @@ extern "C" { pub fn LLVMGetInitializer(GlobalVar: ValueRef) -> ValueRef; pub fn LLVMSetInitializer(GlobalVar: ValueRef, ConstantVal: ValueRef); pub fn LLVMSetThreadLocal(GlobalVar: ValueRef, IsThreadLocal: Bool); + pub fn LLVMSetThreadLocalMode(GlobalVar: ValueRef, Mode: ThreadLocalMode); pub fn LLVMIsGlobalConstant(GlobalVar: ValueRef) -> Bool; pub fn LLVMSetGlobalConstant(GlobalVar: ValueRef, IsConstant: Bool); pub fn LLVMRustGetNamedValue(M: ModuleRef, Name: *const c_char) -> ValueRef; diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 98172bca17786..5ccce8de70639 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -172,6 +172,11 @@ pub fn set_thread_local(global: ValueRef, is_thread_local: bool) { LLVMSetThreadLocal(global, is_thread_local as Bool); } } +pub fn set_thread_local_mode(global: ValueRef, mode: ThreadLocalMode) { + unsafe { + LLVMSetThreadLocalMode(global, mode); + } +} impl Attribute { pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) { diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 6153d3dcdbba2..3d923922bb1cf 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -76,6 +76,13 @@ pub const CODE_GEN_MODEL_ARGS : [(&'static str, llvm::CodeModel); 5] = [ ("large", llvm::CodeModel::Large), ]; +pub const TLS_MODEL_ARGS : [(&'static str, llvm::ThreadLocalMode); 4] = [ + ("global-dynamic", llvm::ThreadLocalMode::GeneralDynamic), + ("local-dynamic", llvm::ThreadLocalMode::LocalDynamic), + ("initial-exec", llvm::ThreadLocalMode::InitialExec), + ("local-exec", llvm::ThreadLocalMode::LocalExec), +]; + pub fn llvm_err(handler: &errors::Handler, msg: String) -> FatalError { match llvm::last_error() { Some(err) => handler.fatal(&format!("{}: {}", msg, err)), diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index eaf7392aab5b4..0f5ede91c7d6e 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -23,6 +23,7 @@ use monomorphize::Instance; use type_::Type; use type_of; use rustc::ty; +use context::get_tls_model; use rustc::hir; @@ -196,7 +197,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef { for attr in attrs { if attr.check_name("thread_local") { - llvm::set_thread_local(g, true); + llvm::set_thread_local_mode(g, get_tls_model(ccx.sess())); } } @@ -215,7 +216,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef { // symbol and another one doesn't. for attr in ccx.tcx().get_attrs(def_id).iter() { if attr.check_name("thread_local") { - llvm::set_thread_local(g, true); + llvm::set_thread_local_mode(g, get_tls_model(ccx.sess())); } } if ccx.use_dll_storage_attrs() && !ccx.tcx().is_foreign_item(def_id) { @@ -305,9 +306,8 @@ pub fn trans_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, debuginfo::create_global_var_metadata(ccx, id, g); - if attr::contains_name(attrs, - "thread_local") { - llvm::set_thread_local(g, true); + if attr::contains_name(attrs, "thread_local") { + llvm::set_thread_local_mode(g, get_tls_model(ccx.sess())); } base::set_link_section(ccx, g, attrs); diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index cd9cb8c0df531..afdbc31c456bb 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -166,6 +166,24 @@ pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode { } } +pub fn get_tls_model(sess: &Session) -> llvm::ThreadLocalMode { + let tls_model_arg = match sess.opts.cg.tls_model { + Some(ref s) => &s[..], + None => &sess.target.target.options.tls_model[..], + }; + + match ::back::write::TLS_MODEL_ARGS.iter().find( + |&&arg| arg.0 == tls_model_arg) { + Some(x) => x.1, + _ => { + sess.err(&format!("{:?} is not a valid TLS model", + tls_model_arg)); + sess.abort_if_errors(); + bug!(); + } + } +} + fn is_any_library(sess: &Session) -> bool { sess.crate_types.borrow().iter().any(|ty| { *ty != config::CrateTypeExecutable From ad1bb2e465a1b83bde937ce05b7cf84cf949f1b3 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Fri, 3 Nov 2017 00:23:56 +0000 Subject: [PATCH 3/4] Cache the TLS model in the crate context --- src/librustc_trans/consts.rs | 7 +++---- src/librustc_trans/context.rs | 10 +++++++++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index 0f5ede91c7d6e..4ae289cfada00 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -23,7 +23,6 @@ use monomorphize::Instance; use type_::Type; use type_of; use rustc::ty; -use context::get_tls_model; use rustc::hir; @@ -197,7 +196,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef { for attr in attrs { if attr.check_name("thread_local") { - llvm::set_thread_local_mode(g, get_tls_model(ccx.sess())); + llvm::set_thread_local_mode(g, ccx.tls_model()); } } @@ -216,7 +215,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef { // symbol and another one doesn't. for attr in ccx.tcx().get_attrs(def_id).iter() { if attr.check_name("thread_local") { - llvm::set_thread_local_mode(g, get_tls_model(ccx.sess())); + llvm::set_thread_local_mode(g, ccx.tls_model()); } } if ccx.use_dll_storage_attrs() && !ccx.tcx().is_foreign_item(def_id) { @@ -307,7 +306,7 @@ pub fn trans_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, debuginfo::create_global_var_metadata(ccx, id, g); if attr::contains_name(attrs, "thread_local") { - llvm::set_thread_local_mode(g, get_tls_model(ccx.sess())); + llvm::set_thread_local_mode(g, ccx.tls_model()); } base::set_link_section(ccx, g, attrs); diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index afdbc31c456bb..0089dd67121cb 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -52,6 +52,7 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, check_overflow: bool, use_dll_storage_attrs: bool, + tls_model: llvm::ThreadLocalMode, } /// The local portion of a `CrateContext`. There is one `LocalCrateContext` @@ -166,7 +167,7 @@ pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode { } } -pub fn get_tls_model(sess: &Session) -> llvm::ThreadLocalMode { +fn get_tls_model(sess: &Session) -> llvm::ThreadLocalMode { let tls_model_arg = match sess.opts.cg.tls_model { Some(ref s) => &s[..], None => &sess.target.target.options.tls_model[..], @@ -299,10 +300,13 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { let check_overflow = tcx.sess.overflow_checks(); + let tls_model = get_tls_model(&tcx.sess); + SharedCrateContext { tcx, check_overflow, use_dll_storage_attrs, + tls_model, } } @@ -544,6 +548,10 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { self.shared.use_dll_storage_attrs() } + pub fn tls_model(&self) -> llvm::ThreadLocalMode { + self.shared.tls_model + } + /// Generate a new symbol name with the given prefix. This symbol name must /// only be used for definitions with `internal` or `private` linkage. pub fn generate_local_symbol_name(&self, prefix: &str) -> String { From fdf7ba2ce9e304a21d50adf41643da28268fd6fc Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Mon, 6 Nov 2017 21:10:49 +0000 Subject: [PATCH 4/4] Move tls-model to a -Z option since it is unstable --- src/librustc/session/config.rs | 12 ++++++------ src/librustc_trans/context.rs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index d1d04e883b8fd..558761256d2a9 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -911,8 +911,6 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, "choose the relocation model to use (rustc --print relocation-models for details)"), code_model: Option = (None, parse_opt_string, [TRACKED], "choose the code model to use (rustc --print code-models for details)"), - tls_model: Option = (None, parse_opt_string, [TRACKED], - "choose the TLS model to use (rustc --print tls-models for details)"), metadata: Vec = (Vec::new(), parse_list, [TRACKED], "metadata to mangle symbol names with"), extra_filename: String = ("".to_string(), parse_string, [UNTRACKED], @@ -1107,6 +1105,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "enable ThinLTO when possible"), inline_in_all_cgus: Option = (None, parse_opt_bool, [TRACKED], "control whether #[inline] functions are in all cgus"), + tls_model: Option = (None, parse_opt_string, [TRACKED], + "choose the TLS model to use (rustc --print tls-models for details)"), } pub fn default_lib_output() -> CrateType { @@ -1475,7 +1475,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) }) }); - let debugging_opts = build_debugging_options(matches, error_format); + let mut debugging_opts = build_debugging_options(matches, error_format); let mut output_types = BTreeMap::new(); if !debugging_opts.parse_only { @@ -1576,9 +1576,9 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) prints.push(PrintRequest::CodeModels); cg.code_model = None; } - if cg.tls_model.as_ref().map_or(false, |s| s == "help") { + if debugging_opts.tls_model.as_ref().map_or(false, |s| s == "help") { prints.push(PrintRequest::TlsModels); - cg.tls_model = None; + debugging_opts.tls_model = None; } let cg = cg; @@ -2523,7 +2523,7 @@ mod tests { assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); opts = reference.clone(); - opts.cg.tls_model = Some(String::from("tls model")); + opts.debugging_opts.tls_model = Some(String::from("tls model")); assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); opts = reference.clone(); diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 0089dd67121cb..cb71ef104d3d9 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -168,7 +168,7 @@ pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode { } fn get_tls_model(sess: &Session) -> llvm::ThreadLocalMode { - let tls_model_arg = match sess.opts.cg.tls_model { + let tls_model_arg = match sess.opts.debugging_opts.tls_model { Some(ref s) => &s[..], None => &sess.target.target.options.tls_model[..], };