Skip to content

Commit 5f47281

Browse files
committed
Auto merge of #72248 - petrochenkov:codemodel, r=Amanieu
Cleanup and document `-C code-model` r? @Amanieu
2 parents d79f1bd + 59187f9 commit 5f47281

File tree

15 files changed

+125
-57
lines changed

15 files changed

+125
-57
lines changed

src/doc/rustc/src/codegen-options/index.md

+18-2
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,25 @@ This option is deprecated and does nothing.
99

1010
## code-model
1111

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

14-
To find the valid options for this flag, run `rustc --print code-models`.
17+
The specific ranges depend on target architectures and addressing modes available to them. \
18+
For x86 more detailed description of its code models can be found in
19+
[System V Application Binary Interface](https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf)
20+
specification.
21+
22+
Supported values for this option are:
23+
24+
<!-- - `tiny` - Tiny code model. -->
25+
- `small` - Small code model. This is the default model for majority of supported targets.
26+
- `kernel` - Kernel code model.
27+
- `medium` - Medium code model.
28+
- `large` - Large code model.
29+
30+
Supported values can also be discovered by running `rustc --print code-models`.
1531

1632
## codegen-units
1733

src/librustc_codegen_llvm/back/write.rs

+13-22
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use rustc_middle::bug;
2424
use rustc_middle::ty::TyCtxt;
2525
use rustc_session::config::{self, Lto, OutputType, Passes, Sanitizer, SwitchWithOptPath};
2626
use rustc_session::Session;
27-
use rustc_target::spec::RelocModel;
27+
use rustc_target::spec::{CodeModel, RelocModel};
2828

2929
use libc::{c_char, c_int, c_uint, c_void, size_t};
3030
use std::ffi::CString;
@@ -35,13 +35,6 @@ use std::slice;
3535
use std::str;
3636
use std::sync::Arc;
3737

38-
pub const CODE_GEN_MODEL_ARGS: &[(&str, llvm::CodeModel)] = &[
39-
("small", llvm::CodeModel::Small),
40-
("kernel", llvm::CodeModel::Kernel),
41-
("medium", llvm::CodeModel::Medium),
42-
("large", llvm::CodeModel::Large),
43-
];
44-
4538
pub fn llvm_err(handler: &rustc_errors::Handler, msg: &str) -> FatalError {
4639
match llvm::last_error() {
4740
Some(err) => handler.fatal(&format!("{}: {}", msg, err)),
@@ -114,6 +107,17 @@ fn to_llvm_relocation_model(relocation_model: RelocModel) -> llvm::RelocModel {
114107
}
115108
}
116109

110+
fn to_llvm_code_model(code_model: Option<CodeModel>) -> llvm::CodeModel {
111+
match code_model {
112+
Some(CodeModel::Tiny) => llvm::CodeModel::Tiny,
113+
Some(CodeModel::Small) => llvm::CodeModel::Small,
114+
Some(CodeModel::Kernel) => llvm::CodeModel::Kernel,
115+
Some(CodeModel::Medium) => llvm::CodeModel::Medium,
116+
Some(CodeModel::Large) => llvm::CodeModel::Large,
117+
None => llvm::CodeModel::None,
118+
}
119+
}
120+
117121
pub fn target_machine_factory(
118122
sess: &Session,
119123
optlvl: config::OptLevel,
@@ -126,20 +130,7 @@ pub fn target_machine_factory(
126130
let ffunction_sections = sess.target.target.options.function_sections;
127131
let fdata_sections = ffunction_sections;
128132

129-
let code_model_arg =
130-
sess.opts.cg.code_model.as_ref().or(sess.target.target.options.code_model.as_ref());
131-
132-
let code_model = match code_model_arg {
133-
Some(s) => match CODE_GEN_MODEL_ARGS.iter().find(|arg| arg.0 == s) {
134-
Some(x) => x.1,
135-
_ => {
136-
sess.err(&format!("{:?} is not a valid code model", code_model_arg));
137-
sess.abort_if_errors();
138-
bug!();
139-
}
140-
},
141-
None => llvm::CodeModel::None,
142-
};
133+
let code_model = to_llvm_code_model(sess.code_model());
143134

144135
let features = attributes::llvm_target_features(sess).collect::<Vec<_>>();
145136
let mut singlethread = sess.target.target.options.singlethread;

src/librustc_codegen_llvm/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ impl CodegenBackend for LlvmCodegenBackend {
208208
}
209209
PrintRequest::CodeModels => {
210210
println!("Available code models:");
211-
for &(name, _) in back::write::CODE_GEN_MODEL_ARGS.iter() {
211+
for name in &["small", "kernel", "medium", "large"] {
212212
println!(" {}", name);
213213
}
214214
println!();

src/librustc_codegen_llvm/llvm/ffi.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -458,9 +458,7 @@ pub enum RelocModel {
458458
#[derive(Copy, Clone)]
459459
#[repr(C)]
460460
pub enum CodeModel {
461-
// FIXME: figure out if this variant is needed at all.
462-
#[allow(dead_code)]
463-
Other,
461+
Tiny,
464462
Small,
465463
Kernel,
466464
Medium,

src/librustc_interface/tests.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_session::{build_session, Session};
1515
use rustc_span::edition::{Edition, DEFAULT_EDITION};
1616
use rustc_span::symbol::sym;
1717
use rustc_span::SourceFileHashAlgorithm;
18-
use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy};
18+
use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy};
1919
use rustc_target::spec::{RelocModel, RelroLevel, TlsModel};
2020
use std::collections::{BTreeMap, BTreeSet};
2121
use std::iter::FromIterator;
@@ -411,7 +411,7 @@ fn test_codegen_options_tracking_hash() {
411411

412412
// Make sure that changing a [TRACKED] option changes the hash.
413413
// This list is in alphabetical order.
414-
tracked!(code_model, Some(String::from("code model")));
414+
tracked!(code_model, Some(CodeModel::Large));
415415
tracked!(debug_assertions, Some(true));
416416
tracked!(debuginfo, 0xdeadbeef);
417417
tracked!(embed_bitcode, false);

src/librustc_session/config.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -1324,10 +1324,6 @@ fn collect_print_requests(
13241324
prints.push(PrintRequest::TargetFeatures);
13251325
cg.target_feature = String::new();
13261326
}
1327-
if cg.code_model.as_ref().map_or(false, |s| s == "help") {
1328-
prints.push(PrintRequest::CodeModels);
1329-
cg.code_model = None;
1330-
}
13311327

13321328
prints.extend(matches.opt_strs("print").into_iter().map(|s| match &*s {
13331329
"crate-name" => PrintRequest::CrateName,
@@ -2010,7 +2006,7 @@ crate mod dep_tracking {
20102006
use crate::utils::NativeLibraryKind;
20112007
use rustc_feature::UnstableFeatures;
20122008
use rustc_span::edition::Edition;
2013-
use rustc_target::spec::{MergeFunctions, PanicStrategy, RelocModel};
2009+
use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel};
20142010
use rustc_target::spec::{RelroLevel, TargetTriple, TlsModel};
20152011
use std::collections::hash_map::DefaultHasher;
20162012
use std::collections::BTreeMap;
@@ -2060,6 +2056,7 @@ crate mod dep_tracking {
20602056
impl_dep_tracking_hash_via_hash!(Option<Vec<String>>);
20612057
impl_dep_tracking_hash_via_hash!(Option<MergeFunctions>);
20622058
impl_dep_tracking_hash_via_hash!(Option<RelocModel>);
2059+
impl_dep_tracking_hash_via_hash!(Option<CodeModel>);
20632060
impl_dep_tracking_hash_via_hash!(Option<TlsModel>);
20642061
impl_dep_tracking_hash_via_hash!(Option<PanicStrategy>);
20652062
impl_dep_tracking_hash_via_hash!(Option<RelroLevel>);

src/librustc_session/options.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ use crate::lint;
55
use crate::search_paths::SearchPath;
66
use crate::utils::NativeLibraryKind;
77

8-
use rustc_target::spec::TargetTriple;
9-
use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy};
10-
use rustc_target::spec::{RelocModel, RelroLevel, TlsModel};
8+
use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy};
9+
use rustc_target::spec::{RelocModel, RelroLevel, TargetTriple, TlsModel};
1110

1211
use rustc_feature::UnstableFeatures;
1312
use rustc_span::edition::Edition;
@@ -269,6 +268,8 @@ macro_rules! options {
269268
pub const parse_src_file_hash: &str = "either `md5` or `sha1`";
270269
pub const parse_relocation_model: &str =
271270
"one of supported relocation models (`rustc --print relocation-models`)";
271+
pub const parse_code_model: &str =
272+
"one of supported code models (`rustc --print code-models`)";
272273
pub const parse_tls_model: &str =
273274
"one of supported TLS models (`rustc --print tls-models`)";
274275
pub const parse_target_feature: &str = parse_string;
@@ -621,6 +622,14 @@ macro_rules! options {
621622
true
622623
}
623624

625+
fn parse_code_model(slot: &mut Option<CodeModel>, v: Option<&str>) -> bool {
626+
match v.and_then(|s| CodeModel::from_str(s).ok()) {
627+
Some(code_model) => *slot = Some(code_model),
628+
_ => return false,
629+
}
630+
true
631+
}
632+
624633
fn parse_tls_model(slot: &mut Option<TlsModel>, v: Option<&str>) -> bool {
625634
match v.and_then(|s| TlsModel::from_str(s).ok()) {
626635
Some(tls_model) => *slot = Some(tls_model),
@@ -676,7 +685,7 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
676685

677686
ar: String = (String::new(), parse_string, [UNTRACKED],
678687
"this option is deprecated and does nothing"),
679-
code_model: Option<String> = (None, parse_opt_string, [TRACKED],
688+
code_model: Option<CodeModel> = (None, parse_code_model, [TRACKED],
680689
"choose the code model to use (`rustc --print code-models` for details)"),
681690
codegen_units: Option<usize> = (None, parse_opt_uint, [UNTRACKED],
682691
"divide crate into N units to optimize in parallel"),

src/librustc_session/session.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId, ErrorReported
2323
use rustc_span::edition::Edition;
2424
use rustc_span::source_map::{self, FileLoader, MultiSpan, RealFileLoader, SourceMap, Span};
2525
use rustc_span::{SourceFileHashAlgorithm, Symbol};
26-
use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, Target, TargetTriple, TlsModel};
26+
use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel};
27+
use rustc_target::spec::{Target, TargetTriple, TlsModel};
2728

2829
use std::cell::{self, RefCell};
2930
use std::env;
@@ -625,6 +626,10 @@ impl Session {
625626
self.opts.cg.relocation_model.unwrap_or(self.target.target.options.relocation_model)
626627
}
627628

629+
pub fn code_model(&self) -> Option<CodeModel> {
630+
self.opts.cg.code_model.or(self.target.target.options.code_model)
631+
}
632+
628633
pub fn tls_model(&self) -> TlsModel {
629634
self.opts.debugging_opts.tls_model.unwrap_or(self.target.target.options.tls_model)
630635
}

src/librustc_target/spec/mod.rs

+52-2
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,43 @@ impl ToJson for RelocModel {
305305
}
306306
}
307307

308+
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
309+
pub enum CodeModel {
310+
Tiny,
311+
Small,
312+
Kernel,
313+
Medium,
314+
Large,
315+
}
316+
317+
impl FromStr for CodeModel {
318+
type Err = ();
319+
320+
fn from_str(s: &str) -> Result<CodeModel, ()> {
321+
Ok(match s {
322+
// "tiny" => CodeModel::Tiny, // Not exposed to users right now.
323+
"small" => CodeModel::Small,
324+
"kernel" => CodeModel::Kernel,
325+
"medium" => CodeModel::Medium,
326+
"large" => CodeModel::Large,
327+
_ => return Err(()),
328+
})
329+
}
330+
}
331+
332+
impl ToJson for CodeModel {
333+
fn to_json(&self) -> Json {
334+
match *self {
335+
CodeModel::Tiny => "tiny",
336+
CodeModel::Small => "small",
337+
CodeModel::Kernel => "kernel",
338+
CodeModel::Medium => "medium",
339+
CodeModel::Large => "large",
340+
}
341+
.to_json()
342+
}
343+
}
344+
308345
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
309346
pub enum TlsModel {
310347
GeneralDynamic,
@@ -699,7 +736,8 @@ pub struct TargetOptions {
699736
/// -relocation-model=$relocation_model`. Defaults to `Pic`.
700737
pub relocation_model: RelocModel,
701738
/// Code model to use. Corresponds to `llc -code-model=$code_model`.
702-
pub code_model: Option<String>,
739+
/// Defaults to `None` which means "inherited from the base LLVM target".
740+
pub code_model: Option<CodeModel>,
703741
/// TLS model to use. Options are "global-dynamic" (default), "local-dynamic", "initial-exec"
704742
/// and "local-exec". This is similar to the -ftls-model option in GCC/Clang.
705743
pub tls_model: TlsModel,
@@ -1114,6 +1152,18 @@ impl Target {
11141152
Some(Ok(()))
11151153
})).unwrap_or(Ok(()))
11161154
} );
1155+
($key_name:ident, CodeModel) => ( {
1156+
let name = (stringify!($key_name)).replace("_", "-");
1157+
obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
1158+
match s.parse::<CodeModel>() {
1159+
Ok(code_model) => base.options.$key_name = Some(code_model),
1160+
_ => return Some(Err(format!("'{}' is not a valid code model. \
1161+
Run `rustc --print code-models` to \
1162+
see the list of supported values.", s))),
1163+
}
1164+
Some(Ok(()))
1165+
})).unwrap_or(Ok(()))
1166+
} );
11171167
($key_name:ident, TlsModel) => ( {
11181168
let name = (stringify!($key_name)).replace("_", "-");
11191169
obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
@@ -1266,7 +1316,7 @@ impl Target {
12661316
key!(only_cdylib, bool);
12671317
key!(executables, bool);
12681318
key!(relocation_model, RelocModel)?;
1269-
key!(code_model, optional);
1319+
key!(code_model, CodeModel)?;
12701320
key!(tls_model, TlsModel)?;
12711321
key!(disable_redzone, bool);
12721322
key!(eliminate_frame_pointer, bool);

src/librustc_target/spec/riscv64gc_unknown_linux_gnu.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
1+
use crate::spec::{CodeModel, LinkerFlavor, Target, TargetOptions, TargetResult};
22

33
pub fn target() -> TargetResult {
44
Ok(Target {
@@ -14,7 +14,7 @@ pub fn target() -> TargetResult {
1414
linker_flavor: LinkerFlavor::Gcc,
1515
options: TargetOptions {
1616
abi_blacklist: super::riscv_base::abi_blacklist(),
17-
code_model: Some("medium".to_string()),
17+
code_model: Some(CodeModel::Medium),
1818
cpu: "generic-rv64".to_string(),
1919
features: "+m,+a,+f,+d,+c".to_string(),
2020
llvm_abiname: "lp64d".to_string(),

src/librustc_target/spec/riscv64gc_unknown_none_elf.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
1+
use crate::spec::{CodeModel, LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
22
use crate::spec::{Target, TargetOptions, TargetResult};
33

44
pub fn target() -> TargetResult {
@@ -23,7 +23,7 @@ pub fn target() -> TargetResult {
2323
executables: true,
2424
panic_strategy: PanicStrategy::Abort,
2525
relocation_model: RelocModel::Static,
26-
code_model: Some("medium".to_string()),
26+
code_model: Some(CodeModel::Medium),
2727
emit_debug_gdb_scripts: false,
2828
abi_blacklist: super::riscv_base::abi_blacklist(),
2929
eliminate_frame_pointer: false,

src/librustc_target/spec/riscv64imac_unknown_none_elf.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
use crate::spec::{CodeModel, Target, TargetOptions, TargetResult};
12
use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
2-
use crate::spec::{Target, TargetOptions, TargetResult};
33

44
pub fn target() -> TargetResult {
55
Ok(Target {
@@ -23,7 +23,7 @@ pub fn target() -> TargetResult {
2323
executables: true,
2424
panic_strategy: PanicStrategy::Abort,
2525
relocation_model: RelocModel::Static,
26-
code_model: Some("medium".to_string()),
26+
code_model: Some(CodeModel::Medium),
2727
emit_debug_gdb_scripts: false,
2828
abi_blacklist: super::riscv_base::abi_blacklist(),
2929
eliminate_frame_pointer: false,

src/librustc_target/spec/x86_64_linux_kernel.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// This defines the amd64 target for the Linux Kernel. See the linux-kernel-base module for
22
// generic Linux kernel options.
33

4-
use crate::spec::{LinkerFlavor, Target, TargetResult};
4+
use crate::spec::{CodeModel, LinkerFlavor, Target, TargetResult};
55

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

1616
Ok(Target {

src/librustc_target/spec/x86_64_unknown_uefi.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// The win64 ABI is used. It differs from the sysv64 ABI, so we must use a windows target with
66
// LLVM. "x86_64-unknown-windows" is used to get the minimal subset of windows-specific features.
77

8-
use crate::spec::{LinkerFlavor, LldFlavor, Target, TargetResult};
8+
use crate::spec::{CodeModel, LinkerFlavor, LldFlavor, Target, TargetResult};
99

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

3131
Ok(Target {
3232
llvm_target: "x86_64-unknown-windows".to_string(),

0 commit comments

Comments
 (0)