Skip to content

Add support for LoongArch32#957

Merged
atgreen merged 2 commits into
libffi:masterfrom
cloudspurs:la32
Apr 21, 2026
Merged

Add support for LoongArch32#957
atgreen merged 2 commits into
libffi:masterfrom
cloudspurs:la32

Conversation

@cloudspurs

Copy link
Copy Markdown
Contributor

Change src/loongarch64 to src/loongarch.

Change __loongarch64 to __loongarch_grlen.
__loongarch64 is used for compatibility with legacy code, new programs should not assume existence of this macro.[1] And there is no __loongarch32 macro for LoongArch32.

Add ilp32s, ilp32f, ilp32d abi.
Add ADDI macro.

[1] https://github.com/loongson/la-toolchain-conventions?tab=readme-ov-file#cc-preprocessor-built-in-macro-definitions

@atgreen atgreen left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the LoongArch32 work! A few items worth discussing:

  1. Memory layout change in ffi_call_int affects LP64 too — The introduction of extra_bytes and the change to cb.stack initialization (cb.stack = (void *) alloc_base + extra_bytes + rval_bytes) diverges from the current layout where cb.stack and cb.used_stack both start at alloc_base. This changes behavior for 64-bit as well, not just 32-bit. Could you explain why this layout change is needed for LA32, and confirm it doesn't regress LP64?

  2. Trampoline size assumptions — The trampoline code table uses .rept 65536 / 16 — do the size assumptions hold on 32-bit where pointer sizes differ?

  3. LOONGARCH32 target define appears unusedconfigure.host sets TARGET=LOONGARCH32 vs TARGET=LOONGARCH64, but ffi.c doesn't branch on this anywhere. The ABI selection relies entirely on __loongarch_grlen from the compiler, which is fine, but is the TARGET distinction used elsewhere (e.g. Makefile conditionals), or is it dead?

@cloudspurs

Copy link
Copy Markdown
Contributor Author

Thanks for the LoongArch32 work! A few items worth discussing:

  1. Memory layout change in ffi_call_int affects LP64 too — The introduction of extra_bytes and the change to cb.stack initialization (cb.stack = (void *) alloc_base + extra_bytes + rval_bytes) diverges from the current layout where cb.stack and cb.used_stack both start at alloc_base. This changes behavior for 64-bit as well, not just 32-bit. Could you explain why this layout change is needed for LA32, and confirm it doesn't regress LP64?
  2. Trampoline size assumptions — The trampoline code table uses .rept 65536 / 16 — do the size assumptions hold on 32-bit where pointer sizes differ?
  3. LOONGARCH32 target define appears unusedconfigure.host sets TARGET=LOONGARCH32 vs TARGET=LOONGARCH64, but ffi.c doesn't branch on this anywhere. The ABI selection relies entirely on __loongarch_grlen from the compiler, which is fine, but is the TARGET distinction used elsewhere (e.g. Makefile conditionals), or is it dead?

Thanks for your review. Some replies below.

  1. This is mainly used to fix "libffi.closures/cls_longdouble.c" in the second commit.
    extra_bytes is used for the address of parameters passed by reference.
    Both the result of "make check" for LoongArch64 and LoongArch32 is:
                === libffi Summary ===

# of expected passes            1548
# of unsupported tests          29
  1. Is extra work required to ensure the size of the parameter block is the same as the size of the trampoline and the offset of parameter block is the same as the offset of the trampoline? If not, I think the size assumptions is OK.

  2. LOONGARCH64 is used to add -mcmodel=medium to CFLAGS in configure.

@xry111

xry111 commented Apr 17, 2026

Copy link
Copy Markdown
Contributor
  1. Is extra work required to ensure the size of the parameter block is the same as the size of the trampoline and the offset of parameter block is the same as the offset of the trampoline? If not, I think the size assumptions is OK.

The size of the parameter block must be smaller than the size of the trampoline, so the generic code can guarantee the offset of the parameter block is the same as the offset of the trampoline. Given the parameter block of LA32 must be smaller than the one of LA64 things should be fine.

@atgreen

atgreen commented Apr 18, 2026

Copy link
Copy Markdown
Member

Thanks for the replies and test results! Two items I'd like addressed before merging:

  1. configure.ac needs updatingconfigure.ac:197 has a case for LOONGARCH64 (to add -mcmodel=medium). Since configure.host now sets TARGET=LOONGARCH32 for 32-bit, configure.ac should handle that too — even if it's just an empty case or a comment explaining LA32 doesn't need -mcmodel=medium.

  2. void * arithmetic in ffi.c — This line performs pointer arithmetic on void *:

    cb.stack = (void *) alloc_base + extra_bytes + rval_bytes;

    This relies on a GNU C extension that treats void * like char *. It should use an explicit char * cast instead, e.g.:

    cb.stack = (size_t *)((char *) alloc_base + extra_bytes + rval_bytes);

Change src/loongarch64 to src/loongarch.

Change __loongarch64 to __loongarch_grlen.
__loongarch64 is uesd for compatibility with legacy code,
new programs should not assume existence of this macro.[1]
And there is no __loongarch32 macro for LoongArch32.

Add ilp32s, ilp32f, ilp32d abi.
Add ADDI macro.

[1] https://github.com/loongson/la-toolchain-conventions?tab=readme-ov-file#cc-preprocessor-built-in-macro-definitions
CHECK(a8 == 8) fail on LoongArch32.

long double passed by reference on LoongArch32 ilp32 ABI.
If a argument register is available, the address is passed
in the argument register; otherwise, it is passed on the stack[1].

The address of return value and a1-a7 arguments of cls_ldouble_fn
passed by a0-a7 argument registers. The address of a8 argument need
to be passed by stack.

But ffi_call_int only allocates cif->bytes(sizeof(long double)*8)
bytes space for stack. Both the address of a8 argument and a8 argument
are saved at sp+0 address. The lowest 4-byte of a8 argument are overwritten
by the address of a8 argument.

Allocates extra conservative estimate space like RISC-V.

[1] https://github.com/loongson/la-abi-specs/blob/release/lapcs.adoc#passing-arguments
@cloudspurs

Copy link
Copy Markdown
Contributor Author

Two items I'd like addressed before merging:

Thanks for the replies and test results! Two items I'd like addressed before merging:

  1. configure.ac needs updatingconfigure.ac:197 has a case for LOONGARCH64 (to add -mcmodel=medium). Since configure.host now sets TARGET=LOONGARCH32 for 32-bit, configure.ac should handle that too — even if it's just an empty case or a comment explaining LA32 doesn't need -mcmodel=medium.

  2. void * arithmetic in ffi.c — This line performs pointer arithmetic on void *:

    cb.stack = (void *) alloc_base + extra_bytes + rval_bytes;

    This relies on a GNU C extension that treats void * like char *. It should use an explicit char * cast instead, e.g.:

    cb.stack = (size_t *)((char *) alloc_base + extra_bytes + rval_bytes);

Thanks for the feedback! I’ve addressed both items and rebased to master branch.
The result of make check for LoongArch64 and LoongArch32 remain unchanged.

@atgreen atgreen merged commit 70e6c26 into libffi:master Apr 21, 2026
4 of 29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants