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

Cleanup and document -C code-model #72248

Merged
merged 2 commits into from
May 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions src/doc/rustc/src/codegen-options/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,25 @@ This option is deprecated and does nothing.

## code-model

This option lets you choose which code model to use.
This option lets you choose which code model to use. \
Code models put constraints on address ranges that the program and its symbols may use. \
With smaller address ranges machine instructions
may be able to use use more compact addressing modes.

To find the valid options for this flag, run `rustc --print code-models`.
The specific ranges depend on target architectures and addressing modes available to them. \
For x86 more detailed description of its code models can be found in
[System V Application Binary Interface](https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf)
specification.

Supported values for this option are:

<!-- - `tiny` - Tiny code model. -->
Copy link
Member

Choose a reason for hiding this comment

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

Is there a reason why we don't expose the tiny code model to users? AFAIK it's only available on AArch64 where it assumes all symbols are within 1MB of each other.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As I understand, it was simply introduced to LLVM later than the code-model option had been implemented in rustc.

I'll make a separate PR exposing it, I didn't want to do it in a "cleanup and document" PR.

- `small` - Small code model. This is the default model for majority of supported targets.
- `kernel` - Kernel code model.
- `medium` - Medium code model.
- `large` - Large code model.

Supported values can also be discovered by running `rustc --print code-models`.

## codegen-units

Expand Down
35 changes: 13 additions & 22 deletions src/librustc_codegen_llvm/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use rustc_middle::bug;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::{self, Lto, OutputType, Passes, Sanitizer, SwitchWithOptPath};
use rustc_session::Session;
use rustc_target::spec::RelocModel;
use rustc_target::spec::{CodeModel, RelocModel};

use libc::{c_char, c_int, c_uint, c_void, size_t};
use std::ffi::CString;
Expand All @@ -35,13 +35,6 @@ use std::slice;
use std::str;
use std::sync::Arc;

pub const CODE_GEN_MODEL_ARGS: &[(&str, llvm::CodeModel)] = &[
("small", llvm::CodeModel::Small),
("kernel", llvm::CodeModel::Kernel),
("medium", llvm::CodeModel::Medium),
("large", llvm::CodeModel::Large),
];

pub fn llvm_err(handler: &rustc_errors::Handler, msg: &str) -> FatalError {
match llvm::last_error() {
Some(err) => handler.fatal(&format!("{}: {}", msg, err)),
Expand Down Expand Up @@ -114,6 +107,17 @@ fn to_llvm_relocation_model(relocation_model: RelocModel) -> llvm::RelocModel {
}
}

fn to_llvm_code_model(code_model: Option<CodeModel>) -> llvm::CodeModel {
match code_model {
Some(CodeModel::Tiny) => llvm::CodeModel::Tiny,
Some(CodeModel::Small) => llvm::CodeModel::Small,
Some(CodeModel::Kernel) => llvm::CodeModel::Kernel,
Some(CodeModel::Medium) => llvm::CodeModel::Medium,
Some(CodeModel::Large) => llvm::CodeModel::Large,
None => llvm::CodeModel::None,
}
}

pub fn target_machine_factory(
sess: &Session,
optlvl: config::OptLevel,
Expand All @@ -126,20 +130,7 @@ pub fn target_machine_factory(
let ffunction_sections = sess.target.target.options.function_sections;
let fdata_sections = ffunction_sections;

let code_model_arg =
sess.opts.cg.code_model.as_ref().or(sess.target.target.options.code_model.as_ref());

let code_model = match code_model_arg {
Some(s) => match CODE_GEN_MODEL_ARGS.iter().find(|arg| arg.0 == s) {
Some(x) => x.1,
_ => {
sess.err(&format!("{:?} is not a valid code model", code_model_arg));
sess.abort_if_errors();
bug!();
}
},
None => llvm::CodeModel::None,
};
let code_model = to_llvm_code_model(sess.code_model());

let features = attributes::llvm_target_features(sess).collect::<Vec<_>>();
let mut singlethread = sess.target.target.options.singlethread;
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_codegen_llvm/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ impl CodegenBackend for LlvmCodegenBackend {
}
PrintRequest::CodeModels => {
println!("Available code models:");
for &(name, _) in back::write::CODE_GEN_MODEL_ARGS.iter() {
for name in &["small", "kernel", "medium", "large"] {
println!(" {}", name);
}
println!();
Expand Down
4 changes: 1 addition & 3 deletions src/librustc_codegen_llvm/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,9 +458,7 @@ pub enum RelocModel {
#[derive(Copy, Clone)]
#[repr(C)]
pub enum CodeModel {
// FIXME: figure out if this variant is needed at all.
#[allow(dead_code)]
Other,
Tiny,
Small,
Kernel,
Medium,
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_interface/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use rustc_session::{build_session, Session};
use rustc_span::edition::{Edition, DEFAULT_EDITION};
use rustc_span::symbol::sym;
use rustc_span::SourceFileHashAlgorithm;
use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy};
use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy};
use rustc_target::spec::{RelocModel, RelroLevel, TlsModel};
use std::collections::{BTreeMap, BTreeSet};
use std::iter::FromIterator;
Expand Down Expand Up @@ -411,7 +411,7 @@ fn test_codegen_options_tracking_hash() {

// Make sure that changing a [TRACKED] option changes the hash.
// This list is in alphabetical order.
tracked!(code_model, Some(String::from("code model")));
tracked!(code_model, Some(CodeModel::Large));
tracked!(debug_assertions, Some(true));
tracked!(debuginfo, 0xdeadbeef);
tracked!(embed_bitcode, false);
Expand Down
7 changes: 2 additions & 5 deletions src/librustc_session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1324,10 +1324,6 @@ fn collect_print_requests(
prints.push(PrintRequest::TargetFeatures);
cg.target_feature = String::new();
}
if cg.code_model.as_ref().map_or(false, |s| s == "help") {
prints.push(PrintRequest::CodeModels);
cg.code_model = None;
}

prints.extend(matches.opt_strs("print").into_iter().map(|s| match &*s {
"crate-name" => PrintRequest::CrateName,
Expand Down Expand Up @@ -2010,7 +2006,7 @@ crate mod dep_tracking {
use crate::utils::NativeLibraryKind;
use rustc_feature::UnstableFeatures;
use rustc_span::edition::Edition;
use rustc_target::spec::{MergeFunctions, PanicStrategy, RelocModel};
use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel};
use rustc_target::spec::{RelroLevel, TargetTriple, TlsModel};
use std::collections::hash_map::DefaultHasher;
use std::collections::BTreeMap;
Expand Down Expand Up @@ -2060,6 +2056,7 @@ crate mod dep_tracking {
impl_dep_tracking_hash_via_hash!(Option<Vec<String>>);
impl_dep_tracking_hash_via_hash!(Option<MergeFunctions>);
impl_dep_tracking_hash_via_hash!(Option<RelocModel>);
impl_dep_tracking_hash_via_hash!(Option<CodeModel>);
impl_dep_tracking_hash_via_hash!(Option<TlsModel>);
impl_dep_tracking_hash_via_hash!(Option<PanicStrategy>);
impl_dep_tracking_hash_via_hash!(Option<RelroLevel>);
Expand Down
17 changes: 13 additions & 4 deletions src/librustc_session/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ use crate::lint;
use crate::search_paths::SearchPath;
use crate::utils::NativeLibraryKind;

use rustc_target::spec::TargetTriple;
use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy};
use rustc_target::spec::{RelocModel, RelroLevel, TlsModel};
use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy};
use rustc_target::spec::{RelocModel, RelroLevel, TargetTriple, TlsModel};

use rustc_feature::UnstableFeatures;
use rustc_span::edition::Edition;
Expand Down Expand Up @@ -269,6 +268,8 @@ macro_rules! options {
pub const parse_src_file_hash: &str = "either `md5` or `sha1`";
pub const parse_relocation_model: &str =
"one of supported relocation models (`rustc --print relocation-models`)";
pub const parse_code_model: &str =
"one of supported code models (`rustc --print code-models`)";
pub const parse_tls_model: &str =
"one of supported TLS models (`rustc --print tls-models`)";
}
Expand Down Expand Up @@ -620,6 +621,14 @@ macro_rules! options {
true
}

fn parse_code_model(slot: &mut Option<CodeModel>, v: Option<&str>) -> bool {
match v.and_then(|s| CodeModel::from_str(s).ok()) {
Some(code_model) => *slot = Some(code_model),
_ => return false,
}
true
}

fn parse_tls_model(slot: &mut Option<TlsModel>, v: Option<&str>) -> bool {
match v.and_then(|s| TlsModel::from_str(s).ok()) {
Some(tls_model) => *slot = Some(tls_model),
Expand Down Expand Up @@ -662,7 +671,7 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,

ar: String = (String::new(), parse_string, [UNTRACKED],
"this option is deprecated and does nothing"),
code_model: Option<String> = (None, parse_opt_string, [TRACKED],
code_model: Option<CodeModel> = (None, parse_code_model, [TRACKED],
"choose the code model to use (`rustc --print code-models` for details)"),
codegen_units: Option<usize> = (None, parse_opt_uint, [UNTRACKED],
"divide crate into N units to optimize in parallel"),
Expand Down
7 changes: 6 additions & 1 deletion src/librustc_session/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId, ErrorReported
use rustc_span::edition::Edition;
use rustc_span::source_map::{self, FileLoader, MultiSpan, RealFileLoader, SourceMap, Span};
use rustc_span::{SourceFileHashAlgorithm, Symbol};
use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, Target, TargetTriple, TlsModel};
use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel};
use rustc_target::spec::{Target, TargetTriple, TlsModel};

use std::cell::{self, RefCell};
use std::env;
Expand Down Expand Up @@ -625,6 +626,10 @@ impl Session {
self.opts.cg.relocation_model.unwrap_or(self.target.target.options.relocation_model)
}

pub fn code_model(&self) -> Option<CodeModel> {
self.opts.cg.code_model.or(self.target.target.options.code_model)
}

pub fn tls_model(&self) -> TlsModel {
self.opts.debugging_opts.tls_model.unwrap_or(self.target.target.options.tls_model)
}
Expand Down
54 changes: 52 additions & 2 deletions src/librustc_target/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,43 @@ impl ToJson for RelocModel {
}
}

#[derive(Clone, Copy, PartialEq, Hash, Debug)]
pub enum CodeModel {
Tiny,
Small,
Kernel,
Medium,
Large,
}

impl FromStr for CodeModel {
type Err = ();

fn from_str(s: &str) -> Result<CodeModel, ()> {
Ok(match s {
// "tiny" => CodeModel::Tiny, // Not exposed to users right now.
"small" => CodeModel::Small,
"kernel" => CodeModel::Kernel,
"medium" => CodeModel::Medium,
"large" => CodeModel::Large,
_ => return Err(()),
})
}
}

impl ToJson for CodeModel {
fn to_json(&self) -> Json {
match *self {
CodeModel::Tiny => "tiny",
CodeModel::Small => "small",
CodeModel::Kernel => "kernel",
CodeModel::Medium => "medium",
CodeModel::Large => "large",
}
.to_json()
}
}

#[derive(Clone, Copy, PartialEq, Hash, Debug)]
pub enum TlsModel {
GeneralDynamic,
Expand Down Expand Up @@ -699,7 +736,8 @@ pub struct TargetOptions {
/// -relocation-model=$relocation_model`. Defaults to `Pic`.
pub relocation_model: RelocModel,
/// Code model to use. Corresponds to `llc -code-model=$code_model`.
pub code_model: Option<String>,
/// Defaults to `None` which means "inherited from the base LLVM target".
pub code_model: Option<CodeModel>,
/// TLS model to use. Options are "global-dynamic" (default), "local-dynamic", "initial-exec"
/// and "local-exec". This is similar to the -ftls-model option in GCC/Clang.
pub tls_model: TlsModel,
Expand Down Expand Up @@ -1114,6 +1152,18 @@ impl Target {
Some(Ok(()))
})).unwrap_or(Ok(()))
} );
($key_name:ident, CodeModel) => ( {
let name = (stringify!($key_name)).replace("_", "-");
obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
match s.parse::<CodeModel>() {
Ok(code_model) => base.options.$key_name = Some(code_model),
_ => return Some(Err(format!("'{}' is not a valid code model. \
Run `rustc --print code-models` to \
see the list of supported values.", s))),
}
Some(Ok(()))
})).unwrap_or(Ok(()))
} );
($key_name:ident, TlsModel) => ( {
let name = (stringify!($key_name)).replace("_", "-");
obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
Expand Down Expand Up @@ -1266,7 +1316,7 @@ impl Target {
key!(only_cdylib, bool);
key!(executables, bool);
key!(relocation_model, RelocModel)?;
key!(code_model, optional);
key!(code_model, CodeModel)?;
key!(tls_model, TlsModel)?;
key!(disable_redzone, bool);
key!(eliminate_frame_pointer, bool);
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_target/spec/riscv64gc_unknown_linux_gnu.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
use crate::spec::{CodeModel, LinkerFlavor, Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
Ok(Target {
Expand All @@ -14,7 +14,7 @@ pub fn target() -> TargetResult {
linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
abi_blacklist: super::riscv_base::abi_blacklist(),
code_model: Some("medium".to_string()),
code_model: Some(CodeModel::Medium),
cpu: "generic-rv64".to_string(),
features: "+m,+a,+f,+d,+c".to_string(),
llvm_abiname: "lp64d".to_string(),
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_target/spec/riscv64gc_unknown_none_elf.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
use crate::spec::{CodeModel, LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
use crate::spec::{Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
Expand All @@ -23,7 +23,7 @@ pub fn target() -> TargetResult {
executables: true,
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
code_model: Some("medium".to_string()),
code_model: Some(CodeModel::Medium),
emit_debug_gdb_scripts: false,
abi_blacklist: super::riscv_base::abi_blacklist(),
eliminate_frame_pointer: false,
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_target/spec/riscv64imac_unknown_none_elf.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::spec::{CodeModel, Target, TargetOptions, TargetResult};
use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
use crate::spec::{Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
Ok(Target {
Expand All @@ -23,7 +23,7 @@ pub fn target() -> TargetResult {
executables: true,
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
code_model: Some("medium".to_string()),
code_model: Some(CodeModel::Medium),
emit_debug_gdb_scripts: false,
abi_blacklist: super::riscv_base::abi_blacklist(),
eliminate_frame_pointer: false,
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_target/spec/x86_64_linux_kernel.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// This defines the amd64 target for the Linux Kernel. See the linux-kernel-base module for
// generic Linux kernel options.

use crate::spec::{LinkerFlavor, Target, TargetResult};
use crate::spec::{CodeModel, LinkerFlavor, Target, TargetResult};

pub fn target() -> TargetResult {
let mut base = super::linux_kernel_base::opts();
Expand All @@ -10,7 +10,7 @@ pub fn target() -> TargetResult {
base.features =
"-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float"
.to_string();
base.code_model = Some("kernel".to_string());
base.code_model = Some(CodeModel::Kernel);
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());

Ok(Target {
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_target/spec/x86_64_unknown_uefi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// The win64 ABI is used. It differs from the sysv64 ABI, so we must use a windows target with
// LLVM. "x86_64-unknown-windows" is used to get the minimal subset of windows-specific features.

use crate::spec::{LinkerFlavor, LldFlavor, Target, TargetResult};
use crate::spec::{CodeModel, LinkerFlavor, LldFlavor, Target, TargetResult};

pub fn target() -> TargetResult {
let mut base = super::uefi_msvc_base::opts();
Expand All @@ -26,7 +26,7 @@ pub fn target() -> TargetResult {
// UEFI systems run without a host OS, hence we cannot assume any code locality. We must tell
// LLVM to expect code to reference any address in the address-space. The "large" code-model
// places no locality-restrictions, so it fits well here.
base.code_model = Some("large".to_string());
base.code_model = Some(CodeModel::Large);

Ok(Target {
llvm_target: "x86_64-unknown-windows".to_string(),
Expand Down
Loading