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
6 changes: 6 additions & 0 deletions mk/rustllvm.mk
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ RUSTLLVM_INCS_$(1) = $$(LLVM_EXTRA_INCDIRS_$(1)) \
$$(call CFG_CC_INCLUDE_$(1),$$(S)src/rustllvm/include)
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
# handling flag with the `EHsc` argument here as well.
ifeq ($$(findstring msvc,$(1)),msvc)
Expand All @@ -55,6 +60,7 @@ $(1)/rustllvm/%.o: $(S)src/rustllvm/%.cpp $$(MKFILE_DEPS) $$(LLVM_CONFIG_$(1))
$$(Q)$$(call CFG_COMPILE_CXX_$(1), $$@,) \
$$(subst /,//,$$(LLVM_CXXFLAGS_$(1))) \
$$(RUSTLLVM_COMPONENTS_$(1)) \
$$(RUSTLLVM_CXXFLAGS_$(1)) \
$$(EXTRA_RUSTLLVM_CXXFLAGS_$(1)) \
$$(RUSTLLVM_INCS_$(1)) \
$$<
Expand Down
4 changes: 4 additions & 0 deletions src/bootstrap/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,10 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
if !build.unstable_features {
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));
if build.config.llvm_static_stdcpp {
cargo.env("LLVM_STATIC_STDCPP",
Expand Down
10 changes: 10 additions & 0 deletions src/bootstrap/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,16 @@ impl Build {
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.
///
/// If a custom `llvm-config` was specified for target then that's returned
Expand Down
41 changes: 34 additions & 7 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@ pub enum PrintRequest {
CrateName,
Cfg,
TargetList,
TargetCPUs,
TargetFeatures,
RelocationModels,
CodeModels,
}

pub enum Input {
Expand Down Expand Up @@ -629,9 +633,9 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
lto: bool = (false, parse_bool,
"perform LLVM link-time optimizations"),
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 specific attributes (llc -mattr=help for details)"),
"target specific attributes (rustc --print target-features for details)"),
passes: Vec<String> = (Vec::new(), parse_list,
"a list of extra LLVM passes to run (space separated)"),
llvm_args: Vec<String> = (Vec::new(), parse_list,
Expand All @@ -655,9 +659,9 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
no_redzone: Option<bool> = (None, parse_opt_bool,
"disable the use of the redzone"),
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,
"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 to mangle symbol names with"),
extra_filename: String = ("".to_string(), parse_string,
Expand Down Expand Up @@ -1022,7 +1026,8 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
"[asm|llvm-bc|llvm-ir|obj|link|dep-info]"),
opt::multi_s("", "print", "Comma separated list of compiler information to \
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("O", "", "Equivalent to -C opt-level=2"),
opt::opt_s("o", "", "Write output to <filename>", "FILENAME"),
Expand Down Expand Up @@ -1236,6 +1241,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 @@ -1313,18 +1336,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
23 changes: 23 additions & 0 deletions src/librustc_driver/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,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, RELOC_MODEL_ARGS, CODE_GEN_MODEL_ARGS};
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 @@ -660,6 +661,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;
Expand Down
4 changes: 4 additions & 0 deletions src/librustc_llvm/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ fn main() {
cfg.flag(&flag);
}

if env::var_os("LLVM_RUSTLLVM").is_some() {
cfg.flag("-DLLVM_RUSTLLVM");
}

cfg.file("../rustllvm/PassWrapper.cpp")
.file("../rustllvm/RustWrapper.cpp")
.file("../rustllvm/ArchiveWrapper.cpp")
Expand Down
3 changes: 3 additions & 0 deletions src/librustc_llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1940,6 +1940,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
24 changes: 18 additions & 6 deletions src/librustc_trans/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,21 @@ use std::sync::mpsc::channel;
use std::thread;
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) -> ! {
match llvm::last_error() {
Some(err) => panic!(handler.fatal(&format!("{}: {}", msg, err))),
Expand Down Expand Up @@ -168,12 +183,9 @@ pub fn create_target_machine(sess: &Session) -> TargetMachineRef {
None => &sess.target.target.options.code_model[..],
};

let code_model = match code_model_arg {
"default" => llvm::CodeModel::Default,
"small" => llvm::CodeModel::Small,
"kernel" => llvm::CodeModel::Kernel,
"medium" => llvm::CodeModel::Medium,
"large" => llvm::CodeModel::Large,
let code_model = match CODE_GEN_MODEL_ARGS.iter().find(
|&&arg| arg.0 == code_model_arg) {
Some(x) => x.1,
_ => {
sess.err(&format!("{:?} is not a valid code model",
sess.opts
Expand Down
10 changes: 4 additions & 6 deletions src/librustc_trans/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,16 +324,14 @@ pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
None => &sess.target.target.options.relocation_model[..],
};

match reloc_model_arg {
"pic" => llvm::RelocMode::PIC,
"static" => llvm::RelocMode::Static,
"default" => llvm::RelocMode::Default,
"dynamic-no-pic" => llvm::RelocMode::DynamicNoPic,
match ::back::write::RELOC_MODEL_ARGS.iter().find(
|&&arg| arg.0 == reloc_model_arg) {
Some(x) => x.1,
_ => {
sess.err(&format!("{:?} is not a valid relocation mode",
sess.opts
.cg
.relocation_model));
.code_model));
sess.abort_if_errors();
bug!();
}
Expand Down
2 changes: 1 addition & 1 deletion src/llvm
52 changes: 52 additions & 0 deletions src/rustllvm/PassWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
LLVMRustCreateTargetMachine(const char *triple,
const char *cpu,
Expand Down
2 changes: 1 addition & 1 deletion src/rustllvm/llvm-auto-clean-trigger
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 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
# build bots then the contents should be changed so git updates the mtime.
2016-07-25b
2016-08-07