Skip to content

Fortran function like - #3135

Merged
isaacaka merged 26 commits into
mainfrom
fortran_function_like
Sep 23, 2026
Merged

isaacaka merged 26 commits into
mainfrom
fortran_function_like

Conversation

@isaacaka

@isaacaka isaacaka commented Aug 10, 2026 •

Copy link
Copy Markdown
Collaborator

Add Fortran enzyme_function_like support

Summary

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:

procedure(log1p_like_function), pointer, private :: &
  fn__enzyme_function_like__log1p => log1p_like_function

This declaration creates a module global that points at
log1p_like_function. Because Fortran cannot construct the equivalent of C’s
statically 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 reads log1p from its
suffix.

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 } global
didn't work:

type, bind(C) :: function_like_record
  type(c_funptr) :: target
  type(c_ptr) :: name
end type function_like_record

type(function_like_record), bind(C, name="__enzyme_function_like") :: &
  registration = function_like_record( &
    c_funloc(log1p_like_function), c_loc(log1p_name))

Flang rejects the initialiser because c_funloc and c_loc are not valid
constant initialisation expressions here:

error: Must be a constant value
c_funloc(log1p_like_function), c_loc(log1p_name)

C is able to handle things like the above but Fortran cannot

Passing "log1p" directly

call enzyme_function_like(log1p_like_function, "log1p")

does not lower to a direct constant-string argument. Flang copies the literal through a stack temporary variable

Tests

  • End-to-end Fortran differentiation through the call-style registration.
  • End-to-end differentiation through an independently registered
    procedure-pointer marker.
  • IR checks that the declaration form adds "enzyme_math"="log1p"
  • Add a warning for Conflicting registrations while retaining current behaviour

@isaacaka
isaacaka marked this pull request as draft August 10, 2026 15:30
@isaacaka isaacaka self-assigned this Aug 10, 2026
@isaacaka isaacaka changed the title Fortran function like Fortran function like [WIP] Aug 10, 2026
@isaacaka
isaacaka force-pushed the fortran_function_like branch from d14e34f to 0dddd1b Compare August 18, 2026 08:54

@joewallwork joewallwork left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Comment thread enzyme/Fortran/README.md Outdated
Comment thread enzyme/Fortran/README.md Outdated
Comment thread enzyme/Fortran/README.md Outdated
Comment thread enzyme/Fortran/README.md Outdated
Comment thread enzyme/test/Fortran/ReverseMode/function_like.f90
Comment thread enzyme/test/Fortran/ReverseMode/function_like.f90 Outdated
Comment thread enzyme/test/Fortran/ReverseMode/function_like_procedure_pointer.f90
@vchuravy
vchuravy marked this pull request as ready for review September 7, 2026 15:49
Comment thread enzyme/test/Fortran/ReverseMode/function_like_procedure_pointer.f90 Outdated
@isaacaka
isaacaka force-pushed the fortran_function_like branch from 3da5c9e to 17791a0 Compare September 10, 2026 15:07
@isaacaka

Copy link
Copy Markdown
Collaborator Author

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?

Both work, I think it was left over from when I was trying out different things. I've changed it to use real.

@joewallwork joewallwork left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread enzyme/Fortran/README.md
Comment thread enzyme/Fortran/README.md Outdated
Comment thread enzyme/Fortran/README.md Outdated
Comment thread enzyme/Fortran/README.md
Comment thread enzyme/Fortran/README.md Outdated
Comment thread enzyme/Fortran/README.md Outdated
Comment thread enzyme/Fortran/README.md Outdated
Comment thread enzyme/test/Fortran/ReverseMode/function_like_procedure_pointer.f90 Outdated
@isaacaka
isaacaka force-pushed the fortran_function_like branch from f98bd87 to e40b065 Compare September 15, 2026 15:20
@joewallwork joewallwork added the fortran Related to Enzyme's Fortran bindings label Sep 15, 2026

@joewallwork joewallwork left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy with this now, thanks @isaacaka!

@vchuravy vchuravy changed the title Fortran function like [WIP] Fortran function like Sep 21, 2026
Comment thread enzyme/Fortran/enzyme.f90 Outdated
Comment thread enzyme/test/Fortran/ReverseMode/function_like_procedure_pointer.f90
Comment thread enzyme/test/Fortran/ReverseMode/function_like.f90
Comment thread enzyme/Fortran/enzyme.f90 Outdated
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.
@isaacaka
isaacaka force-pushed the fortran_function_like branch from d6efe5c to 0e5f92e Compare September 22, 2026 19:13
@isaacaka
isaacaka added this pull request to the merge queue Sep 23, 2026
Merged via the queue into main with commit dea2b4e Sep 23, 2026
52 checks passed
@isaacaka
isaacaka deleted the fortran_function_like branch September 23, 2026 12:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fortran Related to Enzyme's Fortran bindings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants