You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Encode reverse-mode early returns with a named lambda
The reverse-mode early-return encoding emitted a label inside the master
reverse and a goto into it from each early-return point. That violates
[stmt.dcl]/2 whenever a local with a non-trivial initializer or
destructor sits between the goto and its target, which is why
DifferentiateWithClad had to bypass Sema::ActOnFinishFunctionBody on the
generated function.
Materialise the master reverse as a `[&]` lambda bound to an `auto`
VarDecl instead, called at each early return and at the tail. The body
is assembled outside the closure scope, so its references to captured
variables are rebuilt in scope where the `[&]` default registers the
capture; the reverse statements are emitted into the closure directly. An
early return is a NullStmt marker in the forward block, patched with
`{ _rev(); return; }` at finalization so no subtree gains a second parent.
Whether a function has a non-tail return is a fact about the primal, so
DiffRequest answers hasEarlyReturns() off the primal body; the encoder
reads it to pick the lambda vs plain shape up front. A branch condition
read by the master reverse is zero-initialized so an early return that
skips its forward store leaves it false -- the same zero-initialized
additive state clad already relies on for adjoints and loop counters.
A return inside a switch case is an early return too: it closes that
case's fall-through group so the reverse switch -- rebuilt on the stored
condition -- enters only that case's adjoint. The synthesized closure
makes Clang's own exception-handling codegen (EHScopeStack landing pad)
read an uninitialized value under Valgrind on some runtimes; the read is
inside libclang, not clad, and the derivative is correct, so
EarlyReturns.C is XFAILed under Valgrind like the other switch/loop tests.
Fixes#367
0 commit comments