Auto merge of #34845 - bitshifter:issue-30961, r=alexcrichton

Add help for target CPUs, features, relocation and code models.

Fix for https://github.com/rust-lang/rust/issues/30961. Requires PR https://github.com/rust-lang/llvm/pull/45 to be accepted first, and the .gitmodules for llvm to be updated before this can be merged.
This commit is contained in:
bors 2016-08-10 21:42:48 -07:00 committed by GitHub
commit 1222f5d52b
12 changed files with 160 additions and 21 deletions

View File

@ -32,6 +32,11 @@ RUSTLLVM_INCS_$(1) = $$(LLVM_EXTRA_INCDIRS_$(1)) \
$$(call CFG_CC_INCLUDE_$(1),$$(S)src/rustllvm/include) $$(call CFG_CC_INCLUDE_$(1),$$(S)src/rustllvm/include)
RUSTLLVM_OBJS_OBJS_$(1) := $$(RUSTLLVM_OBJS_CS_$(1):rustllvm/%.cpp=$(1)/rustllvm/%.o) RUSTLLVM_OBJS_OBJS_$(1) := $$(RUSTLLVM_OBJS_CS_$(1):rustllvm/%.cpp=$(1)/rustllvm/%.o)
# Flag that we are building with Rust's llvm fork
ifeq ($(CFG_LLVM_ROOT),)
RUSTLLVM_CXXFLAGS_$(1) := -DLLVM_RUSTLLVM
endif
# Note that we appease `cl.exe` and its need for some sort of exception # Note that we appease `cl.exe` and its need for some sort of exception
# handling flag with the `EHsc` argument here as well. # handling flag with the `EHsc` argument here as well.
ifeq ($$(findstring msvc,$(1)),msvc) ifeq ($$(findstring msvc,$(1)),msvc)
@ -55,6 +60,7 @@ $(1)/rustllvm/%.o: $(S)src/rustllvm/%.cpp $$(MKFILE_DEPS) $$(LLVM_CONFIG_$(1))
$$(Q)$$(call CFG_COMPILE_CXX_$(1), $$@,) \ $$(Q)$$(call CFG_COMPILE_CXX_$(1), $$@,) \
$$(subst /,//,$$(LLVM_CXXFLAGS_$(1))) \ $$(subst /,//,$$(LLVM_CXXFLAGS_$(1))) \
$$(RUSTLLVM_COMPONENTS_$(1)) \ $$(RUSTLLVM_COMPONENTS_$(1)) \
$$(RUSTLLVM_CXXFLAGS_$(1)) \
$$(EXTRA_RUSTLLVM_CXXFLAGS_$(1)) \ $$(EXTRA_RUSTLLVM_CXXFLAGS_$(1)) \
$$(RUSTLLVM_INCS_$(1)) \ $$(RUSTLLVM_INCS_$(1)) \
$$< $$<

View File

@ -198,6 +198,10 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
if !build.unstable_features { if !build.unstable_features {
cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1"); cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
} }
// Flag that rust llvm is in use
if build.is_rust_llvm(target) {
cargo.env("LLVM_RUSTLLVM", "1");
}
cargo.env("LLVM_CONFIG", build.llvm_config(target)); cargo.env("LLVM_CONFIG", build.llvm_config(target));
if build.config.llvm_static_stdcpp { if build.config.llvm_static_stdcpp {
cargo.env("LLVM_STATIC_STDCPP", cargo.env("LLVM_STATIC_STDCPP",

View File

@ -727,6 +727,16 @@ impl Build {
self.out.join(target).join("llvm") self.out.join(target).join("llvm")
} }
/// Returns true if no custom `llvm-config` is set for the specified target.
///
/// If no custom `llvm-config` was specified then Rust's llvm will be used.
fn is_rust_llvm(&self, target: &str) -> bool {
match self.config.target_config.get(target) {
Some(ref c) => c.llvm_config.is_none(),
None => true
}
}
/// Returns the path to `llvm-config` for the specified target. /// Returns the path to `llvm-config` for the specified target.
/// ///
/// If a custom `llvm-config` was specified for target then that's returned /// If a custom `llvm-config` was specified for target then that's returned

View File

@ -176,6 +176,10 @@ pub enum PrintRequest {
CrateName, CrateName,
Cfg, Cfg,
TargetList, TargetList,
TargetCPUs,
TargetFeatures,
RelocationModels,
CodeModels,
} }
pub enum Input { pub enum Input {
@ -629,9 +633,9 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
lto: bool = (false, parse_bool, lto: bool = (false, parse_bool,
"perform LLVM link-time optimizations"), "perform LLVM link-time optimizations"),
target_cpu: Option<String> = (None, parse_opt_string, target_cpu: Option<String> = (None, parse_opt_string,
"select target processor (llc -mcpu=help for details)"), "select target processor (rustc --print target-cpus for details)"),
target_feature: String = ("".to_string(), parse_string, target_feature: String = ("".to_string(), parse_string,
"target specific attributes (llc -mattr=help for details)"), "target specific attributes (rustc --print target-features for details)"),
passes: Vec<String> = (Vec::new(), parse_list, passes: Vec<String> = (Vec::new(), parse_list,
"a list of extra LLVM passes to run (space separated)"), "a list of extra LLVM passes to run (space separated)"),
llvm_args: Vec<String> = (Vec::new(), parse_list, llvm_args: Vec<String> = (Vec::new(), parse_list,
@ -655,9 +659,9 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
no_redzone: Option<bool> = (None, parse_opt_bool, no_redzone: Option<bool> = (None, parse_opt_bool,
"disable the use of the redzone"), "disable the use of the redzone"),
relocation_model: Option<String> = (None, parse_opt_string, relocation_model: Option<String> = (None, parse_opt_string,
"choose the relocation model to use (llc -relocation-model for details)"), "choose the relocation model to use (rustc --print relocation-models for details)"),
code_model: Option<String> = (None, parse_opt_string, code_model: Option<String> = (None, parse_opt_string,
"choose the code model to use (llc -code-model for details)"), "choose the code model to use (rustc --print code-models for details)"),
metadata: Vec<String> = (Vec::new(), parse_list, metadata: Vec<String> = (Vec::new(), parse_list,
"metadata to mangle symbol names with"), "metadata to mangle symbol names with"),
extra_filename: String = ("".to_string(), parse_string, extra_filename: String = ("".to_string(), parse_string,
@ -1024,7 +1028,8 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
"[asm|llvm-bc|llvm-ir|obj|link|dep-info]"), "[asm|llvm-bc|llvm-ir|obj|link|dep-info]"),
opt::multi_s("", "print", "Comma separated list of compiler information to \ opt::multi_s("", "print", "Comma separated list of compiler information to \
print on stdout", print on stdout",
"[crate-name|file-names|sysroot|cfg|target-list]"), "[crate-name|file-names|sysroot|cfg|target-list|target-cpus|\
target-features|relocation-models|code-models]"),
opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"), opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"),
opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"), opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"),
opt::opt_s("o", "", "Write output to <filename>", "FILENAME"), opt::opt_s("o", "", "Write output to <filename>", "FILENAME"),
@ -1238,6 +1243,24 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
early_error(error_format, "Value for codegen units must be a positive nonzero integer"); early_error(error_format, "Value for codegen units must be a positive nonzero integer");
} }
let mut prints = Vec::<PrintRequest>::new();
if cg.target_cpu.as_ref().map_or(false, |s| s == "help") {
prints.push(PrintRequest::TargetCPUs);
cg.target_cpu = None;
};
if cg.target_feature == "help" {
prints.push(PrintRequest::TargetFeatures);
cg.target_feature = "".to_string();
}
if cg.relocation_model.as_ref().map_or(false, |s| s == "help") {
prints.push(PrintRequest::RelocationModels);
cg.relocation_model = None;
}
if cg.code_model.as_ref().map_or(false, |s| s == "help") {
prints.push(PrintRequest::CodeModels);
cg.code_model = None;
}
let cg = cg; let cg = cg;
let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m)); let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m));
@ -1315,18 +1338,22 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
let cfg = parse_cfgspecs(matches.opt_strs("cfg")); let cfg = parse_cfgspecs(matches.opt_strs("cfg"));
let test = matches.opt_present("test"); let test = matches.opt_present("test");
let prints = matches.opt_strs("print").into_iter().map(|s| { prints.extend(matches.opt_strs("print").into_iter().map(|s| {
match &*s { match &*s {
"crate-name" => PrintRequest::CrateName, "crate-name" => PrintRequest::CrateName,
"file-names" => PrintRequest::FileNames, "file-names" => PrintRequest::FileNames,
"sysroot" => PrintRequest::Sysroot, "sysroot" => PrintRequest::Sysroot,
"cfg" => PrintRequest::Cfg, "cfg" => PrintRequest::Cfg,
"target-list" => PrintRequest::TargetList, "target-list" => PrintRequest::TargetList,
"target-cpus" => PrintRequest::TargetCPUs,
"target-features" => PrintRequest::TargetFeatures,
"relocation-models" => PrintRequest::RelocationModels,
"code-models" => PrintRequest::CodeModels,
req => { req => {
early_error(error_format, &format!("unknown print request `{}`", req)) early_error(error_format, &format!("unknown print request `{}`", req))
} }
} }
}).collect::<Vec<_>>(); }));
if !cg.remark.is_empty() && debuginfo == NoDebugInfo { if !cg.remark.is_empty() && debuginfo == NoDebugInfo {
early_warn(error_format, "-C remark will not show source locations without \ early_warn(error_format, "-C remark will not show source locations without \

View File

@ -68,6 +68,7 @@ use pretty::{PpMode, UserIdentifiedItem};
use rustc_resolve as resolve; use rustc_resolve as resolve;
use rustc_save_analysis as save; use rustc_save_analysis as save;
use rustc_trans::back::link; use rustc_trans::back::link;
use rustc_trans::back::write::{create_target_machine, RELOC_MODEL_ARGS, CODE_GEN_MODEL_ARGS};
use rustc::dep_graph::DepGraph; use rustc::dep_graph::DepGraph;
use rustc::session::{self, config, Session, build_session, CompileResult}; use rustc::session::{self, config, Session, build_session, CompileResult};
use rustc::session::config::{Input, PrintRequest, OutputType, ErrorOutputType}; use rustc::session::config::{Input, PrintRequest, OutputType, ErrorOutputType};
@ -654,6 +655,28 @@ impl RustcDefaultCalls {
} }
} }
} }
PrintRequest::TargetCPUs => {
let tm = create_target_machine(sess);
unsafe { llvm::LLVMRustPrintTargetCPUs(tm); }
}
PrintRequest::TargetFeatures => {
let tm = create_target_machine(sess);
unsafe { llvm::LLVMRustPrintTargetFeatures(tm); }
}
PrintRequest::RelocationModels => {
println!("Available relocation models:");
for &(name, _) in RELOC_MODEL_ARGS.iter() {
println!(" {}", name);
}
println!("");
}
PrintRequest::CodeModels => {
println!("Available code models:");
for &(name, _) in CODE_GEN_MODEL_ARGS.iter(){
println!(" {}", name);
}
println!("");
}
} }
} }
return Compilation::Stop; return Compilation::Stop;

View File

@ -112,6 +112,10 @@ fn main() {
cfg.flag(&flag); cfg.flag(&flag);
} }
if env::var_os("LLVM_RUSTLLVM").is_some() {
cfg.flag("-DLLVM_RUSTLLVM");
}
cfg.file("../rustllvm/PassWrapper.cpp") cfg.file("../rustllvm/PassWrapper.cpp")
.file("../rustllvm/RustWrapper.cpp") .file("../rustllvm/RustWrapper.cpp")
.file("../rustllvm/ArchiveWrapper.cpp") .file("../rustllvm/ArchiveWrapper.cpp")

View File

@ -1940,6 +1940,9 @@ extern {
pub fn LLVMRustHasFeature(T: TargetMachineRef, pub fn LLVMRustHasFeature(T: TargetMachineRef,
s: *const c_char) -> bool; s: *const c_char) -> bool;
pub fn LLVMRustPrintTargetCPUs(T: TargetMachineRef);
pub fn LLVMRustPrintTargetFeatures(T: TargetMachineRef);
pub fn LLVMRustCreateTargetMachine(Triple: *const c_char, pub fn LLVMRustCreateTargetMachine(Triple: *const c_char,
CPU: *const c_char, CPU: *const c_char,
Features: *const c_char, Features: *const c_char,

View File

@ -36,6 +36,21 @@ use std::sync::mpsc::channel;
use std::thread; use std::thread;
use libc::{c_uint, c_void}; use libc::{c_uint, c_void};
pub const RELOC_MODEL_ARGS : [(&'static str, llvm::RelocMode); 4] = [
("pic", llvm::RelocMode::PIC),
("static", llvm::RelocMode::Static),
("default", llvm::RelocMode::Default),
("dynamic-no-pic", llvm::RelocMode::DynamicNoPic),
];
pub const CODE_GEN_MODEL_ARGS : [(&'static str, llvm::CodeModel); 5] = [
("default", llvm::CodeModel::Default),
("small", llvm::CodeModel::Small),
("kernel", llvm::CodeModel::Kernel),
("medium", llvm::CodeModel::Medium),
("large", llvm::CodeModel::Large),
];
pub fn llvm_err(handler: &errors::Handler, msg: String) -> ! { pub fn llvm_err(handler: &errors::Handler, msg: String) -> ! {
match llvm::last_error() { match llvm::last_error() {
Some(err) => panic!(handler.fatal(&format!("{}: {}", msg, err))), Some(err) => panic!(handler.fatal(&format!("{}: {}", msg, err))),
@ -168,12 +183,9 @@ pub fn create_target_machine(sess: &Session) -> TargetMachineRef {
None => &sess.target.target.options.code_model[..], None => &sess.target.target.options.code_model[..],
}; };
let code_model = match code_model_arg { let code_model = match CODE_GEN_MODEL_ARGS.iter().find(
"default" => llvm::CodeModel::Default, |&&arg| arg.0 == code_model_arg) {
"small" => llvm::CodeModel::Small, Some(x) => x.1,
"kernel" => llvm::CodeModel::Kernel,
"medium" => llvm::CodeModel::Medium,
"large" => llvm::CodeModel::Large,
_ => { _ => {
sess.err(&format!("{:?} is not a valid code model", sess.err(&format!("{:?} is not a valid code model",
sess.opts sess.opts

View File

@ -337,16 +337,14 @@ pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
None => &sess.target.target.options.relocation_model[..], None => &sess.target.target.options.relocation_model[..],
}; };
match reloc_model_arg { match ::back::write::RELOC_MODEL_ARGS.iter().find(
"pic" => llvm::RelocMode::PIC, |&&arg| arg.0 == reloc_model_arg) {
"static" => llvm::RelocMode::Static, Some(x) => x.1,
"default" => llvm::RelocMode::Default,
"dynamic-no-pic" => llvm::RelocMode::DynamicNoPic,
_ => { _ => {
sess.err(&format!("{:?} is not a valid relocation mode", sess.err(&format!("{:?} is not a valid relocation mode",
sess.opts sess.opts
.cg .cg
.relocation_model)); .code_model));
sess.abort_if_errors(); sess.abort_if_errors();
bug!(); bug!();
} }

@ -1 +1 @@
Subproject commit d1cc48989b13780f21c408fef17dceb104a09c9d Subproject commit 786aad117be48547f4ca50fae84c4879fa992d4d

View File

@ -226,6 +226,58 @@ from_rust(LLVMRustCodeGenOptLevel level)
} }
} }
#if LLVM_RUSTLLVM
/// getLongestEntryLength - Return the length of the longest entry in the table.
///
static size_t getLongestEntryLength(ArrayRef<SubtargetFeatureKV> Table) {
size_t MaxLen = 0;
for (auto &I : Table)
MaxLen = std::max(MaxLen, std::strlen(I.Key));
return MaxLen;
}
extern "C" void
LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM) {
const TargetMachine *Target = unwrap(TM);
const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
const ArrayRef<SubtargetFeatureKV> CPUTable = MCInfo->getCPUTable();
unsigned MaxCPULen = getLongestEntryLength(CPUTable);
printf("Available CPUs for this target:\n");
for (auto &CPU : CPUTable)
printf(" %-*s - %s.\n", MaxCPULen, CPU.Key, CPU.Desc);
printf("\n");
}
extern "C" void
LLVMRustPrintTargetFeatures(LLVMTargetMachineRef TM) {
const TargetMachine *Target = unwrap(TM);
const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable();
unsigned MaxFeatLen = getLongestEntryLength(FeatTable);
printf("Available features for this target:\n");
for (auto &Feature : FeatTable)
printf(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc);
printf("\n");
printf("Use +feature to enable a feature, or -feature to disable it.\n"
"For example, rustc -C -target-cpu=mycpu -C target-feature=+feature1,-feature2\n\n");
}
#else
extern "C" void
LLVMRustPrintTargetCPUs(LLVMTargetMachineRef) {
printf("Target CPU help is not supported by this LLVM version.\n\n");
}
extern "C" void
LLVMRustPrintTargetFeatures(LLVMTargetMachineRef) {
printf("Target features help is not supported by this LLVM version.\n\n");
}
#endif
extern "C" LLVMTargetMachineRef extern "C" LLVMTargetMachineRef
LLVMRustCreateTargetMachine(const char *triple, LLVMRustCreateTargetMachine(const char *triple,
const char *cpu, const char *cpu,

View File

@ -1,4 +1,4 @@
# If this file is modified, then llvm will be forcibly cleaned and then rebuilt. # If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
# The actual contents of this file do not matter, but to trigger a change on the # The actual contents of this file do not matter, but to trigger a change on the
# build bots then the contents should be changed so git updates the mtime. # build bots then the contents should be changed so git updates the mtime.
2016-07-25b 2016-08-07