core: reduce code duplication in codegen/extern_fns #453

Merged
sb10q merged 2 commits from refactor-extern_fns into master 2024-07-09 16:31:12 +08:00
Showing only changes of commit 3da5d1a03a - Show all commits

View File

@ -4,17 +4,34 @@ use itertools::Either;
use crate::codegen::CodeGenContext; use crate::codegen::CodeGenContext;
/// Macro to conveniently generate extern function call /// Macro to generate extern function
/// Generates a public function with `FloatValue` return type /// Both function return type and function parameter type are `FloatValue`
/// ///
/// Arguments: /// Arguments:
/// * `unary/binary`: Whether the extern function requires one (unary) or two (binary) operands
/// * `$fn_name:ident`: The identifier of the rust function to be generated /// * `$fn_name:ident`: The identifier of the rust function to be generated
/// * `$extern_fn:literal`: Name of underlying extern function /// * `$extern_fn:literal`: Name of underlying extern function
/// * `$(,$args:ident)*`: Operands of the function
/// The data type of these operands must be `FloatValue`
/// * `$(,$attributes:literal)*)`: Attributes linked with the extern function
/// ///
macro_rules! helper_generate_extern_fn_call { /// Optional Arguments:
/// * `$(,$attributes:literal)*)`: Attributes linked with the extern function
/// The default attributes are "mustprogress", "nofree", "nounwind", "willreturn", and "writeonly"
/// These will be used unless other attributes are specified
/// * `$(,$args:ident)*`: Operands of the extern function
/// The data type of these operands will be set to `FloatValue`
///
macro_rules! generate_extern_fn {
("unary", $fn_name:ident, $extern_fn:literal) => {
generate_extern_fn!($fn_name, $extern_fn, arg, "mustprogress", "nofree", "nounwind", "willreturn", "writeonly");
};
("unary", $fn_name:ident, $extern_fn:literal $(,$attributes:literal)*) => {
generate_extern_fn!($fn_name, $extern_fn, arg $(,$attributes)*);
};
("binary", $fn_name:ident, $extern_fn:literal) => {
generate_extern_fn!($fn_name, $extern_fn, arg1, arg2, "mustprogress", "nofree", "nounwind", "willreturn", "writeonly");
};
("binary", $fn_name:ident, $extern_fn:literal $(,$attributes:literal)*) => {
generate_extern_fn!($fn_name, $extern_fn, arg1, arg2 $(,$attributes)*);
};
($fn_name:ident, $extern_fn:literal $(,$args:ident)* $(,$attributes:literal)*) => { ($fn_name:ident, $extern_fn:literal $(,$args:ident)* $(,$attributes:literal)*) => {
#[doc = concat!("Invokes the [`", stringify!($extern_fn), "`](https://en.cppreference.com/w/c/numeric/math/", stringify!($llvm_name), ") function." )] #[doc = concat!("Invokes the [`", stringify!($extern_fn), "`](https://en.cppreference.com/w/c/numeric/math/", stringify!($llvm_name), ") function." )]
pub fn $fn_name<'ctx>( pub fn $fn_name<'ctx>(
@ -49,58 +66,19 @@ macro_rules! helper_generate_extern_fn_call {
}; };
} }
/// Macro to conveniently generate extern function call with [`helper_generate_extern_fn_call`]. generate_extern_fn!("unary", call_tan, "tan");
/// Handles unary extern functions only (Use `generate_extern_binary_fn_call` for binary functions) generate_extern_fn!("unary", call_asin, "asin");
/// Both function return type and function parameter type are `FloatValue` generate_extern_fn!("unary", call_acos, "acos");
/// generate_extern_fn!("unary", call_atan, "atan");
/// Arguments: generate_extern_fn!("unary", call_sinh, "sinh");
/// * `$fn_name:ident`: The identifier of the rust function to be generated generate_extern_fn!("unary", call_cosh, "cosh");
/// * `$extern_fn:literal`: Name of underlying extern function generate_extern_fn!("unary", call_tanh, "tanh");
/// * `$(,$attributes:literal)*)`: Attributes linked with the extern function generate_extern_fn!("unary", call_asinh, "asinh");
/// The default attributes are "mustprogress", "nofree", "nounwind", "willreturn", and "writeonly" generate_extern_fn!("unary", call_acosh, "acosh");
/// These will be used unless other attributes are specified generate_extern_fn!("unary", call_atanh, "atanh");
/// generate_extern_fn!("unary", call_expm1, "expm1");
macro_rules! generate_extern_unary_fn_call { generate_extern_fn!(
($fn_name:ident, $extern_fn:literal) => { "unary",
helper_generate_extern_fn_call!($fn_name, $extern_fn, arg, "mustprogress", "nofree", "nounwind", "willreturn", "writeonly");
};
($fn_name:ident, $extern_fn:literal $(,$attributes:literal)*) => {
helper_generate_extern_fn_call!($fn_name, $extern_fn, arg $(,$attributes)*);
};
}
/// Macro to conveniently generate extern function call with [`helper_generate_extern_fn_call`].
/// Handles binary extern functions only (Use `generate_extern_unary_fn_call` for unary functions)
/// Both function return type and function parameter type are `FloatValue`
///
/// Arguments:
/// * `$fn_name:ident`: The identifier of the rust function to be generated
/// * `$extern_fn:literal`: Name of underlying extern function
/// * `$(,$attributes:literal)*)`: Attributes linked with the extern function
/// The default attributes are "mustprogress", "nofree", "nounwind", "willreturn", and "writeonly"
/// These will be used unless other attributes are specified
///
macro_rules! generate_extern_binary_fn_call {
($fn_name:ident, $extern_fn:literal) => {
helper_generate_extern_fn_call!($fn_name, $extern_fn, arg1, arg2, "mustprogress", "nofree", "nounwind", "willreturn", "writeonly");
};
($fn_name:ident, $extern_fn:literal $(,$attributes:literal)*) => {
helper_generate_extern_fn_call!($fn_name, $extern_fn, arg1, arg2 $(,$attributes)*);
};
}
generate_extern_unary_fn_call!(call_tan, "tan");
generate_extern_unary_fn_call!(call_asin, "asin");
generate_extern_unary_fn_call!(call_acos, "acos");
generate_extern_unary_fn_call!(call_atan, "atan");
generate_extern_unary_fn_call!(call_sinh, "sinh");
generate_extern_unary_fn_call!(call_cosh, "cosh");
generate_extern_unary_fn_call!(call_tanh, "tanh");
generate_extern_unary_fn_call!(call_asinh, "asinh");
generate_extern_unary_fn_call!(call_acosh, "acosh");
generate_extern_unary_fn_call!(call_atanh, "atanh");
generate_extern_unary_fn_call!(call_expm1, "expm1");
generate_extern_unary_fn_call!(
call_cbrt, call_cbrt,
"cbrt", "cbrt",
Review

It's rather confusing what is "helper" and what is not. Can you find a better name, or remove "helper" entirely?

It's rather confusing what is "helper" and what is not. Can you find a better name, or remove "helper" entirely?
Review

Removed helper entirely and merged the macros into generate_extern_fn macro

Removed helper entirely and merged the macros into `generate_extern_fn` macro
"mustprogress", "mustprogress",
@ -110,13 +88,13 @@ generate_extern_unary_fn_call!(
"readonly", "readonly",
"willreturn" "willreturn"
); );
generate_extern_unary_fn_call!(call_erf, "erf", "nounwind"); generate_extern_fn!("unary", call_erf, "erf", "nounwind");
generate_extern_unary_fn_call!(call_erfc, "erfc", "nounwind"); generate_extern_fn!("unary", call_erfc, "erfc", "nounwind");
generate_extern_unary_fn_call!(call_j1, "j1", "nounwind"); generate_extern_fn!("unary", call_j1, "j1", "nounwind");
generate_extern_binary_fn_call!(call_atan2, "atan2"); generate_extern_fn!("binary", call_atan2, "atan2");
generate_extern_binary_fn_call!(call_hypot, "hypot", "nounwind"); generate_extern_fn!("binary", call_hypot, "hypot", "nounwind");
generate_extern_binary_fn_call!(call_nextafter, "nextafter", "nounwind"); generate_extern_fn!("binary", call_nextafter, "nextafter", "nounwind");
/// Invokes the [`ldexp`](https://en.cppreference.com/w/c/numeric/math/ldexp) function. /// Invokes the [`ldexp`](https://en.cppreference.com/w/c/numeric/math/ldexp) function.
pub fn call_ldexp<'ctx>( pub fn call_ldexp<'ctx>(