TargetFeatures,
RelocationModels,
CodeModels,
+ TlsModels,
TargetSpec,
NativeStaticLibs,
}
"choose the relocation model to use (rustc --print relocation-models for details)"),
code_model: Option<String> = (None, parse_opt_string, [TRACKED],
"choose the code model to use (rustc --print code-models for details)"),
+ tls_model: Option<String> = (None, parse_opt_string, [TRACKED],
+ "choose the TLS model to use (rustc --print tls-models for details)"),
metadata: Vec<String> = (Vec::new(), parse_list, [TRACKED],
"metadata to mangle symbol names with"),
extra_filename: String = ("".to_string(), parse_string, [UNTRACKED],
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"),
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;
"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) {
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());
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] = [];
}
}
}
}
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);
}
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 {}
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;
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) {
("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)),
use type_::Type;
use type_of;
use rustc::ty;
+use context::get_tls_model;
use rustc::hir;
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()));
}
}
// 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) {
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);
}
}
+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