Add dual-mode bigint to compaheuiler backends - #7
Conversation
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (19)
WalkthroughThe change adds width-aware CFG optimization, direct jump targets, floor arithmetic, Rust/C/WAT generators, BigInt runtimes, Cranelift runtime support, a shared CLI, and expanded integration tests with flexible fixture discovery. ChangesCompiler and backend expansion
Estimated code review effort: 5 (Critical) | ~120 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
1eb68e5 to
49661df
Compare
49661df to
85a5887
Compare
85a5887 to
2937965
Compare
There was a problem hiding this comment.
Actionable comments posted: 40
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
compaheuiler/src/cranelift_backend.rs (1)
426-501: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winDocument the
sp_ctxtype requirement in the public safety contract.With the
bigintfeature enabled,promote_executioncastsctx.sp_ctxto*mut SpecialStoragewhenever it is non-null.executeandexecute_bufferedare public and accept any*mut u8together with arbitrarysp_push/sp_popcallbacks. A caller that passes its own context object and its own callbacks compiles and runs today, then gets undefined behavior on the first arithmetic overflow.State the requirement in the
# Safetydocumentation of both public methods.📝 Proposed documentation change
/// Execute the JIT-compiled function. /// - /// `sp_ctx`: pointer to `SpecialStorage` (or null if unused). + /// # Safety + /// + /// `sp_ctx` must be a valid `*mut SpecialStorage` owned by this crate, + /// or null. The bigint promotion path dereferences it as + /// `*mut SpecialStorage`; any other context type is undefined behavior. /// `sp_push_fn` .. `sp_swap_fn`: callback function pointers for special storage ops.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@compaheuiler/src/cranelift_backend.rs` around lines 426 - 501, Update the public safety documentation for both execute and execute_buffered to state that, when bigint is enabled and sp_ctx is non-null, it must point to a valid SpecialStorage instance compatible with the supplied special-storage callbacks, including promote_execution’s expectations; callers must not provide an unrelated context or arbitrary callbacks.ahsembler/src/cfg_optimize.rs (1)
586-613: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
floor_div_i64wraps silently oni64::MIN / -1, and one of its two callers does not guard it. The helper useswrapping_div. For that pair the true quotient is2^63, which does not fiti64, and the remainder is0, so the sign correction never fires and the wrappedi64::MINis returned with no signal.ahsembler/src/compiler.rsLine 668 declines the fold withchecked_div. The CFG folder does not, so it writes a constant that disagrees with the run-time bigint result.
ahsembler/src/cfg_optimize.rs#L586-L613: addlhs.checked_div(rhs)?;before thefloor_div_i64call in theBinOpKind::Divarm, so the fold is declined fori64::MIN / -1. Add a test asserting that this pair does not fold underConstWidth::I64.ahsembler/src/consts.rs#L141-L161: document both preconditions onfloor_div_i64—b != 0, becausewrapping_divstill panics on a zero divisor, and(a, b) != (i64::MIN, -1), because that quotient wraps silently.
floor_mod_i64needs no guard: it returns0for that pair, which is correct.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@ahsembler/src/cfg_optimize.rs` around lines 586 - 613, Update eval_binop in ahsembler/src/cfg_optimize.rs (lines 586-613) to perform checked_div before floor_div_i64 in the BinOpKind::Div arm, declining the fold for i64::MIN / -1, and add a ConstWidth::I64 test covering that pair. Document floor_div_i64’s preconditions in ahsembler/src/consts.rs (lines 141-161): the divisor must be nonzero and the operands must not be (i64::MIN, -1); floor_mod_i64 requires no change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@ahsembler/src/cfg_linearize.rs`:
- Around line 216-225: Update the public linearize API documentation and
contract to state that input CFGs must contain only I32-width folded values,
including Push operands representable as i32. Keep the existing i32 conversion
behavior, but clearly document this precondition near linearize and ensure
callers understand unsupported I64 operands are not accepted.
In `@ahsembler/src/compiler.rs`:
- Around line 44-57: Make resolve_jump_targets genuinely idempotent by adding
explicit resolved-state tracking to the owning compiler type and returning early
when targets have already been rewritten. Update the method to mark that state
only after resolving jumps, and ensure any operation that replaces or rebuilds
labels/values resets it so newly generated programs are still resolved. Preserve
the existing label-to-PC conversion behavior.
In `@ahsembler/src/consts.rs`:
- Around line 141-161: Update the documentation for floor_div_i64 to explicitly
state that callers must ensure b is nonzero and must reject the overflowing pair
(i64::MIN, -1), since the helper does not enforce either precondition. Keep the
existing flooring semantics documentation and direct all callers to guard these
cases before invoking the helper.
In `@check.sh`:
- Around line 6-11: Update check.sh to resolve the snippet corpus in the same
order as common::snippets_dir(): use the initialized snippets submodule first,
then AHEUI_SNIPPETS, then rpaheui/snippets, and remove the redundant TESTS_DIR
variable. In compaheuiler/tests/common/mod.rs, retain the documentation claim
that resolution matches check.sh once aligned; no direct change is needed there.
In `@compaheuiler/Cargo.toml`:
- Line 13: Update the bigint feature in Cargo.toml to also enable the
malachite-bigint dependency, so the bigint,cranelift configuration provides the
BigInt implementation selected by cranelift_backend.rs while preserving the
existing num-traits dependency.
In `@compaheuiler/src/c_bigint_bridge.rs`:
- Around line 6-19: Address ownership of heap-allocated BigInt values produced
by normalize: implement an arena with lifecycle cleanup, or introduce
reference-counted handles with an explicit cbig_release invoked when C-runtime
slots are overwritten, while preserving Dup and Swap semantics. If retaining
intentional leaks instead, document the trade-off in the header comment and
specify a workload cap.
- Around line 74-84: Update the exported functions cbig_to_i64 and
cbig_write_num to check the value’s tag bit before dereferencing it as BigInt,
matching the existing C caller guard. For tagged immediates, return the
appropriate fallback from cbig_to_i64 and avoid emitting through cbig_write_num;
preserve current behavior for valid BigInt pointers.
- Around line 86-93: Update the generated manifest templates to declare
rust-version = "1.85" alongside edition = "2024". Apply this to every generated
manifest, not just the crate containing compaheuiler_c_entry, so all generated
crates expose the required MSRV.
In `@compaheuiler/src/c_bigint_runtime.c`:
- Around line 79-85: Protect all fixed-capacity writes in sp_push and sp_dup by
checking q_len against QUEUE_CAP and p_len against PORT_CAP before writing or
incrementing. On overflow, emit a diagnostic to stderr and terminate using the
established process-exit behavior, while preserving normal queue and port
operations within capacity.
- Around line 124-125: Update read_num to parse input with strtoll, using errno
and end-pointer validation to handle malformed text and overflow, then pass the
resulting value through promote_val rather than int_lit so arbitrary input
values remain correct in BigInt mode. Add the required errno include alongside
the existing headers, while preserving the zero result for failed input reads.
In `@compaheuiler/src/c_gen.rs`:
- Around line 47-54: Update c_bigint_dependency_toml to include the num-traits
dependency alongside the selected BigInt crate, ensuring the generated manifest
satisfies c_bigint_bridge_rs’s use of num_traits::ToPrimitive in both feature
branches.
In `@compaheuiler/src/cli.rs`:
- Around line 200-293: Replace predictable, attacker-controlled scratch paths in
compile_rs, compile_wat, compile_c, and compile_c_bigint with exclusive
randomized directory creation, following common::scratch_dir’s create-or-retry
pattern or equivalent create_dir behavior that fails on collisions. Ensure all
generated source, manifest, config, and build files remain inside the newly
owned directory, and do not reuse a shared /tmp CARGO_TARGET_DIR.
- Around line 56-70: Update BuildArgs::output_path to handle current_dir()
failure without calling unwrap; propagate or convert the error through the CLI’s
existing error-reporting path so users receive the standard “error: ...” message
instead of a panic. Adjust the method’s return type and its callers as needed
while preserving explicit output paths and the existing generated filename
behavior.
- Around line 208-231: Update the manifest construction in compile_rs to reuse
crate::c_bigint_dependency_toml() for the BigInt dependency instead of selecting
hardcoded num-bigint or malachite-bigint strings. Confirm the helper is
language-agnostic, then use its returned dependency line so generated Rust
runtime dependencies stay aligned with compile_c_bigint.
In `@compaheuiler/src/cranelift_backend.rs`:
- Line 1076: Rename the declared variable v_sp_ctx to v_runtime_ctx and update
every reference to it throughout the generated-function builder, including
emit_binop, emit_write_char, write_num, read callbacks, emit_is_zero, and
emit_to_i64 calls. Preserve its role as the ExecutionContext pointer passed to
runtime adapters.
- Around line 875-883: Replace the inline is_q/is_p/bor special-storage checks
in Inst::GuardDepth, Terminator::StackGuard, and Terminator::BranchZero with
calls to is_special_at_runtime, passing each site’s existing builder and
selector variable; preserve the surrounding guard and branch behavior.
- Around line 170-197: Bound the lifetime of boxed BigInt values created by
promote_value and normalize_big by tracking their allocations in
ExecutionContext and releasing them after func returns, or by using an
execution-owned arena with equivalent cleanup. Ensure cleanup covers values
retained in stacks, overwritten slots, popped values, and intermediate
arithmetic results while preserving the existing tagged small-integer fast path
and tagged_to_big behavior.
- Around line 666-672: Update the bigint mode load in the relevant backend
function to use std::mem::offset_of!(ExecutionContext, big_mode) instead of
hardcoded offset 0, matching emit_write_char. Replace the unused
Option<Variable> v_big_mode parameter and plumbing with a bool feature flag,
remove the Variable declaration, and preserve the existing discriminant-based
enablement behavior in emit_literal and the binary-op path.
- Around line 588-615: Update the BinOpKind::Div | BinOpKind::Mod branch in
emit_raw_binop to detect the (i64::MIN, -1) operands before executing srem or
sdiv. Return i64::MIN for Div and 0 for Mod for that pair, while preserving the
existing zero-divisor fallback and normal signed floor-division behavior for all
other inputs.
- Around line 744-755: Update the literal emission around the visible
`v_big_mode` handling so values outside SMALL_MIN..=SMALL_MAX use the same
boxing path as promote_value before tagging. Keep in-range literals on the
existing raw/tagged select path, and preserve the current runtime big-mode
selection for values that do not require boxing.
In `@compaheuiler/src/pipeline.rs`:
- Around line 10-15: Update optimize so OptimizationLevel::O0 builds the CFG
without invoking ahsembler::compile_to_cfg_aot or its embedded optimize_cfg_aot
baseline, preserving the documented raw, unoptimized output; keep the existing
AOT compilation and optimize_cfg flow for higher optimization levels.
In `@compaheuiler/src/rust_gen.rs`:
- Around line 1019-1020: Reduce startup allocation in the generated program
around the data and bases initialization by avoiding eager allocation and
zeroing of all 28 MAX_STACK-sized storage vectors. Prefer lazy per-storage
allocation, or size only storages identified by the generator’s existing used
set, while preserving valid pointers for every storage accessed by the generated
code.
- Around line 882-888: Update IntQueue::scan_to_zero to use the mode-aware zero
representation, matching Int::is_zero: compare queued values against tagged zero
in dual mode and raw zero otherwise. Also return the corresponding tagged Int
zero, and add the equivalent BM-aware handling in PRELUDE_INT_I64 where needed.
- Around line 701-710: Update the Terminator::Halt generation to read the exit
value from special storage when sel is QUEUE or PORT, matching the existing
StackGuard dynamic split and wat_gen.rs behavior; retain the bases-based logic
for ordinary stacks and the existing empty-storage fallback.
- Around line 1017-1042: Remove the duplicate MAIN_FN_DUAL constant and retain a
single shared MAIN_FN definition, since int_to_i64 already handles both result
modes through the respective prelude definitions. Update the generator branch
around the existing MAIN_FN_DUAL selection to use the shared MAIN_FN directly,
eliminating the redundant conditional while preserving dual-mode behavior.
- Around line 356-409: Update the bigint Add/Sub/Mul handling in Inst::BinOp for
the sp_known and ds special-storage paths so live Abs values retained on other
storages are promoted when arithmetic transitions _bm from false to true,
matching the existing live-variable fixup in the regular path. Reuse the
existing _bm/_bm_prev guard and promotion logic, or flush Abs before switching
storage, and add a regression test covering QUEUE/PORT arithmetic followed by a
register operation.
In `@compaheuiler/src/wat_gen.rs`:
- Line 273: Replace the unnecessary format allocation by passing ind directly to
emit_stack_push at all listed call sites, including the corresponding usage in
emit_terminator. Preserve the existing output and argument order while removing
every format!("{ind}") occurrence.
- Around line 779-816: Deduplicate the stack swap emitters by extracting the
shared value-load and store sequence from emit_stack_swap and
emit_stack_swap_dyn into a helper that assumes $addr is already initialized.
Keep each emitter responsible only for setting $addr via its existing
constant-offset or tops_get_dyn path, then invoke the helper; apply the same
extraction pattern to emit_stack_dup and emit_stack_dup_dyn.
- Around line 1249-1274: Update the WASI input flow around `$read_num` and
`$read_char` to use a shared persistent stdin buffer, with globals tracking the
buffer fill length and current read position. Refill via `$fd_read` only when
the read position reaches the fill length, and advance the shared position as
bytes are consumed so leftover bytes remain available to subsequent calls.
Ensure both readers use the same buffering helpers and preserve existing number
and character parsing behavior.
- Around line 1077-1084: Update the port branch of $sp_dup to read and re-push
the actual top value from port storage at p_len - 1 instead of using PORT_LAST.
Remove the now-unnecessary PORT_LAST dependency for this operation while
preserving the existing p_len increment and matching dup semantics used by the
other backends.
- Around line 1257-1262: The `$read_num` whitespace-skipping logic accepts only
spaces and line feeds, so tabs and carriage returns fail parsing. In
compaheuiler/src/wat_gen.rs:1257-1262, widen the WASI predicate to accept byte
32 and bytes 9–13; apply the identical change in
compaheuiler/src/wat_gen.rs:1309-1353 for the non-WASI variant. Emit this
predicate through one shared helper used by both `$read_num` variants so their
behavior remains synchronized.
- Around line 676-698: The WAT backend must enforce capacity consistently for
stack and queue pushes. In compaheuiler/src/wat_gen.rs lines 676-698, update
emit_stack_push and emit_stack_push_dyn to check the current top against
storage_base(s) plus STORAGE_SIZE before i64.store, trapping or reporting an
error when full. In compaheuiler/src/wat_gen.rs lines 986-999, update $sp_push
to check q_len against QUEUE_CAP before calculating idx or incrementing q_len.
Use the same overflow policy at both sites.
- Around line 1119-1127: Replace the format! wrapper around the raw WebAssembly
stub string in the surrounding output-generation function with a direct push_str
call. Preserve the stub contents and formatting exactly, since no interpolation
is required.
- Around line 24-26: Update the module’s declared memory pages near the memory
declaration to use 225 pages instead of 224, ensuring the final storage region
returned by storage_base fits within linear memory. Keep STORAGE_BASE,
STORAGE_SIZE, and QUEUE_CAP unchanged.
- Around line 1135-1144: Update the $flush_out function to retain and check the
fd_write result, repeatedly writing the remaining buffer until $nwritten reaches
the original $out_pos. Adjust the iovec pointer and length for each short write,
stop immediately when fd_write returns a non-zero errno, and reset $out_pos only
after all bytes are written successfully.
- Around line 551-573: In the StackGuard generation logic, collapse the
branching around `sel` into two cases: use the static depth calculation when
`sel.is_some()`, otherwise emit the `$depth_dyn` call. Remove the redundant
`has_special` condition and its parameter from the relevant function, then
update the caller at the `StackGuard` invocation to stop passing that argument.
- Around line 76-106: Remove the unused has_io and has_dyn_sel scans, their
call-site arguments, and corresponding unused parameters in the surrounding
generator function. Simplify the live-block state checks to use is_none_or for
bottom or missing states and is_some_and for selected-state checks, preserving
existing behavior.
In `@compaheuiler/tests/common/mod.rs`:
- Around line 1-12: Correct the module documentation’s resolution-order
statement near the fixture-path explanation: remove the claim that it matches
check.sh, or update check.sh to use the same candidate order as the helper.
Preserve the documented distinction between the snippets submodule,
AHEUI_SNIPPETS, and the sibling checkout.
In `@compaheuiler/tests/cranelift_test.rs`:
- Around line 45-47: Update run_cranelift_with_num to recover from a poisoned
RUN_LOCK using the same lock-recovery pattern as bigint_test.rs, rather than
unwrapping the lock result. Apply the same recovery handling to every STDOUT_BUF
lock site so later tests report their own assertion failures instead of
cascading on poison errors.
In `@compaheuiler/tests/floored_division_test.rs`:
- Around line 261-333: Update cranelift_aot_uses_floored_division_and_remainder
so cases with Some(case.wide_input) run only when the bigint feature is enabled;
under not(feature = "bigint"), skip those wide cases while continuing to run the
regular i64 cases. Match the existing WAT test’s feature-gating behavior without
changing compilation or assertions for supported cases.
---
Outside diff comments:
In `@ahsembler/src/cfg_optimize.rs`:
- Around line 586-613: Update eval_binop in ahsembler/src/cfg_optimize.rs (lines
586-613) to perform checked_div before floor_div_i64 in the BinOpKind::Div arm,
declining the fold for i64::MIN / -1, and add a ConstWidth::I64 test covering
that pair. Document floor_div_i64’s preconditions in ahsembler/src/consts.rs
(lines 141-161): the divisor must be nonzero and the operands must not be
(i64::MIN, -1); floor_mod_i64 requires no change.
In `@compaheuiler/src/cranelift_backend.rs`:
- Around line 426-501: Update the public safety documentation for both execute
and execute_buffered to state that, when bigint is enabled and sp_ctx is
non-null, it must point to a valid SpecialStorage instance compatible with the
supplied special-storage callbacks, including promote_execution’s expectations;
callers must not provide an unrelated context or arbitrary callbacks.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 350b7bae-ea83-482e-bd39-777f9215cf70
📒 Files selected for processing (30)
ahsembler/src/cfg_linearize.rsahsembler/src/cfg_optimize.rsahsembler/src/compiler.rsahsembler/src/consts.rsahsembler/src/lib.rsahsembler/src/rgen.rsahsembler/src/stackify.rscheck.shcompaheuiler/Cargo.tomlcompaheuiler/src/c_bigint_bridge.rscompaheuiler/src/c_bigint_runtime.ccompaheuiler/src/c_gen.rscompaheuiler/src/cli.rscompaheuiler/src/cranelift_backend.rscompaheuiler/src/lib.rscompaheuiler/src/main.rscompaheuiler/src/pipeline.rscompaheuiler/src/rgen.rscompaheuiler/src/rust_gen.rscompaheuiler/src/wat_gen.rscompaheuiler/tests/all_snippets_test.rscompaheuiler/tests/bigint_test.rscompaheuiler/tests/cgen_test.rscompaheuiler/tests/codegen_debug.rscompaheuiler/tests/common/mod.rscompaheuiler/tests/cranelift_test.rscompaheuiler/tests/floored_division_test.rscompaheuiler/tests/quine_test.rscompaheuiler/tests/rgen_test.rscompaheuiler/tests/snippets_test.rs
💤 Files with no reviewable changes (3)
- ahsembler/src/rgen.rs
- ahsembler/src/stackify.rs
- compaheuiler/src/rgen.rs
| /// Rewrite `values[pc]` for every jump op so it carries the target PC | ||
| /// instead of a label id. Idempotent — once resolved, target PCs are | ||
| /// already valid PCs (in `0..size`) and re-running the pass keeps | ||
| /// them unchanged. | ||
| pub fn resolve_jump_targets(&mut self) { | ||
| for pc in 0..self.size { | ||
| if is_jump_op(self.opcodes[pc]) { | ||
| let label_id = self.values[pc]; | ||
| if let Some(&target_pc) = self.labels.get(&label_id) { | ||
| self.values[pc] = target_pc as i32; | ||
| } | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
resolve_jump_targets is not idempotent; label IDs and PCs share one numeric space.
serialize creates label IDs from lines.len() (Line 243 and Line 278), so a label ID is numerically a line index. Program counters are also line indices. The two spaces overlap.
After the first pass, values[pc] holds a target PC. A second pass looks up self.labels.get(&target_pc). If that PC value also exists as a label ID, the pass rewrites the operand again and the jump goes to the wrong target. The rewrite is silent.
The current call sites run the pass once per program, so no defect is observable today. The doc comment states a guarantee the code does not provide, and the method is public on a public type.
Record the resolved state instead of relying on the value space, or correct the doc comment to state the single-call precondition.
🛡️ Proposed fix: track the resolved state
pub struct Program {
pub opcodes: Vec<u8>,
pub values: Vec<i32>,
pub labels: HashMap<i32, usize>,
pub size: usize,
+ /// Set once `resolve_jump_targets` has rewritten jump operands to PCs.
+ pub jump_targets_resolved: bool,
} pub fn resolve_jump_targets(&mut self) {
+ if self.jump_targets_resolved {
+ return;
+ }
for pc in 0..self.size {
if is_jump_op(self.opcodes[pc]) {
let label_id = self.values[pc];
if let Some(&target_pc) = self.labels.get(&label_id) {
self.values[pc] = target_pc as i32;
}
}
}
+ self.jump_targets_resolved = true;
}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@ahsembler/src/compiler.rs` around lines 44 - 57, Make resolve_jump_targets
genuinely idempotent by adding explicit resolved-state tracking to the owning
compiler type and returning early when targets have already been rewritten.
Update the method to mark that state only after resolving jumps, and ensure any
operation that replaces or rebuilds labels/values resets it so newly generated
programs are still resolved. Preserve the existing label-to-PC conversion
behavior.
What
i64path until overflow, then promote to Rust'smalachite-bigintcompaheuiler/check.shand thetestssymlink with environment/relative pathsWhy
Rust already had complete dual-mode bigint semantics, but C and Cranelift did not. Rust's fast path also paid unnecessary snapshot-copy overhead even when no value promoted. This brings the same promote-on-overflow behavior to all native AOT backends while keeping ordinary
i64workloads fast.The PR history is a single commit whose snapshot contains no
al03219714,/Users/..., or/home/...paths. The lateraheui-jitimplementation work is not included.Performance
On the local logo benchmark, optimized Rust improved from about 90.1 ms to 65.4 ms; C measured about 64.4 ms. Factorial remains on the unpromoted
i64path. Overflow workloads preserve matching output across Rust, C, and Cranelift.Validation
cargo fmt --all -- --checkcargo check -p compaheuiler --features craneliftcargo clippy -p compaheuiler --all-targets --features cranelift -- -D warningscargo test -p compaheuiler --features cranelift -- --test-threads=1bash -n check.shThe two compiler crates were validated in an isolated workspace with the same naive interpreter for reference-output comparisons. The current
mainworkspace cannot be loaded as-is because its pre-existingaheui-jitmanifest points to the absent../../majit/majit-codewriter;mainalso has nodynasmfeature.Summary by CodeRabbit
New Features
Improvements
Bug Fixes