about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2024-12-30 19:08:03 +0100
committerRalf Jung <post@ralfj.de>2024-12-30 21:59:05 +0100
commita0dbb37ebd7919df4b698deb356e024a741283ec (patch)
tree44f86eee8f6ccca604db1afc1541c1a39f3eacfc
parentfff026c8e572809cfce7202ec1ad63897b72c5b0 (diff)
downloadrust-a0dbb37ebd7919df4b698deb356e024a741283ec.tar.gz
rust-a0dbb37ebd7919df4b698deb356e024a741283ec.zip
add llvm_floatabi field to target spec that controls FloatABIType
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs16
-rw-r--r--compiler/rustc_target/src/spec/json.rs14
-rw-r--r--compiler/rustc_target/src/spec/mod.rs41
3 files changed, 67 insertions, 4 deletions
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index ba4492b4936..806f810627d 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -26,7 +26,7 @@ use rustc_session::config::{
     self, Lto, OutputType, Passes, RemapPathScopeComponents, SplitDwarfKind, SwitchWithOptPath,
 };
 use rustc_span::{BytePos, InnerSpan, Pos, SpanData, SyntaxContext, sym};
-use rustc_target::spec::{CodeModel, RelocModel, SanitizerSet, SplitDebuginfo, TlsModel};
+use rustc_target::spec::{CodeModel, FloatAbi, RelocModel, SanitizerSet, SplitDebuginfo, TlsModel};
 use tracing::debug;
 
 use crate::back::lto::ThinBuffer;
@@ -40,7 +40,7 @@ use crate::errors::{
     WithLlvmError, WriteBytecode,
 };
 use crate::llvm::diagnostic::OptimizationDiagnosticKind::*;
-use crate::llvm::{self, DiagnosticInfo, FloatAbi, PassManager};
+use crate::llvm::{self, DiagnosticInfo, PassManager};
 use crate::type_::Type;
 use crate::{LlvmCodegenBackend, ModuleLlvm, base, common, llvm_util};
 
@@ -181,6 +181,14 @@ pub(crate) fn to_llvm_code_model(code_model: Option<CodeModel>) -> llvm::CodeMod
     }
 }
 
+fn to_llvm_float_abi(float_abi: Option<FloatAbi>) -> llvm::FloatAbi {
+    match float_abi {
+        None => llvm::FloatAbi::Default,
+        Some(FloatAbi::Soft) => llvm::FloatAbi::Soft,
+        Some(FloatAbi::Hard) => llvm::FloatAbi::Hard,
+    }
+}
+
 pub(crate) fn target_machine_factory(
     sess: &Session,
     optlvl: config::OptLevel,
@@ -190,11 +198,11 @@ pub(crate) fn target_machine_factory(
 
     let (opt_level, _) = to_llvm_opt_settings(optlvl);
     let float_abi = if sess.target.arch == "arm" && sess.opts.cg.soft_float {
-        FloatAbi::Soft
+        llvm::FloatAbi::Soft
     } else {
         // `validate_commandline_args_with_session_available` has already warned about this being
         // ignored. Let's make sure LLVM doesn't suddenly start using this flag on more targets.
-        FloatAbi::Default
+        to_llvm_float_abi(sess.target.llvm_floatabi)
     };
 
     let ffunction_sections =
diff --git a/compiler/rustc_target/src/spec/json.rs b/compiler/rustc_target/src/spec/json.rs
index 206766325aa..9cdc0801b1f 100644
--- a/compiler/rustc_target/src/spec/json.rs
+++ b/compiler/rustc_target/src/spec/json.rs
@@ -116,6 +116,18 @@ impl Target {
                     Some(Ok(()))
                 })).unwrap_or(Ok(()))
             } );
+            ($key_name:ident, FloatAbi) => ( {
+                let name = (stringify!($key_name)).replace("_", "-");
+                obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
+                    match s.parse::<super::FloatAbi>() {
+                        Ok(float_abi) => base.$key_name = Some(float_abi),
+                        _ => return Some(Err(format!("'{}' is not a valid value for \
+                                                      llvm-floatabi. Use 'soft' or 'hard'.",
+                                                      s))),
+                    }
+                    Some(Ok(()))
+                })).unwrap_or(Ok(()))
+            } );
             ($key_name:ident, RelocModel) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
                 obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
@@ -598,6 +610,7 @@ impl Target {
         key!(mcount = "target-mcount");
         key!(llvm_mcount_intrinsic, optional);
         key!(llvm_abiname);
+        key!(llvm_floatabi, FloatAbi)?;
         key!(relax_elf_relocations, bool);
         key!(llvm_args, list);
         key!(use_ctors_section, bool);
@@ -772,6 +785,7 @@ impl ToJson for Target {
         target_option_val!(mcount, "target-mcount");
         target_option_val!(llvm_mcount_intrinsic);
         target_option_val!(llvm_abiname);
+        target_option_val!(llvm_floatabi);
         target_option_val!(relax_elf_relocations);
         target_option_val!(llvm_args);
         target_option_val!(use_ctors_section);
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index ad746d3f26b..c25788b97e5 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1085,6 +1085,35 @@ impl ToJson for CodeModel {
     }
 }
 
+/// The float ABI setting to be configured in the LLVM target machine.
+#[derive(Clone, Copy, PartialEq, Hash, Debug)]
+pub enum FloatAbi {
+    Soft,
+    Hard,
+}
+
+impl FromStr for FloatAbi {
+    type Err = ();
+
+    fn from_str(s: &str) -> Result<FloatAbi, ()> {
+        Ok(match s {
+            "soft" => FloatAbi::Soft,
+            "hard" => FloatAbi::Hard,
+            _ => return Err(()),
+        })
+    }
+}
+
+impl ToJson for FloatAbi {
+    fn to_json(&self) -> Json {
+        match *self {
+            FloatAbi::Soft => "soft",
+            FloatAbi::Hard => "hard",
+        }
+        .to_json()
+    }
+}
+
 #[derive(Clone, Copy, PartialEq, Hash, Debug)]
 pub enum TlsModel {
     GeneralDynamic,
@@ -2150,6 +2179,8 @@ pub struct TargetOptions {
     pub env: StaticCow<str>,
     /// ABI name to distinguish multiple ABIs on the same OS and architecture. For instance, `"eabi"`
     /// or `"eabihf"`. Defaults to "".
+    /// This field is *not* forwarded directly to LLVM; its primary purpose is `cfg(target_abi)`.
+    /// However, parts of the backend do check this field for specific values to enable special behavior.
     pub abi: StaticCow<str>,
     /// Vendor name to use for conditional compilation (`target_vendor`). Defaults to "unknown".
     pub vendor: StaticCow<str>,
@@ -2446,8 +2477,17 @@ pub struct TargetOptions {
     pub llvm_mcount_intrinsic: Option<StaticCow<str>>,
 
     /// LLVM ABI name, corresponds to the '-mabi' parameter available in multilib C compilers
+    /// and the `-target-abi` flag in llc. In the LLVM API this is `MCOptions.ABIName`.
     pub llvm_abiname: StaticCow<str>,
 
+    /// Control the float ABI to use, for architectures that support it. The only architecture we
+    /// currently use this for is ARM. Corresponds to the `-float-abi` flag in llc. In the LLVM API
+    /// this is `FloatABIType`. (clang's `-mfloat-abi` is similar but more complicated since it
+    /// can also affect the `soft-float` target feature.)
+    ///
+    /// If not provided, LLVM will infer the float ABI from the target triple (`llvm_target`).
+    pub llvm_floatabi: Option<FloatAbi>,
+
     /// Whether or not RelaxElfRelocation flag will be passed to the linker
     pub relax_elf_relocations: bool,
 
@@ -2719,6 +2759,7 @@ impl Default for TargetOptions {
             mcount: "mcount".into(),
             llvm_mcount_intrinsic: None,
             llvm_abiname: "".into(),
+            llvm_floatabi: None,
             relax_elf_relocations: false,
             llvm_args: cvs![],
             use_ctors_section: false,