about summary refs log tree commit diff
path: root/library/compiler-builtins/crates
diff options
context:
space:
mode:
Diffstat (limited to 'library/compiler-builtins/crates')
-rw-r--r--library/compiler-builtins/crates/libm-macros/src/lib.rs30
-rw-r--r--library/compiler-builtins/crates/libm-macros/src/parse.rs16
-rw-r--r--library/compiler-builtins/crates/libm-macros/tests/basic.rs72
-rw-r--r--library/compiler-builtins/crates/util/src/main.rs44
4 files changed, 121 insertions, 41 deletions
diff --git a/library/compiler-builtins/crates/libm-macros/src/lib.rs b/library/compiler-builtins/crates/libm-macros/src/lib.rs
index 144676c1253..e8afe3aad55 100644
--- a/library/compiler-builtins/crates/libm-macros/src/lib.rs
+++ b/library/compiler-builtins/crates/libm-macros/src/lib.rs
@@ -116,6 +116,9 @@ pub fn base_name_enum(attributes: pm::TokenStream, tokens: pm::TokenStream) -> p
 ///     // a simplified match-like syntax.
 ///     fn_extra: match MACRO_FN_NAME {
 ///         hypot | hypotf => |x| x.hypot(),
+///         // `ALL_*` magic matchers also work to extract specific types
+///         ALL_F64 => |x| x,
+///         // The default pattern gets applied to everything that did not match
 ///         _ => |x| x,
 ///     },
 /// }
@@ -138,6 +141,27 @@ pub fn for_each_function(tokens: pm::TokenStream) -> pm::TokenStream {
 ///
 /// Returns the list of function names that we should expand for.
 fn validate(input: &mut StructuredInput) -> syn::Result<Vec<&'static MathOpInfo>> {
+    // Replace magic mappers with a list of relevant functions.
+    if let Some(map) = &mut input.fn_extra {
+        for (name, ty) in [
+            ("ALL_F16", FloatTy::F16),
+            ("ALL_F32", FloatTy::F32),
+            ("ALL_F64", FloatTy::F64),
+            ("ALL_F128", FloatTy::F128),
+        ] {
+            let Some(k) = map.keys().find(|key| *key == name) else {
+                continue;
+            };
+
+            let key = k.clone();
+            let val = map.remove(&key).unwrap();
+
+            for op in ALL_OPERATIONS.iter().filter(|op| op.float_ty == ty) {
+                map.insert(Ident::new(op.name, key.span()), val.clone());
+            }
+        }
+    }
+
     // Collect lists of all functions that are provied as macro inputs in various fields (only,
     // skip, attributes).
     let attr_mentions = input
@@ -195,6 +219,12 @@ fn validate(input: &mut StructuredInput) -> syn::Result<Vec<&'static MathOpInfo>
             continue;
         }
 
+        // Omit f16 and f128 functions if requested
+        if input.skip_f16_f128 && (func.float_ty == FloatTy::F16 || func.float_ty == FloatTy::F128)
+        {
+            continue;
+        }
+
         // Run everything else
         fn_list.push(func);
     }
diff --git a/library/compiler-builtins/crates/libm-macros/src/parse.rs b/library/compiler-builtins/crates/libm-macros/src/parse.rs
index d60d1247a9e..4876f3ef726 100644
--- a/library/compiler-builtins/crates/libm-macros/src/parse.rs
+++ b/library/compiler-builtins/crates/libm-macros/src/parse.rs
@@ -6,7 +6,7 @@ use syn::parse::{Parse, ParseStream, Parser};
 use syn::punctuated::Punctuated;
 use syn::spanned::Spanned;
 use syn::token::{self, Comma};
-use syn::{Arm, Attribute, Expr, ExprMatch, Ident, Meta, Token, bracketed};
+use syn::{Arm, Attribute, Expr, ExprMatch, Ident, LitBool, Meta, Token, bracketed};
 
 /// The input to our macro; just a list of `field: value` items.
 #[derive(Debug)]
@@ -50,6 +50,8 @@ pub struct StructuredInput {
     pub emit_types: Vec<Ident>,
     /// Skip these functions
     pub skip: Vec<Ident>,
+    /// If true, omit f16 and f128 functions that aren't present in other libraries.
+    pub skip_f16_f128: bool,
     /// Invoke only for these functions
     pub only: Option<Vec<Ident>>,
     /// Attributes that get applied to specific functions
@@ -70,6 +72,7 @@ impl StructuredInput {
         let cb_expr = expect_field(&mut map, "callback")?;
         let emit_types_expr = expect_field(&mut map, "emit_types").ok();
         let skip_expr = expect_field(&mut map, "skip").ok();
+        let skip_f16_f128 = expect_field(&mut map, "skip_f16_f128").ok();
         let only_expr = expect_field(&mut map, "only").ok();
         let attr_expr = expect_field(&mut map, "attributes").ok();
         let extra = expect_field(&mut map, "extra").ok();
@@ -93,6 +96,11 @@ impl StructuredInput {
             None => Vec::new(),
         };
 
+        let skip_f16_f128 = match skip_f16_f128 {
+            Some(expr) => expect_litbool(expr)?.value,
+            None => false,
+        };
+
         let only_span = only_expr.as_ref().map(|expr| expr.span());
         let only = match only_expr {
             Some(expr) => Some(Parser::parse2(parse_ident_array, expr.into_token_stream())?),
@@ -122,6 +130,7 @@ impl StructuredInput {
             callback: expect_ident(cb_expr)?,
             emit_types,
             skip,
+            skip_f16_f128,
             only,
             only_span,
             attributes,
@@ -220,6 +229,11 @@ fn expect_ident(expr: Expr) -> syn::Result<Ident> {
     syn::parse2(expr.into_token_stream())
 }
 
+/// Coerce an expression into a simple keyword.
+fn expect_litbool(expr: Expr) -> syn::Result<LitBool> {
+    syn::parse2(expr.into_token_stream())
+}
+
 /// Parse either a single identifier (`foo`) or an array of identifiers (`[foo, bar, baz]`).
 fn parse_ident_or_array(input: ParseStream) -> syn::Result<Vec<Ident>> {
     if !input.peek(token::Bracket) {
diff --git a/library/compiler-builtins/crates/libm-macros/tests/basic.rs b/library/compiler-builtins/crates/libm-macros/tests/basic.rs
index 260350ef254..b4276262229 100644
--- a/library/compiler-builtins/crates/libm-macros/tests/basic.rs
+++ b/library/compiler-builtins/crates/libm-macros/tests/basic.rs
@@ -103,3 +103,75 @@ mod test_emit_types {
         emit_types: [RustFn, RustArgs],
     }
 }
+
+#[test]
+fn test_skip_f16_f128() {
+    macro_rules! skip_f16_f128 {
+        (
+        fn_name: $fn_name:ident,
+        attrs: [$($attr:meta),*],
+        extra: $vec:ident,
+    ) => {
+            $vec.push(stringify!($fn_name));
+        };
+    }
+
+    let mut v = Vec::new();
+    // Test with no extra, no skip, and no attributes
+    libm_macros::for_each_function! {
+        callback: skip_f16_f128,
+        skip_f16_f128: true,
+        extra: v,
+    }
+
+    for name in v {
+        assert!(!name.contains("f16"), "{name}");
+        assert!(!name.contains("f128"), "{name}");
+    }
+}
+
+#[test]
+fn test_fn_extra_expansion() {
+    macro_rules! fn_extra_expansion {
+        (
+            fn_name: $fn_name:ident,
+            attrs: [$($attr:meta),*],
+            fn_extra: $vec:expr,
+        ) => {
+            $vec.push(stringify!($fn_name));
+        };
+    }
+
+    let mut vf16 = Vec::new();
+    let mut vf32 = Vec::new();
+    let mut vf64 = Vec::new();
+    let mut vf128 = Vec::new();
+
+    // Test with no extra, no skip, and no attributes
+    libm_macros::for_each_function! {
+        callback: fn_extra_expansion,
+        fn_extra: match MACRO_FN_NAME {
+            ALL_F16 => vf16,
+            ALL_F32 => vf32,
+            ALL_F64 => vf64,
+            ALL_F128 => vf128,
+        }
+    }
+
+    // Skip functions with a suffix after the type spec
+    vf16.retain(|name| !name.ends_with("_r"));
+    vf32.retain(|name| !name.ends_with("_r"));
+    vf64.retain(|name| !name.ends_with("_r"));
+    vf128.retain(|name| !name.ends_with("_r"));
+
+    for name in vf16 {
+        assert!(name.ends_with("f16"), "{name}");
+    }
+    for name in vf32 {
+        assert!(name.ends_with("f"), "{name}");
+    }
+    let _ = vf64;
+    for name in vf128 {
+        assert!(name.ends_with("f128"), "{name}");
+    }
+}
diff --git a/library/compiler-builtins/crates/util/src/main.rs b/library/compiler-builtins/crates/util/src/main.rs
index e7057869996..5972181531b 100644
--- a/library/compiler-builtins/crates/util/src/main.rs
+++ b/library/compiler-builtins/crates/util/src/main.rs
@@ -86,55 +86,19 @@ fn do_eval(basis: &str, op: &str, inputs: &[&str]) {
         emit_types: [CFn, RustFn, RustArgs],
         extra: (basis, op, inputs),
         fn_extra: match MACRO_FN_NAME {
-            ceilf128
-            | ceilf16
-            | copysignf128
-            | copysignf16
-            | fabsf128
-            | fabsf16
-            | fdimf128
-            | fdimf16
-            | floorf128
-            | floorf16
-            | fmaf128
-            | fmaxf128
-            | fmaxf16
-            | fmaximum
+            // Not provided by musl
+            fmaximum
             | fmaximum_num
             | fmaximum_numf
-            | fmaximum_numf128
-            | fmaximum_numf16
             | fmaximumf
-            | fmaximumf128
-            | fmaximumf16
-            | fminf128
-            | fminf16
             | fminimum
             | fminimum_num
             | fminimum_numf
-            | fminimum_numf128
-            | fminimum_numf16
             | fminimumf
-            | fminimumf128
-            | fminimumf16
-            | fmodf128
-            | fmodf16
-            | ldexpf128
-            | ldexpf16
-            | rintf128
-            | rintf16
             | roundeven
             | roundevenf
-            | roundevenf128
-            | roundevenf16
-            | roundf128
-            | roundf16
-            | scalbnf128
-            | scalbnf16
-            | sqrtf128
-            | sqrtf16
-            | truncf128
-            | truncf16  => None,
+            | ALL_F16
+            | ALL_F128 => None,
             _ => Some(musl_math_sys::MACRO_FN_NAME)
         }
     }