Skip to content

Allow overriding the TLS model #45666

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 7, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ pub enum PrintRequest {
TargetFeatures,
RelocationModels,
CodeModels,
TlsModels,
TargetSpec,
NativeStaticLibs,
}
Expand Down Expand Up @@ -1104,6 +1105,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"enable ThinLTO when possible"),
inline_in_all_cgus: Option<bool> = (None, parse_opt_bool, [TRACKED],
"control whether #[inline] functions are in all cgus"),
tls_model: Option<String> = (None, parse_opt_string, [TRACKED],
"choose the TLS model to use (rustc --print tls-models for details)"),
}

pub fn default_lib_output() -> CrateType {
Expand Down Expand Up @@ -1330,7 +1333,7 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
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>", "FILENAME"),
Expand Down Expand Up @@ -1472,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 {
Expand Down Expand Up @@ -1573,6 +1576,10 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
prints.push(PrintRequest::CodeModels);
cg.code_model = None;
}
if debugging_opts.tls_model.as_ref().map_or(false, |s| s == "help") {
prints.push(PrintRequest::TlsModels);
debugging_opts.tls_model = None;
}

let cg = cg;

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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.debugging_opts.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());
Expand Down
6 changes: 6 additions & 0 deletions src/librustc_back/target/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
8 changes: 8 additions & 0 deletions src/librustc_driver/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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] = [];
}
}
}
Expand Down Expand Up @@ -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);
}
Expand Down
12 changes: 12 additions & 0 deletions src/librustc_llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
Expand Down Expand Up @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions src/librustc_llvm/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
11 changes: 8 additions & 3 deletions src/librustc_trans/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)),
Expand Down Expand Up @@ -173,9 +180,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!();
}
Expand Down
9 changes: 4 additions & 5 deletions src/librustc_trans/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,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(g, true);
llvm::set_thread_local_mode(g, ccx.tls_model());
}
}

Expand All @@ -215,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(g, true);
llvm::set_thread_local_mode(g, ccx.tls_model());
}
}
if ccx.use_dll_storage_attrs() && !ccx.tcx().is_foreign_item(def_id) {
Expand Down Expand Up @@ -305,9 +305,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, ccx.tls_model());
}

base::set_link_section(ccx, g, attrs);
Expand Down
30 changes: 27 additions & 3 deletions src/librustc_trans/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down Expand Up @@ -159,9 +160,25 @@ 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!();
}
}
}

fn get_tls_model(sess: &Session) -> llvm::ThreadLocalMode {
let tls_model_arg = match sess.opts.debugging_opts.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!();
}
Expand Down Expand Up @@ -283,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,
}
}

Expand Down Expand Up @@ -528,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 {
Expand Down