Function pointer - #178
Open
hei411 wants to merge 16 commits into
Open
Conversation
hei411
marked this pull request as draft
July 22, 2026 18:55
hei411
force-pushed
the
heili/func-pointer
branch
from
July 23, 2026 21:05
c6fa059 to
cf6754e
Compare
hei411
marked this pull request as ready for review
July 23, 2026 22:40
gebner
requested changes
Jul 23, 2026
hei411
marked this pull request as draft
July 23, 2026 22:46
Squashed 22 commits from heili/func-pointer for a clean rebase onto main. Adds func_pointer/ examples, Pulse.Lib.C.FuncPtr.fsti, and emitter/IR support for function pointers (typedefs, args, null, is_valid, struct fields, _old on pointer args). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 89e3053b-4388-4455-895e-3f3b624594f1
PAL now emits every function as `divergent fn` (stt_div) unless `_total`. Extend the FuncPtr library, emitter, and tests so function pointers track whether their target may diverge. - fsti: add a `div: bool` bit to valid/is_valid; add of_fn_div/ of_fn_div_valid and call_div; extend weaken with a `div ==> div'` refinement (allows total->divergent, forbids the reverse). - emit.rs: pick of_fn vs of_fn_div by target totality, emit the __fp wrapper as `fn`/`divergent fn` by the function's totality, and emit call vs call_div by the enclosing body's totality. - func_pointer.c: migrate all annotations to the div-aware API; add add_t (_total), use_total_fp (total pointer), and weaken_total_to_div (total->divergent weakening); refresh comments. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 89e3053b-4388-4455-895e-3f3b624594f1
hei411
force-pushed
the
heili/func-pointer
branch
from
July 24, 2026 05:38
5a2cc31 to
e35e276
Compare
hei411
marked this pull request as ready for review
July 24, 2026 05:52
gebner
requested changes
Jul 27, 2026
gebner
left a comment
Contributor
There was a problem hiding this comment.
The basics look great, thank you!
I think we went a bit too fast on some more advanced features (like the ptr_arg_cb test). Let's shelve those for now, and do more design work so that they work more smoothly.
Function pointers are a tangential feature in C. Supporting function pointers shouldn't change or complicate the way we translate every function. We should only pay the price when they're used, also in the PAL emit module.
Move the function-pointer triple (func_<g>_pre / _post / __fp) out of the
function's own Func_<g> module into a dedicated Funcptr_<g> module.
- Add funcptr_module_name(g) helper and register the triple names under
Funcptr_<g> in build_fn_module_map so emit_name auto-qualifies all
triple and spec references (of_fn, is_valid, etc.). The base func_<g>
stays in Func_<g>.
- emit_multifile now emits the triple as a standalone PendingModule
(.fst + .fsti); the wrapper body qualifies Func_<g>.func_<g>.
- Re-point the hand-written inline-Pulse escape hatches in
test/func_pointer/func_pointer.c from Func_<g>.func_<g>_{pre,post,__fp}
to Funcptr_<g>.*.
Gating is unchanged: only address-taken functions get a triple.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: e8f4a381-e050-4a8b-88b6-7181b3a74435
Stop generating named `func_<g>_pre`/`_post` slprops. Instead inline the pre/post directly into the `func_<g>__fp` wrapper's requires/ensures and recover them generically from the wrapper's type via new library projectors. - pulse/Pulse.Lib.C.FuncPtr.fsti: add `[@@pulse_eager_unfold] unfold let` projectors `pre_of`/`post_of` (over `stt_div`) and `pre_of_tot`/ `post_of_tot` (over `stt`). `unfold` is required so they reduce in F*'s SMT VCs, not just Pulse slprop matching. - src/pass/emit.rs: `emit_fnptr_spec_core`/`emit_fnptr_triple` inline the pre/post into the wrapper (no more `func_<g>_pre`/`_post` defs); `emit_of_fn` uses `of_fn[_div] (pre_of[_tot] ..) (post_of[_tot] ..) func_<g>__fp`, choosing the `_tot` variant when the function is `_total`. Drop the now-dead `_pre`/`_post` module-map entries and name helpers. - test/func_pointer/func_pointer.c: rewrite hand-written `_pre`/`_post` references to the projector form (`_tot` for the total `add_t`); switch four `Reassign_join_spec` identity coercions from explicit `rewrite` to empty bodies, which succeed via `pulse_eager_unfold`. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: e8f4a381-e050-4a8b-88b6-7181b3a74435
The emitter special-cased storing a function pointer into an array slot by let-binding the value to a temporary (__pal_arrwr) before array_write, keeping the array spec update over a small variable so the array_spec_upd_* SMTPats would fire. This was ad hoc, so remove it and always inline the value. Consequently, the four func_pointer test functions that store a function pointer into an array element (assign_from_agg, use_array_slot, array_runtime_idx, multilayer) no longer verify: the inlined of_fn_div (pre_of __fp) (post_of __fp) __fp value makes array_spec_upd s i v too large for the array_spec_upd_* SMTPats to fire, so the read-back cannot prove array_spec_mask/array_spec_initd nor recover the stored pointer. Raising z3rlimit does not help (verified: fails identically at 50 and 300) -- it is a trigger/matching problem, not a resource-budget one. Comment those functions out with an explanatory note until a library-level fix is done. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: e8f4a381-e050-4a8b-88b6-7181b3a74435
Several comments still referred to the generated `func_<g>_pre`/`func_<g>_post` slprop definitions, which were removed when fnptr pre/post moved to the inlined `pre_of`/`post_of` projectors (commit 74ed5e0). Update them to describe the current design (inlined pre/post spliced into the `func_<g>__fp` wrapper): - funcptr_module_name / collect_addr_taken / FnPtrSpecCore / FnRef / emit_of_fn doc comments. - The `req ==> ens` rationale now references the inlined post slprop. - Remove a dangling, mis-attached doc comment (a leftover from a removed fnptr param-map field) that was wrongly documenting `fnptr_diverged`. Comment-only changes; no emitted output changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: e8f4a381-e050-4a8b-88b6-7181b3a74435
The `FnRef` variant doc still described the deep-model value as `of_fn func_<name>_pre func_<name>_post func_<name>__fp`, referencing the removed generated pre/post defs. Update to the current `of_fn (pre_of func_<name>__fp) (post_of func_<name>__fp) func_<name>__fp`. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: e8f4a381-e050-4a8b-88b6-7181b3a74435
Function-pointer arguments are now always emitted as plain values. Pointer arguments keep their default `pts_to` permission (via the general `emit_type_slprop` lowering), but the initial-pointee value is no longer threaded through the FuncPtr domain, so a callee's relational `_old(*p)` contract can no longer be expressed across an indirect call. emit.rs: - emit_fnptr_arg_tuple emits one plain component per argument. - fnptr_domain_with_old replaced by plain fnptr_domain. - emit_fnptr_spec_core drops the old-value domain component, the subst/binder machinery, the FnptrPtrSubst activation, and the pinned old/cur pts_to block; pointer params fall through to the general path. - Removed dead infra: FnptrPtrSubst, PtrValNames, ownership_ptr_pointee, the fnptr_ptr_subst field, set_fnptr_phase, and the guarded *p / _old(*p) resolution branches. test/func_pointer: disable ptr_arg_cb (unsupported _old across a FuncPtr); keep inc as a normal _old function (no longer address-taken). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: e8f4a381-e050-4a8b-88b6-7181b3a74435
gebner
reviewed
Jul 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adding function pointers to PAL
We axiomatize the behavior of function pointer in
pulse/Pulse.Lib.C.FuncPtr.fsti, e.g.validandis_validdescribes the spec of the function pointerweakenallows us to relax the speccallapplies the function pointer with argumentsFuture work: