Skip to content

WIP: use the libm MPFR testing infra to test compiler-builtins #926

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

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 36 additions & 7 deletions crates/libm-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ use parse::{Invocation, StructuredInput};
use proc_macro as pm;
use proc_macro2::{self as pm2, Span};
use quote::{ToTokens, quote};
use shared::OpScope;
pub(crate) use shared::{ALL_OPERATIONS, FloatTy, MathOpInfo, Ty};
use syn::spanned::Spanned;
use syn::visit_mut::VisitMut;
use syn::{Ident, ItemEnum};
use syn::{Ident, ItemEnum, PathArguments, PathSegment};

const KNOWN_TYPES: &[&str] = &[
"FTy", "CFn", "CArgs", "CRet", "RustFn", "RustArgs", "RustRet", "public",
"FTy", "CFn", "CArgs", "CRet", "RustFn", "RustArgs", "RustRet", "path",
];

/// Populate an enum with a variant representing function. Names are in upper camel case.
Expand Down Expand Up @@ -82,8 +83,8 @@ pub fn base_name_enum(attributes: pm::TokenStream, tokens: pm::TokenStream) -> p
/// RustArgs: $RustArgs:ty,
/// // The Rust version's return type (e.g. `(f32, f32)`)
/// RustRet: $RustRet:ty,
/// // True if this is part of `libm`'s public API
/// public: $public:expr,
/// // True if this is part of `libm`'s path API
/// path: $path:path,
/// // Attributes for the current function, if any
/// attrs: [$($attr:meta),*],
/// // Extra tokens passed directly (if any)
Expand Down Expand Up @@ -162,6 +163,18 @@ fn validate(input: &mut StructuredInput) -> syn::Result<Vec<&'static MathOpInfo>
map.insert(Ident::new(op.name, key.span()), val.clone());
}
}

if let Some(k) = map.keys().find(|key| *key == "ALL_BUILTINS") {
let key = k.clone();
let val = map.remove(&key).unwrap();

for op in ALL_OPERATIONS
.iter()
.filter(|op| op.scope == OpScope::BuiltinsPublic)
{
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,
Expand Down Expand Up @@ -227,6 +240,10 @@ fn validate(input: &mut StructuredInput) -> syn::Result<Vec<&'static MathOpInfo>
continue;
}

if input.skip_builtins && func.scope == OpScope::BuiltinsPublic {
continue;
}

// Run everything else
fn_list.push(func);
}
Expand Down Expand Up @@ -363,7 +380,17 @@ fn expand(input: StructuredInput, fn_list: &[&MathOpInfo]) -> syn::Result<pm2::T
let c_ret = &func.c_sig.returns;
let rust_args = &func.rust_sig.args;
let rust_ret = &func.rust_sig.returns;
let public = func.public;
let path = syn::Path {
leading_colon: None,
segments: func
.path
.split("::")
.map(|pseg| PathSegment {
ident: Ident::new(pseg, Span::call_site()),
arguments: PathArguments::None,
})
.collect(),
};

let mut ty_fields = Vec::new();
for ty in &input.emit_types {
Expand All @@ -375,8 +402,8 @@ fn expand(input: StructuredInput, fn_list: &[&MathOpInfo]) -> syn::Result<pm2::T
"RustFn" => quote! { RustFn: fn( #(#rust_args),* ,) -> ( #(#rust_ret),* ), },
"RustArgs" => quote! { RustArgs: ( #(#rust_args),* ,), },
"RustRet" => quote! { RustRet: ( #(#rust_ret),* ), },
"public" => quote! { public: #public, },
_ => unreachable!("checked in validation"),
"path" => quote! { path: #path, },
_ => unreachable!("fields should be checked in validation"),
};
ty_fields.push(field);
}
Expand Down Expand Up @@ -465,6 +492,8 @@ fn base_name(name: &str) -> &str {
None => name
.strip_suffix("f")
.or_else(|| name.strip_suffix("f16"))
.or_else(|| name.strip_suffix("f32"))
.or_else(|| name.strip_suffix("f64"))
.or_else(|| name.strip_suffix("f128"))
.unwrap_or(name),
}
Expand Down
8 changes: 8 additions & 0 deletions crates/libm-macros/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ pub struct StructuredInput {
pub skip: Vec<Ident>,
/// If true, omit f16 and f128 functions that aren't present in other libraries.
pub skip_f16_f128: bool,
pub skip_builtins: bool,
/// Invoke only for these functions
pub only: Option<Vec<Ident>>,
/// Attributes that get applied to specific functions
Expand All @@ -73,6 +74,7 @@ impl StructuredInput {
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 skip_builtins = expect_field(&mut map, "skip_builtins").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();
Expand Down Expand Up @@ -101,6 +103,11 @@ impl StructuredInput {
None => false,
};

let skip_builtins = match skip_builtins {
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())?),
Expand Down Expand Up @@ -131,6 +138,7 @@ impl StructuredInput {
emit_types,
skip,
skip_f16_f128,
skip_builtins,
only,
only_span,
attributes,
Expand Down
Loading
Loading