Update README with additional example use
diff --git a/enzyme/Fortran/README.md b/enzyme/Fortran/README.md
index 5525d23..0402e70 100644
--- a/enzyme/Fortran/README.md
+++ b/enzyme/Fortran/README.md
@@ -103,7 +103,7 @@
 then you can make use of activity descriptors like so:
 ```fortran
   call enzyme_autodiff(my_subroutine, enzyme_const, n, &
-                       enzyme_dup, x, dx, enzyme_dup, y, dy
+                       enzyme_dup, x, dx, enzyme_dup, y, dy)
 ```
 
 ## Function hook for batching
@@ -130,8 +130,20 @@
 
 The `enzyme_function_like` hook tells Enzyme to differentiate a function as if
 it were a known mathematical function. For example, Enzyme can use the
-derivative of `log1p` for `log1p_like_function`, regardless of its
-implementation.
+derivative of `log1p` for `double_value`, regardless of its
+implementation. The examples below deliberately compute `2*x` while requesting
+the derivative of `log1p`: at `x = 2`, Enzyme returns `1/3` instead of `2`. This
+illustrates a derivative override; the two functions are not mathematically
+equivalent.
+
+### Choose a registration form
+
+| Function location and interface | When to use each form |
+|---|---|
+| Module function | Use a pointer declaration before the module's `contains` to keep registration with the function. The compiler supplies its explicit interface. A registration call in executable code also works. |
+| External function with an explicit interface | Put the pointer declaration after the interface block in the declaration section. A registration call in executable code also works. |
+| Internal function | Use call registration only if Flang supplies a direct function reference. Access to variables from the containing program or procedure can prevent registration. See the restriction below. The current pointer mechanism cannot register an internal function. |
+| External function with an implicit interface | Use `procedure(real)` for an ordinary pointer to a function with a real result. For scalar math registration, provide the required value arguments and an explicit interface. |
 
 ### Call-style registration
 
@@ -140,9 +152,33 @@
 ```fortran
 use enzyme, only: enzyme_function_like, enzyme_log1p
 
-call enzyme_function_like(log1p_like_function, enzyme_log1p)
+call enzyme_function_like(double_value, enzyme_log1p)
 ```
 
+Put the registration call in executable code, after declarations. For an
+internal function, you must use this form instead of an initialized procedure
+pointer. An internal function follows `contains` inside a program or another
+procedure. The compiler supplies its explicit interface.
+
+The [call-style test](../test/Fortran/ReverseMode/function_like.f90) shows this
+placement. Its registration call is in the main program. Its target function,
+`double_value`, is inside that program, after `contains`.
+
+> [!WARNING]
+> Call registration does not support all internal functions. An internal
+> function can access variables from its containing program or procedure.
+> Fortran calls this access **host association**. For example, `double_value`
+> could calculate `factor * x`, where `factor` is a variable in the containing
+> procedure.
+>
+> Flang can then generate an adapter that gives the function access to those
+> variables. The current registration code requires a direct function reference.
+> It cannot process this adapter, and compilation can fail with
+> `First argument of enzyme_function_like must be a constant function`.
+>
+> The example above uses only the argument `x` and does not need this adapter.
+
+
 Here `enzyme_log1p` supplies the symbolic function name `log1p`; its value is not
 used. Functions passed to `enzyme_function_like` must have an LLVM-level
 signature compatible with the selected mathematical function. Scalar arguments
@@ -167,48 +203,220 @@
 compiler plugin runs `preserve-nvvm` at the start of Flang's LLVM optimization
 pipeline and does not require this separate `opt` step.
 
-Additional symbolic function names can be declared in user code. The `bind(C)`
-name must use the `enzyme_math_` prefix followed by a function name recognized
-by Enzyme:
+The `enzyme` module exports these symbolic names. Import the required names
+with `use enzyme, only: ...`.
+
+| Function group | Bindings |
+|---|---|
+| Trigonometric functions | `enzyme_sin`, `enzyme_cos`, `enzyme_tan`, `enzyme_asin`, `enzyme_acos`, `enzyme_atan`, `enzyme_atan2` |
+| Exponential functions | `enzyme_exp`, `enzyme_exp2`, `enzyme_exp10`, `enzyme_expm1` |
+| Logarithms | `enzyme_log`, `enzyme_log2`, `enzyme_log10`, `enzyme_log1p` |
+| Inverse hyperbolic functions | `enzyme_acosh`, `enzyme_asinh`, `enzyme_atanh` |
+| Roots and powers | `enzyme_sqrt`, `enzyme_cbrt`, `enzyme_hypot`, `enzyme_pow` |
+| Error functions | `enzyme_erf`, `enzyme_erfc` |
+
+For example, use `enzyme_sin` to register a function with the `sin` rule:
+
+```fortran
+use enzyme, only: enzyme_function_like, enzyme_sin
+
+call enzyme_function_like(my_sin, enzyme_sin)
+```
+
+You can declare other symbolic names in user code. Use the `enzyme_math_`
+prefix followed by a function name that Enzyme supports:
 
 ```fortran
 module enzyme_math_names
   use iso_c_binding, only: c_int
   implicit none
 
-  integer(c_int), bind(C, name="enzyme_math_sin") :: enzyme_sin
+  integer(c_int), bind(C, name="enzyme_math_fmin") :: enzyme_fmin
 end module enzyme_math_names
 ```
 
-This makes the call site simple, but every symbolic name needs a corresponding
-`enzyme_math_*` binding, either in the `enzyme` module or in user code.
+Each symbolic name needs an `enzyme_math_*` binding in the `enzyme` module
+or in user code.
 
 ### Procedure-pointer registration
 
 Alternatively, a statically initialized procedure pointer can register the
-same relationship without a hook call or symbolic-name binding:
+same relationship without a hook call or symbolic-name binding. Enzyme reads
+and removes the registration marker at compile time. Do not call through the
+registration pointer. Enzyme replaces remaining references to the marker with
+null pointers. Call the target function directly, for example, `double_value(x)`.
+Use the same FlangEnzyme plugin or separate `opt` pipeline described above for
+call-style registration.
+
+#### Register a module function
+
+Place the declaration before the module's `contains` statement. Unlike a
+`call`, a procedure-pointer declaration is allowed in this part of a module.
 
 ```fortran
 module function_like_example
   implicit none
 
-  procedure(log1p_like_function), pointer, private :: &
-    fn__enzyme_function_like__log1p => log1p_like_function
+  procedure(double_value), pointer, private :: &
+    fn__enzyme_function_like__log1p => double_value
 
 contains
 
-  function log1p_like_function(x) result(y)
-    double precision, value :: x
-    double precision :: y
+  function double_value(x) result(y)
+    real, value :: x
+    real :: y
 
-    y = 2.0d0 * x
-  end function log1p_like_function
+    y = 2.0 * x
+  end function double_value
+
+  function test(x) result(y)
+    real, intent(in) :: x
+    real :: y
+
+    y = double_value(x)
+  end function test
+
 end module function_like_example
+
+program main
+  use enzyme, only: enzyme_autodiff
+  use function_like_example, only: test
+  implicit none
+  real :: x, dx
+
+  x = 2.0
+  dx = 0.0
+  call enzyme_autodiff(test, x, dx)
+  write(*,"(f6.4)") dx ! Prints 0.3333
+end program main
 ```
 
-Here, `procedure(log1p_like_function)` gives the pointer the target's interface,
-and `=> log1p_like_function` initializes it with the target. PreserveNVVM reads
+Here, `procedure(double_value)` gives the pointer the target's interface,
+and `=> double_value` initializes it with the target. PreserveNVVM reads
 the mathematical name after the exact `__enzyme_function_like__` delimiter, so
 this example registers the target as `log1p`. The prefix before the delimiter
-can be any valid name but must be unique in its scope. `private` is optional; it
-keeps the registration marker out of the module's public API.
+can be any valid name but must be unique in its scope. `private` is optional
+in a module; it keeps the registration marker out of the module's public API.
+
+The `test` wrapper takes its argument by reference for the `enzyme_autodiff`
+binding, while `double_value` takes its argument by value to match the scalar
+`log1p` rule.
+
+#### Register an external function with an explicit interface
+
+An external function is defined outside any program, module, or other procedure.
+It can be in the same source file as its caller.
+
+Use an explicit interface when the function has a `value` argument, as required
+by the scalar math rules shown here. Put the pointer declaration after the
+interface block, before executable statements. Omit `private` outside a module.
+
+In this example, `double_value` follows `end program main`. Its interface block
+describes its value argument and result.
+
+```fortran
+program main
+  use enzyme, only: enzyme_autodiff
+  implicit none
+
+  interface
+    function double_value(x) result(y)
+      real, value :: x
+      real :: y
+    end function double_value
+  end interface
+
+  procedure(double_value), pointer :: &
+    fn__enzyme_function_like__log1p => double_value
+
+  real :: x, dx
+
+  x = 2.0
+  dx = 0.0
+  call enzyme_autodiff(test, x, dx)
+  write(*,"(f6.4)") dx ! Prints 0.3333
+
+contains
+
+  function test(x) result(y)
+    real, intent(in) :: x
+    real :: y
+
+    y = double_value(x)
+  end function test
+
+end program main
+
+function double_value(x) result(y)
+  implicit none
+  real, value :: x
+  real :: y
+
+  y = 2.0 * x
+end function double_value
+```
+
+Keep the explicit interface consistent with the external function definition.
+The internal `test` wrapper is allowed here because the initialized pointer
+targets the external `double_value`, not `test`.
+
+#### External function with an implicit interface
+
+A simple external function with scalar arguments passed by reference can use
+an implicit interface. Use this form for ordinary Fortran pointer calls when
+the function has no features that require an explicit interface.
+
+```fortran
+program main
+  implicit none
+  real, external :: double_value
+  procedure(real), pointer :: p => double_value
+
+  print *, p(3.0) ! Prints 6
+end program main
+
+real function double_value(x)
+  implicit none
+  real, intent(in) :: x
+
+  double_value = 2 * x
+end function double_value
+```
+
+Here, `procedure(real)` specifies a real result but does not describe the
+arguments. The pointer therefore has an implicit interface. Use
+`procedure(double_value)` only when an explicit interface for `double_value`
+is available.
+
+This example shows an ordinary pointer call. It does not register a math rule.
+Its by-reference argument does not match the scalar `log1p` interface. To register
+this function as `log1p`, give its argument the `value` attribute. Then provide
+the explicit interface and registration declaration from the preceding example.
+Changing the argument to `value` changes the calling convention. Update the
+interfaces at all call sites and recompile the callers.
+
+#### Register a module function from a subroutine
+
+The declaration can instead appear in a subroutine's declaration section,
+before executable statements. For example, remove the module-level registration
+from `function_like_example` above and add this subroutine alongside its
+`double_value` and `test` functions:
+
+```fortran
+subroutine differentiate(x, dx)
+  use enzyme, only: enzyme_autodiff
+  implicit none
+  real, intent(in) :: x
+  real, intent(inout) :: dx
+
+  procedure(double_value), pointer :: &
+    fn__enzyme_function_like__log1p => double_value
+
+  call enzyme_autodiff(test, x, dx)
+end subroutine differentiate
+```
+
+The main program can then import `differentiate` and call
+`differentiate(x, dx)` with `x = 2.0` and `dx = 0.0`. The result is again
+`0.3333`. The registration remains a compile-time annotation, not a runtime
+switch local to this subroutine.