Skip to content
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

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

Merged
merged 10 commits into from
Aug 11, 2016
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[submodule "src/llvm"]
path = src/llvm
url = https://github.com/rust-lang/llvm.git
url = https://github.com/bitshifter/llvm.git
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs to be updated once llvm PR is accepted.

branch = master
[submodule "src/compiler-rt"]
path = src/compiler-rt
Expand Down
30 changes: 28 additions & 2 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@ pub enum PrintRequest {
CrateName,
Cfg,
TargetList,
TargetCPUs,
TargetFeatures,
RelocationModels,
CodeModels,
}

pub enum Input {
Expand Down Expand Up @@ -1195,6 +1199,24 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
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;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Push as print request and reset target-cpu vaule so LLVM doesn't print help several times when creating a target machine, we want to print ourselves from rustc.

};
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 sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m));
Expand Down Expand Up @@ -1272,18 +1294,22 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
let cfg = parse_cfgspecs(matches.opt_strs("cfg"));
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 {
"crate-name" => PrintRequest::CrateName,
"file-names" => PrintRequest::FileNames,
"sysroot" => PrintRequest::Sysroot,
"cfg" => PrintRequest::Cfg,
"target-list" => PrintRequest::TargetList,
"target-cpus" => PrintRequest::TargetCPUs,
"target-features" => PrintRequest::TargetFeatures,
"relocation-models" => PrintRequest::RelocationModels,
"code-models" => PrintRequest::CodeModels,
req => {
early_error(error_format, &format!("unknown print request `{}`", req))
}
}
}).collect::<Vec<_>>();
}));

if !cg.remark.is_empty() && debuginfo == NoDebugInfo {
early_warn(error_format, "-C remark will not show source locations without \
Expand Down
24 changes: 24 additions & 0 deletions src/librustc_driver/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ use pretty::{PpMode, UserIdentifiedItem};
use rustc_resolve as resolve;
use rustc_save_analysis as save;
use rustc_trans::back::link;
use rustc_trans::back::write::create_target_machine;
use rustc::dep_graph::DepGraph;
use rustc::session::{self, config, Session, build_session, CompileResult};
use rustc::session::config::{Input, PrintRequest, OutputType, ErrorOutputType};
Expand Down Expand Up @@ -657,6 +658,29 @@ 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:\n");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be good to make a list of available strings and their enum mappings instead of duplicating them, but not sure where to put it. This information is currently processed in librustc_trans/back/write.rs create_target_machine function.

println!(" pic");
println!(" static");
println!(" default");
println!(" dynamic-no-pic\n");
}
PrintRequest::CodeModels => {
println!("Available code models:\n");
println!(" default");
println!(" small");
println!(" kernel");
println!(" medium");
println!(" large\n");
}
}
}
return Compilation::Stop;
Expand Down
3 changes: 3 additions & 0 deletions src/librustc_llvm/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2040,6 +2040,9 @@ extern {
pub fn LLVMRustHasFeature(T: TargetMachineRef,
s: *const c_char) -> bool;

pub fn LLVMRustPrintTargetCPUs(T: TargetMachineRef);
pub fn LLVMRustPrintTargetFeatures(T: TargetMachineRef);

pub fn LLVMRustCreateTargetMachine(Triple: *const c_char,
CPU: *const c_char,
Features: *const c_char,
Expand Down
2 changes: 1 addition & 1 deletion src/llvm
38 changes: 38 additions & 0 deletions src/rustllvm/PassWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,44 @@ LLVMRustHasFeature(LLVMTargetMachineRef TM,
return (Bits & FeatureEntry->Value) == FeatureEntry->Value;
}

/// 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\n");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seemed easier to print in C++ to avoid exposing ArrayRef to Rust.

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\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");
}

extern "C" LLVMTargetMachineRef
LLVMRustCreateTargetMachine(const char *triple,
const char *cpu,
Expand Down