5
2
Fork
You've already forked lightening
2

Fix register dependency resolution in JIT calls #2

Open
h-c-mueller wants to merge 2 commits from h-c-mueller/lightening:fix_move_one into main
pull from: h-c-mueller/lightening:fix_move_one
merge into: guile:main
guile:main
guile:reinterpret
guile:callr-fix3
First-time contributor
Copy link
When preparing arguments for a function call, the JIT must detect and
resolve dependencies (cycles) between registers. This occurs when,
for example, the value for the first argument is currently in the
register that should hold the second argument, and vice-versa.
The logic incorrectly used the register's 'kind' (the register class)
instead of its 'abi' (the specific data type/width) to identify the
source operand. This caused the dependency solver to fail or emit
incorrect moves on 64-bit platforms where floating-point arguments
are passed in registers.
This issue is "masked" on 32-bit x86 (IA32) because it primarily
uses the stack for passing double-precision arguments, avoiding
register-to-register swaps for the ABI registers.
The fix has been verified by adjusting 'tests/call_10_2.c' to force
a register swap (F0/F1). Formerly the modified test failed on:
- Linux x86_64 (System V ABI)
- Linux aarch64
- Windows 64-bit (Microsoft x64 ABI) via Cygwin, MINGW64, UCRT64,
 and CLANG64.
* lightening/lightening.c (prepare_args): Use 'src[j].abi' instead of
 'src[j].kind' when resolving register-to-register dependencies.
* tests/call_10_2.c (run_test_double): Swap the order in which dargs[0]
 and dargs[1] are loaded into registers F0 and F1. This forces a
 register cycle during the call, exposing the dependency resolution bug.
``` When preparing arguments for a function call, the JIT must detect and resolve dependencies (cycles) between registers. This occurs when, for example, the value for the first argument is currently in the register that should hold the second argument, and vice-versa. The logic incorrectly used the register's 'kind' (the register class) instead of its 'abi' (the specific data type/width) to identify the source operand. This caused the dependency solver to fail or emit incorrect moves on 64-bit platforms where floating-point arguments are passed in registers. This issue is "masked" on 32-bit x86 (IA32) because it primarily uses the stack for passing double-precision arguments, avoiding register-to-register swaps for the ABI registers. The fix has been verified by adjusting 'tests/call_10_2.c' to force a register swap (F0/F1). Formerly the modified test failed on: - Linux x86_64 (System V ABI) - Linux aarch64 - Windows 64-bit (Microsoft x64 ABI) via Cygwin, MINGW64, UCRT64, and CLANG64. * lightening/lightening.c (prepare_args): Use 'src[j].abi' instead of 'src[j].kind' when resolving register-to-register dependencies. * tests/call_10_2.c (run_test_double): Swap the order in which dargs[0] and dargs[1] are loaded into registers F0 and F1. This forces a register cycle during the call, exposing the dependency resolution bug. ```
The command `make -C tests test-native' now runs successfully on
MSYS2 for MSYS (a Cygwin clone), MINGW32, MINGW64, and UCRT64.
The command `make -C tests CC=clang test-native' passed on CLANG64.
Finally, the command:
'make -C tests check TARGETS="native ia32 aarch64" \
 CC_IA32=i686-linux-gnu-gcc \
 CC_AARCH64=aarch64-linux-gnu-gcc'
passes on Linux x86_64. All without warnings.
Patch regarding __ffs is based on ideas from Michael Gran.
* lightening.h (JIT_API): Update copyright year. Disable visibility
 attributes on Cygwin and Windows, as they are not supported the
 same way as on ELF platforms.
* lightening/aarch64.c: Update copyright year. Add `maybe_unused'
 attributes to instruction helpers generated by the
 `DEFINE_PATCHABLE_INSTRUCTION' macro to suppress warnings.
* lightening/lightening.c: Update copyright year. Remove
 inclusion of `<sys/mman.h>' since it is no longer required. Fix
 warnings from -Wundef.
* lightening/lightening.c (jit_address): Cast ternary operator results
 to `(jit_pointer_t)' and wrap in parentheses to avoid pointer type
 mismatch warnings in Clang.
* lightening/x86-cpu.c (__ffs): Update copyright year. New static
 helper to wrap `__builtin_ffs' on Windows/MinGW where the standard
 `ffs' function is missing.
* lightening/x86-cpu.c (ffsw): Use the new `__ffs' helper.
* lightening/x86.c (reset_abi_arg_iterator): Update copyright year.
 Simplify Cygwin 64-bit and Windows 64-bit detection logic without
 changing any code path.
* tests/Makefile: Add `EXEEXT' support for Windows. Update `PROGS' and
 `clean' rules. Refactor test targets to correctly use dependencies
 with extensions. Update Debian package installation instructions and
 dependencies. Add -Wundef since related warnings have been found.
* tests/call_10_2.c (run_test_double): Adjust register usage for the
 Microsoft x64 ABI. Only use `JIT_F0' through `JIT_F4' as scratch
 registers to comply with the MS ABI.
* tests/test.h (main_helper): Use `uint8_t *' for arena_base instead of
 `char *'. Implement Windows-specific JIT memory allocation using
 `CreateFileMapping' and `MapViewOfFile'. Add proper cleanup using
 `UnmapViewOfFile' and `CloseHandle'.
When preparing arguments for a function call, the JIT must detect and
resolve dependencies (cycles) between registers. This occurs when,
for example, the value for the first argument is currently in the
register that should hold the second argument, and vice-versa.
The logic incorrectly used the register's 'kind' (the register class)
instead of its 'abi' (the specific data type/width) to identify the
source operand. This caused the dependency solver to fail or emit
incorrect moves on 64-bit platforms where floating-point arguments
are passed in registers.
This issue is "masked" on 32-bit x86 (IA32) because it primarily
uses the stack for passing double-precision arguments, avoiding
register-to-register swaps for the ABI registers.
The fix has been verified by adjusting 'tests/call_10_2.c' to force
a register swap (F0/F1). Formerly the modified test failed on:
- Linux x86_64 (System V ABI)
- Linux aarch64
- Windows 64-bit (Microsoft x64 ABI) via Cygwin, MINGW64, UCRT64,
 and CLANG64.
* lightening/lightening.c (prepare_args): Use 'src[j].abi' instead of
 'src[j].kind' when resolving register-to-register dependencies.
* tests/call_10_2.c (run_test_double): Swap the order in which dargs[0]
 and dargs[1] are loaded into registers F0 and F1. This forces a
 register cycle during the call, exposing the dependency resolution bug.
hahnjo left a comment
Copy link

The change of parameter to is_fpr_arg looks absolutely correct to me. I don't know how this doesn't cause more havoc 😱

Edit: note that this currently includes the commit from #1, maybe it would make sense to separate the two PRs more strictly?

The change of parameter to `is_fpr_arg` looks absolutely correct to me. I don't know how this doesn't cause more havoc 😱 Edit: note that this currently includes the commit from #1, maybe it would make sense to separate the two PRs more strictly?
Collaborator
Copy link

Hi, could you please rebase on top of main so I can tell the CI to test the changes?
When the PR was proposed the CI was broken... but has been fixed now.

Thank you!

Hi, could you please rebase on top of `main` so I can tell the CI to test the changes? When the PR was proposed the CI was broken... but has been fixed now. Thank you!
This pull request has changes conflicting with the target branch.
  • tests/Makefile
View command line instructions

Manual merge helper

Use this merge commit message when completing the merge manually.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u fix_move_one:h-c-mueller-fix_move_one
git switch h-c-mueller-fix_move_one

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch main
git merge --no-ff h-c-mueller-fix_move_one
git switch h-c-mueller-fix_move_one
git rebase main
git switch main
git merge --ff-only h-c-mueller-fix_move_one
git switch h-c-mueller-fix_move_one
git rebase main
git switch main
git merge --no-ff h-c-mueller-fix_move_one
git switch main
git merge --squash h-c-mueller-fix_move_one
git switch main
git merge --ff-only h-c-mueller-fix_move_one
git switch main
git merge h-c-mueller-fix_move_one
git push origin main
Sign in to join this conversation.
No reviewers
Labels
Clear labels
No items
No labels
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
guile/lightening!2
Reference in a new issue
guile/lightening
No description provided.
Delete branch "h-c-mueller/lightening:fix_move_one"

Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?