Fortran function like - #3135
Conversation
d14e34f to
0dddd1b
Compare
joewallwork
left a comment
There was a problem hiding this comment.
This looks great so far. I left a few comments and suggestions on the Fortran side of things.
I was wondering: is there any particular reason you use double precision rather than real in the test and docs here?
3da5c9e to
17791a0
Compare
Both work, I think it was left over from when I was trying out different things. I've changed it to use real. |
joewallwork
left a comment
There was a problem hiding this comment.
Thanks for your work on this @isaacaka. I have a concern about including procedures that don't belong to programs or modules because it's considered bad practice.
f98bd87 to
e40b065
Compare
joewallwork
left a comment
There was a problem hiding this comment.
I'm happy with this now, thanks @isaacaka!
The logic can be reused across Clang, C and Fortran and avoid duplicating target/name validation, enzyme_math attribution, and linkage preservation.
Recognize Flang marker calls, derive the function name from an enzyme_math_* BIND(C) global, and pass the target and name to the existing handleFunctionLike helper before removing the marker.
Co-authored-by: Joe Wallwork <22053413+joewallwork@users.noreply.github.com>
Co-authored-by: Joe Wallwork <22053413+joewallwork@users.noreply.github.com>
Test declares the binding that is needed and updated README to reflect the removal
d6efe5c to
0e5f92e
Compare
Add Fortran
enzyme_function_likesupportSummary
This adds two ways to register a Fortran function as behaving like a
mathematical function known to Enzyme.
use enzyme, only: enzyme_function_like, enzyme_log1p call enzyme_function_like(log1p_like_function, enzyme_log1p)The declaration-style alternative is closer to C's static registration:
This declaration creates a module global that points at
log1p_like_function. Because Fortran cannot construct the equivalent of C’sstatically initialized {function pointer, string pointer} struct the function whose rule is being copied is instead encoded in the global’s name. PreserveNVVM searches for
__enzyme_function_like__and readslog1pfrom itssuffix.
Trade-offs
Call-style registration, such as
call enzyme_function_like(target, enzyme_log1p), simpler and clearer.However, every math function name needs a global binding such as
integer(c_int), bind(C, name="enzyme_math_log1p") :: enzyme_log1p.Users can declare missing bindings themselves.
Procedure-pointer registration doesn't need a binding per function. Its
less simple and the marker name must be unique, and the rule name
must fit a Fortran identifier. Names containing punctuation etc won't work
Other things I tried
C-compatible static record
The closest translation of C's
{ function pointer, string pointer }globaldidn't work:
Flang rejects the initialiser because
c_funlocandc_locare not validconstant initialisation expressions here:
C is able to handle things like the above but Fortran cannot
Passing
"log1p"directlydoes not lower to a direct constant-string argument. Flang copies the literal through a stack temporary variable
Tests
procedure-pointer marker.
"enzyme_math"="log1p"