about summary refs log tree commit diff
path: root/library/compiler-builtins/crates/libm-macros/src
diff options
context:
space:
mode:
Diffstat (limited to 'library/compiler-builtins/crates/libm-macros/src')
-rw-r--r--library/compiler-builtins/crates/libm-macros/src/lib.rs30
-rw-r--r--library/compiler-builtins/crates/libm-macros/src/parse.rs16
2 files changed, 45 insertions, 1 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) {