Skip to content

Commit b233a6e

Browse files
committed
Add support for specifying the TLS model
1 parent 37b015f commit b233a6e

File tree

7 files changed

+68
-6
lines changed

7 files changed

+68
-6
lines changed

src/librustc/session/config.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ pub enum PrintRequest {
368368
TargetFeatures,
369369
RelocationModels,
370370
CodeModels,
371+
TlsModels,
371372
TargetSpec,
372373
NativeStaticLibs,
373374
}
@@ -910,6 +911,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
910911
"choose the relocation model to use (rustc --print relocation-models for details)"),
911912
code_model: Option<String> = (None, parse_opt_string, [TRACKED],
912913
"choose the code model to use (rustc --print code-models for details)"),
914+
tls_model: Option<String> = (None, parse_opt_string, [TRACKED],
915+
"choose the TLS model to use (rustc --print tls-models for details)"),
913916
metadata: Vec<String> = (Vec::new(), parse_list, [TRACKED],
914917
"metadata to mangle symbol names with"),
915918
extra_filename: String = ("".to_string(), parse_string, [UNTRACKED],
@@ -1330,7 +1333,7 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
13301333
print on stdout",
13311334
"[crate-name|file-names|sysroot|cfg|target-list|\
13321335
target-cpus|target-features|relocation-models|\
1333-
code-models|target-spec-json|native-static-libs]"),
1336+
code-models|tls-models|target-spec-json|native-static-libs]"),
13341337
opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"),
13351338
opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"),
13361339
opt::opt_s("o", "", "Write output to <filename>", "FILENAME"),
@@ -1573,6 +1576,10 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
15731576
prints.push(PrintRequest::CodeModels);
15741577
cg.code_model = None;
15751578
}
1579+
if cg.tls_model.as_ref().map_or(false, |s| s == "help") {
1580+
prints.push(PrintRequest::TlsModels);
1581+
cg.tls_model = None;
1582+
}
15761583

15771584
let cg = cg;
15781585

@@ -1672,6 +1679,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
16721679
"target-features" => PrintRequest::TargetFeatures,
16731680
"relocation-models" => PrintRequest::RelocationModels,
16741681
"code-models" => PrintRequest::CodeModels,
1682+
"tls-models" => PrintRequest::TlsModels,
16751683
"native-static-libs" => PrintRequest::NativeStaticLibs,
16761684
"target-spec-json" => {
16771685
if nightly_options::is_unstable_enabled(matches) {
@@ -2514,6 +2522,10 @@ mod tests {
25142522
opts.cg.code_model = Some(String::from("code model"));
25152523
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
25162524

2525+
opts = reference.clone();
2526+
opts.cg.tls_model = Some(String::from("tls model"));
2527+
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2528+
25172529
opts = reference.clone();
25182530
opts.cg.metadata = vec![String::from("A"), String::from("B")];
25192531
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());

src/librustc_driver/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ mod rustc_trans {
177177
pub mod write {
178178
pub const RELOC_MODEL_ARGS: [(&'static str, ()); 0] = [];
179179
pub const CODE_GEN_MODEL_ARGS: [(&'static str, ()); 0] = [];
180+
pub const TLS_MODEL_ARGS: [(&'static str, ()); 0] = [];
180181
}
181182
}
182183
}
@@ -797,6 +798,13 @@ impl RustcDefaultCalls {
797798
}
798799
println!("");
799800
}
801+
PrintRequest::TlsModels => {
802+
println!("Available TLS models:");
803+
for &(name, _) in rustc_trans::back::write::TLS_MODEL_ARGS.iter(){
804+
println!(" {}", name);
805+
}
806+
println!("");
807+
}
800808
PrintRequest::TargetCPUs | PrintRequest::TargetFeatures => {
801809
rustc_trans::print(*req, sess);
802810
}

src/librustc_llvm/ffi.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,17 @@ pub struct ThinLTOModule {
359359
pub len: usize,
360360
}
361361

362+
/// LLVMThreadLocalMode
363+
#[derive(Copy, Clone)]
364+
#[repr(C)]
365+
pub enum ThreadLocalMode {
366+
NotThreadLocal,
367+
GeneralDynamic,
368+
LocalDynamic,
369+
InitialExec,
370+
LocalExec
371+
}
372+
362373
// Opaque pointer types
363374
#[allow(missing_copy_implementations)]
364375
pub enum Module_opaque {}
@@ -709,6 +720,7 @@ extern "C" {
709720
pub fn LLVMGetInitializer(GlobalVar: ValueRef) -> ValueRef;
710721
pub fn LLVMSetInitializer(GlobalVar: ValueRef, ConstantVal: ValueRef);
711722
pub fn LLVMSetThreadLocal(GlobalVar: ValueRef, IsThreadLocal: Bool);
723+
pub fn LLVMSetThreadLocalMode(GlobalVar: ValueRef, Mode: ThreadLocalMode);
712724
pub fn LLVMIsGlobalConstant(GlobalVar: ValueRef) -> Bool;
713725
pub fn LLVMSetGlobalConstant(GlobalVar: ValueRef, IsConstant: Bool);
714726
pub fn LLVMRustGetNamedValue(M: ModuleRef, Name: *const c_char) -> ValueRef;

src/librustc_llvm/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,11 @@ pub fn set_thread_local(global: ValueRef, is_thread_local: bool) {
172172
LLVMSetThreadLocal(global, is_thread_local as Bool);
173173
}
174174
}
175+
pub fn set_thread_local_mode(global: ValueRef, mode: ThreadLocalMode) {
176+
unsafe {
177+
LLVMSetThreadLocalMode(global, mode);
178+
}
179+
}
175180

176181
impl Attribute {
177182
pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {

src/librustc_trans/back/write.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ pub const CODE_GEN_MODEL_ARGS : [(&'static str, llvm::CodeModel); 5] = [
7676
("large", llvm::CodeModel::Large),
7777
];
7878

79+
pub const TLS_MODEL_ARGS : [(&'static str, llvm::ThreadLocalMode); 4] = [
80+
("global-dynamic", llvm::ThreadLocalMode::GeneralDynamic),
81+
("local-dynamic", llvm::ThreadLocalMode::LocalDynamic),
82+
("initial-exec", llvm::ThreadLocalMode::InitialExec),
83+
("local-exec", llvm::ThreadLocalMode::LocalExec),
84+
];
85+
7986
pub fn llvm_err(handler: &errors::Handler, msg: String) -> FatalError {
8087
match llvm::last_error() {
8188
Some(err) => handler.fatal(&format!("{}: {}", msg, err)),

src/librustc_trans/consts.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use monomorphize::Instance;
2323
use type_::Type;
2424
use type_of;
2525
use rustc::ty;
26+
use context::get_tls_model;
2627

2728
use rustc::hir;
2829

@@ -196,7 +197,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
196197

197198
for attr in attrs {
198199
if attr.check_name("thread_local") {
199-
llvm::set_thread_local(g, true);
200+
llvm::set_thread_local_mode(g, get_tls_model(ccx.sess()));
200201
}
201202
}
202203

@@ -215,7 +216,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
215216
// symbol and another one doesn't.
216217
for attr in ccx.tcx().get_attrs(def_id).iter() {
217218
if attr.check_name("thread_local") {
218-
llvm::set_thread_local(g, true);
219+
llvm::set_thread_local_mode(g, get_tls_model(ccx.sess()));
219220
}
220221
}
221222
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>,
305306

306307
debuginfo::create_global_var_metadata(ccx, id, g);
307308

308-
if attr::contains_name(attrs,
309-
"thread_local") {
310-
llvm::set_thread_local(g, true);
309+
if attr::contains_name(attrs, "thread_local") {
310+
llvm::set_thread_local_mode(g, get_tls_model(ccx.sess()));
311311
}
312312

313313
base::set_link_section(ccx, g, attrs);

src/librustc_trans/context.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,24 @@ pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
166166
}
167167
}
168168

169+
pub fn get_tls_model(sess: &Session) -> llvm::ThreadLocalMode {
170+
let tls_model_arg = match sess.opts.cg.tls_model {
171+
Some(ref s) => &s[..],
172+
None => &sess.target.target.options.tls_model[..],
173+
};
174+
175+
match ::back::write::TLS_MODEL_ARGS.iter().find(
176+
|&&arg| arg.0 == tls_model_arg) {
177+
Some(x) => x.1,
178+
_ => {
179+
sess.err(&format!("{:?} is not a valid TLS model",
180+
tls_model_arg));
181+
sess.abort_if_errors();
182+
bug!();
183+
}
184+
}
185+
}
186+
169187
fn is_any_library(sess: &Session) -> bool {
170188
sess.crate_types.borrow().iter().any(|ty| {
171189
*ty != config::CrateTypeExecutable

0 commit comments

Comments
 (0)