-
Notifications
You must be signed in to change notification settings - Fork 13.3k
[DoNotMerge][WIP] add support for thumb* (Cortex-M) targets #36526
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
Changes from all commits
9298f84
05b64c3
40f94c0
9acc050
0cff11c
fec8724
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# rustbuild-only target |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# rustbuild-only target |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# rustbuild-only target |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# rustbuild-only target |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,11 +34,14 @@ | |
//! far far less than working with compiler-rt's build system over time. | ||
|
||
extern crate gcc; | ||
extern crate rustc_cfg; | ||
|
||
use std::collections::BTreeMap; | ||
use std::env; | ||
use std::path::Path; | ||
|
||
use rustc_cfg::Cfg; | ||
|
||
struct Sources { | ||
// SYMBOL -> PATH TO SOURCE | ||
map: BTreeMap<&'static str, &'static str>, | ||
|
@@ -69,13 +72,33 @@ impl Sources { | |
} | ||
} | ||
} | ||
|
||
fn remove(&mut self, symbols: &[&str]) { | ||
for symbol in symbols { | ||
self.map.remove(*symbol).unwrap(); | ||
} | ||
} | ||
} | ||
|
||
fn main() { | ||
let target = env::var("TARGET").unwrap(); | ||
let Cfg { | ||
ref llvm_target, | ||
ref target_arch, | ||
ref target_os, | ||
ref target_env, | ||
ref target_vendor, | ||
.. | ||
} = Cfg::new(&target).unwrap(); | ||
// TODO(stage0) use `unwrap` instead of `unwrap_or` | ||
// NOTE in the latest stable/beta release, `rustc --print cfg` doesn't include `llvm_target` in | ||
// its output. In those cases simply fallback to the target triple, which is usually similar to | ||
// llvm-target, as a workaround. | ||
let llvm_target = llvm_target.as_ref().unwrap_or(&target).split('-').collect::<Vec<_>>(); | ||
let target_vendor = target_vendor.as_ref().unwrap(); | ||
let cfg = &mut gcc::Config::new(); | ||
|
||
if target.contains("msvc") { | ||
if target_env == "msvc" { | ||
// Don't pull in extra libraries on MSVC | ||
cfg.flag("/Zl"); | ||
|
||
|
@@ -90,6 +113,25 @@ fn main() { | |
cfg.flag("-ffreestanding"); | ||
} | ||
|
||
// NOTE Most of the ARM intrinsics are written in assembly. Tell gcc which arch we are going to | ||
// target to make sure that the assembly implementations really work for the target. If the | ||
// implementation is not valid for the arch, then gcc will error when compiling it. | ||
if llvm_target[0].starts_with("thumb") { | ||
cfg.flag("-mthumb"); | ||
} | ||
|
||
if llvm_target[0] == "thumbv6m" { | ||
cfg.flag("-march=armv6-m"); | ||
} | ||
|
||
if llvm_target[0] == "thumbv7m" { | ||
cfg.flag("-march=armv7-m"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This logic should end up in gcc-rs, right? |
||
} | ||
|
||
if llvm_target[0] == "thumbv7em" { | ||
cfg.flag("-march=armv7e-m"); | ||
} | ||
|
||
let mut sources = Sources::new(); | ||
sources.extend(&["absvdi2.c", | ||
"absvsi2.c", | ||
|
@@ -183,7 +225,7 @@ fn main() { | |
"umoddi3.c", | ||
"umodsi3.c"]); | ||
|
||
if !target.contains("ios") { | ||
if target_os != "ios" { | ||
sources.extend(&["absvti2.c", | ||
"addtf3.c", | ||
"addvti3.c", | ||
|
@@ -226,7 +268,7 @@ fn main() { | |
"umodti3.c"]); | ||
} | ||
|
||
if target.contains("apple") { | ||
if target_vendor == "apple" { | ||
sources.extend(&["atomic_flag_clear.c", | ||
"atomic_flag_clear_explicit.c", | ||
"atomic_flag_test_and_set.c", | ||
|
@@ -235,20 +277,20 @@ fn main() { | |
"atomic_thread_fence.c"]); | ||
} | ||
|
||
if !target.contains("windows") { | ||
if target_os != "windows" && target_os != "none" { | ||
sources.extend(&["emutls.c"]); | ||
} | ||
|
||
if target.contains("msvc") { | ||
if target.contains("x86_64") { | ||
if target_env == "msvc" { | ||
if llvm_target[0] == "x86_64" { | ||
sources.extend(&["x86_64/floatdidf.c", "x86_64/floatdisf.c", "x86_64/floatdixf.c"]); | ||
} | ||
} else { | ||
if !target.contains("freebsd") { | ||
if target_os != "freebsd" { | ||
sources.extend(&["gcc_personality_v0.c"]); | ||
} | ||
|
||
if target.contains("x86_64") { | ||
if target_arch == "x86_64" { | ||
sources.extend(&["x86_64/chkstk.S", | ||
"x86_64/chkstk2.S", | ||
"x86_64/floatdidf.c", | ||
|
@@ -259,7 +301,7 @@ fn main() { | |
"x86_64/floatundixf.S"]); | ||
} | ||
|
||
if target.contains("i386") || target.contains("i586") || target.contains("i686") { | ||
if llvm_target[0] == "i386" || llvm_target[0] == "i586" || llvm_target[0] == "i686" { | ||
sources.extend(&["i386/ashldi3.S", | ||
"i386/ashrdi3.S", | ||
"i386/chkstk.S", | ||
|
@@ -279,7 +321,7 @@ fn main() { | |
} | ||
} | ||
|
||
if target.contains("arm") && !target.contains("ios") { | ||
if target_arch == "arm" && target_os != "ios" { | ||
sources.extend(&["arm/aeabi_cdcmp.S", | ||
"arm/aeabi_cdcmpeq_check_nan.c", | ||
"arm/aeabi_cfcmp.S", | ||
|
@@ -315,7 +357,7 @@ fn main() { | |
"arm/umodsi3.S"]); | ||
} | ||
|
||
if target.contains("armv7") { | ||
if llvm_target[0] == "armv7" { | ||
sources.extend(&["arm/sync_fetch_and_add_4.S", | ||
"arm/sync_fetch_and_add_8.S", | ||
"arm/sync_fetch_and_and_4.S", | ||
|
@@ -338,46 +380,47 @@ fn main() { | |
"arm/sync_fetch_and_xor_8.S"]); | ||
} | ||
|
||
if target.contains("eabihf") { | ||
sources.extend(&["arm/adddf3vfp.S", | ||
"arm/addsf3vfp.S", | ||
"arm/divdf3vfp.S", | ||
"arm/divsf3vfp.S", | ||
"arm/eqdf2vfp.S", | ||
"arm/eqsf2vfp.S", | ||
"arm/extendsfdf2vfp.S", | ||
"arm/fixdfsivfp.S", | ||
"arm/fixsfsivfp.S", | ||
"arm/fixunsdfsivfp.S", | ||
"arm/fixunssfsivfp.S", | ||
"arm/floatsidfvfp.S", | ||
"arm/floatsisfvfp.S", | ||
"arm/floatunssidfvfp.S", | ||
"arm/floatunssisfvfp.S", | ||
"arm/gedf2vfp.S", | ||
"arm/gesf2vfp.S", | ||
"arm/gtdf2vfp.S", | ||
"arm/gtsf2vfp.S", | ||
"arm/ledf2vfp.S", | ||
"arm/lesf2vfp.S", | ||
"arm/ltdf2vfp.S", | ||
"arm/ltsf2vfp.S", | ||
"arm/muldf3vfp.S", | ||
"arm/mulsf3vfp.S", | ||
"arm/negdf2vfp.S", | ||
"arm/negsf2vfp.S", | ||
"arm/nedf2vfp.S", | ||
"arm/nesf2vfp.S", | ||
"arm/restore_vfp_d8_d15_regs.S", | ||
"arm/save_vfp_d8_d15_regs.S", | ||
"arm/subdf3vfp.S", | ||
"arm/subsf3vfp.S", | ||
"arm/truncdfsf2vfp.S", | ||
"arm/unorddf2vfp.S", | ||
"arm/unordsf2vfp.S"]); | ||
if llvm_target.last().unwrap().ends_with("eabihf") { | ||
if !llvm_target[0].starts_with("thumbv7em") { | ||
sources.extend(&["arm/adddf3vfp.S", | ||
"arm/addsf3vfp.S", | ||
"arm/divdf3vfp.S", | ||
"arm/divsf3vfp.S", | ||
"arm/eqdf2vfp.S", | ||
"arm/eqsf2vfp.S", | ||
"arm/extendsfdf2vfp.S", | ||
"arm/fixdfsivfp.S", | ||
"arm/fixsfsivfp.S", | ||
"arm/fixunsdfsivfp.S", | ||
"arm/fixunssfsivfp.S", | ||
"arm/floatsidfvfp.S", | ||
"arm/floatsisfvfp.S", | ||
"arm/floatunssidfvfp.S", | ||
"arm/floatunssisfvfp.S", | ||
"arm/gedf2vfp.S", | ||
"arm/gesf2vfp.S", | ||
"arm/gtdf2vfp.S", | ||
"arm/gtsf2vfp.S", | ||
"arm/ledf2vfp.S", | ||
"arm/lesf2vfp.S", | ||
"arm/ltdf2vfp.S", | ||
"arm/ltsf2vfp.S", | ||
"arm/muldf3vfp.S", | ||
"arm/mulsf3vfp.S", | ||
"arm/nedf2vfp.S", | ||
"arm/nesf2vfp.S", | ||
"arm/restore_vfp_d8_d15_regs.S", | ||
"arm/save_vfp_d8_d15_regs.S", | ||
"arm/subdf3vfp.S", | ||
"arm/subsf3vfp.S", | ||
]); | ||
} | ||
|
||
sources.extend(&["arm/negdf2vfp.S", "arm/negsf2vfp.S"]); | ||
|
||
} | ||
|
||
if target.contains("aarch64") { | ||
if target_arch == "aarch64" { | ||
sources.extend(&["comparetf2.c", | ||
"extenddftf2.c", | ||
"extendsftf2.c", | ||
|
@@ -396,6 +439,18 @@ fn main() { | |
"trunctfsf2.c"]); | ||
} | ||
|
||
// Remove the assembly implementations that won't compile for the target | ||
if llvm_target[0] == "thumbv6m" { | ||
sources.remove(&["aeabi_cdcmp", "aeabi_cfcmp", "aeabi_dcmp", "aeabi_fcmp", "aeabi_ldivmod", | ||
"aeabi_memset", "aeabi_uldivmod", "clzdi2", "clzsi2", "comparesf2", | ||
"divmodsi4", "divsi3", "modsi3", "switch16", "switch32", "switch8", | ||
"switchu8", "udivmodsi4", "udivsi3", "umodsi3"]); | ||
} | ||
|
||
if llvm_target[0] == "thumbv7m" || llvm_target[0] == "thumbv7em" { | ||
sources.remove(&["aeabi_cdcmp", "aeabi_cfcmp"]); | ||
} | ||
|
||
for src in sources.map.values() { | ||
cfg.file(Path::new("../compiler-rt/lib/builtins").join(src)); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -63,11 +63,12 @@ mod netbsd_base; | |
mod solaris_base; | ||
mod windows_base; | ||
mod windows_msvc_base; | ||
mod thumb_base; | ||
|
||
pub type TargetResult = Result<Target, String>; | ||
|
||
macro_rules! supported_targets { | ||
( $(($triple:expr, $module:ident)),+ ) => ( | ||
( $(($triple:expr, $module:ident)),+, ) => ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can actually move the comma inside the parens to require a trailing comma like: ( $(($triple:expr, $module:ident),)+ ) |
||
$(mod $module;)* | ||
|
||
/// List of supported targets | ||
|
@@ -184,7 +185,12 @@ supported_targets! { | |
("i586-pc-windows-msvc", i586_pc_windows_msvc), | ||
|
||
("le32-unknown-nacl", le32_unknown_nacl), | ||
("asmjs-unknown-emscripten", asmjs_unknown_emscripten) | ||
("asmjs-unknown-emscripten", asmjs_unknown_emscripten), | ||
|
||
("thumbv6m-none-eabi", thumbv6m_none_eabi), | ||
("thumbv7m-none-eabi", thumbv7m_none_eabi), | ||
("thumbv7em-none-eabi", thumbv7em_none_eabi), | ||
("thumbv7em-none-eabihf", thumbv7em_none_eabihf), | ||
} | ||
|
||
/// Everything `rustc` knows about how to compile for a specific target. | ||
|
@@ -391,7 +397,13 @@ impl Default for TargetOptions { | |
allow_asm: true, | ||
has_elf_tls: false, | ||
obj_is_bitcode: false, | ||
max_atomic_width: 0, | ||
// NOTE this is *not* the real default value. The default value of max_atomic_width is | ||
// actually the pointer width of the target. This default is injected in the | ||
// Target::from_json function. Still, we have to pick some value to put here. We'll pick | ||
// an impossible value: u64::max_value() because using a valid value like 0 or 8 as the | ||
// default would cause the max-atomic-width field to be "lost" (it would get replaced | ||
// by target_pointer_width) during the Target <-> JSON round trip | ||
max_atomic_width: u64::max_value(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm I'm not sure I quite understand why this is necessary, could you elaborate what you mean by "lost" in the comment? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure! Let me ellaborate here, first, what happens today without this change:
TL;DR You set The bug is subtle and the proposed fix is sort of magical. Perhaps we could solve it in a better way. |
||
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this may be something that should be in gcc-rs, but maybe I'm missing something? Couldn't we just look at
$TARGET
like we do for other platforms?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change is from #36512. Check that PR for context.