Add support for specifying the TLS model

This commit is contained in:
Amanieu d'Antras 2017-10-31 18:24:04 +00:00
parent 37b015fb91
commit b233a6e096
7 changed files with 68 additions and 6 deletions

View File

@ -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<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],
@ -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"),
@ -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());

View File

@ -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);
}

View File

@ -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;

View File

@ -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) {

View File

@ -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)),

View File

@ -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);

View File

@ -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