Skip to content

Riscv32#47

Open
jrrk2 wants to merge 9 commits intoTinyCC:mobfrom
jrrk2:riscv32
Open

Riscv32#47
jrrk2 wants to merge 9 commits intoTinyCC:mobfrom
jrrk2:riscv32

Conversation

@jrrk2
Copy link

@jrrk2 jrrk2 commented Mar 6, 2026

This pull request add riscv32 support to tinycc.

Known limitations to document in PR description:
- -run mode not implemented (no runmain.o)
- Cleanup attribute + struct return bug (test 101)
- 32-bit bitfield alignment (test 95, same as ARM/i386)
- long double is 64-bit internally (TCC_USING_DOUBLE_FOR_LDOUBLE) but converted to
128-bit quad for ABI compliance in varargs

jrrk2 and others added 9 commits March 5, 2026 08:31
RISC-V always uses RELA relocations, even in 32-bit mode. The dynamic
section was using PTR_SIZE==8 to decide between DT_RELA and DT_REL,
which incorrectly selected DT_REL for rv32. Use SHT_RELX==SHT_RELA
instead, which is already set correctly for riscv32 in tcc.h.

Without this fix, glibc's ld.so rejects TCC-compiled binaries:
  Assertion `info[DT_PLTREL]->d_un.d_val == DT_RELA' failed!

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ble varargs

Major fixes for the riscv32 soft-float backend, improving test suite
from 120 PASS to 130 PASS (out of 151 total, 15 skipped).

riscv32-gen.c:
- Handle VT_LLONG in gfunc_call argument loop alongside VT_DOUBLE/VT_LDOUBLE,
  so 64-bit integer constants are loaded via gv() instead of requiring an lvalue.
  Fixes "lvalue expected" errors for expressions like (unsigned long long)1e19
  passed as function arguments (tests 107, 110, 111, 119, 134).
- Fix reg_pass_rec to only handle first scalar field (changed condition from
  !rc[0]||rc[1]==RC_INT to !rc[0]), so multi-field structs use size-based
  fallback packing. Fixes struct return ABI for small structs like
  {uint8_t a,b} and {uint16_t a,b} (test 131).
- Add varargs long double support: detect VT_DOUBLE|VT_LONG in gfunc_call,
  convert 64-bit double to 128-bit quad (binary128) inline, pass by reference
  per RV32 ILP32 ABI. Includes gen_dbl_to_quad_store() for IEEE754 format
  conversion (tests 22, 70).
- Add t3-t6 (x28-x31) as allocatable temp registers (NB_REGS 11→15).
- Fix nregs for byref args to prevent info[] bit encoding conflicts.
- Rewrite gen_opf/gen_cvt_itof/gen_cvt_ftoi to use save_regs+gcall_or_jmp
  pattern instead of vpush_helper_func+gfunc_call to avoid nested call issues.

tccgen.c:
- Preserve VT_LONG flag through floating-point arithmetic in gen_op() so
  varargs detection works for computed long double expressions.
- Add riscv32-specific 64-bit comparison codegen that forces register-register
  comparisons and saves cmp_r for NE re-test (no flags register on RISC-V).

tests/run-rv32-tests.sh:
- New test runner for riscv32 via qemu-user/binfmt_misc.
- Add -latomic for atomic tests 124, 136.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Without an explicit TCC_LIBGCC define, tcc.h constructs a triplet-based
path like /lib/riscv32-linux-gnu/libgcc_s.so.1 which doesn't exist on
musl-based systems. Emit TCC_LIBGCC="libgcc_s.so.1" (bare name for
dynamic lookup) so the linker finds it via the normal library search path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Skip tests that are expected failures on riscv32:
- 95: 32-bit bitfield alignment (same as i386/arm in upstream Makefile)
- 60, 96, 125, 128: -dt mode requires -run which is unavailable
- 101: struct return + cleanup attribute interaction bug

Test suite now: 130 PASS, 0 FAIL, 21 SKIP.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add optional hardware floating-point code generation for RV32 targets
that have the F and D extensions. When enabled via -mfpu, the compiler
emits inline FPU instructions instead of soft-float library calls for:

- Arithmetic operations (fadd, fsub, fmul, fdiv) for float and double
- Comparisons (feq, flt, fle) for float and double
- Integer↔float conversions (fcvt.w.s, fcvt.s.w, etc.)
- Float↔double conversions (fcvt.d.s, fcvt.s.d)

The soft-float ABI is preserved: values are passed in integer registers
and transferred to/from FP registers via fmv.w.x/fmv.x.w (float) or
stack spills (double). This allows mixing with soft-float libraries
while using hardware FP for local computation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.

1 participant