Repository navigation
feat(cl): automatic detection of forwarding macros - #1110
Conversation
Add always-on automatic detection for function-like macros whose body is a
single plain forwarding call to a generated function. Such a macro is turned
into an ordinary Go function that calls the callee directly, filling in the
constant arguments, with no C wrapper and no //go:linkname.
A macro qualifies when: its body is one call to a non-variadic function llcppg
generates (the callee, inferred from the body); every argument is either one of
the macro's own parameters or a compile-time constant (a value llcppg evaluates,
or sizeof(T) over a complete generated type, optionally scalar-cast); and every
macro parameter is passed exactly once. Macros that fail any rule are silently
skipped (logged in verbose mode) and can still be handled explicitly. A macro
listed in MacroFunc is always wrapped and never reinterpreted by detection.
Parameter types come from the callee prototype, the return type is the callee's,
constants are evaluated and emitted inline (c.Str for strings), and sizeof(T) is
routed through unsafe.Sizeof(T{}) so the size is computed per target platform.
Name collisions with existing symbols are skipped with a warning.
See #1109.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1110 +/- ##
==========================================
+ Coverage 90.26% 90.48% +0.21%
==========================================
Files 26 26
Lines 3278 3437 +159
==========================================
+ Hits 2959 3110 +151
- Misses 319 327 +8
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Overall this is a well-structured and thoroughly documented feature. The deferral design (running the autoMacros pass after compiles so every callee's Go declaration is already recorded) is the right fix for the callee-availability ordering, the token-level parsing is largely defensive, and the test fixture covers the important accept/reject cases (sizeof, opaque/zero-field type, double-use, conditional body). Restricting compiledFns recording to Cursor_FunctionDecl to exclude the synthetic macro-wrapper overload, and the unsafe.Sizeof workaround for the llgo toolchain, are both subtle points that are well commented.
A few findings below are worth addressing before merge — one confirmed resource leak, one confirmed nil-dereference panic path, and a method-callee robustness gap — plus some minor cleanups. All findings are code-quality / robustness / doc-accuracy; I did not find a behavioral bug in the happy-path generation itself.
Note: I could not run go test ./cl/... in this environment because the package links against the llgo toolchain (the same reason the unsafe.Sizeof eager-evaluation workaround exists), so findings are from static analysis of the diff and surrounding code.
Requested by @xushiwei
Closes #1109.
Implements automatic detection of forwarding macros, as proposed in #1109. Function-like macros whose body is a single plain forwarding call are recognized on their own, their reference function is inferred, and they are emitted as ordinary Go functions — no C wrapper and no configuration.
What it does
A function-like macro not listed in
MacroFuncis turned into a Go function when all of these hold:ZLIB_VERSION, casts/arithmetic over them), orsizeof(T)over a complete generated type (optionally scalar-cast).Macros that fail any rule are silently skipped (logged in verbose mode) and can still be handled explicitly via
MacroFunc. A macro listed inMacroFuncis always wrapped and never reinterpreted.Semantics
void→ no result, bare call).c.Str("...").sizeof(T)is routed throughunsafe.Sizeof(T{})(converted to the cast type or the callee's parameter type) so the size is computed by the Go compiler per target platform. Incomplete/opaque types (which llcppg would emit as empty Go structs) are rejected, so such macros are skipped.Implementation
cl/macrofunc_auto.go— detection driver, argument classification, and Go function generation.cl/macrofunc_auto_parse.go— token-level parsing of the macro body (forwarding-call shape,sizeof, constant/type resolution); no preprocessor expansion, so the rules stay syntactic.MacroFuncdoc comments inclandtoolupdated.Tests
New fixture
cl/_testc/macrofn_autocovers: method and package-function callees,voidreturn, string/numeric/constant-macro/sizeofarguments, callee-doc fallback, and the skip paths (parameter used twice, non-single-call body,sizeofover an incomplete type). The explicitMacroFuncpath (z_gzgetc→ C wrapper) is exercised alongside, confirming explicit entries are not reinterpreted.Full
llgo test ./cl/... ./tool/...passes; the generated output type-checks.